summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/accessibility/speakup/Makefile4
-rw-r--r--drivers/acpi/arm64/init.c2
-rw-r--r--drivers/acpi/battery.c3
-rw-r--r--drivers/acpi/bus.c5
-rw-r--r--drivers/acpi/processor_idle.c12
-rw-r--r--drivers/acpi/riscv/init.c2
-rw-r--r--drivers/acpi/x86/utils.c30
-rw-r--r--drivers/amba/bus.c6
-rw-r--r--drivers/android/binder.c64
-rw-r--r--drivers/base/auxiliary.c31
-rw-r--r--drivers/base/cacheinfo.c15
-rw-r--r--drivers/base/class.c4
-rw-r--r--drivers/base/core.c63
-rw-r--r--drivers/base/firmware_loader/main.c7
-rw-r--r--drivers/base/node.c12
-rw-r--r--drivers/base/power/sysfs.c17
-rw-r--r--drivers/base/topology.c40
-rw-r--r--drivers/base/trace.h6
-rw-r--r--drivers/block/brd.c4
-rw-r--r--drivers/block/loop.c30
-rw-r--r--drivers/block/ublk_drv.c2
-rw-r--r--drivers/bus/mhi/host/boot.c4
-rw-r--r--drivers/bus/mhi/host/internal.h2
-rw-r--r--drivers/bus/mhi/host/pci_generic.c6
-rw-r--r--drivers/bus/mhi/host/trace.h25
-rw-r--r--drivers/cdx/cdx.c2
-rw-r--r--drivers/char/powernv-op-panel.c2
-rw-r--r--drivers/char/sonypi.c2
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c2
-rw-r--r--drivers/char/xillybus/xillybus_of.c2
-rw-r--r--drivers/comedi/comedi_fops.c12
-rw-r--r--drivers/counter/ftm-quaddec.c1
-rw-r--r--drivers/counter/intel-qep.c10
-rw-r--r--drivers/counter/stm32-timer-cnt.c17
-rw-r--r--drivers/counter/ti-ecap-capture.c7
-rw-r--r--drivers/cpuidle/cpuidle-riscv-sbi.c11
-rw-r--r--drivers/cxl/port.c2
-rw-r--r--drivers/dma/Kconfig28
-rw-r--r--drivers/dma/Makefile2
-rw-r--r--drivers/dma/acpi-dma.c43
-rw-r--r--drivers/dma/altera-msgdma.c2
-rw-r--r--drivers/dma/amd/qdma/qdma.c2
-rw-r--r--drivers/dma/apple-admac.c2
-rw-r--r--drivers/dma/at_hdmac.c2
-rw-r--r--drivers/dma/at_xdmac.c2
-rw-r--r--drivers/dma/bcm-sba-raid.c2
-rw-r--r--drivers/dma/bcm2835-dma.c2
-rw-r--r--drivers/dma/bestcomm/bestcomm.c2
-rw-r--r--drivers/dma/dma-jz4780.c2
-rw-r--r--drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c2
-rw-r--r--drivers/dma/dw/platform.c2
-rw-r--r--drivers/dma/ep93xx_dma.c3
-rw-r--r--drivers/dma/fsl-edma-main.c2
-rw-r--r--drivers/dma/fsl-qdma.c2
-rw-r--r--drivers/dma/fsl_raid.c2
-rw-r--r--drivers/dma/fsldma.c2
-rw-r--r--drivers/dma/idma64.c2
-rw-r--r--drivers/dma/idxd/registers.h4
-rw-r--r--drivers/dma/img-mdc-dma.c2
-rw-r--r--drivers/dma/imx-dma.c2
-rw-r--r--drivers/dma/imx-sdma.c2
-rw-r--r--drivers/dma/k3dma.c2
-rw-r--r--drivers/dma/loongson2-apb-dma.c (renamed from drivers/dma/ls2x-apb-dma.c)6
-rw-r--r--drivers/dma/mcf-edma-main.c2
-rw-r--r--drivers/dma/mediatek/mtk-cqdma.c2
-rw-r--r--drivers/dma/mediatek/mtk-hsdma.c2
-rw-r--r--drivers/dma/mediatek/mtk-uart-apdma.c2
-rw-r--r--drivers/dma/milbeaut-hdmac.c2
-rw-r--r--drivers/dma/milbeaut-xdmac.c2
-rw-r--r--drivers/dma/mmp_pdma.c2
-rw-r--r--drivers/dma/mmp_tdma.c2
-rw-r--r--drivers/dma/moxart-dma.c2
-rw-r--r--drivers/dma/mpc512x_dma.c2
-rw-r--r--drivers/dma/mv_xor_v2.c4
-rw-r--r--drivers/dma/nbpfaxi.c2
-rw-r--r--drivers/dma/owl-dma.c2
-rw-r--r--drivers/dma/ppc4xx/adma.c2
-rw-r--r--drivers/dma/pxa_dma.c2
-rw-r--r--drivers/dma/qcom/bam_dma.c2
-rw-r--r--drivers/dma/qcom/hidma.c2
-rw-r--r--drivers/dma/qcom/qcom_adm.c2
-rw-r--r--drivers/dma/sa11x0-dma.c2
-rw-r--r--drivers/dma/sf-pdma/sf-pdma.c4
-rw-r--r--drivers/dma/sh/Kconfig8
-rw-r--r--drivers/dma/sh/rcar-dmac.c2
-rw-r--r--drivers/dma/sh/rz-dmac.c4
-rw-r--r--drivers/dma/sh/shdma-base.c2
-rw-r--r--drivers/dma/sh/shdmac.c2
-rw-r--r--drivers/dma/sh/usb-dmac.c4
-rw-r--r--drivers/dma/sprd-dma.c2
-rw-r--r--drivers/dma/st_fdma.c2
-rw-r--r--drivers/dma/stm32/stm32-dma3.c121
-rw-r--r--drivers/dma/sun4i-dma.c2
-rw-r--r--drivers/dma/sun6i-dma.c2
-rw-r--r--drivers/dma/tegra186-gpc-dma.c2
-rw-r--r--drivers/dma/tegra20-apb-dma.c2
-rw-r--r--drivers/dma/tegra210-adma.c2
-rw-r--r--drivers/dma/ti/cppi41.c2
-rw-r--r--drivers/dma/ti/edma.c2
-rw-r--r--drivers/dma/ti/omap-dma.c2
-rw-r--r--drivers/dma/timb_dma.c2
-rw-r--r--drivers/dma/txx9dmac.c4
-rw-r--r--drivers/dma/uniphier-mdmac.c2
-rw-r--r--drivers/dma/uniphier-xdmac.c2
-rw-r--r--drivers/dma/xgene-dma.c2
-rw-r--r--drivers/dma/xilinx/xdma.c2
-rw-r--r--drivers/dma/xilinx/xilinx_dma.c2
-rw-r--r--drivers/dma/xilinx/xilinx_dpdma.c2
-rw-r--r--drivers/dma/xilinx/zynqmp_dma.c4
-rw-r--r--drivers/firmware/arm_scmi/driver.c2
-rw-r--r--drivers/firmware/arm_scpi.c2
-rw-r--r--drivers/firmware/google/coreboot_table.c2
-rw-r--r--drivers/firmware/imx/imx-dsp.c2
-rw-r--r--drivers/firmware/memmap.c2
-rw-r--r--drivers/firmware/microchip/mpfs-auto-update.c2
-rw-r--r--drivers/firmware/mtk-adsp-ipc.c9
-rw-r--r--drivers/firmware/qemu_fw_cfg.c2
-rw-r--r--drivers/firmware/raspberrypi.c2
-rw-r--r--drivers/firmware/stratix10-rsu.c2
-rw-r--r--drivers/firmware/stratix10-svc.c2
-rw-r--r--drivers/firmware/xilinx/zynqmp.c2
-rw-r--r--drivers/fpga/altera-fpga2sdram.c2
-rw-r--r--drivers/fpga/altera-freeze-bridge.c2
-rw-r--r--drivers/fpga/altera-hps2fpga.c2
-rw-r--r--drivers/fpga/dfl-afu-main.c8
-rw-r--r--drivers/fpga/dfl-fme-br.c8
-rw-r--r--drivers/fpga/dfl-fme-main.c8
-rw-r--r--drivers/fpga/dfl-fme-region.c8
-rw-r--r--drivers/fpga/intel-m10-bmc-sec-update.c2
-rw-r--r--drivers/fpga/of-fpga-region.c2
-rw-r--r--drivers/fpga/socfpga-a10.c2
-rw-r--r--drivers/fpga/stratix10-soc.c2
-rw-r--r--drivers/fpga/xilinx-pr-decoupler.c2
-rw-r--r--drivers/fpga/zynq-fpga.c2
-rw-r--r--drivers/gpio/gpio-altera.c5
-rw-r--r--drivers/gpio/gpio-aspeed-sgpio.c2
-rw-r--r--drivers/gpio/gpio-aspeed.c2
-rw-r--r--drivers/gpio/gpio-ep93xx.c2
-rw-r--r--drivers/gpio/gpio-exar.c10
-rw-r--r--drivers/gpio/gpio-hlwd.c2
-rw-r--r--drivers/gpio/gpio-mlxbf2.c2
-rw-r--r--drivers/gpio/gpio-mpsse.c4
-rw-r--r--drivers/gpio/gpio-omap.c2
-rw-r--r--drivers/gpio/gpio-pca953x.c2
-rw-r--r--drivers/gpio/gpio-pl061.c2
-rw-r--r--drivers/gpio/gpio-tegra.c2
-rw-r--r--drivers/gpio/gpio-tegra186.c2
-rw-r--r--drivers/gpio/gpio-tqmx86.c2
-rw-r--r--drivers/gpio/gpio-visconti.c2
-rw-r--r--drivers/gpio/gpio-xgs-iproc.c2
-rw-r--r--drivers/gpio/gpio-zevio.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/aldebaran.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c29
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c37
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c41
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/df_v3_6.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c7
-rw-r--r--drivers/gpu/drm/amd/display/Kconfig15
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl.c97
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h13
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h118
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c24
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c8
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c6
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c12
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c33
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c3
-rw-r--r--drivers/gpu/drm/display/drm_dp_aux_bus.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp.c32
-rw-r--r--drivers/gpu/drm/radeon/radeon_audio.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c10
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c3
-rw-r--r--drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c2
-rw-r--r--drivers/gpu/drm/xe/xe_devcoredump.c6
-rw-r--r--drivers/gpu/drm/xe/xe_device.c3
-rw-r--r--drivers/gpu/drm/xe/xe_guc_submit.c34
-rw-r--r--drivers/gpu/drm/xe/xe_migrate.c6
-rw-r--r--drivers/gpu/drm/xe/xe_pci.c2
-rw-r--r--drivers/gpu/drm/xe/xe_sync.c6
-rw-r--r--drivers/greybus/interface.c2
-rw-r--r--drivers/iio/accel/adxl355_core.c2
-rw-r--r--drivers/iio/accel/adxl367.c2
-rw-r--r--drivers/iio/accel/adxl372.c2
-rw-r--r--drivers/iio/accel/adxl380.c11
-rw-r--r--drivers/iio/accel/bma180.c3
-rw-r--r--drivers/iio/accel/bma220_spi.c1
-rw-r--r--drivers/iio/accel/bma400_core.c4
-rw-r--r--drivers/iio/accel/bmc150-accel-core.c2
-rw-r--r--drivers/iio/accel/bmc150-accel.h3
-rw-r--r--drivers/iio/accel/fxls8962af-core.c8
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c9
-rw-r--r--drivers/iio/accel/kionix-kx022a.c5
-rw-r--r--drivers/iio/accel/kxcjk-1013.c442
-rw-r--r--drivers/iio/accel/kxsd9.c3
-rw-r--r--drivers/iio/accel/mma7455_core.c3
-rw-r--r--drivers/iio/accel/mma8452.c5
-rw-r--r--drivers/iio/accel/mma9551.c27
-rw-r--r--drivers/iio/accel/mma9553.c46
-rw-r--r--drivers/iio/accel/msa311.c3
-rw-r--r--drivers/iio/accel/mxc4005.c3
-rw-r--r--drivers/iio/accel/sca3000.c6
-rw-r--r--drivers/iio/accel/stk8312.c3
-rw-r--r--drivers/iio/accel/stk8ba50.c3
-rw-r--r--drivers/iio/adc/Kconfig43
-rw-r--r--drivers/iio/adc/Makefile3
-rw-r--r--drivers/iio/adc/ab8500-gpadc.c2
-rw-r--r--drivers/iio/adc/ad4000.c6
-rw-r--r--drivers/iio/adc/ad7091r-base.c3
-rw-r--r--drivers/iio/adc/ad7091r-base.h2
-rw-r--r--drivers/iio/adc/ad7173.c38
-rw-r--r--drivers/iio/adc/ad7192.c3
-rw-r--r--drivers/iio/adc/ad7266.c2
-rw-r--r--drivers/iio/adc/ad7280a.c14
-rw-r--r--drivers/iio/adc/ad7291.c2
-rw-r--r--drivers/iio/adc/ad7380.c178
-rw-r--r--drivers/iio/adc/ad7606.c1056
-rw-r--r--drivers/iio/adc/ad7606.h134
-rw-r--r--drivers/iio/adc/ad7606_par.c133
-rw-r--r--drivers/iio/adc/ad7606_spi.c195
-rw-r--r--drivers/iio/adc/ad7625.c684
-rw-r--r--drivers/iio/adc/ad7779.c914
-rw-r--r--drivers/iio/adc/ad7780.c2
-rw-r--r--drivers/iio/adc/ad7791.c4
-rw-r--r--drivers/iio/adc/ad7793.c2
-rw-r--r--drivers/iio/adc/ad7887.c4
-rw-r--r--drivers/iio/adc/ad7923.c4
-rw-r--r--drivers/iio/adc/ad7944.c4
-rw-r--r--drivers/iio/adc/ad799x.c2
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c4
-rw-r--r--drivers/iio/adc/at91-sama5d2_adc.c2
-rw-r--r--drivers/iio/adc/at91_adc.c2
-rw-r--r--drivers/iio/adc/axp20x_adc.c62
-rw-r--r--drivers/iio/adc/axp288_adc.c2
-rw-r--r--drivers/iio/adc/bcm_iproc_adc.c8
-rw-r--r--drivers/iio/adc/da9150-gpadc.c26
-rw-r--r--drivers/iio/adc/dln2-adc.c2
-rw-r--r--drivers/iio/adc/ep93xx_adc.c2
-rw-r--r--drivers/iio/adc/exynos_adc.c2
-rw-r--r--drivers/iio/adc/gehc-pmc-adc.c228
-rw-r--r--drivers/iio/adc/hi8435.c2
-rw-r--r--drivers/iio/adc/imx8qxp-adc.c2
-rw-r--r--drivers/iio/adc/imx93_adc.c2
-rw-r--r--drivers/iio/adc/intel_mrfld_adc.c2
-rw-r--r--drivers/iio/adc/lp8788_adc.c18
-rw-r--r--drivers/iio/adc/ltc2497-core.c15
-rw-r--r--drivers/iio/adc/max1363.c5
-rw-r--r--drivers/iio/adc/max34408.c2
-rw-r--r--drivers/iio/adc/meson_saradc.c2
-rw-r--r--drivers/iio/adc/mp2629_adc.c4
-rw-r--r--drivers/iio/adc/mt6360-adc.c2
-rw-r--r--drivers/iio/adc/mxs-lradc-adc.c6
-rw-r--r--drivers/iio/adc/npcm_adc.c2
-rw-r--r--drivers/iio/adc/pac1921.c48
-rw-r--r--drivers/iio/adc/pac1934.c2
-rw-r--r--drivers/iio/adc/palmas_gpadc.c4
-rw-r--r--drivers/iio/adc/qcom-pm8xxx-xoadc.c10
-rw-r--r--drivers/iio/adc/qcom-spmi-adc5.c4
-rw-r--r--drivers/iio/adc/qcom-spmi-vadc.c7
-rw-r--r--drivers/iio/adc/rcar-gyroadc.c2
-rw-r--r--drivers/iio/adc/rn5t618-adc.c2
-rw-r--r--drivers/iio/adc/stm32-adc-core.c2
-rw-r--r--drivers/iio/adc/stm32-adc.c2
-rw-r--r--drivers/iio/adc/stm32-dfsdm-adc.c2
-rw-r--r--drivers/iio/adc/stm32-dfsdm-core.c2
-rw-r--r--drivers/iio/adc/sun20i-gpadc-iio.c7
-rw-r--r--drivers/iio/adc/sun4i-gpadc-iio.c9
-rw-r--r--drivers/iio/adc/ti-ads1015.c5
-rw-r--r--drivers/iio/adc/ti-ads1119.c2
-rw-r--r--drivers/iio/adc/ti-ads1298.c2
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c10
-rw-r--r--drivers/iio/adc/twl4030-madc.c4
-rw-r--r--drivers/iio/adc/twl6030-gpadc.c2
-rw-r--r--drivers/iio/adc/vf610_adc.c2
-rw-r--r--drivers/iio/adc/xilinx-ams.c2
-rw-r--r--drivers/iio/adc/xilinx-xadc-events.c4
-rw-r--r--drivers/iio/adc/xilinx-xadc.h2
-rw-r--r--drivers/iio/addac/ad74115.c18
-rw-r--r--drivers/iio/addac/ad74413r.c102
-rw-r--r--drivers/iio/cdc/ad7150.c2
-rw-r--r--drivers/iio/chemical/Kconfig2
-rw-r--r--drivers/iio/chemical/bme680.h11
-rw-r--r--drivers/iio/chemical/bme680_core.c366
-rw-r--r--drivers/iio/common/inv_sensors/inv_sensors_timestamp.c4
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_trigger.c2
-rw-r--r--drivers/iio/dac/Kconfig32
-rw-r--r--drivers/iio/dac/Makefile3
-rw-r--r--drivers/iio/dac/ad3552r-common.c249
-rw-r--r--drivers/iio/dac/ad3552r-hs.c529
-rw-r--r--drivers/iio/dac/ad3552r-hs.h19
-rw-r--r--drivers/iio/dac/ad3552r.c557
-rw-r--r--drivers/iio/dac/ad3552r.h228
-rw-r--r--drivers/iio/dac/ad5380.c85
-rw-r--r--drivers/iio/dac/ad5421.c2
-rw-r--r--drivers/iio/dac/ad5446.c77
-rw-r--r--drivers/iio/dac/ad5504.c61
-rw-r--r--drivers/iio/dac/ad5624r.h1
-rw-r--r--drivers/iio/dac/ad5624r_spi.c71
-rw-r--r--drivers/iio/dac/ad5755.c11
-rw-r--r--drivers/iio/dac/ad5761.c109
-rw-r--r--drivers/iio/dac/ad5770r.c44
-rw-r--r--drivers/iio/dac/ad5791.c205
-rw-r--r--drivers/iio/dac/ad8460.c951
-rw-r--r--drivers/iio/dac/adi-axi-dac.c449
-rw-r--r--drivers/iio/dac/dpot-dac.c2
-rw-r--r--drivers/iio/dac/lpc18xx_dac.c6
-rw-r--r--drivers/iio/dac/m62332.c2
-rw-r--r--drivers/iio/dac/max517.c2
-rw-r--r--drivers/iio/dac/stm32-dac-core.c2
-rw-r--r--drivers/iio/dac/stm32-dac.c2
-rw-r--r--drivers/iio/dac/vf610_dac.c2
-rw-r--r--drivers/iio/dummy/iio_simple_dummy.h2
-rw-r--r--drivers/iio/dummy/iio_simple_dummy_events.c32
-rw-r--r--drivers/iio/frequency/ad9523.c2
-rw-r--r--drivers/iio/frequency/adf4350.c2
-rw-r--r--drivers/iio/frequency/adf4371.c63
-rw-r--r--drivers/iio/gyro/Kconfig2
-rw-r--r--drivers/iio/gyro/bmg160_core.c19
-rw-r--r--drivers/iio/gyro/bmg160_i2c.c6
-rw-r--r--drivers/iio/gyro/fxas21002c_core.c3
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c8
-rw-r--r--drivers/iio/gyro/mpu3050-core.c2
-rw-r--r--drivers/iio/humidity/hid-sensor-humidity.c4
-rw-r--r--drivers/iio/humidity/hts221_buffer.c3
-rw-r--r--drivers/iio/imu/Kconfig15
-rw-r--r--drivers/iio/imu/Makefile3
-rw-r--r--drivers/iio/imu/bmi160/bmi160_core.c11
-rw-r--r--drivers/iio/imu/bmi270/Kconfig33
-rw-r--r--drivers/iio/imu/bmi270/Makefile7
-rw-r--r--drivers/iio/imu/bmi270/bmi270.h38
-rw-r--r--drivers/iio/imu/bmi270/bmi270_core.c734
-rw-r--r--drivers/iio/imu/bmi270/bmi270_i2c.c66
-rw-r--r--drivers/iio/imu/bmi270/bmi270_spi.c92
-rw-r--r--drivers/iio/imu/bmi323/bmi323.h1
-rw-r--r--drivers/iio/imu/bmi323/bmi323_core.c18
-rw-r--r--drivers/iio/imu/fxos8700_core.c1
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c2
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_core.c10
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c3
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c17
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c17
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c11
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c38
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c10
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h4
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c10
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c1
-rw-r--r--drivers/iio/imu/kmx61.c27
-rw-r--r--drivers/iio/imu/smi240.c621
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h2
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c22
-rw-r--r--drivers/iio/industrialio-acpi.c48
-rw-r--r--drivers/iio/industrialio-backend.c82
-rw-r--r--drivers/iio/industrialio-core.c3
-rw-r--r--drivers/iio/industrialio-gts-helper.c4
-rw-r--r--drivers/iio/inkern.c9
-rw-r--r--drivers/iio/light/Kconfig18
-rw-r--r--drivers/iio/light/Makefile1
-rw-r--r--drivers/iio/light/adux1020.c12
-rw-r--r--drivers/iio/light/al3010.c11
-rw-r--r--drivers/iio/light/apds9300.c20
-rw-r--r--drivers/iio/light/apds9306.c7
-rw-r--r--drivers/iio/light/apds9960.c10
-rw-r--r--drivers/iio/light/bh1745.c50
-rw-r--r--drivers/iio/light/cm32181.c3
-rw-r--r--drivers/iio/light/cm3605.c2
-rw-r--r--drivers/iio/light/cm36651.c2
-rw-r--r--drivers/iio/light/gp2ap002.c2
-rw-r--r--drivers/iio/light/gp2ap020a00f.c2
-rw-r--r--drivers/iio/light/hid-sensor-als.c8
-rw-r--r--drivers/iio/light/hid-sensor-prox.c201
-rw-r--r--drivers/iio/light/iqs621-als.c2
-rw-r--r--drivers/iio/light/isl29018.c38
-rw-r--r--drivers/iio/light/lm3533-als.c8
-rw-r--r--drivers/iio/light/ltr390.c362
-rw-r--r--drivers/iio/light/ltr501.c35
-rw-r--r--drivers/iio/light/ltrf216a.c1
-rw-r--r--drivers/iio/light/max44009.c2
-rw-r--r--drivers/iio/light/opt3001.c191
-rw-r--r--drivers/iio/light/rpr0521.c14
-rw-r--r--drivers/iio/light/st_uvis25_core.c3
-rw-r--r--drivers/iio/light/stk3310.c5
-rw-r--r--drivers/iio/light/tcs3472.c2
-rw-r--r--drivers/iio/light/tsl2563.c2
-rw-r--r--drivers/iio/light/tsl2591.c2
-rw-r--r--drivers/iio/light/tsl2772.c6
-rw-r--r--drivers/iio/light/us5182d.c2
-rw-r--r--drivers/iio/light/vcnl4000.c5
-rw-r--r--drivers/iio/light/veml3235.c495
-rw-r--r--drivers/iio/light/veml6030.c537
-rw-r--r--drivers/iio/light/veml6070.c201
-rw-r--r--drivers/iio/light/vl6180.c255
-rw-r--r--drivers/iio/magnetometer/Kconfig13
-rw-r--r--drivers/iio/magnetometer/Makefile1
-rw-r--r--drivers/iio/magnetometer/ak8974.c2
-rw-r--r--drivers/iio/magnetometer/als31300.c494
-rw-r--r--drivers/iio/magnetometer/bmc150_magn.c15
-rw-r--r--drivers/iio/magnetometer/bmc150_magn_i2c.c9
-rw-r--r--drivers/iio/magnetometer/bmc150_magn_spi.c9
-rw-r--r--drivers/iio/magnetometer/hid-sensor-magn-3d.c6
-rw-r--r--drivers/iio/orientation/hid-sensor-incl-3d.c8
-rw-r--r--drivers/iio/orientation/hid-sensor-rotation.c8
-rw-r--r--drivers/iio/position/hid-sensor-custom-intel-hinge.c8
-rw-r--r--drivers/iio/position/iqs624-pos.c2
-rw-r--r--drivers/iio/pressure/bmp280-core.c713
-rw-r--r--drivers/iio/pressure/bmp280-i2c.c4
-rw-r--r--drivers/iio/pressure/bmp280-spi.c4
-rw-r--r--drivers/iio/pressure/bmp280.h56
-rw-r--r--drivers/iio/pressure/hid-sensor-press.c8
-rw-r--r--drivers/iio/pressure/rohm-bm1390.c3
-rw-r--r--drivers/iio/proximity/aw96103.c2
-rw-r--r--drivers/iio/proximity/cros_ec_mkbp_proximity.c4
-rw-r--r--drivers/iio/proximity/hx9023s.c4
-rw-r--r--drivers/iio/proximity/irsd200.c5
-rw-r--r--drivers/iio/proximity/srf04.c2
-rw-r--r--drivers/iio/proximity/sx9324.c20
-rw-r--r--drivers/iio/proximity/sx9360.c1
-rw-r--r--drivers/iio/proximity/sx9500.c6
-rw-r--r--drivers/iio/proximity/sx_common.c23
-rw-r--r--drivers/iio/proximity/sx_common.h6
-rw-r--r--drivers/iio/proximity/vcnl3020.c2
-rw-r--r--drivers/iio/proximity/vl53l0x-i2c.c174
-rw-r--r--drivers/iio/temperature/Kconfig2
-rw-r--r--drivers/iio/temperature/hid-sensor-temperature.c4
-rw-r--r--drivers/iio/temperature/mcp9600.c2
-rw-r--r--drivers/iio/temperature/tmp006.c134
-rw-r--r--drivers/iio/temperature/tmp007.c2
-rw-r--r--drivers/iio/trigger/iio-trig-interrupt.c2
-rw-r--r--drivers/iio/trigger/stm32-timer-trigger.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_sysfs.c2
-rw-r--r--drivers/interconnect/core.c4
-rw-r--r--drivers/interconnect/imx/imx8mm.c2
-rw-r--r--drivers/interconnect/imx/imx8mn.c2
-rw-r--r--drivers/interconnect/imx/imx8mp.c2
-rw-r--r--drivers/interconnect/imx/imx8mq.c2
-rw-r--r--drivers/interconnect/mediatek/mt8183.c2
-rw-r--r--drivers/interconnect/mediatek/mt8195.c2
-rw-r--r--drivers/interconnect/qcom/Kconfig29
-rw-r--r--drivers/interconnect/qcom/Makefile6
-rw-r--r--drivers/interconnect/qcom/icc-rpmh.c5
-rw-r--r--drivers/interconnect/qcom/icc-rpmh.h2
-rw-r--r--drivers/interconnect/qcom/msm8909.c2
-rw-r--r--drivers/interconnect/qcom/msm8916.c2
-rw-r--r--drivers/interconnect/qcom/msm8937.c10
-rw-r--r--drivers/interconnect/qcom/msm8939.c2
-rw-r--r--drivers/interconnect/qcom/msm8953.c2
-rw-r--r--drivers/interconnect/qcom/msm8974.c2
-rw-r--r--drivers/interconnect/qcom/msm8976.c2
-rw-r--r--drivers/interconnect/qcom/msm8996.c2
-rw-r--r--drivers/interconnect/qcom/osm-l3.c2
-rw-r--r--drivers/interconnect/qcom/qcm2290.c2
-rw-r--r--drivers/interconnect/qcom/qcs404.c2
-rw-r--r--drivers/interconnect/qcom/qcs615.c1563
-rw-r--r--drivers/interconnect/qcom/qcs615.h128
-rw-r--r--drivers/interconnect/qcom/qcs8300.c2088
-rw-r--r--drivers/interconnect/qcom/qcs8300.h177
-rw-r--r--drivers/interconnect/qcom/qdu1000.c2
-rw-r--r--drivers/interconnect/qcom/sa8775p.c2
-rw-r--r--drivers/interconnect/qcom/sar2130p.c1930
-rw-r--r--drivers/interconnect/qcom/sc7180.c2
-rw-r--r--drivers/interconnect/qcom/sc7280.c6
-rw-r--r--drivers/interconnect/qcom/sc8180x.c2
-rw-r--r--drivers/interconnect/qcom/sc8280xp.c2
-rw-r--r--drivers/interconnect/qcom/sdm660.c2
-rw-r--r--drivers/interconnect/qcom/sdm670.c2
-rw-r--r--drivers/interconnect/qcom/sdm845.c2
-rw-r--r--drivers/interconnect/qcom/sdx55.c2
-rw-r--r--drivers/interconnect/qcom/sdx65.c2
-rw-r--r--drivers/interconnect/qcom/sdx75.c2
-rw-r--r--drivers/interconnect/qcom/sm6115.c2
-rw-r--r--drivers/interconnect/qcom/sm6350.c2
-rw-r--r--drivers/interconnect/qcom/sm7150.c2
-rw-r--r--drivers/interconnect/qcom/sm8150.c2
-rw-r--r--drivers/interconnect/qcom/sm8250.c2
-rw-r--r--drivers/interconnect/qcom/sm8350.c2
-rw-r--r--drivers/interconnect/qcom/sm8450.c2
-rw-r--r--drivers/interconnect/qcom/sm8550.c2
-rw-r--r--drivers/interconnect/qcom/sm8650.c2
-rw-r--r--drivers/interconnect/qcom/smd-rpm.c2
-rw-r--r--drivers/interconnect/qcom/x1e80100.c2
-rw-r--r--drivers/interconnect/samsung/exynos.c2
-rw-r--r--drivers/iommu/amd/iommu.c9
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c9
-rw-r--r--drivers/iommu/intel/iommu.c15
-rw-r--r--drivers/iommu/intel/iommu.h6
-rw-r--r--drivers/iommu/intel/nested.c11
-rw-r--r--drivers/iommu/iommu.c4
-rw-r--r--drivers/iommu/iommufd/hw_pagetable.c16
-rw-r--r--drivers/iommu/iommufd/selftest.c15
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c50
-rw-r--r--drivers/irqchip/irq-gic.c2
-rw-r--r--drivers/irqchip/irq-imgpdc.c2
-rw-r--r--drivers/irqchip/irq-imx-intmux.c2
-rw-r--r--drivers/irqchip/irq-imx-irqsteer.c2
-rw-r--r--drivers/irqchip/irq-keystone.c2
-rw-r--r--drivers/irqchip/irq-ls-scfg-msi.c2
-rw-r--r--drivers/irqchip/irq-madera.c2
-rw-r--r--drivers/irqchip/irq-mvebu-pic.c4
-rw-r--r--drivers/irqchip/irq-mvebu-sei.c2
-rw-r--r--drivers/irqchip/irq-pruss-intc.c2
-rw-r--r--drivers/irqchip/irq-renesas-intc-irqpin.c2
-rw-r--r--drivers/irqchip/irq-renesas-irqc.c2
-rw-r--r--drivers/irqchip/irq-renesas-rza1.c2
-rw-r--r--drivers/irqchip/irq-ts4800.c2
-rw-r--r--drivers/irqchip/irq-versatile-fpga.c2
-rw-r--r--drivers/mailbox/omap-mailbox.c1
-rw-r--r--drivers/md/raid0.c1
-rw-r--r--drivers/md/raid1.c20
-rw-r--r--drivers/md/raid10.c20
-rw-r--r--drivers/misc/Kconfig1
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/apds990x.c12
-rw-r--r--drivers/misc/atmel-ssc.c4
-rw-r--r--drivers/misc/cardreader/alcor_pci.c2
-rw-r--r--drivers/misc/cardreader/rtsx_usb.c6
-rw-r--r--drivers/misc/eeprom/Kconfig4
-rw-r--r--drivers/misc/eeprom/eeprom_93cx6.c15
-rw-r--r--drivers/misc/eeprom/eeprom_93xx46.c2
-rw-r--r--drivers/misc/isl29020.c2
-rw-r--r--drivers/misc/keba/Kconfig13
-rw-r--r--drivers/misc/keba/Makefile1
-rw-r--r--drivers/misc/keba/cp500.c558
-rw-r--r--drivers/misc/keba/lan9252.c359
-rw-r--r--drivers/misc/mei/bus.c2
-rw-r--r--drivers/misc/mei/platform-vsc.c2
-rw-r--r--drivers/misc/mei/vsc-fw-loader.c26
-rw-r--r--drivers/misc/mei/vsc-tp.c2
-rw-r--r--drivers/misc/ocxl/sysfs.c2
-rw-r--r--drivers/misc/rpmb-core.c9
-rw-r--r--drivers/misc/ti-st/Kconfig19
-rw-r--r--drivers/misc/ti-st/Makefile7
-rw-r--r--drivers/misc/ti-st/st_core.c918
-rw-r--r--drivers/misc/ti-st/st_kim.c839
-rw-r--r--drivers/misc/ti-st/st_ll.c156
-rw-r--r--drivers/mtd/spi-nor/sysfs.c2
-rw-r--r--drivers/mtd/ubi/attach.c12
-rw-r--r--drivers/mtd/ubi/fastmap-wl.c19
-rw-r--r--drivers/mtd/ubi/nvmem.c2
-rw-r--r--drivers/mtd/ubi/ubi.h3
-rw-r--r--drivers/mtd/ubi/vmt.c2
-rw-r--r--drivers/mtd/ubi/wl.c32
-rw-r--r--drivers/mtd/ubi/wl.h3
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c37
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c9
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c4
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h3
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.c70
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.h5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h7
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rpm.c87
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rpm.h18
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.c1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.h1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c45
-rw-r--r--drivers/net/ethernet/marvell/pxa168_eth.c14
-rw-r--r--drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c17
-rw-r--r--drivers/net/ethernet/realtek/rtase/rtase.h7
-rw-r--r--drivers/net/ethernet/realtek/rtase/rtase_main.c43
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c3
-rw-r--r--drivers/net/mdio/mdio-ipq4019.c5
-rw-r--r--drivers/net/phy/phy-c45.c2
-rw-r--r--drivers/net/phy/phy.c52
-rw-r--r--drivers/net/usb/lan78xx.c40
-rw-r--r--drivers/nvdimm/virtio_pmem.c24
-rw-r--r--drivers/nvme/host/core.c22
-rw-r--r--drivers/nvme/host/ioctl.c12
-rw-r--r--drivers/nvme/host/multipath.c21
-rw-r--r--drivers/nvme/host/nvme.h10
-rw-r--r--drivers/nvme/host/pci.c147
-rw-r--r--drivers/nvme/host/pr.c122
-rw-r--r--drivers/nvme/host/rdma.c4
-rw-r--r--drivers/nvme/target/admin-cmd.c7
-rw-r--r--drivers/nvmem/Kconfig11
-rw-r--r--drivers/nvmem/Makefile2
-rw-r--r--drivers/nvmem/brcm_nvram.c2
-rw-r--r--drivers/nvmem/core.c22
-rw-r--r--drivers/nvmem/imx-iim.c10
-rw-r--r--drivers/nvmem/lpc18xx_otp.c2
-rw-r--r--drivers/nvmem/microchip-otpc.c2
-rw-r--r--drivers/nvmem/rcar-efuse.c142
-rw-r--r--drivers/of/Kconfig6
-rw-r--r--drivers/opp/opp.h2
-rw-r--r--drivers/pci/p2pdma.c2
-rw-r--r--drivers/pci/pci-sysfs.c42
-rw-r--r--drivers/pci/remove.c9
-rw-r--r--drivers/pci/vpd.c2
-rw-r--r--drivers/peci/controller/peci-npcm.c2
-rw-r--r--drivers/perf/arm-cmn.c4
-rw-r--r--drivers/perf/arm-ni.c1
-rw-r--r--drivers/perf/arm_smmuv3_pmu.c19
-rw-r--r--drivers/phy/Kconfig11
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/allwinner/phy-sun4i-usb.c8
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns-usb2.c54
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb-init.c435
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb.c2
-rw-r--r--drivers/phy/cadence/cdns-dphy.c2
-rw-r--r--drivers/phy/cadence/phy-cadence-sierra.c2
-rw-r--r--drivers/phy/cadence/phy-cadence-torrent.c4
-rw-r--r--drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c6
-rw-r--r--drivers/phy/freescale/phy-fsl-lynx-28g.c6
-rw-r--r--drivers/phy/freescale/phy-fsl-samsung-hdmi.c608
-rw-r--r--drivers/phy/intel/phy-intel-lgm-combo.c2
-rw-r--r--drivers/phy/marvell/phy-mvebu-cp110-utmi.c16
-rw-r--r--drivers/phy/microchip/sparx5_serdes.c195
-rw-r--r--drivers/phy/microchip/sparx5_serdes.h44
-rw-r--r--drivers/phy/microchip/sparx5_serdes_regs.h746
-rw-r--r--drivers/phy/motorola/phy-cpcap-usb.c2
-rw-r--r--drivers/phy/motorola/phy-mapphone-mdm6600.c2
-rw-r--r--drivers/phy/phy-airoha-pcie-regs.h6
-rw-r--r--drivers/phy/phy-airoha-pcie.c8
-rw-r--r--drivers/phy/phy-lgm-usb.c2
-rw-r--r--drivers/phy/phy-nxp-ptn3222.c123
-rw-r--r--drivers/phy/qualcomm/phy-qcom-apq8064-sata.c10
-rw-r--r--drivers/phy/qualcomm/phy-qcom-edp.c74
-rw-r--r--drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c2
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c8
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-combo.c8
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcie.c214
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_30.h25
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_30.h19
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-usb.c65
-rw-r--r--drivers/phy/realtek/phy-rtk-usb2.c4
-rw-r--r--drivers/phy/realtek/phy-rtk-usb3.c4
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-pcie.c8
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-usb2.c2
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-usb3.c8
-rw-r--r--drivers/phy/renesas/r8a779f0-ether-serdes.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-csidphy.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-hdmi.c4
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-usb2.c200
-rw-r--r--drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c17
-rw-r--r--drivers/phy/rockchip/phy-rockchip-typec.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-usbdp.c41
-rw-r--r--drivers/phy/st/Kconfig11
-rw-r--r--drivers/phy/st/Makefile1
-rw-r--r--drivers/phy/st/phy-stm32-combophy.c598
-rw-r--r--drivers/phy/st/phy-stm32-usbphyc.c2
-rw-r--r--drivers/phy/tegra/xusb.c4
-rw-r--r--drivers/phy/ti/phy-am654-serdes.c2
-rw-r--r--drivers/phy/ti/phy-da8xx-usb.c4
-rw-r--r--drivers/phy/ti/phy-dm816x-usb.c2
-rw-r--r--drivers/phy/ti/phy-gmii-sel.c3
-rw-r--r--drivers/phy/ti/phy-j721e-wiz.c2
-rw-r--r--drivers/phy/ti/phy-omap-usb2.c2
-rw-r--r--drivers/phy/ti/phy-ti-pipe3.c2
-rw-r--r--drivers/phy/ti/phy-twl4030-usb.c2
-rw-r--r--drivers/phy/xilinx/phy-zynqmp.c2
-rw-r--r--drivers/pinctrl/bcm/pinctrl-iproc-gpio.c2
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-37xx.c2
-rw-r--r--drivers/pinctrl/pinctrl-mcp23s08.c2
-rw-r--r--drivers/pinctrl/pinctrl-stmfx.c2
-rw-r--r--drivers/pinctrl/pinctrl-sx150x.c2
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzg2l.c2
-rw-r--r--drivers/platform/goldfish/goldfish_pipe.c3
-rw-r--r--drivers/platform/x86/amd/hsmp/acpi.c2
-rw-r--r--drivers/platform/x86/amd/hsmp/plat.c2
-rw-r--r--drivers/platform/x86/intel/pmt/class.c2
-rw-r--r--drivers/platform/x86/intel/sdsi.c2
-rw-r--r--drivers/power/reset/Kconfig1
-rw-r--r--drivers/power/reset/at91-poweroff.c2
-rw-r--r--drivers/power/reset/at91-reset.c2
-rw-r--r--drivers/power/reset/at91-sama5d2_shdwc.c2
-rw-r--r--drivers/power/reset/keystone-reset.c2
-rw-r--r--drivers/power/reset/ltc2952-poweroff.c2
-rw-r--r--drivers/power/reset/qnap-poweroff.c2
-rw-r--r--drivers/power/reset/syscon-reboot.c3
-rw-r--r--drivers/power/supply/88pm860x_battery.c4
-rw-r--r--drivers/power/supply/Kconfig10
-rw-r--r--drivers/power/supply/Makefile1
-rw-r--r--drivers/power/supply/ab8500_bmdata.c4
-rw-r--r--drivers/power/supply/ab8500_btemp.c4
-rw-r--r--drivers/power/supply/ab8500_chargalg.c2
-rw-r--r--drivers/power/supply/ab8500_charger.c2
-rw-r--r--drivers/power/supply/ab8500_fg.c2
-rw-r--r--drivers/power/supply/acer_a500_battery.c9
-rw-r--r--drivers/power/supply/act8945a_charger.c2
-rw-r--r--drivers/power/supply/adp5061.c2
-rw-r--r--drivers/power/supply/axp20x_battery.c33
-rw-r--r--drivers/power/supply/axp20x_usb_power.c33
-rw-r--r--drivers/power/supply/bq27xxx_battery.c40
-rw-r--r--drivers/power/supply/charger-manager.c4
-rw-r--r--drivers/power/supply/cpcap-battery.c2
-rw-r--r--drivers/power/supply/cpcap-charger.c2
-rw-r--r--drivers/power/supply/cros_usbpd-charger.c4
-rw-r--r--drivers/power/supply/da9030_battery.c6
-rw-r--r--drivers/power/supply/da9052-battery.c2
-rw-r--r--drivers/power/supply/da9150-charger.c2
-rw-r--r--drivers/power/supply/generic-adc-battery.c4
-rw-r--r--drivers/power/supply/ipaq_micro_battery.c2
-rw-r--r--drivers/power/supply/isp1704_charger.c2
-rw-r--r--drivers/power/supply/lenovo_yoga_c630_battery.c14
-rw-r--r--drivers/power/supply/lp8788-charger.c2
-rw-r--r--drivers/power/supply/max14577_charger.c2
-rw-r--r--drivers/power/supply/max77650-charger.c2
-rw-r--r--drivers/power/supply/max77693_charger.c2
-rw-r--r--drivers/power/supply/max77976_charger.c3
-rw-r--r--drivers/power/supply/max8925_power.c4
-rw-r--r--drivers/power/supply/pcf50633-charger.c2
-rw-r--r--drivers/power/supply/pmu_battery.c1
-rw-r--r--drivers/power/supply/power_supply.h22
-rw-r--r--drivers/power/supply/power_supply_core.c87
-rw-r--r--drivers/power/supply/power_supply_hwmon.c1
-rw-r--r--drivers/power/supply/power_supply_sysfs.c12
-rw-r--r--drivers/power/supply/qcom_battmgr.c2
-rw-r--r--drivers/power/supply/qcom_pmi8998_charger.c2
-rw-r--r--drivers/power/supply/qcom_smbb.c8
-rw-r--r--drivers/power/supply/rk817_charger.c112
-rw-r--r--drivers/power/supply/rt9471.c52
-rw-r--r--drivers/power/supply/samsung-sdi-battery.c10
-rw-r--r--drivers/power/supply/sc2731_charger.c2
-rw-r--r--drivers/power/supply/sc27xx_fuel_gauge.c12
-rw-r--r--drivers/power/supply/tps65090-charger.c2
-rw-r--r--drivers/power/supply/tps65217_charger.c2
-rw-r--r--drivers/power/supply/twl4030_charger.c2
-rw-r--r--drivers/power/supply/twl6030_charger.c581
-rw-r--r--drivers/power/supply/wm831x_power.c2
-rw-r--r--drivers/power/supply/wm8350_power.c2
-rw-r--r--drivers/power/supply/wm97xx_battery.c2
-rw-r--r--drivers/regulator/core.c3
-rw-r--r--drivers/regulator/qcom-rpmh-regulator.c83
-rw-r--r--drivers/rtc/Kconfig33
-rw-r--r--drivers/rtc/Makefile5
-rw-r--r--drivers/rtc/interface.c7
-rw-r--r--drivers/rtc/rtc-88pm80x.c2
-rw-r--r--drivers/rtc/rtc-88pm860x.c2
-rw-r--r--drivers/rtc/rtc-88pm886.c97
-rw-r--r--drivers/rtc/rtc-ab-eoz9.c11
-rw-r--r--drivers/rtc/rtc-ab8500.c2
-rw-r--r--drivers/rtc/rtc-abx80x.c2
-rw-r--r--drivers/rtc/rtc-ac100.c2
-rw-r--r--drivers/rtc/rtc-amlogic-a4.c465
-rw-r--r--drivers/rtc/rtc-asm9260.c2
-rw-r--r--drivers/rtc/rtc-at91rm9200.c2
-rw-r--r--drivers/rtc/rtc-at91sam9.c2
-rw-r--r--drivers/rtc/rtc-brcmstb-waketimer.c3
-rw-r--r--drivers/rtc/rtc-cadence.c2
-rw-r--r--drivers/rtc/rtc-cmos.c33
-rw-r--r--drivers/rtc/rtc-cros-ec.c2
-rw-r--r--drivers/rtc/rtc-ds1685.c2
-rw-r--r--drivers/rtc/rtc-ftrtc010.c2
-rw-r--r--drivers/rtc/rtc-hid-sensor-time.c2
-rw-r--r--drivers/rtc/rtc-imxdi.c2
-rw-r--r--drivers/rtc/rtc-isl12022.c269
-rw-r--r--drivers/rtc/rtc-loongson.c2
-rw-r--r--drivers/rtc/rtc-lpc24xx.c2
-rw-r--r--drivers/rtc/rtc-m48t59.c26
-rw-r--r--drivers/rtc/rtc-max77686.c2
-rw-r--r--drivers/rtc/rtc-mc13xxx.c2
-rw-r--r--drivers/rtc/rtc-mc146818-lib.c6
-rw-r--r--drivers/rtc/rtc-mpc5121.c2
-rw-r--r--drivers/rtc/rtc-mpfs.c2
-rw-r--r--drivers/rtc/rtc-mt6397.c29
-rw-r--r--drivers/rtc/rtc-mt7622.c2
-rw-r--r--drivers/rtc/rtc-mv.c2
-rw-r--r--drivers/rtc/rtc-mxc_v2.c2
-rw-r--r--drivers/rtc/rtc-nxp-bbnsm.c20
-rw-r--r--drivers/rtc/rtc-omap.c2
-rw-r--r--drivers/rtc/rtc-palmas.c2
-rw-r--r--drivers/rtc/rtc-pcf50633.c2
-rw-r--r--drivers/rtc/rtc-pcf8563.c212
-rw-r--r--drivers/rtc/rtc-pic32.c2
-rw-r--r--drivers/rtc/rtc-pm8xxx.c2
-rw-r--r--drivers/rtc/rtc-pxa.c2
-rw-r--r--drivers/rtc/rtc-rc5t583.c2
-rw-r--r--drivers/rtc/rtc-renesas-rtca3.c900
-rw-r--r--drivers/rtc/rtc-rtd119x.c2
-rw-r--r--drivers/rtc/rtc-rv3028.c6
-rw-r--r--drivers/rtc/rtc-rzn1.c92
-rw-r--r--drivers/rtc/rtc-s3c.c2
-rw-r--r--drivers/rtc/rtc-sa1100.c2
-rw-r--r--drivers/rtc/rtc-sh.c2
-rw-r--r--drivers/rtc/rtc-spear.c2
-rw-r--r--drivers/rtc/rtc-st-lpc.c5
-rw-r--r--drivers/rtc/rtc-stm32.c2
-rw-r--r--drivers/rtc/rtc-stmp3xxx.c2
-rw-r--r--drivers/rtc/rtc-sunplus.c2
-rw-r--r--drivers/rtc/rtc-tegra.c2
-rw-r--r--drivers/rtc/rtc-tps6586x.c2
-rw-r--r--drivers/rtc/rtc-twl.c2
-rw-r--r--drivers/rtc/rtc-vt8500.c2
-rw-r--r--drivers/rtc/rtc-wm8350.c2
-rw-r--r--drivers/rtc/rtc-xgene.c2
-rw-r--r--drivers/rtc/rtc-zynqmp.c2
-rw-r--r--drivers/s390/char/con3215.c1
-rw-r--r--drivers/s390/crypto/ap_bus.c2
-rw-r--r--drivers/s390/crypto/vfio_ap_ops.c32
-rw-r--r--drivers/scsi/scsi_sysfs.c2
-rw-r--r--drivers/sh/intc/core.c2
-rw-r--r--drivers/soundwire/amd_init.c1
-rw-r--r--drivers/soundwire/amd_manager.c99
-rw-r--r--drivers/soundwire/amd_manager.h16
-rw-r--r--drivers/soundwire/bus.c2
-rw-r--r--drivers/soundwire/cadence_master.c30
-rw-r--r--drivers/soundwire/cadence_master.h1
-rw-r--r--drivers/soundwire/intel_auxdevice.c12
-rw-r--r--drivers/soundwire/intel_bus_common.c6
-rw-r--r--drivers/soundwire/mipi_disco.c144
-rw-r--r--drivers/soundwire/qcom.c2
-rw-r--r--drivers/soundwire/sysfs_slave.c2
-rw-r--r--drivers/spi/atmel-quadspi.c2
-rw-r--r--drivers/spi/spi-imx.c2
-rw-r--r--drivers/spi/spi-rockchip-sfc.c2
-rw-r--r--drivers/spi/spi.c13
-rw-r--r--drivers/spmi/spmi-pmic-arb.c3
-rw-r--r--drivers/staging/Kconfig16
-rw-r--r--drivers/staging/Makefile8
-rw-r--r--drivers/staging/axis-fifo/axis-fifo.c2
-rw-r--r--drivers/staging/fbtft/fbtft.h2
-rw-r--r--drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev31
-rw-r--r--drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev62
-rw-r--r--drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt71
-rw-r--r--drivers/staging/fieldbus/Documentation/fieldbus_dev.txt66
-rw-r--r--drivers/staging/fieldbus/Kconfig19
-rw-r--r--drivers/staging/fieldbus/Makefile7
-rw-r--r--drivers/staging/fieldbus/TODO5
-rw-r--r--drivers/staging/fieldbus/anybuss/Kconfig41
-rw-r--r--drivers/staging/fieldbus/anybuss/Makefile10
-rw-r--r--drivers/staging/fieldbus/anybuss/anybuss-client.h95
-rw-r--r--drivers/staging/fieldbus/anybuss/anybuss-controller.h47
-rw-r--r--drivers/staging/fieldbus/anybuss/arcx-anybus.c379
-rw-r--r--drivers/staging/fieldbus/anybuss/hms-profinet.c224
-rw-r--r--drivers/staging/fieldbus/anybuss/host.c1452
-rw-r--r--drivers/staging/fieldbus/dev_core.c344
-rw-r--r--drivers/staging/fieldbus/fieldbus_dev.h114
-rw-r--r--drivers/staging/gdm724x/Kconfig16
-rw-r--r--drivers/staging/gdm724x/Makefile8
-rw-r--r--drivers/staging/gdm724x/TODO16
-rw-r--r--drivers/staging/gdm724x/gdm_endian.c37
-rw-r--r--drivers/staging/gdm724x/gdm_endian.h30
-rw-r--r--drivers/staging/gdm724x/gdm_lte.c937
-rw-r--r--drivers/staging/gdm724x/gdm_lte.h71
-rw-r--r--drivers/staging/gdm724x/gdm_mux.c668
-rw-r--r--drivers/staging/gdm724x/gdm_mux.h85
-rw-r--r--drivers/staging/gdm724x/gdm_tty.c316
-rw-r--r--drivers/staging/gdm724x/gdm_tty.h60
-rw-r--r--drivers/staging/gdm724x/gdm_usb.c1012
-rw-r--r--drivers/staging/gdm724x/gdm_usb.h99
-rw-r--r--drivers/staging/gdm724x/hci.h45
-rw-r--r--drivers/staging/gdm724x/hci_packet.h82
-rw-r--r--drivers/staging/gdm724x/netlink_k.c128
-rw-r--r--drivers/staging/gdm724x/netlink_k.h16
-rw-r--r--drivers/staging/gpib/Kconfig251
-rw-r--r--drivers/staging/gpib/Makefile20
-rw-r--r--drivers/staging/gpib/TODO21
-rw-r--r--drivers/staging/gpib/agilent_82350b/Makefile2
-rw-r--r--drivers/staging/gpib/agilent_82350b/agilent_82350b.c932
-rw-r--r--drivers/staging/gpib/agilent_82350b/agilent_82350b.h209
-rw-r--r--drivers/staging/gpib/agilent_82357a/Makefile4
-rw-r--r--drivers/staging/gpib/agilent_82357a/agilent_82357a.c1712
-rw-r--r--drivers/staging/gpib/agilent_82357a/agilent_82357a.h182
-rw-r--r--drivers/staging/gpib/cb7210/Makefile4
-rw-r--r--drivers/staging/gpib/cb7210/cb7210.c1556
-rw-r--r--drivers/staging/gpib/cb7210/cb7210.h251
-rw-r--r--drivers/staging/gpib/cec/Makefile3
-rw-r--r--drivers/staging/gpib/cec/cec.h53
-rw-r--r--drivers/staging/gpib/cec/cec_gpib.c385
-rw-r--r--drivers/staging/gpib/common/Makefile6
-rw-r--r--drivers/staging/gpib/common/gpib_os.c2328
-rw-r--r--drivers/staging/gpib/common/iblib.c740
-rw-r--r--drivers/staging/gpib/common/ibsys.h31
-rw-r--r--drivers/staging/gpib/eastwood/Makefile3
-rw-r--r--drivers/staging/gpib/eastwood/fluke_gpib.c1179
-rw-r--r--drivers/staging/gpib/eastwood/fluke_gpib.h143
-rw-r--r--drivers/staging/gpib/fmh_gpib/Makefile2
-rw-r--r--drivers/staging/gpib/fmh_gpib/fmh_gpib.c1725
-rw-r--r--drivers/staging/gpib/fmh_gpib/fmh_gpib.h177
-rw-r--r--drivers/staging/gpib/gpio/Makefile4
-rw-r--r--drivers/staging/gpib/gpio/gpib_bitbang.c1476
-rw-r--r--drivers/staging/gpib/hp_82335/Makefile4
-rw-r--r--drivers/staging/gpib/hp_82335/hp82335.c360
-rw-r--r--drivers/staging/gpib/hp_82335/hp82335.h85
-rw-r--r--drivers/staging/gpib/hp_82341/Makefile2
-rw-r--r--drivers/staging/gpib/hp_82341/hp_82341.c895
-rw-r--r--drivers/staging/gpib/hp_82341/hp_82341.h207
-rw-r--r--drivers/staging/gpib/include/amcc5920.h49
-rw-r--r--drivers/staging/gpib/include/amccs5933.h59
-rw-r--r--drivers/staging/gpib/include/gpibP.h50
-rw-r--r--drivers/staging/gpib/include/gpib_pci_ids.h23
-rw-r--r--drivers/staging/gpib/include/gpib_proto.h56
-rw-r--r--drivers/staging/gpib/include/gpib_state_machines.h23
-rw-r--r--drivers/staging/gpib/include/gpib_types.h353
-rw-r--r--drivers/staging/gpib/include/nec7210.h138
-rw-r--r--drivers/staging/gpib/include/nec7210_registers.h217
-rw-r--r--drivers/staging/gpib/include/plx9050.h72
-rw-r--r--drivers/staging/gpib/include/quancom_pci.h22
-rw-r--r--drivers/staging/gpib/include/tms9914.h274
-rw-r--r--drivers/staging/gpib/include/tnt4882_registers.h192
-rw-r--r--drivers/staging/gpib/ines/Makefile4
-rw-r--r--drivers/staging/gpib/ines/ines.h215
-rw-r--r--drivers/staging/gpib/ines/ines_gpib.c1464
-rw-r--r--drivers/staging/gpib/lpvo_usb_gpib/Makefile3
-rw-r--r--drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c2136
-rw-r--r--drivers/staging/gpib/nec7210/Makefile4
-rw-r--r--drivers/staging/gpib/nec7210/board.h19
-rw-r--r--drivers/staging/gpib/nec7210/nec7210.c1134
-rw-r--r--drivers/staging/gpib/ni_usb/Makefile4
-rw-r--r--drivers/staging/gpib/ni_usb/ni_usb_gpib.c2640
-rw-r--r--drivers/staging/gpib/ni_usb/ni_usb_gpib.h216
-rw-r--r--drivers/staging/gpib/pc2/Makefile5
-rw-r--r--drivers/staging/gpib/pc2/pc2_gpib.c656
-rw-r--r--drivers/staging/gpib/tms9914/Makefile6
-rw-r--r--drivers/staging/gpib/tms9914/tms9914.c910
-rw-r--r--drivers/staging/gpib/tnt4882/Makefile7
-rw-r--r--drivers/staging/gpib/tnt4882/mite.c219
-rw-r--r--drivers/staging/gpib/tnt4882/mite.h243
-rw-r--r--drivers/staging/gpib/tnt4882/tnt4882_gpib.c1874
-rw-r--r--drivers/staging/gpib/uapi/gpib_ioctl.h169
-rw-r--r--drivers/staging/gpib/uapi/gpib_user.h363
-rw-r--r--drivers/staging/greybus/arche-apb-ctrl.c2
-rw-r--r--drivers/staging/greybus/arche-platform.c2
-rw-r--r--drivers/staging/greybus/gpio.c33
-rw-r--r--drivers/staging/greybus/uart.c2
-rw-r--r--drivers/staging/iio/TODO5
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c6
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c2
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c2
-rw-r--r--drivers/staging/media/imx/imx-media-csi.c2
-rw-r--r--drivers/staging/media/imx/imx-media-dev.c2
-rw-r--r--drivers/staging/media/imx/imx6-mipi-csi2.c2
-rw-r--r--drivers/staging/media/meson/vdec/vdec.c2
-rw-r--r--drivers/staging/media/rkvdec/rkvdec.c2
-rw-r--r--drivers/staging/media/starfive/camss/stf-camss.c2
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus.c2
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c2
-rw-r--r--drivers/staging/media/tegra-video/csi.c2
-rw-r--r--drivers/staging/media/tegra-video/vi.c2
-rw-r--r--drivers/staging/media/tegra-video/vip.c2
-rw-r--r--drivers/staging/most/TODO7
-rw-r--r--drivers/staging/most/dim2/dim2.c2
-rw-r--r--drivers/staging/most/i2c/i2c.c4
-rw-r--r--drivers/staging/nvec/nvec.c2
-rw-r--r--drivers/staging/nvec/nvec_kbd.c2
-rw-r--r--drivers/staging/nvec/nvec_power.c2
-rw-r--r--drivers/staging/nvec/nvec_ps2.c2
-rw-r--r--drivers/staging/octeon/ethernet-tx.c6
-rw-r--r--drivers/staging/octeon/ethernet.c2
-rw-r--r--drivers/staging/olpc_dcon/Kconfig17
-rw-r--r--drivers/staging/olpc_dcon/Makefile5
-rw-r--r--drivers/staging/olpc_dcon/TODO15
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.c807
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.h112
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon_xo_1.c201
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c204
-rw-r--r--drivers/staging/rtl8712/Kconfig21
-rw-r--r--drivers/staging/rtl8712/Makefile35
-rw-r--r--drivers/staging/rtl8712/TODO12
-rw-r--r--drivers/staging/rtl8712/basic_types.h28
-rw-r--r--drivers/staging/rtl8712/drv_types.h175
-rw-r--r--drivers/staging/rtl8712/ethernet.h21
-rw-r--r--drivers/staging/rtl8712/hal_init.c401
-rw-r--r--drivers/staging/rtl8712/ieee80211.c415
-rw-r--r--drivers/staging/rtl8712/ieee80211.h165
-rw-r--r--drivers/staging/rtl8712/mlme_linux.c160
-rw-r--r--drivers/staging/rtl8712/mlme_osdep.h31
-rw-r--r--drivers/staging/rtl8712/mp_custom_oid.h287
-rw-r--r--drivers/staging/rtl8712/os_intfs.c482
-rw-r--r--drivers/staging/rtl8712/osdep_intf.h32
-rw-r--r--drivers/staging/rtl8712/osdep_service.h60
-rw-r--r--drivers/staging/rtl8712/recv_linux.c139
-rw-r--r--drivers/staging/rtl8712/recv_osdep.h39
-rw-r--r--drivers/staging/rtl8712/rtl8712_bitdef.h26
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.c409
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.h231
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h95
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h41
-rw-r--r--drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h32
-rw-r--r--drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h65
-rw-r--r--drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h24
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.c563
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.h44
-rw-r--r--drivers/staging/rtl8712/rtl8712_event.h86
-rw-r--r--drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h131
-rw-r--r--drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h61
-rw-r--r--drivers/staging/rtl8712/rtl8712_gp_bitdef.h68
-rw-r--r--drivers/staging/rtl8712/rtl8712_gp_regdef.h29
-rw-r--r--drivers/staging/rtl8712/rtl8712_hal.h142
-rw-r--r--drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h44
-rw-r--r--drivers/staging/rtl8712/rtl8712_io.c99
-rw-r--r--drivers/staging/rtl8712/rtl8712_led.c1830
-rw-r--r--drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h31
-rw-r--r--drivers/staging/rtl8712/rtl8712_macsetting_regdef.h20
-rw-r--r--drivers/staging/rtl8712/rtl8712_powersave_bitdef.h39
-rw-r--r--drivers/staging/rtl8712/rtl8712_powersave_regdef.h26
-rw-r--r--drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h36
-rw-r--r--drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h43
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.c1075
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.h145
-rw-r--r--drivers/staging/rtl8712/rtl8712_regdef.h32
-rw-r--r--drivers/staging/rtl8712/rtl8712_security_bitdef.h34
-rw-r--r--drivers/staging/rtl8712/rtl8712_spec.h121
-rw-r--r--drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h163
-rw-r--r--drivers/staging/rtl8712/rtl8712_syscfg_regdef.h42
-rw-r--r--drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h49
-rw-r--r--drivers/staging/rtl8712/rtl8712_timectrl_regdef.h26
-rw-r--r--drivers/staging/rtl8712/rtl8712_wmac_bitdef.h49
-rw-r--r--drivers/staging/rtl8712/rtl8712_wmac_regdef.h36
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.c732
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.h108
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.c750
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.h750
-rw-r--r--drivers/staging/rtl8712/rtl871x_debug.h130
-rw-r--r--drivers/staging/rtl8712/rtl871x_eeprom.c220
-rw-r--r--drivers/staging/rtl8712/rtl871x_eeprom.h88
-rw-r--r--drivers/staging/rtl8712/rtl871x_event.h109
-rw-r--r--drivers/staging/rtl8712/rtl871x_ht.h33
-rw-r--r--drivers/staging/rtl8712/rtl871x_io.c147
-rw-r--r--drivers/staging/rtl8712/rtl871x_io.h236
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl.h94
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_linux.c2275
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_rtl.c519
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_rtl.h109
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.c354
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.h45
-rw-r--r--drivers/staging/rtl8712/rtl871x_led.h118
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.c1710
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.h205
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.c724
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.h275
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_ioctl.c883
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_ioctl.h328
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h1034
-rw-r--r--drivers/staging/rtl8712/rtl871x_pwrctrl.c234
-rw-r--r--drivers/staging/rtl8712/rtl871x_pwrctrl.h113
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.c671
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.h208
-rw-r--r--drivers/staging/rtl8712/rtl871x_rf.h55
-rw-r--r--drivers/staging/rtl8712/rtl871x_security.c1386
-rw-r--r--drivers/staging/rtl8712/rtl871x_security.h218
-rw-r--r--drivers/staging/rtl8712/rtl871x_sta_mgt.c263
-rw-r--r--drivers/staging/rtl8712/rtl871x_wlan_sme.h35
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.c1056
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.h287
-rw-r--r--drivers/staging/rtl8712/sta_info.h132
-rw-r--r--drivers/staging/rtl8712/usb_halinit.c307
-rw-r--r--drivers/staging/rtl8712/usb_intf.c638
-rw-r--r--drivers/staging/rtl8712/usb_ops.c195
-rw-r--r--drivers/staging/rtl8712/usb_ops.h38
-rw-r--r--drivers/staging/rtl8712/usb_ops_linux.c508
-rw-r--r--drivers/staging/rtl8712/usb_osintf.h35
-rw-r--r--drivers/staging/rtl8712/wifi.h196
-rw-r--r--drivers/staging/rtl8712/wlan_bssdef.h223
-rw-r--r--drivers/staging/rtl8712/xmit_linux.c181
-rw-r--r--drivers/staging/rtl8712/xmit_osdep.h52
-rw-r--r--drivers/staging/rtl8723bs/TODO3
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_cmd.c6
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_efuse.c94
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme.c6
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme_ext.c11
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_pwrctrl.c7
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_wlan_util.c68
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_xmit.c2
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_com.c42
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_intf.c137
-rw-r--r--drivers/staging/rtl8723bs/hal/odm.c14
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c550
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c15
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c4
-rw-r--r--drivers/staging/rtl8723bs/hal/sdio_halinit.c59
-rw-r--r--drivers/staging/rtl8723bs/include/drv_types.h10
-rw-r--r--drivers/staging/rtl8723bs/include/hal_com.h4
-rw-r--r--drivers/staging/rtl8723bs/include/hal_intf.h95
-rw-r--r--drivers/staging/rtl8723bs/include/hal_phy_cfg.h5
-rw-r--r--drivers/staging/rtl8723bs/include/osdep_intf.h3
-rw-r--r--drivers/staging/rtl8723bs/include/osdep_service.h5
-rw-r--r--drivers/staging/rtl8723bs/include/rtl8723b_recv.h5
-rw-r--r--drivers/staging/rtl8723bs/include/rtl8723b_xmit.h2
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_efuse.h4
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_mlme_ext.h5
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_mp.h4
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c12
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_linux.c17
-rw-r--r--drivers/staging/rtl8723bs/os_dep/os_intfs.c31
-rw-r--r--drivers/staging/rtl8723bs/os_dep/sdio_intf.c17
-rw-r--r--drivers/staging/rts5208/Kconfig9
-rw-r--r--drivers/staging/rts5208/Makefile5
-rw-r--r--drivers/staging/rts5208/TODO7
-rw-r--r--drivers/staging/rts5208/general.c25
-rw-r--r--drivers/staging/rts5208/general.h19
-rw-r--r--drivers/staging/rts5208/ms.c4311
-rw-r--r--drivers/staging/rts5208/ms.h214
-rw-r--r--drivers/staging/rts5208/rtsx.c987
-rw-r--r--drivers/staging/rts5208/rtsx.h164
-rw-r--r--drivers/staging/rts5208/rtsx_card.c1151
-rw-r--r--drivers/staging/rts5208/rtsx_card.h1087
-rw-r--r--drivers/staging/rts5208/rtsx_chip.c2161
-rw-r--r--drivers/staging/rts5208/rtsx_chip.h987
-rw-r--r--drivers/staging/rts5208/rtsx_scsi.c3279
-rw-r--r--drivers/staging/rts5208/rtsx_scsi.h131
-rw-r--r--drivers/staging/rts5208/rtsx_sys.h36
-rw-r--r--drivers/staging/rts5208/rtsx_transport.c768
-rw-r--r--drivers/staging/rts5208/rtsx_transport.h57
-rw-r--r--drivers/staging/rts5208/sd.c4717
-rw-r--r--drivers/staging/rts5208/sd.h289
-rw-r--r--drivers/staging/rts5208/spi.c906
-rw-r--r--drivers/staging/rts5208/spi.h52
-rw-r--r--drivers/staging/rts5208/xd.c2145
-rw-r--r--drivers/staging/rts5208/xd.h176
-rw-r--r--drivers/staging/sm750fb/TODO5
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c3
-rw-r--r--drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h7
-rw-r--r--drivers/staging/vc04_services/interface/TESTING4
-rw-r--r--drivers/staging/vc04_services/interface/TODO13
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c526
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h3
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c696
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h55
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h3
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c44
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h2
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h21
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c7
-rw-r--r--drivers/staging/vme_user/vme_bridge.h56
-rw-r--r--drivers/staging/vt6655/Kconfig6
-rw-r--r--drivers/staging/vt6655/Makefile15
-rw-r--r--drivers/staging/vt6655/TODO20
-rw-r--r--drivers/staging/vt6655/baseband.c2257
-rw-r--r--drivers/staging/vt6655/baseband.h72
-rw-r--r--drivers/staging/vt6655/card.c836
-rw-r--r--drivers/staging/vt6655/card.h62
-rw-r--r--drivers/staging/vt6655/channel.c135
-rw-r--r--drivers/staging/vt6655/channel.h17
-rw-r--r--drivers/staging/vt6655/desc.h249
-rw-r--r--drivers/staging/vt6655/device.h292
-rw-r--r--drivers/staging/vt6655/device_cfg.h44
-rw-r--r--drivers/staging/vt6655/device_main.c1868
-rw-r--r--drivers/staging/vt6655/dpc.c145
-rw-r--r--drivers/staging/vt6655/dpc.h21
-rw-r--r--drivers/staging/vt6655/key.c143
-rw-r--r--drivers/staging/vt6655/key.h51
-rw-r--r--drivers/staging/vt6655/mac.c851
-rw-r--r--drivers/staging/vt6655/mac.h580
-rw-r--r--drivers/staging/vt6655/power.c144
-rw-r--r--drivers/staging/vt6655/power.h29
-rw-r--r--drivers/staging/vt6655/rf.c535
-rw-r--r--drivers/staging/vt6655/rf.h71
-rw-r--r--drivers/staging/vt6655/rxtx.c1462
-rw-r--r--drivers/staging/vt6655/rxtx.h184
-rw-r--r--drivers/staging/vt6655/srom.c139
-rw-r--r--drivers/staging/vt6655/srom.h85
-rw-r--r--drivers/staging/vt6655/test9
-rw-r--r--drivers/staging/vt6656/Kconfig7
-rw-r--r--drivers/staging/vt6656/Makefile15
-rw-r--r--drivers/staging/vt6656/TODO17
-rw-r--r--drivers/staging/vt6656/baseband.c455
-rw-r--r--drivers/staging/vt6656/baseband.h75
-rw-r--r--drivers/staging/vt6656/card.c456
-rw-r--r--drivers/staging/vt6656/card.h44
-rw-r--r--drivers/staging/vt6656/channel.c77
-rw-r--r--drivers/staging/vt6656/channel.h21
-rw-r--r--drivers/staging/vt6656/desc.h91
-rw-r--r--drivers/staging/vt6656/device.h386
-rw-r--r--drivers/staging/vt6656/key.c142
-rw-r--r--drivers/staging/vt6656/key.h40
-rw-r--r--drivers/staging/vt6656/mac.c183
-rw-r--r--drivers/staging/vt6656/mac.h373
-rw-r--r--drivers/staging/vt6656/main_usb.c1121
-rw-r--r--drivers/staging/vt6656/power.c112
-rw-r--r--drivers/staging/vt6656/power.h23
-rw-r--r--drivers/staging/vt6656/rf.c443
-rw-r--r--drivers/staging/vt6656/rf.h46
-rw-r--r--drivers/staging/vt6656/rxtx.c730
-rw-r--r--drivers/staging/vt6656/rxtx.h178
-rw-r--r--drivers/staging/vt6656/usbpipe.c506
-rw-r--r--drivers/staging/vt6656/usbpipe.h67
-rw-r--r--drivers/staging/vt6656/wcmd.c185
-rw-r--r--drivers/staging/vt6656/wcmd.h48
-rw-r--r--drivers/thermal/gov_power_allocator.c7
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3400_thermal.c18
-rw-r--r--drivers/thermal/qcom/qcom-spmi-adc-tm5.c7
-rw-r--r--drivers/thermal/sun8i_thermal.c11
-rw-r--r--drivers/thermal/tegra/soctherm.c5
-rw-r--r--drivers/thermal/thermal_of.c50
-rw-r--r--drivers/thunderbolt/debugfs.c504
-rw-r--r--drivers/thunderbolt/nhi.c12
-rw-r--r--drivers/thunderbolt/sb_regs.h32
-rw-r--r--drivers/thunderbolt/tb.h16
-rw-r--r--drivers/thunderbolt/usb4.c18
-rw-r--r--drivers/tty/serial/8250/8250_aspeed_vuart.c2
-rw-r--r--drivers/tty/serial/8250/8250_bcm2835aux.c2
-rw-r--r--drivers/tty/serial/8250/8250_bcm7271.c4
-rw-r--r--drivers/tty/serial/8250/8250_dw.c7
-rw-r--r--drivers/tty/serial/8250/8250_em.c2
-rw-r--r--drivers/tty/serial/8250/8250_exar.c134
-rw-r--r--drivers/tty/serial/8250/8250_fintek.c16
-rw-r--r--drivers/tty/serial/8250/8250_fsl.c2
-rw-r--r--drivers/tty/serial/8250/8250_ingenic.c2
-rw-r--r--drivers/tty/serial/8250/8250_ioc3.c2
-rw-r--r--drivers/tty/serial/8250/8250_lpc18xx.c2
-rw-r--r--drivers/tty/serial/8250/8250_mtk.c6
-rw-r--r--drivers/tty/serial/8250/8250_of.c2
-rw-r--r--drivers/tty/serial/8250/8250_omap.c10
-rw-r--r--drivers/tty/serial/8250/8250_platform.c2
-rw-r--r--drivers/tty/serial/8250/8250_pxa.c2
-rw-r--r--drivers/tty/serial/8250/8250_tegra.c2
-rw-r--r--drivers/tty/serial/8250/8250_uniphier.c2
-rw-r--r--drivers/tty/serial/8250/Kconfig1
-rw-r--r--drivers/tty/serial/altera_jtaguart.c6
-rw-r--r--drivers/tty/serial/altera_uart.c6
-rw-r--r--drivers/tty/serial/amba-pl011.c9
-rw-r--r--drivers/tty/serial/ar933x_uart.c2
-rw-r--r--drivers/tty/serial/atmel_serial.c16
-rw-r--r--drivers/tty/serial/bcm63xx_uart.c2
-rw-r--r--drivers/tty/serial/clps711x.c2
-rw-r--r--drivers/tty/serial/cpm_uart.c2
-rw-r--r--drivers/tty/serial/digicolor-usart.c2
-rw-r--r--drivers/tty/serial/esp32_acm.c2
-rw-r--r--drivers/tty/serial/esp32_uart.c2
-rw-r--r--drivers/tty/serial/fsl_linflexuart.c2
-rw-r--r--drivers/tty/serial/fsl_lpuart.c23
-rw-r--r--drivers/tty/serial/imx.c137
-rw-r--r--drivers/tty/serial/lantiq.c2
-rw-r--r--drivers/tty/serial/liteuart.c2
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c2
-rw-r--r--drivers/tty/serial/ma35d1_serial.c2
-rw-r--r--drivers/tty/serial/mcf.c2
-rw-r--r--drivers/tty/serial/meson_uart.c2
-rw-r--r--drivers/tty/serial/milbeaut_usio.c2
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c2
-rw-r--r--drivers/tty/serial/msm_serial.c2
-rw-r--r--drivers/tty/serial/mxs-auart.c2
-rw-r--r--drivers/tty/serial/omap-serial.c2
-rw-r--r--drivers/tty/serial/owl-uart.c2
-rw-r--r--drivers/tty/serial/pic32_uart.c2
-rw-r--r--drivers/tty/serial/pmac_zilog.c2
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c2
-rw-r--r--drivers/tty/serial/rda-uart.c2
-rw-r--r--drivers/tty/serial/sa1100.c2
-rw-r--r--drivers/tty/serial/samsung_tty.c15
-rw-r--r--drivers/tty/serial/sc16is7xx.c2
-rw-r--r--drivers/tty/serial/sccnxp.c2
-rw-r--r--drivers/tty/serial/serial-tegra.c2
-rw-r--r--drivers/tty/serial/serial_txx9.c2
-rw-r--r--drivers/tty/serial/sh-sci.c2
-rw-r--r--drivers/tty/serial/sifive.c2
-rw-r--r--drivers/tty/serial/sprd_serial.c43
-rw-r--r--drivers/tty/serial/st-asc.c2
-rw-r--r--drivers/tty/serial/stm32-usart.c2
-rw-r--r--drivers/tty/serial/sunhv.c2
-rw-r--r--drivers/tty/serial/sunplus-uart.c2
-rw-r--r--drivers/tty/serial/sunsab.c2
-rw-r--r--drivers/tty/serial/sunsu.c2
-rw-r--r--drivers/tty/serial/sunzilog.c2
-rw-r--r--drivers/tty/serial/tegra-tcu.c2
-rw-r--r--drivers/tty/serial/timbuart.c2
-rw-r--r--drivers/tty/serial/uartlite.c2
-rw-r--r--drivers/tty/serial/ucc_uart.c2
-rw-r--r--drivers/tty/serial/xilinx_uartps.c2
-rw-r--r--drivers/tty/tty_io.c2
-rw-r--r--drivers/uio/uio_dmem_genirq.c5
-rw-r--r--drivers/uio/uio_hv_generic.c2
-rw-r--r--drivers/uio/uio_pdrv_genirq.c5
-rw-r--r--drivers/usb/atm/ueagle-atm.c6
-rw-r--r--drivers/usb/atm/usbatm.c2
-rw-r--r--drivers/usb/c67x00/c67x00-drv.c2
-rw-r--r--drivers/usb/cdns3/cdns3-imx.c2
-rw-r--r--drivers/usb/cdns3/cdns3-pci-wrap.c4
-rw-r--r--drivers/usb/cdns3/cdns3-plat.c2
-rw-r--r--drivers/usb/cdns3/cdns3-starfive.c2
-rw-r--r--drivers/usb/cdns3/cdns3-ti.c2
-rw-r--r--drivers/usb/cdns3/cdnsp-pci.c26
-rw-r--r--drivers/usb/chipidea/ci.h2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c3
-rw-r--r--drivers/usb/chipidea/ci_hdrc_msm.c2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_npcm.c2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_tegra.c2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_usb2.c2
-rw-r--r--drivers/usb/chipidea/core.c6
-rw-r--r--drivers/usb/chipidea/udc.c178
-rw-r--r--drivers/usb/chipidea/udc.h2
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c4
-rw-r--r--drivers/usb/common/common.c3
-rw-r--r--drivers/usb/common/usb-conn-gpio.c2
-rw-r--r--drivers/usb/core/config.c2
-rw-r--r--drivers/usb/core/devio.c5
-rw-r--r--drivers/usb/core/driver.c24
-rw-r--r--drivers/usb/core/endpoint.c11
-rw-r--r--drivers/usb/core/ledtrig-usbport.c3
-rw-r--r--drivers/usb/core/port.c11
-rw-r--r--drivers/usb/core/sysfs.c2
-rw-r--r--drivers/usb/core/usb.h2
-rw-r--r--drivers/usb/dwc2/Kconfig2
-rw-r--r--drivers/usb/dwc2/platform.c2
-rw-r--r--drivers/usb/dwc3/Kconfig2
-rw-r--r--drivers/usb/dwc3/core.c16
-rw-r--r--drivers/usb/dwc3/core.h14
-rw-r--r--drivers/usb/dwc3/dwc3-am62.c2
-rw-r--r--drivers/usb/dwc3/dwc3-exynos.c2
-rw-r--r--drivers/usb/dwc3/dwc3-imx8mp.c2
-rw-r--r--drivers/usb/dwc3/dwc3-keystone.c2
-rw-r--r--drivers/usb/dwc3/dwc3-meson-g12a.c2
-rw-r--r--drivers/usb/dwc3/dwc3-octeon.c2
-rw-r--r--drivers/usb/dwc3/dwc3-of-simple.c2
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c4
-rw-r--r--drivers/usb/dwc3/dwc3-qcom.c4
-rw-r--r--drivers/usb/dwc3/dwc3-rtk.c2
-rw-r--r--drivers/usb/dwc3/dwc3-st.c2
-rw-r--r--drivers/usb/dwc3/dwc3-xilinx.c2
-rw-r--r--drivers/usb/dwc3/ep0.c4
-rw-r--r--drivers/usb/dwc3/gadget.c152
-rw-r--r--drivers/usb/dwc3/host.c2
-rw-r--r--drivers/usb/fotg210/fotg210-core.c2
-rw-r--r--drivers/usb/gadget/composite.c30
-rw-r--r--drivers/usb/gadget/config.c4
-rw-r--r--drivers/usb/gadget/configfs.c2
-rw-r--r--drivers/usb/gadget/function/Makefile4
-rw-r--r--drivers/usb/gadget/function/f_fs.c6
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c8
-rw-r--r--drivers/usb/gadget/function/f_midi.c8
-rw-r--r--drivers/usb/gadget/function/f_midi2.c4
-rw-r--r--drivers/usb/gadget/function/f_uvc.c4
-rw-r--r--drivers/usb/gadget/function/uvc.h13
-rw-r--r--drivers/usb/gadget/function/uvc_configfs.c348
-rw-r--r--drivers/usb/gadget/function/uvc_configfs.h16
-rw-r--r--drivers/usb/gadget/function/uvc_queue.c26
-rw-r--r--drivers/usb/gadget/function/uvc_queue.h2
-rw-r--r--drivers/usb/gadget/function/uvc_trace.c11
-rw-r--r--drivers/usb/gadget/function/uvc_trace.h60
-rw-r--r--drivers/usb/gadget/function/uvc_v4l2.c66
-rw-r--r--drivers/usb/gadget/function/uvc_video.c268
-rw-r--r--drivers/usb/gadget/legacy/hid.c2
-rw-r--r--drivers/usb/gadget/legacy/raw_gadget.c4
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/core.c2
-rw-r--r--drivers/usb/gadget/udc/aspeed_udc.c4
-rw-r--r--drivers/usb/gadget/udc/at91_udc.c2
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.c2
-rw-r--r--drivers/usb/gadget/udc/bcm63xx_udc.c2
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_core.c2
-rw-r--r--drivers/usb/gadget/udc/cdns2/cdns2-pci.c3
-rw-r--r--drivers/usb/gadget/udc/dummy_hcd.c6
-rw-r--r--drivers/usb/gadget/udc/fsl_qe_udc.c8
-rw-r--r--drivers/usb/gadget/udc/fsl_udc_core.c2
-rw-r--r--drivers/usb/gadget/udc/fusb300_udc.c4
-rw-r--r--drivers/usb/gadget/udc/gr_udc.c2
-rw-r--r--drivers/usb/gadget/udc/lpc32xx_udc.c2
-rw-r--r--drivers/usb/gadget/udc/m66592-udc.c2
-rw-r--r--drivers/usb/gadget/udc/mv_u3d_core.c2
-rw-r--r--drivers/usb/gadget/udc/mv_udc_core.c2
-rw-r--r--drivers/usb/gadget/udc/net2272.c4
-rw-r--r--drivers/usb/gadget/udc/omap_udc.c6
-rw-r--r--drivers/usb/gadget/udc/pxa25x_udc.c2
-rw-r--r--drivers/usb/gadget/udc/pxa27x_udc.c2
-rw-r--r--drivers/usb/gadget/udc/r8a66597-udc.c2
-rw-r--r--drivers/usb/gadget/udc/renesas_usb3.c2
-rw-r--r--drivers/usb/gadget/udc/renesas_usbf.c4
-rw-r--r--drivers/usb/gadget/udc/rzv2m_usb3drd.c2
-rw-r--r--drivers/usb/gadget/udc/snps_udc_core.c2
-rw-r--r--drivers/usb/gadget/udc/snps_udc_plat.c2
-rw-r--r--drivers/usb/gadget/udc/tegra-xudc.c2
-rw-r--r--drivers/usb/gadget/udc/udc-xilinx.c2
-rw-r--r--drivers/usb/gadget/usbstring.c2
-rw-r--r--drivers/usb/host/bcma-hcd.c1
-rw-r--r--drivers/usb/host/ehci-atmel.c2
-rw-r--r--drivers/usb/host/ehci-brcm.c2
-rw-r--r--drivers/usb/host/ehci-exynos.c2
-rw-r--r--drivers/usb/host/ehci-fsl.c2
-rw-r--r--drivers/usb/host/ehci-grlib.c2
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-mv.c2
-rw-r--r--drivers/usb/host/ehci-npcm7xx.c2
-rw-r--r--drivers/usb/host/ehci-omap.c2
-rw-r--r--drivers/usb/host/ehci-orion.c2
-rw-r--r--drivers/usb/host/ehci-platform.c2
-rw-r--r--drivers/usb/host/ehci-ppc-of.c2
-rw-r--r--drivers/usb/host/ehci-sh.c2
-rw-r--r--drivers/usb/host/ehci-spear.c9
-rw-r--r--drivers/usb/host/ehci-st.c2
-rw-r--r--drivers/usb/host/ehci-xilinx-of.c2
-rw-r--r--drivers/usb/host/fhci-hcd.c2
-rw-r--r--drivers/usb/host/fhci-sched.c4
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c2
-rw-r--r--drivers/usb/host/isp116x-hcd.c2
-rw-r--r--drivers/usb/host/isp1362-hcd.c2
-rw-r--r--drivers/usb/host/octeon-hcd.c6
-rw-r--r--drivers/usb/host/ohci-at91.c2
-rw-r--r--drivers/usb/host/ohci-da8xx.c2
-rw-r--r--drivers/usb/host/ohci-exynos.c2
-rw-r--r--drivers/usb/host/ohci-nxp.c2
-rw-r--r--drivers/usb/host/ohci-omap.c4
-rw-r--r--drivers/usb/host/ohci-platform.c2
-rw-r--r--drivers/usb/host/ohci-ppc-of.c2
-rw-r--r--drivers/usb/host/ohci-pxa27x.c2
-rw-r--r--drivers/usb/host/ohci-s3c2410.c2
-rw-r--r--drivers/usb/host/ohci-sm501.c2
-rw-r--r--drivers/usb/host/ohci-spear.c2
-rw-r--r--drivers/usb/host/ohci-st.c2
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c8
-rw-r--r--drivers/usb/host/r8a66597-hcd.c6
-rw-r--r--drivers/usb/host/sl811-hcd.c2
-rw-r--r--drivers/usb/host/uhci-grlib.c2
-rw-r--r--drivers/usb/host/uhci-platform.c2
-rw-r--r--drivers/usb/host/xhci-dbgcap.c13
-rw-r--r--drivers/usb/host/xhci-debugfs.c10
-rw-r--r--drivers/usb/host/xhci-histb.c2
-rw-r--r--drivers/usb/host/xhci-hub.c6
-rw-r--r--drivers/usb/host/xhci-mem.c235
-rw-r--r--drivers/usb/host/xhci-mtk.c2
-rw-r--r--drivers/usb/host/xhci-pci.c45
-rw-r--r--drivers/usb/host/xhci-plat.c2
-rw-r--r--drivers/usb/host/xhci-rcar.c2
-rw-r--r--drivers/usb/host/xhci-ring.c302
-rw-r--r--drivers/usb/host/xhci-tegra.c2
-rw-r--r--drivers/usb/host/xhci-trace.h79
-rw-r--r--drivers/usb/host/xhci.c123
-rw-r--r--drivers/usb/host/xhci.h51
-rw-r--r--drivers/usb/isp1760/Kconfig2
-rw-r--r--drivers/usb/isp1760/isp1760-if.c2
-rw-r--r--drivers/usb/misc/chaoskey.c35
-rw-r--r--drivers/usb/misc/iowarrior.c50
-rw-r--r--drivers/usb/misc/onboard_usb_dev.c2
-rw-r--r--drivers/usb/misc/qcom_eud.c2
-rw-r--r--drivers/usb/misc/usb-ljca.c20
-rw-r--r--drivers/usb/misc/usb3503.c2
-rw-r--r--drivers/usb/misc/usbtest.c3
-rw-r--r--drivers/usb/misc/yurex.c5
-rw-r--r--drivers/usb/mon/mon_bin.c2
-rw-r--r--drivers/usb/mtu3/Kconfig2
-rw-r--r--drivers/usb/mtu3/mtu3_plat.c4
-rw-r--r--drivers/usb/musb/Kconfig2
-rw-r--r--drivers/usb/musb/da8xx.c2
-rw-r--r--drivers/usb/musb/jz4740.c2
-rw-r--r--drivers/usb/musb/mediatek.c2
-rw-r--r--drivers/usb/musb/mpfs.c2
-rw-r--r--drivers/usb/musb/musb_core.c4
-rw-r--r--drivers/usb/musb/musb_dsps.c2
-rw-r--r--drivers/usb/musb/musb_gadget.c13
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c2
-rw-r--r--drivers/usb/musb/musb_host.c5
-rw-r--r--drivers/usb/musb/omap2430.c2
-rw-r--r--drivers/usb/musb/sunxi.c2
-rw-r--r--drivers/usb/musb/tusb6010.c2
-rw-r--r--drivers/usb/musb/ux500.c2
-rw-r--r--drivers/usb/phy/phy-ab8500-usb.c2
-rw-r--r--drivers/usb/phy/phy-am335x.c2
-rw-r--r--drivers/usb/phy/phy-fsl-usb.c2
-rw-r--r--drivers/usb/phy/phy-generic.c2
-rw-r--r--drivers/usb/phy/phy-gpio-vbus-usb.c2
-rw-r--r--drivers/usb/phy/phy-isp1301.c2
-rw-r--r--drivers/usb/phy/phy-keystone.c2
-rw-r--r--drivers/usb/phy/phy-mv-usb.c2
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c2
-rw-r--r--drivers/usb/phy/phy-tahvo.c2
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c2
-rw-r--r--drivers/usb/phy/phy-twl6030-usb.c2
-rw-r--r--drivers/usb/phy/phy.c2
-rw-r--r--drivers/usb/renesas_usbhs/common.c4
-rw-r--r--drivers/usb/roles/intel-xhci-usb-role-switch.c2
-rw-r--r--drivers/usb/serial/bus.c4
-rw-r--r--drivers/usb/serial/ftdi_sio.c2
-rw-r--r--drivers/usb/serial/io_edgeport.c2
-rw-r--r--drivers/usb/serial/pl2303.c38
-rw-r--r--drivers/usb/serial/sierra.c2
-rw-r--r--drivers/usb/serial/usb-serial.c4
-rw-r--r--drivers/usb/storage/ene_ub6250.c8
-rw-r--r--drivers/usb/storage/realtek_cr.c4
-rw-r--r--drivers/usb/storage/sddr09.c4
-rw-r--r--drivers/usb/storage/sddr55.c8
-rw-r--r--drivers/usb/storage/transport.c2
-rw-r--r--drivers/usb/typec/altmodes/displayport.c2
-rw-r--r--drivers/usb/typec/class.c205
-rw-r--r--drivers/usb/typec/class.h3
-rw-r--r--drivers/usb/typec/mux/Kconfig9
-rw-r--r--drivers/usb/typec/mux/Makefile1
-rw-r--r--drivers/usb/typec/mux/gpio-sbu-mux.c2
-rw-r--r--drivers/usb/typec/mux/intel_pmc_mux.c2
-rw-r--r--drivers/usb/typec/mux/tusb1046.c196
-rw-r--r--drivers/usb/typec/stusb160x.c7
-rw-r--r--drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpci_mt6360.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpci_mt6370.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpm.c96
-rw-r--r--drivers/usb/typec/tcpm/wcove.c2
-rw-r--r--drivers/usb/typec/ucsi/debugfs.c1
-rw-r--r--drivers/usb/typec/ucsi/psy.c28
-rw-r--r--drivers/usb/typec/ucsi/trace.h28
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c153
-rw-r--r--drivers/usb/typec/ucsi/ucsi.h241
-rw-r--r--drivers/usb/typec/ucsi/ucsi_acpi.c65
-rw-r--r--drivers/usb/typec/ucsi/ucsi_ccg.c5
-rw-r--r--drivers/usb/typec/ucsi/ucsi_glink.c21
-rw-r--r--drivers/usb/usbip/vhci_hcd.c2
-rw-r--r--drivers/usb/usbip/vudc_main.c2
-rw-r--r--drivers/vdpa/mlx5/core/mr.c4
-rw-r--r--drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c266
-rw-r--r--drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h19
-rw-r--r--drivers/vfio/pci/mlx5/cmd.c6
-rw-r--r--drivers/vfio/pci/mlx5/main.c35
-rw-r--r--drivers/vfio/pci/nvgrace-gpu/main.c2
-rw-r--r--drivers/vfio/pci/qat/main.c2
-rw-r--r--drivers/vfio/pci/vfio_pci_config.c16
-rw-r--r--drivers/vfio/pci/virtio/Kconfig42
-rw-r--r--drivers/vfio/pci/virtio/Makefile3
-rw-r--r--drivers/vfio/pci/virtio/common.h127
-rw-r--r--drivers/vfio/pci/virtio/legacy_io.c418
-rw-r--r--drivers/vfio/pci/virtio/main.c476
-rw-r--r--drivers/vfio/pci/virtio/migrate.c1337
-rw-r--r--drivers/virtio/virtio_pci_common.h19
-rw-r--r--drivers/virtio/virtio_pci_modern.c457
-rw-r--r--drivers/virtio/virtio_ring.c225
-rw-r--r--drivers/virtio/virtio_vdpa.c3
1552 files changed, 63287 insertions, 87141 deletions
diff --git a/drivers/accessibility/speakup/Makefile b/drivers/accessibility/speakup/Makefile
index 6f6a83565c0d..14ba1cca87f4 100644
--- a/drivers/accessibility/speakup/Makefile
+++ b/drivers/accessibility/speakup/Makefile
@@ -40,9 +40,7 @@ hostprogs += makemapdata
makemapdata-objs := makemapdata.o
quiet_cmd_mkmap = MKMAP $@
- cmd_mkmap = TOPDIR=$(srctree) \
- SPKDIR=$(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD),$(srctree)/drivers/accessibility/speakup) \
- $(obj)/makemapdata > $@
+ cmd_mkmap = TOPDIR=$(srctree) SPKDIR=$(src) $(obj)/makemapdata > $@
$(obj)/mapdata.h: $(obj)/makemapdata
$(call cmd,mkmap)
diff --git a/drivers/acpi/arm64/init.c b/drivers/acpi/arm64/init.c
index d0c8aed90fd1..7a47d8095a7d 100644
--- a/drivers/acpi/arm64/init.c
+++ b/drivers/acpi/arm64/init.c
@@ -2,7 +2,7 @@
#include <linux/acpi.h>
#include "init.h"
-void __init acpi_arm_init(void)
+void __init acpi_arch_init(void)
{
if (IS_ENABLED(CONFIG_ACPI_AGDI))
acpi_agdi_init();
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index aed4a37da03e..3d5342f8d7b3 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -853,6 +853,7 @@ static int sysfs_add_battery(struct acpi_battery *battery)
struct power_supply_config psy_cfg = {
.drv_data = battery,
.attr_grp = acpi_battery_groups,
+ .no_wakeup_source = true,
};
bool full_cap_broken = false;
@@ -888,7 +889,7 @@ static int sysfs_add_battery(struct acpi_battery *battery)
battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
battery->bat_desc.get_property = acpi_battery_get_property;
- battery->bat = power_supply_register_no_ws(&battery->device->dev,
+ battery->bat = power_supply_register(&battery->device->dev,
&battery->bat_desc, &psy_cfg);
if (IS_ERR(battery->bat)) {
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 16917dc3ad60..058910af82bc 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -1434,6 +1434,8 @@ static int __init acpi_bus_init(void)
struct kobject *acpi_kobj;
EXPORT_SYMBOL_GPL(acpi_kobj);
+void __weak __init acpi_arch_init(void) { }
+
static int __init acpi_init(void)
{
int result;
@@ -1461,8 +1463,7 @@ static int __init acpi_init(void)
acpi_viot_early_init();
acpi_hest_init();
acpi_ghes_init();
- acpi_arm_init();
- acpi_riscv_init();
+ acpi_arch_init();
acpi_scan_init();
acpi_ec_init();
acpi_debugfs_init();
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index ce728cf7e301..698897b29de2 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -800,12 +800,12 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr)
state->enter = acpi_idle_enter;
state->flags = 0;
- if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2 ||
- cx->type == ACPI_STATE_C3) {
- state->enter_dead = acpi_idle_play_dead;
- if (cx->type != ACPI_STATE_C3)
- drv->safe_state_index = count;
- }
+
+ state->enter_dead = acpi_idle_play_dead;
+
+ if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2)
+ drv->safe_state_index = count;
+
/*
* Halt-induced C1 is not good for ->enter_s2idle, because it
* re-enables interrupts on exit. Moreover, C1 is generally not
diff --git a/drivers/acpi/riscv/init.c b/drivers/acpi/riscv/init.c
index 5ef97905a727..673e4d5dd752 100644
--- a/drivers/acpi/riscv/init.c
+++ b/drivers/acpi/riscv/init.c
@@ -7,7 +7,7 @@
#include <linux/acpi.h>
#include "init.h"
-void __init acpi_riscv_init(void)
+void __init acpi_arch_init(void)
{
riscv_acpi_init_gsi_mapping();
}
diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
index 423565c31d5e..cb45ef5240da 100644
--- a/drivers/acpi/x86/utils.c
+++ b/drivers/acpi/x86/utils.c
@@ -296,6 +296,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
/*
* 2. Devices which also have the skip i2c/serdev quirks and which
* need the x86-android-tablets module to properly work.
+ * Sorted alphabetically.
*/
#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
{
@@ -309,6 +310,19 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
},
{
+ /* Acer Iconia One 8 A1-840 (non FHD version) */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
+ /* Above strings are too generic also match BIOS date */
+ DMI_MATCH(DMI_BIOS_DATE, "04/01/2014"),
+ },
+ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
+ ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
+ },
+ {
+ /* Asus ME176C tablet */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
@@ -319,23 +333,24 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
},
{
- /* Lenovo Yoga Book X90F/L */
+ /* Asus TF103C transformer 2-in-1 */
.matches = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
- DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
},
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
- ACPI_QUIRK_UART1_SKIP |
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
},
{
+ /* Lenovo Yoga Book X90F/L */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
},
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+ ACPI_QUIRK_UART1_SKIP |
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
},
@@ -425,6 +440,7 @@ static const struct acpi_device_id i2c_acpi_known_good_ids[] = {
{ "10EC5640", 0 }, /* RealTek ALC5640 audio codec */
{ "10EC5651", 0 }, /* RealTek ALC5651 audio codec */
{ "INT33F4", 0 }, /* X-Powers AXP288 PMIC */
+ { "INT33F5", 0 }, /* TI Dollar Cove PMIC */
{ "INT33FD", 0 }, /* Intel Crystal Cove PMIC */
{ "INT34D3", 0 }, /* Intel Whiskey Cove PMIC */
{ "NPCE69A", 0 }, /* Asus Transformer keyboard dock */
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 0230c43377c1..8ef259b4d037 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -449,6 +449,12 @@ const struct bus_type amba_bustype = {
};
EXPORT_SYMBOL_GPL(amba_bustype);
+bool dev_is_amba(const struct device *dev)
+{
+ return dev->bus == &amba_bustype;
+}
+EXPORT_SYMBOL_GPL(dev_is_amba);
+
static int __init amba_init(void)
{
return bus_register(&amba_bustype);
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 978740537a1a..ef353ca13c35 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1225,6 +1225,12 @@ static void binder_cleanup_ref_olocked(struct binder_ref *ref)
binder_dequeue_work(ref->proc, &ref->death->work);
binder_stats_deleted(BINDER_STAT_DEATH);
}
+
+ if (ref->freeze) {
+ binder_dequeue_work(ref->proc, &ref->freeze->work);
+ binder_stats_deleted(BINDER_STAT_FREEZE);
+ }
+
binder_stats_deleted(BINDER_STAT_REF);
}
@@ -3850,7 +3856,6 @@ binder_request_freeze_notification(struct binder_proc *proc,
{
struct binder_ref_freeze *freeze;
struct binder_ref *ref;
- bool is_frozen;
freeze = kzalloc(sizeof(*freeze), GFP_KERNEL);
if (!freeze)
@@ -3866,32 +3871,31 @@ binder_request_freeze_notification(struct binder_proc *proc,
}
binder_node_lock(ref->node);
-
- if (ref->freeze || !ref->node->proc) {
- binder_user_error("%d:%d invalid BC_REQUEST_FREEZE_NOTIFICATION %s\n",
- proc->pid, thread->pid,
- ref->freeze ? "already set" : "dead node");
+ if (ref->freeze) {
+ binder_user_error("%d:%d BC_REQUEST_FREEZE_NOTIFICATION already set\n",
+ proc->pid, thread->pid);
binder_node_unlock(ref->node);
binder_proc_unlock(proc);
kfree(freeze);
return -EINVAL;
}
- binder_inner_proc_lock(ref->node->proc);
- is_frozen = ref->node->proc->is_frozen;
- binder_inner_proc_unlock(ref->node->proc);
binder_stats_created(BINDER_STAT_FREEZE);
INIT_LIST_HEAD(&freeze->work.entry);
freeze->cookie = handle_cookie->cookie;
freeze->work.type = BINDER_WORK_FROZEN_BINDER;
- freeze->is_frozen = is_frozen;
-
ref->freeze = freeze;
- binder_inner_proc_lock(proc);
- binder_enqueue_work_ilocked(&ref->freeze->work, &proc->todo);
- binder_wakeup_proc_ilocked(proc);
- binder_inner_proc_unlock(proc);
+ if (ref->node->proc) {
+ binder_inner_proc_lock(ref->node->proc);
+ freeze->is_frozen = ref->node->proc->is_frozen;
+ binder_inner_proc_unlock(ref->node->proc);
+
+ binder_inner_proc_lock(proc);
+ binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
+ binder_wakeup_proc_ilocked(proc);
+ binder_inner_proc_unlock(proc);
+ }
binder_node_unlock(ref->node);
binder_proc_unlock(proc);
@@ -5151,6 +5155,16 @@ static void binder_release_work(struct binder_proc *proc,
} break;
case BINDER_WORK_NODE:
break;
+ case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION: {
+ struct binder_ref_freeze *freeze;
+
+ freeze = container_of(w, struct binder_ref_freeze, work);
+ binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+ "undelivered freeze notification, %016llx\n",
+ (u64)freeze->cookie);
+ kfree(freeze);
+ binder_stats_deleted(BINDER_STAT_FREEZE);
+ } break;
default:
pr_err("unexpected work type, %d, not freed\n",
wtype);
@@ -5552,6 +5566,7 @@ static bool binder_txns_pending_ilocked(struct binder_proc *proc)
static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
{
+ struct binder_node *prev = NULL;
struct rb_node *n;
struct binder_ref *ref;
@@ -5560,7 +5575,10 @@ static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
struct binder_node *node;
node = rb_entry(n, struct binder_node, rb_node);
+ binder_inc_node_tmpref_ilocked(node);
binder_inner_proc_unlock(proc);
+ if (prev)
+ binder_put_node(prev);
binder_node_lock(node);
hlist_for_each_entry(ref, &node->refs, node_entry) {
/*
@@ -5586,10 +5604,15 @@ static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
}
binder_inner_proc_unlock(ref->proc);
}
+ prev = node;
binder_node_unlock(node);
binder_inner_proc_lock(proc);
+ if (proc->is_dead)
+ break;
}
binder_inner_proc_unlock(proc);
+ if (prev)
+ binder_put_node(prev);
}
static int binder_ioctl_freeze(struct binder_freeze_info *info,
@@ -6260,6 +6283,7 @@ static void binder_deferred_release(struct binder_proc *proc)
binder_release_work(proc, &proc->todo);
binder_release_work(proc, &proc->delivered_death);
+ binder_release_work(proc, &proc->delivered_freeze);
binder_debug(BINDER_DEBUG_OPEN_CLOSE,
"%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d\n",
@@ -6393,6 +6417,12 @@ static void print_binder_work_ilocked(struct seq_file *m,
case BINDER_WORK_CLEAR_DEATH_NOTIFICATION:
seq_printf(m, "%shas cleared death notification\n", prefix);
break;
+ case BINDER_WORK_FROZEN_BINDER:
+ seq_printf(m, "%shas frozen binder\n", prefix);
+ break;
+ case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION:
+ seq_printf(m, "%shas cleared freeze notification\n", prefix);
+ break;
default:
seq_printf(m, "%sunknown work: type %d\n", prefix, w->type);
break;
@@ -6539,6 +6569,10 @@ static void print_binder_proc(struct seq_file *m,
seq_puts(m, " has delivered dead binder\n");
break;
}
+ list_for_each_entry(w, &proc->delivered_freeze, entry) {
+ seq_puts(m, " has delivered freeze binder\n");
+ break;
+ }
binder_inner_proc_unlock(proc);
if (!print_all && m->count == header_pos)
m->count = start_pos;
diff --git a/drivers/base/auxiliary.c b/drivers/base/auxiliary.c
index 7823888af4f6..afa4df4c5a3f 100644
--- a/drivers/base/auxiliary.c
+++ b/drivers/base/auxiliary.c
@@ -92,7 +92,7 @@
* Auxiliary devices are created and registered by a subsystem-level core
* device that needs to break up its functionality into smaller fragments. One
* way to extend the scope of an auxiliary_device is to encapsulate it within a
- * domain- pecific structure defined by the parent device. This structure
+ * domain-specific structure defined by the parent device. This structure
* contains the auxiliary_device and any associated shared data/callbacks
* needed to establish the connection with the parent.
*
@@ -336,35 +336,6 @@ int __auxiliary_device_add(struct auxiliary_device *auxdev, const char *modname)
EXPORT_SYMBOL_GPL(__auxiliary_device_add);
/**
- * auxiliary_find_device - auxiliary device iterator for locating a particular device.
- * @start: Device to begin with
- * @data: Data to pass to match function
- * @match: Callback function to check device
- *
- * This function returns a reference to a device that is 'found'
- * for later use, as determined by the @match callback.
- *
- * The reference returned should be released with put_device().
- *
- * The callback should return 0 if the device doesn't match and non-zero
- * if it does. If the callback returns non-zero, this function will
- * return to the caller and not iterate over any more devices.
- */
-struct auxiliary_device *auxiliary_find_device(struct device *start,
- const void *data,
- device_match_t match)
-{
- struct device *dev;
-
- dev = bus_find_device(&auxiliary_bus_type, start, data, match);
- if (!dev)
- return NULL;
-
- return to_auxiliary_dev(dev);
-}
-EXPORT_SYMBOL_GPL(auxiliary_find_device);
-
-/**
* __auxiliary_driver_register - register a driver for auxiliary bus devices
* @auxdrv: auxiliary_driver structure
* @owner: owning module/driver
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index 7a7609298e18..609935ad5091 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -254,11 +254,11 @@ static int of_count_cache_leaves(struct device_node *np)
{
unsigned int leaves = 0;
- if (of_property_read_bool(np, "cache-size"))
+ if (of_property_present(np, "cache-size"))
++leaves;
- if (of_property_read_bool(np, "i-cache-size"))
+ if (of_property_present(np, "i-cache-size"))
++leaves;
- if (of_property_read_bool(np, "d-cache-size"))
+ if (of_property_present(np, "d-cache-size"))
++leaves;
if (!leaves) {
@@ -367,9 +367,7 @@ static int cache_shared_cpu_map_setup(unsigned int cpu)
cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map);
for_each_online_cpu(i) {
- struct cpu_cacheinfo *sib_cpu_ci = get_cpu_cacheinfo(i);
-
- if (i == cpu || !sib_cpu_ci->info_list)
+ if (i == cpu || !per_cpu_cacheinfo(i))
continue;/* skip if itself or no cacheinfo */
for (sib_index = 0; sib_index < cache_leaves(i); sib_index++) {
sib_leaf = per_cpu_cacheinfo_idx(i, sib_index);
@@ -409,10 +407,7 @@ static void cache_shared_cpu_map_remove(unsigned int cpu)
for (index = 0; index < cache_leaves(cpu); index++) {
this_leaf = per_cpu_cacheinfo_idx(cpu, index);
for_each_cpu(sibling, &this_leaf->shared_cpu_map) {
- struct cpu_cacheinfo *sib_cpu_ci =
- get_cpu_cacheinfo(sibling);
-
- if (sibling == cpu || !sib_cpu_ci->info_list)
+ if (sibling == cpu || !per_cpu_cacheinfo(sibling))
continue;/* skip if itself or no cacheinfo */
for (sib_index = 0; sib_index < cache_leaves(sibling); sib_index++) {
diff --git a/drivers/base/class.c b/drivers/base/class.c
index cb5359235c70..582b5a02a5c4 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -405,7 +405,7 @@ int class_for_each_device(const struct class *class, const struct device *start,
if (!class)
return -EINVAL;
if (!sp) {
- WARN(1, "%s called for class '%s' before it was initialized",
+ WARN(1, "%s called for class '%s' before it was registered",
__func__, class->name);
return -EINVAL;
}
@@ -453,7 +453,7 @@ struct device *class_find_device(const struct class *class, const struct device
if (!class)
return NULL;
if (!sp) {
- WARN(1, "%s called for class '%s' before it was initialized",
+ WARN(1, "%s called for class '%s' before it was registered",
__func__, class->name);
return NULL;
}
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 529af59e25ff..94865c9d8adc 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -552,7 +552,7 @@ void device_link_wait_removal(void)
}
EXPORT_SYMBOL_GPL(device_link_wait_removal);
-static struct class devlink_class = {
+static const struct class devlink_class = {
.name = "devlink",
.dev_groups = devlink_groups,
.dev_release = devlink_dev_release,
@@ -1971,7 +1971,7 @@ static struct device *fwnode_get_next_parent_dev(const struct fwnode_handle *fwn
/**
* __fw_devlink_relax_cycles - Relax and mark dependency cycles.
- * @con: Potential consumer device.
+ * @con_handle: Potential consumer device fwnode.
* @sup_handle: Potential supplier's fwnode.
*
* Needs to be called with fwnode_lock and device link lock held.
@@ -1989,10 +1989,10 @@ static struct device *fwnode_get_next_parent_dev(const struct fwnode_handle *fwn
*
* Return true if one or more cycles were found. Otherwise, return false.
*/
-static bool __fw_devlink_relax_cycles(struct device *con,
+static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle,
struct fwnode_handle *sup_handle)
{
- struct device *sup_dev = NULL, *par_dev = NULL;
+ struct device *sup_dev = NULL, *par_dev = NULL, *con_dev = NULL;
struct fwnode_link *link;
struct device_link *dev_link;
bool ret = false;
@@ -2009,22 +2009,22 @@ static bool __fw_devlink_relax_cycles(struct device *con,
sup_handle->flags |= FWNODE_FLAG_VISITED;
- sup_dev = get_dev_from_fwnode(sup_handle);
-
/* Termination condition. */
- if (sup_dev == con) {
+ if (sup_handle == con_handle) {
pr_debug("----- cycle: start -----\n");
ret = true;
goto out;
}
+ sup_dev = get_dev_from_fwnode(sup_handle);
+ con_dev = get_dev_from_fwnode(con_handle);
/*
* If sup_dev is bound to a driver and @con hasn't started binding to a
* driver, sup_dev can't be a consumer of @con. So, no need to check
* further.
*/
if (sup_dev && sup_dev->links.status == DL_DEV_DRIVER_BOUND &&
- con->links.status == DL_DEV_NO_DRIVER) {
+ con_dev && con_dev->links.status == DL_DEV_NO_DRIVER) {
ret = false;
goto out;
}
@@ -2033,7 +2033,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
if (link->flags & FWLINK_FLAG_IGNORE)
continue;
- if (__fw_devlink_relax_cycles(con, link->supplier)) {
+ if (__fw_devlink_relax_cycles(con_handle, link->supplier)) {
__fwnode_link_cycle(link);
ret = true;
}
@@ -2048,7 +2048,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
else
par_dev = fwnode_get_next_parent_dev(sup_handle);
- if (par_dev && __fw_devlink_relax_cycles(con, par_dev->fwnode)) {
+ if (par_dev && __fw_devlink_relax_cycles(con_handle, par_dev->fwnode)) {
pr_debug("%pfwf: cycle: child of %pfwf\n", sup_handle,
par_dev->fwnode);
ret = true;
@@ -2066,7 +2066,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
!(dev_link->flags & DL_FLAG_CYCLE))
continue;
- if (__fw_devlink_relax_cycles(con,
+ if (__fw_devlink_relax_cycles(con_handle,
dev_link->supplier->fwnode)) {
pr_debug("%pfwf: cycle: depends on %pfwf\n", sup_handle,
dev_link->supplier->fwnode);
@@ -2114,11 +2114,6 @@ static int fw_devlink_create_devlink(struct device *con,
if (link->flags & FWLINK_FLAG_IGNORE)
return 0;
- if (con->fwnode == link->consumer)
- flags = fw_devlink_get_flags(link->flags);
- else
- flags = FW_DEVLINK_FLAGS_PERMISSIVE;
-
/*
* In some cases, a device P might also be a supplier to its child node
* C. However, this would defer the probe of C until the probe of P
@@ -2139,25 +2134,23 @@ static int fw_devlink_create_devlink(struct device *con,
return -EINVAL;
/*
- * SYNC_STATE_ONLY device links don't block probing and supports cycles.
- * So, one might expect that cycle detection isn't necessary for them.
- * However, if the device link was marked as SYNC_STATE_ONLY because
- * it's part of a cycle, then we still need to do cycle detection. This
- * is because the consumer and supplier might be part of multiple cycles
- * and we need to detect all those cycles.
+ * Don't try to optimize by not calling the cycle detection logic under
+ * certain conditions. There's always some corner case that won't get
+ * detected.
*/
- if (!device_link_flag_is_sync_state_only(flags) ||
- flags & DL_FLAG_CYCLE) {
- device_links_write_lock();
- if (__fw_devlink_relax_cycles(con, sup_handle)) {
- __fwnode_link_cycle(link);
- flags = fw_devlink_get_flags(link->flags);
- pr_debug("----- cycle: end -----\n");
- dev_info(con, "Fixed dependency cycle(s) with %pfwf\n",
- sup_handle);
- }
- device_links_write_unlock();
+ device_links_write_lock();
+ if (__fw_devlink_relax_cycles(link->consumer, sup_handle)) {
+ __fwnode_link_cycle(link);
+ pr_debug("----- cycle: end -----\n");
+ pr_info("%pfwf: Fixed dependency cycle(s) with %pfwf\n",
+ link->consumer, sup_handle);
}
+ device_links_write_unlock();
+
+ if (con->fwnode == link->consumer)
+ flags = fw_devlink_get_flags(link->flags);
+ else
+ flags = FW_DEVLINK_FLAGS_PERMISSIVE;
if (sup_handle->flags & FWNODE_FLAG_NOT_DEVICE)
sup_dev = fwnode_get_next_parent_dev(sup_handle);
@@ -2180,8 +2173,8 @@ static int fw_devlink_create_devlink(struct device *con,
}
if (con != sup_dev && !device_link_add(con, sup_dev, flags)) {
- dev_err(con, "Failed to create device link (0x%x) with %s\n",
- flags, dev_name(sup_dev));
+ dev_err(con, "Failed to create device link (0x%x) with supplier %s for %pfwf\n",
+ flags, dev_name(sup_dev), link->consumer);
ret = -EINVAL;
}
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index 324a9a3c087a..cb0912ea3e62 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -829,19 +829,18 @@ static void fw_log_firmware_info(const struct firmware *fw, const char *name, st
shash->tfm = alg;
if (crypto_shash_digest(shash, fw->data, fw->size, sha256buf) < 0)
- goto out_shash;
+ goto out_free;
for (int i = 0; i < SHA256_DIGEST_SIZE; i++)
sprintf(&outbuf[i * 2], "%02x", sha256buf[i]);
outbuf[SHA256_BLOCK_SIZE] = 0;
dev_dbg(device, "Loaded FW: %s, sha256: %s\n", name, outbuf);
-out_shash:
- crypto_free_shash(alg);
out_free:
kfree(shash);
kfree(outbuf);
kfree(sha256buf);
+ crypto_free_shash(alg);
}
#else
static void fw_log_firmware_info(const struct firmware *fw, const char *name,
@@ -1075,8 +1074,8 @@ EXPORT_SYMBOL_GPL(firmware_request_platform);
/**
* firmware_request_cache() - cache firmware for suspend so resume can use it
- * @name: name of firmware file
* @device: device for which firmware should be cached for
+ * @name: name of firmware file
*
* There are some devices with an optimization that enables the device to not
* require loading firmware on system reboot. This optimization may still
diff --git a/drivers/base/node.c b/drivers/base/node.c
index eb72580288e6..0ea653fa3433 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -27,7 +27,7 @@ static const struct bus_type node_subsys = {
};
static inline ssize_t cpumap_read(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
+ const struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
@@ -45,10 +45,10 @@ static inline ssize_t cpumap_read(struct file *file, struct kobject *kobj,
return n;
}
-static BIN_ATTR_RO(cpumap, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(cpumap, CPUMAP_FILE_MAX_BYTES);
static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
+ const struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
@@ -66,7 +66,7 @@ static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj,
return n;
}
-static BIN_ATTR_RO(cpulist, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(cpulist, CPULIST_FILE_MAX_BYTES);
/**
* struct node_access_nodes - Access class device to hold user visible
@@ -578,7 +578,7 @@ static struct attribute *node_dev_attrs[] = {
NULL
};
-static struct bin_attribute *node_dev_bin_attrs[] = {
+static const struct bin_attribute *node_dev_bin_attrs[] = {
&bin_attr_cpumap,
&bin_attr_cpulist,
NULL
@@ -586,7 +586,7 @@ static struct bin_attribute *node_dev_bin_attrs[] = {
static const struct attribute_group node_dev_group = {
.attrs = node_dev_attrs,
- .bin_attrs = node_dev_bin_attrs
+ .bin_attrs_new = node_dev_bin_attrs,
};
static const struct attribute_group *node_dev_groups[] = {
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index a1474fb67db9..f8163b559bf9 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -509,14 +509,6 @@ static ssize_t wakeup_last_time_ms_show(struct device *dev,
return sysfs_emit(buf, "%lld\n", msec);
}
-static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
- kgid_t kgid)
-{
- if (dev->power.wakeup && dev->power.wakeup->dev)
- return device_change_owner(dev->power.wakeup->dev, kuid, kgid);
- return 0;
-}
-
static DEVICE_ATTR_RO(wakeup_last_time_ms);
#ifdef CONFIG_PM_AUTOSLEEP
@@ -541,6 +533,15 @@ static ssize_t wakeup_prevent_sleep_time_ms_show(struct device *dev,
static DEVICE_ATTR_RO(wakeup_prevent_sleep_time_ms);
#endif /* CONFIG_PM_AUTOSLEEP */
+
+static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
+ kgid_t kgid)
+{
+ if (dev->power.wakeup && dev->power.wakeup->dev)
+ return device_change_owner(dev->power.wakeup->dev, kuid, kgid);
+ return 0;
+}
+
#else /* CONFIG_PM_SLEEP */
static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
kgid_t kgid)
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 89f98be5c5b9..cf160dd2c27b 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -23,7 +23,7 @@ static ssize_t name##_show(struct device *dev, \
#define define_siblings_read_func(name, mask) \
static ssize_t name##_read(struct file *file, struct kobject *kobj, \
- struct bin_attribute *attr, char *buf, \
+ const struct bin_attribute *attr, char *buf, \
loff_t off, size_t count) \
{ \
struct device *dev = kobj_to_dev(kobj); \
@@ -33,7 +33,7 @@ static ssize_t name##_read(struct file *file, struct kobject *kobj, \
} \
\
static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \
- struct bin_attribute *attr, char *buf, \
+ const struct bin_attribute *attr, char *buf, \
loff_t off, size_t count) \
{ \
struct device *dev = kobj_to_dev(kobj); \
@@ -62,50 +62,50 @@ define_id_show_func(ppin, "0x%llx");
static DEVICE_ATTR_ADMIN_RO(ppin);
define_siblings_read_func(thread_siblings, sibling_cpumask);
-static BIN_ATTR_RO(thread_siblings, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(thread_siblings_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(thread_siblings, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(thread_siblings_list, CPULIST_FILE_MAX_BYTES);
define_siblings_read_func(core_cpus, sibling_cpumask);
-static BIN_ATTR_RO(core_cpus, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(core_cpus_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(core_cpus, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(core_cpus_list, CPULIST_FILE_MAX_BYTES);
define_siblings_read_func(core_siblings, core_cpumask);
-static BIN_ATTR_RO(core_siblings, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(core_siblings_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(core_siblings, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(core_siblings_list, CPULIST_FILE_MAX_BYTES);
#ifdef TOPOLOGY_CLUSTER_SYSFS
define_siblings_read_func(cluster_cpus, cluster_cpumask);
-static BIN_ATTR_RO(cluster_cpus, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(cluster_cpus_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(cluster_cpus, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(cluster_cpus_list, CPULIST_FILE_MAX_BYTES);
#endif
#ifdef TOPOLOGY_DIE_SYSFS
define_siblings_read_func(die_cpus, die_cpumask);
-static BIN_ATTR_RO(die_cpus, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(die_cpus_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(die_cpus, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(die_cpus_list, CPULIST_FILE_MAX_BYTES);
#endif
define_siblings_read_func(package_cpus, core_cpumask);
-static BIN_ATTR_RO(package_cpus, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(package_cpus_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(package_cpus, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(package_cpus_list, CPULIST_FILE_MAX_BYTES);
#ifdef TOPOLOGY_BOOK_SYSFS
define_id_show_func(book_id, "%d");
static DEVICE_ATTR_RO(book_id);
define_siblings_read_func(book_siblings, book_cpumask);
-static BIN_ATTR_RO(book_siblings, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(book_siblings_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(book_siblings, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(book_siblings_list, CPULIST_FILE_MAX_BYTES);
#endif
#ifdef TOPOLOGY_DRAWER_SYSFS
define_id_show_func(drawer_id, "%d");
static DEVICE_ATTR_RO(drawer_id);
define_siblings_read_func(drawer_siblings, drawer_cpumask);
-static BIN_ATTR_RO(drawer_siblings, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(drawer_siblings_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(drawer_siblings, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(drawer_siblings_list, CPULIST_FILE_MAX_BYTES);
#endif
-static struct bin_attribute *bin_attrs[] = {
+static const struct bin_attribute *const bin_attrs[] = {
&bin_attr_core_cpus,
&bin_attr_core_cpus_list,
&bin_attr_thread_siblings,
@@ -163,7 +163,7 @@ static umode_t topology_is_visible(struct kobject *kobj,
static const struct attribute_group topology_attr_group = {
.attrs = default_attrs,
- .bin_attrs = bin_attrs,
+ .bin_attrs_new = bin_attrs,
.is_visible = topology_is_visible,
.name = "topology"
};
diff --git a/drivers/base/trace.h b/drivers/base/trace.h
index e52b6eae060d..3b83b13a57ff 100644
--- a/drivers/base/trace.h
+++ b/drivers/base/trace.h
@@ -24,18 +24,18 @@ DECLARE_EVENT_CLASS(devres,
__field(struct device *, dev)
__field(const char *, op)
__field(void *, node)
- __field(const char *, name)
+ __string(name, name)
__field(size_t, size)
),
TP_fast_assign(
__assign_str(devname);
__entry->op = op;
__entry->node = node;
- __entry->name = name;
+ __assign_str(name);
__entry->size = size;
),
TP_printk("%s %3s %p %s (%zu bytes)", __get_str(devname),
- __entry->op, __entry->node, __entry->name, __entry->size)
+ __entry->op, __entry->node, __get_str(name), __entry->size)
);
DEFINE_EVENT(devres, devres_log,
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 5a95671d8151..292f127cae0a 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -231,8 +231,10 @@ static void brd_do_discard(struct brd_device *brd, sector_t sector, u32 size)
xa_lock(&brd->brd_pages);
while (size >= PAGE_SIZE && aligned_sector < rd_size * 2) {
page = __xa_erase(&brd->brd_pages, aligned_sector >> PAGE_SECTORS_SHIFT);
- if (page)
+ if (page) {
__free_page(page);
+ brd->brd_nr_pages--;
+ }
aligned_sector += PAGE_SECTORS;
size -= PAGE_SIZE;
}
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index fe9bb4fb5f1b..8f6761c27c68 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -770,12 +770,11 @@ static void loop_sysfs_exit(struct loop_device *lo)
&loop_attribute_group);
}
-static void loop_config_discard(struct loop_device *lo,
- struct queue_limits *lim)
+static void loop_get_discard_config(struct loop_device *lo,
+ u32 *granularity, u32 *max_discard_sectors)
{
struct file *file = lo->lo_backing_file;
struct inode *inode = file->f_mapping->host;
- u32 granularity = 0, max_discard_sectors = 0;
struct kstatfs sbuf;
/*
@@ -788,24 +787,17 @@ static void loop_config_discard(struct loop_device *lo,
if (S_ISBLK(inode->i_mode)) {
struct block_device *bdev = I_BDEV(inode);
- max_discard_sectors = bdev_write_zeroes_sectors(bdev);
- granularity = bdev_discard_granularity(bdev);
+ *max_discard_sectors = bdev_write_zeroes_sectors(bdev);
+ *granularity = bdev_discard_granularity(bdev);
/*
* We use punch hole to reclaim the free space used by the
* image a.k.a. discard.
*/
} else if (file->f_op->fallocate && !vfs_statfs(&file->f_path, &sbuf)) {
- max_discard_sectors = UINT_MAX >> 9;
- granularity = sbuf.f_bsize;
+ *max_discard_sectors = UINT_MAX >> 9;
+ *granularity = sbuf.f_bsize;
}
-
- lim->max_hw_discard_sectors = max_discard_sectors;
- lim->max_write_zeroes_sectors = max_discard_sectors;
- if (max_discard_sectors)
- lim->discard_granularity = granularity;
- else
- lim->discard_granularity = 0;
}
struct loop_worker {
@@ -991,6 +983,7 @@ static int loop_reconfigure_limits(struct loop_device *lo, unsigned int bsize)
struct inode *inode = file->f_mapping->host;
struct block_device *backing_bdev = NULL;
struct queue_limits lim;
+ u32 granularity = 0, max_discard_sectors = 0;
if (S_ISBLK(inode->i_mode))
backing_bdev = I_BDEV(inode);
@@ -1000,6 +993,8 @@ static int loop_reconfigure_limits(struct loop_device *lo, unsigned int bsize)
if (!bsize)
bsize = loop_default_blocksize(lo, backing_bdev);
+ loop_get_discard_config(lo, &granularity, &max_discard_sectors);
+
lim = queue_limits_start_update(lo->lo_queue);
lim.logical_block_size = bsize;
lim.physical_block_size = bsize;
@@ -1009,7 +1004,12 @@ static int loop_reconfigure_limits(struct loop_device *lo, unsigned int bsize)
lim.features |= BLK_FEAT_WRITE_CACHE;
if (backing_bdev && !bdev_nonrot(backing_bdev))
lim.features |= BLK_FEAT_ROTATIONAL;
- loop_config_discard(lo, &lim);
+ lim.max_hw_discard_sectors = max_discard_sectors;
+ lim.max_write_zeroes_sectors = max_discard_sectors;
+ if (max_discard_sectors)
+ lim.discard_granularity = granularity;
+ else
+ lim.discard_granularity = 0;
return queue_limits_commit_update(lo->lo_queue, &lim);
}
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index c6d18cd8af44..d4aed12dd436 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -3041,7 +3041,7 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
ret = ublk_ctrl_end_recovery(ub, cmd);
break;
default:
- ret = -ENOTSUPP;
+ ret = -EOPNOTSUPP;
break;
}
diff --git a/drivers/bus/mhi/host/boot.c b/drivers/bus/mhi/host/boot.c
index dedd29ca8db3..e8c92972f9df 100644
--- a/drivers/bus/mhi/host/boot.c
+++ b/drivers/bus/mhi/host/boot.c
@@ -82,9 +82,9 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl)
* other cores to shutdown while we're collecting RDDM buffer. After
* returning from this function, we expect the device to reset.
*
- * Normaly, we read/write pm_state only after grabbing the
+ * Normally, we read/write pm_state only after grabbing the
* pm_lock, since we're in a panic, skipping it. Also there is no
- * gurantee that this state change would take effect since
+ * guarantee that this state change would take effect since
* we're setting it w/o grabbing pm_lock
*/
mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT;
diff --git a/drivers/bus/mhi/host/internal.h b/drivers/bus/mhi/host/internal.h
index d057e877932e..3134f111be35 100644
--- a/drivers/bus/mhi/host/internal.h
+++ b/drivers/bus/mhi/host/internal.h
@@ -255,7 +255,7 @@ struct mhi_chan {
/*
* Important: When consuming, increment tre_ring first and when
* releasing, decrement buf_ring first. If tre_ring has space, buf_ring
- * is guranteed to have space so we do not need to check both rings.
+ * is guaranteed to have space so we do not need to check both rings.
*/
struct mhi_ring buf_ring;
struct mhi_ring tre_ring;
diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
index 9938bb034c1c..07645ce2119a 100644
--- a/drivers/bus/mhi/host/pci_generic.c
+++ b/drivers/bus/mhi/host/pci_generic.c
@@ -917,12 +917,12 @@ static int mhi_pci_claim(struct mhi_controller *mhi_cntrl,
return err;
}
- err = pcim_iomap_regions(pdev, 1 << bar_num, pci_name(pdev));
- if (err) {
+ mhi_cntrl->regs = pcim_iomap_region(pdev, 1 << bar_num, pci_name(pdev));
+ if (IS_ERR(mhi_cntrl->regs)) {
+ err = PTR_ERR(mhi_cntrl->regs);
dev_err(&pdev->dev, "failed to map pci region: %d\n", err);
return err;
}
- mhi_cntrl->regs = pcim_iomap_table(pdev)[bar_num];
mhi_cntrl->reg_len = pci_resource_len(pdev, bar_num);
err = dma_set_mask_and_coherent(&pdev->dev, dma_mask);
diff --git a/drivers/bus/mhi/host/trace.h b/drivers/bus/mhi/host/trace.h
index 95613c8ebe06..3e0c41777429 100644
--- a/drivers/bus/mhi/host/trace.h
+++ b/drivers/bus/mhi/host/trace.h
@@ -9,6 +9,7 @@
#if !defined(_TRACE_EVENT_MHI_HOST_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_EVENT_MHI_HOST_H
+#include <linux/byteorder/generic.h>
#include <linux/tracepoint.h>
#include <linux/trace_seq.h>
#include "../common.h"
@@ -97,18 +98,18 @@ TRACE_EVENT(mhi_gen_tre,
__string(name, mhi_cntrl->mhi_dev->name)
__field(int, ch_num)
__field(void *, wp)
- __field(__le64, tre_ptr)
- __field(__le32, dword0)
- __field(__le32, dword1)
+ __field(uint64_t, tre_ptr)
+ __field(uint32_t, dword0)
+ __field(uint32_t, dword1)
),
TP_fast_assign(
__assign_str(name);
__entry->ch_num = mhi_chan->chan;
__entry->wp = mhi_tre;
- __entry->tre_ptr = mhi_tre->ptr;
- __entry->dword0 = mhi_tre->dword[0];
- __entry->dword1 = mhi_tre->dword[1];
+ __entry->tre_ptr = le64_to_cpu(mhi_tre->ptr);
+ __entry->dword0 = le32_to_cpu(mhi_tre->dword[0]);
+ __entry->dword1 = le32_to_cpu(mhi_tre->dword[1]);
),
TP_printk("%s: Chan: %d TRE: 0x%p TRE buf: 0x%llx DWORD0: 0x%08x DWORD1: 0x%08x\n",
@@ -176,19 +177,19 @@ DECLARE_EVENT_CLASS(mhi_process_event_ring,
TP_STRUCT__entry(
__string(name, mhi_cntrl->mhi_dev->name)
- __field(__le32, dword0)
- __field(__le32, dword1)
+ __field(uint32_t, dword0)
+ __field(uint32_t, dword1)
__field(int, state)
- __field(__le64, ptr)
+ __field(uint64_t, ptr)
__field(void *, rp)
),
TP_fast_assign(
__assign_str(name);
__entry->rp = rp;
- __entry->ptr = rp->ptr;
- __entry->dword0 = rp->dword[0];
- __entry->dword1 = rp->dword[1];
+ __entry->ptr = le64_to_cpu(rp->ptr);
+ __entry->dword0 = le32_to_cpu(rp->dword[0]);
+ __entry->dword1 = le32_to_cpu(rp->dword[1]);
__entry->state = MHI_TRE_GET_EV_STATE(rp);
),
diff --git a/drivers/cdx/cdx.c b/drivers/cdx/cdx.c
index 07371cb653d3..316bd89a95ca 100644
--- a/drivers/cdx/cdx.c
+++ b/drivers/cdx/cdx.c
@@ -707,7 +707,7 @@ static const struct vm_operations_struct cdx_phys_vm_ops = {
* Return: true on success, false otherwise.
*/
static int cdx_mmap_resource(struct file *fp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct cdx_device *cdx_dev = to_cdx_device(kobj_to_dev(kobj));
diff --git a/drivers/char/powernv-op-panel.c b/drivers/char/powernv-op-panel.c
index f2cff1a6fed5..53467b0a6187 100644
--- a/drivers/char/powernv-op-panel.c
+++ b/drivers/char/powernv-op-panel.c
@@ -213,7 +213,7 @@ static struct platform_driver oppanel_driver = {
.of_match_table = oppanel_match,
},
.probe = oppanel_probe,
- .remove_new = oppanel_remove,
+ .remove = oppanel_remove,
};
module_platform_driver(oppanel_driver);
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 0f8185e541ed..f887569fd3d0 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1467,7 +1467,7 @@ static struct platform_driver sonypi_driver = {
.pm = SONYPI_PM,
},
.probe = sonypi_probe,
- .remove_new = sonypi_remove,
+ .remove = sonypi_remove,
.shutdown = sonypi_shutdown,
};
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 4f6c3cb8aa41..34a345dc5e72 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -738,7 +738,7 @@ MODULE_DEVICE_TABLE(of, hwicap_of_match);
static struct platform_driver hwicap_platform_driver = {
.probe = hwicap_drv_probe,
- .remove_new = hwicap_drv_remove,
+ .remove = hwicap_drv_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = hwicap_of_match,
diff --git a/drivers/char/xillybus/xillybus_of.c b/drivers/char/xillybus/xillybus_of.c
index 8802e2a6fd20..1a1e64133315 100644
--- a/drivers/char/xillybus/xillybus_of.c
+++ b/drivers/char/xillybus/xillybus_of.c
@@ -74,7 +74,7 @@ static void xilly_drv_remove(struct platform_device *op)
static struct platform_driver xillybus_platform_driver = {
.probe = xilly_drv_probe,
- .remove_new = xilly_drv_remove,
+ .remove = xilly_drv_remove,
.driver = {
.name = xillyname,
.of_match_table = xillybus_of_match,
diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
index 1b481731df96..b9df9b19d4bd 100644
--- a/drivers/comedi/comedi_fops.c
+++ b/drivers/comedi/comedi_fops.c
@@ -2407,6 +2407,18 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
start += PAGE_SIZE;
}
+
+#ifdef CONFIG_MMU
+ /*
+ * Leaving behind a partial mapping of a buffer we're about to
+ * drop is unsafe, see remap_pfn_range_notrack().
+ * We need to zap the range here ourselves instead of relying
+ * on the automatic zapping in remap_pfn_range() because we call
+ * remap_pfn_range() in a loop.
+ */
+ if (retval)
+ zap_vma_ptes(vma, vma->vm_start, size);
+#endif
}
if (retval == 0) {
diff --git a/drivers/counter/ftm-quaddec.c b/drivers/counter/ftm-quaddec.c
index 200876f3ec04..6ac4efb5658b 100644
--- a/drivers/counter/ftm-quaddec.c
+++ b/drivers/counter/ftm-quaddec.c
@@ -311,6 +311,7 @@ static const struct of_device_id ftm_quaddec_match[] = {
{ .compatible = "fsl,ftm-quaddec" },
{},
};
+MODULE_DEVICE_TABLE(of, ftm_quaddec_match);
static struct platform_driver ftm_quaddec_driver = {
.driver = {
diff --git a/drivers/counter/intel-qep.c b/drivers/counter/intel-qep.c
index af5942e66f7d..ee2bae27b728 100644
--- a/drivers/counter/intel-qep.c
+++ b/drivers/counter/intel-qep.c
@@ -408,13 +408,9 @@ static int intel_qep_probe(struct pci_dev *pci, const struct pci_device_id *id)
pci_set_master(pci);
- ret = pcim_iomap_regions(pci, BIT(0), pci_name(pci));
- if (ret)
- return ret;
-
- regs = pcim_iomap_table(pci)[0];
- if (!regs)
- return -ENOMEM;
+ regs = pcim_iomap_region(pci, 0, pci_name(pci));
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
qep->dev = dev;
qep->regs = regs;
diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c
index 186e73d6ccb4..87b6ec567b54 100644
--- a/drivers/counter/stm32-timer-cnt.c
+++ b/drivers/counter/stm32-timer-cnt.c
@@ -214,11 +214,17 @@ static int stm32_count_enable_write(struct counter_device *counter,
{
struct stm32_timer_cnt *const priv = counter_priv(counter);
u32 cr1;
+ int ret;
if (enable) {
regmap_read(priv->regmap, TIM_CR1, &cr1);
- if (!(cr1 & TIM_CR1_CEN))
- clk_enable(priv->clk);
+ if (!(cr1 & TIM_CR1_CEN)) {
+ ret = clk_enable(priv->clk);
+ if (ret) {
+ dev_err(counter->parent, "Cannot enable clock %d\n", ret);
+ return ret;
+ }
+ }
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
TIM_CR1_CEN);
@@ -694,6 +700,7 @@ static int stm32_timer_cnt_probe_encoder(struct device *dev,
}
ret = of_property_read_u32(tnode, "reg", &idx);
+ of_node_put(tnode);
if (ret) {
dev_err(dev, "Can't get index (%d)\n", ret);
return ret;
@@ -816,7 +823,11 @@ static int __maybe_unused stm32_timer_cnt_resume(struct device *dev)
return ret;
if (priv->enabled) {
- clk_enable(priv->clk);
+ ret = clk_enable(priv->clk);
+ if (ret) {
+ dev_err(dev, "Cannot enable clock %d\n", ret);
+ return ret;
+ }
/* Restore registers that may have been lost */
regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr);
diff --git a/drivers/counter/ti-ecap-capture.c b/drivers/counter/ti-ecap-capture.c
index 675447315caf..b119aeede693 100644
--- a/drivers/counter/ti-ecap-capture.c
+++ b/drivers/counter/ti-ecap-capture.c
@@ -574,8 +574,13 @@ static int ecap_cnt_resume(struct device *dev)
{
struct counter_device *counter_dev = dev_get_drvdata(dev);
struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev);
+ int ret;
- clk_enable(ecap_dev->clk);
+ ret = clk_enable(ecap_dev->clk);
+ if (ret) {
+ dev_err(dev, "Cannot enable clock %d\n", ret);
+ return ret;
+ }
ecap_cnt_capture_set_evmode(counter_dev, ecap_dev->pm_ctx.ev_mode);
diff --git a/drivers/cpuidle/cpuidle-riscv-sbi.c b/drivers/cpuidle/cpuidle-riscv-sbi.c
index d228b4d18d56..14462c092039 100644
--- a/drivers/cpuidle/cpuidle-riscv-sbi.c
+++ b/drivers/cpuidle/cpuidle-riscv-sbi.c
@@ -26,6 +26,7 @@
#include <asm/smp.h>
#include <asm/suspend.h>
+#include "cpuidle.h"
#include "dt_idle_states.h"
#include "dt_idle_genpd.h"
@@ -329,6 +330,9 @@ static int sbi_cpuidle_init_cpu(struct device *dev, int cpu)
return ret;
}
+ if (cpuidle_disabled())
+ return 0;
+
ret = cpuidle_register(drv, NULL);
if (ret)
goto deinit;
@@ -538,7 +542,10 @@ static int sbi_cpuidle_probe(struct platform_device *pdev)
/* Setup CPU hotplut notifiers */
sbi_idle_init_cpuhp();
- pr_info("idle driver registered for all CPUs\n");
+ if (cpuidle_disabled())
+ pr_info("cpuidle is disabled\n");
+ else
+ pr_info("idle driver registered for all CPUs\n");
return 0;
@@ -582,4 +589,4 @@ static int __init sbi_cpuidle_init(void)
return 0;
}
-device_initcall(sbi_cpuidle_init);
+arch_initcall(sbi_cpuidle_init);
diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c
index 9dc394295e1f..24041cf85cfb 100644
--- a/drivers/cxl/port.c
+++ b/drivers/cxl/port.c
@@ -173,7 +173,7 @@ static ssize_t CDAT_read(struct file *filp, struct kobject *kobj,
static BIN_ATTR_ADMIN_RO(CDAT, 0);
static umode_t cxl_port_bin_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *attr, int i)
+ const struct bin_attribute *attr, int i)
{
struct device *dev = kobj_to_dev(kobj);
struct cxl_port *port = to_cxl_port(dev);
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d9ec1e69e428..e994d6e0779e 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -378,6 +378,20 @@ config LOONGSON1_APB_DMA
This selects support for the APB DMA controller in Loongson1 SoCs,
which is required by Loongson1 NAND and audio support.
+config LOONGSON2_APB_DMA
+ tristate "Loongson2 APB DMA support"
+ depends on LOONGARCH || COMPILE_TEST
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ help
+ Support for the Loongson2 APB DMA controller driver. The
+ DMA controller is having single DMA channel which can be
+ configured for different peripherals like audio, nand, sdio
+ etc which is in APB bus.
+
+ This DMA controller transfers data from memory to peripheral fifo.
+ It does not support memory to memory data transfer.
+
config LPC18XX_DMAMUX
bool "NXP LPC18xx/43xx DMA MUX for PL080"
depends on ARCH_LPC18XX || COMPILE_TEST
@@ -396,20 +410,6 @@ config LPC32XX_DMAMUX
Support for PL080 multiplexed DMA request lines on
LPC32XX platrofm.
-config LS2X_APB_DMA
- tristate "Loongson LS2X APB DMA support"
- depends on LOONGARCH || COMPILE_TEST
- select DMA_ENGINE
- select DMA_VIRTUAL_CHANNELS
- help
- Support for the Loongson LS2X APB DMA controller driver. The
- DMA controller is having single DMA channel which can be
- configured for different peripherals like audio, nand, sdio
- etc which is in APB bus.
-
- This DMA controller transfers data from memory to peripheral fifo.
- It does not support memory to memory data transfer.
-
config MCF_EDMA
tristate "Freescale eDMA engine support, ColdFire mcf5441x SoCs"
depends on M5441x || (COMPILE_TEST && FSL_EDMA=n)
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index ad6a03c052ec..5b2a52f4f2ee 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -50,9 +50,9 @@ obj-$(CONFIG_INTEL_IOATDMA) += ioat/
obj-y += idxd/
obj-$(CONFIG_K3_DMA) += k3dma.o
obj-$(CONFIG_LOONGSON1_APB_DMA) += loongson1-apb-dma.o
+obj-$(CONFIG_LOONGSON2_APB_DMA) += loongson2-apb-dma.o
obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o
obj-$(CONFIG_LPC32XX_DMAMUX) += lpc32xx-dmamux.o
-obj-$(CONFIG_LS2X_APB_DMA) += ls2x-apb-dma.o
obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o
obj-$(CONFIG_MILBEAUT_XDMAC) += milbeaut-xdmac.o
obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c
index a58a1600dd65..2abbe11e797e 100644
--- a/drivers/dma/acpi-dma.c
+++ b/drivers/dma/acpi-dma.c
@@ -9,18 +9,21 @@
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
+#include <linux/acpi.h>
+#include <linux/acpi_dma.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
-#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/acpi.h>
-#include <linux/acpi_dma.h>
#include <linux/property.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
static LIST_HEAD(acpi_dma_list);
static DEFINE_MUTEX(acpi_dma_lock);
@@ -236,7 +239,7 @@ int acpi_dma_controller_free(struct device *dev)
}
EXPORT_SYMBOL_GPL(acpi_dma_controller_free);
-static void devm_acpi_dma_release(struct device *dev, void *res)
+static void devm_acpi_dma_free(void *dev)
{
acpi_dma_controller_free(dev);
}
@@ -259,37 +262,15 @@ int devm_acpi_dma_controller_register(struct device *dev,
(struct acpi_dma_spec *, struct acpi_dma *),
void *data)
{
- void *res;
int ret;
- res = devres_alloc(devm_acpi_dma_release, 0, GFP_KERNEL);
- if (!res)
- return -ENOMEM;
-
ret = acpi_dma_controller_register(dev, acpi_dma_xlate, data);
- if (ret) {
- devres_free(res);
+ if (ret)
return ret;
- }
- devres_add(dev, res);
- return 0;
-}
-EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_register);
-/**
- * devm_acpi_dma_controller_free - resource managed acpi_dma_controller_free()
- * @dev: device that is unregistering as DMA controller
- *
- * Unregister a DMA controller registered with
- * devm_acpi_dma_controller_register(). Normally this function will not need to
- * be called and the resource management code will ensure that the resource is
- * freed.
- */
-void devm_acpi_dma_controller_free(struct device *dev)
-{
- WARN_ON(devres_release(dev, devm_acpi_dma_release, NULL, NULL));
+ return devm_add_action_or_reset(dev, devm_acpi_dma_free, dev);
}
-EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_free);
+EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_register);
/**
* acpi_dma_update_dma_spec - prepare dma specifier to pass to translation function
diff --git a/drivers/dma/altera-msgdma.c b/drivers/dma/altera-msgdma.c
index e6a6566b309e..a203fdd84950 100644
--- a/drivers/dma/altera-msgdma.c
+++ b/drivers/dma/altera-msgdma.c
@@ -954,7 +954,7 @@ static struct platform_driver msgdma_driver = {
.of_match_table = of_match_ptr(msgdma_match),
},
.probe = msgdma_probe,
- .remove_new = msgdma_remove,
+ .remove = msgdma_remove,
};
module_platform_driver(msgdma_driver);
diff --git a/drivers/dma/amd/qdma/qdma.c b/drivers/dma/amd/qdma/qdma.c
index b0a1f3ad851b..6d9079458fe9 100644
--- a/drivers/dma/amd/qdma/qdma.c
+++ b/drivers/dma/amd/qdma/qdma.c
@@ -1133,7 +1133,7 @@ static struct platform_driver amd_qdma_driver = {
.name = "amd-qdma",
},
.probe = amd_qdma_probe,
- .remove_new = amd_qdma_remove,
+ .remove = amd_qdma_remove,
};
module_platform_driver(amd_qdma_driver);
diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c
index 9588773dd2eb..c499173d80b2 100644
--- a/drivers/dma/apple-admac.c
+++ b/drivers/dma/apple-admac.c
@@ -950,7 +950,7 @@ static struct platform_driver apple_admac_driver = {
.of_match_table = admac_of_match,
},
.probe = admac_probe,
- .remove_new = admac_remove,
+ .remove = admac_remove,
};
module_platform_driver(apple_admac_driver);
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index baebddc740b0..2d147712cbc6 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -2250,7 +2250,7 @@ static const struct dev_pm_ops __maybe_unused at_dma_dev_pm_ops = {
};
static struct platform_driver at_dma_driver = {
- .remove_new = at_dma_remove,
+ .remove = at_dma_remove,
.shutdown = at_dma_shutdown,
.id_table = atdma_devtypes,
.driver = {
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 299396121e6d..9c7b40220004 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -2476,7 +2476,7 @@ MODULE_DEVICE_TABLE(of, atmel_xdmac_dt_ids);
static struct platform_driver at_xdmac_driver = {
.probe = at_xdmac_probe,
- .remove_new = at_xdmac_remove,
+ .remove = at_xdmac_remove,
.driver = {
.name = "at_xdmac",
.of_match_table = of_match_ptr(atmel_xdmac_dt_ids),
diff --git a/drivers/dma/bcm-sba-raid.c b/drivers/dma/bcm-sba-raid.c
index cfa6e1167a1f..7f0e76439ce5 100644
--- a/drivers/dma/bcm-sba-raid.c
+++ b/drivers/dma/bcm-sba-raid.c
@@ -1756,7 +1756,7 @@ MODULE_DEVICE_TABLE(of, sba_of_match);
static struct platform_driver sba_driver = {
.probe = sba_probe,
- .remove_new = sba_remove,
+ .remove = sba_remove,
.driver = {
.name = "bcm-sba-raid",
.of_match_table = sba_of_match,
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index e1b92b4d7b05..7ba52dee40a9 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -1029,7 +1029,7 @@ static void bcm2835_dma_remove(struct platform_device *pdev)
static struct platform_driver bcm2835_dma_driver = {
.probe = bcm2835_dma_probe,
- .remove_new = bcm2835_dma_remove,
+ .remove = bcm2835_dma_remove,
.driver = {
.name = "bcm2835-dma",
.of_match_table = of_match_ptr(bcm2835_dma_of_match),
diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c
index 0bbaa7620bdd..6c4d655ffe77 100644
--- a/drivers/dma/bestcomm/bestcomm.c
+++ b/drivers/dma/bestcomm/bestcomm.c
@@ -486,7 +486,7 @@ MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
static struct platform_driver mpc52xx_bcom_of_platform_driver = {
.probe = mpc52xx_bcom_probe,
- .remove_new = mpc52xx_bcom_remove,
+ .remove = mpc52xx_bcom_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = mpc52xx_bcom_of_match,
diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
index c9cfa341db51..100057603fd4 100644
--- a/drivers/dma/dma-jz4780.c
+++ b/drivers/dma/dma-jz4780.c
@@ -1122,7 +1122,7 @@ MODULE_DEVICE_TABLE(of, jz4780_dma_dt_match);
static struct platform_driver jz4780_dma_driver = {
.probe = jz4780_dma_probe,
- .remove_new = jz4780_dma_remove,
+ .remove = jz4780_dma_remove,
.driver = {
.name = "jz4780-dma",
.of_match_table = jz4780_dma_dt_match,
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index fffafa86d964..b23536645ff7 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -1676,7 +1676,7 @@ MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
static struct platform_driver dw_driver = {
.probe = dw_probe,
- .remove_new = dw_remove,
+ .remove = dw_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = dw_dma_of_id_table,
diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c
index 47c58ad468cb..2606cf9cd429 100644
--- a/drivers/dma/dw/platform.c
+++ b/drivers/dma/dw/platform.c
@@ -191,7 +191,7 @@ static const struct dev_pm_ops dw_dev_pm_ops = {
static struct platform_driver dw_driver = {
.probe = dw_probe,
- .remove_new = dw_remove,
+ .remove = dw_remove,
.shutdown = dw_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index 6b98a23e3332..e424bb5c40e7 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -929,8 +929,7 @@ static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan)
/* Sanity check the channel parameters */
if (!edmac->edma->m2m) {
- if (edmac->dma_cfg.port < EP93XX_DMA_I2S1 ||
- edmac->dma_cfg.port > EP93XX_DMA_IRDA)
+ if (edmac->dma_cfg.port > EP93XX_DMA_IRDA)
return -EINVAL;
if (edmac->dma_cfg.dir != ep93xx_dma_chan_direction(chan))
return -EINVAL;
diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
index f9f1eda79254..60de1003193a 100644
--- a/drivers/dma/fsl-edma-main.c
+++ b/drivers/dma/fsl-edma-main.c
@@ -740,7 +740,7 @@ static struct platform_driver fsl_edma_driver = {
.pm = &fsl_edma_pm_ops,
},
.probe = fsl_edma_probe,
- .remove_new = fsl_edma_remove,
+ .remove = fsl_edma_remove,
};
static int __init fsl_edma_init(void)
diff --git a/drivers/dma/fsl-qdma.c b/drivers/dma/fsl-qdma.c
index 5005e138fc23..823f5c6bc2e1 100644
--- a/drivers/dma/fsl-qdma.c
+++ b/drivers/dma/fsl-qdma.c
@@ -1288,7 +1288,7 @@ static struct platform_driver fsl_qdma_driver = {
.of_match_table = fsl_qdma_dt_ids,
},
.probe = fsl_qdma_probe,
- .remove_new = fsl_qdma_remove,
+ .remove = fsl_qdma_remove,
};
module_platform_driver(fsl_qdma_driver);
diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
index 014ff523d5ec..6aa97e258a55 100644
--- a/drivers/dma/fsl_raid.c
+++ b/drivers/dma/fsl_raid.c
@@ -886,7 +886,7 @@ static struct platform_driver fsl_re_driver = {
.of_match_table = fsl_re_ids,
},
.probe = fsl_re_probe,
- .remove_new = fsl_re_remove,
+ .remove = fsl_re_remove,
};
module_platform_driver(fsl_re_driver);
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 18a6c4bf6275..b5e7d18b9766 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1404,7 +1404,7 @@ static struct platform_driver fsldma_of_driver = {
#endif
},
.probe = fsldma_of_probe,
- .remove_new = fsldma_of_remove,
+ .remove = fsldma_of_remove,
};
/*----------------------------------------------------------------------------*/
diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c
index 3c648308a54a..d147353d47ab 100644
--- a/drivers/dma/idma64.c
+++ b/drivers/dma/idma64.c
@@ -693,7 +693,7 @@ static const struct dev_pm_ops idma64_dev_pm_ops = {
static struct platform_driver idma64_platform_driver = {
.probe = idma64_platform_probe,
- .remove_new = idma64_platform_remove,
+ .remove = idma64_platform_remove,
.driver = {
.name = LPSS_IDMA64_DRIVER_NAME,
.pm = &idma64_dev_pm_ops,
diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h
index e16dbf9ab324..c426511f2104 100644
--- a/drivers/dma/idxd/registers.h
+++ b/drivers/dma/idxd/registers.h
@@ -6,6 +6,10 @@
#include <uapi/linux/idxd.h>
/* PCI Config */
+#define PCI_DEVICE_ID_INTEL_DSA_GNRD 0x11fb
+#define PCI_DEVICE_ID_INTEL_DSA_DMR 0x1212
+#define PCI_DEVICE_ID_INTEL_IAA_DMR 0x1216
+
#define DEVICE_VERSION_1 0x100
#define DEVICE_VERSION_2 0x200
diff --git a/drivers/dma/img-mdc-dma.c b/drivers/dma/img-mdc-dma.c
index 0532dd2640dc..4127c1bdcca7 100644
--- a/drivers/dma/img-mdc-dma.c
+++ b/drivers/dma/img-mdc-dma.c
@@ -1076,7 +1076,7 @@ static struct platform_driver mdc_dma_driver = {
.of_match_table = of_match_ptr(mdc_dma_of_match),
},
.probe = mdc_dma_probe,
- .remove_new = mdc_dma_remove,
+ .remove = mdc_dma_remove,
};
module_platform_driver(mdc_dma_driver);
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index e913f0db99da..a651e0995ce8 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -1233,7 +1233,7 @@ static struct platform_driver imxdma_driver = {
.name = "imx-dma",
.of_match_table = imx_dma_of_dev_id,
},
- .remove_new = imxdma_remove,
+ .remove = imxdma_remove,
};
static int __init imxdma_module_init(void)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 72299a08af44..3449006cd14b 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2440,7 +2440,7 @@ static struct platform_driver sdma_driver = {
.name = "imx-sdma",
.of_match_table = sdma_dt_ids,
},
- .remove_new = sdma_remove,
+ .remove = sdma_remove,
.probe = sdma_probe,
};
diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c
index 5de8c21d41e7..acc2983e28e0 100644
--- a/drivers/dma/k3dma.c
+++ b/drivers/dma/k3dma.c
@@ -1028,7 +1028,7 @@ static struct platform_driver k3_pdma_driver = {
.of_match_table = k3_pdma_dt_ids,
},
.probe = k3_dma_probe,
- .remove_new = k3_dma_remove,
+ .remove = k3_dma_remove,
};
module_platform_driver(k3_pdma_driver);
diff --git a/drivers/dma/ls2x-apb-dma.c b/drivers/dma/loongson2-apb-dma.c
index 9652e8666722..367ed34ce4da 100644
--- a/drivers/dma/ls2x-apb-dma.c
+++ b/drivers/dma/loongson2-apb-dma.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Driver for the Loongson LS2X APB DMA Controller
+ * Driver for the Loongson-2 APB DMA Controller
*
* Copyright (C) 2017-2023 Loongson Corporation
*/
@@ -692,7 +692,7 @@ MODULE_DEVICE_TABLE(of, ls2x_dma_of_match_table);
static struct platform_driver ls2x_dmac_driver = {
.probe = ls2x_dma_probe,
- .remove_new = ls2x_dma_remove,
+ .remove = ls2x_dma_remove,
.driver = {
.name = "ls2x-apbdma",
.of_match_table = ls2x_dma_of_match_table,
@@ -700,6 +700,6 @@ static struct platform_driver ls2x_dmac_driver = {
};
module_platform_driver(ls2x_dmac_driver);
-MODULE_DESCRIPTION("Loongson LS2X APB DMA Controller driver");
+MODULE_DESCRIPTION("Loongson-2 APB DMA Controller driver");
MODULE_AUTHOR("Loongson Technology Corporation Limited");
MODULE_LICENSE("GPL");
diff --git a/drivers/dma/mcf-edma-main.c b/drivers/dma/mcf-edma-main.c
index 0c5862bf26f8..9e1c6400c77b 100644
--- a/drivers/dma/mcf-edma-main.c
+++ b/drivers/dma/mcf-edma-main.c
@@ -267,7 +267,7 @@ static struct platform_driver mcf_edma_driver = {
.name = "mcf-edma",
},
.probe = mcf_edma_probe,
- .remove_new = mcf_edma_remove,
+ .remove = mcf_edma_remove,
};
bool mcf_edma_filter_fn(struct dma_chan *chan, void *param)
diff --git a/drivers/dma/mediatek/mtk-cqdma.c b/drivers/dma/mediatek/mtk-cqdma.c
index b69eabf12a24..d5ddb4e30e71 100644
--- a/drivers/dma/mediatek/mtk-cqdma.c
+++ b/drivers/dma/mediatek/mtk-cqdma.c
@@ -922,7 +922,7 @@ static void mtk_cqdma_remove(struct platform_device *pdev)
static struct platform_driver mtk_cqdma_driver = {
.probe = mtk_cqdma_probe,
- .remove_new = mtk_cqdma_remove,
+ .remove = mtk_cqdma_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = mtk_cqdma_match,
diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c
index 58c7961ab9ad..fa77bb24a430 100644
--- a/drivers/dma/mediatek/mtk-hsdma.c
+++ b/drivers/dma/mediatek/mtk-hsdma.c
@@ -1038,7 +1038,7 @@ static void mtk_hsdma_remove(struct platform_device *pdev)
static struct platform_driver mtk_hsdma_driver = {
.probe = mtk_hsdma_probe,
- .remove_new = mtk_hsdma_remove,
+ .remove = mtk_hsdma_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = mtk_hsdma_match,
diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c
index 1bdc1500be40..08e15177427b 100644
--- a/drivers/dma/mediatek/mtk-uart-apdma.c
+++ b/drivers/dma/mediatek/mtk-uart-apdma.c
@@ -637,7 +637,7 @@ static const struct dev_pm_ops mtk_uart_apdma_pm_ops = {
static struct platform_driver mtk_uart_apdma_driver = {
.probe = mtk_uart_apdma_probe,
- .remove_new = mtk_uart_apdma_remove,
+ .remove = mtk_uart_apdma_remove,
.driver = {
.name = KBUILD_MODNAME,
.pm = &mtk_uart_apdma_pm_ops,
diff --git a/drivers/dma/milbeaut-hdmac.c b/drivers/dma/milbeaut-hdmac.c
index 7b41c670970a..9a5ec247ed6d 100644
--- a/drivers/dma/milbeaut-hdmac.c
+++ b/drivers/dma/milbeaut-hdmac.c
@@ -571,7 +571,7 @@ MODULE_DEVICE_TABLE(of, milbeaut_hdmac_match);
static struct platform_driver milbeaut_hdmac_driver = {
.probe = milbeaut_hdmac_probe,
- .remove_new = milbeaut_hdmac_remove,
+ .remove = milbeaut_hdmac_remove,
.driver = {
.name = "milbeaut-m10v-hdmac",
.of_match_table = milbeaut_hdmac_match,
diff --git a/drivers/dma/milbeaut-xdmac.c b/drivers/dma/milbeaut-xdmac.c
index 2cce529b448e..58d4fd6df0bf 100644
--- a/drivers/dma/milbeaut-xdmac.c
+++ b/drivers/dma/milbeaut-xdmac.c
@@ -409,7 +409,7 @@ MODULE_DEVICE_TABLE(of, milbeaut_xdmac_match);
static struct platform_driver milbeaut_xdmac_driver = {
.probe = milbeaut_xdmac_probe,
- .remove_new = milbeaut_xdmac_remove,
+ .remove = milbeaut_xdmac_remove,
.driver = {
.name = "milbeaut-m10v-xdmac",
.of_match_table = milbeaut_xdmac_match,
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index 136fcaeff8dd..a95d31103d30 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -1137,7 +1137,7 @@ static struct platform_driver mmp_pdma_driver = {
},
.id_table = mmp_pdma_id_table,
.probe = mmp_pdma_probe,
- .remove_new = mmp_pdma_remove,
+ .remove = mmp_pdma_remove,
};
module_platform_driver(mmp_pdma_driver);
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
index b76fe99e1151..c8dc504510f1 100644
--- a/drivers/dma/mmp_tdma.c
+++ b/drivers/dma/mmp_tdma.c
@@ -736,7 +736,7 @@ static struct platform_driver mmp_tdma_driver = {
.of_match_table = mmp_tdma_dt_ids,
},
.probe = mmp_tdma_probe,
- .remove_new = mmp_tdma_remove,
+ .remove = mmp_tdma_remove,
};
module_platform_driver(mmp_tdma_driver);
diff --git a/drivers/dma/moxart-dma.c b/drivers/dma/moxart-dma.c
index 66dc6d31b603..de09e1ab7767 100644
--- a/drivers/dma/moxart-dma.c
+++ b/drivers/dma/moxart-dma.c
@@ -644,7 +644,7 @@ MODULE_DEVICE_TABLE(of, moxart_dma_match);
static struct platform_driver moxart_driver = {
.probe = moxart_probe,
- .remove_new = moxart_remove,
+ .remove = moxart_remove,
.driver = {
.name = "moxart-dma-engine",
.of_match_table = moxart_dma_match,
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 68c247a46321..bf131cb5db66 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -1110,7 +1110,7 @@ MODULE_DEVICE_TABLE(of, mpc_dma_match);
static struct platform_driver mpc_dma_driver = {
.probe = mpc_dma_probe,
- .remove_new = mpc_dma_remove,
+ .remove = mpc_dma_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = mpc_dma_match,
diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c
index c8c67f4d982c..cad4d4fb51ac 100644
--- a/drivers/dma/mv_xor_v2.c
+++ b/drivers/dma/mv_xor_v2.c
@@ -635,7 +635,7 @@ static int mv_xor_v2_descq_init(struct mv_xor_v2_device *xor_dev)
writel(MV_XOR_V2_DESC_NUM,
xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_SIZE_OFF);
- /* write the DESQ address to the DMA enngine*/
+ /* write the DESQ address to the DMA engine*/
writel(lower_32_bits(xor_dev->hw_desq),
xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_BALR_OFF);
writel(upper_32_bits(xor_dev->hw_desq),
@@ -884,7 +884,7 @@ static struct platform_driver mv_xor_v2_driver = {
.probe = mv_xor_v2_probe,
.suspend = mv_xor_v2_suspend,
.resume = mv_xor_v2_resume,
- .remove_new = mv_xor_v2_remove,
+ .remove = mv_xor_v2_remove,
.driver = {
.name = "mv_xor_v2",
.of_match_table = of_match_ptr(mv_xor_v2_dt_ids),
diff --git a/drivers/dma/nbpfaxi.c b/drivers/dma/nbpfaxi.c
index 3b011a91d48e..0d6324c4e2be 100644
--- a/drivers/dma/nbpfaxi.c
+++ b/drivers/dma/nbpfaxi.c
@@ -1515,7 +1515,7 @@ static struct platform_driver nbpf_driver = {
},
.id_table = nbpf_ids,
.probe = nbpf_probe,
- .remove_new = nbpf_remove,
+ .remove = nbpf_remove,
};
module_platform_driver(nbpf_driver);
diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c
index aa436f9e3571..57cec757d8f5 100644
--- a/drivers/dma/owl-dma.c
+++ b/drivers/dma/owl-dma.c
@@ -1252,7 +1252,7 @@ static void owl_dma_remove(struct platform_device *pdev)
static struct platform_driver owl_dma_driver = {
.probe = owl_dma_probe,
- .remove_new = owl_dma_remove,
+ .remove = owl_dma_remove,
.driver = {
.name = "dma-owl",
.of_match_table = of_match_ptr(owl_dma_match),
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index 7b78759ac734..9d2a5a967a99 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -4549,7 +4549,7 @@ MODULE_DEVICE_TABLE(of, ppc440spe_adma_of_match);
static struct platform_driver ppc440spe_adma_driver = {
.probe = ppc440spe_adma_probe,
- .remove_new = ppc440spe_adma_remove,
+ .remove = ppc440spe_adma_remove,
.driver = {
.name = "PPC440SP(E)-ADMA",
.of_match_table = ppc440spe_adma_of_match,
diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c
index 31f8da810c05..e50cf3357e5e 100644
--- a/drivers/dma/pxa_dma.c
+++ b/drivers/dma/pxa_dma.c
@@ -1442,7 +1442,7 @@ static struct platform_driver pxad_driver = {
},
.id_table = pxad_id_table,
.probe = pxad_probe,
- .remove_new = pxad_remove,
+ .remove = pxad_remove,
};
static bool pxad_filter_fn(struct dma_chan *chan, void *param)
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c
index d43a881e43b9..bbc3276992bb 100644
--- a/drivers/dma/qcom/bam_dma.c
+++ b/drivers/dma/qcom/bam_dma.c
@@ -1469,7 +1469,7 @@ static const struct dev_pm_ops bam_dma_pm_ops = {
static struct platform_driver bam_dma_driver = {
.probe = bam_dma_probe,
- .remove_new = bam_dma_remove,
+ .remove = bam_dma_remove,
.driver = {
.name = "bam-dma-engine",
.pm = &bam_dma_pm_ops,
diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index 4d2cd8d9ec74..c2b3e4452e71 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -948,7 +948,7 @@ MODULE_DEVICE_TABLE(acpi, hidma_acpi_ids);
static struct platform_driver hidma_driver = {
.probe = hidma_probe,
- .remove_new = hidma_remove,
+ .remove = hidma_remove,
.shutdown = hidma_shutdown,
.driver = {
.name = "hidma",
diff --git a/drivers/dma/qcom/qcom_adm.c b/drivers/dma/qcom/qcom_adm.c
index c1db398adc84..6be54fddcee1 100644
--- a/drivers/dma/qcom/qcom_adm.c
+++ b/drivers/dma/qcom/qcom_adm.c
@@ -937,7 +937,7 @@ MODULE_DEVICE_TABLE(of, adm_of_match);
static struct platform_driver adm_dma_driver = {
.probe = adm_dma_probe,
- .remove_new = adm_dma_remove,
+ .remove = adm_dma_remove,
.driver = {
.name = "adm-dma-engine",
.of_match_table = adm_of_match,
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
index 01e656c69e6c..dc1a9a05252e 100644
--- a/drivers/dma/sa11x0-dma.c
+++ b/drivers/dma/sa11x0-dma.c
@@ -1079,7 +1079,7 @@ static struct platform_driver sa11x0_dma_driver = {
.pm = &sa11x0_dma_pm_ops,
},
.probe = sa11x0_dma_probe,
- .remove_new = sa11x0_dma_remove,
+ .remove = sa11x0_dma_remove,
};
static int __init sa11x0_dma_init(void)
diff --git a/drivers/dma/sf-pdma/sf-pdma.c b/drivers/dma/sf-pdma/sf-pdma.c
index 428473611115..7ad3c29be146 100644
--- a/drivers/dma/sf-pdma/sf-pdma.c
+++ b/drivers/dma/sf-pdma/sf-pdma.c
@@ -354,7 +354,7 @@ static irqreturn_t sf_pdma_done_isr(int irq, void *dev_id)
if (!residue) {
tasklet_hi_schedule(&chan->done_tasklet);
} else {
- /* submit next trascatioin if possible */
+ /* submit next transaction if possible */
struct sf_pdma_desc *desc = chan->desc;
desc->src_addr += desc->xfer_size - residue;
@@ -633,7 +633,7 @@ MODULE_DEVICE_TABLE(of, sf_pdma_dt_ids);
static struct platform_driver sf_pdma_driver = {
.probe = sf_pdma_probe,
- .remove_new = sf_pdma_remove,
+ .remove = sf_pdma_remove,
.driver = {
.name = "sf-pdma",
.of_match_table = sf_pdma_dt_ids,
diff --git a/drivers/dma/sh/Kconfig b/drivers/dma/sh/Kconfig
index c0b2997ab7fd..6ea5a880b433 100644
--- a/drivers/dma/sh/Kconfig
+++ b/drivers/dma/sh/Kconfig
@@ -49,10 +49,10 @@ config RENESAS_USB_DMAC
SoCs.
config RZ_DMAC
- tristate "Renesas RZ/{G2L,V2L} DMA Controller"
- depends on ARCH_RZG2L || COMPILE_TEST
+ tristate "Renesas RZ DMA Controller"
+ depends on ARCH_R7S72100 || ARCH_RZG2L || COMPILE_TEST
select RENESAS_DMA
select DMA_VIRTUAL_CHANNELS
help
- This driver supports the general purpose DMA controller found in the
- Renesas RZ/{G2L,V2L} SoC variants.
+ This driver supports the general purpose DMA controller typically
+ found in the Renesas RZ SoC variants.
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 1094a2f82164..2679c1f09faf 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -2037,7 +2037,7 @@ static struct platform_driver rcar_dmac_driver = {
.of_match_table = rcar_dmac_of_ids,
},
.probe = rcar_dmac_probe,
- .remove_new = rcar_dmac_remove,
+ .remove = rcar_dmac_remove,
.shutdown = rcar_dmac_shutdown,
};
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index 811389fc9cb8..9235db551026 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -893,7 +893,7 @@ static int rz_dmac_probe(struct platform_device *pdev)
/* Initialize the channels. */
INIT_LIST_HEAD(&dmac->engine.channels);
- dmac->rstc = devm_reset_control_array_get_exclusive(&pdev->dev);
+ dmac->rstc = devm_reset_control_array_get_optional_exclusive(&pdev->dev);
if (IS_ERR(dmac->rstc))
return dev_err_probe(&pdev->dev, PTR_ERR(dmac->rstc),
"failed to get resets\n");
@@ -1004,7 +1004,7 @@ static struct platform_driver rz_dmac_driver = {
.of_match_table = of_rz_dmac_match,
},
.probe = rz_dmac_probe,
- .remove_new = rz_dmac_remove,
+ .remove = rz_dmac_remove,
};
module_platform_driver(rz_dmac_driver);
diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index 588c5f409a80..fdd41e1c2263 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -961,7 +961,7 @@ void shdma_chan_probe(struct shdma_dev *sdev,
spin_lock_init(&schan->chan_lock);
- /* Init descripter manage list */
+ /* Init descriptor manage list */
INIT_LIST_HEAD(&schan->ld_queue);
INIT_LIST_HEAD(&schan->ld_free);
diff --git a/drivers/dma/sh/shdmac.c b/drivers/dma/sh/shdmac.c
index 8ead0a1fd237..093e449e19ee 100644
--- a/drivers/dma/sh/shdmac.c
+++ b/drivers/dma/sh/shdmac.c
@@ -906,7 +906,7 @@ static struct platform_driver sh_dmae_driver = {
.pm = &sh_dmae_pm,
.name = SH_DMAE_DRV_NAME,
},
- .remove_new = sh_dmae_remove,
+ .remove = sh_dmae_remove,
};
static int __init sh_dmae_init(void)
diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c
index f7cd0cad056c..7e2b6c97fa2f 100644
--- a/drivers/dma/sh/usb-dmac.c
+++ b/drivers/dma/sh/usb-dmac.c
@@ -301,7 +301,7 @@ static struct usb_dmac_desc *usb_dmac_desc_get(struct usb_dmac_chan *chan,
struct usb_dmac_desc *desc = NULL;
unsigned long flags;
- /* Get a freed descritpor */
+ /* Get a freed descriptor */
spin_lock_irqsave(&chan->vc.lock, flags);
list_for_each_entry(desc, &chan->desc_freed, node) {
if (sg_len <= desc->sg_allocated_len) {
@@ -899,7 +899,7 @@ static struct platform_driver usb_dmac_driver = {
.of_match_table = usb_dmac_of_ids,
},
.probe = usb_dmac_probe,
- .remove_new = usb_dmac_remove,
+ .remove = usb_dmac_remove,
.shutdown = usb_dmac_shutdown,
};
diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c
index 3f54ff37c5e0..187a090463ce 100644
--- a/drivers/dma/sprd-dma.c
+++ b/drivers/dma/sprd-dma.c
@@ -1298,7 +1298,7 @@ static const struct dev_pm_ops sprd_dma_pm_ops = {
static struct platform_driver sprd_dma_driver = {
.probe = sprd_dma_probe,
- .remove_new = sprd_dma_remove,
+ .remove = sprd_dma_remove,
.driver = {
.name = "sprd-dma",
.of_match_table = sprd_dma_match,
diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c
index 8880b5e336f8..c65ee0c7bfbd 100644
--- a/drivers/dma/st_fdma.c
+++ b/drivers/dma/st_fdma.c
@@ -858,7 +858,7 @@ static struct platform_driver st_fdma_platform_driver = {
.of_match_table = st_fdma_match,
},
.probe = st_fdma_probe,
- .remove_new = st_fdma_remove,
+ .remove = st_fdma_remove,
};
module_platform_driver(st_fdma_platform_driver);
diff --git a/drivers/dma/stm32/stm32-dma3.c b/drivers/dma/stm32/stm32-dma3.c
index 0be6e944df6f..0c6c4258b195 100644
--- a/drivers/dma/stm32/stm32-dma3.c
+++ b/drivers/dma/stm32/stm32-dma3.c
@@ -221,6 +221,8 @@ enum stm32_dma3_port_data_width {
#define STM32_DMA3_DT_BREQ BIT(8) /* CTR2_BREQ */
#define STM32_DMA3_DT_PFREQ BIT(9) /* CTR2_PFREQ */
#define STM32_DMA3_DT_TCEM GENMASK(13, 12) /* CTR2_TCEM */
+#define STM32_DMA3_DT_NOPACK BIT(16) /* CTR1_PAM */
+#define STM32_DMA3_DT_NOREFACT BIT(17)
/* struct stm32_dma3_chan .config_set bitfield */
#define STM32_DMA3_CFG_SET_DT BIT(0)
@@ -228,6 +230,8 @@ enum stm32_dma3_port_data_width {
#define STM32_DMA3_CFG_SET_BOTH (STM32_DMA3_CFG_SET_DT | STM32_DMA3_CFG_SET_DMA)
#define STM32_DMA3_MAX_BLOCK_SIZE ALIGN_DOWN(CBR1_BNDT, 64)
+#define STM32_DMA3_MAX_BURST_LEN (1 + min_t(u32, FIELD_MAX(CTR1_SBL_1), \
+ FIELD_MAX(CTR1_DBL_1)))
#define port_is_ahb(maxdw) ({ typeof(maxdw) (_maxdw) = (maxdw); \
((_maxdw) != DW_INVALID) && ((_maxdw) == DW_32); })
#define port_is_axi(maxdw) ({ typeof(maxdw) (_maxdw) = (maxdw); \
@@ -293,6 +297,10 @@ struct stm32_dma3_chan {
u32 dma_status;
};
+struct stm32_dma3_pdata {
+ u32 axi_max_burst_len;
+};
+
struct stm32_dma3_ddata {
struct dma_device dma_dev;
void __iomem *base;
@@ -301,6 +309,7 @@ struct stm32_dma3_ddata {
u32 dma_channels;
u32 dma_requests;
enum stm32_dma3_port_data_width ports_max_dw[2];
+ u32 axi_max_burst_len;
};
static inline struct stm32_dma3_ddata *to_stm32_dma3_ddata(struct stm32_dma3_chan *chan)
@@ -533,7 +542,8 @@ static enum dma_slave_buswidth stm32_dma3_get_max_dw(u32 chan_max_burst,
return 1 << __ffs(len | addr | max_dw);
}
-static u32 stm32_dma3_get_max_burst(u32 len, enum dma_slave_buswidth dw, u32 chan_max_burst)
+static u32 stm32_dma3_get_max_burst(u32 len, enum dma_slave_buswidth dw,
+ u32 chan_max_burst, u32 bus_max_burst)
{
u32 max_burst = chan_max_burst ? chan_max_burst / dw : 1;
@@ -544,8 +554,9 @@ static u32 stm32_dma3_get_max_burst(u32 len, enum dma_slave_buswidth dw, u32 cha
/*
* HW doesn't modify the burst if burst size <= half of the fifo size.
* If len is not a multiple of burst size, last burst is shortened by HW.
+ * Take care of maximum burst supported on interconnect bus.
*/
- return max_burst;
+ return min_t(u32, max_burst, bus_max_burst);
}
static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transfer_direction dir,
@@ -554,6 +565,7 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
{
struct stm32_dma3_ddata *ddata = to_stm32_dma3_ddata(chan);
struct dma_device dma_device = ddata->dma_dev;
+ u32 src_max_burst = STM32_DMA3_MAX_BURST_LEN, dst_max_burst = STM32_DMA3_MAX_BURST_LEN;
u32 sdw, ddw, sbl_max, dbl_max, tcem, init_dw, init_bl_max;
u32 _ctr1 = 0, _ctr2 = 0;
u32 ch_conf = chan->dt_config.ch_conf;
@@ -594,10 +606,14 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
_ctr1 |= CTR1_SINC;
if (sap)
_ctr1 |= CTR1_SAP;
+ if (port_is_axi(sap_max_dw)) /* AXI - apply axi maximum burst limitation */
+ src_max_burst = ddata->axi_max_burst_len;
if (FIELD_GET(STM32_DMA3_DT_DINC, tr_conf))
_ctr1 |= CTR1_DINC;
if (dap)
_ctr1 |= CTR1_DAP;
+ if (port_is_axi(dap_max_dw)) /* AXI - apply axi maximum burst limitation */
+ dst_max_burst = ddata->axi_max_burst_len;
_ctr2 |= FIELD_PREP(CTR2_REQSEL, chan->dt_config.req_line) & ~CTR2_SWREQ;
if (FIELD_GET(STM32_DMA3_DT_BREQ, tr_conf))
@@ -617,11 +633,16 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
/* Set destination (device) data width and burst */
ddw = min_t(u32, ddw, stm32_dma3_get_max_dw(chan->max_burst, dap_max_dw,
len, dst_addr));
- dbl_max = min_t(u32, dbl_max, stm32_dma3_get_max_burst(len, ddw, chan->max_burst));
+ dbl_max = min_t(u32, dbl_max, stm32_dma3_get_max_burst(len, ddw, chan->max_burst,
+ dst_max_burst));
/* Set source (memory) data width and burst */
sdw = stm32_dma3_get_max_dw(chan->max_burst, sap_max_dw, len, src_addr);
- sbl_max = stm32_dma3_get_max_burst(len, sdw, chan->max_burst);
+ sbl_max = stm32_dma3_get_max_burst(len, sdw, chan->max_burst, src_max_burst);
+ if (!!FIELD_GET(STM32_DMA3_DT_NOPACK, tr_conf)) {
+ sdw = ddw;
+ sbl_max = dbl_max;
+ }
_ctr1 |= FIELD_PREP(CTR1_SDW_LOG2, ilog2(sdw));
_ctr1 |= FIELD_PREP(CTR1_SBL_1, sbl_max - 1);
@@ -647,11 +668,17 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
/* Set source (device) data width and burst */
sdw = min_t(u32, sdw, stm32_dma3_get_max_dw(chan->max_burst, sap_max_dw,
len, src_addr));
- sbl_max = min_t(u32, sbl_max, stm32_dma3_get_max_burst(len, sdw, chan->max_burst));
+ sbl_max = min_t(u32, sbl_max, stm32_dma3_get_max_burst(len, sdw, chan->max_burst,
+ src_max_burst));
/* Set destination (memory) data width and burst */
ddw = stm32_dma3_get_max_dw(chan->max_burst, dap_max_dw, len, dst_addr);
- dbl_max = stm32_dma3_get_max_burst(len, ddw, chan->max_burst);
+ dbl_max = stm32_dma3_get_max_burst(len, ddw, chan->max_burst, dst_max_burst);
+ if (!!FIELD_GET(STM32_DMA3_DT_NOPACK, tr_conf) ||
+ ((_ctr2 & CTR2_PFREQ) && ddw > sdw)) { /* Packing to wider ddw not supported */
+ ddw = sdw;
+ dbl_max = sbl_max;
+ }
_ctr1 |= FIELD_PREP(CTR1_SDW_LOG2, ilog2(sdw));
_ctr1 |= FIELD_PREP(CTR1_SBL_1, sbl_max - 1);
@@ -678,22 +705,24 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
init_dw = sdw;
init_bl_max = sbl_max;
sdw = stm32_dma3_get_max_dw(chan->max_burst, sap_max_dw, len, src_addr);
- sbl_max = stm32_dma3_get_max_burst(len, sdw, chan->max_burst);
+ sbl_max = stm32_dma3_get_max_burst(len, sdw, chan->max_burst, src_max_burst);
if (chan->config_set & STM32_DMA3_CFG_SET_DMA) {
sdw = min_t(u32, init_dw, sdw);
- sbl_max = min_t(u32, init_bl_max,
- stm32_dma3_get_max_burst(len, sdw, chan->max_burst));
+ sbl_max = min_t(u32, init_bl_max, stm32_dma3_get_max_burst(len, sdw,
+ chan->max_burst,
+ src_max_burst));
}
/* Set destination (memory) data width and burst */
init_dw = ddw;
init_bl_max = dbl_max;
ddw = stm32_dma3_get_max_dw(chan->max_burst, dap_max_dw, len, dst_addr);
- dbl_max = stm32_dma3_get_max_burst(len, ddw, chan->max_burst);
+ dbl_max = stm32_dma3_get_max_burst(len, ddw, chan->max_burst, dst_max_burst);
if (chan->config_set & STM32_DMA3_CFG_SET_DMA) {
ddw = min_t(u32, init_dw, ddw);
- dbl_max = min_t(u32, init_bl_max,
- stm32_dma3_get_max_burst(len, ddw, chan->max_burst));
+ dbl_max = min_t(u32, init_bl_max, stm32_dma3_get_max_burst(len, ddw,
+ chan->max_burst,
+ dst_max_burst));
}
_ctr1 |= FIELD_PREP(CTR1_SDW_LOG2, ilog2(sdw));
@@ -1116,6 +1145,28 @@ static void stm32_dma3_free_chan_resources(struct dma_chan *c)
chan->config_set = 0;
}
+static u32 stm32_dma3_get_ll_count(struct stm32_dma3_chan *chan, size_t len, bool prevent_refactor)
+{
+ u32 count;
+
+ if (prevent_refactor)
+ return DIV_ROUND_UP(len, STM32_DMA3_MAX_BLOCK_SIZE);
+
+ count = len / STM32_DMA3_MAX_BLOCK_SIZE;
+ len -= (len / STM32_DMA3_MAX_BLOCK_SIZE) * STM32_DMA3_MAX_BLOCK_SIZE;
+
+ if (len >= chan->max_burst) {
+ count += 1; /* len < STM32_DMA3_MAX_BLOCK_SIZE here, so it fits in one item */
+ len -= (len / chan->max_burst) * chan->max_burst;
+ }
+
+ /* Unaligned remainder fits in one extra item */
+ if (len > 0)
+ count += 1;
+
+ return count;
+}
+
static void stm32_dma3_init_chan_config_for_memcpy(struct stm32_dma3_chan *chan,
dma_addr_t dst, dma_addr_t src)
{
@@ -1150,8 +1201,10 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_dma_memcpy(struct dma_cha
struct stm32_dma3_swdesc *swdesc;
size_t next_size, offset;
u32 count, i, ctr1, ctr2;
+ bool prevent_refactor = !!FIELD_GET(STM32_DMA3_DT_NOPACK, chan->dt_config.tr_conf) ||
+ !!FIELD_GET(STM32_DMA3_DT_NOREFACT, chan->dt_config.tr_conf);
- count = DIV_ROUND_UP(len, STM32_DMA3_MAX_BLOCK_SIZE);
+ count = stm32_dma3_get_ll_count(chan, len, prevent_refactor);
swdesc = stm32_dma3_chan_desc_alloc(chan, count);
if (!swdesc)
@@ -1167,6 +1220,10 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_dma_memcpy(struct dma_cha
remaining = len - offset;
next_size = min_t(size_t, remaining, STM32_DMA3_MAX_BLOCK_SIZE);
+ if (!prevent_refactor &&
+ (next_size < STM32_DMA3_MAX_BLOCK_SIZE && next_size >= chan->max_burst))
+ next_size = chan->max_burst * (remaining / chan->max_burst);
+
ret = stm32_dma3_chan_prep_hw(chan, DMA_MEM_TO_MEM, &swdesc->ccr, &ctr1, &ctr2,
src + offset, dst + offset, next_size);
if (ret)
@@ -1203,14 +1260,13 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_slave_sg(struct dma_chan
size_t len;
dma_addr_t sg_addr, dev_addr, src, dst;
u32 i, j, count, ctr1, ctr2;
+ bool prevent_refactor = !!FIELD_GET(STM32_DMA3_DT_NOPACK, chan->dt_config.tr_conf) ||
+ !!FIELD_GET(STM32_DMA3_DT_NOREFACT, chan->dt_config.tr_conf);
int ret;
- count = sg_len;
- for_each_sg(sgl, sg, sg_len, i) {
- len = sg_dma_len(sg);
- if (len > STM32_DMA3_MAX_BLOCK_SIZE)
- count += DIV_ROUND_UP(len, STM32_DMA3_MAX_BLOCK_SIZE) - 1;
- }
+ count = 0;
+ for_each_sg(sgl, sg, sg_len, i)
+ count += stm32_dma3_get_ll_count(chan, sg_dma_len(sg), prevent_refactor);
swdesc = stm32_dma3_chan_desc_alloc(chan, count);
if (!swdesc)
@@ -1227,6 +1283,10 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_slave_sg(struct dma_chan
do {
size_t chunk = min_t(size_t, len, STM32_DMA3_MAX_BLOCK_SIZE);
+ if (!prevent_refactor &&
+ (chunk < STM32_DMA3_MAX_BLOCK_SIZE && chunk >= chan->max_burst))
+ chunk = chan->max_burst * (len / chan->max_burst);
+
if (dir == DMA_MEM_TO_DEV) {
src = sg_addr;
dst = dev_addr;
@@ -1259,6 +1319,10 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_slave_sg(struct dma_chan
} while (len);
}
+ if (count != sg_len && chan->tcem != CTR2_TCEM_CHANNEL)
+ dev_warn(chan2dev(chan), "Linked-list refactored, %d items instead of %d\n",
+ count, sg_len);
+
/* Enable Error interrupts */
swdesc->ccr |= CCR_USEIE | CCR_ULEIE | CCR_DTEIE;
/* Enable Transfer state interrupts */
@@ -1601,8 +1665,12 @@ static u32 stm32_dma3_check_rif(struct stm32_dma3_ddata *ddata)
return chan_reserved;
}
+static struct stm32_dma3_pdata stm32mp25_pdata = {
+ .axi_max_burst_len = 16,
+};
+
static const struct of_device_id stm32_dma3_of_match[] = {
- { .compatible = "st,stm32mp25-dma3", },
+ { .compatible = "st,stm32mp25-dma3", .data = &stm32mp25_pdata, },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, stm32_dma3_of_match);
@@ -1610,6 +1678,7 @@ MODULE_DEVICE_TABLE(of, stm32_dma3_of_match);
static int stm32_dma3_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
+ const struct stm32_dma3_pdata *pdata;
struct stm32_dma3_ddata *ddata;
struct reset_control *reset;
struct stm32_dma3_chan *chan;
@@ -1704,6 +1773,16 @@ static int stm32_dma3_probe(struct platform_device *pdev)
else /* Dual master ports */
ddata->ports_max_dw[1] = FIELD_GET(G_M1_DATA_WIDTH_ENC, hwcfgr);
+ /* axi_max_burst_len is optional, if not defined, use STM32_DMA3_MAX_BURST_LEN */
+ ddata->axi_max_burst_len = STM32_DMA3_MAX_BURST_LEN;
+ pdata = device_get_match_data(&pdev->dev);
+ if (pdata && pdata->axi_max_burst_len) {
+ ddata->axi_max_burst_len = min_t(u32, pdata->axi_max_burst_len,
+ STM32_DMA3_MAX_BURST_LEN);
+ dev_dbg(&pdev->dev, "Burst is limited to %u beats through AXI port\n",
+ ddata->axi_max_burst_len);
+ }
+
ddata->chans = devm_kcalloc(&pdev->dev, ddata->dma_channels, sizeof(*ddata->chans),
GFP_KERNEL);
if (!ddata->chans) {
@@ -1827,7 +1906,7 @@ static const struct dev_pm_ops stm32_dma3_pm_ops = {
static struct platform_driver stm32_dma3_driver = {
.probe = stm32_dma3_probe,
- .remove_new = stm32_dma3_remove,
+ .remove = stm32_dma3_remove,
.driver = {
.name = "stm32-dma3",
.of_match_table = stm32_dma3_of_match,
diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
index 2e7f9b07fdd2..f37cdf6f2179 100644
--- a/drivers/dma/sun4i-dma.c
+++ b/drivers/dma/sun4i-dma.c
@@ -1292,7 +1292,7 @@ MODULE_DEVICE_TABLE(of, sun4i_dma_match);
static struct platform_driver sun4i_dma_driver = {
.probe = sun4i_dma_probe,
- .remove_new = sun4i_dma_remove,
+ .remove = sun4i_dma_remove,
.driver = {
.name = "sun4i-dma",
.of_match_table = sun4i_dma_match,
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 583bf49031cf..95ecb12caaa5 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -1488,7 +1488,7 @@ static void sun6i_dma_remove(struct platform_device *pdev)
static struct platform_driver sun6i_dma_driver = {
.probe = sun6i_dma_probe,
- .remove_new = sun6i_dma_remove,
+ .remove = sun6i_dma_remove,
.driver = {
.name = "sun6i-dma",
.of_match_table = sun6i_dma_match,
diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index 3642508e88bb..cacf3757adc2 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -1532,7 +1532,7 @@ static struct platform_driver tegra_dma_driver = {
.of_match_table = tegra_dma_of_match,
},
.probe = tegra_dma_probe,
- .remove_new = tegra_dma_remove,
+ .remove = tegra_dma_remove,
};
module_platform_driver(tegra_dma_driver);
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index 7d1acda2d72b..14a61e53a41b 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -1675,7 +1675,7 @@ static struct platform_driver tegra_dmac_driver = {
.of_match_table = tegra_dma_of_match,
},
.probe = tegra_dma_probe,
- .remove_new = tegra_dma_remove,
+ .remove = tegra_dma_remove,
};
module_platform_driver(tegra_dmac_driver);
diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index 24ad7077c53b..2953008d42ef 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -1008,7 +1008,7 @@ static struct platform_driver tegra_admac_driver = {
.of_match_table = tegra_adma_of_match,
},
.probe = tegra_adma_probe,
- .remove_new = tegra_adma_remove,
+ .remove = tegra_adma_remove,
};
module_platform_driver(tegra_admac_driver);
diff --git a/drivers/dma/ti/cppi41.c b/drivers/dma/ti/cppi41.c
index a8bb70c2d109..8d8c3d6038fc 100644
--- a/drivers/dma/ti/cppi41.c
+++ b/drivers/dma/ti/cppi41.c
@@ -1243,7 +1243,7 @@ static const struct dev_pm_ops cppi41_pm_ops = {
static struct platform_driver cpp41_dma_driver = {
.probe = cppi41_dma_probe,
- .remove_new = cppi41_dma_remove,
+ .remove = cppi41_dma_remove,
.driver = {
.name = "cppi41-dma-engine",
.pm = &cppi41_pm_ops,
diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c
index 5f8d2e93ff3f..343e986e66e7 100644
--- a/drivers/dma/ti/edma.c
+++ b/drivers/dma/ti/edma.c
@@ -2636,7 +2636,7 @@ static const struct dev_pm_ops edma_pm_ops = {
static struct platform_driver edma_driver = {
.probe = edma_probe,
- .remove_new = edma_remove,
+ .remove = edma_remove,
.driver = {
.name = "edma",
.pm = &edma_pm_ops,
diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c
index 6ab9bfbdc480..8c023c6e623a 100644
--- a/drivers/dma/ti/omap-dma.c
+++ b/drivers/dma/ti/omap-dma.c
@@ -1915,7 +1915,7 @@ MODULE_DEVICE_TABLE(of, omap_dma_match);
static struct platform_driver omap_dma_driver = {
.probe = omap_dma_probe,
- .remove_new = omap_dma_remove,
+ .remove = omap_dma_remove,
.driver = {
.name = "omap-dma-engine",
.of_match_table = omap_dma_match,
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index 7410025605e0..ecaf002558af 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -761,7 +761,7 @@ static struct platform_driver td_driver = {
.name = DRIVER_NAME,
},
.probe = td_probe,
- .remove_new = td_remove,
+ .remove = td_remove,
};
module_platform_driver(td_driver);
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index 44ba377b4b5a..35d5221683b2 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -1260,14 +1260,14 @@ static const struct dev_pm_ops txx9dmac_dev_pm_ops = {
};
static struct platform_driver txx9dmac_chan_driver = {
- .remove_new = txx9dmac_chan_remove,
+ .remove = txx9dmac_chan_remove,
.driver = {
.name = "txx9dmac-chan",
},
};
static struct platform_driver txx9dmac_driver = {
- .remove_new = txx9dmac_remove,
+ .remove = txx9dmac_remove,
.shutdown = txx9dmac_shutdown,
.driver = {
.name = "txx9dmac",
diff --git a/drivers/dma/uniphier-mdmac.c b/drivers/dma/uniphier-mdmac.c
index ad7125f6e2ca..7a99f86ecb5a 100644
--- a/drivers/dma/uniphier-mdmac.c
+++ b/drivers/dma/uniphier-mdmac.c
@@ -493,7 +493,7 @@ MODULE_DEVICE_TABLE(of, uniphier_mdmac_match);
static struct platform_driver uniphier_mdmac_driver = {
.probe = uniphier_mdmac_probe,
- .remove_new = uniphier_mdmac_remove,
+ .remove = uniphier_mdmac_remove,
.driver = {
.name = "uniphier-mio-dmac",
.of_match_table = uniphier_mdmac_match,
diff --git a/drivers/dma/uniphier-xdmac.c b/drivers/dma/uniphier-xdmac.c
index 3ce2dc2ad9de..ceeb6171c9d1 100644
--- a/drivers/dma/uniphier-xdmac.c
+++ b/drivers/dma/uniphier-xdmac.c
@@ -603,7 +603,7 @@ MODULE_DEVICE_TABLE(of, uniphier_xdmac_match);
static struct platform_driver uniphier_xdmac_driver = {
.probe = uniphier_xdmac_probe,
- .remove_new = uniphier_xdmac_remove,
+ .remove = uniphier_xdmac_remove,
.driver = {
.name = "uniphier-xdmac",
.of_match_table = uniphier_xdmac_match,
diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c
index 275848a9c450..f64624ea44ad 100644
--- a/drivers/dma/xgene-dma.c
+++ b/drivers/dma/xgene-dma.c
@@ -1815,7 +1815,7 @@ MODULE_DEVICE_TABLE(of, xgene_dma_of_match_ptr);
static struct platform_driver xgene_dma_driver = {
.probe = xgene_dma_probe,
- .remove_new = xgene_dma_remove,
+ .remove = xgene_dma_remove,
.driver = {
.name = "X-Gene-DMA",
.of_match_table = xgene_dma_of_match_ptr,
diff --git a/drivers/dma/xilinx/xdma.c b/drivers/dma/xilinx/xdma.c
index 718842fdaf98..93772abc3b49 100644
--- a/drivers/dma/xilinx/xdma.c
+++ b/drivers/dma/xilinx/xdma.c
@@ -1315,7 +1315,7 @@ static struct platform_driver xdma_driver = {
},
.id_table = xdma_id_table,
.probe = xdma_probe,
- .remove_new = xdma_remove,
+ .remove = xdma_remove,
};
module_platform_driver(xdma_driver);
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 5eb51ae93e89..1bdd57de87a6 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -3271,7 +3271,7 @@ static struct platform_driver xilinx_vdma_driver = {
.of_match_table = xilinx_dma_of_ids,
},
.probe = xilinx_dma_probe,
- .remove_new = xilinx_dma_remove,
+ .remove = xilinx_dma_remove,
};
module_platform_driver(xilinx_vdma_driver);
diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c
index be87764af9e8..ee5d9fdbfd7f 100644
--- a/drivers/dma/xilinx/xilinx_dpdma.c
+++ b/drivers/dma/xilinx/xilinx_dpdma.c
@@ -1863,7 +1863,7 @@ MODULE_DEVICE_TABLE(of, xilinx_dpdma_of_match);
static struct platform_driver xilinx_dpdma_driver = {
.probe = xilinx_dpdma_probe,
- .remove_new = xilinx_dpdma_remove,
+ .remove = xilinx_dpdma_remove,
.driver = {
.name = "xilinx-zynqmp-dpdma",
.of_match_table = xilinx_dpdma_of_match,
diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
index 9ae46f1198fe..d05fc5fcc77d 100644
--- a/drivers/dma/xilinx/zynqmp_dma.c
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -366,7 +366,7 @@ static void zynqmp_dma_init(struct zynqmp_dma_chan *chan)
}
writel(val, chan->regs + ZYNQMP_DMA_DATA_ATTR);
- /* Clearing the interrupt account rgisters */
+ /* Clearing the interrupt account registers */
val = readl(chan->regs + ZYNQMP_DMA_IRQ_SRC_ACCT);
val = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
@@ -1192,7 +1192,7 @@ static struct platform_driver zynqmp_dma_driver = {
.pm = &zynqmp_dma_dev_pm_ops,
},
.probe = zynqmp_dma_probe,
- .remove_new = zynqmp_dma_remove,
+ .remove = zynqmp_dma_remove,
};
module_platform_driver(zynqmp_dma_driver);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 1f53ca1f87e3..1b5fb2c4ce86 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -3333,7 +3333,7 @@ static struct platform_driver scmi_driver = {
.dev_groups = versions_groups,
},
.probe = scmi_probe,
- .remove_new = scmi_remove,
+ .remove = scmi_remove,
};
static struct dentry *scmi_debugfs_init(void)
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index f4d47577f83e..87c323de17b9 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -1049,7 +1049,7 @@ static struct platform_driver scpi_driver = {
.dev_groups = versions_groups,
},
.probe = scpi_probe,
- .remove_new = scpi_remove,
+ .remove = scpi_remove,
};
module_platform_driver(scpi_driver);
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c
index 208652a8087c..882db32e51be 100644
--- a/drivers/firmware/google/coreboot_table.c
+++ b/drivers/firmware/google/coreboot_table.c
@@ -220,7 +220,7 @@ MODULE_DEVICE_TABLE(of, coreboot_of_match);
static struct platform_driver coreboot_table_driver = {
.probe = coreboot_table_probe,
- .remove_new = coreboot_table_remove,
+ .remove = coreboot_table_remove,
.driver = {
.name = "coreboot_table",
.acpi_match_table = ACPI_PTR(cros_coreboot_acpi_match),
diff --git a/drivers/firmware/imx/imx-dsp.c b/drivers/firmware/imx/imx-dsp.c
index 01c8ef14eaec..ed79e823157a 100644
--- a/drivers/firmware/imx/imx-dsp.c
+++ b/drivers/firmware/imx/imx-dsp.c
@@ -180,7 +180,7 @@ static struct platform_driver imx_dsp_driver = {
.name = "imx-dsp",
},
.probe = imx_dsp_probe,
- .remove_new = imx_dsp_remove,
+ .remove = imx_dsp_remove,
};
builtin_platform_driver(imx_dsp_driver);
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 8e59be3782cb..55b9cfad8a04 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -116,7 +116,7 @@ static void __meminit release_firmware_map_entry(struct kobject *kobj)
kfree(entry);
}
-static struct kobj_type __refdata memmap_ktype = {
+static const struct kobj_type memmap_ktype = {
.release = release_firmware_map_entry,
.sysfs_ops = &memmap_attr_ops,
.default_groups = def_groups,
diff --git a/drivers/firmware/microchip/mpfs-auto-update.c b/drivers/firmware/microchip/mpfs-auto-update.c
index 0f7ec8848202..38a03698cec9 100644
--- a/drivers/firmware/microchip/mpfs-auto-update.c
+++ b/drivers/firmware/microchip/mpfs-auto-update.c
@@ -458,7 +458,7 @@ static struct platform_driver mpfs_auto_update_driver = {
.name = "mpfs-auto-update",
},
.probe = mpfs_auto_update_probe,
- .remove_new = mpfs_auto_update_remove,
+ .remove = mpfs_auto_update_remove,
};
module_platform_driver(mpfs_auto_update_driver);
diff --git a/drivers/firmware/mtk-adsp-ipc.c b/drivers/firmware/mtk-adsp-ipc.c
index a762302978de..2b79371c61c9 100644
--- a/drivers/firmware/mtk-adsp-ipc.c
+++ b/drivers/firmware/mtk-adsp-ipc.c
@@ -95,10 +95,9 @@ static int mtk_adsp_ipc_probe(struct platform_device *pdev)
adsp_chan->idx = i;
adsp_chan->ch = mbox_request_channel_byname(cl, adsp_mbox_ch_names[i]);
if (IS_ERR(adsp_chan->ch)) {
- ret = PTR_ERR(adsp_chan->ch);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "Failed to request mbox chan %s ret %d\n",
- adsp_mbox_ch_names[i], ret);
+ ret = dev_err_probe(dev, PTR_ERR(adsp_chan->ch),
+ "Failed to request mbox channel %s\n",
+ adsp_mbox_ch_names[i]);
for (j = 0; j < i; j++) {
adsp_chan = &adsp_ipc->chans[j];
@@ -133,7 +132,7 @@ static struct platform_driver mtk_adsp_ipc_driver = {
.name = "mtk-adsp-ipc",
},
.probe = mtk_adsp_ipc_probe,
- .remove_new = mtk_adsp_ipc_remove,
+ .remove = mtk_adsp_ipc_remove,
};
builtin_platform_driver(mtk_adsp_ipc_driver);
diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index 85c525745b31..d58da3e4500a 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -757,7 +757,7 @@ MODULE_DEVICE_TABLE(acpi, fw_cfg_sysfs_acpi_match);
static struct platform_driver fw_cfg_sysfs_driver = {
.probe = fw_cfg_sysfs_probe,
- .remove_new = fw_cfg_sysfs_remove,
+ .remove = fw_cfg_sysfs_remove,
.driver = {
.name = "fw_cfg",
.of_match_table = fw_cfg_sysfs_mmio_match,
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 18cc34987108..7ecde6921a0a 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -406,7 +406,7 @@ static struct platform_driver rpi_firmware_driver = {
},
.probe = rpi_firmware_probe,
.shutdown = rpi_firmware_shutdown,
- .remove_new = rpi_firmware_remove,
+ .remove = rpi_firmware_remove,
};
module_platform_driver(rpi_firmware_driver);
diff --git a/drivers/firmware/stratix10-rsu.c b/drivers/firmware/stratix10-rsu.c
index e20cee9c2d32..1ea39a0a76c7 100644
--- a/drivers/firmware/stratix10-rsu.c
+++ b/drivers/firmware/stratix10-rsu.c
@@ -802,7 +802,7 @@ static void stratix10_rsu_remove(struct platform_device *pdev)
static struct platform_driver stratix10_rsu_driver = {
.probe = stratix10_rsu_probe,
- .remove_new = stratix10_rsu_remove,
+ .remove = stratix10_rsu_remove,
.driver = {
.name = "stratix10-rsu",
.dev_groups = rsu_groups,
diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c
index 528f37417aea..c5c78b869561 100644
--- a/drivers/firmware/stratix10-svc.c
+++ b/drivers/firmware/stratix10-svc.c
@@ -1271,7 +1271,7 @@ static void stratix10_svc_drv_remove(struct platform_device *pdev)
static struct platform_driver stratix10_svc_driver = {
.probe = stratix10_svc_drv_probe,
- .remove_new = stratix10_svc_drv_remove,
+ .remove = stratix10_svc_drv_remove,
.driver = {
.name = "stratix10-svc",
.of_match_table = stratix10_svc_drv_match,
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index cdb565c41119..720fa8b5d8e9 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -2118,6 +2118,6 @@ static struct platform_driver zynqmp_firmware_driver = {
.dev_groups = zynqmp_firmware_groups,
},
.probe = zynqmp_firmware_probe,
- .remove_new = zynqmp_firmware_remove,
+ .remove = zynqmp_firmware_remove,
};
module_platform_driver(zynqmp_firmware_driver);
diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c
index f4de3fea0b2d..e41492988dd6 100644
--- a/drivers/fpga/altera-fpga2sdram.c
+++ b/drivers/fpga/altera-fpga2sdram.c
@@ -152,7 +152,7 @@ MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
static struct platform_driver altera_fpga_driver = {
.probe = alt_fpga_bridge_probe,
- .remove_new = alt_fpga_bridge_remove,
+ .remove = alt_fpga_bridge_remove,
.driver = {
.name = "altera_fpga2sdram_bridge",
.of_match_table = of_match_ptr(altera_fpga_of_match),
diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c
index 44061cb16f87..594693ff786e 100644
--- a/drivers/fpga/altera-freeze-bridge.c
+++ b/drivers/fpga/altera-freeze-bridge.c
@@ -262,7 +262,7 @@ static void altera_freeze_br_remove(struct platform_device *pdev)
static struct platform_driver altera_freeze_br_driver = {
.probe = altera_freeze_br_probe,
- .remove_new = altera_freeze_br_remove,
+ .remove = altera_freeze_br_remove,
.driver = {
.name = "altera_freeze_br",
.of_match_table = altera_freeze_br_of_match,
diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c
index 6f8e24be19c6..f2f1250689cb 100644
--- a/drivers/fpga/altera-hps2fpga.c
+++ b/drivers/fpga/altera-hps2fpga.c
@@ -205,7 +205,7 @@ MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
static struct platform_driver alt_fpga_bridge_driver = {
.probe = alt_fpga_bridge_probe,
- .remove_new = alt_fpga_bridge_remove,
+ .remove = alt_fpga_bridge_remove,
.driver = {
.name = "altera_hps2fpga_bridge",
.of_match_table = of_match_ptr(altera_fpga_of_match),
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 6b97c073849e..2fd4f07ed081 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -947,12 +947,12 @@ static const struct attribute_group *afu_dev_groups[] = {
};
static struct platform_driver afu_driver = {
- .driver = {
- .name = DFL_FPGA_FEATURE_DEV_PORT,
+ .driver = {
+ .name = DFL_FPGA_FEATURE_DEV_PORT,
.dev_groups = afu_dev_groups,
},
- .probe = afu_probe,
- .remove_new = afu_remove,
+ .probe = afu_probe,
+ .remove = afu_remove,
};
static int __init afu_init(void)
diff --git a/drivers/fpga/dfl-fme-br.c b/drivers/fpga/dfl-fme-br.c
index 0b01b3895277..950c606c59d4 100644
--- a/drivers/fpga/dfl-fme-br.c
+++ b/drivers/fpga/dfl-fme-br.c
@@ -92,11 +92,11 @@ static void fme_br_remove(struct platform_device *pdev)
}
static struct platform_driver fme_br_driver = {
- .driver = {
- .name = DFL_FPGA_FME_BRIDGE,
+ .driver = {
+ .name = DFL_FPGA_FME_BRIDGE,
},
- .probe = fme_br_probe,
- .remove_new = fme_br_remove,
+ .probe = fme_br_probe,
+ .remove = fme_br_remove,
};
module_platform_driver(fme_br_driver);
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
index 864924f68f5e..f8d89a4a6ccb 100644
--- a/drivers/fpga/dfl-fme-main.c
+++ b/drivers/fpga/dfl-fme-main.c
@@ -742,12 +742,12 @@ static const struct attribute_group *fme_dev_groups[] = {
};
static struct platform_driver fme_driver = {
- .driver = {
- .name = DFL_FPGA_FEATURE_DEV_FME,
+ .driver = {
+ .name = DFL_FPGA_FEATURE_DEV_FME,
.dev_groups = fme_dev_groups,
},
- .probe = fme_probe,
- .remove_new = fme_remove,
+ .probe = fme_probe,
+ .remove = fme_remove,
};
module_platform_driver(fme_driver);
diff --git a/drivers/fpga/dfl-fme-region.c b/drivers/fpga/dfl-fme-region.c
index 71616f8b4982..c6cd63063c82 100644
--- a/drivers/fpga/dfl-fme-region.c
+++ b/drivers/fpga/dfl-fme-region.c
@@ -71,11 +71,11 @@ static void fme_region_remove(struct platform_device *pdev)
}
static struct platform_driver fme_region_driver = {
- .driver = {
- .name = DFL_FPGA_FME_REGION,
+ .driver = {
+ .name = DFL_FPGA_FME_REGION,
},
- .probe = fme_region_probe,
- .remove_new = fme_region_remove,
+ .probe = fme_region_probe,
+ .remove = fme_region_remove,
};
module_platform_driver(fme_region_driver);
diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c
index 7ac9f9f5af12..dd515083bbdd 100644
--- a/drivers/fpga/intel-m10-bmc-sec-update.c
+++ b/drivers/fpga/intel-m10-bmc-sec-update.c
@@ -759,7 +759,7 @@ MODULE_DEVICE_TABLE(platform, intel_m10bmc_sec_ids);
static struct platform_driver intel_m10bmc_sec_driver = {
.probe = m10bmc_sec_probe,
- .remove_new = m10bmc_sec_remove,
+ .remove = m10bmc_sec_remove,
.driver = {
.name = "intel-m10bmc-sec-update",
.dev_groups = m10bmc_sec_attr_groups,
diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c
index 8526a5a86f0c..43db4bb77138 100644
--- a/drivers/fpga/of-fpga-region.c
+++ b/drivers/fpga/of-fpga-region.c
@@ -436,7 +436,7 @@ static void of_fpga_region_remove(struct platform_device *pdev)
static struct platform_driver of_fpga_region_driver = {
.probe = of_fpga_region_probe,
- .remove_new = of_fpga_region_remove,
+ .remove = of_fpga_region_remove,
.driver = {
.name = "of-fpga-region",
.of_match_table = of_match_ptr(fpga_region_of_match),
diff --git a/drivers/fpga/socfpga-a10.c b/drivers/fpga/socfpga-a10.c
index 4c03513b8f03..0165a3c86932 100644
--- a/drivers/fpga/socfpga-a10.c
+++ b/drivers/fpga/socfpga-a10.c
@@ -535,7 +535,7 @@ MODULE_DEVICE_TABLE(of, socfpga_a10_fpga_of_match);
static struct platform_driver socfpga_a10_fpga_driver = {
.probe = socfpga_a10_fpga_probe,
- .remove_new = socfpga_a10_fpga_remove,
+ .remove = socfpga_a10_fpga_remove,
.driver = {
.name = "socfpga_a10_fpga_manager",
.of_match_table = socfpga_a10_fpga_of_match,
diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c
index 2c0def7d7cbb..0a295ccf1644 100644
--- a/drivers/fpga/stratix10-soc.c
+++ b/drivers/fpga/stratix10-soc.c
@@ -455,7 +455,7 @@ MODULE_DEVICE_TABLE(of, s10_of_match);
static struct platform_driver s10_driver = {
.probe = s10_probe,
- .remove_new = s10_remove,
+ .remove = s10_remove,
.driver = {
.name = "Stratix10 SoC FPGA manager",
.of_match_table = of_match_ptr(s10_of_match),
diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c
index 788dd2f63a65..822751fad18a 100644
--- a/drivers/fpga/xilinx-pr-decoupler.c
+++ b/drivers/fpga/xilinx-pr-decoupler.c
@@ -162,7 +162,7 @@ static void xlnx_pr_decoupler_remove(struct platform_device *pdev)
static struct platform_driver xlnx_pr_decoupler_driver = {
.probe = xlnx_pr_decoupler_probe,
- .remove_new = xlnx_pr_decoupler_remove,
+ .remove = xlnx_pr_decoupler_remove,
.driver = {
.name = "xlnx_pr_decoupler",
.of_match_table = xlnx_pr_decoupler_of_match,
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index 4db3d80e10b0..f7e08f7ea9ef 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -642,7 +642,7 @@ MODULE_DEVICE_TABLE(of, zynq_fpga_of_match);
static struct platform_driver zynq_fpga_driver = {
.probe = zynq_fpga_probe,
- .remove_new = zynq_fpga_remove,
+ .remove = zynq_fpga_remove,
.driver = {
.name = "zynq_fpga_manager",
.of_match_table = of_match_ptr(zynq_fpga_of_match),
diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c
index 039fef26546e..73e660c5e38a 100644
--- a/drivers/gpio/gpio-altera.c
+++ b/drivers/gpio/gpio-altera.c
@@ -261,6 +261,11 @@ static int altera_gpio_probe(struct platform_device *pdev)
altera_gc->gc.set = altera_gpio_set;
altera_gc->gc.owner = THIS_MODULE;
altera_gc->gc.parent = &pdev->dev;
+ altera_gc->gc.base = -1;
+
+ altera_gc->gc.label = devm_kasprintf(dev, GFP_KERNEL, "%pfw", dev_fwnode(dev));
+ if (!altera_gc->gc.label)
+ return -ENOMEM;
altera_gc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(altera_gc->regs))
diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c
index 72755fee6478..34eb26298e32 100644
--- a/drivers/gpio/gpio-aspeed-sgpio.c
+++ b/drivers/gpio/gpio-aspeed-sgpio.c
@@ -420,7 +420,7 @@ static void aspeed_sgpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
int offset;
irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
- seq_printf(p, dev_name(gpio->dev));
+ seq_puts(p, dev_name(gpio->dev));
}
static const struct irq_chip aspeed_sgpio_irq_chip = {
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index 208f95fb585e..40c1bd80f8b0 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -1049,7 +1049,7 @@ static void aspeed_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
if (rc)
return;
- seq_printf(p, dev_name(gpio->dev));
+ seq_puts(p, dev_name(gpio->dev));
}
static const struct irq_chip aspeed_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
index ab798c848215..58d2464c07bc 100644
--- a/drivers/gpio/gpio-ep93xx.c
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -249,7 +249,7 @@ static void ep93xx_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static const struct irq_chip gpio_eic_irq_chip = {
diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
index 5170fe7599cd..d5909a4f0433 100644
--- a/drivers/gpio/gpio-exar.c
+++ b/drivers/gpio/gpio-exar.c
@@ -99,11 +99,13 @@ static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
+ unsigned int bit_value = value ? BIT(bit) : 0;
- if (value)
- regmap_set_bits(exar_gpio->regmap, addr, BIT(bit));
- else
- regmap_clear_bits(exar_gpio->regmap, addr, BIT(bit));
+ /*
+ * regmap_write_bits() forces value to be written when an external
+ * pull up/down might otherwise indicate value was already set.
+ */
+ regmap_write_bits(exar_gpio->regmap, addr, BIT(bit), bit_value);
}
static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
diff --git a/drivers/gpio/gpio-hlwd.c b/drivers/gpio/gpio-hlwd.c
index 1bcfc1835dae..0580f6712bea 100644
--- a/drivers/gpio/gpio-hlwd.c
+++ b/drivers/gpio/gpio-hlwd.c
@@ -210,7 +210,7 @@ static void hlwd_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p)
struct hlwd_gpio *hlwd =
gpiochip_get_data(irq_data_get_irq_chip_data(data));
- seq_printf(p, dev_name(hlwd->dev));
+ seq_puts(p, dev_name(hlwd->dev));
}
static const struct irq_chip hlwd_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c
index 6abe01bc39c3..6f3dda6b635f 100644
--- a/drivers/gpio/gpio-mlxbf2.c
+++ b/drivers/gpio/gpio-mlxbf2.c
@@ -331,7 +331,7 @@ static void mlxbf2_gpio_irq_print_chip(struct irq_data *irqd,
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc);
- seq_printf(p, dev_name(gs->dev));
+ seq_puts(p, dev_name(gs->dev));
}
static const struct irq_chip mlxbf2_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-mpsse.c b/drivers/gpio/gpio-mpsse.c
index 9ef24449126a..3ea32c5e33d1 100644
--- a/drivers/gpio/gpio-mpsse.c
+++ b/drivers/gpio/gpio-mpsse.c
@@ -403,7 +403,7 @@ static void gpio_mpsse_ida_remove(void *data)
{
struct mpsse_priv *priv = data;
- ida_simple_remove(&gpio_mpsse_ida, priv->id);
+ ida_free(&gpio_mpsse_ida, priv->id);
}
static int gpio_mpsse_probe(struct usb_interface *interface,
@@ -422,7 +422,7 @@ static int gpio_mpsse_probe(struct usb_interface *interface,
priv->intf = interface;
priv->intf_id = interface->cur_altsetting->desc.bInterfaceNumber;
- priv->id = ida_simple_get(&gpio_mpsse_ida, 0, 0, GFP_KERNEL);
+ priv->id = ida_alloc(&gpio_mpsse_ida, GFP_KERNEL);
if (priv->id < 0)
return priv->id;
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 7ad453405496..54c4bfdccf56 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -715,7 +715,7 @@ static void omap_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
{
struct gpio_bank *bank = omap_irq_data_get_bank(d);
- seq_printf(p, dev_name(bank->dev));
+ seq_puts(p, dev_name(bank->dev));
}
static const struct irq_chip omap_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 3f2d33ee20cc..272febc3230e 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -815,7 +815,7 @@ static void pca953x_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static const struct irq_chip pca953x_irq_chip = {
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index a211a02d4b4a..1c273727ffa3 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -291,7 +291,7 @@ static void pl061_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static const struct irq_chip pl061_irq_chip = {
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 6d3a39a03f58..9ad286adf263 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -600,7 +600,7 @@ static void tegra_gpio_irq_print_chip(struct irq_data *d, struct seq_file *s)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
- seq_printf(s, dev_name(chip->parent));
+ seq_puts(s, dev_name(chip->parent));
}
static const struct irq_chip tegra_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
index 1ecb733a5e88..6895b65c86af 100644
--- a/drivers/gpio/gpio-tegra186.c
+++ b/drivers/gpio/gpio-tegra186.c
@@ -610,7 +610,7 @@ static void tegra186_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static const struct irq_chip tegra186_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c
index f2e7e8754d95..5e26eb3adabb 100644
--- a/drivers/gpio/gpio-tqmx86.c
+++ b/drivers/gpio/gpio-tqmx86.c
@@ -275,7 +275,7 @@ static void tqmx86_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- seq_printf(p, gc->label);
+ seq_puts(p, gc->label);
}
static const struct irq_chip tqmx86_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-visconti.c b/drivers/gpio/gpio-visconti.c
index ebc71ecdb6cf..5bd965c18a46 100644
--- a/drivers/gpio/gpio-visconti.c
+++ b/drivers/gpio/gpio-visconti.c
@@ -142,7 +142,7 @@ static void visconti_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct visconti_gpio *priv = gpiochip_get_data(gc);
- seq_printf(p, dev_name(priv->dev));
+ seq_puts(p, dev_name(priv->dev));
}
static const struct irq_chip visconti_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-xgs-iproc.c b/drivers/gpio/gpio-xgs-iproc.c
index 0f9d1f61fee3..93544e98ccbd 100644
--- a/drivers/gpio/gpio-xgs-iproc.c
+++ b/drivers/gpio/gpio-xgs-iproc.c
@@ -198,7 +198,7 @@ static void iproc_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct iproc_gpio_chip *chip = to_iproc_gpio(gc);
- seq_printf(p, dev_name(chip->dev));
+ seq_puts(p, dev_name(chip->dev));
}
static const struct irq_chip iproc_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-zevio.c b/drivers/gpio/gpio-zevio.c
index 2de61337ad3b..d7230fd83f5d 100644
--- a/drivers/gpio/gpio-zevio.c
+++ b/drivers/gpio/gpio-zevio.c
@@ -11,6 +11,7 @@
#include <linux/io.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@@ -169,6 +170,7 @@ static const struct gpio_chip zevio_gpio_chip = {
/* Initialization */
static int zevio_gpio_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct zevio_gpio *controller;
int status, i;
@@ -180,6 +182,10 @@ static int zevio_gpio_probe(struct platform_device *pdev)
controller->chip = zevio_gpio_chip;
controller->chip.parent = &pdev->dev;
+ controller->chip.label = devm_kasprintf(dev, GFP_KERNEL, "%pfw", dev_fwnode(dev));
+ if (!controller->chip.label)
+ return -ENOMEM;
+
controller->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(controller->regs))
return dev_err_probe(&pdev->dev, PTR_ERR(controller->regs),
diff --git a/drivers/gpu/drm/amd/amdgpu/aldebaran.c b/drivers/gpu/drm/amd/amdgpu/aldebaran.c
index 3a588fecb0c5..f44de9d4b6a1 100644
--- a/drivers/gpu/drm/amd/amdgpu/aldebaran.c
+++ b/drivers/gpu/drm/amd/amdgpu/aldebaran.c
@@ -330,6 +330,8 @@ aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
}
list_for_each_entry(tmp_adev, reset_device_list, reset_list) {
+ amdgpu_set_init_level(tmp_adev,
+ AMDGPU_INIT_LEVEL_RESET_RECOVERY);
dev_info(tmp_adev->dev,
"GPU reset succeeded, trying to resume\n");
r = aldebaran_mode2_restore_ip(tmp_adev);
@@ -375,6 +377,8 @@ aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
tmp_adev);
if (!r) {
+ amdgpu_set_init_level(tmp_adev,
+ AMDGPU_INIT_LEVEL_DEFAULT);
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
r = amdgpu_ib_ring_tests(tmp_adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index d8bc6da50016..4653a8d2823a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -839,6 +839,7 @@ struct amdgpu_mqd {
enum amdgpu_init_lvl_id {
AMDGPU_INIT_LEVEL_DEFAULT,
AMDGPU_INIT_LEVEL_MINIMAL_XGMI,
+ AMDGPU_INIT_LEVEL_RESET_RECOVERY,
};
struct amdgpu_init_level {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 0171d240fcb0..9095c05e0269 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -156,6 +156,11 @@ struct amdgpu_init_level amdgpu_init_default = {
.hwini_ip_block_mask = AMDGPU_IP_BLK_MASK_ALL,
};
+struct amdgpu_init_level amdgpu_init_recovery = {
+ .level = AMDGPU_INIT_LEVEL_RESET_RECOVERY,
+ .hwini_ip_block_mask = AMDGPU_IP_BLK_MASK_ALL,
+};
+
/*
* Minimal blocks needed to be initialized before a XGMI hive can be reset. This
* is used for cases like reset on initialization where the entire hive needs to
@@ -182,6 +187,9 @@ void amdgpu_set_init_level(struct amdgpu_device *adev,
case AMDGPU_INIT_LEVEL_MINIMAL_XGMI:
adev->init_lvl = &amdgpu_init_minimal_xgmi;
break;
+ case AMDGPU_INIT_LEVEL_RESET_RECOVERY:
+ adev->init_lvl = &amdgpu_init_recovery;
+ break;
case AMDGPU_INIT_LEVEL_DEFAULT:
fallthrough;
default:
@@ -3250,7 +3258,7 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
return r;
}
- if (!amdgpu_in_reset(adev))
+ if (!amdgpu_reset_in_recovery(adev))
amdgpu_ras_set_error_query_ready(adev, true);
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
@@ -4669,8 +4677,8 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
int idx;
bool px;
- amdgpu_fence_driver_sw_fini(adev);
amdgpu_device_ip_fini(adev);
+ amdgpu_fence_driver_sw_fini(adev);
amdgpu_ucode_release(&adev->firmware.gpu_info_fw);
adev->accel_working = false;
dma_fence_put(rcu_dereference_protected(adev->gang_submit, true));
@@ -5419,7 +5427,7 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context)
struct list_head *device_list_handle;
bool full_reset, vram_lost = false;
struct amdgpu_device *tmp_adev;
- int r;
+ int r, init_level;
device_list_handle = reset_context->reset_device_list;
@@ -5428,10 +5436,18 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context)
full_reset = test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
+ /**
+ * If it's reset on init, it's default init level, otherwise keep level
+ * as recovery level.
+ */
+ if (reset_context->method == AMD_RESET_METHOD_ON_INIT)
+ init_level = AMDGPU_INIT_LEVEL_DEFAULT;
+ else
+ init_level = AMDGPU_INIT_LEVEL_RESET_RECOVERY;
+
r = 0;
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
- /* After reset, it's default init level */
- amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_DEFAULT);
+ amdgpu_set_init_level(tmp_adev, init_level);
if (full_reset) {
/* post card */
amdgpu_ras_set_fed(tmp_adev, false);
@@ -5518,6 +5534,9 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context)
out:
if (!r) {
+ /* IP init is complete now, set level as default */
+ amdgpu_set_init_level(tmp_adev,
+ AMDGPU_INIT_LEVEL_DEFAULT);
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
r = amdgpu_ib_ring_tests(tmp_adev);
if (r) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index f57cc72c43cf..69a6b6dba0a5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -1778,9 +1778,11 @@ int amdgpu_gfx_sysfs_init(struct amdgpu_device *adev)
void amdgpu_gfx_sysfs_fini(struct amdgpu_device *adev)
{
- amdgpu_gfx_sysfs_xcp_fini(adev);
- amdgpu_gfx_sysfs_isolation_shader_fini(adev);
- amdgpu_gfx_sysfs_reset_mask_fini(adev);
+ if (adev->dev->kobj.sd) {
+ amdgpu_gfx_sysfs_xcp_fini(adev);
+ amdgpu_gfx_sysfs_isolation_shader_fini(adev);
+ amdgpu_gfx_sysfs_reset_mask_fini(adev);
+ }
}
int amdgpu_gfx_cleaner_shader_sw_init(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
index 04eb51674596..b6d2eb049f54 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
@@ -447,6 +447,8 @@ int amdgpu_jpeg_sysfs_reset_mask_init(struct amdgpu_device *adev)
void amdgpu_jpeg_sysfs_reset_mask_fini(struct amdgpu_device *adev)
{
- if (adev->jpeg.num_jpeg_inst)
- device_remove_file(adev->dev, &dev_attr_jpeg_reset_mask);
+ if (adev->dev->kobj.sd) {
+ if (adev->jpeg.num_jpeg_inst)
+ device_remove_file(adev->dev, &dev_attr_jpeg_reset_mask);
+ }
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
index e8adfd0a570a..34b5e22b44e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
@@ -137,7 +137,8 @@ void amdgpu_preempt_mgr_fini(struct amdgpu_device *adev)
if (ret)
return;
- device_remove_file(adev->dev, &dev_attr_mem_info_preempt_used);
+ if (adev->dev->kobj.sd)
+ device_remove_file(adev->dev, &dev_attr_mem_info_preempt_used);
ttm_resource_manager_cleanup(man);
ttm_set_driver_manager(&adev->mman.bdev, AMDGPU_PL_PREEMPT, NULL);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 17cf10c0b72b..448f9e742983 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -4112,7 +4112,7 @@ static umode_t amdgpu_flash_attr_is_visible(struct kobject *kobj, struct attribu
}
static umode_t amdgpu_bin_flash_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
int idx)
{
struct device *dev = kobj_to_dev(kobj);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 1bc95b0cdbb8..4c9fa24dd972 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -1298,7 +1298,7 @@ int amdgpu_ras_bind_aca(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
struct ras_manager *obj;
/* in resume phase, no need to create aca fs node */
- if (adev->in_suspend || amdgpu_in_reset(adev))
+ if (adev->in_suspend || amdgpu_reset_in_recovery(adev))
return 0;
obj = get_ras_manager(adev, blk);
@@ -3610,7 +3610,7 @@ static void amdgpu_ras_event_mgr_init(struct amdgpu_device *adev)
ras->event_mgr = hive ? &hive->event_mgr : &ras->__event_mgr;
/* init event manager with node 0 on xgmi system */
- if (!amdgpu_in_reset(adev)) {
+ if (!amdgpu_reset_in_recovery(adev)) {
if (!hive || adev->gmc.xgmi.node_id == 0)
ras_event_mgr_init(ras->event_mgr);
}
@@ -3825,7 +3825,7 @@ int amdgpu_ras_block_late_init(struct amdgpu_device *adev,
r = amdgpu_ras_feature_enable_on_boot(adev, ras_block, 1);
if (r) {
- if (adev->in_suspend || amdgpu_in_reset(adev)) {
+ if (adev->in_suspend || amdgpu_reset_in_recovery(adev)) {
/* in resume phase, if fail to enable ras,
* clean up all ras fs nodes, and disable ras */
goto cleanup;
@@ -3837,7 +3837,7 @@ int amdgpu_ras_block_late_init(struct amdgpu_device *adev,
amdgpu_persistent_edc_harvesting(adev, ras_block);
/* in resume phase, no need to create ras fs node */
- if (adev->in_suspend || amdgpu_in_reset(adev))
+ if (adev->in_suspend || amdgpu_reset_in_recovery(adev))
return 0;
ras_obj = container_of(ras_block, struct amdgpu_ras_block_object, ras_comm);
@@ -3967,7 +3967,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev)
amdgpu_ras_event_mgr_init(adev);
if (amdgpu_ras_aca_is_supported(adev)) {
- if (amdgpu_in_reset(adev)) {
+ if (amdgpu_reset_in_recovery(adev)) {
if (amdgpu_aca_is_enabled(adev))
r = amdgpu_aca_reset(adev);
else
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
index 24dae7cdbe95..a0acb65f4b40 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
@@ -342,3 +342,8 @@ void amdgpu_reset_get_desc(struct amdgpu_reset_context *rst_ctxt, char *buf,
strscpy(buf, "unknown", len);
}
}
+
+bool amdgpu_reset_in_recovery(struct amdgpu_device *adev)
+{
+ return (adev->init_lvl->level == AMDGPU_INIT_LEVEL_RESET_RECOVERY);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
index f8628bc898df..4d9b9701139b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
@@ -158,4 +158,6 @@ extern struct amdgpu_reset_handler xgmi_reset_on_init_handler;
int amdgpu_reset_do_xgmi_reset_on_init(
struct amdgpu_reset_context *reset_context);
+bool amdgpu_reset_in_recovery(struct amdgpu_device *adev);
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index 8c89b69edc20..113f0d242618 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -451,6 +451,8 @@ void amdgpu_sdma_sysfs_reset_mask_fini(struct amdgpu_device *adev)
if (!amdgpu_gpu_recovery)
return;
- if (adev->sdma.num_instances)
- device_remove_file(adev->dev, &dev_attr_sdma_reset_mask);
+ if (adev->dev->kobj.sd) {
+ if (adev->sdma.num_instances)
+ device_remove_file(adev->dev, &dev_attr_sdma_reset_mask);
+ }
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 74fdbf71d95b..599d3ca4e0ef 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -214,15 +214,15 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
drm_sched_entity_destroy(&adev->vce.entity);
- amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
- (void **)&adev->vce.cpu_addr);
-
for (i = 0; i < adev->vce.num_rings; i++)
amdgpu_ring_fini(&adev->vce.ring[i]);
amdgpu_ucode_release(&adev->vce.fw);
mutex_destroy(&adev->vce.idle_mutex);
+ amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
+ (void **)&adev->vce.cpu_addr);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index aecb78e0519f..3e94c3ba1ba2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -1283,3 +1283,40 @@ int amdgpu_vcn_psp_update_sram(struct amdgpu_device *adev, int inst_idx,
return psp_execute_ip_fw_load(&adev->psp, &ucode);
}
+
+static ssize_t amdgpu_get_vcn_reset_mask(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ if (!adev)
+ return -ENODEV;
+
+ return amdgpu_show_reset_mask(buf, adev->vcn.supported_reset);
+}
+
+static DEVICE_ATTR(vcn_reset_mask, 0444,
+ amdgpu_get_vcn_reset_mask, NULL);
+
+int amdgpu_vcn_sysfs_reset_mask_init(struct amdgpu_device *adev)
+{
+ int r = 0;
+
+ if (adev->vcn.num_vcn_inst) {
+ r = device_create_file(adev->dev, &dev_attr_vcn_reset_mask);
+ if (r)
+ return r;
+ }
+
+ return r;
+}
+
+void amdgpu_vcn_sysfs_reset_mask_fini(struct amdgpu_device *adev)
+{
+ if (adev->dev->kobj.sd) {
+ if (adev->vcn.num_vcn_inst)
+ device_remove_file(adev->dev, &dev_attr_vcn_reset_mask);
+ }
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 765b809d48a2..1e32311c1dff 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -333,6 +333,8 @@ struct amdgpu_vcn {
/* IP reg dump */
uint32_t *ip_dump;
+
+ uint32_t supported_reset;
};
struct amdgpu_fw_shared_rb_ptrs_struct {
@@ -519,5 +521,7 @@ int amdgpu_vcn_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_vcn_psp_update_sram(struct amdgpu_device *adev, int inst_idx,
enum AMDGPU_UCODE_ID ucode_id);
int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev);
+int amdgpu_vcn_sysfs_reset_mask_init(struct amdgpu_device *adev);
+void amdgpu_vcn_sysfs_reset_mask_fini(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
index 3e6f9dfb61bb..110b120d7375 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
@@ -904,8 +904,10 @@ int amdgpu_vpe_sysfs_reset_mask_init(struct amdgpu_device *adev)
void amdgpu_vpe_sysfs_reset_mask_fini(struct amdgpu_device *adev)
{
- if (adev->vpe.num_instances)
- device_remove_file(adev->dev, &dev_attr_vpe_reset_mask);
+ if (adev->dev->kobj.sd) {
+ if (adev->vpe.num_instances)
+ device_remove_file(adev->dev, &dev_attr_vpe_reset_mask);
+ }
}
static const struct amdgpu_ring_funcs vpe_ring_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
index b47422b0b5b1..74b4349e345a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -40,6 +40,11 @@
#define smnPCS_GOPX1_PCS_ERROR_STATUS 0x12200210
#define smnPCS_GOPX1_PCS_ERROR_NONCORRECTABLE_MASK 0x12200218
+#define XGMI_STATE_DISABLE 0xD1
+#define XGMI_STATE_LS0 0x81
+#define XGMI_LINK_ACTIVE 1
+#define XGMI_LINK_INACTIVE 0
+
static DEFINE_MUTEX(xgmi_mutex);
#define AMDGPU_MAX_XGMI_DEVICE_PER_HIVE 4
@@ -289,6 +294,42 @@ static const struct amdgpu_pcs_ras_field xgmi3x16_pcs_ras_fields[] = {
SOC15_REG_FIELD(PCS_XGMI3X16_PCS_ERROR_STATUS, RxCMDPktErr)},
};
+static u32 xgmi_v6_4_get_link_status(struct amdgpu_device *adev, int global_link_num)
+{
+ const u32 smnpcs_xgmi3x16_pcs_state_hist1 = 0x11a00070;
+ const int xgmi_inst = 2;
+ u32 link_inst;
+ u64 addr;
+
+ link_inst = global_link_num % xgmi_inst;
+
+ addr = (smnpcs_xgmi3x16_pcs_state_hist1 | (link_inst << 20)) +
+ adev->asic_funcs->encode_ext_smn_addressing(global_link_num / xgmi_inst);
+
+ return RREG32_PCIE_EXT(addr);
+}
+
+int amdgpu_get_xgmi_link_status(struct amdgpu_device *adev, int global_link_num)
+{
+ u32 xgmi_state_reg_val;
+
+ switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
+ case IP_VERSION(6, 4, 0):
+ xgmi_state_reg_val = xgmi_v6_4_get_link_status(adev, global_link_num);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ if ((xgmi_state_reg_val & 0xFF) == XGMI_STATE_DISABLE)
+ return -ENOLINK;
+
+ if ((xgmi_state_reg_val & 0xFF) == XGMI_STATE_LS0)
+ return XGMI_LINK_ACTIVE;
+
+ return XGMI_LINK_INACTIVE;
+}
+
/**
* DOC: AMDGPU XGMI Support
*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
index 8cc7ab38db7c..d1282b4c6348 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
@@ -84,5 +84,7 @@ int amdgpu_xgmi_reset_on_init(struct amdgpu_device *adev);
int amdgpu_xgmi_request_nps_change(struct amdgpu_device *adev,
struct amdgpu_hive_info *hive,
int req_nps_mode);
+int amdgpu_get_xgmi_link_status(struct amdgpu_device *adev,
+ int global_link_num);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
index 483a441b46aa..621aeca53880 100644
--- a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
+++ b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
@@ -254,8 +254,8 @@ static void df_v3_6_sw_init(struct amdgpu_device *adev)
static void df_v3_6_sw_fini(struct amdgpu_device *adev)
{
-
- device_remove_file(adev->dev, &dev_attr_df_cntr_avail);
+ if (adev->dev->kobj.sd)
+ device_remove_file(adev->dev, &dev_attr_df_cntr_avail);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index 07f45f1a503a..b6016f11956e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -87,9 +87,14 @@ static void gmc_v7_0_init_golden_registers(struct amdgpu_device *adev)
static void gmc_v7_0_mc_stop(struct amdgpu_device *adev)
{
+ struct amdgpu_ip_block *ip_block;
u32 blackout;
- gmc_v7_0_wait_for_idle((void *)adev);
+ ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_GMC);
+ if (!ip_block)
+ return;
+
+ gmc_v7_0_wait_for_idle(ip_block);
blackout = RREG32(mmMC_SHARED_BLACKOUT_CNTL);
if (REG_GET_FIELD(blackout, MC_SHARED_BLACKOUT_CNTL, BLACKOUT_MODE) != 1) {
@@ -251,9 +256,14 @@ static void gmc_v7_0_vram_gtt_location(struct amdgpu_device *adev,
*/
static void gmc_v7_0_mc_program(struct amdgpu_device *adev)
{
+ struct amdgpu_ip_block *ip_block;
u32 tmp;
int i, j;
+ ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_GMC);
+ if (!ip_block)
+ return;
+
/* Initialize HDP */
for (i = 0, j = 0; i < 32; i++, j += 0x6) {
WREG32((0xb05 + j), 0x00000000);
@@ -264,7 +274,7 @@ static void gmc_v7_0_mc_program(struct amdgpu_device *adev)
}
WREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL, 0);
- if (gmc_v7_0_wait_for_idle((void *)adev))
+ if (gmc_v7_0_wait_for_idle(ip_block))
dev_warn(adev->dev, "Wait for MC idle timedout !\n");
if (adev->mode_info.num_crtc) {
@@ -288,7 +298,7 @@ static void gmc_v7_0_mc_program(struct amdgpu_device *adev)
WREG32(mmMC_VM_AGP_BASE, 0);
WREG32(mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 22);
WREG32(mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 22);
- if (gmc_v7_0_wait_for_idle((void *)adev))
+ if (gmc_v7_0_wait_for_idle(ip_block))
dev_warn(adev->dev, "Wait for MC idle timedout !\n");
WREG32(mmBIF_FB_EN, BIF_FB_EN__FB_READ_EN_MASK | BIF_FB_EN__FB_WRITE_EN_MASK);
@@ -1183,7 +1193,7 @@ static int gmc_v7_0_soft_reset(struct amdgpu_ip_block *ip_block)
if (srbm_soft_reset) {
gmc_v7_0_mc_stop(adev);
- if (gmc_v7_0_wait_for_idle((void *)adev))
+ if (gmc_v7_0_wait_for_idle(ip_block))
dev_warn(adev->dev, "Wait for GMC idle timed out !\n");
tmp = RREG32(mmSRBM_SOFT_RESET);
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
index 03b8b7cd5229..7319299f25ae 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
@@ -604,7 +604,7 @@ static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev)
static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
- bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
+ bool set_clocks = !cancel_delayed_work_sync(&adev->jpeg.idle_work);
int cnt = 0;
mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
index d6823fb45d32..6e29b69894a5 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
@@ -150,7 +150,7 @@ static int jpeg_v2_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
index 5063a38801d6..9ac421486f05 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
@@ -211,7 +211,7 @@ static int jpeg_v2_5_hw_fini(struct amdgpu_ip_block *ip_block)
struct amdgpu_device *adev = ip_block->adev;
int i;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
if (adev->jpeg.harvest_config & (1 << i))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
index 10adbb7cbf53..e0df6800502c 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
@@ -164,7 +164,7 @@ static int jpeg_v3_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index 193dfac5dc76..eca1963c33b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -202,7 +202,7 @@ static int jpeg_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
if (!amdgpu_sriov_vf(adev)) {
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
index b48e2412e6cc..1d9e3b101c3a 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
@@ -227,7 +227,7 @@ static int jpeg_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block)
struct amdgpu_device *adev = ip_block->adev;
int i;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
if (adev->jpeg.harvest_config & (1 << i))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
index 686f9605239d..58fb1e5fa89c 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
@@ -168,7 +168,7 @@ static int jpeg_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c
index 7a9adfda5814..814ab59fdd4a 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c
@@ -275,6 +275,15 @@ static void nbio_v7_11_init_registers(struct amdgpu_device *adev)
if (def != data)
WREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3, data);
+ switch (adev->ip_versions[NBIO_HWIP][0]) {
+ case IP_VERSION(7, 11, 0):
+ case IP_VERSION(7, 11, 1):
+ case IP_VERSION(7, 11, 2):
+ case IP_VERSION(7, 11, 3):
+ data = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF5_STRAP4) & ~BIT(23);
+ WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF5_STRAP4, data);
+ break;
+ }
}
static void nbio_v7_11_update_medium_grain_clock_gating(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c b/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c
index 9b01e074af47..2594467bdd87 100644
--- a/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c
+++ b/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c
@@ -220,6 +220,7 @@ sienna_cichlid_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
int r;
struct amdgpu_device *tmp_adev = (struct amdgpu_device *)reset_ctl->handle;
+ amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_RESET_RECOVERY);
dev_info(tmp_adev->dev,
"GPU reset succeeded, trying to resume\n");
r = sienna_cichlid_mode2_restore_ip(tmp_adev);
@@ -237,6 +238,7 @@ sienna_cichlid_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
+ amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_DEFAULT);
r = amdgpu_ib_ring_tests(tmp_adev);
if (r) {
dev_err(tmp_adev->dev,
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c b/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
index e70ebad3f9fa..70569ea906bc 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
@@ -221,6 +221,7 @@ smu_v13_0_10_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
int r;
struct amdgpu_device *tmp_adev = (struct amdgpu_device *)reset_ctl->handle;
+ amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_RESET_RECOVERY);
dev_info(tmp_adev->dev,
"GPU reset succeeded, trying to resume\n");
r = smu_v13_0_10_mode2_restore_ip(tmp_adev);
@@ -234,6 +235,7 @@ smu_v13_0_10_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
+ amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_DEFAULT);
r = amdgpu_ib_ring_tests(tmp_adev);
if (r) {
dev_err(tmp_adev->dev,
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 5512259cac79..fcc8511e91ee 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -225,6 +225,10 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
vcn_v4_0_fw_shared_init(adev, i);
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->vcn.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
+
if (amdgpu_sriov_vf(adev)) {
r = amdgpu_virt_alloc_mm_table(adev);
if (r)
@@ -247,6 +251,10 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
adev->vcn.ip_dump = ptr;
}
+ r = amdgpu_vcn_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return 0;
}
@@ -284,6 +292,7 @@ static int vcn_v4_0_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_vcn_sysfs_reset_mask_fini(adev);
r = amdgpu_vcn_sw_fini(adev);
kfree(adev->vcn.ip_dump);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index cf808a153fce..3f69b9b2bcd0 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -123,6 +123,20 @@ static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
return amdgpu_vcn_early_init(adev);
}
+static int vcn_v4_0_3_fw_shared_init(struct amdgpu_device *adev, int inst_idx)
+{
+ struct amdgpu_vcn4_fw_shared *fw_shared;
+
+ fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
+ fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
+ fw_shared->sq.is_enabled = 1;
+
+ if (amdgpu_vcnfw_log)
+ amdgpu_vcn_fwlog_init(&adev->vcn.inst[inst_idx]);
+
+ return 0;
+}
+
/**
* vcn_v4_0_3_sw_init - sw init for VCN block
*
@@ -155,8 +169,6 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
return r;
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
- volatile struct amdgpu_vcn4_fw_shared *fw_shared;
-
vcn_inst = GET_INST(VCN, i);
ring = &adev->vcn.inst[i].ring_enc[0];
@@ -179,14 +191,13 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
- fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
- fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
- fw_shared->sq.is_enabled = true;
-
- if (amdgpu_vcnfw_log)
- amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
+ vcn_v4_0_3_fw_shared_init(adev, i);
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->vcn.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
+
if (amdgpu_sriov_vf(adev)) {
r = amdgpu_virt_alloc_mm_table(adev);
if (r)
@@ -213,6 +224,10 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
adev->vcn.ip_dump = ptr;
}
+ r = amdgpu_vcn_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return 0;
}
@@ -246,6 +261,7 @@ static int vcn_v4_0_3_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_vcn_sysfs_reset_mask_fini(adev);
r = amdgpu_vcn_sw_fini(adev);
kfree(adev->vcn.ip_dump);
@@ -280,6 +296,8 @@ static int vcn_v4_0_3_hw_init(struct amdgpu_ip_block *ip_block)
}
} else {
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ struct amdgpu_vcn4_fw_shared *fw_shared;
+
vcn_inst = GET_INST(VCN, i);
ring = &adev->vcn.inst[i].ring_enc[0];
@@ -303,6 +321,11 @@ static int vcn_v4_0_3_hw_init(struct amdgpu_ip_block *ip_block)
regVCN_RB1_DB_CTRL);
}
+ /* Re-init fw_shared when RAS fatal error occurred */
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+ if (!fw_shared->sq.is_enabled)
+ vcn_v4_0_3_fw_shared_init(adev, i);
+
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index fe2cc1a80c13..bd3d2bbdc16b 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -170,6 +170,10 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->vcn.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
+
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
adev->vcn.pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode;
@@ -181,6 +185,11 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
} else {
adev->vcn.ip_dump = ptr;
}
+
+ r = amdgpu_vcn_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return 0;
}
@@ -215,6 +224,7 @@ static int vcn_v5_0_0_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_vcn_sysfs_reset_mask_fini(adev);
r = amdgpu_vcn_sw_fini(adev);
kfree(adev->vcn.ip_dump);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
index 4843dcb9a5f7..2b0a830f5b29 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
@@ -125,7 +125,7 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev,
memset(kq->pq_kernel_addr, 0, queue_size);
memset(kq->rptr_kernel, 0, sizeof(*kq->rptr_kernel));
- memset(kq->wptr_kernel, 0, sizeof(*kq->wptr_kernel));
+ memset(kq->wptr_kernel, 0, dev->kfd->device_info.doorbell_size);
prop.queue_size = queue_size;
prop.is_interop = false;
@@ -306,12 +306,17 @@ int kq_submit_packet(struct kernel_queue *kq)
if (amdgpu_amdkfd_is_fed(kq->dev->adev))
return -EIO;
+ /* Make sure ring buffer is updated before wptr updated */
+ mb();
+
if (kq->dev->kfd->device_info.doorbell_size == 8) {
*kq->wptr64_kernel = kq->pending_wptr64;
+ mb(); /* Make sure wptr updated before ring doorbell */
write_kernel_doorbell64(kq->queue->properties.doorbell_ptr,
kq->pending_wptr64);
} else {
*kq->wptr_kernel = kq->pending_wptr;
+ mb(); /* Make sure wptr updated before ring doorbell */
write_kernel_doorbell(kq->queue->properties.doorbell_ptr,
kq->pending_wptr);
}
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig
index df17e79c45c7..11e3f2f3b174 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -7,20 +7,21 @@ menu "Display Engine Configuration"
config DRM_AMD_DC
bool "AMD DC - Enable new display engine"
default y
- depends on BROKEN || !CC_IS_CLANG || ARM64 || RISCV || SPARC64 || X86_64
+ depends on BROKEN || !CC_IS_CLANG || ARM64 || LOONGARCH || RISCV || SPARC64 || X86_64
select SND_HDA_COMPONENT if SND_HDA_CORE
# !CC_IS_CLANG: https://github.com/ClangBuiltLinux/linux/issues/1752
- select DRM_AMD_DC_FP if ARCH_HAS_KERNEL_FPU_SUPPORT && !(CC_IS_CLANG && (ARM64 || RISCV))
+ select DRM_AMD_DC_FP if ARCH_HAS_KERNEL_FPU_SUPPORT && !(CC_IS_CLANG && (ARM64 || LOONGARCH || RISCV))
help
Choose this option if you want to use the new display engine
support for AMDGPU. This adds required support for Vega and
Raven ASICs.
- calculate_bandwidth() is presently broken on all !(X86_64 || SPARC64 || ARM64)
- architectures built with Clang (all released versions), whereby the stack
- frame gets blown up to well over 5k. This would cause an immediate kernel
- panic on most architectures. We'll revert this when the following bug report
- has been resolved: https://github.com/llvm/llvm-project/issues/41896.
+ calculate_bandwidth() is presently broken on all !(X86_64 || SPARC64 ||
+ ARM64 || LOONGARCH || RISCV) architectures built with Clang (all released
+ versions), whereby the stack frame gets blown up to well over 5k. This
+ would cause an immediate kernel panic on most architectures. We'll revert
+ this when the following bug report has been resolved:
+ https://github.com/llvm/llvm-project/issues/41896.
config DRM_AMD_DC_FP
def_bool n
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 7872c6cabb14..1dd26d5df6b9 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3141,7 +3141,10 @@ static void restore_planes_and_stream_state(
return;
for (i = 0; i < status->plane_count; i++) {
+ /* refcount will always be valid, restore everything else */
+ struct kref refcount = status->plane_states[i]->refcount;
*status->plane_states[i] = scratch->plane_states[i];
+ status->plane_states[i]->refcount = refcount;
}
*stream = scratch->stream_state;
}
@@ -6097,11 +6100,11 @@ struct dc_power_profile dc_get_power_profile_for_dc_state(const struct dc_state
{
struct dc_power_profile profile = { 0 };
- if (!context || !context->clk_mgr || !context->clk_mgr->ctx || !context->clk_mgr->ctx->dc)
+ profile.power_level = !context->bw_ctx.bw.dcn.clk.p_state_change_support;
+ if (!context->clk_mgr || !context->clk_mgr->ctx || !context->clk_mgr->ctx->dc)
return profile;
struct dc *dc = context->clk_mgr->ctx->dc;
-
if (dc->res_pool->funcs->get_power_profile)
profile.power_level = dc->res_pool->funcs->get_power_profile(context);
return profile;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 0419ee7f22a5..252af83e34a5 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -898,6 +898,9 @@ void hwss_setup_dpp(union block_sequence_params *params)
struct dpp *dpp = pipe_ctx->plane_res.dpp;
struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+ if (!plane_state)
+ return;
+
if (dpp && dpp->funcs->dpp_setup) {
// program the input csc
dpp->funcs->dpp_setup(dpp,
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 33125b95c3a1..619fad17de55 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1501,6 +1501,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
res = spl_calculate_scaler_params(spl_in, spl_out);
// Convert respective out params from SPL to scaler data
translate_SPL_out_params_to_pipe_ctx(pipe_ctx, spl_out);
+
+ /* Ignore scaler failure if pipe context plane is phantom plane */
+ if (!res && plane_state->is_phantom)
+ res = true;
} else {
#endif
/* depends on h_active */
@@ -1571,6 +1575,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
&plane_state->scaling_quality);
}
+ /* Ignore scaler failure if pipe context plane is phantom plane */
+ if (!res && plane_state->is_phantom)
+ res = true;
+
if (res && (pipe_ctx->plane_res.scl_data.taps.v_taps != temp.v_taps ||
pipe_ctx->plane_res.scl_data.taps.h_taps != temp.h_taps ||
pipe_ctx->plane_res.scl_data.taps.v_taps_c != temp.v_taps_c ||
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index e143fab00a86..104051935884 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -55,7 +55,7 @@ struct aux_payload;
struct set_config_cmd_payload;
struct dmub_notification;
-#define DC_VER "3.2.309"
+#define DC_VER "3.2.310"
#define MAX_SURFACES 3
#define MAX_PLANES 6
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
index 838d72eaa87f..b363f5360818 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
@@ -1392,10 +1392,10 @@ static void dccg35_set_dtbclk_dto(
/* The recommended programming sequence to enable DTBCLK DTO to generate
* valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
- * be set only after DTO is enabled
+ * be set only after DTO is enabled.
+ * PIPEx_DTO_SRC_SEL should not be programmed during DTBCLK update since OTG may still be on, and the
+ * programming is handled in program_pix_clk() regardless, so it can be removed from here.
*/
- REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
- PIPE_DTO_SRC_SEL[params->otg_inst], 2);
} else {
switch (params->otg_inst) {
case 0:
@@ -1412,9 +1412,12 @@ static void dccg35_set_dtbclk_dto(
break;
}
- REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
- DTBCLK_DTO_ENABLE[params->otg_inst], 0,
- PIPE_DTO_SRC_SEL[params->otg_inst], params->is_hdmi ? 0 : 1);
+ /**
+ * PIPEx_DTO_SRC_SEL should not be programmed during DTBCLK update since OTG may still be on, and the
+ * programming is handled in program_pix_clk() regardless, so it can be removed from here.
+ */
+ REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
+ DTBCLK_DTO_ENABLE[params->otg_inst], 0);
REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
index 92e43a1e4dd4..601320b1be81 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
@@ -11,6 +11,7 @@
#define DML2_MAX_FMT_420_BUFFER_WIDTH 4096
#define DML_MAX_NUM_OF_SLICES_PER_DSC 4
+#define ALLOW_SDPIF_RATE_LIMIT_PRE_CSTATE
const char *dml2_core_internal_bw_type_str(enum dml2_core_internal_bw_type bw_type)
{
@@ -3886,6 +3887,10 @@ static void CalculateSwathAndDETConfiguration(struct dml2_core_internal_scratch
#endif
*p->hw_debug5 = false;
+#ifdef ALLOW_SDPIF_RATE_LIMIT_PRE_CSTATE
+ if (p->NumberOfActiveSurfaces > 1)
+ *p->hw_debug5 = true;
+#else
for (unsigned int k = 0; k < p->NumberOfActiveSurfaces; ++k) {
if (!(p->mrq_present) && (!(*p->UnboundedRequestEnabled)) && (TotalActiveDPP == 1)
&& p->display_cfg->plane_descriptors[k].surface.dcc.enable
@@ -3901,6 +3906,7 @@ static void CalculateSwathAndDETConfiguration(struct dml2_core_internal_scratch
dml2_printf("DML::%s: k=%u hw_debug5 = %u\n", __func__, k, *p->hw_debug5);
#endif
}
+#endif
}
static enum dml2_odm_mode DecideODMMode(unsigned int HActive,
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
index 6eccf0241d85..1ed21c1b86a5 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
@@ -258,12 +258,25 @@ static unsigned int find_preferred_pipe_candidates(const struct dc_state *existi
* However this condition comes with a caveat. We need to ignore pipes that will
* require a change in OPP but still have the same stream id. For example during
* an MPC to ODM transiton.
+ *
+ * Adding check to avoid pipe select on the head pipe by utilizing dc resource
+ * helper function resource_get_primary_dpp_pipe and comparing the pipe index.
*/
if (existing_state) {
for (i = 0; i < pipe_count; i++) {
if (existing_state->res_ctx.pipe_ctx[i].stream && existing_state->res_ctx.pipe_ctx[i].stream->stream_id == stream_id) {
+ struct pipe_ctx *head_pipe =
+ resource_is_pipe_type(&existing_state->res_ctx.pipe_ctx[i], DPP_PIPE) ?
+ resource_get_primary_dpp_pipe(&existing_state->res_ctx.pipe_ctx[i]) :
+ NULL;
+
+ // we should always respect the head pipe from selection
+ if (head_pipe && head_pipe->pipe_idx == i)
+ continue;
if (existing_state->res_ctx.pipe_ctx[i].plane_res.hubp &&
- existing_state->res_ctx.pipe_ctx[i].plane_res.hubp->opp_id != i)
+ existing_state->res_ctx.pipe_ctx[i].plane_res.hubp->opp_id != i &&
+ (existing_state->res_ctx.pipe_ctx[i].prev_odm_pipe ||
+ existing_state->res_ctx.pipe_ctx[i].next_odm_pipe))
continue;
preferred_pipe_candidates[num_preferred_candidates++] = i;
@@ -292,6 +305,14 @@ static unsigned int find_last_resort_pipe_candidates(const struct dc_state *exis
*/
if (existing_state) {
for (i = 0; i < pipe_count; i++) {
+ struct pipe_ctx *head_pipe =
+ resource_is_pipe_type(&existing_state->res_ctx.pipe_ctx[i], DPP_PIPE) ?
+ resource_get_primary_dpp_pipe(&existing_state->res_ctx.pipe_ctx[i]) :
+ NULL;
+
+ // we should always respect the head pipe from selection
+ if (head_pipe && head_pipe->pipe_idx == i)
+ continue;
if ((existing_state->res_ctx.pipe_ctx[i].plane_res.hubp &&
existing_state->res_ctx.pipe_ctx[i].plane_res.hubp->opp_id != i) ||
existing_state->res_ctx.pipe_ctx[i].stream_res.tg)
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
index ebd5df1a36e8..d9aaebfa3a0a 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
@@ -1093,14 +1093,11 @@ static bool setup_dsc_config(
if (!is_dsc_possible)
goto done;
- // Final decission: can we do DSC or not?
- if (is_dsc_possible) {
- // Fill out the rest of DSC settings
- dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported;
- dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth;
- dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4;
- dsc_cfg->is_dp = dsc_sink_caps->is_dp;
- }
+ /* Fill out the rest of DSC settings */
+ dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported;
+ dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth;
+ dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4;
+ dsc_cfg->is_dp = dsc_sink_caps->is_dp;
done:
if (!is_dsc_possible)
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
index 4bd1dda07719..9fbd45c7dfef 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
@@ -200,6 +200,7 @@ struct dcn_hubbub_registers {
uint32_t DCHUBBUB_ARB_FRAC_URG_BW_MALL_B;
uint32_t DCHUBBUB_TIMEOUT_DETECTION_CTRL1;
uint32_t DCHUBBUB_TIMEOUT_DETECTION_CTRL2;
+ uint32_t DCHUBBUB_CTRL_STATUS;
};
#define HUBBUB_REG_FIELD_LIST_DCN32(type) \
@@ -320,7 +321,12 @@ struct dcn_hubbub_registers {
type DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD;\
type DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD;\
type DCHUBBUB_TIMEOUT_DETECTION_EN;\
- type DCHUBBUB_TIMEOUT_TIMER_RESET
+ type DCHUBBUB_TIMEOUT_TIMER_RESET;\
+ type ROB_UNDERFLOW_STATUS;\
+ type ROB_OVERFLOW_STATUS;\
+ type ROB_OVERFLOW_CLEAR;\
+ type DCHUBBUB_HW_DEBUG;\
+ type CSTATE_SWATH_CHK_GOOD_MODE
#define HUBBUB_STUTTER_REG_FIELD_LIST(type) \
type DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A;\
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h
index 036bb3e6c957..46d8f5c70750 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h
@@ -96,6 +96,7 @@ struct dcn20_hubbub {
unsigned int det1_size;
unsigned int det2_size;
unsigned int det3_size;
+ bool allow_sdpif_rate_limit_when_cstate_req;
};
void hubbub2_construct(struct dcn20_hubbub *hubbub,
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
index 5d658e9bef64..92fab471b183 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
@@ -1192,15 +1192,35 @@ static void dcn401_wait_for_det_update(struct hubbub *hubbub, int hubp_inst)
}
}
-static void dcn401_program_timeout_thresholds(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs)
+static bool dcn401_program_arbiter(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, bool safe_to_lower)
{
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ bool wm_pending = false;
+ uint32_t temp;
+
/* request backpressure and outstanding return threshold (unused)*/
//REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, arb_regs->req_stall_threshold);
/* P-State stall threshold */
REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, arb_regs->pstate_stall_threshold);
+
+ if (safe_to_lower || arb_regs->allow_sdpif_rate_limit_when_cstate_req > hubbub2->allow_sdpif_rate_limit_when_cstate_req) {
+ hubbub2->allow_sdpif_rate_limit_when_cstate_req = arb_regs->allow_sdpif_rate_limit_when_cstate_req;
+
+ /* only update the required bits */
+ REG_GET(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, &temp);
+ if (hubbub2->allow_sdpif_rate_limit_when_cstate_req) {
+ temp |= (1 << 5);
+ } else {
+ temp &= ~(1 << 5);
+ }
+ REG_UPDATE(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, temp);
+ } else {
+ wm_pending = true;
+ }
+
+ return wm_pending;
}
static const struct hubbub_funcs hubbub4_01_funcs = {
@@ -1226,7 +1246,7 @@ static const struct hubbub_funcs hubbub4_01_funcs = {
.program_det_segments = dcn401_program_det_segments,
.program_compbuf_segments = dcn401_program_compbuf_segments,
.wait_for_det_update = dcn401_wait_for_det_update,
- .program_timeout_thresholds = dcn401_program_timeout_thresholds,
+ .program_arbiter = dcn401_program_arbiter,
};
void hubbub401_construct(struct dcn20_hubbub *hubbub2,
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h
index 5f1960722ebd..b1d9ea9d1c3d 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h
@@ -128,7 +128,12 @@
HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, mask_sh),\
HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, mask_sh),\
HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_DETECTION_EN, mask_sh),\
- HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_TIMER_RESET, mask_sh)
+ HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_TIMER_RESET, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_UNDERFLOW_STATUS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_STATUS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_CLEAR, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, CSTATE_SWATH_CHK_GOOD_MODE, mask_sh)
bool hubbub401_program_urgent_watermarks(
struct hubbub *hubbub,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index 05424a9af58b..b029ec1b26d3 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -1925,9 +1925,9 @@ static void dcn20_program_pipe(
dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size);
}
- if (pipe_ctx->update_flags.raw ||
- (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) ||
- pipe_ctx->stream->update_flags.raw)
+ if (pipe_ctx->plane_state && (pipe_ctx->update_flags.raw ||
+ pipe_ctx->plane_state->update_flags.raw ||
+ pipe_ctx->stream->update_flags.raw))
dcn20_update_dchubp_dpp(dc, pipe_ctx, context);
if (pipe_ctx->plane_state && (pipe_ctx->update_flags.bits.enable ||
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index e8cc1bfa73f3..5de11e2837c0 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -1488,6 +1488,10 @@ void dcn401_prepare_bandwidth(struct dc *dc,
&context->bw_ctx.bw.dcn.watermarks,
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
false);
+ /* update timeout thresholds */
+ if (hubbub->funcs->program_arbiter) {
+ dc->wm_optimized_required |= hubbub->funcs->program_arbiter(hubbub, &context->bw_ctx.bw.dcn.arb_regs, false);
+ }
/* decrease compbuf size */
if (hubbub->funcs->program_compbuf_segments) {
@@ -1529,6 +1533,10 @@ void dcn401_optimize_bandwidth(
&context->bw_ctx.bw.dcn.watermarks,
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
true);
+ /* update timeout thresholds */
+ if (hubbub->funcs->program_arbiter) {
+ hubbub->funcs->program_arbiter(hubbub, &context->bw_ctx.bw.dcn.arb_regs, true);
+ }
if (dc->clk_mgr->dc_mode_softmax_enabled)
if (dc->clk_mgr->clks.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
@@ -1554,11 +1562,6 @@ void dcn401_optimize_bandwidth(
pipe_ctx->dlg_regs.min_dst_y_next_start);
}
}
-
- /* update timeout thresholds */
- if (hubbub->funcs->program_timeout_thresholds) {
- hubbub->funcs->program_timeout_thresholds(hubbub, &context->bw_ctx.bw.dcn.arb_regs);
- }
}
void dcn401_fams2_global_control_lock(struct dc *dc,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
index 6c1d41c0f099..52b745667ef7 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -228,7 +228,7 @@ struct hubbub_funcs {
void (*program_det_segments)(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_seg);
void (*program_compbuf_segments)(struct hubbub *hubbub, unsigned compbuf_size_seg, bool safe_to_increase);
void (*wait_for_det_update)(struct hubbub *hubbub, int hubp_inst);
- void (*program_timeout_thresholds)(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs);
+ bool (*program_arbiter)(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, bool safe_to_lower);
};
struct hubbub {
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
index 7c8d61db153d..19568c359669 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
@@ -612,7 +612,8 @@ void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context);
SR(DCHUBBUB_SDPIF_CFG1), \
SR(DCHUBBUB_MEM_PWR_MODE_CTRL), \
SR(DCHUBBUB_TIMEOUT_DETECTION_CTRL1), \
- SR(DCHUBBUB_TIMEOUT_DETECTION_CTRL2)
+ SR(DCHUBBUB_TIMEOUT_DETECTION_CTRL2), \
+ SR(DCHUBBUB_CTRL_STATUS)
/* DCCG */
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
index 614276200aa0..73a65913cb12 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
@@ -99,7 +99,7 @@ static struct spl_rect calculate_plane_rec_in_timing_active(
*
* recout_x = 128 + round(plane_x * 2304 / 1920)
* recout_w = 128 + round((plane_x + plane_w) * 2304 / 1920) - recout_x
- * recout_y = 0 + round(plane_y * 1440 / 1280)
+ * recout_y = 0 + round(plane_y * 1440 / 1200)
* recout_h = 0 + round((plane_y + plane_h) * 1440 / 1200) - recout_y
*
* NOTE: fixed point division is not error free. To reduce errors
@@ -739,14 +739,13 @@ static enum scl_mode spl_get_dscl_mode(const struct spl_in *spl_in,
return SCL_MODE_SCALING_444_RGB_ENABLE;
}
- /* Bypass YUV if at 1:1 with no ISHARP or if doing 2:1 YUV
- * downscale without EASF
+ /*
+ * Bypass YUV if Y is 1:1 with no ISHARP
+ * Do not bypass UV at 1:1 for cositing to be applied
*/
- if ((!enable_isharp) && (!enable_easf)) {
+ if (!enable_isharp) {
if (data->ratios.horz.value == one && data->ratios.vert.value == one)
return SCL_MODE_SCALING_420_LUMA_BYPASS;
- if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one)
- return SCL_MODE_SCALING_420_CHROMA_BYPASS;
}
return SCL_MODE_SCALING_420_YCBCR_ENABLE;
@@ -933,6 +932,7 @@ static bool spl_get_optimal_number_of_taps(
int min_taps_y, min_taps_c;
enum lb_memory_config lb_config;
bool skip_easf = false;
+ bool is_ycbcr = spl_dscl_is_video_format(spl_in->basic_in.format);
if (spl_scratch->scl_data.viewport.width > spl_scratch->scl_data.h_active &&
max_downscale_src_width != 0 &&
@@ -1074,10 +1074,9 @@ static bool spl_get_optimal_number_of_taps(
/* Sharpener requires scaler to be enabled, including for 1:1
* Check if ISHARP can be enabled
- * If ISHARP is not enabled, for 1:1, set taps to 1 and disable
- * EASF
- * For case of 2:1 YUV where chroma is 1:1, set taps to 1 if
- * EASF is not enabled
+ * If ISHARP is not enabled, set taps to 1 if ratio is 1:1
+ * except for chroma taps. Keep previous taps so it can
+ * handle cositing
*/
*enable_isharp = spl_get_isharp_en(spl_in, spl_scratch);
@@ -1087,20 +1086,28 @@ static bool spl_get_optimal_number_of_taps(
spl_scratch->scl_data.taps.h_taps = 1;
spl_scratch->scl_data.taps.v_taps = 1;
- if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c))
+ if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c) && !is_ycbcr)
spl_scratch->scl_data.taps.h_taps_c = 1;
- if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c))
+ if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c) && !is_ycbcr)
spl_scratch->scl_data.taps.v_taps_c = 1;
*enable_easf_v = false;
*enable_easf_h = false;
} else {
if ((!*enable_easf_h) &&
+ (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz)))
+ spl_scratch->scl_data.taps.h_taps = 1;
+
+ if ((!*enable_easf_v) &&
+ (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert)))
+ spl_scratch->scl_data.taps.v_taps = 1;
+
+ if ((!*enable_easf_h) && !is_ycbcr &&
(IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c)))
spl_scratch->scl_data.taps.h_taps_c = 1;
- if ((!*enable_easf_v) &&
+ if ((!*enable_easf_v) && !is_ycbcr &&
(IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c)))
spl_scratch->scl_data.taps.v_taps_c = 1;
}
@@ -1111,8 +1118,7 @@ static bool spl_get_optimal_number_of_taps(
static void spl_set_black_color_data(enum spl_pixel_format format,
struct scl_black_color *scl_black_color)
{
- bool ycbcr = format >= SPL_PIXEL_FORMAT_VIDEO_BEGIN
- && format <= SPL_PIXEL_FORMAT_VIDEO_END;
+ bool ycbcr = spl_dscl_is_video_format(format);
if (ycbcr) {
scl_black_color->offset_rgb_y = BLACK_OFFSET_RGB_Y;
scl_black_color->offset_rgb_cbcr = BLACK_OFFSET_CBCR;
@@ -1746,6 +1752,32 @@ static void spl_set_isharp_data(struct dscl_prog_data *dscl_prog_data,
spl_set_blur_scale_data(dscl_prog_data, data);
}
+/* Calculate recout, scaling ratio, and viewport, then get optimal number of taps */
+static bool spl_calculate_number_of_taps(struct spl_in *spl_in, struct spl_scratch *spl_scratch, struct spl_out *spl_out,
+ bool *enable_easf_v, bool *enable_easf_h, bool *enable_isharp)
+{
+ bool res = false;
+
+ memset(spl_scratch, 0, sizeof(struct spl_scratch));
+ spl_scratch->scl_data.h_active = spl_in->h_active;
+ spl_scratch->scl_data.v_active = spl_in->v_active;
+
+ // All SPL calls
+ /* recout calculation */
+ /* depends on h_active */
+ spl_calculate_recout(spl_in, spl_scratch, spl_out);
+ /* depends on pixel format */
+ spl_calculate_scaling_ratios(spl_in, spl_scratch, spl_out);
+ /* depends on scaling ratios and recout, does not calculate offset yet */
+ spl_calculate_viewport_size(spl_in, spl_scratch);
+
+ res = spl_get_optimal_number_of_taps(
+ spl_in->basic_out.max_downscale_src_width, spl_in,
+ spl_scratch, &spl_in->scaling_quality, enable_easf_v,
+ enable_easf_h, enable_isharp);
+ return res;
+}
+
/* Calculate scaler parameters */
bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out)
{
@@ -1760,23 +1792,9 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out)
bool enable_isharp = false;
const struct spl_scaler_data *data = &spl_scratch.scl_data;
- memset(&spl_scratch, 0, sizeof(struct spl_scratch));
- spl_scratch.scl_data.h_active = spl_in->h_active;
- spl_scratch.scl_data.v_active = spl_in->v_active;
+ res = spl_calculate_number_of_taps(spl_in, &spl_scratch, spl_out,
+ &enable_easf_v, &enable_easf_h, &enable_isharp);
- // All SPL calls
- /* recout calculation */
- /* depends on h_active */
- spl_calculate_recout(spl_in, &spl_scratch, spl_out);
- /* depends on pixel format */
- spl_calculate_scaling_ratios(spl_in, &spl_scratch, spl_out);
- /* depends on scaling ratios and recout, does not calculate offset yet */
- spl_calculate_viewport_size(spl_in, &spl_scratch);
-
- res = spl_get_optimal_number_of_taps(
- spl_in->basic_out.max_downscale_src_width, spl_in,
- &spl_scratch, &spl_in->scaling_quality, &enable_easf_v,
- &enable_easf_h, &enable_isharp);
/*
* Depends on recout, scaling ratios, h_active and taps
* May need to re-check lb size after this in some obscure scenario
@@ -1824,3 +1842,20 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out)
return res;
}
+
+/* External interface to get number of taps only */
+bool spl_get_number_of_taps(struct spl_in *spl_in, struct spl_out *spl_out)
+{
+ bool res = false;
+ bool enable_easf_v = false;
+ bool enable_easf_h = false;
+ bool enable_isharp = false;
+ struct spl_scratch spl_scratch;
+ struct dscl_prog_data *dscl_prog_data = spl_out->dscl_prog_data;
+ const struct spl_scaler_data *data = &spl_scratch.scl_data;
+
+ res = spl_calculate_number_of_taps(spl_in, &spl_scratch, spl_out,
+ &enable_easf_v, &enable_easf_h, &enable_isharp);
+ spl_set_taps_data(dscl_prog_data, data);
+ return res;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.h
index 205e59a2a8ee..02a2d6725ed5 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.h
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.h
@@ -13,4 +13,6 @@
bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out);
+bool spl_get_number_of_taps(struct spl_in *spl_in, struct spl_out *spl_out);
+
#endif /* __DC_SPL_H__ */
diff --git a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h
index 5ebe4cb40f9d..c38a01742d6f 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h
@@ -7571,6 +7571,8 @@
// base address: 0x10100000
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0 0xd000
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_BASE_IDX 5
+#define regRCC_DEV0_EPF5_STRAP4 0xd284
+#define regRCC_DEV0_EPF5_STRAP4_BASE_IDX 5
// addressBlock: nbio_nbif0_bif_rst_bif_rst_regblk
diff --git a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h
index eb8c556d9c93..3b96f1e5a180 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h
@@ -50665,6 +50665,19 @@
#define RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_D1_SUPPORT_DEV0_F0_MASK 0x40000000L
#define RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_D2_SUPPORT_DEV0_F0_MASK 0x80000000L
+//RCC_DEV0_EPF5_STRAP4
+#define RCC_DEV0_EPF5_STRAP4__STRAP_ATOMIC_64BIT_EN_DEV0_F5__SHIFT 0x14
+#define RCC_DEV0_EPF5_STRAP4__STRAP_ATOMIC_EN_DEV0_F5__SHIFT 0x15
+#define RCC_DEV0_EPF5_STRAP4__STRAP_FLR_EN_DEV0_F5__SHIFT 0x16
+#define RCC_DEV0_EPF5_STRAP4__STRAP_PME_SUPPORT_DEV0_F5__SHIFT 0x17
+#define RCC_DEV0_EPF5_STRAP4__STRAP_INTERRUPT_PIN_DEV0_F5__SHIFT 0x1c
+#define RCC_DEV0_EPF5_STRAP4__STRAP_AUXPWR_SUPPORT_DEV0_F5__SHIFT 0x1f
+#define RCC_DEV0_EPF5_STRAP4__STRAP_ATOMIC_64BIT_EN_DEV0_F5_MASK 0x00100000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_ATOMIC_EN_DEV0_F5_MASK 0x00200000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_FLR_EN_DEV0_F5_MASK 0x00400000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_PME_SUPPORT_DEV0_F5_MASK 0x0F800000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_INTERRUPT_PIN_DEV0_F5_MASK 0x70000000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_AUXPWR_SUPPORT_DEV0_F5_MASK 0x80000000L
// addressBlock: nbio_nbif0_bif_rst_bif_rst_regblk
//HARD_RST_CTRL
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index bb27c0d2a9ae..67a5de573943 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -357,11 +357,22 @@ struct dpm_clocks;
struct amdgpu_xcp_metrics {
/* Utilization Instantaneous (%) */
- u32 gfx_busy_inst[MAX_XCC];
- u16 jpeg_busy[NUM_JPEG_ENG];
- u16 vcn_busy[NUM_VCN];
+ uint32_t gfx_busy_inst[MAX_XCC];
+ uint16_t jpeg_busy[NUM_JPEG_ENG];
+ uint16_t vcn_busy[NUM_VCN];
/* Utilization Accumulated (%) */
- u64 gfx_busy_acc[MAX_XCC];
+ uint64_t gfx_busy_acc[MAX_XCC];
+};
+
+struct amdgpu_xcp_metrics_v1_1 {
+ /* Utilization Instantaneous (%) */
+ uint32_t gfx_busy_inst[MAX_XCC];
+ uint16_t jpeg_busy[NUM_JPEG_ENG];
+ uint16_t vcn_busy[NUM_VCN];
+ /* Utilization Accumulated (%) */
+ uint64_t gfx_busy_acc[MAX_XCC];
+ /* Total App Clock Counter Accumulated */
+ uint64_t gfx_below_host_limit_acc[MAX_XCC];
};
struct amd_pm_funcs {
@@ -977,6 +988,105 @@ struct gpu_metrics_v1_6 {
uint32_t pcie_lc_perf_other_end_recovery;
};
+struct gpu_metrics_v1_7 {
+ struct metrics_table_header common_header;
+
+ /* Temperature (Celsius) */
+ uint16_t temperature_hotspot;
+ uint16_t temperature_mem;
+ uint16_t temperature_vrsoc;
+
+ /* Power (Watts) */
+ uint16_t curr_socket_power;
+
+ /* Utilization (%) */
+ uint16_t average_gfx_activity;
+ uint16_t average_umc_activity; // memory controller
+
+ /* VRAM max bandwidthi (in GB/sec) at max memory clock */
+ uint64_t mem_max_bandwidth;
+
+ /* Energy (15.259uJ (2^-16) units) */
+ uint64_t energy_accumulator;
+
+ /* Driver attached timestamp (in ns) */
+ uint64_t system_clock_counter;
+
+ /* Accumulation cycle counter */
+ uint32_t accumulation_counter;
+
+ /* Accumulated throttler residencies */
+ uint32_t prochot_residency_acc;
+ uint32_t ppt_residency_acc;
+ uint32_t socket_thm_residency_acc;
+ uint32_t vr_thm_residency_acc;
+ uint32_t hbm_thm_residency_acc;
+
+ /* Clock Lock Status. Each bit corresponds to clock instance */
+ uint32_t gfxclk_lock_status;
+
+ /* Link width (number of lanes) and speed (in 0.1 GT/s) */
+ uint16_t pcie_link_width;
+ uint16_t pcie_link_speed;
+
+ /* XGMI bus width and bitrate (in Gbps) */
+ uint16_t xgmi_link_width;
+ uint16_t xgmi_link_speed;
+
+ /* Utilization Accumulated (%) */
+ uint32_t gfx_activity_acc;
+ uint32_t mem_activity_acc;
+
+ /*PCIE accumulated bandwidth (GB/sec) */
+ uint64_t pcie_bandwidth_acc;
+
+ /*PCIE instantaneous bandwidth (GB/sec) */
+ uint64_t pcie_bandwidth_inst;
+
+ /* PCIE L0 to recovery state transition accumulated count */
+ uint64_t pcie_l0_to_recov_count_acc;
+
+ /* PCIE replay accumulated count */
+ uint64_t pcie_replay_count_acc;
+
+ /* PCIE replay rollover accumulated count */
+ uint64_t pcie_replay_rover_count_acc;
+
+ /* PCIE NAK sent accumulated count */
+ uint32_t pcie_nak_sent_count_acc;
+
+ /* PCIE NAK received accumulated count */
+ uint32_t pcie_nak_rcvd_count_acc;
+
+ /* XGMI accumulated data transfer size(KiloBytes) */
+ uint64_t xgmi_read_data_acc[NUM_XGMI_LINKS];
+ uint64_t xgmi_write_data_acc[NUM_XGMI_LINKS];
+
+ /* XGMI link status(active/inactive) */
+ uint16_t xgmi_link_status[NUM_XGMI_LINKS];
+
+ uint16_t padding;
+
+ /* PMFW attached timestamp (10ns resolution) */
+ uint64_t firmware_timestamp;
+
+ /* Current clocks (Mhz) */
+ uint16_t current_gfxclk[MAX_GFX_CLKS];
+ uint16_t current_socclk[MAX_CLKS];
+ uint16_t current_vclk0[MAX_CLKS];
+ uint16_t current_dclk0[MAX_CLKS];
+ uint16_t current_uclk;
+
+ /* Number of current partition */
+ uint16_t num_partition;
+
+ /* XCP metrics stats */
+ struct amdgpu_xcp_metrics_v1_1 xcp_stats[NUM_XCP];
+
+ /* PCIE other end recovery counter */
+ uint32_t pcie_lc_perf_other_end_recovery;
+};
+
/*
* gpu_metrics_v2_0 is not recommended as it's not naturally aligned.
* Use gpu_metrics_v2_1 or later instead.
diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c
index b52ce135d84d..d3ff6a831ed5 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c
@@ -257,20 +257,18 @@ static int vega12_smu_init(struct pp_hwmgr *hwmgr)
priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t);
tools_size = 0x19000;
- if (tools_size) {
- ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
- tools_size,
- PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
- &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
- &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
- if (ret)
- goto err1;
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+ tools_size,
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
+ if (ret)
+ goto err1;
- priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
- priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
- }
+ priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
+ priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
/* allocate space for AVFS Fuse table */
ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 64f917959576..b8355293518f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -1704,7 +1704,9 @@ static int smu_smc_hw_setup(struct smu_context *smu)
return ret;
}
- if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
+ if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5)
+ pcie_gen = 4;
+ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
pcie_gen = 3;
else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
pcie_gen = 2;
@@ -1717,7 +1719,9 @@ static int smu_smc_hw_setup(struct smu_context *smu)
* Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4
* Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32
*/
- if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
+ if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X32)
+ pcie_width = 7;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
pcie_width = 6;
else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
pcie_width = 5;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
index 0546b02e198d..29a4583db873 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
@@ -53,7 +53,7 @@
#define CTF_OFFSET_MEM 5
extern const int decoded_link_speed[5];
-extern const int decoded_link_width[7];
+extern const int decoded_link_width[8];
#define DECODE_GEN_SPEED(gen_speed_idx) (decoded_link_speed[gen_speed_idx])
#define DECODE_LANE_WIDTH(lane_width_idx) (decoded_link_width[lane_width_idx])
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 4b36c230e43a..12125303bb79 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1344,8 +1344,12 @@ static int arcturus_get_power_limit(struct smu_context *smu,
*default_power_limit = power_limit;
if (max_power_limit)
*max_power_limit = power_limit;
+ /**
+ * No lower bound is imposed on the limit. Any unreasonable limit set
+ * will result in frequent throttling.
+ */
if (min_power_limit)
- *min_power_limit = power_limit;
+ *min_power_limit = 0;
return 0;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
index fa30a9e1f27a..ab3c93ddce46 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@ -96,7 +96,6 @@ MODULE_FIRMWARE("amdgpu/smu_13_0_14.bin");
#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0xE0
#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0x5
#define LINK_SPEED_MAX 4
-
#define SMU_13_0_6_DSCLK_THRESHOLD 140
#define MCA_BANK_IPID(_ip, _hwid, _type) \
@@ -370,7 +369,7 @@ static int smu_v13_0_6_tables_init(struct smu_context *smu)
return -ENOMEM;
smu_table->metrics_time = 0;
- smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_6);
+ smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_7);
smu_table->gpu_metrics_table =
kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
if (!smu_table->gpu_metrics_table) {
@@ -2321,8 +2320,8 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
{
bool per_inst, smu_13_0_6_per_inst, smu_13_0_14_per_inst, apu_per_inst;
struct smu_table_context *smu_table = &smu->smu_table;
- struct gpu_metrics_v1_6 *gpu_metrics =
- (struct gpu_metrics_v1_6 *)smu_table->gpu_metrics_table;
+ struct gpu_metrics_v1_7 *gpu_metrics =
+ (struct gpu_metrics_v1_7 *)smu_table->gpu_metrics_table;
bool flag = smu_v13_0_6_is_unified_metrics(smu);
int ret = 0, xcc_id, inst, i, j, k, idx;
struct amdgpu_device *adev = smu->adev;
@@ -2341,7 +2340,7 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
metrics_a = (MetricsTableA_t *)metrics_x;
- smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 6);
+ smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 7);
gpu_metrics->temperature_hotspot =
SMUQ10_ROUND(GET_METRIC_FIELD(MaxSocketTemperature, flag));
@@ -2448,6 +2447,9 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
SMUQ10_ROUND(GET_METRIC_FIELD(XgmiReadDataSizeAcc, flag)[i]);
gpu_metrics->xgmi_write_data_acc[i] =
SMUQ10_ROUND(GET_METRIC_FIELD(XgmiWriteDataSizeAcc, flag)[i]);
+ ret = amdgpu_get_xgmi_link_status(adev, i);
+ if (ret >= 0)
+ gpu_metrics->xgmi_link_status[i] = ret;
}
gpu_metrics->num_partition = adev->xcp_mgr->num_xcps;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
index c5d3e25cc967..4fd0354bd312 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -2147,6 +2147,8 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
+ gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
+ gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0];
gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_1];
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
index ecb0164d533e..a87040cb2f2e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
@@ -49,7 +49,7 @@
#define regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0_BASE_IDX 0
const int decoded_link_speed[5] = {1, 2, 3, 4, 5};
-const int decoded_link_width[7] = {0, 1, 2, 4, 8, 12, 16};
+const int decoded_link_width[8] = {0, 1, 2, 4, 8, 12, 16, 32};
/*
* DO NOT use these for err/warn/info/debug messages.
* Use dev_err, dev_warn, dev_info and dev_dbg instead.
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
index 59b369eff30f..687a0f5ac94f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
@@ -1173,13 +1173,15 @@ static int smu_v14_0_2_print_clk_levels(struct smu_context *smu,
(pcie_table->pcie_gen[i] == 0) ? "2.5GT/s," :
(pcie_table->pcie_gen[i] == 1) ? "5.0GT/s," :
(pcie_table->pcie_gen[i] == 2) ? "8.0GT/s," :
- (pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," : "",
+ (pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," :
+ (pcie_table->pcie_gen[i] == 4) ? "32.0GT/s," : "",
(pcie_table->pcie_lane[i] == 1) ? "x1" :
(pcie_table->pcie_lane[i] == 2) ? "x2" :
(pcie_table->pcie_lane[i] == 3) ? "x4" :
(pcie_table->pcie_lane[i] == 4) ? "x8" :
(pcie_table->pcie_lane[i] == 5) ? "x12" :
- (pcie_table->pcie_lane[i] == 6) ? "x16" : "",
+ (pcie_table->pcie_lane[i] == 6) ? "x16" :
+ (pcie_table->pcie_lane[i] == 7) ? "x32" : "",
pcie_table->clk_freq[i],
(gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) &&
(lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ?
@@ -1463,15 +1465,35 @@ static int smu_v14_0_2_update_pcie_parameters(struct smu_context *smu,
struct smu_14_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
struct smu_14_0_pcie_table *pcie_table =
&dpm_context->dpm_tables.pcie_table;
+ int num_of_levels = pcie_table->num_of_link_levels;
uint32_t smu_pcie_arg;
int ret, i;
- for (i = 0; i < pcie_table->num_of_link_levels; i++) {
- if (pcie_table->pcie_gen[i] > pcie_gen_cap)
+ if (!num_of_levels)
+ return 0;
+
+ if (!(smu->adev->pm.pp_feature & PP_PCIE_DPM_MASK)) {
+ if (pcie_table->pcie_gen[num_of_levels - 1] < pcie_gen_cap)
+ pcie_gen_cap = pcie_table->pcie_gen[num_of_levels - 1];
+
+ if (pcie_table->pcie_lane[num_of_levels - 1] < pcie_width_cap)
+ pcie_width_cap = pcie_table->pcie_lane[num_of_levels - 1];
+
+ /* Force all levels to use the same settings */
+ for (i = 0; i < num_of_levels; i++) {
pcie_table->pcie_gen[i] = pcie_gen_cap;
- if (pcie_table->pcie_lane[i] > pcie_width_cap)
pcie_table->pcie_lane[i] = pcie_width_cap;
+ }
+ } else {
+ for (i = 0; i < num_of_levels; i++) {
+ if (pcie_table->pcie_gen[i] > pcie_gen_cap)
+ pcie_table->pcie_gen[i] = pcie_gen_cap;
+ if (pcie_table->pcie_lane[i] > pcie_width_cap)
+ pcie_table->pcie_lane[i] = pcie_width_cap;
+ }
+ }
+ for (i = 0; i < num_of_levels; i++) {
smu_pcie_arg = i << 16;
smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
smu_pcie_arg |= pcie_table->pcie_lane[i];
@@ -2753,7 +2775,6 @@ static const struct pptable_funcs smu_v14_0_2_ppt_funcs = {
.get_unique_id = smu_v14_0_2_get_unique_id,
.get_power_limit = smu_v14_0_2_get_power_limit,
.set_power_limit = smu_v14_0_2_set_power_limit,
- .set_power_source = smu_v14_0_set_power_source,
.get_power_profile_mode = smu_v14_0_2_get_power_profile_mode,
.set_power_profile_mode = smu_v14_0_2_set_power_profile_mode,
.run_btc = smu_v14_0_run_btc,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index f1ab1a6bb467..dbbd3759bff3 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -1081,6 +1081,9 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev)
case METRICS_VERSION(1, 6):
structure_size = sizeof(struct gpu_metrics_v1_6);
break;
+ case METRICS_VERSION(1, 7):
+ structure_size = sizeof(struct gpu_metrics_v1_7);
+ break;
case METRICS_VERSION(2, 0):
structure_size = sizeof(struct gpu_metrics_v2_0);
break;
diff --git a/drivers/gpu/drm/display/drm_dp_aux_bus.c b/drivers/gpu/drm/display/drm_dp_aux_bus.c
index d810529ebfb6..ec7eac6b595f 100644
--- a/drivers/gpu/drm/display/drm_dp_aux_bus.c
+++ b/drivers/gpu/drm/display/drm_dp_aux_bus.c
@@ -292,7 +292,7 @@ int of_dp_aux_populate_bus(struct drm_dp_aux *aux,
aux_ep->dev.parent = aux->dev;
aux_ep->dev.bus = &dp_aux_bus_type;
aux_ep->dev.type = &dp_aux_device_type_type;
- aux_ep->dev.of_node = of_node_get(np);
+ device_set_node(&aux_ep->dev, of_fwnode_handle(of_node_get(np)));
dev_set_name(&aux_ep->dev, "aux-%s", dev_name(aux->dev));
ret = device_register(&aux_ep->dev);
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c
index f6d42ec6949e..f57e4dba2873 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -1503,6 +1503,8 @@ static int hdcp2_deauthenticate_port(struct intel_connector *connector)
static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
+ struct intel_digital_port *dig_port =
+ intel_attached_dig_port(connector);
struct intel_hdcp *hdcp = &connector->hdcp;
union {
struct hdcp2_ake_init ake_init;
@@ -1513,30 +1515,36 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
} msgs;
const struct intel_hdcp_shim *shim = hdcp->shim;
size_t size;
- int ret, i;
+ int ret, i, max_retries;
/* Init for seq_num */
hdcp->seq_num_v = 0;
hdcp->seq_num_m = 0;
+ if (intel_encoder_is_dp(&dig_port->base) ||
+ intel_encoder_is_mst(&dig_port->base))
+ max_retries = 10;
+ else
+ max_retries = 1;
+
ret = hdcp2_prepare_ake_init(connector, &msgs.ake_init);
if (ret < 0)
return ret;
/*
* Retry the first read and write to downstream at least 10 times
- * with a 50ms delay if not hdcp2 capable(dock decides to stop advertising
- * hdcp2 capability for some reason). The reason being that
- * during suspend resume dock usually keeps the HDCP2 registers inaccesible
- * causing AUX error. This wouldn't be a big problem if the userspace
- * just kept retrying with some delay while it continues to play low
- * value content but most userpace applications end up throwing an error
- * when it receives one from KMD. This makes sure we give the dock
- * and the sink devices to complete its power cycle and then try HDCP
- * authentication. The values of 10 and delay of 50ms was decided based
- * on multiple trial and errors.
+ * with a 50ms delay if not hdcp2 capable for DP/DPMST encoders
+ * (dock decides to stop advertising hdcp2 capability for some reason).
+ * The reason being that during suspend resume dock usually keeps the
+ * HDCP2 registers inaccesible causing AUX error. This wouldn't be a
+ * big problem if the userspace just kept retrying with some delay while
+ * it continues to play low value content but most userpace applications
+ * end up throwing an error when it receives one from KMD. This makes
+ * sure we give the dock and the sink devices to complete its power cycle
+ * and then try HDCP authentication. The values of 10 and delay of 50ms
+ * was decided based on multiple trial and errors.
*/
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < max_retries; i++) {
if (!intel_hdcp2_get_capability(connector)) {
msleep(50);
continue;
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
index 47aa06a9a942..5b69cc8011b4 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.c
+++ b/drivers/gpu/drm/radeon/radeon_audio.c
@@ -760,16 +760,20 @@ static int radeon_audio_component_get_eld(struct device *kdev, int port,
if (!rdev->audio.enabled || !rdev->mode_info.mode_config_initialized)
return 0;
- list_for_each_entry(encoder, &rdev_to_drm(rdev)->mode_config.encoder_list, head) {
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ const struct drm_connector_helper_funcs *connector_funcs =
+ connector->helper_private;
+ encoder = connector_funcs->best_encoder(connector);
+
+ if (!encoder)
+ continue;
+
if (!radeon_encoder_is_digital(encoder))
continue;
radeon_encoder = to_radeon_encoder(encoder);
dig = radeon_encoder->enc_priv;
if (!dig->pin || dig->pin->id != port)
continue;
- connector = radeon_get_connector_for_encoder(encoder);
- if (!connector)
- continue;
*enabled = true;
ret = drm_eld_size(connector->eld);
memcpy(buf, connector->eld, min(max_bytes, ret));
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index f9c73c55f04f..f9996304d943 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -1255,16 +1255,6 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
goto exit;
}
}
-
- if (dret && radeon_connector->hpd.hpd != RADEON_HPD_NONE &&
- !radeon_hpd_sense(rdev, radeon_connector->hpd.hpd) &&
- connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) {
- DRM_DEBUG_KMS("EDID is readable when HPD disconnected\n");
- schedule_delayed_work(&rdev->hotplug_work, msecs_to_jiffies(1000));
- ret = connector_status_disconnected;
- goto exit;
- }
-
if (dret) {
radeon_connector->detected_by_load = false;
radeon_connector_free_edid(connector);
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 23d6d1a2586d..5e958cc223f4 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -248,10 +248,9 @@ int radeon_cik_support = 1;
MODULE_PARM_DESC(cik_support, "CIK support (1 = enabled (default), 0 = disabled)");
module_param_named(cik_support, radeon_cik_support, int, 0444);
-static struct pci_device_id pciidlist[] = {
+static const struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
};
-
MODULE_DEVICE_TABLE(pci, pciidlist);
static const struct drm_driver kms_driver;
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 69d0c12fa419..616d25c8c2de 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -219,8 +219,7 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict,
if (old_mem->mem_type == TTM_PL_TT &&
new_mem->mem_type == TTM_PL_SYSTEM) {
radeon_ttm_tt_unbind(bo->bdev, bo->ttm);
- ttm_resource_free(bo, &bo->resource);
- ttm_bo_assign_mem(bo, new_mem);
+ ttm_bo_move_null(bo, new_mem);
goto out;
}
if (rdev->ring[radeon_copy_ring_index(rdev)].ready &&
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
index 9c796ee4c303..c8b362cc2b95 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -82,7 +82,7 @@ static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
* comment in rk_hdptx_phy_power_on() from
* drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
*/
- phy_set_bus_width(hdmi->phy, rate / 100);
+ phy_set_bus_width(hdmi->phy, div_u64(rate, 100));
}
}
diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c
index d2679c5d976b..0b0cd6aa1d9f 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump.c
+++ b/drivers/gpu/drm/xe/xe_devcoredump.c
@@ -23,6 +23,7 @@
#include "xe_guc_submit.h"
#include "xe_hw_engine.h"
#include "xe_module.h"
+#include "xe_pm.h"
#include "xe_sched_job.h"
#include "xe_vm.h"
@@ -158,8 +159,11 @@ static void xe_devcoredump_deferred_snap_work(struct work_struct *work)
{
struct xe_devcoredump_snapshot *ss = container_of(work, typeof(*ss), work);
struct xe_devcoredump *coredump = container_of(ss, typeof(*coredump), snapshot);
+ struct xe_device *xe = coredump_to_xe(coredump);
unsigned int fw_ref;
+ xe_pm_runtime_get(xe);
+
/* keep going if fw fails as we still want to save the memory and SW data */
fw_ref = xe_force_wake_get(gt_to_fw(ss->gt), XE_FORCEWAKE_ALL);
if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
@@ -168,6 +172,8 @@ static void xe_devcoredump_deferred_snap_work(struct work_struct *work)
xe_guc_exec_queue_snapshot_capture_delayed(ss->ge);
xe_force_wake_put(gt_to_fw(ss->gt), fw_ref);
+ xe_pm_runtime_put(xe);
+
/* Calculate devcoredump size */
ss->read.size = __xe_devcoredump_read(NULL, INT_MAX, coredump);
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 0e2dd691bdae..06d6db8b50f9 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -350,7 +350,8 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
INIT_LIST_HEAD(&xe->pinned.external_vram);
INIT_LIST_HEAD(&xe->pinned.evicted);
- xe->preempt_fence_wq = alloc_ordered_workqueue("xe-preempt-fence-wq", 0);
+ xe->preempt_fence_wq = alloc_ordered_workqueue("xe-preempt-fence-wq",
+ WQ_MEM_RECLAIM);
xe->ordered_wq = alloc_ordered_workqueue("xe-ordered-wq", 0);
xe->unordered_wq = alloc_workqueue("xe-unordered-wq", 0, 0);
xe->destroy_wq = alloc_workqueue("xe-destroy-wq", 0, 0);
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 9a8564ea06b5..6f4a9812b4f4 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -767,17 +767,19 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
struct xe_exec_queue *q)
{
MAKE_SCHED_CONTEXT_ACTION(q, DISABLE);
- struct xe_device *xe = guc_to_xe(guc);
int ret;
set_min_preemption_timeout(guc, q);
smp_rmb();
- ret = wait_event_timeout(guc->ct.wq, !exec_queue_pending_enable(q) ||
- xe_guc_read_stopped(guc), HZ * 5);
+ ret = wait_event_timeout(guc->ct.wq,
+ (!exec_queue_pending_enable(q) &&
+ !exec_queue_pending_disable(q)) ||
+ xe_guc_read_stopped(guc),
+ HZ * 5);
if (!ret) {
struct xe_gpu_scheduler *sched = &q->guc->sched;
- drm_warn(&xe->drm, "Pending enable failed to respond");
+ xe_gt_warn(q->gt, "Pending enable/disable failed to respond\n");
xe_sched_submission_start(sched);
xe_gt_reset_async(q->gt);
xe_sched_tdr_queue_imm(sched);
@@ -1099,7 +1101,8 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
* modifying state
*/
ret = wait_event_timeout(guc->ct.wq,
- !exec_queue_pending_enable(q) ||
+ (!exec_queue_pending_enable(q) &&
+ !exec_queue_pending_disable(q)) ||
xe_guc_read_stopped(guc), HZ * 5);
if (!ret || xe_guc_read_stopped(guc))
goto trigger_reset;
@@ -1328,8 +1331,8 @@ static void __guc_exec_queue_process_msg_suspend(struct xe_sched_msg *msg)
if (guc_exec_queue_allowed_to_change_state(q) && !exec_queue_suspended(q) &&
exec_queue_enabled(q)) {
- wait_event(guc->ct.wq, q->guc->resume_time != RESUME_PENDING ||
- xe_guc_read_stopped(guc));
+ wait_event(guc->ct.wq, (q->guc->resume_time != RESUME_PENDING ||
+ xe_guc_read_stopped(guc)) && !exec_queue_pending_disable(q));
if (!xe_guc_read_stopped(guc)) {
s64 since_resume_ms =
@@ -1866,16 +1869,29 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q,
xe_gt_assert(guc_to_gt(guc), runnable_state == 0);
xe_gt_assert(guc_to_gt(guc), exec_queue_pending_disable(q));
- clear_exec_queue_pending_disable(q);
if (q->guc->suspend_pending) {
suspend_fence_signal(q);
+ clear_exec_queue_pending_disable(q);
} else {
if (exec_queue_banned(q) || check_timeout) {
smp_wmb();
wake_up_all(&guc->ct.wq);
}
- if (!check_timeout)
+ if (!check_timeout && exec_queue_destroyed(q)) {
+ /*
+ * Make sure to clear the pending_disable only
+ * after sampling the destroyed state. We want
+ * to ensure we don't trigger the unregister too
+ * early with something intending to only
+ * disable scheduling. The caller doing the
+ * destroy must wait for an ongoing
+ * pending_disable before marking as destroyed.
+ */
+ clear_exec_queue_pending_disable(q);
deregister_exec_queue(guc, q);
+ } else {
+ clear_exec_queue_pending_disable(q);
+ }
}
}
}
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index cfd31ae49cc1..1b97d90aadda 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -209,7 +209,8 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m,
num_entries * XE_PAGE_SIZE,
ttm_bo_type_kernel,
XE_BO_FLAG_VRAM_IF_DGFX(tile) |
- XE_BO_FLAG_PINNED);
+ XE_BO_FLAG_PINNED |
+ XE_BO_FLAG_PAGETABLE);
if (IS_ERR(bo))
return PTR_ERR(bo);
@@ -1350,6 +1351,7 @@ __xe_migrate_update_pgtables(struct xe_migrate *m,
/* For sysmem PTE's, need to map them in our hole.. */
if (!IS_DGFX(xe)) {
+ u16 pat_index = xe->pat.idx[XE_CACHE_WB];
u32 ptes, ofs;
ppgtt_ofs = NUM_KERNEL_PDE - 1;
@@ -1409,7 +1411,7 @@ __xe_migrate_update_pgtables(struct xe_migrate *m,
pt_bo->update_index = current_update;
addr = vm->pt_ops->pte_encode_bo(pt_bo, 0,
- XE_CACHE_WB, 0);
+ pat_index, 0);
bb->cs[bb->len++] = lower_32_bits(addr);
bb->cs[bb->len++] = upper_32_bits(addr);
}
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index e6640283893f..6b7f77425c7f 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -174,7 +174,7 @@ static const struct xe_graphics_desc graphics_xelpg = {
GENMASK(XE_HW_ENGINE_CCS3, XE_HW_ENGINE_CCS0)
static const struct xe_graphics_desc graphics_xe2 = {
- .name = "Xe2_LPG / Xe2_HPG",
+ .name = "Xe2_LPG / Xe2_HPG / Xe3_LPG",
XE2_GFX_FEATURES,
};
diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c
index a90480c6aecf..42f5bebd09e5 100644
--- a/drivers/gpu/drm/xe/xe_sync.c
+++ b/drivers/gpu/drm/xe/xe_sync.c
@@ -87,8 +87,12 @@ static void user_fence_worker(struct work_struct *w)
drm_dbg(&ufence->xe->drm, "mmget_not_zero() failed, ufence wasn't signaled\n");
}
- wake_up_all(&ufence->xe->ufence_wq);
+ /*
+ * Wake up waiters only after updating the ufence state, allowing the UMD
+ * to safely reuse the same ufence without encountering -EBUSY errors.
+ */
WRITE_ONCE(ufence->signalled, 1);
+ wake_up_all(&ufence->xe->ufence_wq);
user_fence_put(ufence);
}
diff --git a/drivers/greybus/interface.c b/drivers/greybus/interface.c
index d022bfb5e95d..a0f3e9422721 100644
--- a/drivers/greybus/interface.c
+++ b/drivers/greybus/interface.c
@@ -780,7 +780,7 @@ const struct device_type greybus_interface_type = {
* The position of interface within the Endo is encoded in "interface_id"
* argument.
*
- * Returns a pointer to the new interfce or a null pointer if a
+ * Returns a pointer to the new interface or a null pointer if a
* failure occurs due to memory exhaustion.
*/
struct gb_interface *gb_interface_create(struct gb_module *module,
diff --git a/drivers/iio/accel/adxl355_core.c b/drivers/iio/accel/adxl355_core.c
index eabaefa92f19..7ccd2f653b9b 100644
--- a/drivers/iio/accel/adxl355_core.c
+++ b/drivers/iio/accel/adxl355_core.c
@@ -643,7 +643,7 @@ static irqreturn_t adxl355_trigger_handler(int irq, void *p)
* The acceleration data is 24 bits and big endian. It has to be saved
* in 32 bits, hence, it is saved in the 2nd byte of the 4 byte buffer.
* The buf array is 14 bytes as it includes 3x4=12 bytes for
- * accelaration data of x, y, and z axis. It also includes 2 bytes for
+ * acceleration data of x, y, and z axis. It also includes 2 bytes for
* temperature data.
*/
ret = regmap_bulk_read(data->regmap, ADXL355_XDATA3_REG,
diff --git a/drivers/iio/accel/adxl367.c b/drivers/iio/accel/adxl367.c
index e790a66d86c7..705375f3b56e 100644
--- a/drivers/iio/accel/adxl367.c
+++ b/drivers/iio/accel/adxl367.c
@@ -1073,7 +1073,7 @@ static int adxl367_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
enum adxl367_activity_type act;
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index ef8dd557877b..5b9eb364760a 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -940,7 +940,7 @@ static int adxl372_read_event_config(struct iio_dev *indio_dev, const struct iio
static int adxl372_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan,
enum iio_event_type type, enum iio_event_direction dir,
- int state)
+ bool state)
{
struct adxl372_state *st = iio_priv(indio_dev);
diff --git a/drivers/iio/accel/adxl380.c b/drivers/iio/accel/adxl380.c
index f80527d899be..a1460120d9da 100644
--- a/drivers/iio/accel/adxl380.c
+++ b/drivers/iio/accel/adxl380.c
@@ -1181,7 +1181,7 @@ static int adxl380_read_raw(struct iio_dev *indio_dev,
ret = adxl380_read_chn(st, chan->address);
iio_device_release_direct_mode(indio_dev);
- if (ret)
+ if (ret < 0)
return ret;
*val = sign_extend32(ret >> chan->scan_type.shift,
@@ -1386,7 +1386,7 @@ static int adxl380_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct adxl380_state *st = iio_priv(indio_dev);
enum adxl380_axis axis;
@@ -1719,7 +1719,6 @@ static int adxl380_config_irq(struct iio_dev *indio_dev)
{
struct adxl380_state *st = iio_priv(indio_dev);
unsigned long irq_flag;
- struct irq_data *desc;
u32 irq_type;
u8 polarity;
int ret;
@@ -1737,11 +1736,7 @@ static int adxl380_config_irq(struct iio_dev *indio_dev)
st->int_map[1] = ADXL380_INT1_MAP1_REG;
}
- desc = irq_get_irq_data(st->irq);
- if (!desc)
- return dev_err_probe(st->dev, -EINVAL, "Could not find IRQ %d\n", st->irq);
-
- irq_type = irqd_get_trigger_type(desc);
+ irq_type = irq_get_trigger_type(st->irq);
if (irq_type == IRQ_TYPE_LEVEL_HIGH) {
polarity = 0;
irq_flag = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c
index 2445a0f7bc2b..128db14ba726 100644
--- a/drivers/iio/accel/bma180.c
+++ b/drivers/iio/accel/bma180.c
@@ -21,6 +21,7 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/types.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
@@ -144,7 +145,7 @@ struct bma180_data {
/* Ensure timestamp is naturally aligned */
struct {
s16 chan[4];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
};
diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c
index fcbd695e4654..009e6243c6cb 100644
--- a/drivers/iio/accel/bma220_spi.c
+++ b/drivers/iio/accel/bma220_spi.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
+#include <linux/types.h>
#include <linux/spi/spi.h>
#include <linux/iio/buffer.h>
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index e4fe36768216..906d2577be2d 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -115,7 +115,7 @@ struct bma400_data {
struct {
__le16 buff[3];
u8 temperature;
- s64 ts __aligned(8);
+ aligned_s64 ts;
} buffer __aligned(IIO_DMA_MINALIGN);
__le16 status;
__be16 duration;
@@ -1293,7 +1293,7 @@ static int bma400_disable_adv_interrupt(struct bma400_data *data)
static int bma400_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct bma400_data *data = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
index 0f32c1e92b4d..158579350d59 100644
--- a/drivers/iio/accel/bmc150-accel-core.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -804,7 +804,7 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct bmc150_accel_data *data = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/accel/bmc150-accel.h b/drivers/iio/accel/bmc150-accel.h
index 7775c5edaeef..7a7baf52e595 100644
--- a/drivers/iio/accel/bmc150-accel.h
+++ b/drivers/iio/accel/bmc150-accel.h
@@ -6,6 +6,7 @@
#include <linux/iio/iio.h>
#include <linux/mutex.h>
#include <linux/regulator/consumer.h>
+#include <linux/types.h>
#include <linux/workqueue.h>
struct regmap;
@@ -69,7 +70,7 @@ struct bmc150_accel_data {
*/
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan;
u8 bw_bits;
u32 slope_dur;
diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c
index acadabec4df7..f07fba17048e 100644
--- a/drivers/iio/accel/fxls8962af-core.c
+++ b/drivers/iio/accel/fxls8962af-core.c
@@ -22,6 +22,7 @@
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/regmap.h>
+#include <linux/types.h>
#include <linux/iio/buffer.h>
#include <linux/iio/events.h>
@@ -163,7 +164,7 @@ struct fxls8962af_data {
const struct fxls8962af_chip_info *chip_info;
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan;
int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */
struct iio_mount_matrix orientation;
@@ -616,7 +617,7 @@ static int
fxls8962af_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct fxls8962af_data *data = iio_priv(indio_dev);
u8 enable_event, enable_bits;
@@ -1103,8 +1104,7 @@ static int fxls8962af_irq_setup(struct iio_dev *indio_dev, int irq)
if (ret)
return ret;
- irq_type = irqd_get_trigger_type(irq_get_irq_data(irq));
-
+ irq_type = irq_get_trigger_type(irq);
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 9b7a73a4c48a..26b1033799fe 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -28,7 +28,7 @@ struct accel_3d_state {
/* Ensure timestamp is naturally aligned */
struct {
u32 accel_val[3];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -328,6 +328,7 @@ static int accel_3d_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_accel_3d_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
const char *name;
struct iio_dev *indio_dev;
@@ -335,8 +336,6 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
const struct iio_chan_spec *channel_spec;
int channel_size;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
-
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct accel_3d_state));
if (indio_dev == NULL)
@@ -424,7 +423,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_accel_3d_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct accel_3d_state *accel_state = iio_priv(indio_dev);
@@ -452,7 +451,7 @@ static struct platform_driver hid_accel_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_accel_3d_probe,
- .remove_new = hid_accel_3d_remove,
+ .remove = hid_accel_3d_remove,
};
module_platform_driver(hid_accel_3d_platform_driver);
diff --git a/drivers/iio/accel/kionix-kx022a.c b/drivers/iio/accel/kionix-kx022a.c
index 53d59a04ae15..53261e1d5d1f 100644
--- a/drivers/iio/accel/kionix-kx022a.c
+++ b/drivers/iio/accel/kionix-kx022a.c
@@ -16,6 +16,7 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/string_choices.h>
+#include <linux/types.h>
#include <linux/units.h>
#include <linux/iio/iio.h>
@@ -292,7 +293,7 @@ struct kx022a_data {
__le16 buffer[8] __aligned(IIO_DMA_MINALIGN);
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan;
};
@@ -594,7 +595,7 @@ static int kx022a_get_axis(struct kx022a_data *data,
if (ret)
return ret;
- *val = le16_to_cpu(data->buffer[0]);
+ *val = (s16)le16_to_cpu(data->buffer[0]);
return IIO_VAL_INT;
}
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
index b76df8816323..f2496cad8ec2 100644
--- a/drivers/iio/accel/kxcjk-1013.c
+++ b/drivers/iio/accel/kxcjk-1013.c
@@ -4,13 +4,15 @@
* Copyright (c) 2014, Intel Corporation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/bitops.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/types.h>
#include <linux/acpi.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
@@ -168,14 +170,73 @@
#define KXCJK1013_DEFAULT_WAKE_THRES 1
-enum kx_chipset {
- KXCJK1013,
- KXCJ91008,
- KXTJ21009,
- KXTF9,
- KX0221020,
- KX0231025,
- KX_MAX_CHIPS /* this must be last */
+/* Refer to section 4 of the specification */
+struct kx_odr_start_up_time {
+ int odr_bits;
+ int usec;
+};
+
+/* KXCJK-1013 */
+static const struct kx_odr_start_up_time kxcjk1013_odr_start_up_times[] = {
+ { 0x08, 100000 },
+ { 0x09, 100000 },
+ { 0x0A, 100000 },
+ { 0x0B, 100000 },
+ { 0x00, 80000 },
+ { 0x01, 41000 },
+ { 0x02, 21000 },
+ { 0x03, 11000 },
+ { 0x04, 6400 },
+ { 0x05, 3900 },
+ { 0x06, 2700 },
+ { 0x07, 2100 },
+ { }
+};
+
+/* KXCTJ2-1009 */
+static const struct kx_odr_start_up_time kxtj21009_odr_start_up_times[] = {
+ { 0x08, 1240000 },
+ { 0x09, 621000 },
+ { 0x0A, 309000 },
+ { 0x0B, 151000 },
+ { 0x00, 80000 },
+ { 0x01, 41000 },
+ { 0x02, 21000 },
+ { 0x03, 11000 },
+ { 0x04, 6000 },
+ { 0x05, 4000 },
+ { 0x06, 3000 },
+ { 0x07, 2000 },
+ { }
+};
+
+/* KXTF9 */
+static const struct kx_odr_start_up_time kxtf9_odr_start_up_times[] = {
+ { 0x01, 81000 },
+ { 0x02, 41000 },
+ { 0x03, 21000 },
+ { 0x04, 11000 },
+ { 0x05, 5100 },
+ { 0x06, 2700 },
+ { }
+};
+
+/* KX023-1025 */
+static const struct kx_odr_start_up_time kx0231025_odr_start_up_times[] = {
+ /* First 4 are not in datasheet, taken from KXCTJ2-1009 */
+ { 0x08, 1240000 },
+ { 0x09, 621000 },
+ { 0x0A, 309000 },
+ { 0x0B, 151000 },
+ { 0x00, 81000 },
+ { 0x01, 40000 },
+ { 0x02, 22000 },
+ { 0x03, 12000 },
+ { 0x04, 7000 },
+ { 0x05, 4400 },
+ { 0x06, 3000 },
+ { 0x07, 3000 },
+ { }
};
enum kx_acpi_type {
@@ -234,6 +295,55 @@ static const struct kx_chipset_regs kx0231025_regs = {
.wake_thres = KX023_REG_ATH,
};
+struct kx_chipset_info {
+ const struct kx_chipset_regs *regs;
+ const struct kx_odr_start_up_time *times;
+ enum kx_acpi_type acpi_type;
+};
+
+static const struct kx_chipset_info kxcjk1013_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+};
+
+static const struct kx_chipset_info kxcj91008_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+};
+
+static const struct kx_chipset_info kxcj91008_kiox010a_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+ .acpi_type = ACPI_KIOX010A,
+};
+
+static const struct kx_chipset_info kxcj91008_kiox020a_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+ .acpi_type = ACPI_GENERIC,
+};
+
+static const struct kx_chipset_info kxcj91008_smo8500_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+ .acpi_type = ACPI_SMO8500,
+};
+
+static const struct kx_chipset_info kxtj21009_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxtj21009_odr_start_up_times),
+};
+
+static const struct kx_chipset_info kxtf9_info = {
+ .regs = &kxtf9_regs,
+ .times = pm_ptr(kxtf9_odr_start_up_times),
+};
+
+static const struct kx_chipset_info kx0231025_info = {
+ .regs = &kx0231025_regs,
+ .times = pm_ptr(kx0231025_odr_start_up_times),
+};
+
enum kxcjk1013_axis {
AXIS_X,
AXIS_Y,
@@ -250,7 +360,7 @@ struct kxcjk1013_data {
/* Ensure timestamp naturally aligned */
struct {
s16 chans[AXIS_MAX];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
u8 odr_bits;
u8 range;
@@ -261,9 +371,7 @@ struct kxcjk1013_data {
int ev_enable_state;
bool motion_trigger_on;
int64_t timestamp;
- enum kx_chipset chipset;
- enum kx_acpi_type acpi_type;
- const struct kx_chipset_regs *regs;
+ const struct kx_chipset_info *info;
};
enum kxcjk1013_mode {
@@ -314,83 +422,6 @@ static const struct kx_odr_map kxtf9_samp_freq_table[] = {
static const char *const kxtf9_samp_freq_avail =
"25 50 100 200 400 800";
-/* Refer to section 4 of the specification */
-static __maybe_unused const struct {
- int odr_bits;
- int usec;
-} odr_start_up_times[KX_MAX_CHIPS][12] = {
- /* KXCJK-1013 */
- {
- {0x08, 100000},
- {0x09, 100000},
- {0x0A, 100000},
- {0x0B, 100000},
- {0, 80000},
- {0x01, 41000},
- {0x02, 21000},
- {0x03, 11000},
- {0x04, 6400},
- {0x05, 3900},
- {0x06, 2700},
- {0x07, 2100},
- },
- /* KXCJ9-1008 */
- {
- {0x08, 100000},
- {0x09, 100000},
- {0x0A, 100000},
- {0x0B, 100000},
- {0, 80000},
- {0x01, 41000},
- {0x02, 21000},
- {0x03, 11000},
- {0x04, 6400},
- {0x05, 3900},
- {0x06, 2700},
- {0x07, 2100},
- },
- /* KXCTJ2-1009 */
- {
- {0x08, 1240000},
- {0x09, 621000},
- {0x0A, 309000},
- {0x0B, 151000},
- {0, 80000},
- {0x01, 41000},
- {0x02, 21000},
- {0x03, 11000},
- {0x04, 6000},
- {0x05, 4000},
- {0x06, 3000},
- {0x07, 2000},
- },
- /* KXTF9 */
- {
- {0x01, 81000},
- {0x02, 41000},
- {0x03, 21000},
- {0x04, 11000},
- {0x05, 5100},
- {0x06, 2700},
- },
- /* KX023-1025 */
- {
- /* First 4 are not in datasheet, taken from KXCTJ2-1009 */
- {0x08, 1240000},
- {0x09, 621000},
- {0x0A, 309000},
- {0x0B, 151000},
- {0, 81000},
- {0x01, 40000},
- {0x02, 22000},
- {0x03, 12000},
- {0x04, 7000},
- {0x05, 4400},
- {0x06, 3000},
- {0x07, 3000},
- },
-};
-
static const struct {
u16 scale;
u8 gsel_0;
@@ -424,30 +455,15 @@ static int kiox010a_dsm(struct device *dev, int fn_index)
return 0;
}
-static const struct acpi_device_id kx_acpi_match[] = {
- {"KXCJ1013", KXCJK1013},
- {"KXCJ1008", KXCJ91008},
- {"KXCJ9000", KXCJ91008},
- {"KIOX0008", KXCJ91008},
- {"KIOX0009", KXTJ21009},
- {"KIOX000A", KXCJ91008},
- {"KIOX010A", KXCJ91008}, /* KXCJ91008 in the display of a yoga 2-in-1 */
- {"KIOX020A", KXCJ91008}, /* KXCJ91008 in the base of a yoga 2-in-1 */
- {"KXTJ1009", KXTJ21009},
- {"KXJ2109", KXTJ21009},
- {"SMO8500", KXCJ91008},
- { }
-};
-MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
-
#endif
static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
enum kxcjk1013_mode mode)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -458,7 +474,7 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
else
ret |= KXCJK1013_REG_CTRL1_BIT_PC1;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
@@ -470,9 +486,10 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
static int kxcjk1013_get_mode(struct kxcjk1013_data *data,
enum kxcjk1013_mode *mode)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -488,9 +505,10 @@ static int kxcjk1013_get_mode(struct kxcjk1013_data *data,
static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -501,7 +519,7 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3);
ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4);
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
@@ -514,10 +532,11 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
#ifdef CONFIG_ACPI
- if (data->acpi_type == ACPI_KIOX010A) {
+ if (data->info->acpi_type == ACPI_KIOX010A) {
/* Make sure the kbd and touchpad on 2-in-1s using 2 KXCJ91008-s work */
kiox010a_dsm(&data->client->dev, KIOX010A_SET_LAPTOP_MODE);
}
@@ -535,7 +554,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
if (ret < 0)
return ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -544,7 +563,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
/* Set 12 bit mode */
ret |= KXCJK1013_REG_CTRL1_BIT_RES;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl\n");
return ret;
@@ -555,7 +574,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
if (ret < 0)
return ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->data_ctrl);
+ ret = i2c_smbus_read_byte_data(data->client, regs->data_ctrl);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_data_ctrl\n");
return ret;
@@ -564,7 +583,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
data->odr_bits = ret;
/* Set up INT polarity */
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
return ret;
@@ -575,14 +594,14 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
else
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEA;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
return ret;
}
- /* On KX023 and KX022, route all used interrupts to INT1 for now */
- if ((data->chipset == KX0231025 || data->chipset == KX0221020) && data->client->irq > 0) {
+ /* On KX023, route all used interrupts to INT1 for now */
+ if (data->info == &kx0231025_info && data->client->irq > 0) {
ret = i2c_smbus_write_byte_data(data->client, KX023_REG_INC4,
KX023_REG_INC4_DRDY1 |
KX023_REG_INC4_WUFI1);
@@ -601,20 +620,17 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
return 0;
}
-#ifdef CONFIG_PM
static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data)
{
- int i;
- int idx = data->chipset;
+ const struct kx_odr_start_up_time *times;
- for (i = 0; i < ARRAY_SIZE(odr_start_up_times[idx]); ++i) {
- if (odr_start_up_times[idx][i].odr_bits == data->odr_bits)
- return odr_start_up_times[idx][i].usec;
+ for (times = data->info->times; times->usec; times++) {
+ if (times->odr_bits == data->odr_bits)
+ return times->usec;
}
return KXCJK1013_MAX_STARTUP_TIME_US;
}
-#endif
static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
{
@@ -639,18 +655,17 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->wake_timer,
- data->wake_dur);
+ ret = i2c_smbus_write_byte_data(data->client, regs->wake_timer, data->wake_dur);
if (ret < 0) {
dev_err(&data->client->dev,
"Error writing reg_wake_timer\n");
return ret;
}
- ret = i2c_smbus_write_byte_data(data->client, data->regs->wake_thres,
- data->wake_thres);
+ ret = i2c_smbus_write_byte_data(data->client, regs->wake_thres, data->wake_thres);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_wake_thres\n");
return ret;
@@ -662,6 +677,7 @@ static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)
static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
bool status)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
enum kxcjk1013_mode store_mode;
@@ -678,7 +694,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
if (ret < 0)
return ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
return ret;
@@ -689,13 +705,13 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
else
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
return ret;
}
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -706,7 +722,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
else
ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
@@ -724,6 +740,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
bool status)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
enum kxcjk1013_mode store_mode;
@@ -736,7 +753,7 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
if (ret < 0)
return ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
return ret;
@@ -747,13 +764,13 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
else
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
return ret;
}
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -764,7 +781,7 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
else
ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
@@ -811,6 +828,7 @@ static int kxcjk1013_convert_odr_value(const struct kx_odr_map *map,
static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
enum kxcjk1013_mode store_mode;
const struct kx_odr_map *odr_setting;
@@ -819,7 +837,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
if (ret < 0)
return ret;
- if (data->chipset == KXTF9)
+ if (data->info == &kxtf9_info)
odr_setting = kxcjk1013_find_odr_value(kxtf9_samp_freq_table,
ARRAY_SIZE(kxtf9_samp_freq_table),
val, val2);
@@ -836,7 +854,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
if (ret < 0)
return ret;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->data_ctrl,
+ ret = i2c_smbus_write_byte_data(data->client, regs->data_ctrl,
odr_setting->odr_bits);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing data_ctrl\n");
@@ -845,7 +863,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
data->odr_bits = odr_setting->odr_bits;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->wuf_ctrl,
+ ret = i2c_smbus_write_byte_data(data->client, regs->wuf_ctrl,
odr_setting->wuf_bits);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl2\n");
@@ -863,7 +881,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
static int kxcjk1013_get_odr(struct kxcjk1013_data *data, int *val, int *val2)
{
- if (data->chipset == KXTF9)
+ if (data->info == &kxtf9_info)
return kxcjk1013_convert_odr_value(kxtf9_samp_freq_table,
ARRAY_SIZE(kxtf9_samp_freq_table),
data->odr_bits, val, val2);
@@ -1063,7 +1081,7 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct kxcjk1013_data *data = iio_priv(indio_dev);
int ret;
@@ -1130,7 +1148,7 @@ static ssize_t kxcjk1013_get_samp_freq_avail(struct device *dev,
struct kxcjk1013_data *data = iio_priv(indio_dev);
const char *str;
- if (data->chipset == KXTF9)
+ if (data->info == &kxtf9_info)
str = kxtf9_samp_freq_avail;
else
str = kxcjk1013_samp_freq_avail;
@@ -1207,7 +1225,7 @@ static const struct iio_buffer_setup_ops kxcjk1013_buffer_setup_ops = {
.postdisable = kxcjk1013_buffer_postdisable,
};
-static const struct iio_info kxcjk1013_info = {
+static const struct iio_info kxcjk1013_iio_info = {
.attrs = &kxcjk1013_attrs_group,
.read_raw = kxcjk1013_read_raw,
.write_raw = kxcjk1013_write_raw,
@@ -1247,9 +1265,10 @@ static void kxcjk1013_trig_reen(struct iio_trigger *trig)
{
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
struct kxcjk1013_data *data = iio_priv(indio_dev);
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_rel);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_rel);
if (ret < 0)
dev_err(&data->client->dev, "Error reading reg_int_rel\n");
}
@@ -1301,8 +1320,9 @@ static const struct iio_trigger_ops kxcjk1013_trigger_ops = {
static void kxcjk1013_report_motion_event(struct iio_dev *indio_dev)
{
struct kxcjk1013_data *data = iio_priv(indio_dev);
+ const struct kx_chipset_regs *regs = data->info->regs;
- int ret = i2c_smbus_read_byte_data(data->client, data->regs->int_src2);
+ int ret = i2c_smbus_read_byte_data(data->client, regs->int_src2);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_src2\n");
return;
@@ -1367,16 +1387,17 @@ static irqreturn_t kxcjk1013_event_handler(int irq, void *private)
{
struct iio_dev *indio_dev = private;
struct kxcjk1013_data *data = iio_priv(indio_dev);
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_src1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_src1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_src1\n");
goto ack_intr;
}
if (ret & KXCJK1013_REG_INT_SRC1_BIT_WUFS) {
- if (data->chipset == KXTF9)
+ if (data->info == &kxtf9_info)
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
@@ -1392,7 +1413,7 @@ ack_intr:
if (data->dready_trigger_on)
return IRQ_HANDLED;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_rel);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_rel);
if (ret < 0)
dev_err(&data->client->dev, "Error reading reg_int_rel\n");
@@ -1417,31 +1438,6 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private)
return IRQ_HANDLED;
}
-static const char *kxcjk1013_match_acpi_device(struct device *dev,
- enum kx_chipset *chipset,
- enum kx_acpi_type *acpi_type,
- const char **label)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- if (strcmp(id->id, "SMO8500") == 0) {
- *acpi_type = ACPI_SMO8500;
- } else if (strcmp(id->id, "KIOX010A") == 0) {
- *acpi_type = ACPI_KIOX010A;
- *label = "accel-display";
- } else if (strcmp(id->id, "KIOX020A") == 0) {
- *label = "accel-base";
- }
-
- *chipset = (enum kx_chipset)id->driver_data;
-
- return dev_name(dev);
-}
-
static int kxcjk1013_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -1449,6 +1445,7 @@ static int kxcjk1013_probe(struct i2c_client *client)
struct kxcjk1013_data *data;
struct iio_dev *indio_dev;
struct kxcjk_1013_platform_data *pdata;
+ const void *ddata = NULL;
const char *name;
int ret;
@@ -1489,32 +1486,18 @@ static int kxcjk1013_probe(struct i2c_client *client)
msleep(20);
if (id) {
- data->chipset = (enum kx_chipset)(id->driver_data);
name = id->name;
- } else if (ACPI_HANDLE(&client->dev)) {
- name = kxcjk1013_match_acpi_device(&client->dev,
- &data->chipset,
- &data->acpi_type,
- &indio_dev->label);
- } else
- return -ENODEV;
-
- switch (data->chipset) {
- case KXCJK1013:
- case KXCJ91008:
- case KXTJ21009:
- data->regs = &kxcjk1013_regs;
- break;
- case KXTF9:
- data->regs = &kxtf9_regs;
- break;
- case KX0221020:
- case KX0231025:
- data->regs = &kx0231025_regs;
- break;
- default:
- return -EINVAL;
+ data->info = (const struct kx_chipset_info *)(id->driver_data);
+ } else {
+ name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
+ data->info = ddata;
+ if (data->info == &kxcj91008_kiox010a_info)
+ indio_dev->label = "accel-display";
+ else if (data->info == &kxcj91008_kiox020a_info)
+ indio_dev->label = "accel-base";
}
+ if (!name)
+ return -ENODEV;
ret = kxcjk1013_chip_init(data);
if (ret < 0)
@@ -1527,9 +1510,9 @@ static int kxcjk1013_probe(struct i2c_client *client)
indio_dev->available_scan_masks = kxcjk1013_scan_masks;
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->info = &kxcjk1013_info;
+ indio_dev->info = &kxcjk1013_iio_info;
- if (client->irq > 0 && data->acpi_type != ACPI_SMO8500) {
+ if (client->irq > 0 && data->info->acpi_type != ACPI_SMO8500) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
kxcjk1013_data_rdy_trig_poll,
kxcjk1013_event_handler,
@@ -1637,7 +1620,6 @@ static void kxcjk1013_remove(struct i2c_client *client)
mutex_unlock(&data->mutex);
}
-#ifdef CONFIG_PM_SLEEP
static int kxcjk1013_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
@@ -1665,9 +1647,7 @@ static int kxcjk1013_resume(struct device *dev)
return ret;
}
-#endif
-#ifdef CONFIG_PM
static int kxcjk1013_runtime_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
@@ -1701,44 +1681,56 @@ static int kxcjk1013_runtime_resume(struct device *dev)
return 0;
}
-#endif
static const struct dev_pm_ops kxcjk1013_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(kxcjk1013_suspend, kxcjk1013_resume)
- SET_RUNTIME_PM_OPS(kxcjk1013_runtime_suspend,
- kxcjk1013_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(kxcjk1013_suspend, kxcjk1013_resume)
+ RUNTIME_PM_OPS(kxcjk1013_runtime_suspend, kxcjk1013_runtime_resume, NULL)
};
static const struct i2c_device_id kxcjk1013_id[] = {
- {"kxcjk1013", KXCJK1013},
- {"kxcj91008", KXCJ91008},
- {"kxtj21009", KXTJ21009},
- {"kxtf9", KXTF9},
- {"kx022-1020", KX0221020},
- {"kx023-1025", KX0231025},
- {"SMO8500", KXCJ91008},
- {}
+ { "kxcjk1013", (kernel_ulong_t)&kxcjk1013_info },
+ { "kxcj91008", (kernel_ulong_t)&kxcj91008_info },
+ { "kxtj21009", (kernel_ulong_t)&kxtj21009_info },
+ { "kxtf9", (kernel_ulong_t)&kxtf9_info },
+ { "kx023-1025", (kernel_ulong_t)&kx0231025_info },
+ { }
};
-
MODULE_DEVICE_TABLE(i2c, kxcjk1013_id);
static const struct of_device_id kxcjk1013_of_match[] = {
- { .compatible = "kionix,kxcjk1013", },
- { .compatible = "kionix,kxcj91008", },
- { .compatible = "kionix,kxtj21009", },
- { .compatible = "kionix,kxtf9", },
- { .compatible = "kionix,kx022-1020", },
- { .compatible = "kionix,kx023-1025", },
+ { .compatible = "kionix,kxcjk1013", &kxcjk1013_info },
+ { .compatible = "kionix,kxcj91008", &kxcj91008_info },
+ { .compatible = "kionix,kxtj21009", &kxtj21009_info },
+ { .compatible = "kionix,kxtf9", &kxtf9_info },
+ { .compatible = "kionix,kx023-1025", &kx0231025_info },
{ }
};
MODULE_DEVICE_TABLE(of, kxcjk1013_of_match);
+static const struct acpi_device_id kx_acpi_match[] = {
+ { "KIOX0008", (kernel_ulong_t)&kxcj91008_info },
+ { "KIOX0009", (kernel_ulong_t)&kxtj21009_info },
+ { "KIOX000A", (kernel_ulong_t)&kxcj91008_info },
+ /* KXCJ91008 in the display of a yoga 2-in-1 */
+ { "KIOX010A", (kernel_ulong_t)&kxcj91008_kiox010a_info },
+ /* KXCJ91008 in the base of a yoga 2-in-1 */
+ { "KIOX020A", (kernel_ulong_t)&kxcj91008_kiox020a_info },
+ { "KXCJ1008", (kernel_ulong_t)&kxcj91008_info },
+ { "KXCJ1013", (kernel_ulong_t)&kxcjk1013_info },
+ { "KXCJ9000", (kernel_ulong_t)&kxcj91008_info },
+ { "KXJ2109", (kernel_ulong_t)&kxtj21009_info },
+ { "KXTJ1009", (kernel_ulong_t)&kxtj21009_info },
+ { "SMO8500", (kernel_ulong_t)&kxcj91008_smo8500_info },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
+
static struct i2c_driver kxcjk1013_driver = {
.driver = {
.name = KXCJK1013_DRV_NAME,
- .acpi_match_table = ACPI_PTR(kx_acpi_match),
+ .acpi_match_table = kx_acpi_match,
.of_match_table = kxcjk1013_of_match,
- .pm = &kxcjk1013_pm_ops,
+ .pm = pm_ptr(&kxcjk1013_pm_ops),
},
.probe = kxcjk1013_probe,
.remove = kxcjk1013_remove,
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c
index 70dfd6e354db..6d2b0a22e550 100644
--- a/drivers/iio/accel/kxsd9.c
+++ b/drivers/iio/accel/kxsd9.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
+#include <linux/types.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/bitops.h>
@@ -215,7 +216,7 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p)
*/
struct {
__be16 chan[4];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} hw_values;
int ret;
diff --git a/drivers/iio/accel/mma7455_core.c b/drivers/iio/accel/mma7455_core.c
index a34195b3215d..50f7ac1845c6 100644
--- a/drivers/iio/accel/mma7455_core.c
+++ b/drivers/iio/accel/mma7455_core.c
@@ -19,6 +19,7 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/module.h>
#include <linux/regmap.h>
+#include <linux/types.h>
#include "mma7455.h"
@@ -58,7 +59,7 @@ struct mma7455_data {
*/
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan;
};
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index 62e6369e2269..962d289065ab 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -32,6 +32,7 @@
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
+#include <linux/types.h>
#define MMA8452_STATUS 0x00
#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
@@ -115,7 +116,7 @@ struct mma8452_data {
/* Ensure correct alignment of time stamp when present */
struct {
__be16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} buffer;
};
@@ -973,7 +974,7 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct mma8452_data *data = iio_priv(indio_dev);
int val, ret;
diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c
index fa1799b0b0df..6d73eec95126 100644
--- a/drivers/iio/accel/mma9551.c
+++ b/drivers/iio/accel/mma9551.c
@@ -4,11 +4,11 @@
* Copyright (c) 2014, Intel Corporation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/iio.h>
@@ -45,7 +45,7 @@ enum mma9551_tilt_axis {
struct mma9551_data {
struct i2c_client *client;
struct mutex mutex;
- int event_enabled[3];
+ bool event_enabled[3];
int irqs[MMA9551_GPIO_COUNT];
};
@@ -162,7 +162,7 @@ static int mma9551_read_event_config(struct iio_dev *indio_dev,
static int mma9551_config_incli_event(struct iio_dev *indio_dev,
enum iio_modifier axis,
- int state)
+ bool state)
{
struct mma9551_data *data = iio_priv(indio_dev);
enum mma9551_tilt_axis mma_axis;
@@ -174,7 +174,7 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev,
if (data->event_enabled[mma_axis] == state)
return 0;
- if (state == 0) {
+ if (!state) {
ret = mma9551_gpio_config(data->client,
(enum mma9551_gpio_pin)mma_axis,
MMA9551_APPID_NONE, 0, 0);
@@ -225,7 +225,7 @@ static int mma9551_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct mma9551_data *data = iio_priv(indio_dev);
int ret;
@@ -435,17 +435,6 @@ static int mma9551_gpio_probe(struct iio_dev *indio_dev)
return 0;
}
-static const char *mma9551_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
static int mma9551_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -464,8 +453,8 @@ static int mma9551_probe(struct i2c_client *client)
if (id)
name = id->name;
- else if (ACPI_HANDLE(&client->dev))
- name = mma9551_match_acpi_device(&client->dev);
+ else
+ name = iio_get_acpi_device_name(&client->dev);
ret = mma9551_init(data);
if (ret < 0)
diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c
index 86543f34ef17..8536743a6886 100644
--- a/drivers/iio/accel/mma9553.c
+++ b/drivers/iio/accel/mma9553.c
@@ -4,11 +4,11 @@
* Copyright (c) 2014, Intel Corporation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
@@ -725,7 +725,8 @@ static int mma9553_read_event_config(struct iio_dev *indio_dev,
static int mma9553_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct mma9553_data *data = iio_priv(indio_dev);
struct mma9553_event *event;
@@ -1030,9 +1031,9 @@ static irqreturn_t mma9553_event_handler(int irq, void *private)
if (ev_step_detect->enabled && (stepcnt != data->stepcnt)) {
data->stepcnt = stepcnt;
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
- IIO_EV_DIR_NONE,
- IIO_EV_TYPE_CHANGE, 0, 0, 0),
+ IIO_UNMOD_EVENT_CODE(IIO_STEPS, 0,
+ IIO_EV_TYPE_CHANGE,
+ IIO_EV_DIR_NONE),
data->timestamp);
}
@@ -1041,20 +1042,18 @@ static irqreturn_t mma9553_event_handler(int irq, void *private)
/* ev_activity can be NULL if activity == ACTIVITY_UNKNOWN */
if (ev_prev_activity && ev_prev_activity->enabled)
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- ev_prev_activity->info->mod,
- IIO_EV_DIR_FALLING,
- IIO_EV_TYPE_THRESH, 0, 0,
- 0),
+ IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
+ ev_prev_activity->info->mod,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
data->timestamp);
if (ev_activity && ev_activity->enabled)
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- ev_activity->info->mod,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH, 0, 0,
- 0),
+ IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
+ ev_activity->info->mod,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
data->timestamp);
}
mutex_unlock(&data->mutex);
@@ -1062,17 +1061,6 @@ static irqreturn_t mma9553_event_handler(int irq, void *private)
return IRQ_HANDLED;
}
-static const char *mma9553_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
static int mma9553_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -1091,9 +1079,9 @@ static int mma9553_probe(struct i2c_client *client)
if (id)
name = id->name;
- else if (ACPI_HANDLE(&client->dev))
- name = mma9553_match_acpi_device(&client->dev);
else
+ name = iio_get_acpi_device_name(&client->dev);
+ if (!name)
return -ENOSYS;
mutex_init(&data->mutex);
diff --git a/drivers/iio/accel/msa311.c b/drivers/iio/accel/msa311.c
index 57025354c7cd..e7fb860f3233 100644
--- a/drivers/iio/accel/msa311.c
+++ b/drivers/iio/accel/msa311.c
@@ -34,6 +34,7 @@
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/string_choices.h>
+#include <linux/types.h>
#include <linux/units.h>
#include <linux/iio/buffer.h>
@@ -893,7 +894,7 @@ static irqreturn_t msa311_buffer_thread(int irq, void *p)
__le16 axis;
struct {
__le16 channels[MSA311_SI_Z + 1];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} buf;
memset(&buf, 0, sizeof(buf));
diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c
index fc54a2a4693c..cb5c4e354fc0 100644
--- a/drivers/iio/accel/mxc4005.c
+++ b/drivers/iio/accel/mxc4005.c
@@ -11,6 +11,7 @@
#include <linux/iio/iio.h>
#include <linux/mod_devicetable.h>
#include <linux/regmap.h>
+#include <linux/types.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/buffer.h>
@@ -69,7 +70,7 @@ struct mxc4005_data {
/* Ensure timestamp is naturally aligned */
struct {
__be16 chans[3];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
bool trigger_enabled;
unsigned int control;
diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c
index 87c54e41f6cc..3fb0f386c3db 100644
--- a/drivers/iio/accel/sca3000.c
+++ b/drivers/iio/accel/sca3000.c
@@ -1158,7 +1158,7 @@ error_ret:
return ret;
}
-static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state)
+static int sca3000_freefall_set_state(struct iio_dev *indio_dev, bool state)
{
struct sca3000_state *st = iio_priv(indio_dev);
int ret;
@@ -1181,7 +1181,7 @@ static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state)
}
static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis,
- int state)
+ bool state)
{
struct sca3000_state *st = iio_priv(indio_dev);
int ret, ctrlval;
@@ -1253,7 +1253,7 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct sca3000_state *st = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c
index abead190254b..471c154c3631 100644
--- a/drivers/iio/accel/stk8312.c
+++ b/drivers/iio/accel/stk8312.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/types.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -105,7 +106,7 @@ struct stk8312_data {
/* Ensure timestamp is naturally aligned */
struct {
s8 chans[3];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
};
diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c
index a32a77324e92..cab592a68622 100644
--- a/drivers/iio/accel/stk8ba50.c
+++ b/drivers/iio/accel/stk8ba50.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
+#include <linux/types.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -94,7 +95,7 @@ struct stk8ba50_data {
/* Ensure timestamp is naturally aligned */
struct {
s16 chans[3];
- s64 timetamp __aligned(8);
+ aligned_s64 timetamp;
} scan;
};
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 6c4e74420fd2..849c90203071 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -226,12 +226,14 @@ config AD7606_IFACE_PARALLEL
tristate "Analog Devices AD7606 ADC driver with parallel interface support"
depends on HAS_IOPORT
select AD7606
+ select IIO_BACKEND
help
Say yes here to build parallel interface support for Analog Devices:
ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC).
+ It also support iio_backended devices for AD7606B.
To compile this driver as a module, choose M here: the
- module will be called ad7606_parallel.
+ module will be called ad7606_par.
config AD7606_IFACE_SPI
tristate "Analog Devices AD7606 ADC driver with spi interface support"
@@ -244,6 +246,22 @@ config AD7606_IFACE_SPI
To compile this driver as a module, choose M here: the
module will be called ad7606_spi.
+config AD7625
+ tristate "Analog Devices AD7625/AD7626 High Speed ADC driver"
+ depends on PWM
+ select IIO_BACKEND
+ help
+ Say yes here to build support for Analog Devices:
+ * AD7625 16-Bit, 6 MSPS PulSAR Analog-to-Digital Converter
+ * AD7626 16-Bit, 10 MSPS PulSAR Analog-to-Digital Converter
+ * AD7960 18-Bit, 5 MSPS PulSAR Analog-to-Digital Converter
+ * AD7961 16-Bit, 5 MSPS PulSAR Analog-to-Digital Converter
+
+ The driver requires the assistance of the AXI ADC IP core to operate.
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad7625.
+
config AD7766
tristate "Analog Devices AD7766/AD7767 ADC driver"
depends on SPI_MASTER
@@ -269,6 +287,18 @@ config AD7768_1
To compile this driver as a module, choose M here: the module will be
called ad7768-1.
+config AD7779
+ tristate "Analog Devices AD7779 ADC driver"
+ depends on SPI
+ select CRC8
+ select IIO_BUFFER
+ help
+ Say yes here to build support for Analog Devices AD777X family
+ (AD7770, AD7771, AD7779) analog to digital converter (ADC).
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad7779.
+
config AD7780
tristate "Analog Devices AD7780 and similar ADCs driver"
depends on SPI
@@ -575,6 +605,16 @@ config FSL_MX25_ADC
Generic Conversion Queue driver used for general purpose ADC in the
MX25. This driver supports single measurements using the MX25 ADC.
+config GEHC_PMC_ADC
+ tristate "GE HealthCare PMC ADC driver"
+ depends on I2C
+ help
+ Say yes here to build support for the GE HealthCare PMC 16-bit
+ 16-Channel ADC.
+
+ To compile this driver as a module, choose M here: the module will be
+ called gehc-pmc-adc.
+
config HI8435
tristate "Holt Integrated Circuits HI-8435 threshold detector"
select IIO_TRIGGERED_EVENT
@@ -1580,7 +1620,6 @@ config TWL4030_MADC
config TWL6030_GPADC
tristate "TWL6030 GPADC (General Purpose A/D Converter) Support"
depends on TWL4030_CORE
- default n
help
Say yes here if you want support for the TWL6030/TWL6032 General
Purpose A/D Converter. This will add support for battery type
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 7b91cd98c0e0..ee19afba62b7 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -25,8 +25,10 @@ obj-$(CONFIG_AD7476) += ad7476.o
obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
obj-$(CONFIG_AD7606) += ad7606.o
+obj-$(CONFIG_AD7625) += ad7625.o
obj-$(CONFIG_AD7766) += ad7766.o
obj-$(CONFIG_AD7768_1) += ad7768-1.o
+obj-$(CONFIG_AD7779) += ad7779.o
obj-$(CONFIG_AD7780) += ad7780.o
obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AD7793) += ad7793.o
@@ -52,6 +54,7 @@ obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o
obj-$(CONFIG_EP93XX_ADC) += ep93xx_adc.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o
+obj-$(CONFIG_GEHC_PMC_ADC) += gehc-pmc-adc.o
obj-$(CONFIG_HI8435) += hi8435.o
obj-$(CONFIG_HX711) += hx711.o
obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c
index 59f66e9cb0e8..f3b057f92310 100644
--- a/drivers/iio/adc/ab8500-gpadc.c
+++ b/drivers/iio/adc/ab8500-gpadc.c
@@ -1194,7 +1194,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(ab8500_gpadc_pm_ops,
static struct platform_driver ab8500_gpadc_driver = {
.probe = ab8500_gpadc_probe,
- .remove_new = ab8500_gpadc_remove,
+ .remove = ab8500_gpadc_remove,
.driver = {
.name = "ab8500-gpadc",
.pm = pm_ptr(&ab8500_gpadc_pm_ops),
diff --git a/drivers/iio/adc/ad4000.c b/drivers/iio/adc/ad4000.c
index 6ea491245084..b3b82535f5c1 100644
--- a/drivers/iio/adc/ad4000.c
+++ b/drivers/iio/adc/ad4000.c
@@ -344,6 +344,8 @@ static int ad4000_single_conversion(struct iio_dev *indio_dev,
if (chan->scan_type.sign == 's')
*val = sign_extend32(sample, chan->scan_type.realbits - 1);
+ else
+ *val = sample;
return IIO_VAL_INT;
}
@@ -637,7 +639,9 @@ static int ad4000_probe(struct spi_device *spi)
indio_dev->name = chip->dev_name;
indio_dev->num_channels = 1;
- devm_mutex_init(dev, &st->lock);
+ ret = devm_mutex_init(dev, &st->lock);
+ if (ret)
+ return ret;
st->gain_milli = 1000;
if (chip->has_hardware_gain) {
diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c
index d6876259ad14..eb0a059b4b0e 100644
--- a/drivers/iio/adc/ad7091r-base.c
+++ b/drivers/iio/adc/ad7091r-base.c
@@ -150,7 +150,8 @@ static int ad7091r_read_event_config(struct iio_dev *indio_dev,
static int ad7091r_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct ad7091r_state *st = iio_priv(indio_dev);
diff --git a/drivers/iio/adc/ad7091r-base.h b/drivers/iio/adc/ad7091r-base.h
index 696bf7a897bb..092ddea0f395 100644
--- a/drivers/iio/adc/ad7091r-base.h
+++ b/drivers/iio/adc/ad7091r-base.h
@@ -65,7 +65,7 @@ struct ad7091r_state {
struct regulator *vref;
const struct ad7091r_chip_info *chip_info;
enum ad7091r_mode mode;
- struct mutex lock; /*lock to prevent concurent reads */
+ struct mutex lock; /*lock to prevent concurrent reads */
__be16 tx_buf __aligned(IIO_DMA_MINALIGN);
__be16 rx_buf;
};
diff --git a/drivers/iio/adc/ad7173.c b/drivers/iio/adc/ad7173.c
index 0702ec71aa29..a0fca16c3be0 100644
--- a/drivers/iio/adc/ad7173.c
+++ b/drivers/iio/adc/ad7173.c
@@ -3,7 +3,7 @@
* AD717x and AD411x family SPI ADC driver
*
* Supported devices:
- * AD4111/AD4112/AD4114/AD4115/AD4116
+ * AD4111/AD4112/AD4113/AD4114/AD4115/AD4116
* AD7172-2/AD7172-4/AD7173-8/AD7175-2
* AD7175-8/AD7176-2/AD7177-2
*
@@ -76,14 +76,15 @@
(x) == AD7173_AIN_REF_NEG)
#define AD7172_2_ID 0x00d0
-#define AD7175_ID 0x0cd0
#define AD7176_ID 0x0c90
+#define AD7175_ID 0x0cd0
#define AD7175_2_ID 0x0cd0
#define AD7172_4_ID 0x2050
#define AD7173_ID 0x30d0
#define AD4111_ID AD7173_ID
#define AD4112_ID AD7173_ID
#define AD4114_ID AD7173_ID
+#define AD4113_ID 0x31d0
#define AD4116_ID 0x34d0
#define AD4115_ID 0x38d0
#define AD7175_8_ID 0x3cd0
@@ -170,6 +171,7 @@ struct ad7173_device_info {
bool has_temp;
/* ((AVDD1 − AVSS)/5) */
bool has_pow_supply_monitoring;
+ bool data_reg_only_16bit;
bool has_input_buf;
bool has_int_ref;
bool has_ref2;
@@ -294,6 +296,24 @@ static const struct ad7173_device_info ad4112_device_info = {
.num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates),
};
+static const struct ad7173_device_info ad4113_device_info = {
+ .name = "ad4113",
+ .id = AD4113_ID,
+ .num_voltage_in_div = 8,
+ .num_channels = 16,
+ .num_configs = 8,
+ .num_voltage_in = 8,
+ .num_gpios = 2,
+ .data_reg_only_16bit = true,
+ .higher_gpio_bits = true,
+ .has_vincom_input = true,
+ .has_input_buf = true,
+ .has_int_ref = true,
+ .clock = 2 * HZ_PER_MHZ,
+ .sinc5_data_rates = ad7173_sinc5_data_rates,
+ .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates),
+};
+
static const struct ad7173_device_info ad4114_device_info = {
.name = "ad4114",
.id = AD4114_ID,
@@ -985,6 +1005,13 @@ static const struct iio_info ad7173_info = {
.update_scan_mode = ad7173_update_scan_mode,
};
+static const struct iio_scan_type ad4113_scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_BE,
+};
+
static const struct iio_chan_spec ad7173_channel_template = {
.type = IIO_VOLTAGE,
.indexed = 1,
@@ -1226,6 +1253,8 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev)
chan_st_priv->cfg.input_buf = st->info->has_input_buf;
chan_st_priv->cfg.ref_sel = AD7173_SETUP_REF_SEL_INT_REF;
st->adc_mode |= AD7173_ADC_MODE_REF_EN;
+ if (st->info->data_reg_only_16bit)
+ chan_arr[chan_index].scan_type = ad4113_scan_type;
chan_index++;
}
@@ -1306,6 +1335,9 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev)
chan_st_priv->ain = AD7173_CH_ADDRESS(ain[0], ain[1]);
}
+ if (st->info->data_reg_only_16bit)
+ chan_arr[chan_index].scan_type = ad4113_scan_type;
+
chan_index++;
}
return 0;
@@ -1434,6 +1466,7 @@ static int ad7173_probe(struct spi_device *spi)
static const struct of_device_id ad7173_of_match[] = {
{ .compatible = "adi,ad4111", .data = &ad4111_device_info },
{ .compatible = "adi,ad4112", .data = &ad4112_device_info },
+ { .compatible = "adi,ad4113", .data = &ad4113_device_info },
{ .compatible = "adi,ad4114", .data = &ad4114_device_info },
{ .compatible = "adi,ad4115", .data = &ad4115_device_info },
{ .compatible = "adi,ad4116", .data = &ad4116_device_info },
@@ -1451,6 +1484,7 @@ MODULE_DEVICE_TABLE(of, ad7173_of_match);
static const struct spi_device_id ad7173_id_table[] = {
{ "ad4111", (kernel_ulong_t)&ad4111_device_info },
{ "ad4112", (kernel_ulong_t)&ad4112_device_info },
+ { "ad4113", (kernel_ulong_t)&ad4113_device_info },
{ "ad4114", (kernel_ulong_t)&ad4114_device_info },
{ "ad4115", (kernel_ulong_t)&ad4115_device_info },
{ "ad4116", (kernel_ulong_t)&ad4116_device_info },
diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index 7042ddfdfc03..955e9eff0099 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -1394,6 +1394,9 @@ static int ad7192_probe(struct spi_device *spi)
st->int_vref_mv = ret == -ENODEV ? avdd_mv : ret / MILLI;
st->chip_info = spi_get_device_match_data(spi);
+ if (!st->chip_info)
+ return -ENODEV;
+
indio_dev->name = st->chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = st->chip_info->info;
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index 7949b076fb87..858c8be2ff1a 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -383,7 +383,7 @@ static const char * const ad7266_gpio_labels[] = {
static int ad7266_probe(struct spi_device *spi)
{
- struct ad7266_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7266_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad7266_state *st;
unsigned int i;
diff --git a/drivers/iio/adc/ad7280a.c b/drivers/iio/adc/ad7280a.c
index 35aa39fe4bde..f9f32737db80 100644
--- a/drivers/iio/adc/ad7280a.c
+++ b/drivers/iio/adc/ad7280a.c
@@ -822,17 +822,15 @@ static irqreturn_t ad7280_event_handler(int irq, void *private)
if (FIELD_GET(AD7280A_TRANS_READ_CONV_CHANADDR_MSK, channels[i]) <=
AD7280A_CELL_VOLTAGE_6_REG) {
if (val >= st->cell_threshhigh) {
- u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0);
+ u64 tmp = IIO_DIFF_EVENT_CODE(IIO_VOLTAGE, 0, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING);
iio_push_event(indio_dev, tmp,
iio_get_time_ns(indio_dev));
} else if (val <= st->cell_threshlow) {
- u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0,
- IIO_EV_DIR_FALLING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0);
+ u64 tmp = IIO_DIFF_EVENT_CODE(IIO_VOLTAGE, 0, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING);
iio_push_event(indio_dev, tmp,
iio_get_time_ns(indio_dev));
}
diff --git a/drivers/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c
index 4c7f887adbbf..60e12faa3207 100644
--- a/drivers/iio/adc/ad7291.c
+++ b/drivers/iio/adc/ad7291.c
@@ -269,7 +269,7 @@ static int ad7291_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
int ret = 0;
struct ad7291_chip_info *chip = iio_priv(indio_dev);
diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c
index fb728570debe..4f32cb22f140 100644
--- a/drivers/iio/adc/ad7380.c
+++ b/drivers/iio/adc/ad7380.c
@@ -13,6 +13,8 @@
* ad7381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7381-4.pdf
* ad7383/4-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-4-ad7384-4.pdf
* ad7386/7/8-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7386-4-7387-4-7388-4.pdf
+ * adaq4370-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4370-4.pdf
+ * adaq4380-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4380-4.pdf
*/
#include <linux/align.h>
@@ -22,11 +24,14 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kernel.h>
+#include <linux/math.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
+#include <linux/units.h>
+#include <linux/util_macros.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
@@ -36,6 +41,8 @@
#define MAX_NUM_CHANNELS 8
/* 2.5V internal reference voltage */
#define AD7380_INTERNAL_REF_MV 2500
+/* 3.3V internal reference voltage for ADAQ */
+#define ADAQ4380_INTERNAL_REF_MV 3300
/* reading and writing registers is more reliable at lower than max speed */
#define AD7380_REG_WR_SPEED_HZ 10000000
@@ -77,6 +84,13 @@
#define T_CONVERT_X_NS 500 /* xth conversion start time (oversampling) */
#define T_POWERUP_US 5000 /* Power up */
+/*
+ * AD738x support several SDO lines to increase throughput, but driver currently
+ * supports only 1 SDO line (standard SPI transaction)
+ */
+#define AD7380_NUM_SDO_LINES 1
+#define AD7380_DEFAULT_GAIN_MILLI 1000
+
struct ad7380_timing_specs {
const unsigned int t_csh_ns; /* CS minimum high time */
};
@@ -86,10 +100,12 @@ struct ad7380_chip_info {
const struct iio_chan_spec *channels;
unsigned int num_channels;
unsigned int num_simult_channels;
+ bool has_hardware_gain;
bool has_mux;
const char * const *supplies;
unsigned int num_supplies;
bool external_ref_only;
+ bool adaq_internal_ref_only;
const char * const *vcm_supplies;
unsigned int num_vcm_supplies;
const unsigned long *available_scan_masks;
@@ -181,11 +197,12 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = {
},
};
-#define AD7380_CHANNEL(index, bits, diff, sign) { \
+#define _AD7380_CHANNEL(index, bits, diff, sign, gain) { \
.type = IIO_VOLTAGE, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ ((gain) ? BIT(IIO_CHAN_INFO_SCALE) : 0) | \
((diff) ? 0 : BIT(IIO_CHAN_INFO_OFFSET)), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ .info_mask_shared_by_type = ((gain) ? 0 : BIT(IIO_CHAN_INFO_SCALE)) | \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
.info_mask_shared_by_type_available = \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
@@ -199,6 +216,12 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = {
.num_ext_scan_type = ARRAY_SIZE(ad7380_scan_type_##bits##_##sign), \
}
+#define AD7380_CHANNEL(index, bits, diff, sign) \
+ _AD7380_CHANNEL(index, bits, diff, sign, false)
+
+#define ADAQ4380_CHANNEL(index, bits, diff, sign) \
+ _AD7380_CHANNEL(index, bits, diff, sign, true)
+
#define DEFINE_AD7380_2_CHANNEL(name, bits, diff, sign) \
static const struct iio_chan_spec name[] = { \
AD7380_CHANNEL(0, bits, diff, sign), \
@@ -215,6 +238,15 @@ static const struct iio_chan_spec name[] = { \
IIO_CHAN_SOFT_TIMESTAMP(4), \
}
+#define DEFINE_ADAQ4380_4_CHANNEL(name, bits, diff, sign) \
+static const struct iio_chan_spec name[] = { \
+ ADAQ4380_CHANNEL(0, bits, diff, sign), \
+ ADAQ4380_CHANNEL(1, bits, diff, sign), \
+ ADAQ4380_CHANNEL(2, bits, diff, sign), \
+ ADAQ4380_CHANNEL(3, bits, diff, sign), \
+ IIO_CHAN_SOFT_TIMESTAMP(4), \
+}
+
#define DEFINE_AD7380_8_CHANNEL(name, bits, diff, sign) \
static const struct iio_chan_spec name[] = { \
AD7380_CHANNEL(0, bits, diff, sign), \
@@ -233,6 +265,7 @@ DEFINE_AD7380_2_CHANNEL(ad7380_channels, 16, 1, s);
DEFINE_AD7380_2_CHANNEL(ad7381_channels, 14, 1, s);
DEFINE_AD7380_4_CHANNEL(ad7380_4_channels, 16, 1, s);
DEFINE_AD7380_4_CHANNEL(ad7381_4_channels, 14, 1, s);
+DEFINE_ADAQ4380_4_CHANNEL(adaq4380_4_channels, 16, 1, s);
/* pseudo differential */
DEFINE_AD7380_2_CHANNEL(ad7383_channels, 16, 0, s);
DEFINE_AD7380_2_CHANNEL(ad7384_channels, 14, 0, s);
@@ -251,6 +284,10 @@ static const char * const ad7380_supplies[] = {
"vcc", "vlogic",
};
+static const char * const adaq4380_supplies[] = {
+ "ldo", "vcc", "vlogic", "vs-p", "vs-n", "refin",
+};
+
static const char * const ad7380_2_channel_vcm_supplies[] = {
"aina", "ainb",
};
@@ -341,6 +378,11 @@ static const int ad7380_oversampling_ratios[] = {
1, 2, 4, 8, 16, 32,
};
+/* Gains stored as fractions of 1000 so they can be expressed by integers. */
+static const int ad7380_gains[] = {
+ 300, 600, 1000, 1600,
+};
+
static const struct ad7380_chip_info ad7380_chip_info = {
.name = "ad7380",
.channels = ad7380_channels,
@@ -510,6 +552,32 @@ static const struct ad7380_chip_info ad7388_4_chip_info = {
.timing_specs = &ad7380_4_timing,
};
+static const struct ad7380_chip_info adaq4370_4_chip_info = {
+ .name = "adaq4370-4",
+ .channels = adaq4380_4_channels,
+ .num_channels = ARRAY_SIZE(adaq4380_4_channels),
+ .num_simult_channels = 4,
+ .supplies = adaq4380_supplies,
+ .num_supplies = ARRAY_SIZE(adaq4380_supplies),
+ .adaq_internal_ref_only = true,
+ .has_hardware_gain = true,
+ .available_scan_masks = ad7380_4_channel_scan_masks,
+ .timing_specs = &ad7380_4_timing,
+};
+
+static const struct ad7380_chip_info adaq4380_4_chip_info = {
+ .name = "adaq4380-4",
+ .channels = adaq4380_4_channels,
+ .num_channels = ARRAY_SIZE(adaq4380_4_channels),
+ .num_simult_channels = 4,
+ .supplies = adaq4380_supplies,
+ .num_supplies = ARRAY_SIZE(adaq4380_supplies),
+ .adaq_internal_ref_only = true,
+ .has_hardware_gain = true,
+ .available_scan_masks = ad7380_4_channel_scan_masks,
+ .timing_specs = &ad7380_4_timing,
+};
+
struct ad7380_state {
const struct ad7380_chip_info *chip_info;
struct spi_device *spi;
@@ -520,6 +588,7 @@ struct ad7380_state {
bool seq;
unsigned int vref_mv;
unsigned int vcm_mv[MAX_NUM_CHANNELS];
+ unsigned int gain_milli[MAX_NUM_CHANNELS];
/* xfers, message an buffer for reading sample data */
struct spi_transfer normal_xfer[2];
struct spi_message normal_msg;
@@ -649,7 +718,8 @@ static int ad7380_set_ch(struct ad7380_state *st, unsigned int ch)
if (st->oversampling_ratio > 1)
xfer.delay.value = T_CONVERT_0_NS +
- T_CONVERT_X_NS * (st->oversampling_ratio - 1);
+ T_CONVERT_X_NS * (st->oversampling_ratio - 1) *
+ st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
return spi_sync_transfer(st->spi, &xfer, 1);
}
@@ -672,7 +742,8 @@ static void ad7380_update_xfers(struct ad7380_state *st,
*/
if (st->oversampling_ratio > 1)
t_convert = T_CONVERT_0_NS + T_CONVERT_X_NS *
- (st->oversampling_ratio - 1);
+ (st->oversampling_ratio - 1) *
+ st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
if (st->seq) {
xfer[0].delay.value = xfer[1].delay.value = t_convert;
@@ -868,8 +939,15 @@ static int ad7380_read_raw(struct iio_dev *indio_dev,
* * (2 × VREF) / 2^N, for differential chips
* * VREF / 2^N, for pseudo-differential chips
* where N is the ADC resolution (i.e realbits)
+ *
+ * The gain is stored as a fraction of 1000 and, as we need to
+ * divide vref_mv by the gain, we invert the gain/1000 fraction.
*/
- *val = st->vref_mv;
+ if (st->chip_info->has_hardware_gain)
+ *val = mult_frac(st->vref_mv, MILLI,
+ st->gain_milli[chan->scan_index]);
+ else
+ *val = st->vref_mv;
*val2 = scan_type->realbits - chan->differential;
return IIO_VAL_FRACTIONAL_LOG2;
@@ -1021,17 +1099,19 @@ static int ad7380_init(struct ad7380_state *st, bool external_ref_en)
/* SPI 1-wire mode */
return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2,
AD7380_CONFIG2_SDO,
- FIELD_PREP(AD7380_CONFIG2_SDO, 1));
+ FIELD_PREP(AD7380_CONFIG2_SDO,
+ AD7380_NUM_SDO_LINES));
}
static int ad7380_probe(struct spi_device *spi)
{
+ struct device *dev = &spi->dev;
struct iio_dev *indio_dev;
struct ad7380_state *st;
bool external_ref_en;
int ret, i;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
@@ -1039,21 +1119,32 @@ static int ad7380_probe(struct spi_device *spi)
st->spi = spi;
st->chip_info = spi_get_device_match_data(spi);
if (!st->chip_info)
- return dev_err_probe(&spi->dev, -EINVAL, "missing match data\n");
+ return dev_err_probe(dev, -EINVAL, "missing match data\n");
- ret = devm_regulator_bulk_get_enable(&spi->dev, st->chip_info->num_supplies,
+ ret = devm_regulator_bulk_get_enable(dev, st->chip_info->num_supplies,
st->chip_info->supplies);
if (ret)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Failed to enable power supplies\n");
fsleep(T_POWERUP_US);
- if (st->chip_info->external_ref_only) {
- ret = devm_regulator_get_enable_read_voltage(&spi->dev,
- "refin");
+ if (st->chip_info->adaq_internal_ref_only) {
+ /*
+ * ADAQ chips use fixed internal reference but still
+ * require a specific reference supply to power it.
+ * "refin" is already enabled with other power supplies
+ * in bulk_get_enable().
+ */
+
+ st->vref_mv = ADAQ4380_INTERNAL_REF_MV;
+
+ /* these chips don't have a register bit for this */
+ external_ref_en = false;
+ } else if (st->chip_info->external_ref_only) {
+ ret = devm_regulator_get_enable_read_voltage(dev, "refin");
if (ret < 0)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Failed to get refin regulator\n");
st->vref_mv = ret / 1000;
@@ -1065,10 +1156,9 @@ static int ad7380_probe(struct spi_device *spi)
* If there is no REFIO supply, then it means that we are using
* the internal reference, otherwise REFIO is reference voltage.
*/
- ret = devm_regulator_get_enable_read_voltage(&spi->dev,
- "refio");
+ ret = devm_regulator_get_enable_read_voltage(dev, "refio");
if (ret < 0 && ret != -ENODEV)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Failed to get refio regulator\n");
external_ref_en = ret != -ENODEV;
@@ -1076,7 +1166,7 @@ static int ad7380_probe(struct spi_device *spi)
}
if (st->chip_info->num_vcm_supplies > ARRAY_SIZE(st->vcm_mv))
- return dev_err_probe(&spi->dev, -EINVAL,
+ return dev_err_probe(dev, -EINVAL,
"invalid number of VCM supplies\n");
/*
@@ -1086,18 +1176,54 @@ static int ad7380_probe(struct spi_device *spi)
for (i = 0; i < st->chip_info->num_vcm_supplies; i++) {
const char *vcm = st->chip_info->vcm_supplies[i];
- ret = devm_regulator_get_enable_read_voltage(&spi->dev, vcm);
+ ret = devm_regulator_get_enable_read_voltage(dev, vcm);
if (ret < 0)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Failed to get %s regulator\n",
vcm);
st->vcm_mv[i] = ret / 1000;
}
- st->regmap = devm_regmap_init(&spi->dev, NULL, st, &ad7380_regmap_config);
+ for (i = 0; i < MAX_NUM_CHANNELS; i++)
+ st->gain_milli[i] = AD7380_DEFAULT_GAIN_MILLI;
+
+ if (st->chip_info->has_hardware_gain) {
+ device_for_each_child_node_scoped(dev, node) {
+ unsigned int channel, gain;
+ int gain_idx;
+
+ ret = fwnode_property_read_u32(node, "reg", &channel);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to read reg property\n");
+
+ if (channel >= st->chip_info->num_channels - 1)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid channel number %i\n",
+ channel);
+
+ ret = fwnode_property_read_u32(node, "adi,gain-milli",
+ &gain);
+ if (ret && ret != -EINVAL)
+ return dev_err_probe(dev, ret,
+ "Failed to read gain for channel %i\n",
+ channel);
+ if (ret != -EINVAL) {
+ /*
+ * Match gain value from dt to one of supported
+ * gains
+ */
+ gain_idx = find_closest(gain, ad7380_gains,
+ ARRAY_SIZE(ad7380_gains));
+ st->gain_milli[channel] = ad7380_gains[gain_idx];
+ }
+ }
+ }
+
+ st->regmap = devm_regmap_init(dev, NULL, st, &ad7380_regmap_config);
if (IS_ERR(st->regmap))
- return dev_err_probe(&spi->dev, PTR_ERR(st->regmap),
+ return dev_err_probe(dev, PTR_ERR(st->regmap),
"failed to allocate register map\n");
/*
@@ -1148,7 +1274,7 @@ static int ad7380_probe(struct spi_device *spi)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->available_scan_masks = st->chip_info->available_scan_masks;
- ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
iio_pollfunc_store_time,
ad7380_trigger_handler,
&ad7380_buffer_setup_ops);
@@ -1159,7 +1285,7 @@ static int ad7380_probe(struct spi_device *spi)
if (ret)
return ret;
- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct of_device_id ad7380_of_match_table[] = {
@@ -1177,6 +1303,8 @@ static const struct of_device_id ad7380_of_match_table[] = {
{ .compatible = "adi,ad7386-4", .data = &ad7386_4_chip_info },
{ .compatible = "adi,ad7387-4", .data = &ad7387_4_chip_info },
{ .compatible = "adi,ad7388-4", .data = &ad7388_4_chip_info },
+ { .compatible = "adi,adaq4370-4", .data = &adaq4370_4_chip_info },
+ { .compatible = "adi,adaq4380-4", .data = &adaq4380_4_chip_info },
{ }
};
@@ -1195,6 +1323,8 @@ static const struct spi_device_id ad7380_id_table[] = {
{ "ad7386-4", (kernel_ulong_t)&ad7386_4_chip_info },
{ "ad7387-4", (kernel_ulong_t)&ad7387_4_chip_info },
{ "ad7388-4", (kernel_ulong_t)&ad7388_4_chip_info },
+ { "adaq4370-4", (kernel_ulong_t)&adaq4370_4_chip_info },
+ { "adaq4380-4", (kernel_ulong_t)&adaq4380_4_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ad7380_id_table);
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
index 9b457472d49c..8b2046baaa3e 100644
--- a/drivers/iio/adc/ad7606.c
+++ b/drivers/iio/adc/ad7606.c
@@ -13,14 +13,17 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/property.h>
+#include <linux/pwm.h>
#include <linux/regulator/consumer.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/units.h>
#include <linux/util_macros.h>
-#include <linux/iio/iio.h>
+#include <linux/iio/backend.h>
#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
@@ -30,15 +33,52 @@
/*
* Scales are computed as 5000/32768 and 10000/32768 respectively,
- * so that when applied to the raw values they provide mV values
+ * so that when applied to the raw values they provide mV values.
+ * The scale arrays are kept as IIO_VAL_INT_PLUS_MICRO, so index
+ * X is the integer part and X + 1 is the fractional part.
*/
-static const unsigned int ad7606_scale_avail[2] = {
- 152588, 305176
+static const unsigned int ad7606_16bit_hw_scale_avail[2][2] = {
+ { 0, 152588 }, { 0, 305176 }
+};
+
+static const unsigned int ad7606_18bit_hw_scale_avail[2][2] = {
+ { 0, 38147 }, { 0, 76294 }
+};
+
+static const unsigned int ad7606c_16bit_single_ended_unipolar_scale_avail[3][2] = {
+ { 0, 76294 }, { 0, 152588 }, { 0, 190735 }
+};
+
+static const unsigned int ad7606c_16bit_single_ended_bipolar_scale_avail[5][2] = {
+ { 0, 76294 }, { 0, 152588 }, { 0, 190735 }, { 0, 305176 }, { 0, 381470 }
+};
+
+static const unsigned int ad7606c_16bit_differential_bipolar_scale_avail[4][2] = {
+ { 0, 152588 }, { 0, 305176 }, { 0, 381470 }, { 0, 610352 }
+};
+
+static const unsigned int ad7606c_18bit_single_ended_unipolar_scale_avail[3][2] = {
+ { 0, 19073 }, { 0, 38147 }, { 0, 47684 }
+};
+
+static const unsigned int ad7606c_18bit_single_ended_bipolar_scale_avail[5][2] = {
+ { 0, 19073 }, { 0, 38147 }, { 0, 47684 }, { 0, 76294 }, { 0, 95367 }
};
+static const unsigned int ad7606c_18bit_differential_bipolar_scale_avail[4][2] = {
+ { 0, 38147 }, { 0, 76294 }, { 0, 95367 }, { 0, 152588 }
+};
+
+static const unsigned int ad7606_16bit_sw_scale_avail[3][2] = {
+ { 0, 76293 }, { 0, 152588 }, { 0, 305176 }
+};
-static const unsigned int ad7616_sw_scale_avail[3] = {
- 76293, 152588, 305176
+static const unsigned int ad7607_hw_scale_avail[2][2] = {
+ { 0, 610352 }, { 1, 220703 }
+};
+
+static const unsigned int ad7609_hw_scale_avail[2][2] = {
+ { 0, 152588 }, { 0, 305176 }
};
static const unsigned int ad7606_oversampling_avail[7] = {
@@ -49,6 +89,227 @@ static const unsigned int ad7616_oversampling_avail[8] = {
1, 2, 4, 8, 16, 32, 64, 128,
};
+static const struct iio_chan_spec ad7605_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ AD7605_CHANNEL(0),
+ AD7605_CHANNEL(1),
+ AD7605_CHANNEL(2),
+ AD7605_CHANNEL(3),
+};
+
+static const struct iio_chan_spec ad7606_channels_16bit[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_CHANNEL(0, 16),
+ AD7606_CHANNEL(1, 16),
+ AD7606_CHANNEL(2, 16),
+ AD7606_CHANNEL(3, 16),
+ AD7606_CHANNEL(4, 16),
+ AD7606_CHANNEL(5, 16),
+ AD7606_CHANNEL(6, 16),
+ AD7606_CHANNEL(7, 16),
+};
+
+static const struct iio_chan_spec ad7606_channels_18bit[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_CHANNEL(0, 18),
+ AD7606_CHANNEL(1, 18),
+ AD7606_CHANNEL(2, 18),
+ AD7606_CHANNEL(3, 18),
+ AD7606_CHANNEL(4, 18),
+ AD7606_CHANNEL(5, 18),
+ AD7606_CHANNEL(6, 18),
+ AD7606_CHANNEL(7, 18),
+};
+
+static const struct iio_chan_spec ad7607_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_CHANNEL(0, 14),
+ AD7606_CHANNEL(1, 14),
+ AD7606_CHANNEL(2, 14),
+ AD7606_CHANNEL(3, 14),
+ AD7606_CHANNEL(4, 14),
+ AD7606_CHANNEL(5, 14),
+ AD7606_CHANNEL(6, 14),
+ AD7606_CHANNEL(7, 14),
+};
+
+static const struct iio_chan_spec ad7608_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_CHANNEL(0, 18),
+ AD7606_CHANNEL(1, 18),
+ AD7606_CHANNEL(2, 18),
+ AD7606_CHANNEL(3, 18),
+ AD7606_CHANNEL(4, 18),
+ AD7606_CHANNEL(5, 18),
+ AD7606_CHANNEL(6, 18),
+ AD7606_CHANNEL(7, 18),
+};
+
+/*
+ * The current assumption that this driver makes for AD7616, is that it's
+ * working in Hardware Mode with Serial, Burst and Sequencer modes activated.
+ * To activate them, following pins must be pulled high:
+ * -SER/PAR
+ * -SEQEN
+ * And following pins must be pulled low:
+ * -WR/BURST
+ * -DB4/SER1W
+ */
+static const struct iio_chan_spec ad7616_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(16),
+ AD7606_CHANNEL(0, 16),
+ AD7606_CHANNEL(1, 16),
+ AD7606_CHANNEL(2, 16),
+ AD7606_CHANNEL(3, 16),
+ AD7606_CHANNEL(4, 16),
+ AD7606_CHANNEL(5, 16),
+ AD7606_CHANNEL(6, 16),
+ AD7606_CHANNEL(7, 16),
+ AD7606_CHANNEL(8, 16),
+ AD7606_CHANNEL(9, 16),
+ AD7606_CHANNEL(10, 16),
+ AD7606_CHANNEL(11, 16),
+ AD7606_CHANNEL(12, 16),
+ AD7606_CHANNEL(13, 16),
+ AD7606_CHANNEL(14, 16),
+ AD7606_CHANNEL(15, 16),
+};
+
+static int ad7606c_18bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7606c_16bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7606_16bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7607_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7608_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7609_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+
+const struct ad7606_chip_info ad7605_4_info = {
+ .channels = ad7605_channels,
+ .name = "ad7605-4",
+ .num_adc_channels = 4,
+ .num_channels = 5,
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7605_4_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7606_8_info = {
+ .channels = ad7606_channels_16bit,
+ .name = "ad7606-8",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606_8_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7606_6_info = {
+ .channels = ad7606_channels_16bit,
+ .name = "ad7606-6",
+ .num_adc_channels = 6,
+ .num_channels = 7,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606_6_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7606_4_info = {
+ .channels = ad7606_channels_16bit,
+ .name = "ad7606-4",
+ .num_adc_channels = 4,
+ .num_channels = 5,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606_4_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7606b_info = {
+ .channels = ad7606_channels_16bit,
+ .max_samplerate = 800 * KILO,
+ .name = "ad7606b",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606b_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7606c_16_info = {
+ .channels = ad7606_channels_16bit,
+ .name = "ad7606c16",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606c_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606c_16_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7607_info = {
+ .channels = ad7607_channels,
+ .name = "ad7607",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7607_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7607_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7608_info = {
+ .channels = ad7608_channels,
+ .name = "ad7608",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7608_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7608_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7609_info = {
+ .channels = ad7608_channels,
+ .name = "ad7609",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7609_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7609_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7606c_18_info = {
+ .channels = ad7606_channels_18bit,
+ .name = "ad7606c18",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606c_18bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606c_18_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7616_info = {
+ .channels = ad7616_channels,
+ .init_delay_ms = 15,
+ .name = "ad7616",
+ .num_adc_channels = 16,
+ .num_channels = 17,
+ .oversampling_avail = ad7616_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail),
+ .os_req_reset = true,
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7616_info, IIO_AD7606);
+
int ad7606_reset(struct ad7606_state *st)
{
if (st->gpio_reset) {
@@ -62,6 +323,228 @@ int ad7606_reset(struct ad7606_state *st)
}
EXPORT_SYMBOL_NS_GPL(ad7606_reset, IIO_AD7606);
+static int ad7606_16bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+
+ if (!st->sw_mode_en) {
+ /* tied to logic low, analog input range is +/- 5V */
+ cs->range = 0;
+ cs->scale_avail = ad7606_16bit_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_16bit_hw_scale_avail);
+ return 0;
+ }
+
+ /* Scale of 0.076293 is only available in sw mode */
+ /* After reset, in software mode, ±10 V is set by default */
+ cs->range = 2;
+ cs->scale_avail = ad7606_16bit_sw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_16bit_sw_scale_avail);
+
+ return 0;
+}
+
+static int ad7606_get_chan_config(struct ad7606_state *st, int ch,
+ bool *bipolar, bool *differential)
+{
+ unsigned int num_channels = st->chip_info->num_channels - 1;
+ struct device *dev = st->dev;
+ int ret;
+
+ *bipolar = false;
+ *differential = false;
+
+ device_for_each_child_node_scoped(dev, child) {
+ u32 pins[2];
+ int reg;
+
+ ret = fwnode_property_read_u32(child, "reg", &reg);
+ if (ret)
+ continue;
+
+ /* channel number (here) is from 1 to num_channels */
+ if (reg == 0 || reg > num_channels) {
+ dev_warn(dev,
+ "Invalid channel number (ignoring): %d\n", reg);
+ continue;
+ }
+
+ if (reg != (ch + 1))
+ continue;
+
+ *bipolar = fwnode_property_read_bool(child, "bipolar");
+
+ ret = fwnode_property_read_u32_array(child, "diff-channels",
+ pins, ARRAY_SIZE(pins));
+ /* Channel is differential, if pins are the same as 'reg' */
+ if (ret == 0 && (pins[0] != reg || pins[1] != reg)) {
+ dev_err(dev,
+ "Differential pins must be the same as 'reg'");
+ return -EINVAL;
+ }
+
+ *differential = (ret == 0);
+
+ if (*differential && !*bipolar) {
+ dev_err(dev,
+ "'bipolar' must be added for diff channel %d\n",
+ reg);
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+
+ return 0;
+}
+
+static int ad7606c_18bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+ bool bipolar, differential;
+ int ret;
+
+ if (!st->sw_mode_en) {
+ cs->range = 0;
+ cs->scale_avail = ad7606_18bit_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_18bit_hw_scale_avail);
+ return 0;
+ }
+
+ ret = ad7606_get_chan_config(st, ch, &bipolar, &differential);
+ if (ret)
+ return ret;
+
+ if (differential) {
+ cs->scale_avail = ad7606c_18bit_differential_bipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_18bit_differential_bipolar_scale_avail);
+ /* Bipolar differential ranges start at 8 (b1000) */
+ cs->reg_offset = 8;
+ cs->range = 1;
+ chan->differential = 1;
+ chan->channel2 = chan->channel;
+
+ return 0;
+ }
+
+ chan->differential = 0;
+
+ if (bipolar) {
+ cs->scale_avail = ad7606c_18bit_single_ended_bipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_18bit_single_ended_bipolar_scale_avail);
+ /* Bipolar single-ended ranges start at 0 (b0000) */
+ cs->reg_offset = 0;
+ cs->range = 3;
+ chan->scan_type.sign = 's';
+
+ return 0;
+ }
+
+ cs->scale_avail = ad7606c_18bit_single_ended_unipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_18bit_single_ended_unipolar_scale_avail);
+ /* Unipolar single-ended ranges start at 5 (b0101) */
+ cs->reg_offset = 5;
+ cs->range = 1;
+ chan->scan_type.sign = 'u';
+
+ return 0;
+}
+
+static int ad7606c_16bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+ bool bipolar, differential;
+ int ret;
+
+ if (!st->sw_mode_en) {
+ cs->range = 0;
+ cs->scale_avail = ad7606_16bit_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_16bit_hw_scale_avail);
+ return 0;
+ }
+
+ ret = ad7606_get_chan_config(st, ch, &bipolar, &differential);
+ if (ret)
+ return ret;
+
+ if (differential) {
+ cs->scale_avail = ad7606c_16bit_differential_bipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_16bit_differential_bipolar_scale_avail);
+ /* Bipolar differential ranges start at 8 (b1000) */
+ cs->reg_offset = 8;
+ cs->range = 1;
+ chan->differential = 1;
+ chan->channel2 = chan->channel;
+ chan->scan_type.sign = 's';
+
+ return 0;
+ }
+
+ chan->differential = 0;
+
+ if (bipolar) {
+ cs->scale_avail = ad7606c_16bit_single_ended_bipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_16bit_single_ended_bipolar_scale_avail);
+ /* Bipolar single-ended ranges start at 0 (b0000) */
+ cs->reg_offset = 0;
+ cs->range = 3;
+ chan->scan_type.sign = 's';
+
+ return 0;
+ }
+
+ cs->scale_avail = ad7606c_16bit_single_ended_unipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_16bit_single_ended_unipolar_scale_avail);
+ /* Unipolar single-ended ranges start at 5 (b0101) */
+ cs->reg_offset = 5;
+ cs->range = 1;
+ chan->scan_type.sign = 'u';
+
+ return 0;
+}
+
+static int ad7607_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+
+ cs->range = 0;
+ cs->scale_avail = ad7607_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7607_hw_scale_avail);
+ return 0;
+}
+
+static int ad7608_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+
+ cs->range = 0;
+ cs->scale_avail = ad7606_18bit_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_18bit_hw_scale_avail);
+ return 0;
+}
+
+static int ad7609_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+
+ cs->range = 0;
+ cs->scale_avail = ad7609_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7609_hw_scale_avail);
+ return 0;
+}
+
static int ad7606_reg_access(struct iio_dev *indio_dev,
unsigned int reg,
unsigned int writeval,
@@ -83,12 +566,85 @@ static int ad7606_reg_access(struct iio_dev *indio_dev,
}
}
+static int ad7606_pwm_set_high(struct ad7606_state *st)
+{
+ struct pwm_state cnvst_pwm_state;
+ int ret;
+
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ cnvst_pwm_state.enabled = true;
+ cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period;
+
+ ret = pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
+
+ return ret;
+}
+
+static int ad7606_pwm_set_low(struct ad7606_state *st)
+{
+ struct pwm_state cnvst_pwm_state;
+ int ret;
+
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ cnvst_pwm_state.enabled = true;
+ cnvst_pwm_state.duty_cycle = 0;
+
+ ret = pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
+
+ return ret;
+}
+
+static int ad7606_pwm_set_swing(struct ad7606_state *st)
+{
+ struct pwm_state cnvst_pwm_state;
+
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ cnvst_pwm_state.enabled = true;
+ cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period / 2;
+
+ return pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
+}
+
+static bool ad7606_pwm_is_swinging(struct ad7606_state *st)
+{
+ struct pwm_state cnvst_pwm_state;
+
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+
+ return cnvst_pwm_state.duty_cycle != cnvst_pwm_state.period &&
+ cnvst_pwm_state.duty_cycle != 0;
+}
+
+static int ad7606_set_sampling_freq(struct ad7606_state *st, unsigned long freq)
+{
+ struct pwm_state cnvst_pwm_state;
+ bool is_swinging = ad7606_pwm_is_swinging(st);
+ bool is_high;
+
+ if (freq == 0)
+ return -EINVAL;
+
+ /* Retrieve the previous state. */
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ is_high = cnvst_pwm_state.duty_cycle == cnvst_pwm_state.period;
+
+ cnvst_pwm_state.period = DIV_ROUND_UP_ULL(NSEC_PER_SEC, freq);
+ cnvst_pwm_state.polarity = PWM_POLARITY_NORMAL;
+ if (is_high)
+ cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period;
+ else if (is_swinging)
+ cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period / 2;
+ else
+ cnvst_pwm_state.duty_cycle = 0;
+
+ return pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
+}
+
static int ad7606_read_samples(struct ad7606_state *st)
{
- unsigned int num = st->chip_info->num_channels - 1;
- u16 *data = st->data;
+ unsigned int num = st->chip_info->num_adc_channels;
- return st->bops->read_block(st->dev, num, data);
+ return st->bops->read_block(st->dev, num, &st->data);
}
static irqreturn_t ad7606_trigger_handler(int irq, void *p)
@@ -104,7 +660,7 @@ static irqreturn_t ad7606_trigger_handler(int irq, void *p)
if (ret)
goto error_ret;
- iio_push_to_buffers_with_timestamp(indio_dev, st->data,
+ iio_push_to_buffers_with_timestamp(indio_dev, &st->data,
iio_get_time_ns(indio_dev));
error_ret:
iio_trigger_notify_done(indio_dev->trig);
@@ -114,24 +670,62 @@ error_ret:
return IRQ_HANDLED;
}
-static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch)
+static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch,
+ int *val)
{
struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int realbits = st->chip_info->channels[1].scan_type.realbits;
+ const struct iio_chan_spec *chan;
int ret;
- gpiod_set_value(st->gpio_convst, 1);
- ret = wait_for_completion_timeout(&st->completion,
- msecs_to_jiffies(1000));
- if (!ret) {
- ret = -ETIMEDOUT;
- goto error_ret;
+ if (st->gpio_convst) {
+ gpiod_set_value(st->gpio_convst, 1);
+ } else {
+ ret = ad7606_pwm_set_high(st);
+ if (ret < 0)
+ return ret;
+ }
+
+ /*
+ * If no backend, wait for the interruption on busy pin, otherwise just add
+ * a delay to leave time for the data to be available. For now, the latter
+ * will not happen because IIO_CHAN_INFO_RAW is not supported for the backend.
+ * TODO: Add support for reading a single value when the backend is used.
+ */
+ if (!st->back) {
+ ret = wait_for_completion_timeout(&st->completion,
+ msecs_to_jiffies(1000));
+ if (!ret) {
+ ret = -ETIMEDOUT;
+ goto error_ret;
+ }
+ } else {
+ fsleep(1);
}
ret = ad7606_read_samples(st);
- if (ret == 0)
- ret = st->data[ch];
+ if (ret)
+ goto error_ret;
+
+ chan = &indio_dev->channels[ch + 1];
+ if (chan->scan_type.sign == 'u') {
+ if (realbits > 16)
+ *val = st->data.buf32[ch];
+ else
+ *val = st->data.buf16[ch];
+ } else {
+ if (realbits > 16)
+ *val = sign_extend32(st->data.buf32[ch], realbits - 1);
+ else
+ *val = sign_extend32(st->data.buf16[ch], realbits - 1);
+ }
error_ret:
+ if (!st->gpio_convst) {
+ ret = ad7606_pwm_set_low(st);
+ if (ret < 0)
+ return ret;
+ }
gpiod_set_value(st->gpio_convst, 0);
return ret;
@@ -145,53 +739,57 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
{
int ret, ch = 0;
struct ad7606_state *st = iio_priv(indio_dev);
+ struct ad7606_chan_scale *cs;
+ struct pwm_state cnvst_pwm_state;
switch (m) {
case IIO_CHAN_INFO_RAW:
iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
- ret = ad7606_scan_direct(indio_dev, chan->address);
+ ret = ad7606_scan_direct(indio_dev, chan->address, val);
if (ret < 0)
return ret;
- *val = (short) ret;
return IIO_VAL_INT;
}
unreachable();
case IIO_CHAN_INFO_SCALE:
if (st->sw_mode_en)
ch = chan->address;
- *val = 0;
- *val2 = st->scale_avail[st->range[ch]];
+ cs = &st->chan_scales[ch];
+ *val = cs->scale_avail[cs->range][0];
+ *val2 = cs->scale_avail[cs->range][1];
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
*val = st->oversampling;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ /*
+ * TODO: return the real frequency intead of the requested one once
+ * pwm_get_state_hw comes upstream.
+ */
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ *val = DIV_ROUND_CLOSEST_ULL(NSEC_PER_SEC, cnvst_pwm_state.period);
+ return IIO_VAL_INT;
}
return -EINVAL;
}
-static ssize_t ad7606_show_avail(char *buf, const unsigned int *vals,
- unsigned int n, bool micros)
-{
- size_t len = 0;
- int i;
-
- for (i = 0; i < n; i++) {
- len += scnprintf(buf + len, PAGE_SIZE - len,
- micros ? "0.%06u " : "%u ", vals[i]);
- }
- buf[len - 1] = '\n';
-
- return len;
-}
-
static ssize_t in_voltage_scale_available_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7606_state *st = iio_priv(indio_dev);
+ struct ad7606_chan_scale *cs = &st->chan_scales[0];
+ const unsigned int (*vals)[2] = cs->scale_avail;
+ unsigned int i;
+ size_t len = 0;
+
+ for (i = 0; i < cs->num_scales; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%u.%06u ",
+ vals[i][0], vals[i][1]);
+ buf[len - 1] = '\n';
- return ad7606_show_avail(buf, st->scale_avail, st->num_scales, true);
+ return len;
}
static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0);
@@ -229,19 +827,27 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int scale_avail_uv[AD760X_MAX_SCALES];
+ struct ad7606_chan_scale *cs;
int i, ret, ch = 0;
guard(mutex)(&st->lock);
switch (mask) {
case IIO_CHAN_INFO_SCALE:
- i = find_closest(val2, st->scale_avail, st->num_scales);
if (st->sw_mode_en)
ch = chan->address;
- ret = st->write_scale(indio_dev, ch, i);
+ cs = &st->chan_scales[ch];
+ for (i = 0; i < cs->num_scales; i++) {
+ scale_avail_uv[i] = cs->scale_avail[i][0] * MICRO +
+ cs->scale_avail[i][1];
+ }
+ val = (val * MICRO) + val2;
+ i = find_closest(val, scale_avail_uv, cs->num_scales);
+ ret = st->write_scale(indio_dev, ch, i + cs->reg_offset);
if (ret < 0)
return ret;
- st->range[ch] = i;
+ cs->range = i;
return 0;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
@@ -252,8 +858,13 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
ret = st->write_os(indio_dev, i);
if (ret < 0)
return ret;
+ st->oversampling = st->oversampling_avail[i];
return 0;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val < 0 && val2 != 0)
+ return -EINVAL;
+ return ad7606_set_sampling_freq(st, val);
default:
return -EINVAL;
}
@@ -265,9 +876,15 @@ static ssize_t ad7606_oversampling_ratio_avail(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7606_state *st = iio_priv(indio_dev);
+ const unsigned int *vals = st->oversampling_avail;
+ unsigned int i;
+ size_t len = 0;
- return ad7606_show_avail(buf, st->oversampling_avail,
- st->num_os_ratios, false);
+ for (i = 0; i < st->num_os_ratios; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%u ", vals[i]);
+ buf[len - 1] = '\n';
+
+ return len;
}
static IIO_DEVICE_ATTR(oversampling_ratio_available, 0444,
@@ -301,102 +918,13 @@ static const struct attribute_group ad7606_attribute_group_range = {
.attrs = ad7606_attributes_range,
};
-static const struct iio_chan_spec ad7605_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(4),
- AD7605_CHANNEL(0),
- AD7605_CHANNEL(1),
- AD7605_CHANNEL(2),
- AD7605_CHANNEL(3),
-};
-
-static const struct iio_chan_spec ad7606_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(8),
- AD7606_CHANNEL(0),
- AD7606_CHANNEL(1),
- AD7606_CHANNEL(2),
- AD7606_CHANNEL(3),
- AD7606_CHANNEL(4),
- AD7606_CHANNEL(5),
- AD7606_CHANNEL(6),
- AD7606_CHANNEL(7),
-};
-
-/*
- * The current assumption that this driver makes for AD7616, is that it's
- * working in Hardware Mode with Serial, Burst and Sequencer modes activated.
- * To activate them, following pins must be pulled high:
- * -SER/PAR
- * -SEQEN
- * And following pins must be pulled low:
- * -WR/BURST
- * -DB4/SER1W
- */
-static const struct iio_chan_spec ad7616_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(16),
- AD7606_CHANNEL(0),
- AD7606_CHANNEL(1),
- AD7606_CHANNEL(2),
- AD7606_CHANNEL(3),
- AD7606_CHANNEL(4),
- AD7606_CHANNEL(5),
- AD7606_CHANNEL(6),
- AD7606_CHANNEL(7),
- AD7606_CHANNEL(8),
- AD7606_CHANNEL(9),
- AD7606_CHANNEL(10),
- AD7606_CHANNEL(11),
- AD7606_CHANNEL(12),
- AD7606_CHANNEL(13),
- AD7606_CHANNEL(14),
- AD7606_CHANNEL(15),
-};
-
-static const struct ad7606_chip_info ad7606_chip_info_tbl[] = {
- /* More devices added in future */
- [ID_AD7605_4] = {
- .channels = ad7605_channels,
- .num_channels = 5,
- },
- [ID_AD7606_8] = {
- .channels = ad7606_channels,
- .num_channels = 9,
- .oversampling_avail = ad7606_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
- },
- [ID_AD7606_6] = {
- .channels = ad7606_channels,
- .num_channels = 7,
- .oversampling_avail = ad7606_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
- },
- [ID_AD7606_4] = {
- .channels = ad7606_channels,
- .num_channels = 5,
- .oversampling_avail = ad7606_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
- },
- [ID_AD7606B] = {
- .channels = ad7606_channels,
- .num_channels = 9,
- .oversampling_avail = ad7606_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
- },
- [ID_AD7616] = {
- .channels = ad7616_channels,
- .num_channels = 17,
- .oversampling_avail = ad7616_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail),
- .os_req_reset = true,
- .init_delay_ms = 15,
- },
-};
-
static int ad7606_request_gpios(struct ad7606_state *st)
{
struct device *dev = st->dev;
- st->gpio_convst = devm_gpiod_get(dev, "adi,conversion-start",
- GPIOD_OUT_LOW);
+ st->gpio_convst = devm_gpiod_get_optional(dev, "adi,conversion-start",
+ GPIOD_OUT_LOW);
+
if (IS_ERR(st->gpio_convst))
return PTR_ERR(st->gpio_convst);
@@ -438,14 +966,24 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id)
{
struct iio_dev *indio_dev = dev_id;
struct ad7606_state *st = iio_priv(indio_dev);
+ int ret;
if (iio_buffer_enabled(indio_dev)) {
- gpiod_set_value(st->gpio_convst, 0);
+ if (st->gpio_convst) {
+ gpiod_set_value(st->gpio_convst, 0);
+ } else {
+ ret = ad7606_pwm_set_low(st);
+ if (ret < 0) {
+ dev_err(st->dev, "PWM set low failed");
+ goto done;
+ }
+ }
iio_trigger_poll_nested(st->trig);
} else {
complete(&st->completion);
}
+done:
return IRQ_HANDLED;
};
@@ -478,14 +1016,81 @@ static int ad7606_buffer_predisable(struct iio_dev *indio_dev)
return 0;
}
+static int ad7606_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long info)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+ struct ad7606_chan_scale *cs;
+ unsigned int ch = 0;
+
+ switch (info) {
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ *vals = st->oversampling_avail;
+ *length = st->num_os_ratios;
+ *type = IIO_VAL_INT;
+
+ return IIO_AVAIL_LIST;
+
+ case IIO_CHAN_INFO_SCALE:
+ if (st->sw_mode_en)
+ ch = chan->address;
+
+ cs = &st->chan_scales[ch];
+ *vals = (int *)cs->scale_avail;
+ *length = cs->num_scales;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+
+ return IIO_AVAIL_LIST;
+ }
+ return -EINVAL;
+}
+
+static int ad7606_backend_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ return ad7606_pwm_set_swing(st);
+}
+
+static int ad7606_backend_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ return ad7606_pwm_set_low(st);
+}
+
+static int ad7606_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ /*
+ * The update scan mode is only for iio backend compatible drivers.
+ * If the specific update_scan_mode is not defined in the bus ops,
+ * just do nothing and return 0.
+ */
+ if (!st->bops->update_scan_mode)
+ return 0;
+
+ return st->bops->update_scan_mode(indio_dev, scan_mask);
+}
+
static const struct iio_buffer_setup_ops ad7606_buffer_ops = {
.postenable = &ad7606_buffer_postenable,
.predisable = &ad7606_buffer_predisable,
};
+static const struct iio_buffer_setup_ops ad7606_backend_buffer_ops = {
+ .postenable = &ad7606_backend_buffer_postenable,
+ .predisable = &ad7606_backend_buffer_predisable,
+};
+
static const struct iio_info ad7606_info_no_os_or_range = {
.read_raw = &ad7606_read_raw,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
static const struct iio_info ad7606_info_os_and_range = {
@@ -493,14 +1098,16 @@ static const struct iio_info ad7606_info_os_and_range = {
.write_raw = &ad7606_write_raw,
.attrs = &ad7606_attribute_group_os_and_range,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
-static const struct iio_info ad7606_info_os_range_and_debug = {
+static const struct iio_info ad7606_info_sw_mode = {
.read_raw = &ad7606_read_raw,
.write_raw = &ad7606_write_raw,
+ .read_avail = &ad7606_read_avail,
.debugfs_reg_access = &ad7606_reg_access,
- .attrs = &ad7606_attribute_group_os_and_range,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
static const struct iio_info ad7606_info_os = {
@@ -508,6 +1115,7 @@ static const struct iio_info ad7606_info_os = {
.write_raw = &ad7606_write_raw,
.attrs = &ad7606_attribute_group_os,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
static const struct iio_info ad7606_info_range = {
@@ -515,14 +1123,60 @@ static const struct iio_info ad7606_info_range = {
.write_raw = &ad7606_write_raw,
.attrs = &ad7606_attribute_group_range,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
static const struct iio_trigger_ops ad7606_trigger_ops = {
.validate_device = iio_trigger_validate_own_device,
};
+static int ad7606_sw_mode_setup(struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ st->sw_mode_en = st->bops->sw_mode_config &&
+ device_property_present(st->dev, "adi,sw-mode");
+ if (!st->sw_mode_en)
+ return 0;
+
+ indio_dev->info = &ad7606_info_sw_mode;
+
+ return st->bops->sw_mode_config(indio_dev);
+}
+
+static int ad7606_chan_scales_setup(struct iio_dev *indio_dev)
+{
+ unsigned int num_channels = indio_dev->num_channels - 1;
+ struct ad7606_state *st = iio_priv(indio_dev);
+ struct iio_chan_spec *chans;
+ size_t size;
+ int ch, ret;
+
+ /* Clone IIO channels, since some may be differential */
+ size = indio_dev->num_channels * sizeof(*indio_dev->channels);
+ chans = devm_kzalloc(st->dev, size, GFP_KERNEL);
+ if (!chans)
+ return -ENOMEM;
+
+ memcpy(chans, indio_dev->channels, size);
+ indio_dev->channels = chans;
+
+ for (ch = 0; ch < num_channels; ch++) {
+ ret = st->chip_info->scale_setup_cb(st, &chans[ch + 1], ch);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void ad7606_pwm_disable(void *data)
+{
+ pwm_disable(data);
+}
+
int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
- const char *name, unsigned int id,
+ const struct ad7606_chip_info *chip_info,
const struct ad7606_bus_ops *bops)
{
struct ad7606_state *st;
@@ -540,18 +1194,14 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
mutex_init(&st->lock);
st->bops = bops;
st->base_address = base_address;
- /* tied to logic low, analog input range is +/- 5V */
- st->range[0] = 0;
st->oversampling = 1;
- st->scale_avail = ad7606_scale_avail;
- st->num_scales = ARRAY_SIZE(ad7606_scale_avail);
ret = devm_regulator_get_enable(dev, "avcc");
if (ret)
return dev_err_probe(dev, ret,
"Failed to enable specified AVcc supply\n");
- st->chip_info = &ad7606_chip_info_tbl[id];
+ st->chip_info = chip_info;
if (st->chip_info->oversampling_num) {
st->oversampling_avail = st->chip_info->oversampling_avail;
@@ -574,12 +1224,10 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
indio_dev->info = &ad7606_info_no_os_or_range;
}
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->name = name;
+ indio_dev->name = chip_info->name;
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
- init_completion(&st->completion);
-
ret = ad7606_reset(st);
if (ret)
dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n");
@@ -593,52 +1241,90 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
st->write_scale = ad7606_write_scale_hw;
st->write_os = ad7606_write_os_hw;
- if (st->bops->sw_mode_config)
- st->sw_mode_en = device_property_present(st->dev,
- "adi,sw-mode");
+ ret = ad7606_sw_mode_setup(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad7606_chan_scales_setup(indio_dev);
+ if (ret)
+ return ret;
+
+ /* If convst pin is not defined, setup PWM. */
+ if (!st->gpio_convst) {
+ st->cnvst_pwm = devm_pwm_get(dev, NULL);
+ if (IS_ERR(st->cnvst_pwm))
+ return PTR_ERR(st->cnvst_pwm);
- if (st->sw_mode_en) {
- /* Scale of 0.076293 is only available in sw mode */
- st->scale_avail = ad7616_sw_scale_avail;
- st->num_scales = ARRAY_SIZE(ad7616_sw_scale_avail);
+ /* The PWM is initialized at 1MHz to have a fast enough GPIO emulation. */
+ ret = ad7606_set_sampling_freq(st, 1 * MEGA);
+ if (ret)
+ return ret;
- /* After reset, in software mode, ±10 V is set by default */
- memset32(st->range, 2, ARRAY_SIZE(st->range));
- indio_dev->info = &ad7606_info_os_range_and_debug;
+ ret = ad7606_pwm_set_low(st);
+ if (ret)
+ return ret;
- ret = st->bops->sw_mode_config(indio_dev);
- if (ret < 0)
+ /*
+ * PWM is not disabled when sampling stops, but instead its duty cycle is set
+ * to 0% to be sure we have a "low" state. After we unload the driver, let's
+ * disable the PWM.
+ */
+ ret = devm_add_action_or_reset(dev, ad7606_pwm_disable,
+ st->cnvst_pwm);
+ if (ret)
return ret;
}
- st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
- indio_dev->name,
- iio_device_id(indio_dev));
- if (!st->trig)
- return -ENOMEM;
+ if (st->bops->iio_backend_config) {
+ /*
+ * If there is a backend, the PWM should not overpass the maximum sampling
+ * frequency the chip supports.
+ */
+ ret = ad7606_set_sampling_freq(st,
+ chip_info->max_samplerate ? : 2 * KILO);
+ if (ret)
+ return ret;
- st->trig->ops = &ad7606_trigger_ops;
- iio_trigger_set_drvdata(st->trig, indio_dev);
- ret = devm_iio_trigger_register(dev, st->trig);
- if (ret)
- return ret;
+ ret = st->bops->iio_backend_config(dev, indio_dev);
+ if (ret)
+ return ret;
- indio_dev->trig = iio_trigger_get(st->trig);
+ indio_dev->setup_ops = &ad7606_backend_buffer_ops;
+ } else {
- ret = devm_request_threaded_irq(dev, irq,
- NULL,
- &ad7606_interrupt,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- name, indio_dev);
- if (ret)
- return ret;
+ /* Reserve the PWM use only for backend (force gpio_convst definition) */
+ if (!st->gpio_convst)
+ return dev_err_probe(dev, -EINVAL,
+ "No backend, connect convst to a GPIO");
+
+ init_completion(&st->completion);
+ st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!st->trig)
+ return -ENOMEM;
+
+ st->trig->ops = &ad7606_trigger_ops;
+ iio_trigger_set_drvdata(st->trig, indio_dev);
+ ret = devm_iio_trigger_register(dev, st->trig);
+ if (ret)
+ return ret;
- ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
- &iio_pollfunc_store_time,
- &ad7606_trigger_handler,
- &ad7606_buffer_ops);
- if (ret)
- return ret;
+ indio_dev->trig = iio_trigger_get(st->trig);
+
+ ret = devm_request_threaded_irq(dev, irq, NULL, &ad7606_interrupt,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ chip_info->name, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ &iio_pollfunc_store_time,
+ &ad7606_trigger_handler,
+ &ad7606_buffer_ops);
+ if (ret)
+ return ret;
+ }
return devm_iio_device_register(dev, indio_dev);
}
@@ -665,7 +1351,7 @@ static int ad7606_resume(struct device *dev)
struct ad7606_state *st = iio_priv(indio_dev);
if (st->gpio_standby) {
- gpiod_set_value(st->gpio_range, st->range[0]);
+ gpiod_set_value(st->gpio_range, st->chan_scales[0].range);
gpiod_set_value(st->gpio_standby, 1);
ad7606_reset(st);
}
diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h
index 6649e84d25de..998814a92b82 100644
--- a/drivers/iio/adc/ad7606.h
+++ b/drivers/iio/adc/ad7606.h
@@ -8,7 +8,9 @@
#ifndef IIO_ADC_AD7606_H_
#define IIO_ADC_AD7606_H_
-#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all) { \
+#define AD760X_MAX_CHANNELS 16
+
+#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all, bits) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = num, \
@@ -19,39 +21,79 @@
.scan_index = num, \
.scan_type = { \
.sign = 's', \
- .realbits = 16, \
- .storagebits = 16, \
+ .realbits = (bits), \
+ .storagebits = (bits) > 16 ? 32 : 16, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+#define AD7606_SW_CHANNEL(num, bits) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = num, \
+ .address = num, \
+ .info_mask_separate = \
+ BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_separate_available = \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+ .info_mask_shared_by_all_available = \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+ .scan_index = num, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = (bits), \
+ .storagebits = (bits) > 16 ? 32 : 16, \
.endianness = IIO_CPU, \
}, \
}
#define AD7605_CHANNEL(num) \
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \
- BIT(IIO_CHAN_INFO_SCALE), 0)
+ BIT(IIO_CHAN_INFO_SCALE), 0, 16)
-#define AD7606_CHANNEL(num) \
+#define AD7606_CHANNEL(num, bits) \
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \
BIT(IIO_CHAN_INFO_SCALE), \
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), bits)
+
+#define AD7616_CHANNEL(num) AD7606_SW_CHANNEL(num, 16)
+
+#define AD7606_BI_CHANNEL(num) \
+ AD760X_CHANNEL(num, 0, \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), 16)
-#define AD7616_CHANNEL(num) \
- AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),\
- 0, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
+struct ad7606_state;
+
+typedef int (*ad7606_scale_setup_cb_t)(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
/**
* struct ad7606_chip_info - chip specific information
* @channels: channel specification
+ * @max_samplerate: maximum supported samplerate
+ * @name device name
* @num_channels: number of channels
+ * @num_adc_channels the number of channels the ADC actually inputs.
+ * @scale_setup_cb: callback to setup the scales for each channel
* @oversampling_avail pointer to the array which stores the available
* oversampling ratios.
* @oversampling_num number of elements stored in oversampling_avail array
* @os_req_reset some devices require a reset to update oversampling
- * @init_delay_ms required delay in miliseconds for initialization
+ * @init_delay_ms required delay in milliseconds for initialization
* after a restart
*/
struct ad7606_chip_info {
const struct iio_chan_spec *channels;
+ unsigned int max_samplerate;
+ const char *name;
+ unsigned int num_adc_channels;
unsigned int num_channels;
+ ad7606_scale_setup_cb_t scale_setup_cb;
const unsigned int *oversampling_avail;
unsigned int oversampling_num;
bool os_req_reset;
@@ -59,16 +101,31 @@ struct ad7606_chip_info {
};
/**
+ * struct ad7606_chan_scale - channel scale configuration
+ * @scale_avail pointer to the array which stores the available scales
+ * @num_scales number of elements stored in the scale_avail array
+ * @range voltage range selection, selects which scale to apply
+ * @reg_offset offset for the register value, to be applied when
+ * writing the value of 'range' to the register value
+ */
+struct ad7606_chan_scale {
+#define AD760X_MAX_SCALES 16
+ const unsigned int (*scale_avail)[2];
+ unsigned int num_scales;
+ unsigned int range;
+ unsigned int reg_offset;
+};
+
+/**
* struct ad7606_state - driver instance specific data
* @dev pointer to kernel device
* @chip_info entry in the table of chips that describes this device
* @bops bus operations (SPI or parallel)
- * @range voltage range selection, selects which scale to apply
+ * @chan_scales scale configuration for channels
* @oversampling oversampling selection
+ * @cnvst_pwm pointer to the PWM device connected to the cnvst pin
* @base_address address from where to read data in parallel operation
* @sw_mode_en software mode enabled
- * @scale_avail pointer to the array which stores the available scales
- * @num_scales number of elements stored in the scale_avail array
* @oversampling_avail pointer to the array which stores the available
* oversampling ratios.
* @num_os_ratios number of elements stored in oversampling_avail array
@@ -92,14 +149,14 @@ struct ad7606_state {
struct device *dev;
const struct ad7606_chip_info *chip_info;
const struct ad7606_bus_ops *bops;
- unsigned int range[16];
+ struct ad7606_chan_scale chan_scales[AD760X_MAX_CHANNELS];
unsigned int oversampling;
+ struct pwm_device *cnvst_pwm;
void __iomem *base_address;
bool sw_mode_en;
- const unsigned int *scale_avail;
- unsigned int num_scales;
const unsigned int *oversampling_avail;
unsigned int num_os_ratios;
+ struct iio_backend *back;
int (*write_scale)(struct iio_dev *indio_dev, int ch, int val);
int (*write_os)(struct iio_dev *indio_dev, int val);
@@ -116,24 +173,33 @@ struct ad7606_state {
/*
* DMA (thus cache coherency maintenance) may require the
* transfer buffers to live in their own cache lines.
- * 16 * 16-bit samples + 64-bit timestamp
+ * 16 * 16-bit samples + 64-bit timestamp - for AD7616
+ * 8 * 32-bit samples + 64-bit timestamp - for AD7616C-18 (and similar)
*/
- unsigned short data[20] __aligned(IIO_DMA_MINALIGN);
+ union {
+ u16 buf16[20];
+ u32 buf32[10];
+ } data __aligned(IIO_DMA_MINALIGN);
__be16 d16[2];
};
/**
* struct ad7606_bus_ops - driver bus operations
+ * @iio_backend_config function pointer for configuring the iio_backend for
+ * the compatibles that use it
* @read_block function pointer for reading blocks of data
* @sw_mode_config: pointer to a function which configured the device
* for software mode
* @reg_read function pointer for reading spi register
* @reg_write function pointer for writing spi register
* @write_mask function pointer for write spi register with mask
+ * @update_scan_mode function pointer for handling the calls to iio_info's update_scan
+ * mode when enabling/disabling channels.
* @rd_wr_cmd pointer to the function which calculates the spi address
*/
struct ad7606_bus_ops {
/* more methods added in future? */
+ int (*iio_backend_config)(struct device *dev, struct iio_dev *indio_dev);
int (*read_block)(struct device *dev, int num, void *data);
int (*sw_mode_config)(struct iio_dev *indio_dev);
int (*reg_read)(struct ad7606_state *st, unsigned int addr);
@@ -144,23 +210,37 @@ struct ad7606_bus_ops {
unsigned int addr,
unsigned long mask,
unsigned int val);
+ int (*update_scan_mode)(struct iio_dev *indio_dev, const unsigned long *scan_mask);
u16 (*rd_wr_cmd)(int addr, char isWriteOp);
};
+/**
+ * struct ad7606_bus_info - agregate ad7606_chip_info and ad7606_bus_ops
+ * @chip_info entry in the table of chips that describes this device
+ * @bops bus operations (SPI or parallel)
+ */
+struct ad7606_bus_info {
+ const struct ad7606_chip_info *chip_info;
+ const struct ad7606_bus_ops *bops;
+};
+
int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
- const char *name, unsigned int id,
+ const struct ad7606_chip_info *info,
const struct ad7606_bus_ops *bops);
int ad7606_reset(struct ad7606_state *st);
-enum ad7606_supported_device_ids {
- ID_AD7605_4,
- ID_AD7606_8,
- ID_AD7606_6,
- ID_AD7606_4,
- ID_AD7606B,
- ID_AD7616,
-};
+extern const struct ad7606_chip_info ad7605_4_info;
+extern const struct ad7606_chip_info ad7606_8_info;
+extern const struct ad7606_chip_info ad7606_6_info;
+extern const struct ad7606_chip_info ad7606_4_info;
+extern const struct ad7606_chip_info ad7606b_info;
+extern const struct ad7606_chip_info ad7606c_16_info;
+extern const struct ad7606_chip_info ad7606c_18_info;
+extern const struct ad7606_chip_info ad7607_info;
+extern const struct ad7606_chip_info ad7608_info;
+extern const struct ad7606_chip_info ad7609_info;
+extern const struct ad7606_chip_info ad7616_info;
#ifdef CONFIG_PM_SLEEP
extern const struct dev_pm_ops ad7606_pm_ops;
diff --git a/drivers/iio/adc/ad7606_par.c b/drivers/iio/adc/ad7606_par.c
index 02d8c309304e..a25182a3daa7 100644
--- a/drivers/iio/adc/ad7606_par.c
+++ b/drivers/iio/adc/ad7606_par.c
@@ -2,20 +2,95 @@
/*
* AD7606 Parallel Interface ADC driver
*
- * Copyright 2011 Analog Devices Inc.
+ * Copyright 2011 - 2024 Analog Devices Inc.
+ * Copyright 2024 BayLibre SAS.
*/
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/io.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/types.h>
-#include <linux/err.h>
-#include <linux/io.h>
+#include <linux/iio/backend.h>
#include <linux/iio/iio.h>
+
#include "ad7606.h"
+static const struct iio_chan_spec ad7606b_bi_channels[] = {
+ AD7606_BI_CHANNEL(0),
+ AD7606_BI_CHANNEL(1),
+ AD7606_BI_CHANNEL(2),
+ AD7606_BI_CHANNEL(3),
+ AD7606_BI_CHANNEL(4),
+ AD7606_BI_CHANNEL(5),
+ AD7606_BI_CHANNEL(6),
+ AD7606_BI_CHANNEL(7),
+};
+
+static int ad7606_bi_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *scan_mask)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int c, ret;
+
+ for (c = 0; c < indio_dev->num_channels; c++) {
+ if (test_bit(c, scan_mask))
+ ret = iio_backend_chan_enable(st->back, c);
+ else
+ ret = iio_backend_chan_disable(st->back, c);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ad7606_bi_setup_iio_backend(struct device *dev, struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int ret, c;
+ struct iio_backend_data_fmt data = {
+ .sign_extend = true,
+ .enable = true,
+ };
+
+ st->back = devm_iio_backend_get(dev, NULL);
+ if (IS_ERR(st->back))
+ return PTR_ERR(st->back);
+
+ /* If the device is iio_backend powered the PWM is mandatory */
+ if (!st->cnvst_pwm)
+ return dev_err_probe(st->dev, -EINVAL,
+ "A PWM is mandatory when using backend.\n");
+
+ ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_backend_enable(dev, st->back);
+ if (ret)
+ return ret;
+
+ for (c = 0; c < indio_dev->num_channels; c++) {
+ ret = iio_backend_data_format_set(st->back, c, &data);
+ if (ret)
+ return ret;
+ }
+
+ indio_dev->channels = ad7606b_bi_channels;
+ indio_dev->num_channels = 8;
+
+ return 0;
+}
+
+static const struct ad7606_bus_ops ad7606_bi_bops = {
+ .iio_backend_config = ad7606_bi_setup_iio_backend,
+ .update_scan_mode = ad7606_bi_update_scan_mode,
+};
+
static int ad7606_par16_read_block(struct device *dev,
int count, void *buf)
{
@@ -89,12 +164,32 @@ static const struct ad7606_bus_ops ad7606_par8_bops = {
static int ad7606_par_probe(struct platform_device *pdev)
{
- const struct platform_device_id *id = platform_get_device_id(pdev);
+ const struct ad7606_chip_info *chip_info;
+ const struct platform_device_id *id;
struct resource *res;
void __iomem *addr;
resource_size_t remap_size;
int irq;
+ /*
+ * If a firmware node is available (ACPI or DT), platform_device_id is null
+ * and we must use get_match_data.
+ */
+ if (dev_fwnode(&pdev->dev)) {
+ chip_info = device_get_match_data(&pdev->dev);
+ if (device_property_present(&pdev->dev, "io-backends"))
+ /*
+ * If a backend is available ,call the core probe with backend
+ * bops, otherwise use the former bops.
+ */
+ return ad7606_probe(&pdev->dev, 0, NULL,
+ chip_info,
+ &ad7606_bi_bops);
+ } else {
+ id = platform_get_device_id(pdev);
+ chip_info = (const struct ad7606_chip_info *)id->driver_data;
+ }
+
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
@@ -105,26 +200,33 @@ static int ad7606_par_probe(struct platform_device *pdev)
remap_size = resource_size(res);
- return ad7606_probe(&pdev->dev, irq, addr,
- id->name, id->driver_data,
+ return ad7606_probe(&pdev->dev, irq, addr, chip_info,
remap_size > 1 ? &ad7606_par16_bops :
&ad7606_par8_bops);
}
static const struct platform_device_id ad7606_driver_ids[] = {
- { .name = "ad7605-4", .driver_data = ID_AD7605_4, },
- { .name = "ad7606-4", .driver_data = ID_AD7606_4, },
- { .name = "ad7606-6", .driver_data = ID_AD7606_6, },
- { .name = "ad7606-8", .driver_data = ID_AD7606_8, },
+ { .name = "ad7605-4", .driver_data = (kernel_ulong_t)&ad7605_4_info, },
+ { .name = "ad7606-4", .driver_data = (kernel_ulong_t)&ad7606_4_info, },
+ { .name = "ad7606-6", .driver_data = (kernel_ulong_t)&ad7606_6_info, },
+ { .name = "ad7606-8", .driver_data = (kernel_ulong_t)&ad7606_8_info, },
+ { .name = "ad7606b", .driver_data = (kernel_ulong_t)&ad7606b_info, },
+ { .name = "ad7607", .driver_data = (kernel_ulong_t)&ad7607_info, },
+ { .name = "ad7608", .driver_data = (kernel_ulong_t)&ad7608_info, },
+ { .name = "ad7609", .driver_data = (kernel_ulong_t)&ad7609_info, },
{ }
};
MODULE_DEVICE_TABLE(platform, ad7606_driver_ids);
static const struct of_device_id ad7606_of_match[] = {
- { .compatible = "adi,ad7605-4" },
- { .compatible = "adi,ad7606-4" },
- { .compatible = "adi,ad7606-6" },
- { .compatible = "adi,ad7606-8" },
+ { .compatible = "adi,ad7605-4", .data = &ad7605_4_info },
+ { .compatible = "adi,ad7606-4", .data = &ad7606_4_info },
+ { .compatible = "adi,ad7606-6", .data = &ad7606_6_info },
+ { .compatible = "adi,ad7606-8", .data = &ad7606_8_info },
+ { .compatible = "adi,ad7606b", .data = &ad7606b_info },
+ { .compatible = "adi,ad7607", .data = &ad7607_info },
+ { .compatible = "adi,ad7608", .data = &ad7608_info },
+ { .compatible = "adi,ad7609", .data = &ad7609_info },
{ }
};
MODULE_DEVICE_TABLE(of, ad7606_of_match);
@@ -144,3 +246,4 @@ MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7606 ADC");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(IIO_AD7606);
+MODULE_IMPORT_NS(IIO_BACKEND);
diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c
index 62ec12195307..0662300cde8d 100644
--- a/drivers/iio/adc/ad7606_spi.c
+++ b/drivers/iio/adc/ad7606_spi.c
@@ -5,10 +5,10 @@
* Copyright 2011 Analog Devices Inc.
*/
+#include <linux/err.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/types.h>
-#include <linux/err.h>
#include <linux/iio/iio.h>
#include "ad7606.h"
@@ -67,14 +67,26 @@ static const struct iio_chan_spec ad7616_sw_channels[] = {
static const struct iio_chan_spec ad7606b_sw_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(8),
- AD7616_CHANNEL(0),
- AD7616_CHANNEL(1),
- AD7616_CHANNEL(2),
- AD7616_CHANNEL(3),
- AD7616_CHANNEL(4),
- AD7616_CHANNEL(5),
- AD7616_CHANNEL(6),
- AD7616_CHANNEL(7),
+ AD7606_SW_CHANNEL(0, 16),
+ AD7606_SW_CHANNEL(1, 16),
+ AD7606_SW_CHANNEL(2, 16),
+ AD7606_SW_CHANNEL(3, 16),
+ AD7606_SW_CHANNEL(4, 16),
+ AD7606_SW_CHANNEL(5, 16),
+ AD7606_SW_CHANNEL(6, 16),
+ AD7606_SW_CHANNEL(7, 16),
+};
+
+static const struct iio_chan_spec ad7606c_18_sw_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_SW_CHANNEL(0, 18),
+ AD7606_SW_CHANNEL(1, 18),
+ AD7606_SW_CHANNEL(2, 18),
+ AD7606_SW_CHANNEL(3, 18),
+ AD7606_SW_CHANNEL(4, 18),
+ AD7606_SW_CHANNEL(5, 18),
+ AD7606_SW_CHANNEL(6, 18),
+ AD7606_SW_CHANNEL(7, 18),
};
static const unsigned int ad7606B_oversampling_avail[9] = {
@@ -120,6 +132,32 @@ static int ad7606_spi_read_block(struct device *dev,
return 0;
}
+static int ad7606_spi_read_block14to16(struct device *dev,
+ int count, void *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct spi_transfer xfer = {
+ .bits_per_word = 14,
+ .len = count * sizeof(u16),
+ .rx_buf = buf,
+ };
+
+ return spi_sync_transfer(spi, &xfer, 1);
+}
+
+static int ad7606_spi_read_block18to32(struct device *dev,
+ int count, void *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct spi_transfer xfer = {
+ .bits_per_word = 18,
+ .len = count * sizeof(u32),
+ .rx_buf = buf,
+ };
+
+ return spi_sync_transfer(spi, &xfer, 1);
+}
+
static int ad7606_spi_reg_read(struct ad7606_state *st, unsigned int addr)
{
struct spi_device *spi = to_spi_device(st->dev);
@@ -283,10 +321,31 @@ static int ad7606B_sw_mode_config(struct iio_dev *indio_dev)
return 0;
}
+static int ad7606c_18_sw_mode_config(struct iio_dev *indio_dev)
+{
+ int ret;
+
+ ret = ad7606B_sw_mode_config(indio_dev);
+ if (ret)
+ return ret;
+
+ indio_dev->channels = ad7606c_18_sw_channels;
+
+ return 0;
+}
+
static const struct ad7606_bus_ops ad7606_spi_bops = {
.read_block = ad7606_spi_read_block,
};
+static const struct ad7606_bus_ops ad7607_spi_bops = {
+ .read_block = ad7606_spi_read_block14to16,
+};
+
+static const struct ad7606_bus_ops ad7608_spi_bops = {
+ .read_block = ad7606_spi_read_block18to32,
+};
+
static const struct ad7606_bus_ops ad7616_spi_bops = {
.read_block = ad7606_spi_read_block,
.reg_read = ad7606_spi_reg_read,
@@ -296,7 +355,7 @@ static const struct ad7606_bus_ops ad7616_spi_bops = {
.sw_mode_config = ad7616_sw_mode_config,
};
-static const struct ad7606_bus_ops ad7606B_spi_bops = {
+static const struct ad7606_bus_ops ad7606b_spi_bops = {
.read_block = ad7606_spi_read_block,
.reg_read = ad7606_spi_reg_read,
.reg_write = ad7606_spi_reg_write,
@@ -305,46 +364,106 @@ static const struct ad7606_bus_ops ad7606B_spi_bops = {
.sw_mode_config = ad7606B_sw_mode_config,
};
+static const struct ad7606_bus_ops ad7606c_18_spi_bops = {
+ .read_block = ad7606_spi_read_block18to32,
+ .reg_read = ad7606_spi_reg_read,
+ .reg_write = ad7606_spi_reg_write,
+ .write_mask = ad7606_spi_write_mask,
+ .rd_wr_cmd = ad7606B_spi_rd_wr_cmd,
+ .sw_mode_config = ad7606c_18_sw_mode_config,
+};
+
+static const struct ad7606_bus_info ad7605_4_bus_info = {
+ .chip_info = &ad7605_4_info,
+ .bops = &ad7606_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606_8_bus_info = {
+ .chip_info = &ad7606_8_info,
+ .bops = &ad7606_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606_6_bus_info = {
+ .chip_info = &ad7606_6_info,
+ .bops = &ad7606_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606_4_bus_info = {
+ .chip_info = &ad7606_4_info,
+ .bops = &ad7606_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606b_bus_info = {
+ .chip_info = &ad7606b_info,
+ .bops = &ad7606b_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606c_16_bus_info = {
+ .chip_info = &ad7606c_16_info,
+ .bops = &ad7606b_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606c_18_bus_info = {
+ .chip_info = &ad7606c_18_info,
+ .bops = &ad7606c_18_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7607_bus_info = {
+ .chip_info = &ad7607_info,
+ .bops = &ad7607_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7608_bus_info = {
+ .chip_info = &ad7608_info,
+ .bops = &ad7608_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7609_bus_info = {
+ .chip_info = &ad7609_info,
+ .bops = &ad7608_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7616_bus_info = {
+ .chip_info = &ad7616_info,
+ .bops = &ad7616_spi_bops,
+};
+
static int ad7606_spi_probe(struct spi_device *spi)
{
- const struct spi_device_id *id = spi_get_device_id(spi);
- const struct ad7606_bus_ops *bops;
-
- switch (id->driver_data) {
- case ID_AD7616:
- bops = &ad7616_spi_bops;
- break;
- case ID_AD7606B:
- bops = &ad7606B_spi_bops;
- break;
- default:
- bops = &ad7606_spi_bops;
- break;
- }
+ const struct ad7606_bus_info *bus_info = spi_get_device_match_data(spi);
return ad7606_probe(&spi->dev, spi->irq, NULL,
- id->name, id->driver_data,
- bops);
+ bus_info->chip_info, bus_info->bops);
}
static const struct spi_device_id ad7606_id_table[] = {
- { "ad7605-4", ID_AD7605_4 },
- { "ad7606-4", ID_AD7606_4 },
- { "ad7606-6", ID_AD7606_6 },
- { "ad7606-8", ID_AD7606_8 },
- { "ad7606b", ID_AD7606B },
- { "ad7616", ID_AD7616 },
+ { "ad7605-4", (kernel_ulong_t)&ad7605_4_bus_info },
+ { "ad7606-4", (kernel_ulong_t)&ad7606_4_bus_info },
+ { "ad7606-6", (kernel_ulong_t)&ad7606_6_bus_info },
+ { "ad7606-8", (kernel_ulong_t)&ad7606_8_bus_info },
+ { "ad7606b", (kernel_ulong_t)&ad7606b_bus_info },
+ { "ad7606c-16", (kernel_ulong_t)&ad7606c_16_bus_info },
+ { "ad7606c-18", (kernel_ulong_t)&ad7606c_18_bus_info },
+ { "ad7607", (kernel_ulong_t)&ad7607_bus_info },
+ { "ad7608", (kernel_ulong_t)&ad7608_bus_info },
+ { "ad7609", (kernel_ulong_t)&ad7609_bus_info },
+ { "ad7616", (kernel_ulong_t)&ad7616_bus_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ad7606_id_table);
static const struct of_device_id ad7606_of_match[] = {
- { .compatible = "adi,ad7605-4" },
- { .compatible = "adi,ad7606-4" },
- { .compatible = "adi,ad7606-6" },
- { .compatible = "adi,ad7606-8" },
- { .compatible = "adi,ad7606b" },
- { .compatible = "adi,ad7616" },
+ { .compatible = "adi,ad7605-4", .data = &ad7605_4_bus_info },
+ { .compatible = "adi,ad7606-4", .data = &ad7606_4_bus_info },
+ { .compatible = "adi,ad7606-6", .data = &ad7606_6_bus_info },
+ { .compatible = "adi,ad7606-8", .data = &ad7606_8_bus_info },
+ { .compatible = "adi,ad7606b", .data = &ad7606b_bus_info },
+ { .compatible = "adi,ad7606c-16", .data = &ad7606c_16_bus_info },
+ { .compatible = "adi,ad7606c-18", .data = &ad7606c_18_bus_info },
+ { .compatible = "adi,ad7607", .data = &ad7607_bus_info },
+ { .compatible = "adi,ad7608", .data = &ad7608_bus_info },
+ { .compatible = "adi,ad7609", .data = &ad7609_bus_info },
+ { .compatible = "adi,ad7616", .data = &ad7616_bus_info },
{ }
};
MODULE_DEVICE_TABLE(of, ad7606_of_match);
diff --git a/drivers/iio/adc/ad7625.c b/drivers/iio/adc/ad7625.c
new file mode 100644
index 000000000000..ddd1e4a26429
--- /dev/null
+++ b/drivers/iio/adc/ad7625.c
@@ -0,0 +1,684 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Analog Devices Inc. AD7625 ADC driver
+ *
+ * Copyright 2024 Analog Devices Inc.
+ * Copyright 2024 BayLibre, SAS
+ *
+ * Note that this driver requires the AXI ADC IP block configured for
+ * LVDS to function. See Documentation/iio/ad7625.rst for more
+ * information.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/backend.h>
+#include <linux/iio/iio.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/units.h>
+
+#define AD7625_INTERNAL_REF_MV 4096
+#define AD7960_MAX_NBW_FREQ (2 * MEGA)
+
+struct ad7625_timing_spec {
+ /* Max conversion high time (t_{CNVH}). */
+ unsigned int conv_high_ns;
+ /* Max conversion to MSB delay (t_{MSB}). */
+ unsigned int conv_msb_ns;
+};
+
+struct ad7625_chip_info {
+ const char *name;
+ const unsigned int max_sample_freq_hz;
+ const struct ad7625_timing_spec *timing_spec;
+ const struct iio_chan_spec chan_spec;
+ const bool has_power_down_state;
+ const bool has_bandwidth_control;
+ const bool has_internal_vref;
+};
+
+/* AD7625_CHAN_SPEC - Define a chan spec structure for a specific chip */
+#define AD7625_CHAN_SPEC(_bits) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .differential = 1, \
+ .channel = 0, \
+ .channel2 = 1, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = 0, \
+ .scan_type.sign = 's', \
+ .scan_type.storagebits = (_bits) > 16 ? 32 : 16, \
+ .scan_type.realbits = (_bits), \
+}
+
+struct ad7625_state {
+ const struct ad7625_chip_info *info;
+ struct iio_backend *back;
+ /* rate of the clock gated by the "clk_gate" PWM */
+ u32 ref_clk_rate_hz;
+ /* PWM burst signal for transferring acquired data to the host */
+ struct pwm_device *clk_gate_pwm;
+ /*
+ * PWM control signal for initiating data conversion. Analog
+ * inputs are sampled beginning on this signal's rising edge.
+ */
+ struct pwm_device *cnv_pwm;
+ /*
+ * Waveforms containing the last-requested and rounded
+ * properties for the clk_gate and cnv PWMs
+ */
+ struct pwm_waveform clk_gate_wf;
+ struct pwm_waveform cnv_wf;
+ unsigned int vref_mv;
+ u32 sampling_freq_hz;
+ /*
+ * Optional GPIOs for controlling device state. EN0 and EN1
+ * determine voltage reference configuration and on/off state.
+ * EN2 controls the device -3dB bandwidth (and by extension, max
+ * sample rate). EN3 controls the VCM reference output. EN2 and
+ * EN3 are only present for the AD796x devices.
+ */
+ struct gpio_desc *en_gpios[4];
+ bool can_power_down;
+ bool can_refin;
+ bool can_ref_4v096;
+ /*
+ * Indicate whether the bandwidth can be narrow (9MHz).
+ * When true, device sample rate must also be < 2MSPS.
+ */
+ bool can_narrow_bandwidth;
+ /* Indicate whether the bandwidth can be wide (28MHz). */
+ bool can_wide_bandwidth;
+ bool can_ref_5v;
+ bool can_snooze;
+ bool can_test_pattern;
+ /* Indicate whether there is a REFIN supply connected */
+ bool have_refin;
+};
+
+static const struct ad7625_timing_spec ad7625_timing_spec = {
+ .conv_high_ns = 40,
+ .conv_msb_ns = 145,
+};
+
+static const struct ad7625_timing_spec ad7626_timing_spec = {
+ .conv_high_ns = 40,
+ .conv_msb_ns = 80,
+};
+
+/*
+ * conv_msb_ns is set to 0 instead of the datasheet maximum of 200ns to
+ * avoid exceeding the minimum conversion time, i.e. it is effectively
+ * modulo 200 and offset by a full period. Values greater than or equal
+ * to the period would be rejected by the PWM API.
+ */
+static const struct ad7625_timing_spec ad7960_timing_spec = {
+ .conv_high_ns = 80,
+ .conv_msb_ns = 0,
+};
+
+static const struct ad7625_chip_info ad7625_chip_info = {
+ .name = "ad7625",
+ .max_sample_freq_hz = 6 * MEGA,
+ .timing_spec = &ad7625_timing_spec,
+ .chan_spec = AD7625_CHAN_SPEC(16),
+ .has_power_down_state = false,
+ .has_bandwidth_control = false,
+ .has_internal_vref = true,
+};
+
+static const struct ad7625_chip_info ad7626_chip_info = {
+ .name = "ad7626",
+ .max_sample_freq_hz = 10 * MEGA,
+ .timing_spec = &ad7626_timing_spec,
+ .chan_spec = AD7625_CHAN_SPEC(16),
+ .has_power_down_state = true,
+ .has_bandwidth_control = false,
+ .has_internal_vref = true,
+};
+
+static const struct ad7625_chip_info ad7960_chip_info = {
+ .name = "ad7960",
+ .max_sample_freq_hz = 5 * MEGA,
+ .timing_spec = &ad7960_timing_spec,
+ .chan_spec = AD7625_CHAN_SPEC(18),
+ .has_power_down_state = true,
+ .has_bandwidth_control = true,
+ .has_internal_vref = false,
+};
+
+static const struct ad7625_chip_info ad7961_chip_info = {
+ .name = "ad7961",
+ .max_sample_freq_hz = 5 * MEGA,
+ .timing_spec = &ad7960_timing_spec,
+ .chan_spec = AD7625_CHAN_SPEC(16),
+ .has_power_down_state = true,
+ .has_bandwidth_control = true,
+ .has_internal_vref = false,
+};
+
+enum ad7960_mode {
+ AD7960_MODE_POWER_DOWN,
+ AD7960_MODE_SNOOZE,
+ AD7960_MODE_NARROW_BANDWIDTH,
+ AD7960_MODE_WIDE_BANDWIDTH,
+ AD7960_MODE_TEST_PATTERN,
+};
+
+static int ad7625_set_sampling_freq(struct ad7625_state *st, u32 freq)
+{
+ u32 target;
+ struct pwm_waveform clk_gate_wf = { }, cnv_wf = { };
+ int ret;
+
+ target = DIV_ROUND_UP(NSEC_PER_SEC, freq);
+ cnv_wf.period_length_ns = clamp(target, 100, 10 * KILO);
+
+ /*
+ * Use the maximum conversion time t_CNVH from the datasheet as
+ * the duty_cycle for ref_clk, cnv, and clk_gate
+ */
+ cnv_wf.duty_length_ns = st->info->timing_spec->conv_high_ns;
+
+ ret = pwm_round_waveform_might_sleep(st->cnv_pwm, &cnv_wf);
+ if (ret)
+ return ret;
+
+ /*
+ * Set up the burst signal for transferring data. period and
+ * offset should mirror the CNV signal
+ */
+ clk_gate_wf.period_length_ns = cnv_wf.period_length_ns;
+
+ clk_gate_wf.duty_length_ns = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC *
+ st->info->chan_spec.scan_type.realbits,
+ st->ref_clk_rate_hz);
+
+ /* max t_MSB from datasheet */
+ clk_gate_wf.duty_offset_ns = st->info->timing_spec->conv_msb_ns;
+
+ ret = pwm_round_waveform_might_sleep(st->clk_gate_pwm, &clk_gate_wf);
+ if (ret)
+ return ret;
+
+ st->cnv_wf = cnv_wf;
+ st->clk_gate_wf = clk_gate_wf;
+
+ /* TODO: Add a rounding API for PWMs that can simplify this */
+ target = DIV_ROUND_CLOSEST(st->ref_clk_rate_hz, freq);
+ st->sampling_freq_hz = DIV_ROUND_CLOSEST(st->ref_clk_rate_hz,
+ target);
+
+ return 0;
+}
+
+static int ad7625_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long info)
+{
+ struct ad7625_state *st = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = st->sampling_freq_hz;
+
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ *val = st->vref_mv;
+ *val2 = chan->scan_type.realbits - 1;
+
+ return IIO_VAL_FRACTIONAL_LOG2;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7625_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long info)
+{
+ struct ad7625_state *st = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
+ return ad7625_set_sampling_freq(st, val);
+ unreachable();
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7625_parse_mode(struct device *dev, struct ad7625_state *st,
+ int num_gpios)
+{
+ bool en_always_on[4], en_always_off[4];
+ bool en_may_be_on[4], en_may_be_off[4];
+ char en_gpio_buf[4];
+ char always_on_buf[18];
+ int i;
+
+ for (i = 0; i < num_gpios; i++) {
+ snprintf(en_gpio_buf, sizeof(en_gpio_buf), "en%d", i);
+ snprintf(always_on_buf, sizeof(always_on_buf),
+ "adi,en%d-always-on", i);
+ /* Set the device to 0b0000 (power-down mode) by default */
+ st->en_gpios[i] = devm_gpiod_get_optional(dev, en_gpio_buf,
+ GPIOD_OUT_LOW);
+ if (IS_ERR(st->en_gpios[i]))
+ return dev_err_probe(dev, PTR_ERR(st->en_gpios[i]),
+ "failed to get EN%d GPIO\n", i);
+
+ en_always_on[i] = device_property_read_bool(dev, always_on_buf);
+ if (st->en_gpios[i] && en_always_on[i])
+ return dev_err_probe(dev, -EINVAL,
+ "cannot have adi,en%d-always-on and en%d-gpios\n", i, i);
+
+ en_may_be_off[i] = !en_always_on[i];
+ en_may_be_on[i] = en_always_on[i] || st->en_gpios[i];
+ en_always_off[i] = !en_always_on[i] && !st->en_gpios[i];
+ }
+
+ /*
+ * Power down is mode 0bXX00, but not all devices have a valid
+ * power down state.
+ */
+ st->can_power_down = en_may_be_off[1] && en_may_be_off[0] &&
+ st->info->has_power_down_state;
+ /*
+ * The REFIN pin can take a 1.2V (AD762x) or 2.048V (AD796x)
+ * external reference when the mode is 0bXX01.
+ */
+ st->can_refin = en_may_be_off[1] && en_may_be_on[0];
+ /* 4.096V can be applied to REF when the EN mode is 0bXX10. */
+ st->can_ref_4v096 = en_may_be_on[1] && en_may_be_off[0];
+
+ /* Avoid AD796x-specific setup if the part is an AD762x */
+ if (num_gpios == 2)
+ return 0;
+
+ /* mode 0b1100 (AD796x) is invalid */
+ if (en_always_on[3] && en_always_on[2] &&
+ en_always_off[1] && en_always_off[0])
+ return dev_err_probe(dev, -EINVAL,
+ "EN GPIOs set to invalid mode 0b1100\n");
+ /*
+ * 5V can be applied to the AD796x REF pin when the EN mode is
+ * the same (0bX001 or 0bX101) as for can_refin, and REFIN is
+ * 0V.
+ */
+ st->can_ref_5v = st->can_refin;
+ /*
+ * Bandwidth (AD796x) is controlled solely by EN2. If it's
+ * specified and not hard-wired, then we can configure it to
+ * change the bandwidth between 28MHz and 9MHz.
+ */
+ st->can_narrow_bandwidth = en_may_be_on[2];
+ /* Wide bandwidth mode is possible if EN2 can be 0. */
+ st->can_wide_bandwidth = en_may_be_off[2];
+ /* Snooze mode (AD796x) is 0bXX11 when REFIN = 0V. */
+ st->can_snooze = en_may_be_on[1] && en_may_be_on[0];
+ /* Test pattern mode (AD796x) is 0b0100. */
+ st->can_test_pattern = en_may_be_off[3] && en_may_be_on[2] &&
+ en_may_be_off[1] && en_may_be_off[0];
+
+ return 0;
+}
+
+/* Set EN1 and EN0 based on reference voltage source */
+static void ad7625_set_en_gpios_for_vref(struct ad7625_state *st,
+ bool have_refin, int ref_mv)
+{
+ if (have_refin || ref_mv == 5000) {
+ gpiod_set_value_cansleep(st->en_gpios[1], 0);
+ gpiod_set_value_cansleep(st->en_gpios[0], 1);
+ } else if (ref_mv == 4096) {
+ gpiod_set_value_cansleep(st->en_gpios[1], 1);
+ gpiod_set_value_cansleep(st->en_gpios[0], 0);
+ } else {
+ /*
+ * Unreachable by AD796x, since the driver will error if
+ * neither REF nor REFIN is provided
+ */
+ gpiod_set_value_cansleep(st->en_gpios[1], 1);
+ gpiod_set_value_cansleep(st->en_gpios[0], 1);
+ }
+}
+
+static int ad7960_set_mode(struct ad7625_state *st, enum ad7960_mode mode,
+ bool have_refin, int ref_mv)
+{
+ switch (mode) {
+ case AD7960_MODE_POWER_DOWN:
+ if (!st->can_power_down)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[2], 0);
+ gpiod_set_value_cansleep(st->en_gpios[1], 0);
+ gpiod_set_value_cansleep(st->en_gpios[0], 0);
+
+ return 0;
+
+ case AD7960_MODE_SNOOZE:
+ if (!st->can_snooze)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[1], 1);
+ gpiod_set_value_cansleep(st->en_gpios[0], 1);
+
+ return 0;
+
+ case AD7960_MODE_NARROW_BANDWIDTH:
+ if (!st->can_narrow_bandwidth)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[2], 1);
+ ad7625_set_en_gpios_for_vref(st, have_refin, ref_mv);
+
+ return 0;
+
+ case AD7960_MODE_WIDE_BANDWIDTH:
+ if (!st->can_wide_bandwidth)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[2], 0);
+ ad7625_set_en_gpios_for_vref(st, have_refin, ref_mv);
+
+ return 0;
+
+ case AD7960_MODE_TEST_PATTERN:
+ if (!st->can_test_pattern)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[3], 0);
+ gpiod_set_value_cansleep(st->en_gpios[2], 1);
+ gpiod_set_value_cansleep(st->en_gpios[1], 0);
+ gpiod_set_value_cansleep(st->en_gpios[0], 0);
+
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7625_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct ad7625_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = pwm_set_waveform_might_sleep(st->cnv_pwm, &st->cnv_wf, false);
+ if (ret)
+ return ret;
+
+ ret = pwm_set_waveform_might_sleep(st->clk_gate_pwm,
+ &st->clk_gate_wf, false);
+ if (ret) {
+ /* Disable cnv PWM if clk_gate setup failed */
+ pwm_disable(st->cnv_pwm);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ad7625_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad7625_state *st = iio_priv(indio_dev);
+
+ pwm_disable(st->clk_gate_pwm);
+ pwm_disable(st->cnv_pwm);
+
+ return 0;
+}
+
+static const struct iio_info ad7625_info = {
+ .read_raw = ad7625_read_raw,
+ .write_raw = ad7625_write_raw,
+};
+
+static const struct iio_buffer_setup_ops ad7625_buffer_setup_ops = {
+ .preenable = &ad7625_buffer_preenable,
+ .postdisable = &ad7625_buffer_postdisable,
+};
+
+static int devm_ad7625_pwm_get(struct device *dev,
+ struct ad7625_state *st)
+{
+ struct clk *ref_clk;
+ u32 ref_clk_rate_hz;
+
+ st->cnv_pwm = devm_pwm_get(dev, "cnv");
+ if (IS_ERR(st->cnv_pwm))
+ return dev_err_probe(dev, PTR_ERR(st->cnv_pwm),
+ "failed to get cnv pwm\n");
+
+ /* Preemptively disable the PWM in case it was enabled at boot */
+ pwm_disable(st->cnv_pwm);
+
+ st->clk_gate_pwm = devm_pwm_get(dev, "clk_gate");
+ if (IS_ERR(st->clk_gate_pwm))
+ return dev_err_probe(dev, PTR_ERR(st->clk_gate_pwm),
+ "failed to get clk_gate pwm\n");
+
+ /* Preemptively disable the PWM in case it was enabled at boot */
+ pwm_disable(st->clk_gate_pwm);
+
+ ref_clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(ref_clk))
+ return dev_err_probe(dev, PTR_ERR(ref_clk),
+ "failed to get ref_clk");
+
+ ref_clk_rate_hz = clk_get_rate(ref_clk);
+ if (!ref_clk_rate_hz)
+ return dev_err_probe(dev, -EINVAL,
+ "failed to get ref_clk rate");
+
+ st->ref_clk_rate_hz = ref_clk_rate_hz;
+
+ return 0;
+}
+
+/*
+ * There are three required input voltages for each device, plus two
+ * conditionally-optional (depending on part) REF and REFIN voltages
+ * where their validity depends upon the EN pin configuration.
+ *
+ * Power-up info for the device says to bring up vio, then vdd2, then
+ * vdd1, so list them in that order in the regulator_names array.
+ *
+ * The reference voltage source is determined like so:
+ * - internal reference: neither REF or REFIN is connected (invalid for
+ * AD796x)
+ * - internal buffer, external reference: REF not connected, REFIN
+ * connected
+ * - external reference: REF connected, REFIN not connected
+ */
+static int devm_ad7625_regulator_setup(struct device *dev,
+ struct ad7625_state *st)
+{
+ static const char * const regulator_names[] = { "vio", "vdd2", "vdd1" };
+ int ret, ref_mv;
+
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names),
+ regulator_names);
+ if (ret)
+ return ret;
+
+ ret = devm_regulator_get_enable_read_voltage(dev, "ref");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "failed to get REF voltage\n");
+
+ ref_mv = ret == -ENODEV ? 0 : ret / 1000;
+
+ ret = devm_regulator_get_enable_optional(dev, "refin");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "failed to get REFIN voltage\n");
+
+ st->have_refin = ret != -ENODEV;
+
+ if (st->have_refin && !st->can_refin)
+ return dev_err_probe(dev, -EINVAL,
+ "REFIN provided in unsupported mode\n");
+
+ if (!st->info->has_internal_vref && !st->have_refin && !ref_mv)
+ return dev_err_probe(dev, -EINVAL,
+ "Need either REFIN or REF");
+
+ if (st->have_refin && ref_mv)
+ return dev_err_probe(dev, -EINVAL,
+ "cannot have both REFIN and REF supplies\n");
+
+ if (ref_mv == 4096 && !st->can_ref_4v096)
+ return dev_err_probe(dev, -EINVAL,
+ "REF is 4.096V in unsupported mode\n");
+
+ if (ref_mv == 5000 && !st->can_ref_5v)
+ return dev_err_probe(dev, -EINVAL,
+ "REF is 5V in unsupported mode\n");
+
+ st->vref_mv = ref_mv ?: AD7625_INTERNAL_REF_MV;
+
+ return 0;
+}
+
+static int ad7625_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct iio_dev *indio_dev;
+ struct ad7625_state *st;
+ int ret;
+ u32 default_sample_freq;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ st->info = device_get_match_data(dev);
+ if (!st->info)
+ return dev_err_probe(dev, -EINVAL, "no chip info\n");
+
+ if (device_property_read_bool(dev, "adi,no-dco"))
+ return dev_err_probe(dev, -EINVAL,
+ "self-clocked mode not supported\n");
+
+ if (st->info->has_bandwidth_control)
+ ret = ad7625_parse_mode(dev, st, 4);
+ else
+ ret = ad7625_parse_mode(dev, st, 2);
+
+ if (ret)
+ return ret;
+
+ ret = devm_ad7625_regulator_setup(dev, st);
+ if (ret)
+ return ret;
+
+ /* Set the device mode based on detected EN configuration. */
+ if (!st->info->has_bandwidth_control) {
+ ad7625_set_en_gpios_for_vref(st, st->have_refin, st->vref_mv);
+ } else {
+ /*
+ * If neither sampling mode is available, then report an error,
+ * since the other modes are not useful defaults.
+ */
+ if (st->can_wide_bandwidth) {
+ ret = ad7960_set_mode(st, AD7960_MODE_WIDE_BANDWIDTH,
+ st->have_refin, st->vref_mv);
+ } else if (st->can_narrow_bandwidth) {
+ ret = ad7960_set_mode(st, AD7960_MODE_NARROW_BANDWIDTH,
+ st->have_refin, st->vref_mv);
+ } else {
+ return dev_err_probe(dev, -EINVAL,
+ "couldn't set device to wide or narrow bandwidth modes\n");
+ }
+
+ if (ret)
+ return dev_err_probe(dev, -EINVAL,
+ "failed to set EN pins\n");
+ }
+
+ ret = devm_ad7625_pwm_get(dev, st);
+ if (ret)
+ return ret;
+
+ indio_dev->channels = &st->info->chan_spec;
+ indio_dev->num_channels = 1;
+ indio_dev->name = st->info->name;
+ indio_dev->info = &ad7625_info;
+ indio_dev->setup_ops = &ad7625_buffer_setup_ops;
+
+ st->back = devm_iio_backend_get(dev, NULL);
+ if (IS_ERR(st->back))
+ return dev_err_probe(dev, PTR_ERR(st->back),
+ "failed to get IIO backend");
+
+ ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_backend_enable(dev, st->back);
+ if (ret)
+ return ret;
+
+ /*
+ * Set the initial sampling frequency to the maximum, unless the
+ * AD796x device is limited to narrow bandwidth by EN2 == 1, in
+ * which case the sampling frequency should be limited to 2MSPS
+ */
+ default_sample_freq = st->info->max_sample_freq_hz;
+ if (st->info->has_bandwidth_control && !st->can_wide_bandwidth)
+ default_sample_freq = AD7960_MAX_NBW_FREQ;
+
+ ret = ad7625_set_sampling_freq(st, default_sample_freq);
+ if (ret)
+ dev_err_probe(dev, ret,
+ "failed to set valid sampling frequency\n");
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct of_device_id ad7625_of_match[] = {
+ { .compatible = "adi,ad7625", .data = &ad7625_chip_info },
+ { .compatible = "adi,ad7626", .data = &ad7626_chip_info },
+ { .compatible = "adi,ad7960", .data = &ad7960_chip_info },
+ { .compatible = "adi,ad7961", .data = &ad7961_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad7625_of_match);
+
+static const struct platform_device_id ad7625_device_ids[] = {
+ { .name = "ad7625", .driver_data = (kernel_ulong_t)&ad7625_chip_info },
+ { .name = "ad7626", .driver_data = (kernel_ulong_t)&ad7626_chip_info },
+ { .name = "ad7960", .driver_data = (kernel_ulong_t)&ad7960_chip_info },
+ { .name = "ad7961", .driver_data = (kernel_ulong_t)&ad7961_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, ad7625_device_ids);
+
+static struct platform_driver ad7625_driver = {
+ .probe = ad7625_probe,
+ .driver = {
+ .name = "ad7625",
+ .of_match_table = ad7625_of_match,
+ },
+ .id_table = ad7625_device_ids,
+};
+module_platform_driver(ad7625_driver);
+
+MODULE_AUTHOR("Trevor Gamblin <tgamblin@baylibre.com>");
+MODULE_DESCRIPTION("Analog Devices AD7625 ADC");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_IMPORT_NS(IIO_BACKEND);
diff --git a/drivers/iio/adc/ad7779.c b/drivers/iio/adc/ad7779.c
new file mode 100644
index 000000000000..2537dab69a35
--- /dev/null
+++ b/drivers/iio/adc/ad7779.c
@@ -0,0 +1,914 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * AD7770, AD7771, AD7779 ADC
+ *
+ * Copyright 2023-2024 Analog Devices Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitmap.h>
+#include <linux/clk.h>
+#include <linux/crc8.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/unaligned.h>
+#include <linux/units.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+
+#define AD7779_SPI_READ_CMD BIT(7)
+
+#define AD7779_DISABLE_SD BIT(7)
+
+#define AD7779_REG_CH_DISABLE 0x08
+#define AD7779_REG_CH_SYNC_OFFSET(ch) (0x09 + (ch))
+#define AD7779_REG_CH_CONFIG(ch) (0x00 + (ch))
+#define AD7779_REG_GENERAL_USER_CONFIG_1 0x11
+#define AD7779_REG_GENERAL_USER_CONFIG_2 0x12
+#define AD7779_REG_GENERAL_USER_CONFIG_3 0x13
+#define AD7779_REG_DOUT_FORMAT 0x14
+#define AD7779_REG_ADC_MUX_CONFIG 0x15
+#define AD7779_REG_GPIO_CONFIG 0x17
+#define AD7779_REG_BUFFER_CONFIG_1 0x19
+#define AD7779_REG_GLOBAL_MUX_CONFIG 0x16
+#define AD7779_REG_BUFFER_CONFIG_2 0x1A
+#define AD7779_REG_GPIO_DATA 0x18
+#define AD7779_REG_CH_OFFSET_UPPER_BYTE(ch) (0x1C + (ch) * 6)
+#define AD7779_REG_CH_OFFSET_LOWER_BYTE(ch) (0x1E + (ch) * 6)
+#define AD7779_REG_CH_GAIN_UPPER_BYTE(ch) (0x1F + (ch) * 6)
+#define AD7779_REG_CH_OFFSET_MID_BYTE(ch) (0x1D + (ch) * 6)
+#define AD7779_REG_CH_GAIN_MID_BYTE(ch) (0x20 + (ch) * 6)
+#define AD7779_REG_CH_ERR_REG(ch) (0x4C + (ch))
+#define AD7779_REG_CH0_1_SAT_ERR 0x54
+#define AD7779_REG_CH_GAIN_LOWER_BYTE(ch) (0x21 + (ch) * 6)
+#define AD7779_REG_CH2_3_SAT_ERR 0x55
+#define AD7779_REG_CH4_5_SAT_ERR 0x56
+#define AD7779_REG_CH6_7_SAT_ERR 0x57
+#define AD7779_REG_CHX_ERR_REG_EN 0x58
+#define AD7779_REG_GEN_ERR_REG_1 0x59
+#define AD7779_REG_GEN_ERR_REG_1_EN 0x5A
+#define AD7779_REG_GEN_ERR_REG_2 0x5B
+#define AD7779_REG_GEN_ERR_REG_2_EN 0x5C
+#define AD7779_REG_STATUS_REG_1 0x5D
+#define AD7779_REG_STATUS_REG_2 0x5E
+#define AD7779_REG_STATUS_REG_3 0x5F
+#define AD7779_REG_SRC_N_MSB 0x60
+#define AD7779_REG_SRC_N_LSB 0x61
+#define AD7779_REG_SRC_IF_MSB 0x62
+#define AD7779_REG_SRC_IF_LSB 0x63
+#define AD7779_REG_SRC_UPDATE 0x64
+
+#define AD7779_FILTER_MSK BIT(6)
+#define AD7779_MOD_POWERMODE_MSK BIT(6)
+#define AD7779_MOD_PDB_REFOUT_MSK BIT(4)
+#define AD7779_MOD_SPI_EN_MSK BIT(4)
+#define AD7779_USRMOD_INIT_MSK GENMASK(6, 4)
+
+/* AD7779_REG_DOUT_FORMAT */
+#define AD7779_DOUT_FORMAT_MSK GENMASK(7, 6)
+#define AD7779_DOUT_HEADER_FORMAT BIT(5)
+#define AD7779_DCLK_CLK_DIV_MSK GENMASK(3, 1)
+
+#define AD7779_REFMUX_CTRL_MSK GENMASK(7, 6)
+#define AD7779_SPI_CRC_EN_MSK BIT(0)
+
+#define AD7779_MAXCLK_LOWPOWER (4096 * HZ_PER_KHZ)
+#define AD7779_NUM_CHANNELS 8
+#define AD7779_RESET_BUF_SIZE 8
+#define AD7779_CHAN_DATA_SIZE 4
+
+#define AD7779_LOWPOWER_DIV 512
+#define AD7779_HIGHPOWER_DIV 2048
+
+#define AD7779_SINC3_MAXFREQ (16 * HZ_PER_KHZ)
+#define AD7779_SINC5_MAXFREQ (128 * HZ_PER_KHZ)
+
+#define AD7779_DEFAULT_SAMPLING_FREQ (8 * HZ_PER_KHZ)
+#define AD7779_DEFAULT_SAMPLING_2LINE (4 * HZ_PER_KHZ)
+#define AD7779_DEFAULT_SAMPLING_1LINE (2 * HZ_PER_KHZ)
+
+#define AD7779_SPIMODE_MAX_SAMP_FREQ (16 * HZ_PER_KHZ)
+
+#define GAIN_REL 0x555555
+#define AD7779_FREQ_MSB_MSK GENMASK(15, 8)
+#define AD7779_FREQ_LSB_MSK GENMASK(7, 0)
+#define AD7779_UPPER GENMASK(23, 16)
+#define AD7779_MID GENMASK(15, 8)
+#define AD7779_LOWER GENMASK(7, 0)
+
+#define AD7779_REG_MSK GENMASK(6, 0)
+
+#define AD7779_CRC8_POLY 0x07
+DECLARE_CRC8_TABLE(ad7779_crc8_table);
+
+enum ad7779_filter {
+ AD7779_SINC3,
+ AD7779_SINC5,
+};
+
+enum ad7779_variant {
+ ad7770,
+ ad7771,
+ ad7779,
+};
+
+enum ad7779_power_mode {
+ AD7779_LOW_POWER,
+ AD7779_HIGH_POWER,
+};
+
+struct ad7779_chip_info {
+ const char *name;
+ struct iio_chan_spec const *channels;
+};
+
+struct ad7779_state {
+ struct spi_device *spi;
+ const struct ad7779_chip_info *chip_info;
+ struct clk *mclk;
+ struct iio_trigger *trig;
+ struct completion completion;
+ unsigned int sampling_freq;
+ enum ad7779_filter filter_enabled;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ struct {
+ u32 chans[8];
+ aligned_s64 timestamp;
+ } data __aligned(IIO_DMA_MINALIGN);
+ u32 spidata_tx[8];
+ u8 reg_rx_buf[3];
+ u8 reg_tx_buf[3];
+ u8 reset_buf[8];
+};
+
+static const char * const ad7779_filter_type[] = {
+ [AD7779_SINC3] = "sinc3",
+ [AD7779_SINC5] = "sinc5",
+};
+
+static const char * const ad7779_power_supplies[] = {
+ "avdd1", "avdd2", "avdd4",
+};
+
+static int ad7779_spi_read(struct ad7779_state *st, u8 reg, u8 *rbuf)
+{
+ int ret;
+ u8 crc_buf[2];
+ u8 exp_crc;
+ struct spi_transfer t = {
+ .tx_buf = st->reg_tx_buf,
+ .rx_buf = st->reg_rx_buf,
+ };
+
+ st->reg_tx_buf[0] = AD7779_SPI_READ_CMD | FIELD_GET(AD7779_REG_MSK, reg);
+ st->reg_tx_buf[1] = 0;
+
+ if (reg == AD7779_REG_GEN_ERR_REG_1_EN) {
+ t.len = 2;
+ } else {
+ t.len = 3;
+ st->reg_tx_buf[2] = crc8(ad7779_crc8_table, st->reg_tx_buf,
+ t.len - 1, 0);
+ }
+
+ ret = spi_sync_transfer(st->spi, &t, 1);
+ if (ret)
+ return ret;
+
+ crc_buf[0] = AD7779_SPI_READ_CMD | FIELD_GET(AD7779_REG_MSK, reg);
+ crc_buf[1] = st->reg_rx_buf[1];
+ exp_crc = crc8(ad7779_crc8_table, crc_buf, ARRAY_SIZE(crc_buf), 0);
+ if (reg != AD7779_REG_GEN_ERR_REG_1_EN && exp_crc != st->reg_rx_buf[2]) {
+ dev_err(&st->spi->dev, "Bad CRC %x, expected %x",
+ st->reg_rx_buf[2], exp_crc);
+ return -EINVAL;
+ }
+ *rbuf = st->reg_rx_buf[1];
+
+ return 0;
+}
+
+static int ad7779_spi_write(struct ad7779_state *st, u8 reg, u8 val)
+{
+ u8 length = 3;
+
+ st->reg_tx_buf[0] = FIELD_GET(AD7779_REG_MSK, reg);
+ st->reg_tx_buf[1] = val;
+ if (reg == AD7779_REG_GEN_ERR_REG_1_EN)
+ length = 2;
+ else
+ st->reg_tx_buf[2] = crc8(ad7779_crc8_table, st->reg_tx_buf,
+ length - 1, 0);
+
+ return spi_write(st->spi, st->reg_tx_buf, length);
+}
+
+static int ad7779_spi_write_mask(struct ad7779_state *st, u8 reg, u8 mask,
+ u8 val)
+{
+ int ret;
+ u8 regval, data;
+
+ ret = ad7779_spi_read(st, reg, &data);
+ if (ret)
+ return ret;
+
+ regval = (data & ~mask) | (val & mask);
+
+ if (regval == data)
+ return 0;
+
+ return ad7779_spi_write(st, reg, regval);
+}
+
+static int ad7779_reg_access(struct iio_dev *indio_dev,
+ unsigned int reg,
+ unsigned int writeval,
+ unsigned int *readval)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ u8 rval;
+ int ret;
+
+ if (readval) {
+ ret = ad7779_spi_read(st, reg, &rval);
+ *readval = rval;
+ return ret;
+ }
+
+ return ad7779_spi_write(st, reg, writeval);
+}
+
+static int ad7779_set_sampling_frequency(struct ad7779_state *st,
+ unsigned int sampling_freq)
+{
+ int ret;
+ unsigned int dec;
+ unsigned int frac;
+ unsigned int div;
+ unsigned int decimal;
+ unsigned int freq_khz;
+
+ if (st->filter_enabled == AD7779_SINC3 &&
+ sampling_freq > AD7779_SINC3_MAXFREQ)
+ return -EINVAL;
+
+ if (st->filter_enabled == AD7779_SINC5 &&
+ sampling_freq > AD7779_SINC5_MAXFREQ)
+ return -EINVAL;
+
+ if (sampling_freq > AD7779_SPIMODE_MAX_SAMP_FREQ)
+ return -EINVAL;
+
+ div = AD7779_HIGHPOWER_DIV;
+
+ freq_khz = sampling_freq / HZ_PER_KHZ;
+ dec = div / freq_khz;
+ frac = div % freq_khz;
+
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB,
+ FIELD_GET(AD7779_FREQ_MSB_MSK, dec));
+ if (ret)
+ return ret;
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB,
+ FIELD_GET(AD7779_FREQ_LSB_MSK, dec));
+ if (ret)
+ return ret;
+
+ if (frac) {
+ /*
+ * In order to obtain the first three decimals of the decimation
+ * the initial number is multiplied with 10^3 prior to the
+ * division, then the original division result is subtracted and
+ * the number is divided by 10^3.
+ */
+ decimal = ((mult_frac(div, KILO, freq_khz) - dec * KILO) << 16)
+ / KILO;
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB,
+ FIELD_GET(AD7779_FREQ_MSB_MSK, decimal));
+ if (ret)
+ return ret;
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB,
+ FIELD_GET(AD7779_FREQ_LSB_MSK, decimal));
+ if (ret)
+ return ret;
+ } else {
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB,
+ FIELD_GET(AD7779_FREQ_MSB_MSK, 0x0));
+ if (ret)
+ return ret;
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB,
+ FIELD_GET(AD7779_FREQ_LSB_MSK, 0x0));
+ if (ret)
+ return ret;
+ }
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_UPDATE, BIT(0));
+ if (ret)
+ return ret;
+
+ /* SRC update settling time */
+ fsleep(15);
+
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_UPDATE, 0x0);
+ if (ret)
+ return ret;
+
+ /* SRC update settling time */
+ fsleep(15);
+
+ st->sampling_freq = sampling_freq;
+
+ return 0;
+}
+
+static int ad7779_get_filter(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ u8 temp;
+ int ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_GENERAL_USER_CONFIG_2, &temp);
+ if (ret)
+ return ret;
+
+ return FIELD_GET(AD7779_FILTER_MSK, temp);
+}
+
+static int ad7779_set_filter(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ unsigned int mode)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = ad7779_spi_write_mask(st,
+ AD7779_REG_GENERAL_USER_CONFIG_2,
+ AD7779_FILTER_MSK,
+ FIELD_PREP(AD7779_FILTER_MSK, mode));
+ if (ret)
+ return ret;
+
+ ret = ad7779_set_sampling_frequency(st, st->sampling_freq);
+ if (ret)
+ return ret;
+
+ st->filter_enabled = mode;
+
+ return 0;
+}
+
+static int ad7779_get_calibscale(struct ad7779_state *st, int channel)
+{
+ int ret;
+ u8 calibscale[3];
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_LOWER_BYTE(channel),
+ &calibscale[0]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_MID_BYTE(channel),
+ &calibscale[1]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_UPPER_BYTE(channel),
+ &calibscale[2]);
+ if (ret)
+ return ret;
+
+ return get_unaligned_be24(calibscale);
+}
+
+static int ad7779_set_calibscale(struct ad7779_state *st, int channel, int val)
+{
+ int ret;
+ unsigned int gain;
+ u8 gain_bytes[3];
+
+ /*
+ * The gain value is relative to 0x555555, which represents a gain of 1
+ */
+ gain = DIV_ROUND_CLOSEST_ULL((u64)val * 5592405LL, MEGA);
+ put_unaligned_be24(gain, gain_bytes);
+ ret = ad7779_spi_write(st, AD7779_REG_CH_GAIN_UPPER_BYTE(channel),
+ gain_bytes[0]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write(st, AD7779_REG_CH_GAIN_MID_BYTE(channel),
+ gain_bytes[1]);
+ if (ret)
+ return ret;
+
+ return ad7779_spi_write(st, AD7779_REG_CH_GAIN_LOWER_BYTE(channel),
+ gain_bytes[2]);
+}
+
+static int ad7779_get_calibbias(struct ad7779_state *st, int channel)
+{
+ int ret;
+ u8 calibbias[3];
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_LOWER_BYTE(channel),
+ &calibbias[0]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_MID_BYTE(channel),
+ &calibbias[1]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_UPPER_BYTE(channel),
+ &calibbias[2]);
+ if (ret)
+ return ret;
+
+ return get_unaligned_be24(calibbias);
+}
+
+static int ad7779_set_calibbias(struct ad7779_state *st, int channel, int val)
+{
+ int ret;
+ u8 calibbias[3];
+
+ put_unaligned_be24(val, calibbias);
+ ret = ad7779_spi_write(st, AD7779_REG_CH_OFFSET_UPPER_BYTE(channel),
+ calibbias[0]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write(st, AD7779_REG_CH_OFFSET_MID_BYTE(channel),
+ calibbias[1]);
+ if (ret)
+ return ret;
+
+ return ad7779_spi_write(st, AD7779_REG_CH_OFFSET_LOWER_BYTE(channel),
+ calibbias[2]);
+}
+
+static int ad7779_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ int ret;
+
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ switch (mask) {
+ case IIO_CHAN_INFO_CALIBSCALE:
+ ret = ad7779_get_calibscale(st, chan->channel);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ *val2 = GAIN_REL;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ ret = ad7779_get_calibbias(st, chan->channel);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = st->sampling_freq;
+ if (*val < 0)
+ return -EINVAL;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ }
+ unreachable();
+}
+
+static int ad7779_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2,
+ long mask)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ switch (mask) {
+ case IIO_CHAN_INFO_CALIBSCALE:
+ return ad7779_set_calibscale(st, chan->channel, val2);
+ case IIO_CHAN_INFO_CALIBBIAS:
+ return ad7779_set_calibbias(st, chan->channel, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return ad7779_set_sampling_frequency(st, val);
+ default:
+ return -EINVAL;
+ }
+ }
+ unreachable();
+}
+
+static int ad7779_buffer_preenable(struct iio_dev *indio_dev)
+{
+ int ret;
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ ret = ad7779_spi_write_mask(st,
+ AD7779_REG_GENERAL_USER_CONFIG_3,
+ AD7779_MOD_SPI_EN_MSK,
+ FIELD_PREP(AD7779_MOD_SPI_EN_MSK, 1));
+ if (ret)
+ return ret;
+
+ /*
+ * DRDY output cannot be disabled at device level therefore we mask
+ * the irq at host end.
+ */
+ enable_irq(st->spi->irq);
+
+ return 0;
+}
+
+static int ad7779_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ disable_irq(st->spi->irq);
+
+ return ad7779_spi_write(st, AD7779_REG_GENERAL_USER_CONFIG_3,
+ AD7779_DISABLE_SD);
+}
+
+static irqreturn_t ad7779_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct ad7779_state *st = iio_priv(indio_dev);
+ int ret;
+ struct spi_transfer t = {
+ .rx_buf = st->data.chans,
+ .tx_buf = st->spidata_tx,
+ .len = AD7779_NUM_CHANNELS * AD7779_CHAN_DATA_SIZE,
+ };
+
+ st->spidata_tx[0] = AD7779_SPI_READ_CMD;
+ ret = spi_sync_transfer(st->spi, &t, 1);
+ if (ret) {
+ dev_err(&st->spi->dev, "SPI transfer error in IRQ handler");
+ goto exit_handler;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &st->data, pf->timestamp);
+
+exit_handler:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int ad7779_reset(struct iio_dev *indio_dev, struct gpio_desc *reset_gpio)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ int ret;
+ struct spi_transfer t = {
+ .tx_buf = st->reset_buf,
+ .len = 8,
+ };
+
+ if (reset_gpio) {
+ gpiod_set_value(reset_gpio, 1);
+ /* Delay for reset to occur is 225 microseconds */
+ fsleep(230);
+ ret = 0;
+ } else {
+ memset(st->reset_buf, 0xff, sizeof(st->reset_buf));
+ ret = spi_sync_transfer(st->spi, &t, 1);
+ if (ret)
+ return ret;
+ }
+
+ /* Delay for reset to occur is 225 microseconds */
+ fsleep(230);
+
+ return ret;
+}
+
+static const struct iio_info ad7779_info = {
+ .read_raw = ad7779_read_raw,
+ .write_raw = ad7779_write_raw,
+ .debugfs_reg_access = &ad7779_reg_access,
+};
+
+static const struct iio_enum ad7779_filter_enum = {
+ .items = ad7779_filter_type,
+ .num_items = ARRAY_SIZE(ad7779_filter_type),
+ .get = ad7779_get_filter,
+ .set = ad7779_set_filter,
+};
+
+static const struct iio_chan_spec_ext_info ad7779_ext_filter[] = {
+ IIO_ENUM("filter_type", IIO_SHARED_BY_ALL, &ad7779_filter_enum),
+ IIO_ENUM_AVAILABLE("filter_type", IIO_SHARED_BY_ALL,
+ &ad7779_filter_enum),
+ { }
+};
+
+#define AD777x_CHAN_S(index, _ext_info) \
+ { \
+ .type = IIO_VOLTAGE, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_CALIBSCALE) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+ .address = (index), \
+ .indexed = 1, \
+ .channel = (index), \
+ .scan_index = (index), \
+ .ext_info = (_ext_info), \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 24, \
+ .storagebits = 32, \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+#define AD777x_CHAN_NO_FILTER_S(index) \
+ AD777x_CHAN_S(index, NULL)
+
+#define AD777x_CHAN_FILTER_S(index) \
+ AD777x_CHAN_S(index, ad7779_ext_filter)
+static const struct iio_chan_spec ad7779_channels[] = {
+ AD777x_CHAN_NO_FILTER_S(0),
+ AD777x_CHAN_NO_FILTER_S(1),
+ AD777x_CHAN_NO_FILTER_S(2),
+ AD777x_CHAN_NO_FILTER_S(3),
+ AD777x_CHAN_NO_FILTER_S(4),
+ AD777x_CHAN_NO_FILTER_S(5),
+ AD777x_CHAN_NO_FILTER_S(6),
+ AD777x_CHAN_NO_FILTER_S(7),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+static const struct iio_chan_spec ad7779_channels_filter[] = {
+ AD777x_CHAN_FILTER_S(0),
+ AD777x_CHAN_FILTER_S(1),
+ AD777x_CHAN_FILTER_S(2),
+ AD777x_CHAN_FILTER_S(3),
+ AD777x_CHAN_FILTER_S(4),
+ AD777x_CHAN_FILTER_S(5),
+ AD777x_CHAN_FILTER_S(6),
+ AD777x_CHAN_FILTER_S(7),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+static const struct iio_buffer_setup_ops ad7779_buffer_setup_ops = {
+ .preenable = ad7779_buffer_preenable,
+ .postdisable = ad7779_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops ad7779_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
+};
+
+static int ad7779_conf(struct ad7779_state *st, struct gpio_desc *start_gpio)
+{
+ int ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_GEN_ERR_REG_1_EN,
+ AD7779_SPI_CRC_EN_MSK,
+ FIELD_PREP(AD7779_SPI_CRC_EN_MSK, 1));
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1,
+ AD7779_USRMOD_INIT_MSK,
+ FIELD_PREP(AD7779_USRMOD_INIT_MSK, 5));
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT,
+ AD7779_DCLK_CLK_DIV_MSK,
+ FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 1));
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_ADC_MUX_CONFIG,
+ AD7779_REFMUX_CTRL_MSK,
+ FIELD_PREP(AD7779_REFMUX_CTRL_MSK, 1));
+ if (ret)
+ return ret;
+
+ ret = ad7779_set_sampling_frequency(st, AD7779_DEFAULT_SAMPLING_FREQ);
+ if (ret)
+ return ret;
+
+ gpiod_set_value(start_gpio, 0);
+ /* Start setup time */
+ fsleep(15);
+ gpiod_set_value(start_gpio, 1);
+ /* Start setup time */
+ fsleep(15);
+ gpiod_set_value(start_gpio, 0);
+ /* Start setup time */
+ fsleep(15);
+
+ return 0;
+}
+
+static int ad7779_probe(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev;
+ struct ad7779_state *st;
+ struct gpio_desc *reset_gpio, *start_gpio;
+ struct device *dev = &spi->dev;
+ int ret = -EINVAL;
+
+ if (!spi->irq)
+ return dev_err_probe(dev, ret, "DRDY irq not present\n");
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ ret = devm_regulator_bulk_get_enable(dev,
+ ARRAY_SIZE(ad7779_power_supplies),
+ ad7779_power_supplies);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to get and enable supplies\n");
+
+ st->mclk = devm_clk_get_enabled(dev, "mclk");
+ if (IS_ERR(st->mclk))
+ return PTR_ERR(st->mclk);
+
+ reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(reset_gpio))
+ return PTR_ERR(reset_gpio);
+
+ start_gpio = devm_gpiod_get(dev, "start", GPIOD_OUT_HIGH);
+ if (IS_ERR(start_gpio))
+ return PTR_ERR(start_gpio);
+
+ crc8_populate_msb(ad7779_crc8_table, AD7779_CRC8_POLY);
+ st->spi = spi;
+
+ st->chip_info = spi_get_device_match_data(spi);
+ if (!st->chip_info)
+ return -ENODEV;
+
+ ret = ad7779_reset(indio_dev, reset_gpio);
+ if (ret)
+ return ret;
+
+ ret = ad7779_conf(st, start_gpio);
+ if (ret)
+ return ret;
+
+ indio_dev->name = st->chip_info->name;
+ indio_dev->info = &ad7779_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = st->chip_info->channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad7779_channels);
+
+ st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!st->trig)
+ return -ENOMEM;
+
+ st->trig->ops = &ad7779_trigger_ops;
+
+ iio_trigger_set_drvdata(st->trig, st);
+
+ ret = devm_request_irq(dev, spi->irq, iio_trigger_generic_data_rdy_poll,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN, indio_dev->name,
+ st->trig);
+ if (ret)
+ return dev_err_probe(dev, ret, "request IRQ %d failed\n",
+ st->spi->irq);
+
+ ret = devm_iio_trigger_register(dev, st->trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(st->trig);
+
+ init_completion(&st->completion);
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ &iio_pollfunc_store_time,
+ &ad7779_trigger_handler,
+ &ad7779_buffer_setup_ops);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT,
+ AD7779_DCLK_CLK_DIV_MSK,
+ FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 7));
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static int ad7779_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ return ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1,
+ AD7779_MOD_POWERMODE_MSK,
+ FIELD_PREP(AD7779_MOD_POWERMODE_MSK,
+ AD7779_LOW_POWER));
+}
+
+static int ad7779_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ return ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1,
+ AD7779_MOD_POWERMODE_MSK,
+ FIELD_PREP(AD7779_MOD_POWERMODE_MSK,
+ AD7779_HIGH_POWER));
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(ad7779_pm_ops, ad7779_suspend, ad7779_resume);
+
+static const struct ad7779_chip_info ad7770_chip_info = {
+ .name = "ad7770",
+ .channels = ad7779_channels,
+};
+
+static const struct ad7779_chip_info ad7771_chip_info = {
+ .name = "ad7771",
+ .channels = ad7779_channels_filter,
+};
+
+static const struct ad7779_chip_info ad7779_chip_info = {
+ .name = "ad7779",
+ .channels = ad7779_channels,
+};
+
+static const struct spi_device_id ad7779_id[] = {
+ {
+ .name = "ad7770",
+ .driver_data = (kernel_ulong_t)&ad7770_chip_info,
+ },
+ {
+ .name = "ad7771",
+ .driver_data = (kernel_ulong_t)&ad7771_chip_info,
+ },
+ {
+ .name = "ad7779",
+ .driver_data = (kernel_ulong_t)&ad7779_chip_info,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ad7779_id);
+
+static const struct of_device_id ad7779_of_table[] = {
+ {
+ .compatible = "adi,ad7770",
+ .data = &ad7770_chip_info,
+ },
+ {
+ .compatible = "adi,ad7771",
+ .data = &ad7771_chip_info,
+ },
+ {
+ .compatible = "adi,ad7779",
+ .data = &ad7779_chip_info,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad7779_of_table);
+
+static struct spi_driver ad7779_driver = {
+ .driver = {
+ .name = "ad7779",
+ .pm = pm_sleep_ptr(&ad7779_pm_ops),
+ .of_match_table = ad7779_of_table,
+ },
+ .probe = ad7779_probe,
+ .id_table = ad7779_id,
+};
+module_spi_driver(ad7779_driver);
+
+MODULE_AUTHOR("Ramona Alexandra Nechita <ramona.nechita@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD7779 ADC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c
index e9b0c577c9cc..8ccb74f47030 100644
--- a/drivers/iio/adc/ad7780.c
+++ b/drivers/iio/adc/ad7780.c
@@ -152,7 +152,7 @@ static int ad7780_write_raw(struct iio_dev *indio_dev,
switch (m) {
case IIO_CHAN_INFO_SCALE:
- if (val != 0)
+ if (val != 0 || val2 == 0)
return -EINVAL;
vref = st->int_vref_mv * 1000000LL;
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
index 86effe8501b4..5d2ad3dd6caa 100644
--- a/drivers/iio/adc/ad7791.c
+++ b/drivers/iio/adc/ad7791.c
@@ -371,7 +371,7 @@ static const struct iio_info ad7791_no_filter_info = {
};
static int ad7791_setup(struct ad7791_state *st,
- struct ad7791_platform_data *pdata)
+ const struct ad7791_platform_data *pdata)
{
/* Set to poweron-reset default values */
st->mode = AD7791_MODE_BUFFER;
@@ -401,7 +401,7 @@ static void ad7791_reg_disable(void *reg)
static int ad7791_probe(struct spi_device *spi)
{
- struct ad7791_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7791_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad7791_state *st;
int ret;
diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c
index abebd519cafa..b86e89370e0d 100644
--- a/drivers/iio/adc/ad7793.c
+++ b/drivers/iio/adc/ad7793.c
@@ -770,7 +770,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
static int ad7793_probe(struct spi_device *spi)
{
- const struct ad7793_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7793_platform_data *pdata = dev_get_platdata(&spi->dev);
struct ad7793_state *st;
struct iio_dev *indio_dev;
int ret, vref_mv = 0;
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index 6265ce7df703..69add1dc4b53 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -41,7 +41,7 @@ enum ad7887_channels {
};
/**
- * struct ad7887_chip_info - chip specifc information
+ * struct ad7887_chip_info - chip specific information
* @int_vref_mv: the internal reference voltage
* @channels: channels specification
* @num_channels: number of channels
@@ -234,7 +234,7 @@ static void ad7887_reg_disable(void *data)
static int ad7887_probe(struct spi_device *spi)
{
- struct ad7887_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7887_platform_data *pdata = dev_get_platdata(&spi->dev);
struct ad7887_state *st;
struct iio_dev *indio_dev;
uint8_t mode;
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
index 09680015a7ab..acc44cb34f82 100644
--- a/drivers/iio/adc/ad7923.c
+++ b/drivers/iio/adc/ad7923.c
@@ -48,7 +48,7 @@
struct ad7923_state {
struct spi_device *spi;
- struct spi_transfer ring_xfer[5];
+ struct spi_transfer ring_xfer[9];
struct spi_transfer scan_single_xfer[2];
struct spi_message ring_msg;
struct spi_message scan_single_msg;
@@ -64,7 +64,7 @@ struct ad7923_state {
* Length = 8 channels + 4 extra for 8 byte timestamp
*/
__be16 rx_buf[12] __aligned(IIO_DMA_MINALIGN);
- __be16 tx_buf[4];
+ __be16 tx_buf[8];
};
struct ad7923_chip_info {
diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c
index 0f36138a7144..a5aea4e9f1a7 100644
--- a/drivers/iio/adc/ad7944.c
+++ b/drivers/iio/adc/ad7944.c
@@ -80,7 +80,7 @@ struct ad7944_adc {
};
/* quite time before CNV rising edge */
-#define T_QUIET_NS 20
+#define AD7944_T_QUIET_NS 20
static const struct ad7944_timing_spec ad7944_timing_spec = {
.conv_ns = 420,
@@ -150,7 +150,7 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc *
* CS is tied to CNV and we need a low to high transition to start the
* conversion, so place CNV low for t_QUIET to prepare for this.
*/
- xfers[0].delay.value = T_QUIET_NS;
+ xfers[0].delay.value = AD7944_T_QUIET_NS;
xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS;
/*
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
index 0f107e3fc2c8..aa44b4e2542b 100644
--- a/drivers/iio/adc/ad799x.c
+++ b/drivers/iio/adc/ad799x.c
@@ -406,7 +406,7 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct ad799x_state *st = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index ea4aabd3960a..2f3b61765055 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -469,7 +469,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
/*
* Data array after transfer will look like (if status is appended):
* data[] = { [0][sample][sample][sample][status] }
- * Keeping the first byte 0 shifts the status postion by 1 byte to the right.
+ * Keeping the first byte 0 shifts the status position by 1 byte to the right.
*/
status_pos = reg_size + 1;
@@ -656,7 +656,7 @@ int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
sigma_delta->spi = spi;
sigma_delta->info = info;
- /* If the field is unset in ad_sigma_delta_info, asume there can only be 1 slot. */
+ /* If the field is unset in ad_sigma_delta_info, assume there can only be 1 slot. */
if (!info->num_slots)
sigma_delta->num_slots = 1;
else
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index d7fd21e7c6e2..8e5aaf15a921 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -2625,7 +2625,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_match);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
- .remove_new = at91_adc_remove,
+ .remove = at91_adc_remove,
.driver = {
.name = "at91-sama5d2_adc",
.of_match_table = at91_adc_dt_match,
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 9c39acff17e6..a3f0a2321666 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -1341,7 +1341,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
- .remove_new = at91_adc_remove,
+ .remove = at91_adc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = at91_adc_dt_ids,
diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c
index 6c1a5d1b0a83..9fd7027623d0 100644
--- a/drivers/iio/adc/axp20x_adc.c
+++ b/drivers/iio/adc/axp20x_adc.c
@@ -155,52 +155,22 @@ enum axp813_adc_channel_v {
AXP813_BATT_V,
};
-static struct iio_map axp20x_maps[] = {
- {
- .consumer_dev_name = "axp20x-usb-power-supply",
- .consumer_channel = "vbus_v",
- .adc_channel_label = "vbus_v",
- }, {
- .consumer_dev_name = "axp20x-usb-power-supply",
- .consumer_channel = "vbus_i",
- .adc_channel_label = "vbus_i",
- }, {
- .consumer_dev_name = "axp20x-ac-power-supply",
- .consumer_channel = "acin_v",
- .adc_channel_label = "acin_v",
- }, {
- .consumer_dev_name = "axp20x-ac-power-supply",
- .consumer_channel = "acin_i",
- .adc_channel_label = "acin_i",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_v",
- .adc_channel_label = "batt_v",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_chrg_i",
- .adc_channel_label = "batt_chrg_i",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_dischrg_i",
- .adc_channel_label = "batt_dischrg_i",
- }, { /* sentinel */ }
+static const struct iio_map axp20x_maps[] = {
+ IIO_MAP("vbus_v", "axp20x-usb-power-supply", "vbus_v"),
+ IIO_MAP("vbus_i", "axp20x-usb-power-supply", "vbus_i"),
+ IIO_MAP("acin_v", "axp20x-ac-power-supply", "acin_v"),
+ IIO_MAP("acin_i", "axp20x-ac-power-supply", "acin_i"),
+ IIO_MAP("batt_v", "axp20x-battery-power-supply", "batt_v"),
+ IIO_MAP("batt_chrg_i", "axp20x-battery-power-supply", "batt_chrg_i"),
+ IIO_MAP("batt_dischrg_i", "axp20x-battery-power-supply", "batt_dischrg_i"),
+ { /* sentinel */ }
};
-static struct iio_map axp22x_maps[] = {
- {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_v",
- .adc_channel_label = "batt_v",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_chrg_i",
- .adc_channel_label = "batt_chrg_i",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_dischrg_i",
- .adc_channel_label = "batt_dischrg_i",
- }, { /* sentinel */ }
+static const struct iio_map axp22x_maps[] = {
+ IIO_MAP("batt_v", "axp20x-battery-power-supply", "batt_v"),
+ IIO_MAP("batt_chrg_i", "axp20x-battery-power-supply", "batt_chrg_i"),
+ IIO_MAP("batt_dischrg_i", "axp20x-battery-power-supply", "batt_dischrg_i"),
+ { /* sentinel */ }
};
static struct iio_map axp717_maps[] = {
@@ -1044,7 +1014,7 @@ struct axp_data {
unsigned long adc_en2_mask;
int (*adc_rate)(struct axp20x_adc_iio *info,
int rate);
- struct iio_map *maps;
+ const struct iio_map *maps;
};
static const struct axp_data axp192_data = {
@@ -1212,7 +1182,7 @@ static struct platform_driver axp20x_adc_driver = {
},
.id_table = axp20x_adc_id_match,
.probe = axp20x_probe,
- .remove_new = axp20x_remove,
+ .remove = axp20x_remove,
};
module_platform_driver(axp20x_adc_driver);
diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c
index 8c3acc0cd7e9..45542efc3ece 100644
--- a/drivers/iio/adc/axp288_adc.c
+++ b/drivers/iio/adc/axp288_adc.c
@@ -103,7 +103,7 @@ static const struct iio_chan_spec axp288_adc_channels[] = {
};
/* for consumer drivers */
-static struct iio_map axp288_adc_default_maps[] = {
+static const struct iio_map axp288_adc_default_maps[] = {
IIO_MAP("TS_PIN", "axp288-batt", "axp288-batt-temp"),
IIO_MAP("PMIC_TEMP", "axp288-pmic", "axp288-pmic-temp"),
IIO_MAP("GPADC", "axp288-gpadc", "axp288-system-temp"),
diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c
index cdfe304eaa20..f258668b0dc7 100644
--- a/drivers/iio/adc/bcm_iproc_adc.c
+++ b/drivers/iio/adc/bcm_iproc_adc.c
@@ -611,10 +611,10 @@ static const struct of_device_id iproc_adc_of_match[] = {
MODULE_DEVICE_TABLE(of, iproc_adc_of_match);
static struct platform_driver iproc_adc_driver = {
- .probe = iproc_adc_probe,
- .remove_new = iproc_adc_remove,
- .driver = {
- .name = "iproc-static-adc",
+ .probe = iproc_adc_probe,
+ .remove = iproc_adc_remove,
+ .driver = {
+ .name = "iproc-static-adc",
.of_match_table = iproc_adc_of_match,
},
};
diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c
index 8f0d3fb63b67..0290345ade84 100644
--- a/drivers/iio/adc/da9150-gpadc.c
+++ b/drivers/iio/adc/da9150-gpadc.c
@@ -291,27 +291,11 @@ static const struct iio_chan_spec da9150_gpadc_channels[] = {
};
/* Default maps used by da9150-charger */
-static struct iio_map da9150_gpadc_default_maps[] = {
- {
- .consumer_dev_name = "da9150-charger",
- .consumer_channel = "CHAN_IBUS",
- .adc_channel_label = "IBUS",
- },
- {
- .consumer_dev_name = "da9150-charger",
- .consumer_channel = "CHAN_VBUS",
- .adc_channel_label = "VBUS",
- },
- {
- .consumer_dev_name = "da9150-charger",
- .consumer_channel = "CHAN_TJUNC",
- .adc_channel_label = "TJUNC_CORE",
- },
- {
- .consumer_dev_name = "da9150-charger",
- .consumer_channel = "CHAN_VBAT",
- .adc_channel_label = "VBAT",
- },
+static const struct iio_map da9150_gpadc_default_maps[] = {
+ IIO_MAP("IBUS", "da9150-charger", "CHAN_IBUS"),
+ IIO_MAP("VBUS", "da9150-charger", "CHAN_VBUS"),
+ IIO_MAP("TJUNC_CORE", "da9150-charger", "CHAN_TJUNC"),
+ IIO_MAP("VBAT", "da9150-charger", "CHAN_VBAT"),
{},
};
diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c
index de7252a10047..30328626d9be 100644
--- a/drivers/iio/adc/dln2-adc.c
+++ b/drivers/iio/adc/dln2-adc.c
@@ -700,7 +700,7 @@ static void dln2_adc_remove(struct platform_device *pdev)
static struct platform_driver dln2_adc_driver = {
.driver.name = DLN2_ADC_MOD_NAME,
.probe = dln2_adc_probe,
- .remove_new = dln2_adc_remove,
+ .remove = dln2_adc_remove,
};
module_platform_driver(dln2_adc_driver);
diff --git a/drivers/iio/adc/ep93xx_adc.c b/drivers/iio/adc/ep93xx_adc.c
index cc38d5e0608e..a3e9c697e2cb 100644
--- a/drivers/iio/adc/ep93xx_adc.c
+++ b/drivers/iio/adc/ep93xx_adc.c
@@ -238,7 +238,7 @@ static struct platform_driver ep93xx_adc_driver = {
.of_match_table = ep93xx_adc_of_ids,
},
.probe = ep93xx_adc_probe,
- .remove_new = ep93xx_adc_remove,
+ .remove = ep93xx_adc_remove,
};
module_platform_driver(ep93xx_adc_driver);
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 4d00ee8dd14d..4614cf848535 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -1008,7 +1008,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(exynos_adc_pm_ops, exynos_adc_suspend,
static struct platform_driver exynos_adc_driver = {
.probe = exynos_adc_probe,
- .remove_new = exynos_adc_remove,
+ .remove = exynos_adc_remove,
.driver = {
.name = "exynos-adc",
.of_match_table = exynos_adc_match,
diff --git a/drivers/iio/adc/gehc-pmc-adc.c b/drivers/iio/adc/gehc-pmc-adc.c
new file mode 100644
index 000000000000..d1167818b17d
--- /dev/null
+++ b/drivers/iio/adc/gehc-pmc-adc.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * The GE HealthCare PMC ADC is a 16-Channel (Voltage and current), 16-Bit
+ * ADC with an I2C Interface.
+ *
+ * Copyright (C) 2024, GE HealthCare
+ *
+ * Authors:
+ * Herve Codina <herve.codina@bootlin.com>
+ */
+#include <dt-bindings/iio/adc/gehc,pmc-adc.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+struct pmc_adc {
+ struct i2c_client *client;
+};
+
+#define PMC_ADC_CMD_REQUEST_PROTOCOL_VERSION 0x01
+#define PMC_ADC_CMD_READ_VOLTAGE(_ch) (0x10 | (_ch))
+#define PMC_ADC_CMD_READ_CURRENT(_ch) (0x20 | (_ch))
+
+#define PMC_ADC_VOLTAGE_CHANNEL(_ch, _ds_name) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = (_ch), \
+ .address = PMC_ADC_CMD_READ_VOLTAGE(_ch), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .datasheet_name = (_ds_name), \
+}
+
+#define PMC_ADC_CURRENT_CHANNEL(_ch, _ds_name) { \
+ .type = IIO_CURRENT, \
+ .indexed = 1, \
+ .channel = (_ch), \
+ .address = PMC_ADC_CMD_READ_CURRENT(_ch), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .datasheet_name = (_ds_name), \
+}
+
+static const struct iio_chan_spec pmc_adc_channels[] = {
+ PMC_ADC_VOLTAGE_CHANNEL(0, "CH0_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(1, "CH1_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(2, "CH2_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(3, "CH3_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(4, "CH4_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(5, "CH5_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(6, "CH6_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(7, "CH7_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(8, "CH8_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(9, "CH9_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(10, "CH10_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(11, "CH11_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(12, "CH12_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(13, "CH13_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(14, "CH14_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(15, "CH15_V"),
+
+ PMC_ADC_CURRENT_CHANNEL(0, "CH0_I"),
+ PMC_ADC_CURRENT_CHANNEL(1, "CH1_I"),
+ PMC_ADC_CURRENT_CHANNEL(2, "CH2_I"),
+ PMC_ADC_CURRENT_CHANNEL(3, "CH3_I"),
+ PMC_ADC_CURRENT_CHANNEL(4, "CH4_I"),
+ PMC_ADC_CURRENT_CHANNEL(5, "CH5_I"),
+ PMC_ADC_CURRENT_CHANNEL(6, "CH6_I"),
+ PMC_ADC_CURRENT_CHANNEL(7, "CH7_I"),
+ PMC_ADC_CURRENT_CHANNEL(8, "CH8_I"),
+ PMC_ADC_CURRENT_CHANNEL(9, "CH9_I"),
+ PMC_ADC_CURRENT_CHANNEL(10, "CH10_I"),
+ PMC_ADC_CURRENT_CHANNEL(11, "CH11_I"),
+ PMC_ADC_CURRENT_CHANNEL(12, "CH12_I"),
+ PMC_ADC_CURRENT_CHANNEL(13, "CH13_I"),
+ PMC_ADC_CURRENT_CHANNEL(14, "CH14_I"),
+ PMC_ADC_CURRENT_CHANNEL(15, "CH15_I"),
+};
+
+static int pmc_adc_read_raw_ch(struct pmc_adc *pmc_adc, u8 cmd, int *val)
+{
+ s32 ret;
+
+ ret = i2c_smbus_read_word_swapped(pmc_adc->client, cmd);
+ if (ret < 0) {
+ dev_err(&pmc_adc->client->dev, "i2c read word failed (%d)\n", ret);
+ return ret;
+ }
+
+ *val = sign_extend32(ret, 15);
+ return 0;
+}
+
+static int pmc_adc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct pmc_adc *pmc_adc = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ /* Values are directly read in mV or mA */
+ ret = pmc_adc_read_raw_ch(pmc_adc, chan->address, val);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+ }
+
+ return -EINVAL;
+}
+
+static int pmc_adc_fwnode_xlate(struct iio_dev *indio_dev,
+ const struct fwnode_reference_args *iiospec)
+{
+ enum iio_chan_type expected_type;
+ unsigned int i;
+
+ /*
+ * args[0]: Acquisition type (i.e. voltage or current)
+ * args[1]: PMC ADC channel number
+ */
+ if (iiospec->nargs != 2)
+ return -EINVAL;
+
+ switch (iiospec->args[0]) {
+ case GEHC_PMC_ADC_VOLTAGE:
+ expected_type = IIO_VOLTAGE;
+ break;
+ case GEHC_PMC_ADC_CURRENT:
+ expected_type = IIO_CURRENT;
+ break;
+ default:
+ dev_err(&indio_dev->dev, "Invalid channel type %llu\n",
+ iiospec->args[0]);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < indio_dev->num_channels; i++)
+ if (indio_dev->channels[i].type == expected_type &&
+ indio_dev->channels[i].channel == iiospec->args[1])
+ return i;
+
+ dev_err(&indio_dev->dev, "Invalid channel type %llu number %llu\n",
+ iiospec->args[0], iiospec->args[1]);
+ return -EINVAL;
+}
+
+static const struct iio_info pmc_adc_info = {
+ .read_raw = pmc_adc_read_raw,
+ .fwnode_xlate = pmc_adc_fwnode_xlate,
+};
+
+static const char *const pmc_adc_regulator_names[] = {
+ "vdd",
+ "vdda",
+ "vddio",
+ "vref",
+};
+
+static int pmc_adc_probe(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev;
+ struct pmc_adc *pmc_adc;
+ struct clk *clk;
+ s32 val;
+ int ret;
+
+ ret = devm_regulator_bulk_get_enable(&client->dev, ARRAY_SIZE(pmc_adc_regulator_names),
+ pmc_adc_regulator_names);
+ if (ret)
+ return dev_err_probe(&client->dev, ret, "Failed to get regulators\n");
+
+ clk = devm_clk_get_optional_enabled(&client->dev, "osc");
+ if (IS_ERR(clk))
+ return dev_err_probe(&client->dev, PTR_ERR(clk), "Failed to get osc clock\n");
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*pmc_adc));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ pmc_adc = iio_priv(indio_dev);
+ pmc_adc->client = client;
+
+ val = i2c_smbus_read_byte_data(pmc_adc->client, PMC_ADC_CMD_REQUEST_PROTOCOL_VERSION);
+ if (val < 0)
+ return dev_err_probe(&client->dev, val, "Failed to get protocol version\n");
+
+ if (val != 0x01)
+ return dev_err_probe(&client->dev, -EINVAL,
+ "Unsupported protocol version 0x%02x\n", val);
+
+ indio_dev->name = "pmc_adc";
+ indio_dev->info = &pmc_adc_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = pmc_adc_channels;
+ indio_dev->num_channels = ARRAY_SIZE(pmc_adc_channels);
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct of_device_id pmc_adc_of_match[] = {
+ { .compatible = "gehc,pmc-adc"},
+ { }
+};
+MODULE_DEVICE_TABLE(of, pmc_adc_of_match);
+
+static const struct i2c_device_id pmc_adc_id_table[] = {
+ { "pmc-adc" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pmc_adc_id_table);
+
+static struct i2c_driver pmc_adc_i2c_driver = {
+ .driver = {
+ .name = "pmc-adc",
+ .of_match_table = pmc_adc_of_match,
+ },
+ .id_table = pmc_adc_id_table,
+ .probe = pmc_adc_probe,
+};
+
+module_i2c_driver(pmc_adc_i2c_driver);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("GE HealthCare PMC ADC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c
index fb635a756440..689e34f06987 100644
--- a/drivers/iio/adc/hi8435.c
+++ b/drivers/iio/adc/hi8435.c
@@ -132,7 +132,7 @@ static int hi8435_read_event_config(struct iio_dev *idev,
static int hi8435_write_event_config(struct iio_dev *idev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct hi8435_priv *priv = iio_priv(idev);
int ret;
diff --git a/drivers/iio/adc/imx8qxp-adc.c b/drivers/iio/adc/imx8qxp-adc.c
index fe82198170d5..3d19d7d744aa 100644
--- a/drivers/iio/adc/imx8qxp-adc.c
+++ b/drivers/iio/adc/imx8qxp-adc.c
@@ -487,7 +487,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_adc_match);
static struct platform_driver imx8qxp_adc_driver = {
.probe = imx8qxp_adc_probe,
- .remove_new = imx8qxp_adc_remove,
+ .remove = imx8qxp_adc_remove,
.driver = {
.name = ADC_DRIVER_NAME,
.of_match_table = imx8qxp_adc_match,
diff --git a/drivers/iio/adc/imx93_adc.c b/drivers/iio/adc/imx93_adc.c
index 4ccf4819f1f1..002eb19587d6 100644
--- a/drivers/iio/adc/imx93_adc.c
+++ b/drivers/iio/adc/imx93_adc.c
@@ -470,7 +470,7 @@ MODULE_DEVICE_TABLE(of, imx93_adc_match);
static struct platform_driver imx93_adc_driver = {
.probe = imx93_adc_probe,
- .remove_new = imx93_adc_remove,
+ .remove = imx93_adc_remove,
.driver = {
.name = IMX93_ADC_DRIVER_NAME,
.of_match_table = imx93_adc_match,
diff --git a/drivers/iio/adc/intel_mrfld_adc.c b/drivers/iio/adc/intel_mrfld_adc.c
index 30733252aa56..c178850eaaab 100644
--- a/drivers/iio/adc/intel_mrfld_adc.c
+++ b/drivers/iio/adc/intel_mrfld_adc.c
@@ -164,7 +164,7 @@ static const struct iio_chan_spec mrfld_adc_channels[] = {
BCOVE_ADC_CHANNEL(IIO_TEMP, 8, "CH8", 0xC6),
};
-static struct iio_map iio_maps[] = {
+static const struct iio_map iio_maps[] = {
IIO_MAP("CH0", "bcove-battery", "VBATRSLT"),
IIO_MAP("CH1", "bcove-battery", "BATTID"),
IIO_MAP("CH2", "bcove-battery", "IBATRSLT"),
diff --git a/drivers/iio/adc/lp8788_adc.c b/drivers/iio/adc/lp8788_adc.c
index 6d9b354bc705..33bf8aef79e3 100644
--- a/drivers/iio/adc/lp8788_adc.c
+++ b/drivers/iio/adc/lp8788_adc.c
@@ -26,7 +26,7 @@
struct lp8788_adc {
struct lp8788 *lp;
- struct iio_map *map;
+ const struct iio_map *map;
struct mutex lock;
};
@@ -149,17 +149,9 @@ static const struct iio_chan_spec lp8788_adc_channels[] = {
};
/* default maps used by iio consumer (lp8788-charger driver) */
-static struct iio_map lp8788_default_iio_maps[] = {
- {
- .consumer_dev_name = "lp8788-charger",
- .consumer_channel = "lp8788_vbatt_5p0",
- .adc_channel_label = "VBATT_5P0",
- },
- {
- .consumer_dev_name = "lp8788-charger",
- .consumer_channel = "lp8788_adc1",
- .adc_channel_label = "ADC1",
- },
+static const struct iio_map lp8788_default_iio_maps[] = {
+ IIO_MAP("VBATT_5P0", "lp8788-charger", "lp8788_vbatt_5p0"),
+ IIO_MAP("ADC1", "lp8788-charger", "lp8788_adc1"),
{ }
};
@@ -168,7 +160,7 @@ static int lp8788_iio_map_register(struct device *dev,
struct lp8788_platform_data *pdata,
struct lp8788_adc *adc)
{
- struct iio_map *map;
+ const struct iio_map *map;
int ret;
map = (!pdata || !pdata->adc_pdata) ?
diff --git a/drivers/iio/adc/ltc2497-core.c b/drivers/iio/adc/ltc2497-core.c
index 996f6cbbed3c..ad8ddf80310e 100644
--- a/drivers/iio/adc/ltc2497-core.c
+++ b/drivers/iio/adc/ltc2497-core.c
@@ -168,6 +168,7 @@ static const struct iio_info ltc2497core_info = {
int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev)
{
struct ltc2497core_driverdata *ddata = iio_priv(indio_dev);
+ struct iio_map *plat_data = dev_get_platdata(dev);
int ret;
/*
@@ -200,16 +201,10 @@ int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev)
return ret;
}
- if (dev->platform_data) {
- struct iio_map *plat_data;
-
- plat_data = (struct iio_map *)dev->platform_data;
-
- ret = iio_map_array_register(indio_dev, plat_data);
- if (ret) {
- dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
- goto err_regulator_disable;
- }
+ ret = iio_map_array_register(indio_dev, plat_data);
+ if (ret) {
+ dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
+ goto err_regulator_disable;
}
ddata->addr_prev = LTC2497_CONFIG_DEFAULT;
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index d0c6e94f7204..9a0baea08ab6 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
+#include <linux/unaligned.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -392,7 +393,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
if (data < 0)
return data;
- data = (rxbuf[1] | rxbuf[0] << 8) &
+ data = get_unaligned_be16(rxbuf) &
((1 << st->chip_info->bits) - 1);
} else {
/* Get reading */
@@ -943,7 +944,7 @@ error_ret:
static int max1363_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct max1363_state *st = iio_priv(indio_dev);
diff --git a/drivers/iio/adc/max34408.c b/drivers/iio/adc/max34408.c
index ffec22be2d59..971e6e5dee9b 100644
--- a/drivers/iio/adc/max34408.c
+++ b/drivers/iio/adc/max34408.c
@@ -161,7 +161,7 @@ static int max34408_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
/*
- * calcluate current for 8bit ADC with Rsense
+ * calculate current for 8bit ADC with Rsense
* value.
* 10 mV * 1000 / Rsense uOhm = max current
* (max current * adc val * 1000) / (2^8 - 1) mA
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index e16b0e28974e..2d475b43e717 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -1483,7 +1483,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops,
static struct platform_driver meson_sar_adc_driver = {
.probe = meson_sar_adc_probe,
- .remove_new = meson_sar_adc_remove,
+ .remove = meson_sar_adc_remove,
.driver = {
.name = "meson-saradc",
.of_match_table = meson_sar_adc_of_match,
diff --git a/drivers/iio/adc/mp2629_adc.c b/drivers/iio/adc/mp2629_adc.c
index 5fbf9b6abd9c..1cb043b17437 100644
--- a/drivers/iio/adc/mp2629_adc.c
+++ b/drivers/iio/adc/mp2629_adc.c
@@ -52,7 +52,7 @@ static struct iio_chan_spec mp2629_channels[] = {
MP2629_ADC_CHAN(INPUT_CURRENT, IIO_CURRENT)
};
-static struct iio_map mp2629_adc_maps[] = {
+static const struct iio_map mp2629_adc_maps[] = {
MP2629_MAP(BATT_VOLT, "batt-volt"),
MP2629_MAP(SYSTEM_VOLT, "system-volt"),
MP2629_MAP(INPUT_VOLT, "input-volt"),
@@ -195,7 +195,7 @@ static struct platform_driver mp2629_adc_driver = {
.of_match_table = mp2629_adc_of_match,
},
.probe = mp2629_adc_probe,
- .remove_new = mp2629_adc_remove,
+ .remove = mp2629_adc_remove,
};
module_platform_driver(mp2629_adc_driver);
diff --git a/drivers/iio/adc/mt6360-adc.c b/drivers/iio/adc/mt6360-adc.c
index 83161e6d29b9..4eb2455d6ffa 100644
--- a/drivers/iio/adc/mt6360-adc.c
+++ b/drivers/iio/adc/mt6360-adc.c
@@ -124,7 +124,7 @@ static int mt6360_adc_read_channel(struct mt6360_adc_data *mad, int channel, int
usleep_range(ADC_LOOP_TIME_US / 2, ADC_LOOP_TIME_US);
}
- *val = rpt[1] << 8 | rpt[2];
+ *val = get_unaligned_be16(&rpt[1]);
ret = IIO_VAL_INT;
out_adc_conv:
diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c
index 8c7b64e78dbb..152cbe265e1a 100644
--- a/drivers/iio/adc/mxs-lradc-adc.c
+++ b/drivers/iio/adc/mxs-lradc-adc.c
@@ -819,10 +819,10 @@ static void mxs_lradc_adc_remove(struct platform_device *pdev)
static struct platform_driver mxs_lradc_adc_driver = {
.driver = {
- .name = "mxs-lradc-adc",
+ .name = "mxs-lradc-adc",
},
- .probe = mxs_lradc_adc_probe,
- .remove_new = mxs_lradc_adc_remove,
+ .probe = mxs_lradc_adc_probe,
+ .remove = mxs_lradc_adc_remove,
};
module_platform_driver(mxs_lradc_adc_driver);
diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c
index 3a55465951e7..7c1511ee3a4b 100644
--- a/drivers/iio/adc/npcm_adc.c
+++ b/drivers/iio/adc/npcm_adc.c
@@ -337,7 +337,7 @@ static void npcm_adc_remove(struct platform_device *pdev)
static struct platform_driver npcm_adc_driver = {
.probe = npcm_adc_probe,
- .remove_new = npcm_adc_remove,
+ .remove = npcm_adc_remove,
.driver = {
.name = "npcm_adc",
.of_match_table = npcm_adc_match,
diff --git a/drivers/iio/adc/pac1921.c b/drivers/iio/adc/pac1921.c
index 36e813d9c73f..b0f6727cfe38 100644
--- a/drivers/iio/adc/pac1921.c
+++ b/drivers/iio/adc/pac1921.c
@@ -241,7 +241,7 @@ static inline void pac1921_calc_scale(int dividend, int divisor, int *val,
s64 tmp;
tmp = div_s64(dividend * (s64)NANO, divisor);
- *val = (int)div_s64_rem(tmp, NANO, val2);
+ *val = div_s64_rem(tmp, NANO, val2);
}
/*
@@ -260,7 +260,7 @@ static void pac1921_calc_current_scales(struct pac1921_priv *priv)
int max = (PAC1921_MAX_VSENSE_MV * MICRO) >> i;
int vsense_lsb = DIV_ROUND_CLOSEST(max, PAC1921_RES_RESOLUTION);
- pac1921_calc_scale(vsense_lsb, (int)priv->rshunt_uohm,
+ pac1921_calc_scale(vsense_lsb, priv->rshunt_uohm,
&priv->current_scales[i][0],
&priv->current_scales[i][1]);
}
@@ -314,7 +314,7 @@ static int pac1921_check_push_overflow(struct iio_dev *indio_dev, s64 timestamp)
timestamp);
}
- priv->prev_ovf_flags = (u8)flags;
+ priv->prev_ovf_flags = flags;
return 0;
}
@@ -329,8 +329,7 @@ static int pac1921_check_push_overflow(struct iio_dev *indio_dev, s64 timestamp)
static int pac1921_read_res(struct pac1921_priv *priv, unsigned long reg,
u16 *val)
{
- int ret = regmap_bulk_read(priv->regmap, (unsigned int)reg, val,
- sizeof(*val));
+ int ret = regmap_bulk_read(priv->regmap, reg, val, sizeof(*val));
if (ret)
return ret;
@@ -366,7 +365,7 @@ static int pac1921_read_raw(struct iio_dev *indio_dev,
if (ret)
return ret;
- *val = (int)res_val;
+ *val = res_val;
return IIO_VAL_INT;
}
@@ -400,10 +399,10 @@ static int pac1921_read_raw(struct iio_dev *indio_dev,
s64 tmp = curr_scale[0] * (s64)NANO + curr_scale[1];
/* Multiply by max_vbus (V) / dv_gain */
- tmp *= PAC1921_MAX_VBUS_V >> (int)priv->dv_gain;
+ tmp *= PAC1921_MAX_VBUS_V >> priv->dv_gain;
/* Convert back to INT_PLUS_NANO */
- *val = (int)div_s64_rem(tmp, NANO, val2);
+ *val = div_s64_rem(tmp, NANO, val2);
return IIO_VAL_INT_PLUS_NANO;
}
@@ -426,7 +425,7 @@ static int pac1921_read_raw(struct iio_dev *indio_dev,
* 1/(integr_period_usecs/MICRO) = MICRO/integr_period_usecs
*/
*val = MICRO;
- *val2 = (int)priv->integr_period_usecs;
+ *val2 = priv->integr_period_usecs;
return IIO_VAL_FRACTIONAL;
default:
@@ -503,7 +502,7 @@ static int pac1921_lookup_scale(const int (*const scales_tbl)[2], size_t size,
for (unsigned int i = 0; i < size; i++)
if (scales_tbl[i][0] == scale_val &&
scales_tbl[i][1] == scale_val2)
- return (int)i;
+ return i;
return -EINVAL;
}
@@ -553,7 +552,7 @@ static int pac1921_update_gain_from_scale(struct pac1921_priv *priv,
if (ret < 0)
return ret;
- return pac1921_update_gain(priv, &priv->dv_gain, (u8)ret,
+ return pac1921_update_gain(priv, &priv->dv_gain, ret,
PAC1921_GAIN_DV_GAIN_MASK);
case PAC1921_CHAN_VSENSE:
ret = pac1921_lookup_scale(pac1921_vsense_scales,
@@ -562,7 +561,7 @@ static int pac1921_update_gain_from_scale(struct pac1921_priv *priv,
if (ret < 0)
return ret;
- return pac1921_update_gain(priv, &priv->di_gain, (u8)ret,
+ return pac1921_update_gain(priv, &priv->di_gain, ret,
PAC1921_GAIN_DI_GAIN_MASK);
case PAC1921_CHAN_CURRENT:
ret = pac1921_lookup_scale(priv->current_scales,
@@ -571,7 +570,7 @@ static int pac1921_update_gain_from_scale(struct pac1921_priv *priv,
if (ret < 0)
return ret;
- return pac1921_update_gain(priv, &priv->di_gain, (u8)ret,
+ return pac1921_update_gain(priv, &priv->di_gain, ret,
PAC1921_GAIN_DI_GAIN_MASK);
default:
return -EINVAL;
@@ -586,7 +585,7 @@ static int pac1921_lookup_int_num_samples(int num_samples)
{
for (unsigned int i = 0; i < ARRAY_SIZE(pac1921_int_num_samples); i++)
if (pac1921_int_num_samples[i] == num_samples)
- return (int)i;
+ return i;
return -EINVAL;
}
@@ -607,7 +606,7 @@ static int pac1921_update_int_num_samples(struct pac1921_priv *priv,
if (ret < 0)
return ret;
- n_samples = (u8)ret;
+ n_samples = ret;
if (priv->n_samples == n_samples)
return 0;
@@ -700,7 +699,8 @@ static int pac1921_read_event_config(struct iio_dev *indio_dev,
static int pac1921_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct pac1921_priv *priv = iio_priv(indio_dev);
u8 ovf_bit;
@@ -770,7 +770,7 @@ static ssize_t pac1921_read_shunt_resistor(struct iio_dev *indio_dev,
guard(mutex)(&priv->lock);
- vals[0] = (int)priv->rshunt_uohm;
+ vals[0] = priv->rshunt_uohm;
vals[1] = MICRO;
return iio_format_value(buf, IIO_VAL_FRACTIONAL, 1, vals);
@@ -793,13 +793,13 @@ static ssize_t pac1921_write_shunt_resistor(struct iio_dev *indio_dev,
if (ret)
return ret;
- rshunt_uohm = (u32)val * MICRO + (u32)val_fract;
+ rshunt_uohm = val * MICRO + val_fract;
if (rshunt_uohm == 0 || rshunt_uohm > INT_MAX)
return -EINVAL;
guard(mutex)(&priv->lock);
- priv->rshunt_uohm = (u32)rshunt_uohm;
+ priv->rshunt_uohm = rshunt_uohm;
pac1921_calc_current_scales(priv);
@@ -1077,7 +1077,7 @@ static int pac1921_init(struct pac1921_priv *priv)
/*
* Init control register:
* - VPower free run integration mode
- * - OUT pin full scale range: 3V (HW detault)
+ * - OUT pin full scale range: 3V (HW default)
* - no timeout, no sleep, no sleep override, no recalc (HW defaults)
*/
val = FIELD_PREP(PAC1921_CONTROL_MXSL_MASK,
@@ -1168,10 +1168,12 @@ static int pac1921_probe(struct i2c_client *client)
priv->regmap = devm_regmap_init_i2c(client, &pac1921_regmap_config);
if (IS_ERR(priv->regmap))
- return dev_err_probe(dev, (int)PTR_ERR(priv->regmap),
+ return dev_err_probe(dev, PTR_ERR(priv->regmap),
"Cannot initialize register map\n");
- devm_mutex_init(dev, &priv->lock);
+ ret = devm_mutex_init(dev, &priv->lock);
+ if (ret)
+ return ret;
priv->dv_gain = PAC1921_DEFAULT_DV_GAIN;
priv->di_gain = PAC1921_DEFAULT_DI_GAIN;
@@ -1191,7 +1193,7 @@ static int pac1921_probe(struct i2c_client *client)
priv->vdd = devm_regulator_get(dev, "vdd");
if (IS_ERR(priv->vdd))
- return dev_err_probe(dev, (int)PTR_ERR(priv->vdd),
+ return dev_err_probe(dev, PTR_ERR(priv->vdd),
"Cannot get vdd regulator\n");
ret = regulator_enable(priv->vdd);
diff --git a/drivers/iio/adc/pac1934.c b/drivers/iio/adc/pac1934.c
index 7ef249d83286..20802b7f49ea 100644
--- a/drivers/iio/adc/pac1934.c
+++ b/drivers/iio/adc/pac1934.c
@@ -1507,7 +1507,7 @@ static int pac1934_probe(struct i2c_client *client)
indio_dev->name = pac1934_chip_config[ret].name;
}
- if (acpi_match_device(dev->driver->acpi_match_table, dev))
+ if (is_acpi_device_node(dev_fwnode(dev)))
ret = pac1934_acpi_parse_channel_config(client, info);
else
/*
diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c
index 203cbbc70719..d283ee8fb1d2 100644
--- a/drivers/iio/adc/palmas_gpadc.c
+++ b/drivers/iio/adc/palmas_gpadc.c
@@ -456,7 +456,7 @@ static int palmas_gpadc_get_calibrated_code(struct palmas_gpadc *adc,
* raw high threshold = (ideal threshold + INL) * gain error + offset error
*
* The gain error include both gain error, as specified in the datasheet, and
- * the gain error drift. These paramenters vary depending on device and whether
+ * the gain error drift. These parameters vary depending on device and whether
* the channel is calibrated (trimmed) or not.
*/
static int palmas_gpadc_threshold_with_tolerance(int val, const int INL,
@@ -676,7 +676,7 @@ static int palmas_gpadc_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct palmas_gpadc *adc = iio_priv(indio_dev);
int adc_chan = chan->channel;
diff --git a/drivers/iio/adc/qcom-pm8xxx-xoadc.c b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
index 9e1112f5acc6..31f88cf7f7f1 100644
--- a/drivers/iio/adc/qcom-pm8xxx-xoadc.c
+++ b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
@@ -821,7 +821,6 @@ static int pm8xxx_xoadc_parse_channel(struct device *dev,
static int pm8xxx_xoadc_parse_channels(struct pm8xxx_xoadc *adc)
{
- struct fwnode_handle *child;
struct pm8xxx_chan_info *ch;
int ret;
int i;
@@ -844,16 +843,15 @@ static int pm8xxx_xoadc_parse_channels(struct pm8xxx_xoadc *adc)
return -ENOMEM;
i = 0;
- device_for_each_child_node(adc->dev, child) {
+ device_for_each_child_node_scoped(adc->dev, child) {
ch = &adc->chans[i];
ret = pm8xxx_xoadc_parse_channel(adc->dev, child,
adc->variant->channels,
&adc->iio_chans[i],
ch);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
+
i++;
}
@@ -1016,7 +1014,7 @@ static struct platform_driver pm8xxx_xoadc_driver = {
.of_match_table = pm8xxx_xoadc_id_table,
},
.probe = pm8xxx_xoadc_probe,
- .remove_new = pm8xxx_xoadc_remove,
+ .remove = pm8xxx_xoadc_remove,
};
module_platform_driver(pm8xxx_xoadc_driver);
diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c
index 9b69f40beed8..af3c2f659f5e 100644
--- a/drivers/iio/adc/qcom-spmi-adc5.c
+++ b/drivers/iio/adc/qcom-spmi-adc5.c
@@ -830,7 +830,7 @@ static int adc5_get_fw_data(struct adc5_chip *adc)
adc->nchannels = device_get_child_node_count(adc->dev);
if (!adc->nchannels)
- return -EINVAL;
+ return dev_err_probe(adc->dev, -EINVAL, "no channels defined\n");
adc->iio_chans = devm_kcalloc(adc->dev, adc->nchannels,
sizeof(*adc->iio_chans), GFP_KERNEL);
@@ -903,7 +903,7 @@ static int adc5_probe(struct platform_device *pdev)
ret = adc5_get_fw_data(adc);
if (ret)
- return dev_err_probe(dev, ret, "adc get dt data failed\n");
+ return ret;
irq_eoc = platform_get_irq(pdev, 0);
if (irq_eoc < 0) {
diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c
index f5c6f1f27b2c..00a7f0982025 100644
--- a/drivers/iio/adc/qcom-spmi-vadc.c
+++ b/drivers/iio/adc/qcom-spmi-vadc.c
@@ -754,7 +754,6 @@ static int vadc_get_fw_data(struct vadc_priv *vadc)
const struct vadc_channels *vadc_chan;
struct iio_chan_spec *iio_chan;
struct vadc_channel_prop prop;
- struct fwnode_handle *child;
unsigned int index = 0;
int ret;
@@ -774,12 +773,10 @@ static int vadc_get_fw_data(struct vadc_priv *vadc)
iio_chan = vadc->iio_chans;
- device_for_each_child_node(vadc->dev, child) {
+ device_for_each_child_node_scoped(vadc->dev, child) {
ret = vadc_get_fw_channel_data(vadc->dev, &prop, child);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
prop.scale_fn_type = vadc_chans[prop.channel].scale_fn_type;
vadc->chan_props[index] = prop;
diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c
index 15a21d2860e7..11170b5852d1 100644
--- a/drivers/iio/adc/rcar-gyroadc.c
+++ b/drivers/iio/adc/rcar-gyroadc.c
@@ -592,7 +592,7 @@ static const struct dev_pm_ops rcar_gyroadc_pm_ops = {
static struct platform_driver rcar_gyroadc_driver = {
.probe = rcar_gyroadc_probe,
- .remove_new = rcar_gyroadc_remove,
+ .remove = rcar_gyroadc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = rcar_gyroadc_match,
diff --git a/drivers/iio/adc/rn5t618-adc.c b/drivers/iio/adc/rn5t618-adc.c
index ce5f3011fe00..b33536157adc 100644
--- a/drivers/iio/adc/rn5t618-adc.c
+++ b/drivers/iio/adc/rn5t618-adc.c
@@ -185,7 +185,7 @@ static const struct iio_chan_spec rn5t618_adc_iio_channels[] = {
RN5T618_ADC_CHANNEL(AIN0, IIO_VOLTAGE, "AIN0")
};
-static struct iio_map rn5t618_maps[] = {
+static const struct iio_map rn5t618_maps[] = {
IIO_MAP("VADP", "rn5t618-power", "vadp"),
IIO_MAP("VUSB", "rn5t618-power", "vusb"),
{ /* sentinel */ }
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
index 616dd729666a..2201ee9987ae 100644
--- a/drivers/iio/adc/stm32-adc-core.c
+++ b/drivers/iio/adc/stm32-adc-core.c
@@ -906,7 +906,7 @@ MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
static struct platform_driver stm32_adc_driver = {
.probe = stm32_adc_probe,
- .remove_new = stm32_adc_remove,
+ .remove = stm32_adc_remove,
.driver = {
.name = "stm32-adc-core",
.of_match_table = stm32_adc_of_match,
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index 32ca26ed59f7..9d3b23efcc06 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -2644,7 +2644,7 @@ MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
static struct platform_driver stm32_adc_driver = {
.probe = stm32_adc_probe,
- .remove_new = stm32_adc_remove,
+ .remove = stm32_adc_remove,
.driver = {
.name = "stm32-adc",
.of_match_table = stm32_adc_of_match,
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index 2037f73426d4..c2d4f5339cd4 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -1890,7 +1890,7 @@ static struct platform_driver stm32_dfsdm_adc_driver = {
.pm = pm_sleep_ptr(&stm32_dfsdm_adc_pm_ops),
},
.probe = stm32_dfsdm_adc_probe,
- .remove_new = stm32_dfsdm_adc_remove,
+ .remove = stm32_dfsdm_adc_remove,
};
module_platform_driver(stm32_dfsdm_adc_driver);
diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c
index bef59fcc0d80..041dc9ebc048 100644
--- a/drivers/iio/adc/stm32-dfsdm-core.c
+++ b/drivers/iio/adc/stm32-dfsdm-core.c
@@ -506,7 +506,7 @@ static const struct dev_pm_ops stm32_dfsdm_core_pm_ops = {
static struct platform_driver stm32_dfsdm_driver = {
.probe = stm32_dfsdm_probe,
- .remove_new = stm32_dfsdm_core_remove,
+ .remove = stm32_dfsdm_core_remove,
.driver = {
.name = "stm32-dfsdm",
.of_match_table = stm32_dfsdm_of_match,
diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c
index 6a893d484cf7..136b8d9c294f 100644
--- a/drivers/iio/adc/sun20i-gpadc-iio.c
+++ b/drivers/iio/adc/sun20i-gpadc-iio.c
@@ -155,7 +155,6 @@ static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
unsigned int channel;
int num_channels, i, ret;
struct iio_chan_spec *channels;
- struct fwnode_handle *node;
num_channels = device_get_child_node_count(dev);
if (num_channels == 0)
@@ -167,12 +166,10 @@ static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
return -ENOMEM;
i = 0;
- device_for_each_child_node(dev, node) {
+ device_for_each_child_node_scoped(dev, node) {
ret = fwnode_property_read_u32(node, "reg", &channel);
- if (ret) {
- fwnode_handle_put(node);
+ if (ret)
return dev_err_probe(dev, ret, "invalid channel number\n");
- }
channels[i].type = IIO_VOLTAGE;
channels[i].indexed = 1;
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index 100ecced5fc1..8b27458dcd66 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -114,11 +114,8 @@ struct sun4i_gpadc_iio {
.datasheet_name = _name, \
}
-static struct iio_map sun4i_gpadc_hwmon_maps[] = {
- {
- .adc_channel_label = "temp_adc",
- .consumer_dev_name = "iio_hwmon.0",
- },
+static const struct iio_map sun4i_gpadc_hwmon_maps[] = {
+ IIO_MAP("temp_adc", "iio_hwmon.0", NULL),
{ /* sentinel */ },
};
@@ -700,7 +697,7 @@ static struct platform_driver sun4i_gpadc_driver = {
},
.id_table = sun4i_gpadc_id,
.probe = sun4i_gpadc_probe,
- .remove_new = sun4i_gpadc_remove,
+ .remove = sun4i_gpadc_remove,
};
MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id);
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index 6d1bc9659946..47fe8e16aee4 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -806,7 +806,7 @@ static int ads1015_disable_event_config(struct ads1015_data *data,
static int ads1015_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct ads1015_data *data = iio_priv(indio_dev);
int ret;
@@ -1032,8 +1032,7 @@ static int ads1015_probe(struct i2c_client *client)
}
if (client->irq && chip->has_comparator) {
- unsigned long irq_trig =
- irqd_get_trigger_type(irq_get_irq_data(client->irq));
+ unsigned long irq_trig = irq_get_trigger_type(client->irq);
unsigned int cfg_comp_mask = ADS1015_CFG_COMP_QUE_MASK |
ADS1015_CFG_COMP_LAT_MASK | ADS1015_CFG_COMP_POL_MASK;
unsigned int cfg_comp =
diff --git a/drivers/iio/adc/ti-ads1119.c b/drivers/iio/adc/ti-ads1119.c
index 1c7606375149..e9d9d4d46d38 100644
--- a/drivers/iio/adc/ti-ads1119.c
+++ b/drivers/iio/adc/ti-ads1119.c
@@ -804,7 +804,7 @@ static const struct of_device_id __maybe_unused ads1119_of_match[] = {
MODULE_DEVICE_TABLE(of, ads1119_of_match);
static const struct i2c_device_id ads1119_id[] = {
- { "ads1119", 0 },
+ { "ads1119" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ads1119_id);
diff --git a/drivers/iio/adc/ti-ads1298.c b/drivers/iio/adc/ti-ads1298.c
index 0f9f75baaebb..36d43495f603 100644
--- a/drivers/iio/adc/ti-ads1298.c
+++ b/drivers/iio/adc/ti-ads1298.c
@@ -294,7 +294,7 @@ static int ads1298_get_scale(struct ads1298_private *priv,
if (ret)
return ret;
- /* Refererence in millivolts */
+ /* Reference in millivolts */
*val = regval & ADS1298_MASK_CONFIG3_VREF_4V ? 4000 : 2400;
}
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index 426e3c9f88a1..fe1509d3b1e7 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -494,7 +494,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
/*
* We check the complete FIFO. We programmed just one entry but in case
* something went wrong we left empty handed (-EAGAIN previously) and
- * then the value apeared somehow in the FIFO we would have two entries.
+ * then the value appeared somehow in the FIFO we would have two entries.
* Therefore we read every item and keep only the latest version of the
* requested channel.
*/
@@ -740,12 +740,12 @@ MODULE_DEVICE_TABLE(of, ti_adc_dt_ids);
static struct platform_driver tiadc_driver = {
.driver = {
- .name = "TI-am335x-adc",
- .pm = pm_sleep_ptr(&tiadc_pm_ops),
+ .name = "TI-am335x-adc",
+ .pm = pm_sleep_ptr(&tiadc_pm_ops),
.of_match_table = ti_adc_dt_ids,
},
- .probe = tiadc_probe,
- .remove_new = tiadc_remove,
+ .probe = tiadc_probe,
+ .remove = tiadc_remove,
};
module_platform_driver(tiadc_driver);
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index 0253064fadec..0ea51ddeaa0a 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -248,7 +248,7 @@ static const struct s16_fract twl4030_divider_ratios[16] = {
{15, 100}, /* CHANNEL 11 */
{1, 4}, /* CHANNEL 12 */
{1, 1}, /* CHANNEL 13 Reserved channels */
- {1, 1}, /* CHANNEL 14 Reseved channels */
+ {1, 1}, /* CHANNEL 14 Reserved channels */
{5, 11}, /* CHANNEL 15 */
};
@@ -914,7 +914,7 @@ MODULE_DEVICE_TABLE(of, twl_madc_of_match);
static struct platform_driver twl4030_madc_driver = {
.probe = twl4030_madc_probe,
- .remove_new = twl4030_madc_remove,
+ .remove = twl4030_madc_remove,
.driver = {
.name = "twl4030_madc",
.of_match_table = twl_madc_of_match,
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
index 6a3db2bce460..ef7430e6877d 100644
--- a/drivers/iio/adc/twl6030-gpadc.c
+++ b/drivers/iio/adc/twl6030-gpadc.c
@@ -1003,7 +1003,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(twl6030_gpadc_pm_ops, twl6030_gpadc_suspend,
static struct platform_driver twl6030_gpadc_driver = {
.probe = twl6030_gpadc_probe,
- .remove_new = twl6030_gpadc_remove,
+ .remove = twl6030_gpadc_remove,
.driver = {
.name = DRIVER_NAME,
.pm = pm_sleep_ptr(&twl6030_gpadc_pm_ops),
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index 5afd2feb8c3d..4d83c12975c5 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -972,7 +972,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(vf610_adc_pm_ops, vf610_adc_suspend,
static struct platform_driver vf610_adc_driver = {
.probe = vf610_adc_probe,
- .remove_new = vf610_adc_remove,
+ .remove = vf610_adc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = vf610_adc_match,
diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
index ebc583b07e0c..76dd0343f5f7 100644
--- a/drivers/iio/adc/xilinx-ams.c
+++ b/drivers/iio/adc/xilinx-ams.c
@@ -905,7 +905,7 @@ static int ams_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct ams *ams = iio_priv(indio_dev);
unsigned int alarm;
diff --git a/drivers/iio/adc/xilinx-xadc-events.c b/drivers/iio/adc/xilinx-xadc-events.c
index 1bd375fb10e0..c188d3dcab48 100644
--- a/drivers/iio/adc/xilinx-xadc-events.c
+++ b/drivers/iio/adc/xilinx-xadc-events.c
@@ -121,7 +121,7 @@ int xadc_read_event_config(struct iio_dev *indio_dev,
int xadc_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
unsigned int alarm = xadc_get_alarm_mask(chan);
struct xadc *xadc = iio_priv(indio_dev);
@@ -220,7 +220,7 @@ int xadc_write_event_value(struct iio_dev *indio_dev,
/*
* Since we store the hysteresis as relative (to the threshold)
* value, but the hardware expects an absolute value we need to
- * recalcualte this value whenever the hysteresis or the
+ * recalculate this value whenever the hysteresis or the
* threshold changes.
*/
if (xadc->threshold[offset] < xadc->temp_hysteresis)
diff --git a/drivers/iio/adc/xilinx-xadc.h b/drivers/iio/adc/xilinx-xadc.h
index 3036f4d613ff..b4d9d4683117 100644
--- a/drivers/iio/adc/xilinx-xadc.h
+++ b/drivers/iio/adc/xilinx-xadc.h
@@ -25,7 +25,7 @@ int xadc_read_event_config(struct iio_dev *indio_dev,
enum iio_event_direction dir);
int xadc_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state);
+ enum iio_event_direction dir, bool state);
int xadc_read_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, enum iio_event_info info,
diff --git a/drivers/iio/addac/ad74115.c b/drivers/iio/addac/ad74115.c
index 3ee0dd5537c1..a7e480f2472d 100644
--- a/drivers/iio/addac/ad74115.c
+++ b/drivers/iio/addac/ad74115.c
@@ -191,7 +191,7 @@ enum ad74115_gpio_mode {
};
struct ad74115_channels {
- struct iio_chan_spec *channels;
+ const struct iio_chan_spec *channels;
unsigned int num_channels;
};
@@ -1295,46 +1295,46 @@ static const struct iio_info ad74115_info = {
_AD74115_ADC_CHANNEL(_type, index, BIT(IIO_CHAN_INFO_SCALE) \
| BIT(IIO_CHAN_INFO_OFFSET))
-static struct iio_chan_spec ad74115_voltage_input_channels[] = {
+static const struct iio_chan_spec ad74115_voltage_input_channels[] = {
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_voltage_output_channels[] = {
+static const struct iio_chan_spec ad74115_voltage_output_channels[] = {
AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_MAIN),
AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_current_input_channels[] = {
+static const struct iio_chan_spec ad74115_current_input_channels[] = {
AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_current_output_channels[] = {
+static const struct iio_chan_spec ad74115_current_output_channels[] = {
AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_2_wire_resistance_input_channels[] = {
+static const struct iio_chan_spec ad74115_2_wire_resistance_input_channels[] = {
_AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1,
BIT(IIO_CHAN_INFO_PROCESSED)),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_3_4_wire_resistance_input_channels[] = {
+static const struct iio_chan_spec ad74115_3_4_wire_resistance_input_channels[] = {
AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_digital_input_logic_channels[] = {
+static const struct iio_chan_spec ad74115_digital_input_logic_channels[] = {
AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_digital_input_loop_channels[] = {
+static const struct iio_chan_spec ad74115_digital_input_loop_channels[] = {
AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN),
AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c
index 69c586525d21..daea2bde7acf 100644
--- a/drivers/iio/addac/ad74413r.c
+++ b/drivers/iio/addac/ad74413r.c
@@ -6,9 +6,11 @@
#include <linux/unaligned.h>
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/crc8.h>
#include <linux/device.h>
#include <linux/err.h>
+#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
@@ -45,8 +47,8 @@ struct ad74413r_channel_config {
};
struct ad74413r_channels {
- struct iio_chan_spec *channels;
- unsigned int num_channels;
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
};
struct ad74413r_state {
@@ -59,7 +61,7 @@ struct ad74413r_state {
unsigned int num_gpo_gpios;
unsigned int num_comparator_gpios;
u32 sense_resistor_ohms;
-
+ int refin_reg_uv;
/*
* Synchronize consecutive operations when doing a one-shot
* conversion and when updating the ADC samples SPI message.
@@ -68,11 +70,9 @@ struct ad74413r_state {
const struct ad74413r_chip_info *chip_info;
struct spi_device *spi;
- struct regulator *refin_reg;
struct regmap *regmap;
struct device *dev;
struct iio_trigger *trig;
- struct gpio_desc *reset_gpio;
size_t adc_active_channels;
struct spi_message adc_samples_msg;
@@ -407,12 +407,16 @@ static int ad74413r_gpio_set_comp_config(struct gpio_chip *chip,
static int ad74413r_reset(struct ad74413r_state *st)
{
+ struct gpio_desc *reset_gpio;
int ret;
- if (st->reset_gpio) {
- gpiod_set_value_cansleep(st->reset_gpio, 1);
+ reset_gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(reset_gpio))
+ return PTR_ERR(reset_gpio);
+
+ if (reset_gpio) {
fsleep(50);
- gpiod_set_value_cansleep(st->reset_gpio, 0);
+ gpiod_set_value_cansleep(reset_gpio, 0);
return 0;
}
@@ -660,7 +664,7 @@ static int ad74413r_get_output_voltage_scale(struct ad74413r_state *st,
static int ad74413r_get_output_current_scale(struct ad74413r_state *st,
int *val, int *val2)
{
- *val = regulator_get_voltage(st->refin_reg);
+ *val = st->refin_reg_uv;
*val2 = st->sense_resistor_ohms * AD74413R_DAC_CODE_MAX * 1000;
return IIO_VAL_FRACTIONAL;
@@ -861,19 +865,12 @@ static int ad74413r_get_single_adc_result(struct iio_dev *indio_dev,
unsigned int channel, int *val)
{
struct ad74413r_state *st = iio_priv(indio_dev);
- int ret;
-
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
-
- mutex_lock(&st->lock);
- ret = _ad74413r_get_single_adc_result(st, channel, val);
- mutex_unlock(&st->lock);
-
- iio_device_release_direct_mode(indio_dev);
- return ret;
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ guard(mutex)(&st->lock);
+ return _ad74413r_get_single_adc_result(st, channel, val);
+ }
+ unreachable();
}
static void ad74413r_adc_to_resistance_result(int adc_result, int *val)
@@ -895,7 +892,7 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
unsigned int channel;
int ret = -EINVAL;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
spi_message_init(&st->adc_samples_msg);
st->adc_active_channels = 0;
@@ -903,11 +900,11 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
for_each_clear_bit(channel, active_scan_mask, AD74413R_CHANNEL_MAX) {
ret = ad74413r_set_adc_channel_enable(st, channel, false);
if (ret)
- goto out;
+ return ret;
}
if (*active_scan_mask == 0)
- goto out;
+ return ret;
/*
* The read select register is used to select which register's value
@@ -925,7 +922,7 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
for_each_set_bit(channel, active_scan_mask, AD74413R_CHANNEL_MAX) {
ret = ad74413r_set_adc_channel_enable(st, channel, true);
if (ret)
- goto out;
+ return ret;
st->adc_active_channels++;
@@ -956,11 +953,7 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
xfer->cs_change = 0;
spi_message_add_tail(xfer, &st->adc_samples_msg);
-
-out:
- mutex_unlock(&st->lock);
-
- return ret;
+ return 0;
}
static int ad74413r_buffer_postenable(struct iio_dev *indio_dev)
@@ -1138,34 +1131,34 @@ static const struct iio_info ad74413r_info = {
AD74413R_ADC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE) \
| BIT(IIO_CHAN_INFO_OFFSET))
-static struct iio_chan_spec ad74413r_voltage_output_channels[] = {
+static const struct iio_chan_spec ad74413r_voltage_output_channels[] = {
AD74413R_DAC_CHANNEL(IIO_VOLTAGE, BIT(IIO_CHAN_INFO_SCALE)),
AD74413R_ADC_CURRENT_CHANNEL,
};
-static struct iio_chan_spec ad74413r_current_output_channels[] = {
+static const struct iio_chan_spec ad74413r_current_output_channels[] = {
AD74413R_DAC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE)),
AD74413R_ADC_VOLTAGE_CHANNEL,
};
-static struct iio_chan_spec ad74413r_voltage_input_channels[] = {
+static const struct iio_chan_spec ad74413r_voltage_input_channels[] = {
AD74413R_ADC_VOLTAGE_CHANNEL,
};
-static struct iio_chan_spec ad74413r_current_input_channels[] = {
+static const struct iio_chan_spec ad74413r_current_input_channels[] = {
AD74413R_ADC_CURRENT_CHANNEL,
};
-static struct iio_chan_spec ad74413r_current_input_loop_channels[] = {
+static const struct iio_chan_spec ad74413r_current_input_loop_channels[] = {
AD74413R_DAC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE)),
AD74413R_ADC_CURRENT_CHANNEL,
};
-static struct iio_chan_spec ad74413r_resistance_input_channels[] = {
+static const struct iio_chan_spec ad74413r_resistance_input_channels[] = {
AD74413R_ADC_CHANNEL(IIO_RESISTANCE, BIT(IIO_CHAN_INFO_PROCESSED)),
};
-static struct iio_chan_spec ad74413r_digital_input_channels[] = {
+static const struct iio_chan_spec ad74413r_digital_input_channels[] = {
AD74413R_ADC_VOLTAGE_CHANNEL,
};
@@ -1270,7 +1263,8 @@ static int ad74413r_setup_channels(struct iio_dev *indio_dev)
{
struct ad74413r_state *st = iio_priv(indio_dev);
struct ad74413r_channel_config *config;
- struct iio_chan_spec *channels, *chans;
+ const struct iio_chan_spec *chans;
+ struct iio_chan_spec *channels;
unsigned int i, num_chans, chan_i;
int ret;
@@ -1346,11 +1340,6 @@ static int ad74413r_setup_gpios(struct ad74413r_state *st)
return 0;
}
-static void ad74413r_regulator_disable(void *regulator)
-{
- regulator_disable(regulator);
-}
-
static int ad74413r_probe(struct spi_device *spi)
{
struct ad74413r_state *st;
@@ -1369,7 +1358,10 @@ static int ad74413r_probe(struct spi_device *spi)
if (!st->chip_info)
return -EINVAL;
- mutex_init(&st->lock);
+ ret = devm_mutex_init(st->dev, &st->lock);
+ if (ret)
+ return ret;
+
init_completion(&st->adc_data_completion);
st->regmap = devm_regmap_init(st->dev, NULL, st,
@@ -1377,23 +1369,11 @@ static int ad74413r_probe(struct spi_device *spi)
if (IS_ERR(st->regmap))
return PTR_ERR(st->regmap);
- st->reset_gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR(st->reset_gpio))
- return PTR_ERR(st->reset_gpio);
-
- st->refin_reg = devm_regulator_get(st->dev, "refin");
- if (IS_ERR(st->refin_reg))
- return dev_err_probe(st->dev, PTR_ERR(st->refin_reg),
- "Failed to get refin regulator\n");
-
- ret = regulator_enable(st->refin_reg);
- if (ret)
- return ret;
-
- ret = devm_add_action_or_reset(st->dev, ad74413r_regulator_disable,
- st->refin_reg);
- if (ret)
- return ret;
+ ret = devm_regulator_get_enable_read_voltage(st->dev, "refin");
+ if (ret < 0)
+ return dev_err_probe(st->dev, ret,
+ "Failed to get refin regulator voltage\n");
+ st->refin_reg_uv = ret;
st->sense_resistor_ohms = 100000000;
device_property_read_u32(st->dev, "shunt-resistor-micro-ohms",
diff --git a/drivers/iio/cdc/ad7150.c b/drivers/iio/cdc/ad7150.c
index 4c03b9e834b8..e64a41bae32c 100644
--- a/drivers/iio/cdc/ad7150.c
+++ b/drivers/iio/cdc/ad7150.c
@@ -232,7 +232,7 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev,
static int ad7150_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct ad7150_chip_info *chip = iio_priv(indio_dev);
int ret = 0;
diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig
index 6c87223f58d9..330fe0af946f 100644
--- a/drivers/iio/chemical/Kconfig
+++ b/drivers/iio/chemical/Kconfig
@@ -50,6 +50,8 @@ config BME680
select REGMAP
select BME680_I2C if I2C
select BME680_SPI if SPI
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Bosch Sensortec BME680 sensor with
temperature, pressure, humidity and gas sensing capability.
diff --git a/drivers/iio/chemical/bme680.h b/drivers/iio/chemical/bme680.h
index b2c547ac8d34..00ab89b3138b 100644
--- a/drivers/iio/chemical/bme680.h
+++ b/drivers/iio/chemical/bme680.h
@@ -2,6 +2,8 @@
#ifndef BME680_H_
#define BME680_H_
+#include <linux/regmap.h>
+
#define BME680_REG_CHIP_ID 0xD0
#define BME680_CHIP_ID_VAL 0x61
#define BME680_REG_SOFT_RESET 0xE0
@@ -25,8 +27,6 @@
#define BME680_OSRS_TEMP_MASK GENMASK(7, 5)
#define BME680_OSRS_PRESS_MASK GENMASK(4, 2)
#define BME680_MODE_MASK GENMASK(1, 0)
-#define BME680_MODE_FORCED 1
-#define BME680_MODE_SLEEP 0
#define BME680_REG_CONFIG 0x75
#define BME680_FILTER_MASK GENMASK(4, 2)
@@ -42,6 +42,7 @@
#define BME680_RHRANGE_MASK GENMASK(5, 4)
#define BME680_REG_RES_HEAT_VAL 0x00
#define BME680_RSERROR_MASK GENMASK(7, 4)
+#define BME680_REG_IDAC_HEAT_0 0x50
#define BME680_REG_RES_HEAT_0 0x5A
#define BME680_REG_GAS_WAIT_0 0x64
#define BME680_ADC_GAS_RES GENMASK(15, 6)
@@ -63,7 +64,11 @@
#define BME680_MEAS_TRIM_MASK GENMASK(24, 4)
-#define BME680_STARTUP_TIME_US 5000
+/* Datasheet Section 1.1, Table 1 */
+#define BME680_STARTUP_TIME_US 2000
+
+#define BME680_NUM_CHANNELS 4
+#define BME680_NUM_BULK_READ_REGS 15
/* Calibration Parameters */
#define BME680_T2_LSB_REG 0x8A
diff --git a/drivers/iio/chemical/bme680_core.c b/drivers/iio/chemical/bme680_core.c
index 0b96534c6867..9783953e64e0 100644
--- a/drivers/iio/chemical/bme680_core.c
+++ b/drivers/iio/chemical/bme680_core.c
@@ -16,8 +16,11 @@
#include <linux/module.h>
#include <linux/regmap.h>
+#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#include <linux/unaligned.h>
@@ -95,6 +98,19 @@ struct bme680_calib {
s8 range_sw_err;
};
+/* values of CTRL_MEAS register */
+enum bme680_op_mode {
+ BME680_MODE_SLEEP = 0,
+ BME680_MODE_FORCED = 1,
+};
+
+enum bme680_scan {
+ BME680_TEMP,
+ BME680_PRESS,
+ BME680_HUMID,
+ BME680_GAS,
+};
+
struct bme680_data {
struct regmap *regmap;
struct bme680_calib bme680;
@@ -102,11 +118,17 @@ struct bme680_data {
u8 oversampling_temp;
u8 oversampling_press;
u8 oversampling_humid;
+ u8 preheat_curr_mA;
u16 heater_dur;
u16 heater_temp;
+ struct {
+ s32 chan[4];
+ aligned_s64 ts;
+ } scan;
+
union {
- u8 buf[3];
+ u8 buf[BME680_NUM_BULK_READ_REGS];
unsigned int check;
__be16 be16;
u8 bme680_cal_buf_1[BME680_CALIB_RANGE_1_LEN];
@@ -138,22 +160,66 @@ EXPORT_SYMBOL_NS(bme680_regmap_config, IIO_BME680);
static const struct iio_chan_spec bme680_channels[] = {
{
.type = IIO_TEMP,
+ /* PROCESSED maintained for ABI backwards compatibility */
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
},
{
.type = IIO_PRESSURE,
+ /* PROCESSED maintained for ABI backwards compatibility */
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
},
{
.type = IIO_HUMIDITYRELATIVE,
+ /* PROCESSED maintained for ABI backwards compatibility */
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 2,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
},
{
.type = IIO_RESISTANCE,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .scan_index = 3,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ {
+ .type = IIO_CURRENT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .output = 1,
+ .scan_index = -1,
},
};
@@ -224,7 +290,7 @@ static int bme680_read_calib(struct bme680_data *data,
calib->res_heat_val = data->bme680_cal_buf_3[RES_HEAT_VAL];
calib->res_heat_range = FIELD_GET(BME680_RHRANGE_MASK,
- data->bme680_cal_buf_3[RES_HEAT_RANGE]);
+ data->bme680_cal_buf_3[RES_HEAT_RANGE]);
calib->range_sw_err = FIELD_GET(BME680_RSERROR_MASK,
data->bme680_cal_buf_3[RANGE_SW_ERR]);
@@ -438,19 +504,19 @@ static u32 bme680_compensate_gas(struct bme680_data *data, u16 gas_res_adc,
u32 calc_gas_res;
/* Look up table for the possible gas range values */
- static const u32 lookupTable[16] = {2147483647u, 2147483647u,
- 2147483647u, 2147483647u, 2147483647u,
- 2126008810u, 2147483647u, 2130303777u,
- 2147483647u, 2147483647u, 2143188679u,
- 2136746228u, 2147483647u, 2126008810u,
- 2147483647u, 2147483647u};
-
- var1 = ((1340 + (5 * (s64) calib->range_sw_err)) *
- ((s64) lookupTable[gas_range])) >> 16;
+ static const u32 lookup_table[16] = {
+ 2147483647u, 2147483647u, 2147483647u, 2147483647u,
+ 2147483647u, 2126008810u, 2147483647u, 2130303777u,
+ 2147483647u, 2147483647u, 2143188679u, 2136746228u,
+ 2147483647u, 2126008810u, 2147483647u, 2147483647u
+ };
+
+ var1 = ((1340LL + (5 * calib->range_sw_err)) *
+ (lookup_table[gas_range])) >> 16;
var2 = ((gas_res_adc << 15) - 16777216) + var1;
var3 = ((125000 << (15 - gas_range)) * var1) >> 9;
var3 += (var2 >> 1);
- calc_gas_res = div64_s64(var3, (s64) var2);
+ calc_gas_res = div64_s64(var3, (s64)var2);
return calc_gas_res;
}
@@ -468,7 +534,7 @@ static u8 bme680_calc_heater_res(struct bme680_data *data, u16 temp)
if (temp > 400) /* Cap temperature */
temp = 400;
- var1 = (((s32) BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256;
+ var1 = (((s32)BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256;
var2 = (calib->par_gh1 + 784) * (((((calib->par_gh2 + 154009) *
temp * 5) / 100)
+ 3276800) / 10);
@@ -502,23 +568,22 @@ static u8 bme680_calc_heater_dur(u16 dur)
return durval;
}
-static int bme680_set_mode(struct bme680_data *data, bool mode)
+/* Taken from datasheet, section 5.3.3 */
+static u8 bme680_calc_heater_preheat_current(u8 curr)
+{
+ return 8 * curr - 1;
+}
+
+static int bme680_set_mode(struct bme680_data *data, enum bme680_op_mode mode)
{
struct device *dev = regmap_get_device(data->regmap);
int ret;
- if (mode) {
- ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
- BME680_MODE_MASK, BME680_MODE_FORCED);
- if (ret < 0)
- dev_err(dev, "failed to set forced mode\n");
-
- } else {
- ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
- BME680_MODE_MASK, BME680_MODE_SLEEP);
- if (ret < 0)
- dev_err(dev, "failed to set sleep mode\n");
-
+ ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
+ BME680_MODE_MASK, mode);
+ if (ret < 0) {
+ dev_err(dev, "failed to set ctrl_meas register\n");
+ return ret;
}
return ret;
@@ -546,7 +611,7 @@ static int bme680_wait_for_eoc(struct bme680_data *data)
data->oversampling_humid) * 1936) + (477 * 4) +
(477 * 5) + 1000 + (data->heater_dur * 1000);
- usleep_range(wait_eoc_us, wait_eoc_us + 100);
+ fsleep(wait_eoc_us);
ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &data->check);
if (ret) {
@@ -571,9 +636,8 @@ static int bme680_chip_config(struct bme680_data *data)
int ret;
u8 osrs;
- osrs = FIELD_PREP(
- BME680_OSRS_HUMIDITY_MASK,
- bme680_oversampling_to_reg(data->oversampling_humid));
+ osrs = FIELD_PREP(BME680_OSRS_HUMIDITY_MASK,
+ bme680_oversampling_to_reg(data->oversampling_humid));
/*
* Highly recommended to set oversampling of humidity before
* temperature/pressure oversampling.
@@ -587,8 +651,7 @@ static int bme680_chip_config(struct bme680_data *data)
/* IIR filter settings */
ret = regmap_update_bits(data->regmap, BME680_REG_CONFIG,
- BME680_FILTER_MASK,
- BME680_FILTER_COEFF_VAL);
+ BME680_FILTER_MASK, BME680_FILTER_COEFF_VAL);
if (ret < 0) {
dev_err(dev, "failed to write config register\n");
return ret;
@@ -609,14 +672,27 @@ static int bme680_chip_config(struct bme680_data *data)
return 0;
}
+static int bme680_preheat_curr_config(struct bme680_data *data, u8 val)
+{
+ struct device *dev = regmap_get_device(data->regmap);
+ u8 heatr_curr;
+ int ret;
+
+ heatr_curr = bme680_calc_heater_preheat_current(val);
+ ret = regmap_write(data->regmap, BME680_REG_IDAC_HEAT_0, heatr_curr);
+ if (ret < 0)
+ dev_err(dev, "failed to write idac_heat_0 register\n");
+
+ return ret;
+}
+
static int bme680_gas_config(struct bme680_data *data)
{
struct device *dev = regmap_get_device(data->regmap);
int ret;
u8 heatr_res, heatr_dur;
- /* Go to sleep */
- ret = bme680_set_mode(data, false);
+ ret = bme680_set_mode(data, BME680_MODE_SLEEP);
if (ret < 0)
return ret;
@@ -638,6 +714,10 @@ static int bme680_gas_config(struct bme680_data *data)
return ret;
}
+ ret = bme680_preheat_curr_config(data, data->preheat_curr_mA);
+ if (ret)
+ return ret;
+
/* Enable the gas sensor and select heater profile set-point 0 */
ret = regmap_update_bits(data->regmap, BME680_REG_CTRL_GAS_1,
BME680_RUN_GAS_MASK | BME680_NB_CONV_MASK,
@@ -649,23 +729,20 @@ static int bme680_gas_config(struct bme680_data *data)
return ret;
}
-static int bme680_read_temp(struct bme680_data *data, int *val)
+static int bme680_read_temp(struct bme680_data *data, s16 *comp_temp)
{
int ret;
u32 adc_temp;
- s16 comp_temp;
ret = bme680_read_temp_adc(data, &adc_temp);
if (ret)
return ret;
- comp_temp = bme680_compensate_temp(data, adc_temp);
- *val = comp_temp * 10; /* Centidegrees to millidegrees */
- return IIO_VAL_INT;
+ *comp_temp = bme680_compensate_temp(data, adc_temp);
+ return 0;
}
-static int bme680_read_press(struct bme680_data *data,
- int *val, int *val2)
+static int bme680_read_press(struct bme680_data *data, u32 *comp_press)
{
int ret;
u32 adc_press;
@@ -679,16 +756,14 @@ static int bme680_read_press(struct bme680_data *data,
if (ret)
return ret;
- *val = bme680_compensate_press(data, adc_press, t_fine);
- *val2 = 1000;
- return IIO_VAL_FRACTIONAL;
+ *comp_press = bme680_compensate_press(data, adc_press, t_fine);
+ return 0;
}
-static int bme680_read_humid(struct bme680_data *data,
- int *val, int *val2)
+static int bme680_read_humid(struct bme680_data *data, u32 *comp_humidity)
{
int ret;
- u32 adc_humidity, comp_humidity;
+ u32 adc_humidity;
s32 t_fine;
ret = bme680_get_t_fine(data, &t_fine);
@@ -699,15 +774,11 @@ static int bme680_read_humid(struct bme680_data *data,
if (ret)
return ret;
- comp_humidity = bme680_compensate_humid(data, adc_humidity, t_fine);
-
- *val = comp_humidity;
- *val2 = 1000;
- return IIO_VAL_FRACTIONAL;
+ *comp_humidity = bme680_compensate_humid(data, adc_humidity, t_fine);
+ return 0;
}
-static int bme680_read_gas(struct bme680_data *data,
- int *val)
+static int bme680_read_gas(struct bme680_data *data, int *comp_gas_res)
{
struct device *dev = regmap_get_device(data->regmap);
int ret;
@@ -742,9 +813,8 @@ static int bme680_read_gas(struct bme680_data *data,
}
gas_range = FIELD_GET(BME680_GAS_RANGE_MASK, gas_regs_val);
-
- *val = bme680_compensate_gas(data, adc_gas_res, gas_range);
- return IIO_VAL_INT;
+ *comp_gas_res = bme680_compensate_gas(data, adc_gas_res, gas_range);
+ return 0;
}
static int bme680_read_raw(struct iio_dev *indio_dev,
@@ -752,12 +822,12 @@ static int bme680_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct bme680_data *data = iio_priv(indio_dev);
- int ret;
+ int chan_val, ret;
+ s16 temp_chan_val;
guard(mutex)(&data->lock);
- /* set forced mode to trigger measurement */
- ret = bme680_set_mode(data, true);
+ ret = bme680_set_mode(data, BME680_MODE_FORCED);
if (ret < 0)
return ret;
@@ -769,13 +839,77 @@ static int bme680_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_PROCESSED:
switch (chan->type) {
case IIO_TEMP:
- return bme680_read_temp(data, val);
+ ret = bme680_read_temp(data, &temp_chan_val);
+ if (ret)
+ return ret;
+
+ *val = temp_chan_val * 10;
+ return IIO_VAL_INT;
case IIO_PRESSURE:
- return bme680_read_press(data, val, val2);
+ ret = bme680_read_press(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
case IIO_HUMIDITYRELATIVE:
- return bme680_read_humid(data, val, val2);
+ ret = bme680_read_humid(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
case IIO_RESISTANCE:
- return bme680_read_gas(data, val);
+ ret = bme680_read_gas(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_TEMP:
+ ret = bme680_read_temp(data, (s16 *)&chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ case IIO_PRESSURE:
+ ret = bme680_read_press(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ case IIO_HUMIDITYRELATIVE:
+ ret = bme680_read_humid(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val = 10;
+ return IIO_VAL_INT;
+ case IIO_PRESSURE:
+ *val = 1;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_HUMIDITYRELATIVE:
+ *val = 1;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
default:
return -EINVAL;
}
@@ -836,6 +970,15 @@ static int bme680_write_raw(struct iio_dev *indio_dev,
return bme680_chip_config(data);
}
+ case IIO_CHAN_INFO_PROCESSED:
+ {
+ switch (chan->type) {
+ case IIO_CURRENT:
+ return bme680_preheat_curr_config(data, (u8)val);
+ default:
+ return -EINVAL;
+ }
+ }
default:
return -EINVAL;
}
@@ -861,6 +1004,86 @@ static const struct iio_info bme680_info = {
.attrs = &bme680_attribute_group,
};
+static const unsigned long bme680_avail_scan_masks[] = {
+ BIT(BME680_GAS) | BIT(BME680_HUMID) | BIT(BME680_PRESS) | BIT(BME680_TEMP),
+ 0
+};
+
+static irqreturn_t bme680_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct bme680_data *data = iio_priv(indio_dev);
+ struct device *dev = regmap_get_device(data->regmap);
+ u32 adc_temp, adc_press, adc_humid;
+ u16 adc_gas_res, gas_regs_val;
+ u8 gas_range;
+ s32 t_fine;
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ ret = bme680_set_mode(data, BME680_MODE_FORCED);
+ if (ret < 0)
+ goto out;
+
+ ret = bme680_wait_for_eoc(data);
+ if (ret)
+ goto out;
+
+ ret = regmap_bulk_read(data->regmap, BME680_REG_MEAS_STAT_0,
+ data->buf, sizeof(data->buf));
+ if (ret) {
+ dev_err(dev, "failed to burst read sensor data\n");
+ goto out;
+ }
+ if (data->buf[0] & BME680_GAS_MEAS_BIT) {
+ dev_err(dev, "gas measurement incomplete\n");
+ goto out;
+ }
+
+ /* Temperature calculations */
+ adc_temp = FIELD_GET(BME680_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[5]));
+ if (adc_temp == BME680_MEAS_SKIPPED) {
+ dev_err(dev, "reading temperature skipped\n");
+ goto out;
+ }
+ data->scan.chan[0] = bme680_compensate_temp(data, adc_temp);
+ t_fine = bme680_calc_t_fine(data, adc_temp);
+
+ /* Pressure calculations */
+ adc_press = FIELD_GET(BME680_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[2]));
+ if (adc_press == BME680_MEAS_SKIPPED) {
+ dev_err(dev, "reading pressure skipped\n");
+ goto out;
+ }
+ data->scan.chan[1] = bme680_compensate_press(data, adc_press, t_fine);
+
+ /* Humidity calculations */
+ adc_humid = get_unaligned_be16(&data->buf[8]);
+ if (adc_humid == BME680_MEAS_SKIPPED) {
+ dev_err(dev, "reading humidity skipped\n");
+ goto out;
+ }
+ data->scan.chan[2] = bme680_compensate_humid(data, adc_humid, t_fine);
+
+ /* Gas calculations */
+ gas_regs_val = get_unaligned_be16(&data->buf[13]);
+ adc_gas_res = FIELD_GET(BME680_ADC_GAS_RES, gas_regs_val);
+ if ((gas_regs_val & BME680_GAS_STAB_BIT) == 0) {
+ dev_err(dev, "heater failed to reach the target temperature\n");
+ goto out;
+ }
+ gas_range = FIELD_GET(BME680_GAS_RANGE_MASK, gas_regs_val);
+ data->scan.chan[3] = bme680_compensate_gas(data, adc_gas_res, gas_range);
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
+ iio_get_time_ns(indio_dev));
+out:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
int bme680_core_probe(struct device *dev, struct regmap *regmap,
const char *name)
{
@@ -879,6 +1102,7 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
indio_dev->name = name;
indio_dev->channels = bme680_channels;
indio_dev->num_channels = ARRAY_SIZE(bme680_channels);
+ indio_dev->available_scan_masks = bme680_avail_scan_masks;
indio_dev->info = &bme680_info;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -888,13 +1112,13 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
data->oversampling_temp = 8; /* 8X oversampling rate */
data->heater_temp = 320; /* degree Celsius */
data->heater_dur = 150; /* milliseconds */
+ data->preheat_curr_mA = 0;
- ret = regmap_write(regmap, BME680_REG_SOFT_RESET,
- BME680_CMD_SOFTRESET);
+ ret = regmap_write(regmap, BME680_REG_SOFT_RESET, BME680_CMD_SOFTRESET);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to reset chip\n");
- usleep_range(BME680_STARTUP_TIME_US, BME680_STARTUP_TIME_US + 1000);
+ fsleep(BME680_STARTUP_TIME_US);
ret = regmap_read(regmap, BME680_REG_CHIP_ID, &data->check);
if (ret < 0)
@@ -922,6 +1146,14 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
return dev_err_probe(dev, ret,
"failed to set gas config data\n");
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ bme680_trigger_handler,
+ NULL);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "iio triggered buffer setup failed\n");
+
return devm_iio_device_register(dev, indio_dev);
}
EXPORT_SYMBOL_NS_GPL(bme680_core_probe, IIO_BME680);
diff --git a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
index f44458c380d9..37d0bdaa8d82 100644
--- a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
+++ b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
@@ -70,6 +70,10 @@ int inv_sensors_timestamp_update_odr(struct inv_sensors_timestamp *ts,
if (mult != ts->mult)
ts->new_mult = mult;
+ /* When FIFO is off, directly apply the new ODR */
+ if (!fifo)
+ inv_sensors_timestamp_apply_odr(ts, 0, 0, 0);
+
return 0;
}
EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_update_odr, IIO_INV_SENSORS_TIMESTAMP);
diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
index a0df9250a69f..a55967208cdc 100644
--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c
+++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
@@ -134,11 +134,11 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
iio_trigger_set_drvdata(sdata->trig, indio_dev);
sdata->trig->ops = trigger_ops;
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(sdata->irq));
/*
* If the IRQ is triggered on falling edge, we need to mark the
* interrupt as active low, if the hardware supports this.
*/
+ irq_trig = irq_get_trigger_type(sdata->irq);
switch(irq_trig) {
case IRQF_TRIGGER_FALLING:
case IRQF_TRIGGER_LOW:
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 9f5d5ebb8653..5d01ba4edbf3 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -6,9 +6,28 @@
menu "Digital to analog converters"
+config AD3552R_HS
+ tristate "Analog Devices AD3552R DAC High Speed driver"
+ select AD3552R_LIB
+ select IIO_BACKEND
+ help
+ Say yes here to build support for Analog Devices AD3552R
+ Digital to Analog Converter High Speed driver.
+
+ The driver requires the assistance of an IP core to operate,
+ since data is streamed into target device via DMA, sent over a
+ QSPI + DDR (Double Data Rate) bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad3552r-hs.
+
+config AD3552R_LIB
+ tristate
+
config AD3552R
tristate "Analog Devices AD3552R DAC driver"
depends on SPI_MASTER
+ select AD3552R_LIB
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
@@ -306,6 +325,19 @@ config AD7303
To compile this driver as module choose M here: the module will be called
ad7303.
+config AD8460
+ tristate "Analog Devices AD8460 DAC driver"
+ depends on SPI
+ select REGMAP_SPI
+ select IIO_BUFFER
+ select IIO_BUFFER_DMAENGINE
+ help
+ Say yes here to build support for Analog Devices AD8460 Digital to
+ Analog Converters (DAC).
+
+ To compile this driver as a module choose M here: the module will be called
+ ad8460.
+
config AD8801
tristate "Analog Devices AD8801/AD8803 DAC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 2cf148f16306..414c152be779 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -4,6 +4,8 @@
#
# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_AD3552R_HS) += ad3552r-hs.o
+obj-$(CONFIG_AD3552R_LIB) += ad3552r-common.o
obj-$(CONFIG_AD3552R) += ad3552r.o
obj-$(CONFIG_AD5360) += ad5360.o
obj-$(CONFIG_AD5380) += ad5380.o
@@ -28,6 +30,7 @@ obj-$(CONFIG_AD5686_SPI) += ad5686-spi.o
obj-$(CONFIG_AD5696_I2C) += ad5696-i2c.o
obj-$(CONFIG_AD7293) += ad7293.o
obj-$(CONFIG_AD7303) += ad7303.o
+obj-$(CONFIG_AD8460) += ad8460.o
obj-$(CONFIG_AD8801) += ad8801.o
obj-$(CONFIG_AD9739A) += ad9739a.o
obj-$(CONFIG_ADI_AXI_DAC) += adi-axi-dac.o
diff --git a/drivers/iio/dac/ad3552r-common.c b/drivers/iio/dac/ad3552r-common.c
new file mode 100644
index 000000000000..2dfeca3656d2
--- /dev/null
+++ b/drivers/iio/dac/ad3552r-common.c
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (c) 2010-2024 Analog Devices Inc.
+// Copyright (c) 2024 Baylibre, SAS
+
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regulator/consumer.h>
+
+#include "ad3552r.h"
+
+const s32 ad3552r_ch_ranges[AD3552R_MAX_RANGES][2] = {
+ [AD3552R_CH_OUTPUT_RANGE_0__2P5V] = { 0, 2500 },
+ [AD3552R_CH_OUTPUT_RANGE_0__5V] = { 0, 5000 },
+ [AD3552R_CH_OUTPUT_RANGE_0__10V] = { 0, 10000 },
+ [AD3552R_CH_OUTPUT_RANGE_NEG_5__5V] = { -5000, 5000 },
+ [AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] = { -10000, 10000 }
+};
+EXPORT_SYMBOL_NS_GPL(ad3552r_ch_ranges, IIO_AD3552R);
+
+const s32 ad3542r_ch_ranges[AD3542R_MAX_RANGES][2] = {
+ [AD3542R_CH_OUTPUT_RANGE_0__2P5V] = { 0, 2500 },
+ [AD3542R_CH_OUTPUT_RANGE_0__3V] = { 0, 3000 },
+ [AD3542R_CH_OUTPUT_RANGE_0__5V] = { 0, 5000 },
+ [AD3542R_CH_OUTPUT_RANGE_0__10V] = { 0, 10000 },
+ [AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V] = { -2500, 7500 },
+ [AD3542R_CH_OUTPUT_RANGE_NEG_5__5V] = { -5000, 5000 }
+};
+EXPORT_SYMBOL_NS_GPL(ad3542r_ch_ranges, IIO_AD3552R);
+
+/* Gain * AD3552R_GAIN_SCALE */
+static const s32 gains_scaling_table[] = {
+ [AD3552R_CH_GAIN_SCALING_1] = 1000,
+ [AD3552R_CH_GAIN_SCALING_0_5] = 500,
+ [AD3552R_CH_GAIN_SCALING_0_25] = 250,
+ [AD3552R_CH_GAIN_SCALING_0_125] = 125
+};
+
+u16 ad3552r_calc_custom_gain(u8 p, u8 n, s16 goffs)
+{
+ return FIELD_PREP(AD3552R_MASK_CH_RANGE_OVERRIDE, 1) |
+ FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_P, p) |
+ FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_N, n) |
+ FIELD_PREP(AD3552R_MASK_CH_OFFSET_BIT_8, abs(goffs)) |
+ FIELD_PREP(AD3552R_MASK_CH_OFFSET_POLARITY, goffs < 0);
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_calc_custom_gain, IIO_AD3552R);
+
+static void ad3552r_get_custom_range(struct ad3552r_ch_data *ch_data,
+ s32 *v_min, s32 *v_max)
+{
+ s64 vref, tmp, common, offset, gn, gp;
+ /*
+ * From datasheet formula (In Volts):
+ * Vmin = 2.5 + [(GainN + Offset / 1024) * 2.5 * Rfb * 1.03]
+ * Vmax = 2.5 - [(GainP + Offset / 1024) * 2.5 * Rfb * 1.03]
+ * Calculus are converted to milivolts
+ */
+ vref = 2500;
+ /* 2.5 * 1.03 * 1000 (To mV) */
+ common = 2575 * ch_data->rfb;
+ offset = ch_data->gain_offset;
+
+ gn = gains_scaling_table[ch_data->n];
+ tmp = (1024 * gn + AD3552R_GAIN_SCALE * offset) * common;
+ tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
+ *v_max = vref + tmp;
+
+ gp = gains_scaling_table[ch_data->p];
+ tmp = (1024 * gp - AD3552R_GAIN_SCALE * offset) * common;
+ tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
+ *v_min = vref - tmp;
+}
+
+void ad3552r_calc_gain_and_offset(struct ad3552r_ch_data *ch_data,
+ const struct ad3552r_model_data *model_data)
+{
+ s32 idx, v_max, v_min, span, rem;
+ s64 tmp;
+
+ if (ch_data->range_override) {
+ ad3552r_get_custom_range(ch_data, &v_min, &v_max);
+ } else {
+ /* Normal range */
+ idx = ch_data->range;
+ v_min = model_data->ranges_table[idx][0];
+ v_max = model_data->ranges_table[idx][1];
+ }
+
+ /*
+ * From datasheet formula:
+ * Vout = Span * (D / 65536) + Vmin
+ * Converted to scale and offset:
+ * Scale = Span / 65536
+ * Offset = 65536 * Vmin / Span
+ *
+ * Reminders are in micros in order to be printed as
+ * IIO_VAL_INT_PLUS_MICRO
+ */
+ span = v_max - v_min;
+ ch_data->scale_int = div_s64_rem(span, 65536, &rem);
+ /* Do operations in microvolts */
+ ch_data->scale_dec = DIV_ROUND_CLOSEST((s64)rem * 1000000, 65536);
+
+ ch_data->offset_int = div_s64_rem(v_min * 65536, span, &rem);
+ tmp = (s64)rem * 1000000;
+ ch_data->offset_dec = div_s64(tmp, span);
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_calc_gain_and_offset, IIO_AD3552R);
+
+int ad3552r_get_ref_voltage(struct device *dev, u32 *val)
+{
+ int voltage;
+ int delta = 100000;
+
+ voltage = devm_regulator_get_enable_read_voltage(dev, "vref");
+ if (voltage < 0 && voltage != -ENODEV)
+ return dev_err_probe(dev, voltage,
+ "Error getting vref voltage\n");
+
+ if (voltage == -ENODEV) {
+ if (device_property_read_bool(dev, "adi,vref-out-en"))
+ *val = AD3552R_INTERNAL_VREF_PIN_2P5V;
+ else
+ *val = AD3552R_INTERNAL_VREF_PIN_FLOATING;
+
+ return 0;
+ }
+
+ if (voltage > 2500000 + delta || voltage < 2500000 - delta) {
+ dev_warn(dev, "vref-supply must be 2.5V");
+ return -EINVAL;
+ }
+
+ *val = AD3552R_EXTERNAL_VREF_PIN_INPUT;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_get_ref_voltage, IIO_AD3552R);
+
+int ad3552r_get_drive_strength(struct device *dev, u32 *val)
+{
+ int err;
+ u32 drive_strength;
+
+ err = device_property_read_u32(dev, "adi,sdo-drive-strength",
+ &drive_strength);
+ if (err)
+ return err;
+
+ if (drive_strength > 3) {
+ dev_err_probe(dev, -EINVAL,
+ "adi,sdo-drive-strength must be less than 4\n");
+ return -EINVAL;
+ }
+
+ *val = drive_strength;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_get_drive_strength, IIO_AD3552R);
+
+int ad3552r_get_custom_gain(struct device *dev, struct fwnode_handle *child,
+ u8 *gs_p, u8 *gs_n, u16 *rfb, s16 *goffs)
+{
+ int err;
+ u32 val;
+ struct fwnode_handle *gain_child __free(fwnode_handle) =
+ fwnode_get_named_child_node(child,
+ "custom-output-range-config");
+
+ if (!gain_child)
+ return dev_err_probe(dev, -EINVAL,
+ "custom-output-range-config mandatory\n");
+
+ err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,gain-scaling-p mandatory\n");
+ *gs_p = val;
+
+ err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,gain-scaling-n property mandatory\n");
+ *gs_n = val;
+
+ err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,rfb-ohms mandatory\n");
+ *rfb = val;
+
+ err = fwnode_property_read_u32(gain_child, "adi,gain-offset", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,gain-offset mandatory\n");
+ *goffs = val;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_get_custom_gain, IIO_AD3552R);
+
+static int ad3552r_find_range(const struct ad3552r_model_data *model_info,
+ s32 *vals)
+{
+ int i;
+
+ for (i = 0; i < model_info->num_ranges; i++)
+ if (vals[0] == model_info->ranges_table[i][0] * 1000 &&
+ vals[1] == model_info->ranges_table[i][1] * 1000)
+ return i;
+
+ return -EINVAL;
+}
+
+int ad3552r_get_output_range(struct device *dev,
+ const struct ad3552r_model_data *model_info,
+ struct fwnode_handle *child, u32 *val)
+{
+ int ret;
+ s32 vals[2];
+
+ /* This property is optional, so returning -ENOENT if missing */
+ if (!fwnode_property_present(child, "adi,output-range-microvolt"))
+ return -ENOENT;
+
+ ret = fwnode_property_read_u32_array(child,
+ "adi,output-range-microvolt",
+ vals, 2);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "invalid adi,output-range-microvolt\n");
+
+ ret = ad3552r_find_range(model_info, vals);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "invalid adi,output-range-microvolt value\n");
+
+ *val = ret;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_get_output_range, IIO_AD3552R);
+
+MODULE_DESCRIPTION("ad3552r common functions");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/dac/ad3552r-hs.c b/drivers/iio/dac/ad3552r-hs.c
new file mode 100644
index 000000000000..d5c704adf5bf
--- /dev/null
+++ b/drivers/iio/dac/ad3552r-hs.c
@@ -0,0 +1,529 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices AD3552R
+ * Digital to Analog converter driver, High Speed version
+ *
+ * Copyright 2024 Analog Devices Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/backend.h>
+#include <linux/iio/buffer.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/units.h>
+
+#include "ad3552r.h"
+#include "ad3552r-hs.h"
+
+struct ad3552r_hs_state {
+ const struct ad3552r_model_data *model_data;
+ struct gpio_desc *reset_gpio;
+ struct device *dev;
+ struct iio_backend *back;
+ bool single_channel;
+ struct ad3552r_ch_data ch_data[AD3552R_MAX_CH];
+ struct ad3552r_hs_platform_data *data;
+};
+
+static int ad3552r_qspi_update_reg_bits(struct ad3552r_hs_state *st,
+ u32 reg, u32 mask, u32 val,
+ size_t xfer_size)
+{
+ u32 rval;
+ int ret;
+
+ ret = st->data->bus_reg_read(st->back, reg, &rval, xfer_size);
+ if (ret)
+ return ret;
+
+ rval = (rval & ~mask) | val;
+
+ return st->data->bus_reg_write(st->back, reg, rval, xfer_size);
+}
+
+static int ad3552r_hs_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct ad3552r_hs_state *st = iio_priv(indio_dev);
+ int ret;
+ int ch = chan->channel;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ /*
+ * Using 4 lanes (QSPI), then using 2 as DDR mode is
+ * considered always on (considering buffering mode always).
+ */
+ *val = DIV_ROUND_CLOSEST(st->data->bus_sample_data_clock_hz *
+ 4 * 2, chan->scan_type.realbits);
+
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_RAW:
+ ret = st->data->bus_reg_read(st->back,
+ AD3552R_REG_ADDR_CH_DAC_16B(chan->channel),
+ val, 2);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = st->ch_data[ch].scale_int;
+ *val2 = st->ch_data[ch].scale_dec;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_OFFSET:
+ *val = st->ch_data[ch].offset_int;
+ *val2 = st->ch_data[ch].offset_dec;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad3552r_hs_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct ad3552r_hs_state *st = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ return st->data->bus_reg_write(st->back,
+ AD3552R_REG_ADDR_CH_DAC_16B(chan->channel),
+ val, 2);
+ }
+ unreachable();
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad3552r_hs_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct ad3552r_hs_state *st = iio_priv(indio_dev);
+ struct iio_backend_data_fmt fmt = {
+ .type = IIO_BACKEND_DATA_UNSIGNED
+ };
+ int loop_len, val, ret;
+
+ switch (*indio_dev->active_scan_mask) {
+ case AD3552R_CH0_ACTIVE:
+ st->single_channel = true;
+ loop_len = 2;
+ val = AD3552R_REG_ADDR_CH_DAC_16B(0);
+ break;
+ case AD3552R_CH1_ACTIVE:
+ st->single_channel = true;
+ loop_len = 2;
+ val = AD3552R_REG_ADDR_CH_DAC_16B(1);
+ break;
+ case AD3552R_CH0_ACTIVE | AD3552R_CH1_ACTIVE:
+ st->single_channel = false;
+ loop_len = 4;
+ val = AD3552R_REG_ADDR_CH_DAC_16B(1);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_STREAM_MODE,
+ loop_len, 1);
+ if (ret)
+ return ret;
+
+ /* Inform DAC chip to switch into DDR mode */
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SPI_CONFIG_DDR,
+ AD3552R_MASK_SPI_CONFIG_DDR, 1);
+ if (ret)
+ return ret;
+
+ /* Inform DAC IP to go for DDR mode from now on */
+ ret = iio_backend_ddr_enable(st->back);
+ if (ret) {
+ dev_err(st->dev, "could not set DDR mode, not streaming");
+ goto exit_err;
+ }
+
+ ret = iio_backend_data_transfer_addr(st->back, val);
+ if (ret)
+ goto exit_err;
+
+ ret = iio_backend_data_format_set(st->back, 0, &fmt);
+ if (ret)
+ goto exit_err;
+
+ ret = iio_backend_data_stream_enable(st->back);
+ if (ret)
+ goto exit_err;
+
+ return 0;
+
+exit_err:
+ ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SPI_CONFIG_DDR,
+ 0, 1);
+
+ iio_backend_ddr_disable(st->back);
+
+ return ret;
+}
+
+static int ad3552r_hs_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct ad3552r_hs_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = iio_backend_data_stream_disable(st->back);
+ if (ret)
+ return ret;
+
+ /* Inform DAC to set in SDR mode */
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SPI_CONFIG_DDR,
+ 0, 1);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_ddr_disable(st->back);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static inline int ad3552r_hs_set_output_range(struct ad3552r_hs_state *st,
+ int ch, unsigned int mode)
+{
+ int val;
+
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH0_RANGE, mode);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH1_RANGE, mode);
+
+ return ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
+ AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch),
+ val, 1);
+}
+
+static int ad3552r_hs_reset(struct ad3552r_hs_state *st)
+{
+ int ret;
+
+ st->reset_gpio = devm_gpiod_get_optional(st->dev,
+ "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(st->reset_gpio))
+ return PTR_ERR(st->reset_gpio);
+
+ if (st->reset_gpio) {
+ fsleep(10);
+ gpiod_set_value_cansleep(st->reset_gpio, 0);
+ } else {
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
+ AD3552R_MASK_SOFTWARE_RESET,
+ AD3552R_MASK_SOFTWARE_RESET, 1);
+ if (ret)
+ return ret;
+ }
+ msleep(100);
+
+ return 0;
+}
+
+static int ad3552r_hs_scratch_pad_test(struct ad3552r_hs_state *st)
+{
+ int ret, val;
+
+ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ AD3552R_SCRATCH_PAD_TEST_VAL1, 1);
+ if (ret)
+ return ret;
+
+ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ &val, 1);
+ if (ret)
+ return ret;
+
+ if (val != AD3552R_SCRATCH_PAD_TEST_VAL1)
+ return dev_err_probe(st->dev, -EIO,
+ "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n",
+ AD3552R_SCRATCH_PAD_TEST_VAL1, val);
+
+ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ AD3552R_SCRATCH_PAD_TEST_VAL2, 1);
+ if (ret)
+ return ret;
+
+ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ &val, 1);
+ if (ret)
+ return ret;
+
+ if (val != AD3552R_SCRATCH_PAD_TEST_VAL2)
+ return dev_err_probe(st->dev, -EIO,
+ "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n",
+ AD3552R_SCRATCH_PAD_TEST_VAL2, val);
+
+ return 0;
+}
+
+static int ad3552r_hs_setup_custom_gain(struct ad3552r_hs_state *st,
+ int ch, u16 gain, u16 offset)
+{
+ int ret;
+
+ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_CH_OFFSET(ch),
+ offset, 1);
+ if (ret)
+ return ret;
+
+ return st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_CH_GAIN(ch),
+ gain, 1);
+}
+
+static int ad3552r_hs_setup(struct ad3552r_hs_state *st)
+{
+ u16 id;
+ u16 gain = 0, offset = 0;
+ u32 ch, val, range;
+ int ret;
+
+ ret = ad3552r_hs_reset(st);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_ddr_disable(st->back);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_hs_scratch_pad_test(st);
+ if (ret)
+ return ret;
+
+ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_L,
+ &val, 1);
+ if (ret)
+ return ret;
+
+ id = val;
+
+ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_H,
+ &val, 1);
+ if (ret)
+ return ret;
+
+ id |= val << 8;
+ if (id != st->model_data->chip_id)
+ dev_info(st->dev, "Chip ID error. Expected 0x%x, Read 0x%x\n",
+ AD3552R_ID, id);
+
+ ret = st->data->bus_reg_write(st->back,
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+ 0, 1);
+ if (ret)
+ return ret;
+
+ ret = st->data->bus_reg_write(st->back,
+ AD3552R_REG_ADDR_TRANSFER_REGISTER,
+ FIELD_PREP(AD3552R_MASK_MULTI_IO_MODE,
+ AD3552R_QUAD_SPI) |
+ AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE, 1);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_data_source_set(st->back, 0, IIO_BACKEND_EXTERNAL);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_data_source_set(st->back, 1, IIO_BACKEND_EXTERNAL);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_get_ref_voltage(st->dev, &val);
+ if (ret < 0)
+ return ret;
+
+ val = ret;
+
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+ AD3552R_MASK_REFERENCE_VOLTAGE_SEL,
+ val, 1);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_get_drive_strength(st->dev, &val);
+ if (!ret) {
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SDO_DRIVE_STRENGTH,
+ val, 1);
+ if (ret)
+ return ret;
+ }
+
+ device_for_each_child_node_scoped(st->dev, child) {
+ ret = fwnode_property_read_u32(child, "reg", &ch);
+ if (ret)
+ return dev_err_probe(st->dev, ret,
+ "reg property missing\n");
+
+ ret = ad3552r_get_output_range(st->dev, st->model_data, child,
+ &range);
+ if (ret && ret != -ENOENT)
+ return ret;
+ if (ret == -ENOENT) {
+ ret = ad3552r_get_custom_gain(st->dev, child,
+ &st->ch_data[ch].p,
+ &st->ch_data[ch].n,
+ &st->ch_data[ch].rfb,
+ &st->ch_data[ch].gain_offset);
+ if (ret)
+ return ret;
+
+ gain = ad3552r_calc_custom_gain(st->ch_data[ch].p,
+ st->ch_data[ch].n,
+ st->ch_data[ch].gain_offset);
+ offset = abs(st->ch_data[ch].gain_offset);
+
+ st->ch_data[ch].range_override = 1;
+
+ ret = ad3552r_hs_setup_custom_gain(st, ch, gain,
+ offset);
+ if (ret)
+ return ret;
+ } else {
+ st->ch_data[ch].range = range;
+
+ ret = ad3552r_hs_set_output_range(st, ch, range);
+ if (ret)
+ return ret;
+ }
+
+ ad3552r_calc_gain_and_offset(&st->ch_data[ch], st->model_data);
+ }
+
+ return 0;
+}
+
+static const struct iio_buffer_setup_ops ad3552r_hs_buffer_setup_ops = {
+ .postenable = ad3552r_hs_buffer_postenable,
+ .predisable = ad3552r_hs_buffer_predisable,
+};
+
+#define AD3552R_CHANNEL(ch) { \
+ .type = IIO_VOLTAGE, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_OFFSET), \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = (ch), \
+ .scan_index = (ch), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_BE, \
+ } \
+}
+
+static const struct iio_chan_spec ad3552r_hs_channels[] = {
+ AD3552R_CHANNEL(0),
+ AD3552R_CHANNEL(1),
+};
+
+static const struct iio_info ad3552r_hs_info = {
+ .read_raw = &ad3552r_hs_read_raw,
+ .write_raw = &ad3552r_hs_write_raw,
+};
+
+static int ad3552r_hs_probe(struct platform_device *pdev)
+{
+ struct ad3552r_hs_state *st;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+ st->dev = &pdev->dev;
+
+ st->data = dev_get_platdata(st->dev);
+ if (!st->data)
+ return dev_err_probe(st->dev, -ENODEV, "No platform data !");
+
+ st->back = devm_iio_backend_get(&pdev->dev, NULL);
+ if (IS_ERR(st->back))
+ return PTR_ERR(st->back);
+
+ ret = devm_iio_backend_enable(&pdev->dev, st->back);
+ if (ret)
+ return ret;
+
+ st->model_data = device_get_match_data(&pdev->dev);
+ if (!st->model_data)
+ return -ENODEV;
+
+ indio_dev->name = "ad3552r";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->setup_ops = &ad3552r_hs_buffer_setup_ops;
+ indio_dev->channels = ad3552r_hs_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad3552r_hs_channels);
+ indio_dev->info = &ad3552r_hs_info;
+
+ ret = devm_iio_backend_request_buffer(&pdev->dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_hs_setup(st);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(&pdev->dev, indio_dev);
+}
+
+static const struct ad3552r_model_data ad3552r_model_data = {
+ .model_name = "ad3552r",
+ .chip_id = AD3552R_ID,
+ .num_hw_channels = 2,
+ .ranges_table = ad3552r_ch_ranges,
+ .num_ranges = ARRAY_SIZE(ad3552r_ch_ranges),
+};
+
+static const struct of_device_id ad3552r_hs_of_id[] = {
+ { .compatible = "adi,ad3552r", .data = &ad3552r_model_data },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad3552r_hs_of_id);
+
+static struct platform_driver ad3552r_hs_driver = {
+ .driver = {
+ .name = "ad3552r-hs",
+ .of_match_table = ad3552r_hs_of_id,
+ },
+ .probe = ad3552r_hs_probe,
+};
+module_platform_driver(ad3552r_hs_driver);
+
+MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>");
+MODULE_AUTHOR("Angelo Dureghello <adueghello@baylibre.com>");
+MODULE_DESCRIPTION("AD3552R Driver - High Speed version");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(IIO_BACKEND);
+MODULE_IMPORT_NS(IIO_AD3552R);
diff --git a/drivers/iio/dac/ad3552r-hs.h b/drivers/iio/dac/ad3552r-hs.h
new file mode 100644
index 000000000000..724261d38dea
--- /dev/null
+++ b/drivers/iio/dac/ad3552r-hs.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2024 Analog Devices Inc.
+ * Copyright (c) 2024 Baylibre, SAS
+ */
+#ifndef __LINUX_PLATFORM_DATA_AD3552R_HS_H__
+#define __LINUX_PLATFORM_DATA_AD3552R_HS_H__
+
+struct iio_backend;
+
+struct ad3552r_hs_platform_data {
+ int (*bus_reg_read)(struct iio_backend *back, u32 reg, u32 *val,
+ size_t data_size);
+ int (*bus_reg_write)(struct iio_backend *back, u32 reg, u32 val,
+ size_t data_size);
+ u32 bus_sample_data_clock_hz;
+};
+
+#endif /* __LINUX_PLATFORM_DATA_AD3552R_HS_H__ */
diff --git a/drivers/iio/dac/ad3552r.c b/drivers/iio/dac/ad3552r.c
index 7d61b2fe6624..92688d958f4f 100644
--- a/drivers/iio/dac/ad3552r.c
+++ b/drivers/iio/dac/ad3552r.c
@@ -6,271 +6,15 @@
* Copyright 2021 Analog Devices Inc.
*/
#include <linux/unaligned.h>
+#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
-#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
-/* Register addresses */
-/* Primary address space */
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00
-#define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0))
-#define AD3552R_MASK_ADDR_ASCENSION BIT(5)
-#define AD3552R_MASK_SDO_ACTIVE BIT(4)
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01
-#define AD3552R_MASK_SINGLE_INST BIT(7)
-#define AD3552R_MASK_SHORT_INSTRUCTION BIT(3)
-#define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02
-#define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n))
-#define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2)
-#define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0)
-#define AD3552R_REG_ADDR_CHIP_TYPE 0x03
-#define AD3552R_MASK_CLASS GENMASK(7, 0)
-#define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04
-#define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05
-#define AD3552R_REG_ADDR_CHIP_GRADE 0x06
-#define AD3552R_MASK_GRADE GENMASK(7, 4)
-#define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0)
-#define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A
-#define AD3552R_REG_ADDR_SPI_REVISION 0x0B
-#define AD3552R_REG_ADDR_VENDOR_L 0x0C
-#define AD3552R_REG_ADDR_VENDOR_H 0x0D
-#define AD3552R_REG_ADDR_STREAM_MODE 0x0E
-#define AD3552R_MASK_LENGTH GENMASK(7, 0)
-#define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F
-#define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6)
-#define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2)
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10
-#define AD3552R_MASK_CRC_ENABLE (GENMASK(7, 6) |\
- GENMASK(1, 0))
-#define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5)
-#define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11
-#define AD3552R_MASK_INTERFACE_NOT_READY BIT(7)
-#define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5)
-#define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3)
-#define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2)
-#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1)
-#define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0)
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14
-#define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6)
-#define AD3552R_MASK_MEM_CRC_EN BIT(4)
-#define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2)
-#define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1)
-#define AD3552R_MASK_SPI_CONFIG_DDR BIT(0)
-#define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15
-#define AD3552R_MASK_IDUMP_FAST_MODE BIT(6)
-#define AD3552R_MASK_SAMPLE_HOLD_DIFFERENTIAL_USER_EN BIT(5)
-#define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3)
-#define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2)
-#define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0)
-#define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16
-#define AD3552R_MASK_REF_RANGE_ALARM BIT(6)
-#define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5)
-#define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4)
-#define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3)
-#define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2)
-#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1)
-#define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0)
-#define AD3552R_REG_ADDR_ERR_STATUS 0x17
-#define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6)
-#define AD3552R_MASK_DUAL_SPI_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5)
-#define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4)
-#define AD3552R_MASK_RESET_STATUS BIT(0)
-#define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18
-#define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch))
-#define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch)
-#define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19
-#define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) ((ch) ? GENMASK(7, 4) :\
- GENMASK(3, 0))
-#define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2)
-#define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0)
-#define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2)
-#define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7)
-#define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5)
-#define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3)
-#define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2)
-#define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(0)
-/*
- * Secondary region
- * For multibyte registers specify the highest address because the access is
- * done in descending order
- */
-#define AD3552R_SECONDARY_REGION_START 0x28
-#define AD3552R_REG_ADDR_HW_LDAC_16B 0x28
-#define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - ch) * 2)
-#define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E
-#define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F
-#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31
-#define AD3552R_REG_ADDR_SW_LDAC_16B 0x32
-#define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - ch) * 2)
-/* 3 bytes registers */
-#define AD3552R_REG_START_24B 0x37
-#define AD3552R_REG_ADDR_HW_LDAC_24B 0x37
-#define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - ch) * 3)
-#define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40
-#define AD3552R_REG_ADDR_CH_SELECT_24B 0x41
-#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44
-#define AD3552R_REG_ADDR_SW_LDAC_24B 0x45
-#define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - ch) * 3)
-
-/* Useful defines */
-#define AD3552R_MAX_CH 2
-#define AD3552R_MASK_CH(ch) BIT(ch)
-#define AD3552R_MASK_ALL_CH GENMASK(1, 0)
-#define AD3552R_MAX_REG_SIZE 3
-#define AD3552R_READ_BIT BIT(7)
-#define AD3552R_ADDR_MASK GENMASK(6, 0)
-#define AD3552R_MASK_DAC_12B 0xFFF0
-#define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8
-#define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34
-#define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2
-#define AD3552R_GAIN_SCALE 1000
-#define AD3552R_LDAC_PULSE_US 100
-
-enum ad3552r_ch_vref_select {
- /* Internal source with Vref I/O floating */
- AD3552R_INTERNAL_VREF_PIN_FLOATING,
- /* Internal source with Vref I/O at 2.5V */
- AD3552R_INTERNAL_VREF_PIN_2P5V,
- /* External source with Vref I/O as input */
- AD3552R_EXTERNAL_VREF_PIN_INPUT
-};
-
-enum ad3552r_id {
- AD3541R_ID = 0x400b,
- AD3542R_ID = 0x4009,
- AD3551R_ID = 0x400a,
- AD3552R_ID = 0x4008,
-};
-
-enum ad3552r_ch_output_range {
- /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
- AD3552R_CH_OUTPUT_RANGE_0__2P5V,
- /* Range from 0 V to 5 V. Requires Rfb1x connection */
- AD3552R_CH_OUTPUT_RANGE_0__5V,
- /* Range from 0 V to 10 V. Requires Rfb2x connection */
- AD3552R_CH_OUTPUT_RANGE_0__10V,
- /* Range from -5 V to 5 V. Requires Rfb2x connection */
- AD3552R_CH_OUTPUT_RANGE_NEG_5__5V,
- /* Range from -10 V to 10 V. Requires Rfb4x connection */
- AD3552R_CH_OUTPUT_RANGE_NEG_10__10V,
-};
-
-static const s32 ad3552r_ch_ranges[][2] = {
- [AD3552R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500},
- [AD3552R_CH_OUTPUT_RANGE_0__5V] = {0, 5000},
- [AD3552R_CH_OUTPUT_RANGE_0__10V] = {0, 10000},
- [AD3552R_CH_OUTPUT_RANGE_NEG_5__5V] = {-5000, 5000},
- [AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] = {-10000, 10000}
-};
-
-enum ad3542r_ch_output_range {
- /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
- AD3542R_CH_OUTPUT_RANGE_0__2P5V,
- /* Range from 0 V to 3 V. Requires Rfb1x connection */
- AD3542R_CH_OUTPUT_RANGE_0__3V,
- /* Range from 0 V to 5 V. Requires Rfb1x connection */
- AD3542R_CH_OUTPUT_RANGE_0__5V,
- /* Range from 0 V to 10 V. Requires Rfb2x connection */
- AD3542R_CH_OUTPUT_RANGE_0__10V,
- /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */
- AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V,
- /* Range from -5 V to 5 V. Requires Rfb2x connection */
- AD3542R_CH_OUTPUT_RANGE_NEG_5__5V,
-};
-
-static const s32 ad3542r_ch_ranges[][2] = {
- [AD3542R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500},
- [AD3542R_CH_OUTPUT_RANGE_0__3V] = {0, 3000},
- [AD3542R_CH_OUTPUT_RANGE_0__5V] = {0, 5000},
- [AD3542R_CH_OUTPUT_RANGE_0__10V] = {0, 10000},
- [AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V] = {-2500, 7500},
- [AD3542R_CH_OUTPUT_RANGE_NEG_5__5V] = {-5000, 5000}
-};
-
-enum ad3552r_ch_gain_scaling {
- /* Gain scaling of 1 */
- AD3552R_CH_GAIN_SCALING_1,
- /* Gain scaling of 0.5 */
- AD3552R_CH_GAIN_SCALING_0_5,
- /* Gain scaling of 0.25 */
- AD3552R_CH_GAIN_SCALING_0_25,
- /* Gain scaling of 0.125 */
- AD3552R_CH_GAIN_SCALING_0_125,
-};
-
-/* Gain * AD3552R_GAIN_SCALE */
-static const s32 gains_scaling_table[] = {
- [AD3552R_CH_GAIN_SCALING_1] = 1000,
- [AD3552R_CH_GAIN_SCALING_0_5] = 500,
- [AD3552R_CH_GAIN_SCALING_0_25] = 250,
- [AD3552R_CH_GAIN_SCALING_0_125] = 125
-};
-
-enum ad3552r_dev_attributes {
- /* - Direct register values */
- /* From 0-3 */
- AD3552R_SDO_DRIVE_STRENGTH,
- /*
- * 0 -> Internal Vref, vref_io pin floating (default)
- * 1 -> Internal Vref, vref_io driven by internal vref
- * 2 or 3 -> External Vref
- */
- AD3552R_VREF_SELECT,
- /* Read registers in ascending order if set. Else descending */
- AD3552R_ADDR_ASCENSION,
-};
-
-enum ad3552r_ch_attributes {
- /* DAC powerdown */
- AD3552R_CH_DAC_POWERDOWN,
- /* DAC amplifier powerdown */
- AD3552R_CH_AMPLIFIER_POWERDOWN,
- /* Select the output range. Select from enum ad3552r_ch_output_range */
- AD3552R_CH_OUTPUT_RANGE_SEL,
- /*
- * Over-rider the range selector in order to manually set the output
- * voltage range
- */
- AD3552R_CH_RANGE_OVERRIDE,
- /* Manually set the offset voltage */
- AD3552R_CH_GAIN_OFFSET,
- /* Sets the polarity of the offset. */
- AD3552R_CH_GAIN_OFFSET_POLARITY,
- /* PDAC gain scaling */
- AD3552R_CH_GAIN_SCALING_P,
- /* NDAC gain scaling */
- AD3552R_CH_GAIN_SCALING_N,
- /* Rfb value */
- AD3552R_CH_RFB,
- /* Channel select. When set allow Input -> DAC and Mask -> DAC */
- AD3552R_CH_SELECT,
-};
-
-struct ad3552r_ch_data {
- s32 scale_int;
- s32 scale_dec;
- s32 offset_int;
- s32 offset_dec;
- s16 gain_offset;
- u16 rfb;
- u8 n;
- u8 p;
- u8 range;
- bool range_override;
-};
-
-struct ad3552r_model_data {
- const char *model_name;
- enum ad3552r_id chip_id;
- unsigned int num_hw_channels;
- const s32 (*ranges_table)[2];
- int num_ranges;
- bool requires_output_range;
-};
+#include "ad3552r.h"
struct ad3552r_desc {
const struct ad3552r_model_data *model_data;
@@ -285,45 +29,6 @@ struct ad3552r_desc {
unsigned int num_ch;
};
-static const u16 addr_mask_map[][2] = {
- [AD3552R_ADDR_ASCENSION] = {
- AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
- AD3552R_MASK_ADDR_ASCENSION
- },
- [AD3552R_SDO_DRIVE_STRENGTH] = {
- AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
- AD3552R_MASK_SDO_DRIVE_STRENGTH
- },
- [AD3552R_VREF_SELECT] = {
- AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
- AD3552R_MASK_REFERENCE_VOLTAGE_SEL
- },
-};
-
-/* 0 -> reg addr, 1->ch0 mask, 2->ch1 mask */
-static const u16 addr_mask_map_ch[][3] = {
- [AD3552R_CH_DAC_POWERDOWN] = {
- AD3552R_REG_ADDR_POWERDOWN_CONFIG,
- AD3552R_MASK_CH_DAC_POWERDOWN(0),
- AD3552R_MASK_CH_DAC_POWERDOWN(1)
- },
- [AD3552R_CH_AMPLIFIER_POWERDOWN] = {
- AD3552R_REG_ADDR_POWERDOWN_CONFIG,
- AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(0),
- AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(1)
- },
- [AD3552R_CH_OUTPUT_RANGE_SEL] = {
- AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
- AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0),
- AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1)
- },
- [AD3552R_CH_SELECT] = {
- AD3552R_REG_ADDR_CH_SELECT_16B,
- AD3552R_MASK_CH(0),
- AD3552R_MASK_CH(1)
- }
-};
-
static u8 _ad3552r_reg_len(u8 addr)
{
switch (addr) {
@@ -399,11 +104,6 @@ static int ad3552r_read_reg(struct ad3552r_desc *dac, u8 addr, u16 *val)
return 0;
}
-static u16 ad3552r_field_prep(u16 val, u16 mask)
-{
- return (val << __ffs(mask)) & mask;
-}
-
/* Update field of a register, shift val if needed */
static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask,
u16 val)
@@ -416,21 +116,11 @@ static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask,
return ret;
reg &= ~mask;
- reg |= ad3552r_field_prep(val, mask);
+ reg |= val;
return ad3552r_write_reg(dac, addr, reg);
}
-static int ad3552r_set_ch_value(struct ad3552r_desc *dac,
- enum ad3552r_ch_attributes attr,
- u8 ch,
- u16 val)
-{
- /* Update register related to attributes in chip */
- return ad3552r_update_reg_field(dac, addr_mask_map_ch[attr][0],
- addr_mask_map_ch[attr][ch + 1], val);
-}
-
#define AD3552R_CH_DAC(_idx) ((struct iio_chan_spec) { \
.type = IIO_VOLTAGE, \
.output = true, \
@@ -510,8 +200,14 @@ static int ad3552r_write_raw(struct iio_dev *indio_dev,
val);
break;
case IIO_CHAN_INFO_ENABLE:
- err = ad3552r_set_ch_value(dac, AD3552R_CH_DAC_POWERDOWN,
- chan->channel, !val);
+ if (chan->channel == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH_DAC_POWERDOWN(0), !val);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH_DAC_POWERDOWN(1), !val);
+
+ err = ad3552r_update_reg_field(dac, AD3552R_REG_ADDR_POWERDOWN_CONFIG,
+ AD3552R_MASK_CH_DAC_POWERDOWN(chan->channel),
+ val);
break;
default:
err = -EINVAL;
@@ -715,83 +411,9 @@ static int ad3552r_reset(struct ad3552r_desc *dac)
}
return ad3552r_update_reg_field(dac,
- addr_mask_map[AD3552R_ADDR_ASCENSION][0],
- addr_mask_map[AD3552R_ADDR_ASCENSION][1],
- val);
-}
-
-static void ad3552r_get_custom_range(struct ad3552r_desc *dac, s32 i, s32 *v_min,
- s32 *v_max)
-{
- s64 vref, tmp, common, offset, gn, gp;
- /*
- * From datasheet formula (In Volts):
- * Vmin = 2.5 + [(GainN + Offset / 1024) * 2.5 * Rfb * 1.03]
- * Vmax = 2.5 - [(GainP + Offset / 1024) * 2.5 * Rfb * 1.03]
- * Calculus are converted to milivolts
- */
- vref = 2500;
- /* 2.5 * 1.03 * 1000 (To mV) */
- common = 2575 * dac->ch_data[i].rfb;
- offset = dac->ch_data[i].gain_offset;
-
- gn = gains_scaling_table[dac->ch_data[i].n];
- tmp = (1024 * gn + AD3552R_GAIN_SCALE * offset) * common;
- tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
- *v_max = vref + tmp;
-
- gp = gains_scaling_table[dac->ch_data[i].p];
- tmp = (1024 * gp - AD3552R_GAIN_SCALE * offset) * common;
- tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
- *v_min = vref - tmp;
-}
-
-static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch)
-{
- s32 idx, v_max, v_min, span, rem;
- s64 tmp;
-
- if (dac->ch_data[ch].range_override) {
- ad3552r_get_custom_range(dac, ch, &v_min, &v_max);
- } else {
- /* Normal range */
- idx = dac->ch_data[ch].range;
- v_min = dac->model_data->ranges_table[idx][0];
- v_max = dac->model_data->ranges_table[idx][1];
- }
-
- /*
- * From datasheet formula:
- * Vout = Span * (D / 65536) + Vmin
- * Converted to scale and offset:
- * Scale = Span / 65536
- * Offset = 65536 * Vmin / Span
- *
- * Reminders are in micros in order to be printed as
- * IIO_VAL_INT_PLUS_MICRO
- */
- span = v_max - v_min;
- dac->ch_data[ch].scale_int = div_s64_rem(span, 65536, &rem);
- /* Do operations in microvolts */
- dac->ch_data[ch].scale_dec = DIV_ROUND_CLOSEST((s64)rem * 1000000,
- 65536);
-
- dac->ch_data[ch].offset_int = div_s64_rem(v_min * 65536, span, &rem);
- tmp = (s64)rem * 1000000;
- dac->ch_data[ch].offset_dec = div_s64(tmp, span);
-}
-
-static int ad3552r_find_range(const struct ad3552r_model_data *model_data,
- s32 *vals)
-{
- int i;
-
- for (i = 0; i < model_data->num_ranges; i++)
- if (vals[0] == model_data->ranges_table[i][0] * 1000 &&
- vals[1] == model_data->ranges_table[i][1] * 1000)
- return i;
-
- return -EINVAL;
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
+ AD3552R_MASK_ADDR_ASCENSION,
+ FIELD_PREP(AD3552R_MASK_ADDR_ASCENSION, val));
}
static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
@@ -799,57 +421,30 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
u32 ch)
{
struct device *dev = &dac->spi->dev;
- u32 val;
int err;
u8 addr;
- u16 reg = 0, offset;
-
- struct fwnode_handle *gain_child __free(fwnode_handle)
- = fwnode_get_named_child_node(child,
- "custom-output-range-config");
- if (!gain_child)
- return dev_err_probe(dev, -EINVAL,
- "mandatory custom-output-range-config property missing\n");
-
- dac->ch_data[ch].range_override = 1;
- reg |= ad3552r_field_prep(1, AD3552R_MASK_CH_RANGE_OVERRIDE);
-
- err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val);
- if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,gain-scaling-p property missing\n");
- reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_P);
- dac->ch_data[ch].p = val;
-
- err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val);
- if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,gain-scaling-n property missing\n");
- reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_N);
- dac->ch_data[ch].n = val;
-
- err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val);
- if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,rfb-ohms property missing\n");
- dac->ch_data[ch].rfb = val;
+ u16 reg;
- err = fwnode_property_read_u32(gain_child, "adi,gain-offset", &val);
+ err = ad3552r_get_custom_gain(dev, child,
+ &dac->ch_data[ch].p,
+ &dac->ch_data[ch].n,
+ &dac->ch_data[ch].rfb,
+ &dac->ch_data[ch].gain_offset);
if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,gain-offset property missing\n");
- dac->ch_data[ch].gain_offset = val;
+ return err;
- offset = abs((s32)val);
- reg |= ad3552r_field_prep((offset >> 8), AD3552R_MASK_CH_OFFSET_BIT_8);
+ dac->ch_data[ch].range_override = 1;
- reg |= ad3552r_field_prep((s32)val < 0, AD3552R_MASK_CH_OFFSET_POLARITY);
addr = AD3552R_REG_ADDR_CH_GAIN(ch);
err = ad3552r_write_reg(dac, addr,
- offset & AD3552R_MASK_CH_OFFSET_BITS_0_7);
+ abs((s32)dac->ch_data[ch].gain_offset) &
+ AD3552R_MASK_CH_OFFSET_BITS_0_7);
if (err)
return dev_err_probe(dev, err, "Error writing register\n");
+ reg = ad3552r_calc_custom_gain(dac->ch_data[ch].p, dac->ch_data[ch].n,
+ dac->ch_data[ch].gain_offset);
+
err = ad3552r_write_reg(dac, addr, reg);
if (err)
return dev_err_probe(dev, err, "Error writing register\n");
@@ -860,49 +455,31 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
static int ad3552r_configure_device(struct ad3552r_desc *dac)
{
struct device *dev = &dac->spi->dev;
- int err, cnt = 0, voltage, delta = 100000;
- u32 vals[2], val, ch;
+ int err, cnt = 0;
+ u32 val, ch;
dac->gpio_ldac = devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_HIGH);
if (IS_ERR(dac->gpio_ldac))
return dev_err_probe(dev, PTR_ERR(dac->gpio_ldac),
"Error getting gpio ldac");
- voltage = devm_regulator_get_enable_read_voltage(dev, "vref");
- if (voltage < 0 && voltage != -ENODEV)
- return dev_err_probe(dev, voltage, "Error getting vref voltage\n");
-
- if (voltage == -ENODEV) {
- if (device_property_read_bool(dev, "adi,vref-out-en"))
- val = AD3552R_INTERNAL_VREF_PIN_2P5V;
- else
- val = AD3552R_INTERNAL_VREF_PIN_FLOATING;
- } else {
- if (voltage > 2500000 + delta || voltage < 2500000 - delta) {
- dev_warn(dev, "vref-supply must be 2.5V");
- return -EINVAL;
- }
- val = AD3552R_EXTERNAL_VREF_PIN_INPUT;
- }
+ err = ad3552r_get_ref_voltage(dev, &val);
+ if (err < 0)
+ return err;
err = ad3552r_update_reg_field(dac,
- addr_mask_map[AD3552R_VREF_SELECT][0],
- addr_mask_map[AD3552R_VREF_SELECT][1],
- val);
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+ AD3552R_MASK_REFERENCE_VOLTAGE_SEL,
+ FIELD_PREP(AD3552R_MASK_REFERENCE_VOLTAGE_SEL, val));
if (err)
return err;
- err = device_property_read_u32(dev, "adi,sdo-drive-strength", &val);
+ err = ad3552r_get_drive_strength(dev, &val);
if (!err) {
- if (val > 3) {
- dev_err(dev, "adi,sdo-drive-strength must be less than 4\n");
- return -EINVAL;
- }
-
err = ad3552r_update_reg_field(dac,
- addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][0],
- addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][1],
- val);
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SDO_DRIVE_STRENGTH,
+ FIELD_PREP(AD3552R_MASK_SDO_DRIVE_STRENGTH, val));
if (err)
return err;
}
@@ -923,24 +500,21 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
"reg must be less than %d\n",
dac->model_data->num_hw_channels);
- if (fwnode_property_present(child, "adi,output-range-microvolt")) {
- err = fwnode_property_read_u32_array(child,
- "adi,output-range-microvolt",
- vals,
- 2);
- if (err)
- return dev_err_probe(dev, err,
- "adi,output-range-microvolt property could not be parsed\n");
-
- err = ad3552r_find_range(dac->model_data, vals);
- if (err < 0)
- return dev_err_probe(dev, err,
- "Invalid adi,output-range-microvolt value\n");
-
- val = err;
- err = ad3552r_set_ch_value(dac,
- AD3552R_CH_OUTPUT_RANGE_SEL,
- ch, val);
+ err = ad3552r_get_output_range(dev, dac->model_data,
+ child, &val);
+ if (err && err != -ENOENT)
+ return err;
+
+ if (!err) {
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0), val);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1), val);
+
+ err = ad3552r_update_reg_field(dac,
+ AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
+ AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch),
+ val);
if (err)
return err;
@@ -955,10 +529,17 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
return err;
}
- ad3552r_calc_gain_and_offset(dac, ch);
+ ad3552r_calc_gain_and_offset(&dac->ch_data[ch], dac->model_data);
dac->enabled_ch |= BIT(ch);
- err = ad3552r_set_ch_value(dac, AD3552R_CH_SELECT, ch, 1);
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH(0), 1);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH(1), 1);
+
+ err = ad3552r_update_reg_field(dac,
+ AD3552R_REG_ADDR_CH_SELECT_16B,
+ AD3552R_MASK_CH(ch), val);
if (err < 0)
return err;
@@ -970,8 +551,15 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
/* Disable unused channels */
for_each_clear_bit(ch, &dac->enabled_ch,
dac->model_data->num_hw_channels) {
- err = ad3552r_set_ch_value(dac, AD3552R_CH_AMPLIFIER_POWERDOWN,
- ch, 1);
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(0), 1);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(1), 1);
+
+ err = ad3552r_update_reg_field(dac,
+ AD3552R_REG_ADDR_POWERDOWN_CONFIG,
+ AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch),
+ val);
if (err)
return err;
}
@@ -1140,3 +728,4 @@ module_spi_driver(ad3552r_driver);
MODULE_AUTHOR("Mihail Chindris <mihail.chindris@analog.com>");
MODULE_DESCRIPTION("Analog Device AD3552R DAC");
MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(IIO_AD3552R);
diff --git a/drivers/iio/dac/ad3552r.h b/drivers/iio/dac/ad3552r.h
new file mode 100644
index 000000000000..fd5a3dfd1d1c
--- /dev/null
+++ b/drivers/iio/dac/ad3552r.h
@@ -0,0 +1,228 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AD3552R Digital <-> Analog converters common header
+ *
+ * Copyright 2021-2024 Analog Devices Inc.
+ * Author: Angelo Dureghello <adureghello@baylibre.com>
+ */
+
+#ifndef __DRIVERS_IIO_DAC_AD3552R_H__
+#define __DRIVERS_IIO_DAC_AD3552R_H__
+
+/* Register addresses */
+/* Primary address space */
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00
+#define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0))
+#define AD3552R_MASK_ADDR_ASCENSION BIT(5)
+#define AD3552R_MASK_SDO_ACTIVE BIT(4)
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01
+#define AD3552R_MASK_SINGLE_INST BIT(7)
+#define AD3552R_MASK_SHORT_INSTRUCTION BIT(3)
+#define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02
+#define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n))
+#define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2)
+#define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0)
+#define AD3552R_REG_ADDR_CHIP_TYPE 0x03
+#define AD3552R_MASK_CLASS GENMASK(7, 0)
+#define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04
+#define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05
+#define AD3552R_REG_ADDR_CHIP_GRADE 0x06
+#define AD3552R_MASK_GRADE GENMASK(7, 4)
+#define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0)
+#define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A
+#define AD3552R_REG_ADDR_SPI_REVISION 0x0B
+#define AD3552R_REG_ADDR_VENDOR_L 0x0C
+#define AD3552R_REG_ADDR_VENDOR_H 0x0D
+#define AD3552R_REG_ADDR_STREAM_MODE 0x0E
+#define AD3552R_MASK_LENGTH GENMASK(7, 0)
+#define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F
+#define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6)
+#define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2)
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10
+#define AD3552R_MASK_CRC_ENABLE \
+ (GENMASK(7, 6) | GENMASK(1, 0))
+#define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5)
+#define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11
+#define AD3552R_MASK_INTERFACE_NOT_READY BIT(7)
+#define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5)
+#define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3)
+#define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2)
+#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1)
+#define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0)
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14
+#define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6)
+#define AD3552R_MASK_MEM_CRC_EN BIT(4)
+#define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2)
+#define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1)
+#define AD3552R_MASK_SPI_CONFIG_DDR BIT(0)
+#define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15
+#define AD3552R_MASK_IDUMP_FAST_MODE BIT(6)
+#define AD3552R_MASK_SAMPLE_HOLD_DIFF_USER_EN BIT(5)
+#define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3)
+#define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2)
+#define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0)
+#define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16
+#define AD3552R_MASK_REF_RANGE_ALARM BIT(6)
+#define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5)
+#define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4)
+#define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3)
+#define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2)
+#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1)
+#define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0)
+#define AD3552R_REG_ADDR_ERR_STATUS 0x17
+#define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6)
+#define AD3552R_MASK_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5)
+#define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4)
+#define AD3552R_MASK_RESET_STATUS BIT(0)
+#define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18
+#define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch))
+#define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch)
+#define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19
+#define AD3552R_MASK_CH0_RANGE GENMASK(2, 0)
+#define AD3552R_MASK_CH1_RANGE GENMASK(6, 4)
+#define AD3552R_MASK_CH_OUTPUT_RANGE GENMASK(7, 0)
+#define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) \
+ ((ch) ? GENMASK(7, 4) : GENMASK(3, 0))
+#define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2)
+#define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0)
+#define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2)
+#define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7)
+#define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5)
+#define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3)
+#define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2)
+#define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(8)
+/*
+ * Secondary region
+ * For multibyte registers specify the highest address because the access is
+ * done in descending order
+ */
+#define AD3552R_SECONDARY_REGION_START 0x28
+#define AD3552R_REG_ADDR_HW_LDAC_16B 0x28
+#define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - (ch)) * 2)
+#define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E
+#define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F
+#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31
+#define AD3552R_REG_ADDR_SW_LDAC_16B 0x32
+#define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - (ch)) * 2)
+/* 3 bytes registers */
+#define AD3552R_REG_START_24B 0x37
+#define AD3552R_REG_ADDR_HW_LDAC_24B 0x37
+#define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - (ch)) * 3)
+#define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40
+#define AD3552R_REG_ADDR_CH_SELECT_24B 0x41
+#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44
+#define AD3552R_REG_ADDR_SW_LDAC_24B 0x45
+#define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - (ch)) * 3)
+
+#define AD3552R_MAX_CH 2
+#define AD3552R_MASK_CH(ch) BIT(ch)
+#define AD3552R_MASK_ALL_CH GENMASK(1, 0)
+#define AD3552R_MAX_REG_SIZE 3
+#define AD3552R_READ_BIT BIT(7)
+#define AD3552R_ADDR_MASK GENMASK(6, 0)
+#define AD3552R_MASK_DAC_12B GENMASK(15, 4)
+#define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8
+#define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34
+#define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2
+#define AD3552R_GAIN_SCALE 1000
+#define AD3552R_LDAC_PULSE_US 100
+
+#define AD3552R_CH0_ACTIVE BIT(0)
+#define AD3552R_CH1_ACTIVE BIT(1)
+
+#define AD3552R_MAX_RANGES 5
+#define AD3542R_MAX_RANGES 6
+#define AD3552R_QUAD_SPI 2
+
+extern const s32 ad3552r_ch_ranges[AD3552R_MAX_RANGES][2];
+extern const s32 ad3542r_ch_ranges[AD3542R_MAX_RANGES][2];
+
+enum ad3552r_id {
+ AD3541R_ID = 0x400b,
+ AD3542R_ID = 0x4009,
+ AD3551R_ID = 0x400a,
+ AD3552R_ID = 0x4008,
+};
+
+struct ad3552r_model_data {
+ const char *model_name;
+ enum ad3552r_id chip_id;
+ unsigned int num_hw_channels;
+ const s32 (*ranges_table)[2];
+ int num_ranges;
+ bool requires_output_range;
+};
+
+struct ad3552r_ch_data {
+ s32 scale_int;
+ s32 scale_dec;
+ s32 offset_int;
+ s32 offset_dec;
+ s16 gain_offset;
+ u16 rfb;
+ u8 n;
+ u8 p;
+ u8 range;
+ bool range_override;
+};
+
+enum ad3552r_ch_gain_scaling {
+ /* Gain scaling of 1 */
+ AD3552R_CH_GAIN_SCALING_1,
+ /* Gain scaling of 0.5 */
+ AD3552R_CH_GAIN_SCALING_0_5,
+ /* Gain scaling of 0.25 */
+ AD3552R_CH_GAIN_SCALING_0_25,
+ /* Gain scaling of 0.125 */
+ AD3552R_CH_GAIN_SCALING_0_125,
+};
+
+enum ad3552r_ch_vref_select {
+ /* Internal source with Vref I/O floating */
+ AD3552R_INTERNAL_VREF_PIN_FLOATING,
+ /* Internal source with Vref I/O at 2.5V */
+ AD3552R_INTERNAL_VREF_PIN_2P5V,
+ /* External source with Vref I/O as input */
+ AD3552R_EXTERNAL_VREF_PIN_INPUT
+};
+
+enum ad3542r_ch_output_range {
+ /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__2P5V,
+ /* Range from 0 V to 3 V. Requires Rfb1x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__3V,
+ /* Range from 0 V to 5 V. Requires Rfb1x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__5V,
+ /* Range from 0 V to 10 V. Requires Rfb2x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__10V,
+ /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */
+ AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V,
+ /* Range from -5 V to 5 V. Requires Rfb2x connection */
+ AD3542R_CH_OUTPUT_RANGE_NEG_5__5V,
+};
+
+enum ad3552r_ch_output_range {
+ /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
+ AD3552R_CH_OUTPUT_RANGE_0__2P5V,
+ /* Range from 0 V to 5 V. Requires Rfb1x connection */
+ AD3552R_CH_OUTPUT_RANGE_0__5V,
+ /* Range from 0 V to 10 V. Requires Rfb2x connection */
+ AD3552R_CH_OUTPUT_RANGE_0__10V,
+ /* Range from -5 V to 5 V. Requires Rfb2x connection */
+ AD3552R_CH_OUTPUT_RANGE_NEG_5__5V,
+ /* Range from -10 V to 10 V. Requires Rfb4x connection */
+ AD3552R_CH_OUTPUT_RANGE_NEG_10__10V,
+};
+
+int ad3552r_get_output_range(struct device *dev,
+ const struct ad3552r_model_data *model_info,
+ struct fwnode_handle *child, u32 *val);
+int ad3552r_get_custom_gain(struct device *dev, struct fwnode_handle *child,
+ u8 *gs_p, u8 *gs_n, u16 *rfb, s16 *goffs);
+u16 ad3552r_calc_custom_gain(u8 p, u8 n, s16 goffs);
+int ad3552r_get_ref_voltage(struct device *dev, u32 *val);
+int ad3552r_get_drive_strength(struct device *dev, u32 *val);
+void ad3552r_calc_gain_and_offset(struct ad3552r_ch_data *ch_data,
+ const struct ad3552r_model_data *model_data);
+
+#endif /* __DRIVERS_IIO_DAC_AD3552R_H__ */
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c
index 2e3e33f92bc0..392a1c7aee03 100644
--- a/drivers/iio/dac/ad5380.c
+++ b/drivers/iio/dac/ad5380.c
@@ -47,7 +47,6 @@ struct ad5380_chip_info {
* struct ad5380_state - driver instance specific data
* @regmap: regmap instance used by the device
* @chip_info: chip model specific constants, available modes etc
- * @vref_reg: vref supply regulator
* @vref: actual reference voltage used in uA
* @pwr_down: whether the chip is currently in power down mode
* @lock: lock to protect the data buffer during regmap ops
@@ -55,7 +54,6 @@ struct ad5380_chip_info {
struct ad5380_state {
struct regmap *regmap;
const struct ad5380_chip_info *chip_info;
- struct regulator *vref_reg;
int vref;
bool pwr_down;
struct mutex lock;
@@ -341,14 +339,14 @@ static const struct ad5380_chip_info ad5380_chip_info_tbl[] = {
},
};
-static int ad5380_alloc_channels(struct iio_dev *indio_dev)
+static int ad5380_alloc_channels(struct device *dev, struct iio_dev *indio_dev)
{
struct ad5380_state *st = iio_priv(indio_dev);
struct iio_chan_spec *channels;
unsigned int i;
- channels = kcalloc(st->chip_info->num_channels,
- sizeof(struct iio_chan_spec), GFP_KERNEL);
+ channels = devm_kcalloc(dev, st->chip_info->num_channels,
+ sizeof(struct iio_chan_spec), GFP_KERNEL);
if (!channels)
return -ENOMEM;
@@ -379,7 +377,6 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
}
st = iio_priv(indio_dev);
- dev_set_drvdata(dev, indio_dev);
st->chip_info = &ad5380_chip_info_tbl[type];
st->regmap = regmap;
@@ -391,68 +388,32 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
mutex_init(&st->lock);
- ret = ad5380_alloc_channels(indio_dev);
- if (ret) {
- dev_err(dev, "Failed to allocate channel spec: %d\n", ret);
- return ret;
- }
+ ret = ad5380_alloc_channels(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to allocate channel spec\n");
if (st->chip_info->int_vref == 2500)
ctrl |= AD5380_CTRL_INT_VREF_2V5;
- st->vref_reg = devm_regulator_get(dev, "vref");
- if (!IS_ERR(st->vref_reg)) {
- ret = regulator_enable(st->vref_reg);
- if (ret) {
- dev_err(dev, "Failed to enable vref regulators: %d\n",
- ret);
- goto error_free_reg;
- }
-
- ret = regulator_get_voltage(st->vref_reg);
- if (ret < 0)
- goto error_disable_reg;
-
- st->vref = ret / 1000;
- } else {
+ ret = devm_regulator_get_enable_read_voltage(dev, "vref");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "Failed to get vref voltage\n");
+ if (ret == -ENODEV) {
st->vref = st->chip_info->int_vref;
ctrl |= AD5380_CTRL_INT_VREF_EN;
+ } else {
+ st->vref = ret / 1000;
}
ret = regmap_write(st->regmap, AD5380_REG_SF_CTRL, ctrl);
- if (ret) {
- dev_err(dev, "Failed to write to device: %d\n", ret);
- goto error_disable_reg;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to write to device\n");
- ret = iio_device_register(indio_dev);
- if (ret) {
- dev_err(dev, "Failed to register iio device: %d\n", ret);
- goto error_disable_reg;
- }
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register iio device\n");
return 0;
-
-error_disable_reg:
- if (!IS_ERR(st->vref_reg))
- regulator_disable(st->vref_reg);
-error_free_reg:
- kfree(indio_dev->channels);
-
- return ret;
-}
-
-static void ad5380_remove(struct device *dev)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5380_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
-
- kfree(indio_dev->channels);
-
- if (!IS_ERR(st->vref_reg))
- regulator_disable(st->vref_reg);
}
static bool ad5380_reg_false(struct device *dev, unsigned int reg)
@@ -486,11 +447,6 @@ static int ad5380_spi_probe(struct spi_device *spi)
return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name);
}
-static void ad5380_spi_remove(struct spi_device *spi)
-{
- ad5380_remove(&spi->dev);
-}
-
static const struct spi_device_id ad5380_spi_ids[] = {
{ "ad5380-3", ID_AD5380_3 },
{ "ad5380-5", ID_AD5380_5 },
@@ -517,7 +473,6 @@ static struct spi_driver ad5380_spi_driver = {
.name = "ad5380",
},
.probe = ad5380_spi_probe,
- .remove = ad5380_spi_remove,
.id_table = ad5380_spi_ids,
};
@@ -559,11 +514,6 @@ static int ad5380_i2c_probe(struct i2c_client *i2c)
return ad5380_probe(&i2c->dev, regmap, id->driver_data, id->name);
}
-static void ad5380_i2c_remove(struct i2c_client *i2c)
-{
- ad5380_remove(&i2c->dev);
-}
-
static const struct i2c_device_id ad5380_i2c_ids[] = {
{ "ad5380-3", ID_AD5380_3 },
{ "ad5380-5", ID_AD5380_5 },
@@ -590,7 +540,6 @@ static struct i2c_driver ad5380_i2c_driver = {
.name = "ad5380",
},
.probe = ad5380_i2c_probe,
- .remove = ad5380_i2c_remove,
.id_table = ad5380_i2c_ids,
};
diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c
index 7644acfd879e..1462ee640b16 100644
--- a/drivers/iio/dac/ad5421.c
+++ b/drivers/iio/dac/ad5421.c
@@ -384,7 +384,7 @@ static int ad5421_write_raw(struct iio_dev *indio_dev,
static int ad5421_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct ad5421_state *st = iio_priv(indio_dev);
unsigned int mask;
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index 708629efc157..6ad99f97eed5 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -32,7 +32,6 @@
* struct ad5446_state - driver instance specific data
* @dev: this device
* @chip_info: chip model specific constants, available modes etc
- * @reg: supply regulator
* @vref_mv: actual reference voltage used
* @cached_val: store/retrieve values during power down
* @pwr_down_mode: power down mode (1k, 100k or tristate)
@@ -43,7 +42,6 @@
struct ad5446_state {
struct device *dev;
const struct ad5446_chip_info *chip_info;
- struct regulator *reg;
unsigned short vref_mv;
unsigned cached_val;
unsigned pwr_down_mode;
@@ -226,32 +224,15 @@ static int ad5446_probe(struct device *dev, const char *name,
{
struct ad5446_state *st;
struct iio_dev *indio_dev;
- struct regulator *reg;
- int ret, voltage_uv = 0;
-
- reg = devm_regulator_get(dev, "vcc");
- if (!IS_ERR(reg)) {
- ret = regulator_enable(reg);
- if (ret)
- return ret;
-
- ret = regulator_get_voltage(reg);
- if (ret < 0)
- goto error_disable_reg;
-
- voltage_uv = ret;
- }
+ int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_disable_reg;
- }
+ if (!indio_dev)
+ return -ENOMEM;
+
st = iio_priv(indio_dev);
st->chip_info = chip_info;
- dev_set_drvdata(dev, indio_dev);
- st->reg = reg;
st->dev = dev;
indio_dev->name = name;
@@ -264,33 +245,19 @@ static int ad5446_probe(struct device *dev, const char *name,
st->pwr_down_mode = MODE_PWRDWN_1k;
- if (st->chip_info->int_vref_mv)
- st->vref_mv = st->chip_info->int_vref_mv;
- else if (voltage_uv)
- st->vref_mv = voltage_uv / 1000;
- else
- dev_warn(dev, "reference voltage unspecified\n");
-
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_disable_reg;
-
- return 0;
-
-error_disable_reg:
- if (!IS_ERR(reg))
- regulator_disable(reg);
- return ret;
-}
-
-static void ad5446_remove(struct device *dev)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5446_state *st = iio_priv(indio_dev);
+ ret = devm_regulator_get_enable_read_voltage(dev, "vcc");
+ if (ret < 0 && ret != -ENODEV)
+ return ret;
+ if (ret == -ENODEV) {
+ if (chip_info->int_vref_mv)
+ st->vref_mv = chip_info->int_vref_mv;
+ else
+ dev_warn(dev, "reference voltage unspecified\n");
+ } else {
+ st->vref_mv = ret / 1000;
+ }
- iio_device_unregister(indio_dev);
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ return devm_iio_device_register(dev, indio_dev);
}
#if IS_ENABLED(CONFIG_SPI_MASTER)
@@ -491,18 +458,12 @@ static int ad5446_spi_probe(struct spi_device *spi)
&ad5446_spi_chip_info[id->driver_data]);
}
-static void ad5446_spi_remove(struct spi_device *spi)
-{
- ad5446_remove(&spi->dev);
-}
-
static struct spi_driver ad5446_spi_driver = {
.driver = {
.name = "ad5446",
.of_match_table = ad5446_of_ids,
},
.probe = ad5446_spi_probe,
- .remove = ad5446_spi_remove,
.id_table = ad5446_spi_ids,
};
@@ -575,11 +536,6 @@ static int ad5446_i2c_probe(struct i2c_client *i2c)
&ad5446_i2c_chip_info[id->driver_data]);
}
-static void ad5446_i2c_remove(struct i2c_client *i2c)
-{
- ad5446_remove(&i2c->dev);
-}
-
static const struct i2c_device_id ad5446_i2c_ids[] = {
{"ad5301", ID_AD5602},
{"ad5311", ID_AD5612},
@@ -596,7 +552,6 @@ static struct i2c_driver ad5446_i2c_driver = {
.name = "ad5446",
},
.probe = ad5446_i2c_probe,
- .remove = ad5446_i2c_remove,
.id_table = ad5446_i2c_ids,
};
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index e6c5be728bb2..ff0765c8af47 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -270,38 +270,29 @@ static const struct iio_chan_spec ad5504_channels[] = {
static int ad5504_probe(struct spi_device *spi)
{
- struct ad5504_platform_data *pdata = spi->dev.platform_data;
+ const struct ad5504_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad5504_state *st;
- struct regulator *reg;
- int ret, voltage_uv = 0;
+ int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
- reg = devm_regulator_get(&spi->dev, "vcc");
- if (!IS_ERR(reg)) {
- ret = regulator_enable(reg);
- if (ret)
- return ret;
- ret = regulator_get_voltage(reg);
- if (ret < 0)
- goto error_disable_reg;
+ st = iio_priv(indio_dev);
- voltage_uv = ret;
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcc");
+ if (ret < 0 && ret != -ENODEV)
+ return ret;
+ if (ret == -ENODEV) {
+ if (pdata->vref_mv)
+ st->vref_mv = pdata->vref_mv;
+ else
+ dev_warn(&spi->dev, "reference voltage unspecified\n");
+ } else {
+ st->vref_mv = ret / 1000;
}
- spi_set_drvdata(spi, indio_dev);
- st = iio_priv(indio_dev);
- if (voltage_uv)
- st->vref_mv = voltage_uv / 1000;
- else if (pdata)
- st->vref_mv = pdata->vref_mv;
- else
- dev_warn(&spi->dev, "reference voltage unspecified\n");
-
- st->reg = reg;
st->spi = spi;
indio_dev->name = spi_get_device_id(st->spi)->name;
indio_dev->info = &ad5504_info;
@@ -320,31 +311,10 @@ static int ad5504_probe(struct spi_device *spi)
spi_get_device_id(st->spi)->name,
indio_dev);
if (ret)
- goto error_disable_reg;
+ return ret;
}
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_disable_reg;
-
- return 0;
-
-error_disable_reg:
- if (!IS_ERR(reg))
- regulator_disable(reg);
-
- return ret;
-}
-
-static void ad5504_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad5504_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
-
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id ad5504_id[] = {
@@ -359,7 +329,6 @@ static struct spi_driver ad5504_driver = {
.name = "ad5504",
},
.probe = ad5504_probe,
- .remove = ad5504_remove,
.id_table = ad5504_id,
};
module_spi_driver(ad5504_driver);
diff --git a/drivers/iio/dac/ad5624r.h b/drivers/iio/dac/ad5624r.h
index 13964f3a22a4..14a439b06eb6 100644
--- a/drivers/iio/dac/ad5624r.h
+++ b/drivers/iio/dac/ad5624r.h
@@ -54,7 +54,6 @@ struct ad5624r_chip_info {
struct ad5624r_state {
struct spi_device *us;
const struct ad5624r_chip_info *chip_info;
- struct regulator *reg;
unsigned short vref_mv;
unsigned pwr_down_mask;
unsigned pwr_down_mode;
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index 9304d0499bae..2fd38ac8f698 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -223,50 +223,26 @@ static int ad5624r_probe(struct spi_device *spi)
{
struct ad5624r_state *st;
struct iio_dev *indio_dev;
- int ret, voltage_uv = 0;
+ bool external_vref;
+ int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
- st->reg = devm_regulator_get_optional(&spi->dev, "vref");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
- if (ret)
- return ret;
-
- ret = regulator_get_voltage(st->reg);
- if (ret < 0)
- goto error_disable_reg;
-
- voltage_uv = ret;
- } else {
- if (PTR_ERR(st->reg) != -ENODEV)
- return PTR_ERR(st->reg);
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
+ if (ret == -ENODEV)
/* Backwards compatibility. This naming is not correct */
- st->reg = devm_regulator_get_optional(&spi->dev, "vcc");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
- if (ret)
- return ret;
-
- ret = regulator_get_voltage(st->reg);
- if (ret < 0)
- goto error_disable_reg;
-
- voltage_uv = ret;
- }
- }
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcc");
+ if (ret < 0 && ret != -ENODEV)
+ return ret;
+
+ external_vref = ret != -ENODEV;
+ st->vref_mv = external_vref ? ret / 1000 : st->chip_info->int_vref_mv;
- spi_set_drvdata(spi, indio_dev);
st->chip_info =
&ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data];
- if (voltage_uv)
- st->vref_mv = voltage_uv / 1000;
- else
- st->vref_mv = st->chip_info->int_vref_mv;
-
st->us = spi;
indio_dev->name = spi_get_device_id(spi)->name;
@@ -276,31 +252,11 @@ static int ad5624r_probe(struct spi_device *spi)
indio_dev->num_channels = AD5624R_DAC_CHANNELS;
ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0,
- !!voltage_uv, 16);
- if (ret)
- goto error_disable_reg;
-
- ret = iio_device_register(indio_dev);
+ external_vref, 16);
if (ret)
- goto error_disable_reg;
-
- return 0;
-
-error_disable_reg:
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
-
- return ret;
-}
-
-static void ad5624r_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad5624r_state *st = iio_priv(indio_dev);
+ return ret;
- iio_device_unregister(indio_dev);
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id ad5624r_id[] = {
@@ -319,7 +275,6 @@ static struct spi_driver ad5624r_driver = {
.name = "ad5624r",
},
.probe = ad5624r_probe,
- .remove = ad5624r_remove,
.id_table = ad5624r_id,
};
module_spi_driver(ad5624r_driver);
diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c
index 0b24cb19ac9d..05e80b6ae2cc 100644
--- a/drivers/iio/dac/ad5755.c
+++ b/drivers/iio/dac/ad5755.c
@@ -699,7 +699,6 @@ static const struct ad5755_platform_data ad5755_default_pdata = {
static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev)
{
- struct fwnode_handle *pp;
struct ad5755_platform_data *pdata;
unsigned int tmp;
unsigned int tmparray[3];
@@ -746,11 +745,12 @@ static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev)
}
devnr = 0;
- device_for_each_child_node(dev, pp) {
+ device_for_each_child_node_scoped(dev, pp) {
if (devnr >= AD5755_NUM_CHANNELS) {
dev_err(dev,
"There are too many channels defined in DT\n");
- goto error_out;
+ devm_kfree(dev, pdata);
+ return NULL;
}
pdata->dac[devnr].mode = AD5755_MODE_CURRENT_4mA_20mA;
@@ -800,11 +800,6 @@ static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev)
}
return pdata;
-
- error_out:
- fwnode_handle_put(pp);
- devm_kfree(dev, pdata);
- return NULL;
}
static int ad5755_probe(struct spi_device *spi)
diff --git a/drivers/iio/dac/ad5761.c b/drivers/iio/dac/ad5761.c
index 6aa1a068adb0..0aa5ba7f4654 100644
--- a/drivers/iio/dac/ad5761.c
+++ b/drivers/iio/dac/ad5761.c
@@ -53,7 +53,6 @@ enum ad5761_supported_device_ids {
/**
* struct ad5761_state - driver instance specific data
* @spi: spi_device
- * @vref_reg: reference voltage regulator
* @use_intref: true when the internal voltage reference is used
* @vref: actual voltage reference in mVolts
* @range: output range mode used
@@ -62,7 +61,6 @@ enum ad5761_supported_device_ids {
*/
struct ad5761_state {
struct spi_device *spi;
- struct regulator *vref_reg;
struct mutex lock;
bool use_intref;
@@ -287,63 +285,6 @@ static const struct ad5761_chip_info ad5761_chip_infos[] = {
},
};
-static int ad5761_get_vref(struct ad5761_state *st,
- const struct ad5761_chip_info *chip_info)
-{
- int ret;
-
- st->vref_reg = devm_regulator_get_optional(&st->spi->dev, "vref");
- if (PTR_ERR(st->vref_reg) == -ENODEV) {
- /* Use Internal regulator */
- if (!chip_info->int_vref) {
- dev_err(&st->spi->dev,
- "Voltage reference not found\n");
- return -EIO;
- }
-
- st->use_intref = true;
- st->vref = chip_info->int_vref;
- return 0;
- }
-
- if (IS_ERR(st->vref_reg)) {
- dev_err(&st->spi->dev,
- "Error getting voltage reference regulator\n");
- return PTR_ERR(st->vref_reg);
- }
-
- ret = regulator_enable(st->vref_reg);
- if (ret) {
- dev_err(&st->spi->dev,
- "Failed to enable voltage reference\n");
- return ret;
- }
-
- ret = regulator_get_voltage(st->vref_reg);
- if (ret < 0) {
- dev_err(&st->spi->dev,
- "Failed to get voltage reference value\n");
- goto disable_regulator_vref;
- }
-
- if (ret < 2000000 || ret > 3000000) {
- dev_warn(&st->spi->dev,
- "Invalid external voltage ref. value %d uV\n", ret);
- ret = -EIO;
- goto disable_regulator_vref;
- }
-
- st->vref = ret / 1000;
- st->use_intref = false;
-
- return 0;
-
-disable_regulator_vref:
- regulator_disable(st->vref_reg);
- st->vref_reg = NULL;
- return ret;
-}
-
static int ad5761_probe(struct spi_device *spi)
{
struct iio_dev *iio_dev;
@@ -361,11 +302,28 @@ static int ad5761_probe(struct spi_device *spi)
st = iio_priv(iio_dev);
st->spi = spi;
- spi_set_drvdata(spi, iio_dev);
- ret = ad5761_get_vref(st, chip_info);
- if (ret)
- return ret;
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(&spi->dev, ret,
+ "Failed to get voltage reference value\n");
+ if (ret == -ENODEV) {
+ /* Use Internal regulator */
+ if (!chip_info->int_vref)
+ return dev_err_probe(&spi->dev, -EIO,
+ "Voltage reference not found\n");
+
+ st->use_intref = true;
+ st->vref = chip_info->int_vref;
+ } else {
+ if (ret < 2000000 || ret > 3000000)
+ return dev_err_probe(&spi->dev, -EIO,
+ "Invalid external voltage ref. value %d uV\n",
+ ret);
+
+ st->use_intref = false;
+ st->vref = ret / 1000;
+ }
if (pdata)
voltage_range = pdata->voltage_range;
@@ -374,35 +332,15 @@ static int ad5761_probe(struct spi_device *spi)
ret = ad5761_spi_set_range(st, voltage_range);
if (ret)
- goto disable_regulator_err;
+ return ret;
iio_dev->info = &ad5761_info;
iio_dev->modes = INDIO_DIRECT_MODE;
iio_dev->channels = &chip_info->channel;
iio_dev->num_channels = 1;
iio_dev->name = spi_get_device_id(st->spi)->name;
- ret = iio_device_register(iio_dev);
- if (ret)
- goto disable_regulator_err;
-
- return 0;
-
-disable_regulator_err:
- if (!IS_ERR_OR_NULL(st->vref_reg))
- regulator_disable(st->vref_reg);
-
- return ret;
-}
-
-static void ad5761_remove(struct spi_device *spi)
-{
- struct iio_dev *iio_dev = spi_get_drvdata(spi);
- struct ad5761_state *st = iio_priv(iio_dev);
-
- iio_device_unregister(iio_dev);
- if (!IS_ERR_OR_NULL(st->vref_reg))
- regulator_disable(st->vref_reg);
+ return devm_iio_device_register(&spi->dev, iio_dev);
}
static const struct spi_device_id ad5761_id[] = {
@@ -419,7 +357,6 @@ static struct spi_driver ad5761_driver = {
.name = "ad5761",
},
.probe = ad5761_probe,
- .remove = ad5761_remove,
.id_table = ad5761_id,
};
module_spi_driver(ad5761_driver);
diff --git a/drivers/iio/dac/ad5770r.c b/drivers/iio/dac/ad5770r.c
index c360ebf5297a..25cf11d0471b 100644
--- a/drivers/iio/dac/ad5770r.c
+++ b/drivers/iio/dac/ad5770r.c
@@ -17,6 +17,7 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
+#include <linux/unaligned.h>
#define ADI_SPI_IF_CONFIG_A 0x00
#define ADI_SPI_IF_CONFIG_B 0x01
@@ -121,7 +122,6 @@ struct ad5770r_out_range {
* struct ad5770r_state - driver instance specific data
* @spi: spi_device
* @regmap: regmap
- * @vref_reg: fixed regulator for reference configuration
* @gpio_reset: gpio descriptor
* @output_mode: array contains channels output ranges
* @vref: reference value
@@ -133,7 +133,6 @@ struct ad5770r_out_range {
struct ad5770r_state {
struct spi_device *spi;
struct regmap *regmap;
- struct regulator *vref_reg;
struct gpio_desc *gpio_reset;
struct ad5770r_out_range output_mode[AD5770R_MAX_CHANNELS];
int vref;
@@ -325,7 +324,7 @@ static int ad5770r_read_raw(struct iio_dev *indio_dev,
if (ret)
return 0;
- buf16 = st->transf_buf[0] + (st->transf_buf[1] << 8);
+ buf16 = get_unaligned_le16(st->transf_buf);
*val = buf16 >> 2;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
@@ -590,13 +589,6 @@ static int ad5770r_init(struct ad5770r_state *st)
return ret;
}
-static void ad5770r_disable_regulator(void *data)
-{
- struct ad5770r_state *st = data;
-
- regulator_disable(st->vref_reg);
-}
-
static int ad5770r_probe(struct spi_device *spi)
{
struct ad5770r_state *st;
@@ -621,34 +613,12 @@ static int ad5770r_probe(struct spi_device *spi)
}
st->regmap = regmap;
- st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref");
- if (!IS_ERR(st->vref_reg)) {
- ret = regulator_enable(st->vref_reg);
- if (ret) {
- dev_err(&spi->dev,
- "Failed to enable vref regulators: %d\n", ret);
- return ret;
- }
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(&spi->dev, ret, "Failed to get vref voltage\n");
- ret = devm_add_action_or_reset(&spi->dev,
- ad5770r_disable_regulator,
- st);
- if (ret < 0)
- return ret;
-
- ret = regulator_get_voltage(st->vref_reg);
- if (ret < 0)
- return ret;
-
- st->vref = ret / 1000;
- } else {
- if (PTR_ERR(st->vref_reg) == -ENODEV) {
- st->vref = AD5770R_LOW_VREF_mV;
- st->internal_ref = true;
- } else {
- return PTR_ERR(st->vref_reg);
- }
- }
+ st->internal_ref = ret == -ENODEV;
+ st->vref = st->internal_ref ? AD5770R_LOW_VREF_mV : ret / 1000;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->info = &ad5770r_info;
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c
index 75b549827e15..57374f78f6b8 100644
--- a/drivers/iio/dac/ad5791.c
+++ b/drivers/iio/dac/ad5791.c
@@ -9,6 +9,7 @@
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/device.h>
+#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
@@ -61,11 +62,14 @@
/**
* struct ad5791_chip_info - chip specific information
+ * @name: name of the dac chip
+ * @channel: channel specification
* @get_lin_comp: function pointer to the device specific function
*/
-
struct ad5791_chip_info {
- int (*get_lin_comp) (unsigned int span);
+ const char *name;
+ const struct iio_chan_spec channel;
+ int (*get_lin_comp)(unsigned int span);
};
/**
@@ -73,6 +77,9 @@ struct ad5791_chip_info {
* @spi: spi_device
* @reg_vdd: positive supply regulator
* @reg_vss: negative supply regulator
+ * @gpio_reset: reset gpio
+ * @gpio_clear: clear gpio
+ * @gpio_ldac: load dac gpio
* @chip_info: chip model specific constants
* @vref_mv: actual reference voltage used
* @vref_neg_mv: voltage of the negative supply
@@ -85,6 +92,9 @@ struct ad5791_state {
struct spi_device *spi;
struct regulator *reg_vdd;
struct regulator *reg_vss;
+ struct gpio_desc *gpio_reset;
+ struct gpio_desc *gpio_clear;
+ struct gpio_desc *gpio_ldac;
const struct ad5791_chip_info *chip_info;
unsigned short vref_mv;
unsigned int vref_neg_mv;
@@ -98,13 +108,6 @@ struct ad5791_state {
} data[3] __aligned(IIO_DMA_MINALIGN);
};
-enum ad5791_supported_device_ids {
- ID_AD5760,
- ID_AD5780,
- ID_AD5781,
- ID_AD5791,
-};
-
static int ad5791_spi_write(struct ad5791_state *st, u8 addr, u32 val)
{
st->data[0].d32 = cpu_to_be32(AD5791_CMD_WRITE |
@@ -228,20 +231,6 @@ static int ad5780_get_lin_comp(unsigned int span)
else
return AD5780_LINCOMP_10_20;
}
-static const struct ad5791_chip_info ad5791_chip_info_tbl[] = {
- [ID_AD5760] = {
- .get_lin_comp = ad5780_get_lin_comp,
- },
- [ID_AD5780] = {
- .get_lin_comp = ad5780_get_lin_comp,
- },
- [ID_AD5781] = {
- .get_lin_comp = ad5791_get_lin_comp,
- },
- [ID_AD5791] = {
- .get_lin_comp = ad5791_get_lin_comp,
- },
-};
static int ad5791_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -289,30 +278,34 @@ static const struct iio_chan_spec_ext_info ad5791_ext_info[] = {
{ },
};
-#define AD5791_CHAN(bits, _shift) { \
- .type = IIO_VOLTAGE, \
- .output = 1, \
- .indexed = 1, \
- .address = AD5791_ADDR_DAC0, \
- .channel = 0, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
- BIT(IIO_CHAN_INFO_OFFSET), \
- .scan_type = { \
- .sign = 'u', \
- .realbits = (bits), \
- .storagebits = 24, \
- .shift = (_shift), \
- }, \
- .ext_info = ad5791_ext_info, \
+#define AD5791_DEFINE_CHIP_INFO(_name, bits, _shift, _lin_comp) \
+static const struct ad5791_chip_info _name##_chip_info = { \
+ .name = #_name, \
+ .get_lin_comp = &(_lin_comp), \
+ .channel = { \
+ .type = IIO_VOLTAGE, \
+ .output = 1, \
+ .indexed = 1, \
+ .address = AD5791_ADDR_DAC0, \
+ .channel = 0, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_OFFSET), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = (bits), \
+ .storagebits = 24, \
+ .shift = (_shift), \
+ }, \
+ .ext_info = ad5791_ext_info, \
+ }, \
}
-static const struct iio_chan_spec ad5791_channels[] = {
- [ID_AD5760] = AD5791_CHAN(16, 4),
- [ID_AD5780] = AD5791_CHAN(18, 2),
- [ID_AD5781] = AD5791_CHAN(18, 2),
- [ID_AD5791] = AD5791_CHAN(20, 0)
-};
+AD5791_DEFINE_CHIP_INFO(ad5760, 16, 4, ad5780_get_lin_comp);
+AD5791_DEFINE_CHIP_INFO(ad5780, 18, 2, ad5780_get_lin_comp);
+AD5791_DEFINE_CHIP_INFO(ad5781, 18, 2, ad5791_get_lin_comp);
+AD5791_DEFINE_CHIP_INFO(ad5790, 20, 0, ad5791_get_lin_comp);
+AD5791_DEFINE_CHIP_INFO(ad5791, 20, 0, ad5791_get_lin_comp);
static int ad5791_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -341,7 +334,7 @@ static const struct iio_info ad5791_info = {
static int ad5791_probe(struct spi_device *spi)
{
- struct ad5791_platform_data *pdata = spi->dev.platform_data;
+ const struct ad5791_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad5791_state *st;
int ret, pos_voltage_uv = 0, neg_voltage_uv = 0;
@@ -351,31 +344,21 @@ static int ad5791_probe(struct spi_device *spi)
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
- st->reg_vdd = devm_regulator_get(&spi->dev, "vdd");
- if (!IS_ERR(st->reg_vdd)) {
- ret = regulator_enable(st->reg_vdd);
- if (ret)
- return ret;
-
- ret = regulator_get_voltage(st->reg_vdd);
- if (ret < 0)
- goto error_disable_reg_pos;
-
- pos_voltage_uv = ret;
- }
- st->reg_vss = devm_regulator_get(&spi->dev, "vss");
- if (!IS_ERR(st->reg_vss)) {
- ret = regulator_enable(st->reg_vss);
- if (ret)
- goto error_disable_reg_pos;
+ st->gpio_reset = devm_gpiod_get_optional(&spi->dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(st->gpio_reset))
+ return PTR_ERR(st->gpio_reset);
- ret = regulator_get_voltage(st->reg_vss);
- if (ret < 0)
- goto error_disable_reg_neg;
+ st->gpio_clear = devm_gpiod_get_optional(&spi->dev, "clear",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(st->gpio_clear))
+ return PTR_ERR(st->gpio_clear);
- neg_voltage_uv = ret;
- }
+ st->gpio_ldac = devm_gpiod_get_optional(&spi->dev, "ldac",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(st->gpio_ldac))
+ return PTR_ERR(st->gpio_ldac);
st->pwr_down = true;
st->spi = spi;
@@ -386,7 +369,17 @@ static int ad5791_probe(struct spi_device *spi)
use_rbuf_gain2 = device_property_read_bool(&spi->dev,
"adi,rbuf-gain2-en");
- if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) {
+ pos_voltage_uv = devm_regulator_get_enable_read_voltage(&spi->dev, "vdd");
+ if (pos_voltage_uv < 0 && pos_voltage_uv != -ENODEV)
+ return dev_err_probe(&spi->dev, pos_voltage_uv,
+ "failed to get vdd voltage\n");
+
+ neg_voltage_uv = devm_regulator_get_enable_read_voltage(&spi->dev, "vss");
+ if (neg_voltage_uv < 0 && neg_voltage_uv != -ENODEV)
+ return dev_err_probe(&spi->dev, neg_voltage_uv,
+ "failed to get vss voltage\n");
+
+ if (neg_voltage_uv >= 0 && pos_voltage_uv >= 0) {
st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000;
st->vref_neg_mv = neg_voltage_uv / 1000;
} else if (pdata) {
@@ -396,13 +389,18 @@ static int ad5791_probe(struct spi_device *spi)
dev_warn(&spi->dev, "reference voltage unspecified\n");
}
- ret = ad5791_spi_write(st, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
- if (ret)
- goto error_disable_reg_neg;
-
- st->chip_info = &ad5791_chip_info_tbl[spi_get_device_id(spi)
- ->driver_data];
+ if (st->gpio_reset) {
+ fsleep(20);
+ gpiod_set_value_cansleep(st->gpio_reset, 0);
+ } else {
+ ret = ad5791_spi_write(st, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
+ if (ret)
+ return dev_err_probe(&spi->dev, ret, "fail to reset\n");
+ }
+ st->chip_info = spi_get_device_match_data(spi);
+ if (!st->chip_info)
+ return dev_err_probe(&spi->dev, -EINVAL, "no chip info\n");
st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv))
| (use_rbuf_gain2 ? 0 : AD5791_CTRL_RBUF) |
@@ -411,59 +409,42 @@ static int ad5791_probe(struct spi_device *spi)
ret = ad5791_spi_write(st, AD5791_ADDR_CTRL, st->ctrl |
AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
if (ret)
- goto error_disable_reg_neg;
+ return dev_err_probe(&spi->dev, ret, "fail to write ctrl register\n");
- spi_set_drvdata(spi, indio_dev);
indio_dev->info = &ad5791_info;
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->channels
- = &ad5791_channels[spi_get_device_id(spi)->driver_data];
+ indio_dev->channels = &st->chip_info->channel;
indio_dev->num_channels = 1;
- indio_dev->name = spi_get_device_id(st->spi)->name;
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_disable_reg_neg;
-
- return 0;
-
-error_disable_reg_neg:
- if (!IS_ERR(st->reg_vss))
- regulator_disable(st->reg_vss);
-error_disable_reg_pos:
- if (!IS_ERR(st->reg_vdd))
- regulator_disable(st->reg_vdd);
- return ret;
+ indio_dev->name = st->chip_info->name;
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
-static void ad5791_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad5791_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
- if (!IS_ERR(st->reg_vdd))
- regulator_disable(st->reg_vdd);
-
- if (!IS_ERR(st->reg_vss))
- regulator_disable(st->reg_vss);
-}
+static const struct of_device_id ad5791_of_match[] = {
+ { .compatible = "adi,ad5760", .data = &ad5760_chip_info },
+ { .compatible = "adi,ad5780", .data = &ad5780_chip_info },
+ { .compatible = "adi,ad5781", .data = &ad5781_chip_info },
+ { .compatible = "adi,ad5790", .data = &ad5790_chip_info },
+ { .compatible = "adi,ad5791", .data = &ad5791_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad5791_of_match);
static const struct spi_device_id ad5791_id[] = {
- {"ad5760", ID_AD5760},
- {"ad5780", ID_AD5780},
- {"ad5781", ID_AD5781},
- {"ad5790", ID_AD5791},
- {"ad5791", ID_AD5791},
- {}
+ { "ad5760", (kernel_ulong_t)&ad5760_chip_info },
+ { "ad5780", (kernel_ulong_t)&ad5780_chip_info },
+ { "ad5781", (kernel_ulong_t)&ad5781_chip_info },
+ { "ad5790", (kernel_ulong_t)&ad5790_chip_info },
+ { "ad5791", (kernel_ulong_t)&ad5791_chip_info },
+ { }
};
MODULE_DEVICE_TABLE(spi, ad5791_id);
static struct spi_driver ad5791_driver = {
.driver = {
.name = "ad5791",
+ .of_match_table = ad5791_of_match,
},
.probe = ad5791_probe,
- .remove = ad5791_remove,
.id_table = ad5791_id,
};
module_spi_driver(ad5791_driver);
diff --git a/drivers/iio/dac/ad8460.c b/drivers/iio/dac/ad8460.c
new file mode 100644
index 000000000000..f235394589df
--- /dev/null
+++ b/drivers/iio/dac/ad8460.c
@@ -0,0 +1,951 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AD8460 Waveform generator DAC Driver
+ *
+ * Copyright (C) 2024 Analog Devices, Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/gpio/consumer.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/buffer-dma.h>
+#include <linux/iio/buffer-dmaengine.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+
+#define AD8460_CTRL_REG(x) (x)
+#define AD8460_HVDAC_DATA_WORD(x) (0x60 + (2 * (x)))
+
+#define AD8460_HV_RESET_MSK BIT(7)
+#define AD8460_HV_SLEEP_MSK BIT(4)
+#define AD8460_WAVE_GEN_MODE_MSK BIT(0)
+
+#define AD8460_HVDAC_SLEEP_MSK BIT(3)
+
+#define AD8460_FAULT_ARM_MSK BIT(7)
+#define AD8460_FAULT_LIMIT_MSK GENMASK(6, 0)
+
+#define AD8460_APG_MODE_ENABLE_MSK BIT(5)
+#define AD8460_PATTERN_DEPTH_MSK GENMASK(3, 0)
+
+#define AD8460_QUIESCENT_CURRENT_MSK GENMASK(7, 0)
+
+#define AD8460_SHUTDOWN_FLAG_MSK BIT(7)
+
+#define AD8460_DATA_BYTE_LOW_MSK GENMASK(7, 0)
+#define AD8460_DATA_BYTE_HIGH_MSK GENMASK(5, 0)
+#define AD8460_DATA_BYTE_FULL_MSK GENMASK(13, 0)
+
+#define AD8460_DEFAULT_FAULT_PROTECT 0x00
+#define AD8460_DATA_BYTE_WORD_LENGTH 2
+#define AD8460_NUM_DATA_WORDS 16
+#define AD8460_NOMINAL_VOLTAGE_SPAN 80
+#define AD8460_MIN_EXT_RESISTOR_OHMS 2000
+#define AD8460_MAX_EXT_RESISTOR_OHMS 20000
+#define AD8460_MIN_VREFIO_UV 120000
+#define AD8460_MAX_VREFIO_UV 1200000
+#define AD8460_ABS_MAX_OVERVOLTAGE_UV 55000000
+#define AD8460_ABS_MAX_OVERCURRENT_UA 1000000
+#define AD8460_MAX_OVERTEMPERATURE_MC 150000
+#define AD8460_MIN_OVERTEMPERATURE_MC 20000
+#define AD8460_CURRENT_LIMIT_CONV(x) ((x) / 15625)
+#define AD8460_VOLTAGE_LIMIT_CONV(x) ((x) / 1953000)
+#define AD8460_TEMP_LIMIT_CONV(x) (((x) + 266640) / 6510)
+
+enum ad8460_fault_type {
+ AD8460_OVERCURRENT_SRC,
+ AD8460_OVERCURRENT_SNK,
+ AD8460_OVERVOLTAGE_POS,
+ AD8460_OVERVOLTAGE_NEG,
+ AD8460_OVERTEMPERATURE,
+};
+
+struct ad8460_state {
+ struct spi_device *spi;
+ struct regmap *regmap;
+ struct iio_channel *tmp_adc_channel;
+ struct clk *sync_clk;
+ /* lock to protect against multiple access to the device and shared data */
+ struct mutex lock;
+ int refio_1p2v_mv;
+ u32 ext_resistor_ohms;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ __le16 spi_tx_buf __aligned(IIO_DMA_MINALIGN);
+};
+
+static int ad8460_hv_reset(struct ad8460_state *state)
+{
+ int ret;
+
+ ret = regmap_set_bits(state->regmap, AD8460_CTRL_REG(0x00),
+ AD8460_HV_RESET_MSK);
+ if (ret)
+ return ret;
+
+ fsleep(20);
+
+ return regmap_clear_bits(state->regmap, AD8460_CTRL_REG(0x00),
+ AD8460_HV_RESET_MSK);
+}
+
+static int ad8460_reset(const struct ad8460_state *state)
+{
+ struct device *dev = &state->spi->dev;
+ struct gpio_desc *reset;
+
+ reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(reset))
+ return dev_err_probe(dev, PTR_ERR(reset),
+ "Failed to get reset gpio");
+ if (reset) {
+ /* minimum duration of 10ns */
+ ndelay(10);
+ gpiod_set_value_cansleep(reset, 1);
+ return 0;
+ }
+
+ /* bring all registers to their default state */
+ return regmap_write(state->regmap, AD8460_CTRL_REG(0x03), 1);
+}
+
+static int ad8460_enable_apg_mode(struct ad8460_state *state, int val)
+{
+ int ret;
+
+ ret = regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x02),
+ AD8460_APG_MODE_ENABLE_MSK,
+ FIELD_PREP(AD8460_APG_MODE_ENABLE_MSK, val));
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x00),
+ AD8460_WAVE_GEN_MODE_MSK,
+ FIELD_PREP(AD8460_WAVE_GEN_MODE_MSK, val));
+}
+
+static int ad8460_read_shutdown_flag(struct ad8460_state *state, u64 *flag)
+{
+ int ret, val;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x0E), &val);
+ if (ret)
+ return ret;
+
+ *flag = FIELD_GET(AD8460_SHUTDOWN_FLAG_MSK, val);
+ return 0;
+}
+
+static int ad8460_get_hvdac_word(struct ad8460_state *state, int index, int *val)
+{
+ int ret;
+
+ ret = regmap_bulk_read(state->regmap, AD8460_HVDAC_DATA_WORD(index),
+ &state->spi_tx_buf, AD8460_DATA_BYTE_WORD_LENGTH);
+ if (ret)
+ return ret;
+
+ *val = le16_to_cpu(state->spi_tx_buf);
+
+ return ret;
+}
+
+static int ad8460_set_hvdac_word(struct ad8460_state *state, int index, int val)
+{
+ state->spi_tx_buf = cpu_to_le16(FIELD_PREP(AD8460_DATA_BYTE_FULL_MSK, val));
+
+ return regmap_bulk_write(state->regmap, AD8460_HVDAC_DATA_WORD(index),
+ &state->spi_tx_buf, AD8460_DATA_BYTE_WORD_LENGTH);
+}
+
+static ssize_t ad8460_dac_input_read(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = ad8460_get_hvdac_word(state, private, &reg);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%u\n", reg);
+}
+
+static ssize_t ad8460_dac_input_write(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = kstrtou32(buf, 10, &reg);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&state->lock);
+
+ return ad8460_set_hvdac_word(state, private, reg);
+}
+
+static ssize_t ad8460_read_symbol(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x02), &reg);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%lu\n", FIELD_GET(AD8460_PATTERN_DEPTH_MSK, reg));
+}
+
+static ssize_t ad8460_write_symbol(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ uint16_t sym;
+ int ret;
+
+ ret = kstrtou16(buf, 10, &sym);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&state->lock);
+
+ return regmap_update_bits(state->regmap,
+ AD8460_CTRL_REG(0x02),
+ AD8460_PATTERN_DEPTH_MSK,
+ FIELD_PREP(AD8460_PATTERN_DEPTH_MSK, sym));
+}
+
+static ssize_t ad8460_read_toggle_en(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x02), &reg);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%ld\n", FIELD_GET(AD8460_APG_MODE_ENABLE_MSK, reg));
+}
+
+static ssize_t ad8460_write_toggle_en(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ bool toggle_en;
+ int ret;
+
+ ret = kstrtobool(buf, &toggle_en);
+ if (ret)
+ return ret;
+
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
+ return ad8460_enable_apg_mode(state, toggle_en);
+ unreachable();
+}
+
+static ssize_t ad8460_read_powerdown(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x01), &reg);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%ld\n", FIELD_GET(AD8460_HVDAC_SLEEP_MSK, reg));
+}
+
+static ssize_t ad8460_write_powerdown(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ bool pwr_down;
+ u64 sdn_flag;
+ int ret;
+
+ ret = kstrtobool(buf, &pwr_down);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&state->lock);
+
+ /*
+ * If powerdown is set, HVDAC is enabled and the HV driver is
+ * enabled via HV_RESET in case it is in shutdown mode,
+ * If powerdown is cleared, HVDAC is set to shutdown state
+ * as well as the HV driver. Quiescent current decreases and ouput is
+ * floating (high impedance).
+ */
+
+ ret = regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x01),
+ AD8460_HVDAC_SLEEP_MSK,
+ FIELD_PREP(AD8460_HVDAC_SLEEP_MSK, pwr_down));
+ if (ret)
+ return ret;
+
+ if (!pwr_down) {
+ ret = ad8460_read_shutdown_flag(state, &sdn_flag);
+ if (ret)
+ return ret;
+
+ if (sdn_flag) {
+ ret = ad8460_hv_reset(state);
+ if (ret)
+ return ret;
+ }
+ }
+
+ ret = regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x00),
+ AD8460_HV_SLEEP_MSK,
+ FIELD_PREP(AD8460_HV_SLEEP_MSK, !pwr_down));
+ if (ret)
+ return ret;
+
+ return len;
+}
+
+static const char * const ad8460_powerdown_modes[] = {
+ "three_state",
+};
+
+static int ad8460_get_powerdown_mode(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ return 0;
+}
+
+static int ad8460_set_powerdown_mode(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ unsigned int type)
+{
+ return 0;
+}
+
+static int ad8460_set_sample(struct ad8460_state *state, int val)
+{
+ int ret;
+
+ ret = ad8460_enable_apg_mode(state, 1);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&state->lock);
+ ret = ad8460_set_hvdac_word(state, 0, val);
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x02),
+ AD8460_PATTERN_DEPTH_MSK,
+ FIELD_PREP(AD8460_PATTERN_DEPTH_MSK, 0));
+}
+
+static int ad8460_set_fault_threshold(struct ad8460_state *state,
+ enum ad8460_fault_type fault,
+ unsigned int threshold)
+{
+ return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x08 + fault),
+ AD8460_FAULT_LIMIT_MSK,
+ FIELD_PREP(AD8460_FAULT_LIMIT_MSK, threshold));
+}
+
+static int ad8460_get_fault_threshold(struct ad8460_state *state,
+ enum ad8460_fault_type fault,
+ unsigned int *threshold)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x08 + fault), &val);
+ if (ret)
+ return ret;
+
+ *threshold = FIELD_GET(AD8460_FAULT_LIMIT_MSK, val);
+
+ return ret;
+}
+
+static int ad8460_set_fault_threshold_en(struct ad8460_state *state,
+ enum ad8460_fault_type fault, bool en)
+{
+ return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x08 + fault),
+ AD8460_FAULT_ARM_MSK,
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, en));
+}
+
+static int ad8460_get_fault_threshold_en(struct ad8460_state *state,
+ enum ad8460_fault_type fault, bool *en)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x08 + fault), &val);
+ if (ret)
+ return ret;
+
+ *en = FIELD_GET(AD8460_FAULT_ARM_MSK, val);
+
+ return 0;
+}
+
+static int ad8460_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2,
+ long mask)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_VOLTAGE:
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
+ return ad8460_set_sample(state, val);
+ unreachable();
+ case IIO_CURRENT:
+ return regmap_write(state->regmap, AD8460_CTRL_REG(0x04),
+ FIELD_PREP(AD8460_QUIESCENT_CURRENT_MSK, val));
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad8460_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int data, ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_VOLTAGE:
+ scoped_guard(mutex, &state->lock) {
+ ret = ad8460_get_hvdac_word(state, 0, &data);
+ if (ret)
+ return ret;
+ }
+ *val = data;
+ return IIO_VAL_INT;
+ case IIO_CURRENT:
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x04),
+ &data);
+ if (ret)
+ return ret;
+ *val = data;
+ return IIO_VAL_INT;
+ case IIO_TEMP:
+ ret = iio_read_channel_raw(state->tmp_adc_channel, &data);
+ if (ret)
+ return ret;
+ *val = data;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = clk_get_rate(state->sync_clk);
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ /*
+ * vCONV = vNOMINAL_SPAN * (DAC_CODE / 2**14) - 40V
+ * vMAX = vNOMINAL_SPAN * (2**14 / 2**14) - 40V
+ * vMIN = vNOMINAL_SPAN * (0 / 2**14) - 40V
+ * vADJ = vCONV * (2000 / rSET) * (vREF / 1.2)
+ * vSPAN = vADJ_MAX - vADJ_MIN
+ * See datasheet page 49, section FULL-SCALE REDUCTION
+ */
+ *val = AD8460_NOMINAL_VOLTAGE_SPAN * 2000 * state->refio_1p2v_mv;
+ *val2 = state->ext_resistor_ohms * 1200;
+ return IIO_VAL_FRACTIONAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad8460_select_fault_type(int chan_type, enum iio_event_direction dir)
+{
+ switch (chan_type) {
+ case IIO_VOLTAGE:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return AD8460_OVERVOLTAGE_POS;
+ case IIO_EV_DIR_FALLING:
+ return AD8460_OVERVOLTAGE_NEG;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CURRENT:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return AD8460_OVERCURRENT_SRC;
+ case IIO_EV_DIR_FALLING:
+ return AD8460_OVERCURRENT_SNK;
+ default:
+ return -EINVAL;
+ }
+ case IIO_TEMP:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return AD8460_OVERTEMPERATURE;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad8460_write_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info, int val, int val2)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int fault;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ if (info != IIO_EV_INFO_VALUE)
+ return -EINVAL;
+
+ fault = ad8460_select_fault_type(chan->type, dir);
+ if (fault < 0)
+ return fault;
+
+ return ad8460_set_fault_threshold(state, fault, val);
+}
+
+static int ad8460_read_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info, int *val, int *val2)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int fault;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ if (info != IIO_EV_INFO_VALUE)
+ return -EINVAL;
+
+ fault = ad8460_select_fault_type(chan->type, dir);
+ if (fault < 0)
+ return fault;
+
+ return ad8460_get_fault_threshold(state, fault, val);
+}
+
+static int ad8460_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir, bool val)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int fault;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ fault = ad8460_select_fault_type(chan->type, dir);
+ if (fault < 0)
+ return fault;
+
+ return ad8460_set_fault_threshold_en(state, fault, val);
+}
+
+static int ad8460_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int fault, ret;
+ bool en;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ fault = ad8460_select_fault_type(chan->type, dir);
+ if (fault < 0)
+ return fault;
+
+ ret = ad8460_get_fault_threshold_en(state, fault, &en);
+ if (ret)
+ return ret;
+
+ return en;
+}
+
+static int ad8460_reg_access(struct iio_dev *indio_dev, unsigned int reg,
+ unsigned int writeval, unsigned int *readval)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+
+ if (readval)
+ return regmap_read(state->regmap, reg, readval);
+
+ return regmap_write(state->regmap, reg, writeval);
+}
+
+static int ad8460_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+
+ return ad8460_enable_apg_mode(state, 0);
+}
+
+static int ad8460_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+
+ return ad8460_enable_apg_mode(state, 1);
+}
+
+static const struct iio_buffer_setup_ops ad8460_buffer_setup_ops = {
+ .preenable = &ad8460_buffer_preenable,
+ .postdisable = &ad8460_buffer_postdisable,
+};
+
+static const struct iio_info ad8460_info = {
+ .read_raw = &ad8460_read_raw,
+ .write_raw = &ad8460_write_raw,
+ .write_event_value = &ad8460_write_event_value,
+ .read_event_value = &ad8460_read_event_value,
+ .write_event_config = &ad8460_write_event_config,
+ .read_event_config = &ad8460_read_event_config,
+ .debugfs_reg_access = &ad8460_reg_access,
+};
+
+static const struct iio_enum ad8460_powerdown_mode_enum = {
+ .items = ad8460_powerdown_modes,
+ .num_items = ARRAY_SIZE(ad8460_powerdown_modes),
+ .get = ad8460_get_powerdown_mode,
+ .set = ad8460_set_powerdown_mode,
+};
+
+#define AD8460_CHAN_EXT_INFO(_name, _what, _read, _write) { \
+ .name = (_name), \
+ .read = (_read), \
+ .write = (_write), \
+ .private = (_what), \
+ .shared = IIO_SEPARATE, \
+}
+
+static const struct iio_chan_spec_ext_info ad8460_ext_info[] = {
+ AD8460_CHAN_EXT_INFO("raw0", 0, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw1", 1, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw2", 2, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw3", 3, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw4", 4, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw5", 5, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw6", 6, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw7", 7, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw8", 8, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw9", 9, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw10", 10, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw11", 11, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw12", 12, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw13", 13, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw14", 14, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw15", 15, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("toggle_en", 0, ad8460_read_toggle_en,
+ ad8460_write_toggle_en),
+ AD8460_CHAN_EXT_INFO("symbol", 0, ad8460_read_symbol,
+ ad8460_write_symbol),
+ AD8460_CHAN_EXT_INFO("powerdown", 0, ad8460_read_powerdown,
+ ad8460_write_powerdown),
+ IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad8460_powerdown_mode_enum),
+ IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,
+ &ad8460_powerdown_mode_enum),
+ { }
+};
+
+static const struct iio_event_spec ad8460_events[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+};
+
+#define AD8460_VOLTAGE_CHAN { \
+ .type = IIO_VOLTAGE, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = 0, \
+ .scan_index = 0, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 14, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+ .ext_info = ad8460_ext_info, \
+ .event_spec = ad8460_events, \
+ .num_event_specs = ARRAY_SIZE(ad8460_events), \
+}
+
+#define AD8460_CURRENT_CHAN { \
+ .type = IIO_CURRENT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = 0, \
+ .scan_index = -1, \
+ .event_spec = ad8460_events, \
+ .num_event_specs = ARRAY_SIZE(ad8460_events), \
+}
+
+#define AD8460_TEMP_CHAN { \
+ .type = IIO_TEMP, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .indexed = 1, \
+ .channel = 0, \
+ .scan_index = -1, \
+ .event_spec = ad8460_events, \
+ .num_event_specs = 1, \
+}
+
+static const struct iio_chan_spec ad8460_channels[] = {
+ AD8460_VOLTAGE_CHAN,
+ AD8460_CURRENT_CHAN,
+};
+
+static const struct iio_chan_spec ad8460_channels_with_tmp_adc[] = {
+ AD8460_VOLTAGE_CHAN,
+ AD8460_CURRENT_CHAN,
+ AD8460_TEMP_CHAN,
+};
+
+static const struct regmap_config ad8460_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x7F,
+};
+
+static const char * const ad8460_supplies[] = {
+ "avdd_3p3v", "dvdd_3p3v", "vcc_5v", "hvcc", "hvee", "vref_5v"
+};
+
+static int ad8460_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct ad8460_state *state;
+ struct iio_dev *indio_dev;
+ u32 tmp[2], temp;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ state = iio_priv(indio_dev);
+
+ indio_dev->name = "ad8460";
+ indio_dev->info = &ad8460_info;
+
+ state->spi = spi;
+
+ state->regmap = devm_regmap_init_spi(spi, &ad8460_regmap_config);
+ if (IS_ERR(state->regmap))
+ return dev_err_probe(dev, PTR_ERR(state->regmap),
+ "Failed to initialize regmap");
+
+ ret = devm_mutex_init(dev, &state->lock);
+ if (ret)
+ return ret;
+
+ state->sync_clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(state->sync_clk))
+ return dev_err_probe(dev, PTR_ERR(state->sync_clk),
+ "Failed to get sync clk\n");
+
+ state->tmp_adc_channel = devm_iio_channel_get(dev, "ad8460-tmp");
+ if (IS_ERR(state->tmp_adc_channel)) {
+ if (PTR_ERR(state->tmp_adc_channel) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ indio_dev->channels = ad8460_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad8460_channels);
+ } else {
+ indio_dev->channels = ad8460_channels_with_tmp_adc;
+ indio_dev->num_channels = ARRAY_SIZE(ad8460_channels_with_tmp_adc);
+ }
+
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad8460_supplies),
+ ad8460_supplies);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to enable power supplies\n");
+
+ ret = devm_regulator_get_enable_read_voltage(dev, "refio_1p2v");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "Failed to get reference voltage\n");
+
+ state->refio_1p2v_mv = ret == -ENODEV ? 1200 : ret / 1000;
+
+ if (!in_range(state->refio_1p2v_mv, AD8460_MIN_VREFIO_UV / 1000,
+ AD8460_MAX_VREFIO_UV / 1000))
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid ref voltage range(%u mV) [%u mV, %u mV]\n",
+ state->refio_1p2v_mv,
+ AD8460_MIN_VREFIO_UV / 1000,
+ AD8460_MAX_VREFIO_UV / 1000);
+
+ ret = device_property_read_u32(dev, "adi,external-resistor-ohms",
+ &state->ext_resistor_ohms);
+ if (ret)
+ state->ext_resistor_ohms = 2000;
+ else if (!in_range(state->ext_resistor_ohms, AD8460_MIN_EXT_RESISTOR_OHMS,
+ AD8460_MAX_EXT_RESISTOR_OHMS))
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid resistor set range(%u) [%u, %u]\n",
+ state->ext_resistor_ohms,
+ AD8460_MIN_EXT_RESISTOR_OHMS,
+ AD8460_MAX_EXT_RESISTOR_OHMS);
+
+ ret = device_property_read_u32_array(dev, "adi,range-microamp",
+ tmp, ARRAY_SIZE(tmp));
+ if (!ret) {
+ if (in_range(tmp[1], 0, AD8460_ABS_MAX_OVERCURRENT_UA))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x08),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_CURRENT_LIMIT_CONV(tmp[1]));
+
+ if (in_range(tmp[0], -AD8460_ABS_MAX_OVERCURRENT_UA, 0))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x09),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_CURRENT_LIMIT_CONV(abs(tmp[0])));
+ }
+
+ ret = device_property_read_u32_array(dev, "adi,range-microvolt",
+ tmp, ARRAY_SIZE(tmp));
+ if (!ret) {
+ if (in_range(tmp[1], 0, AD8460_ABS_MAX_OVERVOLTAGE_UV))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x0A),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_VOLTAGE_LIMIT_CONV(tmp[1]));
+
+ if (in_range(tmp[0], -AD8460_ABS_MAX_OVERVOLTAGE_UV, 0))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x0B),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_VOLTAGE_LIMIT_CONV(abs(tmp[0])));
+ }
+
+ ret = device_property_read_u32(dev, "adi,max-millicelsius", &temp);
+ if (!ret) {
+ if (in_range(temp, AD8460_MIN_OVERTEMPERATURE_MC,
+ AD8460_MAX_OVERTEMPERATURE_MC))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x0C),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_TEMP_LIMIT_CONV(abs(temp)));
+ }
+
+ ret = ad8460_reset(state);
+ if (ret)
+ return ret;
+
+ /* Enables DAC by default */
+ ret = regmap_clear_bits(state->regmap, AD8460_CTRL_REG(0x01),
+ AD8460_HVDAC_SLEEP_MSK);
+ if (ret)
+ return ret;
+
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->setup_ops = &ad8460_buffer_setup_ops;
+
+ ret = devm_iio_dmaengine_buffer_setup_ext(dev, indio_dev, "tx",
+ IIO_BUFFER_DIRECTION_OUT);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to get DMA buffer\n");
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct of_device_id ad8460_of_match[] = {
+ { .compatible = "adi,ad8460" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad8460_of_match);
+
+static const struct spi_device_id ad8460_spi_match[] = {
+ { .name = "ad8460" },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ad8460_spi_match);
+
+static struct spi_driver ad8460_driver = {
+ .driver = {
+ .name = "ad8460",
+ .of_match_table = ad8460_of_match,
+ },
+ .probe = ad8460_probe,
+ .id_table = ad8460_spi_match,
+};
+module_spi_driver(ad8460_driver);
+
+MODULE_AUTHOR("Mariel Tinaco <mariel.tinaco@analog.com");
+MODULE_DESCRIPTION("AD8460 DAC driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER);
diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
index 0cb00f3bec04..dd1919441b6d 100644
--- a/drivers/iio/dac/adi-axi-dac.c
+++ b/drivers/iio/dac/adi-axi-dac.c
@@ -29,44 +29,77 @@
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
+#include "ad3552r-hs.h"
+
/*
* Register definitions:
* https://wiki.analog.com/resources/fpga/docs/axi_dac_ip#register_map
*/
/* Base controls */
-#define AXI_DAC_REG_CONFIG 0x0c
-#define AXI_DDS_DISABLE BIT(6)
+#define AXI_DAC_CONFIG_REG 0x0c
+#define AXI_DAC_CONFIG_DDS_DISABLE BIT(6)
/* DAC controls */
-#define AXI_DAC_REG_RSTN 0x0040
-#define AXI_DAC_RSTN_CE_N BIT(2)
-#define AXI_DAC_RSTN_MMCM_RSTN BIT(1)
-#define AXI_DAC_RSTN_RSTN BIT(0)
-#define AXI_DAC_REG_CNTRL_1 0x0044
-#define AXI_DAC_SYNC BIT(0)
-#define AXI_DAC_REG_CNTRL_2 0x0048
-#define ADI_DAC_R1_MODE BIT(4)
-#define AXI_DAC_DRP_STATUS 0x0074
-#define AXI_DAC_DRP_LOCKED BIT(17)
+#define AXI_DAC_RSTN_REG 0x0040
+#define AXI_DAC_RSTN_CE_N BIT(2)
+#define AXI_DAC_RSTN_MMCM_RSTN BIT(1)
+#define AXI_DAC_RSTN_RSTN BIT(0)
+#define AXI_DAC_CNTRL_1_REG 0x0044
+#define AXI_DAC_CNTRL_1_SYNC BIT(0)
+#define AXI_DAC_CNTRL_2_REG 0x0048
+#define AXI_DAC_CNTRL_2_SDR_DDR_N BIT(16)
+#define AXI_DAC_CNTRL_2_SYMB_8B BIT(14)
+#define ADI_DAC_CNTRL_2_R1_MODE BIT(5)
+#define AXI_DAC_CNTRL_2_UNSIGNED_DATA BIT(4)
+#define AXI_DAC_STATUS_1_REG 0x0054
+#define AXI_DAC_STATUS_2_REG 0x0058
+#define AXI_DAC_DRP_STATUS_REG 0x0074
+#define AXI_DAC_DRP_STATUS_DRP_LOCKED BIT(17)
+#define AXI_DAC_CUSTOM_RD_REG 0x0080
+#define AXI_DAC_CUSTOM_WR_REG 0x0084
+#define AXI_DAC_CUSTOM_WR_DATA_8 GENMASK(23, 16)
+#define AXI_DAC_CUSTOM_WR_DATA_16 GENMASK(23, 8)
+#define AXI_DAC_UI_STATUS_REG 0x0088
+#define AXI_DAC_UI_STATUS_IF_BUSY BIT(4)
+#define AXI_DAC_CUSTOM_CTRL_REG 0x008C
+#define AXI_DAC_CUSTOM_CTRL_ADDRESS GENMASK(31, 24)
+#define AXI_DAC_CUSTOM_CTRL_SYNCED_TRANSFER BIT(2)
+#define AXI_DAC_CUSTOM_CTRL_STREAM BIT(1)
+#define AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA BIT(0)
+
+#define AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE (AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA | \
+ AXI_DAC_CUSTOM_CTRL_STREAM)
+
/* DAC Channel controls */
-#define AXI_DAC_REG_CHAN_CNTRL_1(c) (0x0400 + (c) * 0x40)
-#define AXI_DAC_REG_CHAN_CNTRL_3(c) (0x0408 + (c) * 0x40)
-#define AXI_DAC_SCALE_SIGN BIT(15)
-#define AXI_DAC_SCALE_INT BIT(14)
-#define AXI_DAC_SCALE GENMASK(14, 0)
-#define AXI_DAC_REG_CHAN_CNTRL_2(c) (0x0404 + (c) * 0x40)
-#define AXI_DAC_REG_CHAN_CNTRL_4(c) (0x040c + (c) * 0x40)
-#define AXI_DAC_PHASE GENMASK(31, 16)
-#define AXI_DAC_FREQUENCY GENMASK(15, 0)
-#define AXI_DAC_REG_CHAN_CNTRL_7(c) (0x0418 + (c) * 0x40)
-#define AXI_DAC_DATA_SEL GENMASK(3, 0)
+#define AXI_DAC_CHAN_CNTRL_1_REG(c) (0x0400 + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_3_REG(c) (0x0408 + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_3_SCALE_SIGN BIT(15)
+#define AXI_DAC_CHAN_CNTRL_3_SCALE_INT BIT(14)
+#define AXI_DAC_CHAN_CNTRL_3_SCALE GENMASK(14, 0)
+#define AXI_DAC_CHAN_CNTRL_2_REG(c) (0x0404 + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_2_PHASE GENMASK(31, 16)
+#define AXI_DAC_CHAN_CNTRL_2_FREQUENCY GENMASK(15, 0)
+#define AXI_DAC_CHAN_CNTRL_4_REG(c) (0x040c + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_7_REG(c) (0x0418 + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_7_DATA_SEL GENMASK(3, 0)
+
+#define AXI_DAC_RD_ADDR(x) (BIT(7) | (x))
/* 360 degrees in rad */
-#define AXI_DAC_2_PI_MEGA 6283190
+#define AXI_DAC_2_PI_MEGA 6283190
+
enum {
AXI_DAC_DATA_INTERNAL_TONE,
AXI_DAC_DATA_DMA = 2,
+ AXI_DAC_DATA_INTERNAL_RAMP_16BIT = 11,
+};
+
+struct axi_dac_info {
+ unsigned int version;
+ const struct iio_backend_info *backend_info;
+ bool has_dac_clk;
+ bool has_child_nodes;
};
struct axi_dac_state {
@@ -77,9 +110,11 @@ struct axi_dac_state {
* data/variables.
*/
struct mutex lock;
+ const struct axi_dac_info *info;
u64 dac_clk;
u32 reg_config;
bool int_tone;
+ int dac_clk_rate;
};
static int axi_dac_enable(struct iio_backend *back)
@@ -89,7 +124,7 @@ static int axi_dac_enable(struct iio_backend *back)
int ret;
guard(mutex)(&st->lock);
- ret = regmap_set_bits(st->regmap, AXI_DAC_REG_RSTN,
+ ret = regmap_set_bits(st->regmap, AXI_DAC_RSTN_REG,
AXI_DAC_RSTN_MMCM_RSTN);
if (ret)
return ret;
@@ -98,12 +133,14 @@ static int axi_dac_enable(struct iio_backend *back)
* designs really use it but if they don't we still get the lock bit
* set. So let's do it all the time so the code is generic.
*/
- ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_DRP_STATUS, __val,
- __val & AXI_DAC_DRP_LOCKED, 100, 1000);
+ ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_DRP_STATUS_REG,
+ __val,
+ __val & AXI_DAC_DRP_STATUS_DRP_LOCKED,
+ 100, 1000);
if (ret)
return ret;
- return regmap_set_bits(st->regmap, AXI_DAC_REG_RSTN,
+ return regmap_set_bits(st->regmap, AXI_DAC_RSTN_REG,
AXI_DAC_RSTN_RSTN | AXI_DAC_RSTN_MMCM_RSTN);
}
@@ -112,7 +149,7 @@ static void axi_dac_disable(struct iio_backend *back)
struct axi_dac_state *st = iio_backend_get_priv(back);
guard(mutex)(&st->lock);
- regmap_write(st->regmap, AXI_DAC_REG_RSTN, 0);
+ regmap_write(st->regmap, AXI_DAC_RSTN_REG, 0);
}
static struct iio_buffer *axi_dac_request_buffer(struct iio_backend *back,
@@ -155,15 +192,15 @@ static int __axi_dac_frequency_get(struct axi_dac_state *st, unsigned int chan,
}
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_4(chan);
+ reg = AXI_DAC_CHAN_CNTRL_4_REG(chan);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_2(chan);
+ reg = AXI_DAC_CHAN_CNTRL_2_REG(chan);
ret = regmap_read(st->regmap, reg, &raw);
if (ret)
return ret;
- raw = FIELD_GET(AXI_DAC_FREQUENCY, raw);
+ raw = FIELD_GET(AXI_DAC_CHAN_CNTRL_2_FREQUENCY, raw);
*freq = DIV_ROUND_CLOSEST_ULL(raw * st->dac_clk, BIT(16));
return 0;
@@ -194,17 +231,18 @@ static int axi_dac_scale_get(struct axi_dac_state *st,
u32 reg, raw;
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_3(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_3_REG(chan->channel);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_1(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_1_REG(chan->channel);
ret = regmap_read(st->regmap, reg, &raw);
if (ret)
return ret;
- sign = FIELD_GET(AXI_DAC_SCALE_SIGN, raw);
- raw = FIELD_GET(AXI_DAC_SCALE, raw);
- scale = DIV_ROUND_CLOSEST_ULL((u64)raw * MEGA, AXI_DAC_SCALE_INT);
+ sign = FIELD_GET(AXI_DAC_CHAN_CNTRL_3_SCALE_SIGN, raw);
+ raw = FIELD_GET(AXI_DAC_CHAN_CNTRL_3_SCALE, raw);
+ scale = DIV_ROUND_CLOSEST_ULL((u64)raw * MEGA,
+ AXI_DAC_CHAN_CNTRL_3_SCALE_INT);
vals[0] = scale / MEGA;
vals[1] = scale % MEGA;
@@ -227,15 +265,15 @@ static int axi_dac_phase_get(struct axi_dac_state *st,
int ret, vals[2];
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_4(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_4_REG(chan->channel);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_2(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_2_REG(chan->channel);
ret = regmap_read(st->regmap, reg, &raw);
if (ret)
return ret;
- raw = FIELD_GET(AXI_DAC_PHASE, raw);
+ raw = FIELD_GET(AXI_DAC_CHAN_CNTRL_2_PHASE, raw);
phase = DIV_ROUND_CLOSEST_ULL((u64)raw * AXI_DAC_2_PI_MEGA, U16_MAX);
vals[0] = phase / MEGA;
@@ -260,18 +298,20 @@ static int __axi_dac_frequency_set(struct axi_dac_state *st, unsigned int chan,
}
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_4(chan);
+ reg = AXI_DAC_CHAN_CNTRL_4_REG(chan);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_2(chan);
+ reg = AXI_DAC_CHAN_CNTRL_2_REG(chan);
raw = DIV64_U64_ROUND_CLOSEST((u64)freq * BIT(16), sample_rate);
- ret = regmap_update_bits(st->regmap, reg, AXI_DAC_FREQUENCY, raw);
+ ret = regmap_update_bits(st->regmap, reg,
+ AXI_DAC_CHAN_CNTRL_2_FREQUENCY, raw);
if (ret)
return ret;
/* synchronize channels */
- return regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);
+ return regmap_set_bits(st->regmap, AXI_DAC_CNTRL_1_REG,
+ AXI_DAC_CNTRL_1_SYNC);
}
static int axi_dac_frequency_set(struct axi_dac_state *st,
@@ -312,16 +352,16 @@ static int axi_dac_scale_set(struct axi_dac_state *st,
/* format is 1.1.14 (sign, integer and fractional bits) */
if (scale < 0) {
- raw = FIELD_PREP(AXI_DAC_SCALE_SIGN, 1);
+ raw = FIELD_PREP(AXI_DAC_CHAN_CNTRL_3_SCALE_SIGN, 1);
scale *= -1;
}
- raw |= div_u64((u64)scale * AXI_DAC_SCALE_INT, MEGA);
+ raw |= div_u64((u64)scale * AXI_DAC_CHAN_CNTRL_3_SCALE_INT, MEGA);
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_3(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_3_REG(chan->channel);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_1(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_1_REG(chan->channel);
guard(mutex)(&st->lock);
ret = regmap_write(st->regmap, reg, raw);
@@ -329,7 +369,8 @@ static int axi_dac_scale_set(struct axi_dac_state *st,
return ret;
/* synchronize channels */
- ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);
+ ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_1_REG,
+ AXI_DAC_CNTRL_1_SYNC);
if (ret)
return ret;
@@ -355,18 +396,19 @@ static int axi_dac_phase_set(struct axi_dac_state *st,
raw = DIV_ROUND_CLOSEST_ULL((u64)phase * U16_MAX, AXI_DAC_2_PI_MEGA);
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_4(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_4_REG(chan->channel);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_2(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_2_REG(chan->channel);
guard(mutex)(&st->lock);
- ret = regmap_update_bits(st->regmap, reg, AXI_DAC_PHASE,
- FIELD_PREP(AXI_DAC_PHASE, raw));
+ ret = regmap_update_bits(st->regmap, reg, AXI_DAC_CHAN_CNTRL_2_PHASE,
+ FIELD_PREP(AXI_DAC_CHAN_CNTRL_2_PHASE, raw));
if (ret)
return ret;
/* synchronize channels */
- ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);
+ ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_1_REG,
+ AXI_DAC_CNTRL_1_SYNC);
if (ret)
return ret;
@@ -437,7 +479,7 @@ static int axi_dac_extend_chan(struct iio_backend *back,
if (chan->type != IIO_ALTVOLTAGE)
return -EINVAL;
- if (st->reg_config & AXI_DDS_DISABLE)
+ if (st->reg_config & AXI_DAC_CONFIG_DDS_DISABLE)
/* nothing to extend */
return 0;
@@ -454,13 +496,19 @@ static int axi_dac_data_source_set(struct iio_backend *back, unsigned int chan,
switch (data) {
case IIO_BACKEND_INTERNAL_CONTINUOUS_WAVE:
return regmap_update_bits(st->regmap,
- AXI_DAC_REG_CHAN_CNTRL_7(chan),
- AXI_DAC_DATA_SEL,
+ AXI_DAC_CHAN_CNTRL_7_REG(chan),
+ AXI_DAC_CHAN_CNTRL_7_DATA_SEL,
AXI_DAC_DATA_INTERNAL_TONE);
case IIO_BACKEND_EXTERNAL:
return regmap_update_bits(st->regmap,
- AXI_DAC_REG_CHAN_CNTRL_7(chan),
- AXI_DAC_DATA_SEL, AXI_DAC_DATA_DMA);
+ AXI_DAC_CHAN_CNTRL_7_REG(chan),
+ AXI_DAC_CHAN_CNTRL_7_DATA_SEL,
+ AXI_DAC_DATA_DMA);
+ case IIO_BACKEND_INTERNAL_RAMP_16BIT:
+ return regmap_update_bits(st->regmap,
+ AXI_DAC_CHAN_CNTRL_7_REG(chan),
+ AXI_DAC_CHAN_CNTRL_7_DATA_SEL,
+ AXI_DAC_DATA_INTERNAL_RAMP_16BIT);
default:
return -EINVAL;
}
@@ -475,7 +523,7 @@ static int axi_dac_set_sample_rate(struct iio_backend *back, unsigned int chan,
if (!sample_rate)
return -EINVAL;
- if (st->reg_config & AXI_DDS_DISABLE)
+ if (st->reg_config & AXI_DAC_CONFIG_DDS_DISABLE)
/* sample_rate has no meaning if DDS is disabled */
return 0;
@@ -518,6 +566,184 @@ static int axi_dac_reg_access(struct iio_backend *back, unsigned int reg,
return regmap_write(st->regmap, reg, writeval);
}
+static int axi_dac_ddr_enable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_clear_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_SDR_DDR_N);
+}
+
+static int axi_dac_ddr_disable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_set_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_SDR_DDR_N);
+}
+
+static int axi_dac_data_stream_enable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_set_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE);
+}
+
+static int axi_dac_data_stream_disable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_clear_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE);
+}
+
+static int axi_dac_data_transfer_addr(struct iio_backend *back, u32 address)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ if (address > FIELD_MAX(AXI_DAC_CUSTOM_CTRL_ADDRESS))
+ return -EINVAL;
+
+ /*
+ * Sample register address, when the DAC is configured, or stream
+ * start address when the FSM is in stream state.
+ */
+ return regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_ADDRESS,
+ FIELD_PREP(AXI_DAC_CUSTOM_CTRL_ADDRESS,
+ address));
+}
+
+static int axi_dac_data_format_set(struct iio_backend *back, unsigned int ch,
+ const struct iio_backend_data_fmt *data)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ switch (data->type) {
+ case IIO_BACKEND_DATA_UNSIGNED:
+ return regmap_clear_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_UNSIGNED_DATA);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int __axi_dac_bus_reg_write(struct iio_backend *back, u32 reg,
+ u32 val, size_t data_size)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+ int ret;
+ u32 ival;
+
+ /*
+ * Both AXI_DAC_CNTRL_2_REG and AXI_DAC_CUSTOM_WR_REG need to know
+ * the data size. So keeping data size control here only,
+ * since data size is mandatory for the current transfer.
+ * DDR state handled separately by specific backend calls,
+ * generally all raw register writes are SDR.
+ */
+ if (data_size == sizeof(u16))
+ ival = FIELD_PREP(AXI_DAC_CUSTOM_WR_DATA_16, val);
+ else
+ ival = FIELD_PREP(AXI_DAC_CUSTOM_WR_DATA_8, val);
+
+ ret = regmap_write(st->regmap, AXI_DAC_CUSTOM_WR_REG, ival);
+ if (ret)
+ return ret;
+
+ if (data_size == sizeof(u8))
+ ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_SYMB_8B);
+ else
+ ret = regmap_clear_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_SYMB_8B);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_ADDRESS,
+ FIELD_PREP(AXI_DAC_CUSTOM_CTRL_ADDRESS, reg));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA,
+ AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA);
+ if (ret)
+ return ret;
+
+ ret = regmap_read_poll_timeout(st->regmap,
+ AXI_DAC_UI_STATUS_REG, ival,
+ FIELD_GET(AXI_DAC_UI_STATUS_IF_BUSY, ival) == 0,
+ 10, 100 * KILO);
+ if (ret == -ETIMEDOUT)
+ dev_err(st->dev, "AXI read timeout\n");
+
+ /* Cleaning always AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA */
+ return regmap_clear_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA);
+}
+
+static int axi_dac_bus_reg_write(struct iio_backend *back, u32 reg,
+ u32 val, size_t data_size)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ guard(mutex)(&st->lock);
+ return __axi_dac_bus_reg_write(back, reg, val, data_size);
+}
+
+static int axi_dac_bus_reg_read(struct iio_backend *back, u32 reg, u32 *val,
+ size_t data_size)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+ int ret;
+
+ guard(mutex)(&st->lock);
+
+ /*
+ * SPI, we write with read flag, then we read just at the AXI
+ * io address space to get data read.
+ */
+ ret = __axi_dac_bus_reg_write(back, AXI_DAC_RD_ADDR(reg), 0,
+ data_size);
+ if (ret)
+ return ret;
+
+ return regmap_read(st->regmap, AXI_DAC_CUSTOM_RD_REG, val);
+}
+
+static void axi_dac_child_remove(void *data)
+{
+ platform_device_unregister(data);
+}
+
+static int axi_dac_create_platform_device(struct axi_dac_state *st,
+ struct fwnode_handle *child)
+{
+ struct ad3552r_hs_platform_data pdata = {
+ .bus_reg_read = axi_dac_bus_reg_read,
+ .bus_reg_write = axi_dac_bus_reg_write,
+ .bus_sample_data_clock_hz = st->dac_clk_rate,
+ };
+ struct platform_device_info pi = {
+ .parent = st->dev,
+ .name = fwnode_get_name(child),
+ .id = PLATFORM_DEVID_AUTO,
+ .fwnode = child,
+ .data = &pdata,
+ .size_data = sizeof(pdata),
+ };
+ struct platform_device *pdev;
+
+ pdev = platform_device_register_full(&pi);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ return devm_add_action_or_reset(st->dev, axi_dac_child_remove, pdev);
+}
+
static const struct iio_backend_ops axi_dac_generic_ops = {
.enable = axi_dac_enable,
.disable = axi_dac_disable,
@@ -531,11 +757,30 @@ static const struct iio_backend_ops axi_dac_generic_ops = {
.debugfs_reg_access = iio_backend_debugfs_ptr(axi_dac_reg_access),
};
+static const struct iio_backend_ops axi_ad3552r_ops = {
+ .enable = axi_dac_enable,
+ .disable = axi_dac_disable,
+ .request_buffer = axi_dac_request_buffer,
+ .free_buffer = axi_dac_free_buffer,
+ .data_source_set = axi_dac_data_source_set,
+ .ddr_enable = axi_dac_ddr_enable,
+ .ddr_disable = axi_dac_ddr_disable,
+ .data_stream_enable = axi_dac_data_stream_enable,
+ .data_stream_disable = axi_dac_data_stream_disable,
+ .data_format_set = axi_dac_data_format_set,
+ .data_transfer_addr = axi_dac_data_transfer_addr,
+};
+
static const struct iio_backend_info axi_dac_generic = {
.name = "axi-dac",
.ops = &axi_dac_generic_ops,
};
+static const struct iio_backend_info axi_ad3552r = {
+ .name = "axi-ad3552r",
+ .ops = &axi_ad3552r_ops,
+};
+
static const struct regmap_config axi_dac_regmap_config = {
.val_bits = 32,
.reg_bits = 32,
@@ -545,7 +790,6 @@ static const struct regmap_config axi_dac_regmap_config = {
static int axi_dac_probe(struct platform_device *pdev)
{
- const unsigned int *expected_ver;
struct axi_dac_state *st;
void __iomem *base;
unsigned int ver;
@@ -556,14 +800,29 @@ static int axi_dac_probe(struct platform_device *pdev)
if (!st)
return -ENOMEM;
- expected_ver = device_get_match_data(&pdev->dev);
- if (!expected_ver)
+ st->info = device_get_match_data(&pdev->dev);
+ if (!st->info)
return -ENODEV;
+ clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk");
+ if (IS_ERR(clk)) {
+ /* Backward compat., old fdt versions without clock-names. */
+ clk = devm_clk_get_enabled(&pdev->dev, NULL);
+ if (IS_ERR(clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(clk),
+ "failed to get clock\n");
+ }
- clk = devm_clk_get_enabled(&pdev->dev, NULL);
- if (IS_ERR(clk))
- return dev_err_probe(&pdev->dev, PTR_ERR(clk),
- "failed to get clock\n");
+ if (st->info->has_dac_clk) {
+ struct clk *dac_clk;
+
+ dac_clk = devm_clk_get_enabled(&pdev->dev, "dac_clk");
+ if (IS_ERR(dac_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(dac_clk),
+ "failed to get dac_clk clock\n");
+
+ /* We only care about the streaming mode rate */
+ st->dac_clk_rate = clk_get_rate(dac_clk) / 2;
+ }
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
@@ -580,7 +839,7 @@ static int axi_dac_probe(struct platform_device *pdev)
* Force disable the core. Up to the frontend to enable us. And we can
* still read/write registers...
*/
- ret = regmap_write(st->regmap, AXI_DAC_REG_RSTN, 0);
+ ret = regmap_write(st->regmap, AXI_DAC_RSTN_REG, 0);
if (ret)
return ret;
@@ -588,12 +847,13 @@ static int axi_dac_probe(struct platform_device *pdev)
if (ret)
return ret;
- if (ADI_AXI_PCORE_VER_MAJOR(ver) != ADI_AXI_PCORE_VER_MAJOR(*expected_ver)) {
+ if (ADI_AXI_PCORE_VER_MAJOR(ver) !=
+ ADI_AXI_PCORE_VER_MAJOR(st->info->version)) {
dev_err(&pdev->dev,
"Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
- ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
- ADI_AXI_PCORE_VER_MINOR(*expected_ver),
- ADI_AXI_PCORE_VER_PATCH(*expected_ver),
+ ADI_AXI_PCORE_VER_MAJOR(st->info->version),
+ ADI_AXI_PCORE_VER_MINOR(st->info->version),
+ ADI_AXI_PCORE_VER_PATCH(st->info->version),
ADI_AXI_PCORE_VER_MAJOR(ver),
ADI_AXI_PCORE_VER_MINOR(ver),
ADI_AXI_PCORE_VER_PATCH(ver));
@@ -601,7 +861,7 @@ static int axi_dac_probe(struct platform_device *pdev)
}
/* Let's get the core read only configuration */
- ret = regmap_read(st->regmap, AXI_DAC_REG_CONFIG, &st->reg_config);
+ ret = regmap_read(st->regmap, AXI_DAC_CONFIG_REG, &st->reg_config);
if (ret)
return ret;
@@ -613,16 +873,40 @@ static int axi_dac_probe(struct platform_device *pdev)
* want independent channels let's override the core's default value and
* set the R1_MODE bit.
*/
- ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_2, ADI_DAC_R1_MODE);
+ ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ ADI_DAC_CNTRL_2_R1_MODE);
if (ret)
return ret;
mutex_init(&st->lock);
- ret = devm_iio_backend_register(&pdev->dev, &axi_dac_generic, st);
+
+ ret = devm_iio_backend_register(&pdev->dev, st->info->backend_info, st);
if (ret)
return dev_err_probe(&pdev->dev, ret,
"failed to register iio backend\n");
+ device_for_each_child_node_scoped(&pdev->dev, child) {
+ int val;
+
+ if (!st->info->has_child_nodes)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "invalid fdt axi-dac compatible.");
+
+ /* Processing only reg 0 node */
+ ret = fwnode_property_read_u32(child, "reg", &val);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "invalid reg property.");
+ if (val != 0)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "invalid node address.");
+
+ ret = axi_dac_create_platform_device(st, child);
+ if (ret)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "cannot create device.");
+ }
+
dev_info(&pdev->dev, "AXI DAC IP core (%d.%.2d.%c) probed\n",
ADI_AXI_PCORE_VER_MAJOR(ver),
ADI_AXI_PCORE_VER_MINOR(ver),
@@ -631,10 +915,21 @@ static int axi_dac_probe(struct platform_device *pdev)
return 0;
}
-static unsigned int axi_dac_9_1_b_info = ADI_AXI_PCORE_VER(9, 1, 'b');
+static const struct axi_dac_info dac_generic = {
+ .version = ADI_AXI_PCORE_VER(9, 1, 'b'),
+ .backend_info = &axi_dac_generic,
+};
+
+static const struct axi_dac_info dac_ad3552r = {
+ .version = ADI_AXI_PCORE_VER(9, 1, 'b'),
+ .backend_info = &axi_ad3552r,
+ .has_dac_clk = true,
+ .has_child_nodes = true,
+};
static const struct of_device_id axi_dac_of_match[] = {
- { .compatible = "adi,axi-dac-9.1.b", .data = &axi_dac_9_1_b_info },
+ { .compatible = "adi,axi-dac-9.1.b", .data = &dac_generic },
+ { .compatible = "adi,axi-ad3552r", .data = &dac_ad3552r },
{}
};
MODULE_DEVICE_TABLE(of, axi_dac_of_match);
diff --git a/drivers/iio/dac/dpot-dac.c b/drivers/iio/dac/dpot-dac.c
index 7332064d0852..f36f10bfb6be 100644
--- a/drivers/iio/dac/dpot-dac.c
+++ b/drivers/iio/dac/dpot-dac.c
@@ -243,7 +243,7 @@ MODULE_DEVICE_TABLE(of, dpot_dac_match);
static struct platform_driver dpot_dac_driver = {
.probe = dpot_dac_probe,
- .remove_new = dpot_dac_remove,
+ .remove = dpot_dac_remove,
.driver = {
.name = "iio-dpot-dac",
.of_match_table = dpot_dac_match,
diff --git a/drivers/iio/dac/lpc18xx_dac.c b/drivers/iio/dac/lpc18xx_dac.c
index b3aa4443a6a4..2332b0c22691 100644
--- a/drivers/iio/dac/lpc18xx_dac.c
+++ b/drivers/iio/dac/lpc18xx_dac.c
@@ -184,9 +184,9 @@ static const struct of_device_id lpc18xx_dac_match[] = {
MODULE_DEVICE_TABLE(of, lpc18xx_dac_match);
static struct platform_driver lpc18xx_dac_driver = {
- .probe = lpc18xx_dac_probe,
- .remove_new = lpc18xx_dac_remove,
- .driver = {
+ .probe = lpc18xx_dac_probe,
+ .remove = lpc18xx_dac_remove,
+ .driver = {
.name = "lpc18xx-dac",
.of_match_table = lpc18xx_dac_match,
},
diff --git a/drivers/iio/dac/m62332.c b/drivers/iio/dac/m62332.c
index ae53baccec91..3497513854d7 100644
--- a/drivers/iio/dac/m62332.c
+++ b/drivers/iio/dac/m62332.c
@@ -201,7 +201,7 @@ static int m62332_probe(struct i2c_client *client)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &m62332_info;
- ret = iio_map_array_register(indio_dev, client->dev.platform_data);
+ ret = iio_map_array_register(indio_dev, dev_get_platdata(&client->dev));
if (ret < 0)
return ret;
diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c
index 685980184d3c..84336736a47b 100644
--- a/drivers/iio/dac/max517.c
+++ b/drivers/iio/dac/max517.c
@@ -143,10 +143,10 @@ static const struct iio_chan_spec max517_channels[] = {
static int max517_probe(struct i2c_client *client)
{
+ const struct max517_platform_data *platform_data = dev_get_platdata(&client->dev);
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct max517_data *data;
struct iio_dev *indio_dev;
- struct max517_platform_data *platform_data = client->dev.platform_data;
int chan;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c
index 2d567073996b..95ed5197d16f 100644
--- a/drivers/iio/dac/stm32-dac-core.c
+++ b/drivers/iio/dac/stm32-dac-core.c
@@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
static struct platform_driver stm32_dac_driver = {
.probe = stm32_dac_probe,
- .remove_new = stm32_dac_remove,
+ .remove = stm32_dac_remove,
.driver = {
.name = "stm32-dac-core",
.of_match_table = stm32_dac_of_match,
diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c
index 5a722f307e7e..3bfb368b3a23 100644
--- a/drivers/iio/dac/stm32-dac.c
+++ b/drivers/iio/dac/stm32-dac.c
@@ -398,7 +398,7 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
static struct platform_driver stm32_dac_driver = {
.probe = stm32_dac_probe,
- .remove_new = stm32_dac_remove,
+ .remove = stm32_dac_remove,
.driver = {
.name = "stm32-dac",
.of_match_table = stm32_dac_of_match,
diff --git a/drivers/iio/dac/vf610_dac.c b/drivers/iio/dac/vf610_dac.c
index de73bc5a1c93..82a078fa98ad 100644
--- a/drivers/iio/dac/vf610_dac.c
+++ b/drivers/iio/dac/vf610_dac.c
@@ -272,7 +272,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(vf610_dac_pm_ops, vf610_dac_suspend,
static struct platform_driver vf610_dac_driver = {
.probe = vf610_dac_probe,
- .remove_new = vf610_dac_remove,
+ .remove = vf610_dac_remove,
.driver = {
.name = "vf610-dac",
.of_match_table = vf610_dac_match,
diff --git a/drivers/iio/dummy/iio_simple_dummy.h b/drivers/iio/dummy/iio_simple_dummy.h
index a91622ac54e0..8246f25dbad0 100644
--- a/drivers/iio/dummy/iio_simple_dummy.h
+++ b/drivers/iio/dummy/iio_simple_dummy.h
@@ -60,7 +60,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state);
+ bool state);
int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
diff --git a/drivers/iio/dummy/iio_simple_dummy_events.c b/drivers/iio/dummy/iio_simple_dummy_events.c
index 63a2b844be50..b51ec21b6309 100644
--- a/drivers/iio/dummy/iio_simple_dummy_events.c
+++ b/drivers/iio/dummy/iio_simple_dummy_events.c
@@ -53,7 +53,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct iio_dummy_state *st = iio_priv(indio_dev);
@@ -183,36 +183,34 @@ static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private)
switch (st->regs->reg_data) {
case 0:
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH, 0, 0, 0),
+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
st->event_timestamp);
break;
case 1:
if (st->activity_running > st->event_val)
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- IIO_MOD_RUNNING,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0),
+ IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
+ IIO_MOD_RUNNING,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
st->event_timestamp);
break;
case 2:
if (st->activity_walking < st->event_val)
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- IIO_MOD_WALKING,
- IIO_EV_DIR_FALLING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0),
+ IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
+ IIO_MOD_WALKING,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
st->event_timestamp);
break;
case 3:
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
- IIO_EV_DIR_NONE,
- IIO_EV_TYPE_CHANGE, 0, 0, 0),
+ IIO_UNMOD_EVENT_CODE(IIO_STEPS, 0,
+ IIO_EV_TYPE_CHANGE,
+ IIO_EV_DIR_NONE),
st->event_timestamp);
break;
default:
diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c
index b391c6e27ab0..b1554ced7a26 100644
--- a/drivers/iio/frequency/ad9523.c
+++ b/drivers/iio/frequency/ad9523.c
@@ -970,7 +970,7 @@ static int ad9523_setup(struct iio_dev *indio_dev)
static int ad9523_probe(struct spi_device *spi)
{
- struct ad9523_platform_data *pdata = spi->dev.platform_data;
+ struct ad9523_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad9523_state *st;
int ret;
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index e13e64a5164c..61828e61e275 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -603,7 +603,7 @@ static int adf4350_probe(struct spi_device *spi)
if (pdata == NULL)
return -EINVAL;
} else {
- pdata = spi->dev.platform_data;
+ pdata = dev_get_platdata(&spi->dev);
}
if (!pdata) {
diff --git a/drivers/iio/frequency/adf4371.c b/drivers/iio/frequency/adf4371.c
index b27088464826..d752507e0c98 100644
--- a/drivers/iio/frequency/adf4371.c
+++ b/drivers/iio/frequency/adf4371.c
@@ -4,6 +4,7 @@
*
* Copyright 2019 Analog Devices Inc.
*/
+#include "linux/dev_printk.h"
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/device.h>
@@ -150,6 +151,7 @@ static const struct regmap_config adf4371_regmap_config = {
};
struct adf4371_chip_info {
+ const char *name;
unsigned int num_channels;
const struct iio_chan_spec *channels;
};
@@ -157,7 +159,6 @@ struct adf4371_chip_info {
struct adf4371_state {
struct spi_device *spi;
struct regmap *regmap;
- struct clk *clkin;
/*
* Lock for accessing device registers. Some operations require
* multiple consecutive R/W operations, during which the device
@@ -444,15 +445,16 @@ static const struct iio_chan_spec adf4371_chan[] = {
ADF4371_CHANNEL(ADF4371_CH_RF32),
};
-static const struct adf4371_chip_info adf4371_chip_info[] = {
- [ADF4371] = {
- .channels = adf4371_chan,
- .num_channels = 4,
- },
- [ADF4372] = {
- .channels = adf4371_chan,
- .num_channels = 3,
- }
+static const struct adf4371_chip_info adf4371_chip_info = {
+ .name = "adf4371",
+ .channels = adf4371_chan,
+ .num_channels = 4,
+};
+
+static const struct adf4371_chip_info adf4372_chip_info = {
+ .name = "adf4372",
+ .channels = adf4371_chan,
+ .num_channels = 3,
};
static int adf4371_reg_access(struct iio_dev *indio_dev,
@@ -542,10 +544,10 @@ static int adf4371_setup(struct adf4371_state *st)
static int adf4371_probe(struct spi_device *spi)
{
- const struct spi_device_id *id = spi_get_device_id(spi);
struct iio_dev *indio_dev;
struct adf4371_state *st;
struct regmap *regmap;
+ struct clk *clkin;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
@@ -553,50 +555,49 @@ static int adf4371_probe(struct spi_device *spi)
return -ENOMEM;
regmap = devm_regmap_init_spi(spi, &adf4371_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
- PTR_ERR(regmap));
- return PTR_ERR(regmap);
- }
+ if (IS_ERR(regmap))
+ return dev_err_probe(&spi->dev, PTR_ERR(regmap),
+ "Error initializing spi regmap\n");
st = iio_priv(indio_dev);
- spi_set_drvdata(spi, indio_dev);
st->spi = spi;
st->regmap = regmap;
mutex_init(&st->lock);
- st->chip_info = &adf4371_chip_info[id->driver_data];
- indio_dev->name = id->name;
+ st->chip_info = spi_get_device_match_data(spi);
+ if (!st->chip_info)
+ return -ENODEV;
+
+ indio_dev->name = st->chip_info->name;
indio_dev->info = &adf4371_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
- st->clkin = devm_clk_get_enabled(&spi->dev, "clkin");
- if (IS_ERR(st->clkin))
- return PTR_ERR(st->clkin);
+ clkin = devm_clk_get_enabled(&spi->dev, "clkin");
+ if (IS_ERR(clkin))
+ return dev_err_probe(&spi->dev, PTR_ERR(clkin),
+ "Failed to get clkin\n");
- st->clkin_freq = clk_get_rate(st->clkin);
+ st->clkin_freq = clk_get_rate(clkin);
ret = adf4371_setup(st);
- if (ret < 0) {
- dev_err(&spi->dev, "ADF4371 setup failed\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(&spi->dev, ret, "ADF4371 setup failed\n");
return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id adf4371_id_table[] = {
- { "adf4371", ADF4371 },
- { "adf4372", ADF4372 },
+ { "adf4371", (kernel_ulong_t)&adf4371_chip_info },
+ { "adf4372", (kernel_ulong_t)&adf4372_chip_info },
{}
};
MODULE_DEVICE_TABLE(spi, adf4371_id_table);
static const struct of_device_id adf4371_of_match[] = {
- { .compatible = "adi,adf4371" },
- { .compatible = "adi,adf4372" },
+ { .compatible = "adi,adf4371", .data = &adf4371_chip_info },
+ { .compatible = "adi,adf4372", .data = &adf4372_chip_info},
{ },
};
MODULE_DEVICE_TABLE(of, adf4371_of_match);
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 97b86c4a53a6..3e193ee0fb61 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -27,7 +27,7 @@ config ADIS16136
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for the Analog Devices ADIS16133, ADIS16135,
- ADIS16136 gyroscope devices.
+ ADIS16136, ADIS16137 gyroscope devices.
config ADIS16260
tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver"
diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c
index 10728d5ccae3..ba877d067afb 100644
--- a/drivers/iio/gyro/bmg160_core.c
+++ b/drivers/iio/gyro/bmg160_core.c
@@ -8,7 +8,6 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
@@ -444,7 +443,7 @@ static int bmg160_setup_new_data_interrupt(struct bmg160_data *data,
static int bmg160_get_bw(struct bmg160_data *data, int *val)
{
- struct device *dev = regmap_get_device(data->regmap);
+ struct device *dev = regmap_get_device(data->regmap);
int i;
unsigned int bw_bits;
int ret;
@@ -749,7 +748,7 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct bmg160_data *data = iio_priv(indio_dev);
int ret;
@@ -1055,17 +1054,6 @@ static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = {
.postdisable = bmg160_buffer_postdisable,
};
-static const char *bmg160_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
const char *name)
{
@@ -1098,9 +1086,6 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
mutex_init(&data->mutex);
- if (ACPI_HANDLE(dev))
- name = bmg160_match_acpi_device(dev);
-
indio_dev->channels = bmg160_channels;
indio_dev->num_channels = ARRAY_SIZE(bmg160_channels);
indio_dev->name = name;
diff --git a/drivers/iio/gyro/bmg160_i2c.c b/drivers/iio/gyro/bmg160_i2c.c
index 672d0b720f61..9c5d7e8ee99c 100644
--- a/drivers/iio/gyro/bmg160_i2c.c
+++ b/drivers/iio/gyro/bmg160_i2c.c
@@ -17,7 +17,7 @@ static int bmg160_i2c_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct regmap *regmap;
- const char *name = NULL;
+ const char *name;
regmap = devm_regmap_init_i2c(client, &bmg160_regmap_i2c_conf);
if (IS_ERR(regmap)) {
@@ -28,6 +28,8 @@ static int bmg160_i2c_probe(struct i2c_client *client)
if (id)
name = id->name;
+ else
+ name = iio_get_acpi_device_name(&client->dev);
return bmg160_core_probe(&client->dev, regmap, client->irq, name);
}
@@ -39,8 +41,6 @@ static void bmg160_i2c_remove(struct i2c_client *client)
static const struct acpi_device_id bmg160_acpi_match[] = {
{"BMG0160", 0},
- {"BMI055B", 0},
- {"BMI088B", 0},
{},
};
diff --git a/drivers/iio/gyro/fxas21002c_core.c b/drivers/iio/gyro/fxas21002c_core.c
index c28d17ca6f5e..688966129f70 100644
--- a/drivers/iio/gyro/fxas21002c_core.c
+++ b/drivers/iio/gyro/fxas21002c_core.c
@@ -849,8 +849,7 @@ static int fxas21002c_trigger_probe(struct fxas21002c_data *data)
if (!data->dready_trig)
return -ENOMEM;
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(data->irq));
-
+ irq_trig = irq_get_trigger_type(data->irq);
if (irq_trig == IRQF_TRIGGER_RISING) {
ret = regmap_field_write(data->regmap_fields[F_IPOL], 1);
if (ret < 0)
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index 59a38bf9459b..0598f1d3fbb3 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -27,7 +27,7 @@ struct gyro_3d_state {
struct hid_sensor_hub_attribute_info gyro[GYRO_3D_CHANNEL_MAX];
struct {
u32 gyro_val[GYRO_3D_CHANNEL_MAX];
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -279,11 +279,11 @@ static int gyro_3d_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_gyro_3d_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static const char *name = "gyro_3d";
struct iio_dev *indio_dev;
struct gyro_3d_state *gyro_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*gyro_state));
if (!indio_dev)
@@ -361,7 +361,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_gyro_3d_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct gyro_3d_state *gyro_state = iio_priv(indio_dev);
@@ -386,7 +386,7 @@ static struct platform_driver hid_gyro_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_gyro_3d_probe,
- .remove_new = hid_gyro_3d_remove,
+ .remove = hid_gyro_3d_remove,
};
module_platform_driver(hid_gyro_3d_platform_driver);
diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c
index 35af68b41408..b6883e8b2a8b 100644
--- a/drivers/iio/gyro/mpu3050-core.c
+++ b/drivers/iio/gyro/mpu3050-core.c
@@ -1059,12 +1059,12 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq)
/* Check if IRQ is open drain */
mpu3050->irq_opendrain = device_property_read_bool(dev, "drive-open-drain");
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
/*
* Configure the interrupt generator hardware to supply whatever
* the interrupt is configured for, edges low/high level low/high,
* we can provide it all.
*/
+ irq_trig = irq_get_trigger_type(irq);
switch (irq_trig) {
case IRQF_TRIGGER_RISING:
dev_info(&indio_dev->dev,
diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
index bf6d2636a85e..f2fa0e1631ff 100644
--- a/drivers/iio/humidity/hid-sensor-humidity.c
+++ b/drivers/iio/humidity/hid-sensor-humidity.c
@@ -18,7 +18,7 @@ struct hid_humidity_state {
struct hid_sensor_hub_attribute_info humidity_attr;
struct {
s32 humidity_data;
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -287,7 +287,7 @@ static struct platform_driver hid_humidity_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_humidity_probe,
- .remove_new = hid_humidity_remove,
+ .remove = hid_humidity_remove,
};
module_platform_driver(hid_humidity_platform_driver);
diff --git a/drivers/iio/humidity/hts221_buffer.c b/drivers/iio/humidity/hts221_buffer.c
index 11ef38994a95..4d03db19063e 100644
--- a/drivers/iio/humidity/hts221_buffer.c
+++ b/drivers/iio/humidity/hts221_buffer.c
@@ -81,8 +81,7 @@ int hts221_allocate_trigger(struct iio_dev *iio_dev)
unsigned long irq_type;
int err;
- irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
-
+ irq_type = irq_get_trigger_type(hw->irq);
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 782fb80e44c2..ca0efecb5b5c 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -53,6 +53,7 @@ config ADIS16480
ADIS16485, ADIS16488 inertial sensors.
source "drivers/iio/imu/bmi160/Kconfig"
+source "drivers/iio/imu/bmi270/Kconfig"
source "drivers/iio/imu/bmi323/Kconfig"
source "drivers/iio/imu/bno055/Kconfig"
@@ -96,6 +97,20 @@ config KMX61
source "drivers/iio/imu/inv_icm42600/Kconfig"
source "drivers/iio/imu/inv_mpu6050/Kconfig"
+
+config SMI240
+ tristate "Bosch Sensor SMI240 Inertial Measurement Unit"
+ depends on SPI
+ select REGMAP_SPI
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ If you say yes here you get support for SMI240 IMU on SPI with
+ accelerometer and gyroscope.
+
+ This driver can also be built as a module. If so, the module will be
+ called smi240.
+
source "drivers/iio/imu/st_lsm6dsx/Kconfig"
source "drivers/iio/imu/st_lsm9ds0/Kconfig"
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index 7e2d7d5c3b7b..04c77c2c4df8 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -15,6 +15,7 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
obj-y += bmi160/
+obj-y += bmi270/
obj-y += bmi323/
obj-y += bno055/
@@ -27,5 +28,7 @@ obj-y += inv_mpu6050/
obj-$(CONFIG_KMX61) += kmx61.o
+obj-$(CONFIG_SMI240) += smi240.o
+
obj-y += st_lsm6dsx/
obj-y += st_lsm9ds0/
diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c
index 495e8a74ac67..807c1a1476c2 100644
--- a/drivers/iio/imu/bmi160/bmi160_core.c
+++ b/drivers/iio/imu/bmi160/bmi160_core.c
@@ -690,18 +690,9 @@ static int bmi160_config_device_irq(struct iio_dev *indio_dev, int irq_type,
static int bmi160_setup_irq(struct iio_dev *indio_dev, int irq,
enum bmi160_int_pin pin)
{
- struct irq_data *desc;
- u32 irq_type;
+ u32 irq_type = irq_get_trigger_type(irq);
int ret;
- desc = irq_get_irq_data(irq);
- if (!desc) {
- dev_err(&indio_dev->dev, "Could not find IRQ %d\n", irq);
- return -EINVAL;
- }
-
- irq_type = irqd_get_trigger_type(desc);
-
ret = bmi160_config_device_irq(indio_dev, irq_type, pin);
if (ret)
return ret;
diff --git a/drivers/iio/imu/bmi270/Kconfig b/drivers/iio/imu/bmi270/Kconfig
new file mode 100644
index 000000000000..6362acc706da
--- /dev/null
+++ b/drivers/iio/imu/bmi270/Kconfig
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# BMI270 IMU driver
+#
+
+config BMI270
+ tristate
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+
+config BMI270_I2C
+ tristate "Bosch BMI270 I2C driver"
+ depends on I2C
+ select BMI270
+ select REGMAP_I2C
+ help
+ Enable support for the Bosch BMI270 6-Axis IMU connected to I2C
+ interface.
+
+ This driver can also be built as a module. If so, the module will be
+ called bmi270_i2c.
+
+config BMI270_SPI
+ tristate "Bosch BMI270 SPI driver"
+ depends on SPI
+ select BMI270
+ select REGMAP_SPI
+ help
+ Enable support for the Bosch BMI270 6-Axis IMU connected to SPI
+ interface.
+
+ This driver can also be built as a module. If so, the module will be
+ called bmi270_spi.
diff --git a/drivers/iio/imu/bmi270/Makefile b/drivers/iio/imu/bmi270/Makefile
new file mode 100644
index 000000000000..d96c96fc3d83
--- /dev/null
+++ b/drivers/iio/imu/bmi270/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for Bosch BMI270 IMU
+#
+obj-$(CONFIG_BMI270) += bmi270_core.o
+obj-$(CONFIG_BMI270_I2C) += bmi270_i2c.o
+obj-$(CONFIG_BMI270_SPI) += bmi270_spi.o
diff --git a/drivers/iio/imu/bmi270/bmi270.h b/drivers/iio/imu/bmi270/bmi270.h
new file mode 100644
index 000000000000..fdfad5784cc5
--- /dev/null
+++ b/drivers/iio/imu/bmi270/bmi270.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef BMI270_H_
+#define BMI270_H_
+
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+
+struct device;
+struct bmi270_data {
+ struct device *dev;
+ struct regmap *regmap;
+ const struct bmi270_chip_info *chip_info;
+
+ /*
+ * Where IIO_DMA_MINALIGN may be larger than 8 bytes, align to
+ * that to ensure a DMA safe buffer.
+ */
+ struct {
+ __le16 channels[6];
+ aligned_s64 timestamp;
+ } data __aligned(IIO_DMA_MINALIGN);
+};
+
+struct bmi270_chip_info {
+ const char *name;
+ int chip_id;
+ const char *fw_name;
+};
+
+extern const struct regmap_config bmi270_regmap_config;
+extern const struct bmi270_chip_info bmi260_chip_info;
+extern const struct bmi270_chip_info bmi270_chip_info;
+
+int bmi270_core_probe(struct device *dev, struct regmap *regmap,
+ const struct bmi270_chip_info *chip_info);
+
+#endif /* BMI270_H_ */
diff --git a/drivers/iio/imu/bmi270/bmi270_core.c b/drivers/iio/imu/bmi270/bmi270_core.c
new file mode 100644
index 000000000000..70db83a20239
--- /dev/null
+++ b/drivers/iio/imu/bmi270/bmi270_core.c
@@ -0,0 +1,734 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <linux/bitfield.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+
+#include "bmi270.h"
+
+#define BMI270_CHIP_ID_REG 0x00
+
+/* Checked to prevent sending incompatible firmware to BMI160 devices */
+#define BMI160_CHIP_ID_VAL 0xD1
+
+#define BMI260_CHIP_ID_VAL 0x27
+#define BMI270_CHIP_ID_VAL 0x24
+#define BMI270_CHIP_ID_MSK GENMASK(7, 0)
+
+#define BMI270_ACCEL_X_REG 0x0c
+#define BMI270_ANG_VEL_X_REG 0x12
+
+#define BMI270_INTERNAL_STATUS_REG 0x21
+#define BMI270_INTERNAL_STATUS_MSG_MSK GENMASK(3, 0)
+#define BMI270_INTERNAL_STATUS_MSG_INIT_OK 0x01
+
+#define BMI270_INTERNAL_STATUS_AXES_REMAP_ERR_MSK BIT(5)
+#define BMI270_INTERNAL_STATUS_ODR_50HZ_ERR_MSK BIT(6)
+
+#define BMI270_ACC_CONF_REG 0x40
+#define BMI270_ACC_CONF_ODR_MSK GENMASK(3, 0)
+#define BMI270_ACC_CONF_ODR_100HZ 0x08
+#define BMI270_ACC_CONF_BWP_MSK GENMASK(6, 4)
+#define BMI270_ACC_CONF_BWP_NORMAL_MODE 0x02
+#define BMI270_ACC_CONF_FILTER_PERF_MSK BIT(7)
+
+#define BMI270_ACC_CONF_RANGE_REG 0x41
+#define BMI270_ACC_CONF_RANGE_MSK GENMASK(1, 0)
+
+#define BMI270_GYR_CONF_REG 0x42
+#define BMI270_GYR_CONF_ODR_MSK GENMASK(3, 0)
+#define BMI270_GYR_CONF_ODR_200HZ 0x09
+#define BMI270_GYR_CONF_BWP_MSK GENMASK(5, 4)
+#define BMI270_GYR_CONF_BWP_NORMAL_MODE 0x02
+#define BMI270_GYR_CONF_NOISE_PERF_MSK BIT(6)
+#define BMI270_GYR_CONF_FILTER_PERF_MSK BIT(7)
+
+#define BMI270_GYR_CONF_RANGE_REG 0x43
+#define BMI270_GYR_CONF_RANGE_MSK GENMASK(2, 0)
+
+#define BMI270_INIT_CTRL_REG 0x59
+#define BMI270_INIT_CTRL_LOAD_DONE_MSK BIT(0)
+
+#define BMI270_INIT_DATA_REG 0x5e
+
+#define BMI270_PWR_CONF_REG 0x7c
+#define BMI270_PWR_CONF_ADV_PWR_SAVE_MSK BIT(0)
+#define BMI270_PWR_CONF_FIFO_WKUP_MSK BIT(1)
+#define BMI270_PWR_CONF_FUP_EN_MSK BIT(2)
+
+#define BMI270_PWR_CTRL_REG 0x7d
+#define BMI270_PWR_CTRL_AUX_EN_MSK BIT(0)
+#define BMI270_PWR_CTRL_GYR_EN_MSK BIT(1)
+#define BMI270_PWR_CTRL_ACCEL_EN_MSK BIT(2)
+#define BMI270_PWR_CTRL_TEMP_EN_MSK BIT(3)
+
+#define BMI260_INIT_DATA_FILE "bmi260-init-data.fw"
+#define BMI270_INIT_DATA_FILE "bmi270-init-data.fw"
+
+enum bmi270_scan {
+ BMI270_SCAN_ACCEL_X,
+ BMI270_SCAN_ACCEL_Y,
+ BMI270_SCAN_ACCEL_Z,
+ BMI270_SCAN_GYRO_X,
+ BMI270_SCAN_GYRO_Y,
+ BMI270_SCAN_GYRO_Z,
+ BMI270_SCAN_TIMESTAMP,
+};
+
+static const unsigned long bmi270_avail_scan_masks[] = {
+ (BIT(BMI270_SCAN_ACCEL_X) |
+ BIT(BMI270_SCAN_ACCEL_Y) |
+ BIT(BMI270_SCAN_ACCEL_Z) |
+ BIT(BMI270_SCAN_GYRO_X) |
+ BIT(BMI270_SCAN_GYRO_Y) |
+ BIT(BMI270_SCAN_GYRO_Z)),
+ 0
+};
+
+const struct bmi270_chip_info bmi260_chip_info = {
+ .name = "bmi260",
+ .chip_id = BMI260_CHIP_ID_VAL,
+ .fw_name = BMI260_INIT_DATA_FILE,
+};
+EXPORT_SYMBOL_NS_GPL(bmi260_chip_info, IIO_BMI270);
+
+const struct bmi270_chip_info bmi270_chip_info = {
+ .name = "bmi270",
+ .chip_id = BMI270_CHIP_ID_VAL,
+ .fw_name = BMI270_INIT_DATA_FILE,
+};
+EXPORT_SYMBOL_NS_GPL(bmi270_chip_info, IIO_BMI270);
+
+enum bmi270_sensor_type {
+ BMI270_ACCEL = 0,
+ BMI270_GYRO,
+};
+
+struct bmi270_scale {
+ int scale;
+ int uscale;
+};
+
+struct bmi270_odr {
+ int odr;
+ int uodr;
+};
+
+static const struct bmi270_scale bmi270_accel_scale[] = {
+ { 0, 598 },
+ { 0, 1197 },
+ { 0, 2394 },
+ { 0, 4788 },
+};
+
+static const struct bmi270_scale bmi270_gyro_scale[] = {
+ { 0, 1065 },
+ { 0, 532 },
+ { 0, 266 },
+ { 0, 133 },
+ { 0, 66 },
+};
+
+struct bmi270_scale_item {
+ const struct bmi270_scale *tbl;
+ int num;
+};
+
+static const struct bmi270_scale_item bmi270_scale_table[] = {
+ [BMI270_ACCEL] = {
+ .tbl = bmi270_accel_scale,
+ .num = ARRAY_SIZE(bmi270_accel_scale),
+ },
+ [BMI270_GYRO] = {
+ .tbl = bmi270_gyro_scale,
+ .num = ARRAY_SIZE(bmi270_gyro_scale),
+ },
+};
+
+static const struct bmi270_odr bmi270_accel_odr[] = {
+ { 0, 781250 },
+ { 1, 562500 },
+ { 3, 125000 },
+ { 6, 250000 },
+ { 12, 500000 },
+ { 25, 0 },
+ { 50, 0 },
+ { 100, 0 },
+ { 200, 0 },
+ { 400, 0 },
+ { 800, 0 },
+ { 1600, 0 },
+};
+
+static const u8 bmi270_accel_odr_vals[] = {
+ 0x01,
+ 0x02,
+ 0x03,
+ 0x04,
+ 0x05,
+ 0x06,
+ 0x07,
+ 0x08,
+ 0x09,
+ 0x0A,
+ 0x0B,
+ 0x0C,
+};
+
+static const struct bmi270_odr bmi270_gyro_odr[] = {
+ { 25, 0 },
+ { 50, 0 },
+ { 100, 0 },
+ { 200, 0 },
+ { 400, 0 },
+ { 800, 0 },
+ { 1600, 0 },
+ { 3200, 0 },
+};
+
+static const u8 bmi270_gyro_odr_vals[] = {
+ 0x06,
+ 0x07,
+ 0x08,
+ 0x09,
+ 0x0A,
+ 0x0B,
+ 0x0C,
+ 0x0D,
+};
+
+struct bmi270_odr_item {
+ const struct bmi270_odr *tbl;
+ const u8 *vals;
+ int num;
+};
+
+static const struct bmi270_odr_item bmi270_odr_table[] = {
+ [BMI270_ACCEL] = {
+ .tbl = bmi270_accel_odr,
+ .vals = bmi270_accel_odr_vals,
+ .num = ARRAY_SIZE(bmi270_accel_odr),
+ },
+ [BMI270_GYRO] = {
+ .tbl = bmi270_gyro_odr,
+ .vals = bmi270_gyro_odr_vals,
+ .num = ARRAY_SIZE(bmi270_gyro_odr),
+ },
+};
+
+static int bmi270_set_scale(struct bmi270_data *data, int chan_type, int uscale)
+{
+ int i;
+ int reg, mask;
+ struct bmi270_scale_item bmi270_scale_item;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ reg = BMI270_ACC_CONF_RANGE_REG;
+ mask = BMI270_ACC_CONF_RANGE_MSK;
+ bmi270_scale_item = bmi270_scale_table[BMI270_ACCEL];
+ break;
+ case IIO_ANGL_VEL:
+ reg = BMI270_GYR_CONF_RANGE_REG;
+ mask = BMI270_GYR_CONF_RANGE_MSK;
+ bmi270_scale_item = bmi270_scale_table[BMI270_GYRO];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < bmi270_scale_item.num; i++) {
+ if (bmi270_scale_item.tbl[i].uscale != uscale)
+ continue;
+
+ return regmap_update_bits(data->regmap, reg, mask, i);
+ }
+
+ return -EINVAL;
+}
+
+static int bmi270_get_scale(struct bmi270_data *bmi270_device, int chan_type,
+ int *uscale)
+{
+ int ret;
+ unsigned int val;
+ struct bmi270_scale_item bmi270_scale_item;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ ret = regmap_read(bmi270_device->regmap,
+ BMI270_ACC_CONF_RANGE_REG, &val);
+ if (ret)
+ return ret;
+
+ val = FIELD_GET(BMI270_ACC_CONF_RANGE_MSK, val);
+ bmi270_scale_item = bmi270_scale_table[BMI270_ACCEL];
+ break;
+ case IIO_ANGL_VEL:
+ ret = regmap_read(bmi270_device->regmap,
+ BMI270_GYR_CONF_RANGE_REG, &val);
+ if (ret)
+ return ret;
+
+ val = FIELD_GET(BMI270_GYR_CONF_RANGE_MSK, val);
+ bmi270_scale_item = bmi270_scale_table[BMI270_GYRO];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (val >= bmi270_scale_item.num)
+ return -EINVAL;
+
+ *uscale = bmi270_scale_item.tbl[val].uscale;
+ return 0;
+}
+
+static int bmi270_set_odr(struct bmi270_data *data, int chan_type, int odr,
+ int uodr)
+{
+ int i;
+ int reg, mask;
+ struct bmi270_odr_item bmi270_odr_item;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ reg = BMI270_ACC_CONF_REG;
+ mask = BMI270_ACC_CONF_ODR_MSK;
+ bmi270_odr_item = bmi270_odr_table[BMI270_ACCEL];
+ break;
+ case IIO_ANGL_VEL:
+ reg = BMI270_GYR_CONF_REG;
+ mask = BMI270_GYR_CONF_ODR_MSK;
+ bmi270_odr_item = bmi270_odr_table[BMI270_GYRO];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < bmi270_odr_item.num; i++) {
+ if (bmi270_odr_item.tbl[i].odr != odr ||
+ bmi270_odr_item.tbl[i].uodr != uodr)
+ continue;
+
+ return regmap_update_bits(data->regmap, reg, mask,
+ bmi270_odr_item.vals[i]);
+ }
+
+ return -EINVAL;
+}
+
+static int bmi270_get_odr(struct bmi270_data *data, int chan_type, int *odr,
+ int *uodr)
+{
+ int i, val, ret;
+ struct bmi270_odr_item bmi270_odr_item;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ ret = regmap_read(data->regmap, BMI270_ACC_CONF_REG, &val);
+ if (ret)
+ return ret;
+
+ val = FIELD_GET(BMI270_ACC_CONF_ODR_MSK, val);
+ bmi270_odr_item = bmi270_odr_table[BMI270_ACCEL];
+ break;
+ case IIO_ANGL_VEL:
+ ret = regmap_read(data->regmap, BMI270_GYR_CONF_REG, &val);
+ if (ret)
+ return ret;
+
+ val = FIELD_GET(BMI270_GYR_CONF_ODR_MSK, val);
+ bmi270_odr_item = bmi270_odr_table[BMI270_GYRO];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < bmi270_odr_item.num; i++) {
+ if (val != bmi270_odr_item.vals[i])
+ continue;
+
+ *odr = bmi270_odr_item.tbl[i].odr;
+ *uodr = bmi270_odr_item.tbl[i].uodr;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static irqreturn_t bmi270_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct bmi270_data *bmi270_device = iio_priv(indio_dev);
+ int ret;
+
+ ret = regmap_bulk_read(bmi270_device->regmap, BMI270_ACCEL_X_REG,
+ &bmi270_device->data.channels,
+ sizeof(bmi270_device->data.channels));
+
+ if (ret)
+ goto done;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &bmi270_device->data,
+ pf->timestamp);
+done:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int bmi270_get_data(struct bmi270_data *bmi270_device,
+ int chan_type, int axis, int *val)
+{
+ __le16 sample;
+ int reg;
+ int ret;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ reg = BMI270_ACCEL_X_REG + (axis - IIO_MOD_X) * 2;
+ break;
+ case IIO_ANGL_VEL:
+ reg = BMI270_ANG_VEL_X_REG + (axis - IIO_MOD_X) * 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_bulk_read(bmi270_device->regmap, reg, &sample, sizeof(sample));
+ if (ret)
+ return ret;
+
+ *val = sign_extend32(le16_to_cpu(sample), 15);
+
+ return 0;
+}
+
+static int bmi270_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ int ret;
+ struct bmi270_data *bmi270_device = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = bmi270_get_data(bmi270_device, chan->type, chan->channel2, val);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ ret = bmi270_get_scale(bmi270_device, chan->type, val2);
+ return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = bmi270_get_odr(bmi270_device, chan->type, val, val2);
+ return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int bmi270_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct bmi270_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return bmi270_set_scale(data, chan->type, val2);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return bmi270_set_odr(data, chan->type, val, val2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int bmi270_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ switch (chan->type) {
+ case IIO_ANGL_VEL:
+ *vals = (const int *)bmi270_gyro_scale;
+ *length = ARRAY_SIZE(bmi270_gyro_scale) * 2;
+ return IIO_AVAIL_LIST;
+ case IIO_ACCEL:
+ *vals = (const int *)bmi270_accel_scale;
+ *length = ARRAY_SIZE(bmi270_accel_scale) * 2;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ switch (chan->type) {
+ case IIO_ANGL_VEL:
+ *vals = (const int *)bmi270_gyro_odr;
+ *length = ARRAY_SIZE(bmi270_gyro_odr) * 2;
+ return IIO_AVAIL_LIST;
+ case IIO_ACCEL:
+ *vals = (const int *)bmi270_accel_odr;
+ *length = ARRAY_SIZE(bmi270_accel_odr) * 2;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info bmi270_info = {
+ .read_raw = bmi270_read_raw,
+ .write_raw = bmi270_write_raw,
+ .read_avail = bmi270_read_avail,
+};
+
+#define BMI270_ACCEL_CHANNEL(_axis) { \
+ .type = IIO_ACCEL, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .info_mask_shared_by_type_available = \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = BMI270_SCAN_ACCEL_##_axis, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ }, \
+}
+
+#define BMI270_ANG_VEL_CHANNEL(_axis) { \
+ .type = IIO_ANGL_VEL, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .info_mask_shared_by_type_available = \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = BMI270_SCAN_GYRO_##_axis, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ }, \
+}
+
+static const struct iio_chan_spec bmi270_channels[] = {
+ BMI270_ACCEL_CHANNEL(X),
+ BMI270_ACCEL_CHANNEL(Y),
+ BMI270_ACCEL_CHANNEL(Z),
+ BMI270_ANG_VEL_CHANNEL(X),
+ BMI270_ANG_VEL_CHANNEL(Y),
+ BMI270_ANG_VEL_CHANNEL(Z),
+ IIO_CHAN_SOFT_TIMESTAMP(BMI270_SCAN_TIMESTAMP),
+};
+
+static int bmi270_validate_chip_id(struct bmi270_data *bmi270_device)
+{
+ int chip_id;
+ int ret;
+ struct device *dev = bmi270_device->dev;
+ struct regmap *regmap = bmi270_device->regmap;
+
+ ret = regmap_read(regmap, BMI270_CHIP_ID_REG, &chip_id);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read chip id");
+
+ /*
+ * Some manufacturers use "BMI0160" for both the BMI160 and
+ * BMI260. If the device is actually a BMI160, the bmi160
+ * driver should handle it and this driver should not.
+ */
+ if (chip_id == BMI160_CHIP_ID_VAL)
+ return -ENODEV;
+
+ if (chip_id != bmi270_device->chip_info->chip_id)
+ dev_info(dev, "Unexpected chip id 0x%x", chip_id);
+
+ if (chip_id == bmi260_chip_info.chip_id)
+ bmi270_device->chip_info = &bmi260_chip_info;
+ else if (chip_id == bmi270_chip_info.chip_id)
+ bmi270_device->chip_info = &bmi270_chip_info;
+
+ return 0;
+}
+
+static int bmi270_write_calibration_data(struct bmi270_data *bmi270_device)
+{
+ int ret;
+ int status = 0;
+ const struct firmware *init_data;
+ struct device *dev = bmi270_device->dev;
+ struct regmap *regmap = bmi270_device->regmap;
+
+ ret = regmap_clear_bits(regmap, BMI270_PWR_CONF_REG,
+ BMI270_PWR_CONF_ADV_PWR_SAVE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to write power configuration");
+
+ /*
+ * After disabling advanced power save, all registers are accessible
+ * after a 450us delay. This delay is specified in table A of the
+ * datasheet.
+ */
+ usleep_range(450, 1000);
+
+ ret = regmap_clear_bits(regmap, BMI270_INIT_CTRL_REG,
+ BMI270_INIT_CTRL_LOAD_DONE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to prepare device to load init data");
+
+ ret = request_firmware(&init_data,
+ bmi270_device->chip_info->fw_name, dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to load init data file");
+
+ ret = regmap_bulk_write(regmap, BMI270_INIT_DATA_REG,
+ init_data->data, init_data->size);
+ release_firmware(init_data);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to write init data");
+
+ ret = regmap_set_bits(regmap, BMI270_INIT_CTRL_REG,
+ BMI270_INIT_CTRL_LOAD_DONE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to stop device initialization");
+
+ /*
+ * Wait at least 140ms for the device to complete configuration.
+ * This delay is specified in table C of the datasheet.
+ */
+ usleep_range(140000, 160000);
+
+ ret = regmap_read(regmap, BMI270_INTERNAL_STATUS_REG, &status);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read internal status");
+
+ if (status != BMI270_INTERNAL_STATUS_MSG_INIT_OK)
+ return dev_err_probe(dev, -ENODEV, "Device failed to initialize");
+
+ return 0;
+}
+
+static int bmi270_configure_imu(struct bmi270_data *bmi270_device)
+{
+ int ret;
+ struct device *dev = bmi270_device->dev;
+ struct regmap *regmap = bmi270_device->regmap;
+
+ ret = regmap_set_bits(regmap, BMI270_PWR_CTRL_REG,
+ BMI270_PWR_CTRL_AUX_EN_MSK |
+ BMI270_PWR_CTRL_GYR_EN_MSK |
+ BMI270_PWR_CTRL_ACCEL_EN_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable accelerometer and gyroscope");
+
+ ret = regmap_set_bits(regmap, BMI270_ACC_CONF_REG,
+ FIELD_PREP(BMI270_ACC_CONF_ODR_MSK,
+ BMI270_ACC_CONF_ODR_100HZ) |
+ FIELD_PREP(BMI270_ACC_CONF_BWP_MSK,
+ BMI270_ACC_CONF_BWP_NORMAL_MODE) |
+ BMI270_PWR_CONF_ADV_PWR_SAVE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to configure accelerometer");
+
+ ret = regmap_set_bits(regmap, BMI270_GYR_CONF_REG,
+ FIELD_PREP(BMI270_GYR_CONF_ODR_MSK,
+ BMI270_GYR_CONF_ODR_200HZ) |
+ FIELD_PREP(BMI270_GYR_CONF_BWP_MSK,
+ BMI270_GYR_CONF_BWP_NORMAL_MODE) |
+ BMI270_PWR_CONF_ADV_PWR_SAVE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to configure gyroscope");
+
+ /* Enable FIFO_WKUP, Disable ADV_PWR_SAVE and FUP_EN */
+ ret = regmap_write(regmap, BMI270_PWR_CONF_REG,
+ BMI270_PWR_CONF_FIFO_WKUP_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to set power configuration");
+
+ return 0;
+}
+
+static int bmi270_chip_init(struct bmi270_data *bmi270_device)
+{
+ int ret;
+
+ ret = bmi270_validate_chip_id(bmi270_device);
+ if (ret)
+ return ret;
+
+ ret = bmi270_write_calibration_data(bmi270_device);
+ if (ret)
+ return ret;
+
+ return bmi270_configure_imu(bmi270_device);
+}
+
+int bmi270_core_probe(struct device *dev, struct regmap *regmap,
+ const struct bmi270_chip_info *chip_info)
+{
+ int ret;
+ struct bmi270_data *bmi270_device;
+ struct iio_dev *indio_dev;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*bmi270_device));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ bmi270_device = iio_priv(indio_dev);
+ bmi270_device->dev = dev;
+ bmi270_device->regmap = regmap;
+ bmi270_device->chip_info = chip_info;
+
+ ret = bmi270_chip_init(bmi270_device);
+ if (ret)
+ return ret;
+
+ indio_dev->channels = bmi270_channels;
+ indio_dev->num_channels = ARRAY_SIZE(bmi270_channels);
+ indio_dev->name = chip_info->name;
+ indio_dev->available_scan_masks = bmi270_avail_scan_masks;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &bmi270_info;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ bmi270_trigger_handler, NULL);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+EXPORT_SYMBOL_NS_GPL(bmi270_core_probe, IIO_BMI270);
+
+MODULE_AUTHOR("Alex Lanzano");
+MODULE_DESCRIPTION("BMI270 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/bmi270/bmi270_i2c.c b/drivers/iio/imu/bmi270/bmi270_i2c.c
new file mode 100644
index 000000000000..6bd82e4362ab
--- /dev/null
+++ b/drivers/iio/imu/bmi270/bmi270_i2c.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+
+#include "bmi270.h"
+
+static const struct regmap_config bmi270_i2c_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int bmi270_i2c_probe(struct i2c_client *client)
+{
+ struct regmap *regmap;
+ struct device *dev = &client->dev;
+ const struct bmi270_chip_info *chip_info;
+
+ chip_info = i2c_get_match_data(client);
+ if (!chip_info)
+ return -ENODEV;
+
+ regmap = devm_regmap_init_i2c(client, &bmi270_i2c_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to init i2c regmap");
+
+ return bmi270_core_probe(dev, regmap, chip_info);
+}
+
+static const struct i2c_device_id bmi270_i2c_id[] = {
+ { "bmi260", (kernel_ulong_t)&bmi260_chip_info },
+ { "bmi270", (kernel_ulong_t)&bmi270_chip_info },
+ { }
+};
+
+static const struct acpi_device_id bmi270_acpi_match[] = {
+ /* GPD Win Mini, Aya Neo AIR Pro, OXP Mini Pro, etc. */
+ { "BMI0160", (kernel_ulong_t)&bmi260_chip_info },
+ { }
+};
+
+static const struct of_device_id bmi270_of_match[] = {
+ { .compatible = "bosch,bmi260", .data = &bmi260_chip_info },
+ { .compatible = "bosch,bmi270", .data = &bmi270_chip_info },
+ { }
+};
+
+static struct i2c_driver bmi270_i2c_driver = {
+ .driver = {
+ .name = "bmi270_i2c",
+ .acpi_match_table = bmi270_acpi_match,
+ .of_match_table = bmi270_of_match,
+ },
+ .probe = bmi270_i2c_probe,
+ .id_table = bmi270_i2c_id,
+};
+module_i2c_driver(bmi270_i2c_driver);
+
+MODULE_AUTHOR("Alex Lanzano");
+MODULE_DESCRIPTION("BMI270 driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(IIO_BMI270);
diff --git a/drivers/iio/imu/bmi270/bmi270_spi.c b/drivers/iio/imu/bmi270/bmi270_spi.c
new file mode 100644
index 000000000000..30b6d13a329c
--- /dev/null
+++ b/drivers/iio/imu/bmi270/bmi270_spi.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <linux/iio/iio.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include "bmi270.h"
+
+/*
+ * The following two functions are taken from the BMI323 spi driver code.
+ * In section 6.4 of the BMI270 data it specifies that after a read
+ * operation the first data byte from the device is a dummy byte
+ */
+static int bmi270_regmap_spi_read(void *spi, const void *reg_buf,
+ size_t reg_size, void *val_buf,
+ size_t val_size)
+{
+ return spi_write_then_read(spi, reg_buf, reg_size, val_buf, val_size);
+}
+
+static int bmi270_regmap_spi_write(void *spi, const void *data,
+ size_t count)
+{
+ u8 *data_buff = (u8 *)data;
+
+ /*
+ * Remove the extra pad byte since its only needed for the read
+ * operation
+ */
+ data_buff[1] = data_buff[0];
+ return spi_write_then_read(spi, data_buff + 1, count - 1, NULL, 0);
+}
+
+static const struct regmap_bus bmi270_regmap_bus = {
+ .read = bmi270_regmap_spi_read,
+ .write = bmi270_regmap_spi_write,
+};
+
+static const struct regmap_config bmi270_spi_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .pad_bits = 8,
+ .read_flag_mask = BIT(7),
+};
+
+static int bmi270_spi_probe(struct spi_device *spi)
+{
+ struct regmap *regmap;
+ struct device *dev = &spi->dev;
+ const struct bmi270_chip_info *chip_info;
+
+ chip_info = spi_get_device_match_data(spi);
+ if (!chip_info)
+ return -ENODEV;
+
+ regmap = devm_regmap_init(dev, &bmi270_regmap_bus, dev,
+ &bmi270_spi_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to init i2c regmap");
+
+ return bmi270_core_probe(dev, regmap, chip_info);
+}
+
+static const struct spi_device_id bmi270_spi_id[] = {
+ { "bmi260", (kernel_ulong_t)&bmi260_chip_info },
+ { "bmi270", (kernel_ulong_t)&bmi270_chip_info },
+ { }
+};
+
+static const struct of_device_id bmi270_of_match[] = {
+ { .compatible = "bosch,bmi260", .data = &bmi260_chip_info },
+ { .compatible = "bosch,bmi270", .data = &bmi270_chip_info },
+ { }
+};
+
+static struct spi_driver bmi270_spi_driver = {
+ .driver = {
+ .name = "bmi270",
+ .of_match_table = bmi270_of_match,
+ },
+ .probe = bmi270_spi_probe,
+ .id_table = bmi270_spi_id,
+};
+module_spi_driver(bmi270_spi_driver);
+
+MODULE_AUTHOR("Alex Lanzano");
+MODULE_DESCRIPTION("BMI270 driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(IIO_BMI270);
diff --git a/drivers/iio/imu/bmi323/bmi323.h b/drivers/iio/imu/bmi323/bmi323.h
index 209bccb1f335..b4cfe92600a4 100644
--- a/drivers/iio/imu/bmi323/bmi323.h
+++ b/drivers/iio/imu/bmi323/bmi323.h
@@ -141,7 +141,6 @@
#define BMI323_STEP_SC1_REG 0x10
#define BMI323_STEP_SC1_WTRMRK_MSK GENMASK(9, 0)
#define BMI323_STEP_SC1_RST_CNT_MSK BIT(10)
-#define BMI323_STEP_SC1_REG 0x10
#define BMI323_STEP_LEN 2
/* Tap gesture config registers */
diff --git a/drivers/iio/imu/bmi323/bmi323_core.c b/drivers/iio/imu/bmi323/bmi323_core.c
index e1f3b0d778be..161bb1d2e761 100644
--- a/drivers/iio/imu/bmi323/bmi323_core.c
+++ b/drivers/iio/imu/bmi323/bmi323_core.c
@@ -467,7 +467,7 @@ static int bmi323_feature_engine_events(struct bmi323_data *data,
BMI323_FEAT_IO_STATUS_MSK);
}
-static int bmi323_step_wtrmrk_en(struct bmi323_data *data, int state)
+static int bmi323_step_wtrmrk_en(struct bmi323_data *data, bool state)
{
enum bmi323_irq_pin step_irq;
int ret;
@@ -484,7 +484,7 @@ static int bmi323_step_wtrmrk_en(struct bmi323_data *data, int state)
ret = bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG,
BMI323_STEP_SC1_WTRMRK_MSK,
FIELD_PREP(BMI323_STEP_SC1_WTRMRK_MSK,
- state ? 1 : 0));
+ state));
if (ret)
return ret;
@@ -506,7 +506,7 @@ static int bmi323_motion_config_reg(enum iio_event_direction dir)
}
static int bmi323_motion_event_en(struct bmi323_data *data,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
unsigned int state_value = state ? BMI323_FEAT_XYZ_MSK : 0;
int config, ret, msk, raw, field_value;
@@ -570,7 +570,7 @@ static int bmi323_motion_event_en(struct bmi323_data *data,
}
static int bmi323_tap_event_en(struct bmi323_data *data,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
enum bmi323_irq_pin tap_irq;
int ret, tap_enabled;
@@ -785,7 +785,7 @@ static const struct attribute_group bmi323_event_attribute_group = {
static int bmi323_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct bmi323_data *data = iio_priv(indio_dev);
@@ -1881,7 +1881,6 @@ static int bmi323_trigger_probe(struct bmi323_data *data,
struct fwnode_handle *fwnode;
enum bmi323_irq_pin irq_pin;
int ret, irq, irq_type;
- struct irq_data *desc;
fwnode = dev_fwnode(data->dev);
if (!fwnode)
@@ -1898,12 +1897,7 @@ static int bmi323_trigger_probe(struct bmi323_data *data,
irq_pin = BMI323_IRQ_INT2;
}
- desc = irq_get_irq_data(irq);
- if (!desc)
- return dev_err_probe(data->dev, -EINVAL,
- "Could not find IRQ %d\n", irq);
-
- irq_type = irqd_get_trigger_type(desc);
+ irq_type = irq_get_trigger_type(irq);
switch (irq_type) {
case IRQF_TRIGGER_RISING:
latch = false;
diff --git a/drivers/iio/imu/fxos8700_core.c b/drivers/iio/imu/fxos8700_core.c
index 6d189c4b9ff9..281ebfd9c15a 100644
--- a/drivers/iio/imu/fxos8700_core.c
+++ b/drivers/iio/imu/fxos8700_core.c
@@ -8,7 +8,6 @@
*/
#include <linux/module.h>
#include <linux/regmap.h>
-#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/bitfield.h>
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 56ac19814250..7968aa27f9fd 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -200,7 +200,6 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev,
{
struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
- struct inv_sensors_timestamp *ts = &accel_st->ts;
struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
unsigned int fifo_en = 0;
unsigned int sleep_temp = 0;
@@ -229,7 +228,6 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev,
}
/* update data FIFO write */
- inv_sensors_timestamp_apply_odr(ts, 0, 0, 0);
ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
out_unlock:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index c3924cc6190e..93b5d7a3339c 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -673,7 +673,6 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
{
struct device *dev = regmap_get_device(regmap);
struct inv_icm42600_state *st;
- struct irq_data *irq_desc;
int irq_type;
bool open_drain;
int ret;
@@ -683,14 +682,7 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
return -ENODEV;
}
- /* get irq properties, set trigger falling by default */
- irq_desc = irq_get_irq_data(irq);
- if (!irq_desc) {
- dev_err(dev, "could not find IRQ %d\n", irq);
- return -EINVAL;
- }
-
- irq_type = irqd_get_trigger_type(irq_desc);
+ irq_type = irq_get_trigger_type(irq);
if (!irq_type)
irq_type = IRQF_TRIGGER_FALLING;
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
index 938af5b640b0..c6bb68bf5e14 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -99,8 +99,6 @@ static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
- struct inv_icm42600_sensor_state *gyro_st = iio_priv(indio_dev);
- struct inv_sensors_timestamp *ts = &gyro_st->ts;
struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
unsigned int fifo_en = 0;
unsigned int sleep_gyro = 0;
@@ -128,7 +126,6 @@ static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev,
}
/* update data FIFO write */
- inv_sensors_timestamp_apply_odr(ts, 0, 0, 0);
ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
out_unlock:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
index ebb31b385881..19563c58b4b1 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
@@ -71,6 +71,22 @@ static int inv_icm42600_probe(struct i2c_client *client)
inv_icm42600_i2c_bus_setup);
}
+/*
+ * device id table is used to identify what device can be
+ * supported by this driver
+ */
+static const struct i2c_device_id inv_icm42600_id[] = {
+ { "icm42600", INV_CHIP_ICM42600 },
+ { "icm42602", INV_CHIP_ICM42602 },
+ { "icm42605", INV_CHIP_ICM42605 },
+ { "icm42686", INV_CHIP_ICM42686 },
+ { "icm42622", INV_CHIP_ICM42622 },
+ { "icm42688", INV_CHIP_ICM42688 },
+ { "icm42631", INV_CHIP_ICM42631 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, inv_icm42600_id);
+
static const struct of_device_id inv_icm42600_of_matches[] = {
{
.compatible = "invensense,icm42600",
@@ -104,6 +120,7 @@ static struct i2c_driver inv_icm42600_driver = {
.of_match_table = inv_icm42600_of_matches,
.pm = pm_ptr(&inv_icm42600_pm_ops),
},
+ .id_table = inv_icm42600_id,
.probe = inv_icm42600_probe,
};
module_i2c_driver(inv_icm42600_driver);
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
index eae5ff7a3cc1..3b6d05fce65d 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
@@ -67,6 +67,22 @@ static int inv_icm42600_probe(struct spi_device *spi)
inv_icm42600_spi_bus_setup);
}
+/*
+ * device id table is used to identify what device can be
+ * supported by this driver
+ */
+static const struct spi_device_id inv_icm42600_id[] = {
+ { "icm42600", INV_CHIP_ICM42600 },
+ { "icm42602", INV_CHIP_ICM42602 },
+ { "icm42605", INV_CHIP_ICM42605 },
+ { "icm42686", INV_CHIP_ICM42686 },
+ { "icm42622", INV_CHIP_ICM42622 },
+ { "icm42688", INV_CHIP_ICM42688 },
+ { "icm42631", INV_CHIP_ICM42631 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, inv_icm42600_id);
+
static const struct of_device_id inv_icm42600_of_matches[] = {
{
.compatible = "invensense,icm42600",
@@ -100,6 +116,7 @@ static struct spi_driver inv_icm42600_driver = {
.of_match_table = inv_icm42600_of_matches,
.pm = pm_ptr(&inv_icm42600_pm_ops),
},
+ .id_table = inv_icm42600_id,
.probe = inv_icm42600_probe,
};
module_spi_driver(inv_icm42600_driver);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
index f7bce428d9eb..373e59f6d91a 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
@@ -10,6 +10,8 @@
#include <linux/i2c.h>
#include <linux/dmi.h>
#include <linux/acpi.h>
+#include <linux/wordpart.h>
+
#include "inv_mpu_iio.h"
enum inv_mpu_product_name {
@@ -102,14 +104,11 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client,
unsigned short *secondary_addr)
{
struct acpi_device *adev = ACPI_COMPANION(&client->dev);
- const struct acpi_device_id *id;
u32 i2c_addr = 0;
LIST_HEAD(resources);
int ret;
- id = acpi_match_device(client->dev.driver->acpi_match_table,
- &client->dev);
- if (!id)
+ if (!is_acpi_device_node(dev_fwnode(&client->dev)))
return -ENODEV;
ret = acpi_dev_get_resources(adev, &resources,
@@ -118,8 +117,8 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client,
return ret;
acpi_dev_free_resource_list(&resources);
- *primary_addr = i2c_addr & 0x0000ffff;
- *secondary_addr = (i2c_addr & 0xffff0000) >> 16;
+ *primary_addr = lower_16_bits(i2c_addr);
+ *secondary_addr = upper_16_bits(i2c_addr);
return 0;
}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 14d95f34e981..40271352b02c 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -286,6 +286,24 @@ static const struct inv_mpu6050_hw hw_info[] = {
.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
.startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
+ {
+ .whoami = INV_IAM20680HP_WHOAMI_VALUE,
+ .name = "IAM20680HP",
+ .reg = &reg_set_6500,
+ .config = &chip_config_6500,
+ .fifo_size = 4 * 1024,
+ .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
+ },
+ {
+ .whoami = INV_IAM20680HT_WHOAMI_VALUE,
+ .name = "IAM20680HT",
+ .reg = &reg_set_6500,
+ .config = &chip_config_6500,
+ .fifo_size = 4 * 1024,
+ .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
+ },
};
static int inv_mpu6050_pwr_mgmt_1_write(struct inv_mpu6050_state *st, bool sleep,
@@ -510,6 +528,8 @@ static int inv_mpu6050_set_accel_lpf_regs(struct inv_mpu6050_state *st,
return 0;
case INV_ICM20689:
case INV_ICM20690:
+ case INV_IAM20680HT:
+ case INV_IAM20680HP:
/* set FIFO size to maximum value */
val |= INV_ICM20689_BITS_FIFO_SIZE_MAX;
break;
@@ -1153,24 +1173,21 @@ static int inv_mpu6050_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct inv_mpu6050_state *st = iio_priv(indio_dev);
- int enable;
/* support only WoM (accel roc rising) event */
if (chan->type != IIO_ACCEL || type != IIO_EV_TYPE_ROC ||
dir != IIO_EV_DIR_RISING)
return -EINVAL;
- enable = !!state;
-
guard(mutex)(&st->lock);
- if (st->chip_config.wom_en == enable)
+ if (st->chip_config.wom_en == state)
return 0;
- return inv_mpu6050_enable_wom(st, enable);
+ return inv_mpu6050_enable_wom(st, state);
}
static int inv_mpu6050_read_event_value(struct iio_dev *indio_dev,
@@ -1859,7 +1876,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
struct inv_mpu6050_platform_data *pdata;
struct device *dev = regmap_get_device(regmap);
int result;
- struct irq_data *desc;
int irq_type;
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
@@ -1893,13 +1909,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
}
if (irq > 0) {
- desc = irq_get_irq_data(irq);
- if (!desc) {
- dev_err(dev, "Could not find IRQ %d\n", irq);
- return -EINVAL;
- }
-
- irq_type = irqd_get_trigger_type(desc);
+ irq_type = irq_get_trigger_type(irq);
if (!irq_type)
irq_type = IRQF_TRIGGER_RISING;
} else {
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 0e03137fb3d4..7a5926ba6b97 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -188,6 +188,8 @@ static const struct i2c_device_id inv_mpu_id[] = {
{"icm20602", INV_ICM20602},
{"icm20690", INV_ICM20690},
{"iam20680", INV_IAM20680},
+ {"iam20680hp", INV_IAM20680HP},
+ {"iam20680ht", INV_IAM20680HT},
{}
};
@@ -254,6 +256,14 @@ static const struct of_device_id inv_of_match[] = {
.compatible = "invensense,iam20680",
.data = (void *)INV_IAM20680
},
+ {
+ .compatible = "invensense,iam20680hp",
+ .data = (void *)INV_IAM20680HP
+ },
+ {
+ .compatible = "invensense,iam20680ht",
+ .data = (void *)INV_IAM20680HT
+ },
{ }
};
MODULE_DEVICE_TABLE(of, inv_of_match);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index e1c0c5146876..a6862cf42639 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -85,6 +85,8 @@ enum inv_devices {
INV_ICM20602,
INV_ICM20690,
INV_IAM20680,
+ INV_IAM20680HP,
+ INV_IAM20680HT,
INV_NUM_PARTS
};
@@ -424,6 +426,8 @@ struct inv_mpu6050_state {
#define INV_ICM20602_WHOAMI_VALUE 0x12
#define INV_ICM20690_WHOAMI_VALUE 0x20
#define INV_IAM20680_WHOAMI_VALUE 0xA9
+#define INV_IAM20680HP_WHOAMI_VALUE 0xF8
+#define INV_IAM20680HT_WHOAMI_VALUE 0xFA
/* scan element definition for generic MPU6xxx devices */
enum inv_mpu6050_scan {
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
index 05451ca1580b..e6a291fcda95 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
@@ -80,6 +80,8 @@ static const struct spi_device_id inv_mpu_id[] = {
{"icm20602", INV_ICM20602},
{"icm20690", INV_ICM20690},
{"iam20680", INV_IAM20680},
+ {"iam20680hp", INV_IAM20680HP},
+ {"iam20680ht", INV_IAM20680HT},
{}
};
@@ -142,6 +144,14 @@ static const struct of_device_id inv_of_match[] = {
.compatible = "invensense,iam20680",
.data = (void *)INV_IAM20680
},
+ {
+ .compatible = "invensense,iam20680hp",
+ .data = (void *)INV_IAM20680HP
+ },
+ {
+ .compatible = "invensense,iam20680ht",
+ .data = (void *)INV_IAM20680HT
+ },
{ }
};
MODULE_DEVICE_TABLE(of, inv_of_match);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index 3bfeabab0ec4..5b1088cc3704 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -112,7 +112,6 @@ int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable)
if (enable) {
/* reset timestamping */
inv_sensors_timestamp_reset(&st->timestamp);
- inv_sensors_timestamp_apply_odr(&st->timestamp, 0, 0, 0);
/* reset FIFO */
d = st->chip_config.user_ctrl | INV_MPU6050_BIT_FIFO_RST;
ret = regmap_write(st->map, st->reg->user_ctrl, d);
diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c
index c61c012e25bb..324c38764656 100644
--- a/drivers/iio/imu/kmx61.c
+++ b/drivers/iio/imu/kmx61.c
@@ -7,12 +7,13 @@
* IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F).
*/
-#include <linux/module.h>
#include <linux/i2c.h>
-#include <linux/acpi.h>
#include <linux/interrupt.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
+
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
@@ -941,7 +942,7 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct kmx61_data *data = kmx61_get_data(indio_dev);
int ret = 0;
@@ -1217,16 +1218,6 @@ err:
return IRQ_HANDLED;
}
-static const char *kmx61_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
- return dev_name(dev);
-}
-
static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data,
const struct iio_info *info,
const struct iio_chan_spec *chan,
@@ -1293,8 +1284,6 @@ static int kmx61_probe(struct i2c_client *client)
if (id)
name = id->name;
- else if (ACPI_HANDLE(&client->dev))
- name = kmx61_match_acpi_device(&client->dev);
else
return -ENODEV;
@@ -1496,13 +1485,6 @@ static const struct dev_pm_ops kmx61_pm_ops = {
RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL)
};
-static const struct acpi_device_id kmx61_acpi_match[] = {
- {"KMX61021", 0},
- {}
-};
-
-MODULE_DEVICE_TABLE(acpi, kmx61_acpi_match);
-
static const struct i2c_device_id kmx61_id[] = {
{ "kmx611021" },
{}
@@ -1513,7 +1495,6 @@ MODULE_DEVICE_TABLE(i2c, kmx61_id);
static struct i2c_driver kmx61_driver = {
.driver = {
.name = KMX61_DRV_NAME,
- .acpi_match_table = kmx61_acpi_match,
.pm = pm_ptr(&kmx61_pm_ops),
},
.probe = kmx61_probe,
diff --git a/drivers/iio/imu/smi240.c b/drivers/iio/imu/smi240.c
new file mode 100644
index 000000000000..4492c4d013bd
--- /dev/null
+++ b/drivers/iio/imu/smi240.c
@@ -0,0 +1,621 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/*
+ * Copyright (c) 2024 Robert Bosch GmbH.
+ */
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <linux/unaligned.h>
+#include <linux/units.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define SMI240_CHIP_ID 0x0024
+
+#define SMI240_SOFT_CONFIG_EOC_MASK BIT(0)
+#define SMI240_SOFT_CONFIG_GYR_BW_MASK BIT(1)
+#define SMI240_SOFT_CONFIG_ACC_BW_MASK BIT(2)
+#define SMI240_SOFT_CONFIG_BITE_AUTO_MASK BIT(3)
+#define SMI240_SOFT_CONFIG_BITE_REP_MASK GENMASK(6, 4)
+
+#define SMI240_CHIP_ID_REG 0x00
+#define SMI240_SOFT_CONFIG_REG 0x0A
+#define SMI240_TEMP_CUR_REG 0x10
+#define SMI240_ACCEL_X_CUR_REG 0x11
+#define SMI240_GYRO_X_CUR_REG 0x14
+#define SMI240_DATA_CAP_FIRST_REG 0x17
+#define SMI240_CMD_REG 0x2F
+
+#define SMI240_SOFT_RESET_CMD 0xB6
+
+#define SMI240_BITE_SEQUENCE_DELAY_US 140000
+#define SMI240_FILTER_FLUSH_DELAY_US 60000
+#define SMI240_DIGITAL_STARTUP_DELAY_US 120000
+#define SMI240_MECH_STARTUP_DELAY_US 100000
+
+#define SMI240_BUS_ID 0x00
+#define SMI240_CRC_INIT 0x05
+#define SMI240_CRC_POLY 0x0B
+#define SMI240_CRC_MASK GENMASK(2, 0)
+
+#define SMI240_READ_SD_BIT_MASK BIT(31)
+#define SMI240_READ_DATA_MASK GENMASK(19, 4)
+#define SMI240_READ_CS_BIT_MASK BIT(3)
+
+#define SMI240_WRITE_BUS_ID_MASK GENMASK(31, 30)
+#define SMI240_WRITE_ADDR_MASK GENMASK(29, 22)
+#define SMI240_WRITE_BIT_MASK BIT(21)
+#define SMI240_WRITE_CAP_BIT_MASK BIT(20)
+#define SMI240_WRITE_DATA_MASK GENMASK(18, 3)
+
+/* T°C = (temp / 256) + 25 */
+#define SMI240_TEMP_OFFSET 6400 /* 25 * 256 */
+#define SMI240_TEMP_SCALE 3906250 /* (1 / 256) * 1e9 */
+
+#define SMI240_ACCEL_SCALE 500 /* (1 / 2000) * 1e6 */
+#define SMI240_GYRO_SCALE 10000 /* (1 / 100) * 1e6 */
+
+#define SMI240_LOW_BANDWIDTH_HZ 50
+#define SMI240_HIGH_BANDWIDTH_HZ 400
+
+#define SMI240_BUILT_IN_SELF_TEST_COUNT 3
+
+#define SMI240_DATA_CHANNEL(_type, _axis, _index) { \
+ .type = _type, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .info_mask_shared_by_type_available = \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+#define SMI240_TEMP_CHANNEL(_index) { \
+ .type = IIO_TEMP, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_TEMP_OBJECT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_OFFSET) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+enum capture_mode { SMI240_CAPTURE_OFF = 0, SMI240_CAPTURE_ON = 1 };
+
+struct smi240_data {
+ struct regmap *regmap;
+ u16 accel_filter_freq;
+ u16 anglvel_filter_freq;
+ u8 built_in_self_test_count;
+ enum capture_mode capture;
+ /*
+ * Ensure natural alignment for timestamp if present.
+ * Channel size: 2 bytes.
+ * Max length needed: 2 * 3 channels + temp channel + 2 bytes padding + 8 byte ts.
+ * If fewer channels are enabled, less space may be needed, as
+ * long as the timestamp is still aligned to 8 bytes.
+ */
+ s16 buf[12] __aligned(8);
+
+ __be32 spi_buf __aligned(IIO_DMA_MINALIGN);
+};
+
+enum {
+ SMI240_TEMP_OBJECT,
+ SMI240_SCAN_ACCEL_X,
+ SMI240_SCAN_ACCEL_Y,
+ SMI240_SCAN_ACCEL_Z,
+ SMI240_SCAN_GYRO_X,
+ SMI240_SCAN_GYRO_Y,
+ SMI240_SCAN_GYRO_Z,
+ SMI240_SCAN_TIMESTAMP,
+};
+
+static const struct iio_chan_spec smi240_channels[] = {
+ SMI240_TEMP_CHANNEL(SMI240_TEMP_OBJECT),
+ SMI240_DATA_CHANNEL(IIO_ACCEL, X, SMI240_SCAN_ACCEL_X),
+ SMI240_DATA_CHANNEL(IIO_ACCEL, Y, SMI240_SCAN_ACCEL_Y),
+ SMI240_DATA_CHANNEL(IIO_ACCEL, Z, SMI240_SCAN_ACCEL_Z),
+ SMI240_DATA_CHANNEL(IIO_ANGL_VEL, X, SMI240_SCAN_GYRO_X),
+ SMI240_DATA_CHANNEL(IIO_ANGL_VEL, Y, SMI240_SCAN_GYRO_Y),
+ SMI240_DATA_CHANNEL(IIO_ANGL_VEL, Z, SMI240_SCAN_GYRO_Z),
+ IIO_CHAN_SOFT_TIMESTAMP(SMI240_SCAN_TIMESTAMP),
+};
+
+static const int smi240_low_pass_freqs[] = { SMI240_LOW_BANDWIDTH_HZ,
+ SMI240_HIGH_BANDWIDTH_HZ };
+
+static u8 smi240_crc3(u32 data, u8 init, u8 poly)
+{
+ u8 crc = init;
+ u8 do_xor;
+ s8 i = 31;
+
+ do {
+ do_xor = crc & 0x04;
+ crc <<= 1;
+ crc |= 0x01 & (data >> i);
+ if (do_xor)
+ crc ^= poly;
+
+ crc &= SMI240_CRC_MASK;
+ } while (--i >= 0);
+
+ return crc;
+}
+
+static bool smi240_sensor_data_is_valid(u32 data)
+{
+ if (smi240_crc3(data, SMI240_CRC_INIT, SMI240_CRC_POLY) != 0)
+ return false;
+
+ if (FIELD_GET(SMI240_READ_SD_BIT_MASK, data) &
+ FIELD_GET(SMI240_READ_CS_BIT_MASK, data))
+ return false;
+
+ return true;
+}
+
+static int smi240_regmap_spi_read(void *context, const void *reg_buf,
+ size_t reg_size, void *val_buf,
+ size_t val_size)
+{
+ int ret;
+ u32 request, response;
+ u16 *val = val_buf;
+ struct spi_device *spi = context;
+ struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
+ struct smi240_data *iio_priv_data = iio_priv(indio_dev);
+
+ if (reg_size != 1 || val_size != 2)
+ return -EINVAL;
+
+ request = FIELD_PREP(SMI240_WRITE_BUS_ID_MASK, SMI240_BUS_ID);
+ request |= FIELD_PREP(SMI240_WRITE_CAP_BIT_MASK, iio_priv_data->capture);
+ request |= FIELD_PREP(SMI240_WRITE_ADDR_MASK, *(u8 *)reg_buf);
+ request |= smi240_crc3(request, SMI240_CRC_INIT, SMI240_CRC_POLY);
+
+ iio_priv_data->spi_buf = cpu_to_be32(request);
+
+ /*
+ * SMI240 module consists of a 32Bit Out Of Frame (OOF)
+ * SPI protocol, where the slave interface responds to
+ * the Master request in the next frame.
+ * CS signal must toggle (> 700 ns) between the frames.
+ */
+ ret = spi_write(spi, &iio_priv_data->spi_buf, sizeof(request));
+ if (ret)
+ return ret;
+
+ ret = spi_read(spi, &iio_priv_data->spi_buf, sizeof(response));
+ if (ret)
+ return ret;
+
+ response = be32_to_cpu(iio_priv_data->spi_buf);
+
+ if (!smi240_sensor_data_is_valid(response))
+ return -EIO;
+
+ *val = FIELD_GET(SMI240_READ_DATA_MASK, response);
+
+ return 0;
+}
+
+static int smi240_regmap_spi_write(void *context, const void *data,
+ size_t count)
+{
+ u8 reg_addr;
+ u16 reg_data;
+ u32 request;
+ const u8 *data_ptr = data;
+ struct spi_device *spi = context;
+ struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
+ struct smi240_data *iio_priv_data = iio_priv(indio_dev);
+
+ if (count < 2)
+ return -EINVAL;
+
+ reg_addr = data_ptr[0];
+ memcpy(&reg_data, &data_ptr[1], sizeof(reg_data));
+
+ request = FIELD_PREP(SMI240_WRITE_BUS_ID_MASK, SMI240_BUS_ID);
+ request |= FIELD_PREP(SMI240_WRITE_BIT_MASK, 1);
+ request |= FIELD_PREP(SMI240_WRITE_ADDR_MASK, reg_addr);
+ request |= FIELD_PREP(SMI240_WRITE_DATA_MASK, reg_data);
+ request |= smi240_crc3(request, SMI240_CRC_INIT, SMI240_CRC_POLY);
+
+ iio_priv_data->spi_buf = cpu_to_be32(request);
+
+ return spi_write(spi, &iio_priv_data->spi_buf, sizeof(request));
+}
+
+static const struct regmap_bus smi240_regmap_bus = {
+ .read = smi240_regmap_spi_read,
+ .write = smi240_regmap_spi_write,
+};
+
+static const struct regmap_config smi240_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .val_format_endian = REGMAP_ENDIAN_NATIVE,
+};
+
+static int smi240_soft_reset(struct smi240_data *data)
+{
+ int ret;
+
+ ret = regmap_write(data->regmap, SMI240_CMD_REG, SMI240_SOFT_RESET_CMD);
+ if (ret)
+ return ret;
+ fsleep(SMI240_DIGITAL_STARTUP_DELAY_US);
+
+ return 0;
+}
+
+static int smi240_soft_config(struct smi240_data *data)
+{
+ int ret;
+ u8 acc_bw, gyr_bw;
+ u16 request;
+
+ switch (data->accel_filter_freq) {
+ case SMI240_LOW_BANDWIDTH_HZ:
+ acc_bw = 0x1;
+ break;
+ case SMI240_HIGH_BANDWIDTH_HZ:
+ acc_bw = 0x0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (data->anglvel_filter_freq) {
+ case SMI240_LOW_BANDWIDTH_HZ:
+ gyr_bw = 0x1;
+ break;
+ case SMI240_HIGH_BANDWIDTH_HZ:
+ gyr_bw = 0x0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ request = FIELD_PREP(SMI240_SOFT_CONFIG_EOC_MASK, 1);
+ request |= FIELD_PREP(SMI240_SOFT_CONFIG_GYR_BW_MASK, gyr_bw);
+ request |= FIELD_PREP(SMI240_SOFT_CONFIG_ACC_BW_MASK, acc_bw);
+ request |= FIELD_PREP(SMI240_SOFT_CONFIG_BITE_AUTO_MASK, 1);
+ request |= FIELD_PREP(SMI240_SOFT_CONFIG_BITE_REP_MASK,
+ data->built_in_self_test_count - 1);
+
+ ret = regmap_write(data->regmap, SMI240_SOFT_CONFIG_REG, request);
+ if (ret)
+ return ret;
+
+ fsleep(SMI240_MECH_STARTUP_DELAY_US +
+ data->built_in_self_test_count * SMI240_BITE_SEQUENCE_DELAY_US +
+ SMI240_FILTER_FLUSH_DELAY_US);
+
+ return 0;
+}
+
+static int smi240_get_low_pass_filter_freq(struct smi240_data *data,
+ int chan_type, int *val)
+{
+ switch (chan_type) {
+ case IIO_ACCEL:
+ *val = data->accel_filter_freq;
+ return 0;
+ case IIO_ANGL_VEL:
+ *val = data->anglvel_filter_freq;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int smi240_get_data(struct smi240_data *data, int chan_type, int axis,
+ int *val)
+{
+ u8 reg;
+ int ret, sample;
+
+ switch (chan_type) {
+ case IIO_TEMP:
+ reg = SMI240_TEMP_CUR_REG;
+ break;
+ case IIO_ACCEL:
+ reg = SMI240_ACCEL_X_CUR_REG + (axis - IIO_MOD_X);
+ break;
+ case IIO_ANGL_VEL:
+ reg = SMI240_GYRO_X_CUR_REG + (axis - IIO_MOD_X);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_read(data->regmap, reg, &sample);
+ if (ret)
+ return ret;
+
+ *val = sign_extend32(sample, 15);
+
+ return 0;
+}
+
+static irqreturn_t smi240_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct smi240_data *data = iio_priv(indio_dev);
+ int base = SMI240_DATA_CAP_FIRST_REG, i = 0;
+ int ret, chan, sample;
+
+ data->capture = SMI240_CAPTURE_ON;
+
+ iio_for_each_active_channel(indio_dev, chan) {
+ ret = regmap_read(data->regmap, base + chan, &sample);
+ data->capture = SMI240_CAPTURE_OFF;
+ if (ret)
+ goto out;
+ data->buf[i++] = sample;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buf, pf->timestamp);
+
+out:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int smi240_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, const int **vals,
+ int *type, int *length, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ *vals = smi240_low_pass_freqs;
+ *length = ARRAY_SIZE(smi240_low_pass_freqs);
+ *type = IIO_VAL_INT;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int smi240_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ int ret;
+ struct smi240_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+ ret = smi240_get_data(data, chan->type, chan->channel2, val);
+ iio_device_release_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ ret = smi240_get_low_pass_filter_freq(data, chan->type, val);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val = SMI240_TEMP_SCALE / GIGA;
+ *val2 = SMI240_TEMP_SCALE % GIGA;
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_ACCEL:
+ *val = 0;
+ *val2 = SMI240_ACCEL_SCALE;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_ANGL_VEL:
+ *val = 0;
+ *val2 = SMI240_GYRO_SCALE;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+
+ case IIO_CHAN_INFO_OFFSET:
+ if (chan->type == IIO_TEMP) {
+ *val = SMI240_TEMP_OFFSET;
+ return IIO_VAL_INT;
+ } else {
+ return -EINVAL;
+ }
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int smi240_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2,
+ long mask)
+{
+ int ret, i;
+ struct smi240_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ for (i = 0; i < ARRAY_SIZE(smi240_low_pass_freqs); i++) {
+ if (val == smi240_low_pass_freqs[i])
+ break;
+ }
+
+ if (i == ARRAY_SIZE(smi240_low_pass_freqs))
+ return -EINVAL;
+
+ switch (chan->type) {
+ case IIO_ACCEL:
+ data->accel_filter_freq = val;
+ break;
+ case IIO_ANGL_VEL:
+ data->anglvel_filter_freq = val;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Write access to soft config is locked until hard/soft reset */
+ ret = smi240_soft_reset(data);
+ if (ret)
+ return ret;
+
+ return smi240_soft_config(data);
+}
+
+static int smi240_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, long info)
+{
+ switch (info) {
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ return IIO_VAL_INT_PLUS_NANO;
+ default:
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ default:
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+}
+
+static int smi240_init(struct smi240_data *data)
+{
+ int ret;
+
+ data->accel_filter_freq = SMI240_HIGH_BANDWIDTH_HZ;
+ data->anglvel_filter_freq = SMI240_HIGH_BANDWIDTH_HZ;
+ data->built_in_self_test_count = SMI240_BUILT_IN_SELF_TEST_COUNT;
+
+ ret = smi240_soft_reset(data);
+ if (ret)
+ return ret;
+
+ return smi240_soft_config(data);
+}
+
+static const struct iio_info smi240_info = {
+ .read_avail = smi240_read_avail,
+ .read_raw = smi240_read_raw,
+ .write_raw = smi240_write_raw,
+ .write_raw_get_fmt = smi240_write_raw_get_fmt,
+};
+
+static int smi240_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct iio_dev *indio_dev;
+ struct regmap *regmap;
+ struct smi240_data *data;
+ int ret, response;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ regmap = devm_regmap_init(dev, &smi240_regmap_bus, dev,
+ &smi240_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to initialize SPI Regmap\n");
+
+ data = iio_priv(indio_dev);
+ dev_set_drvdata(dev, indio_dev);
+ data->regmap = regmap;
+ data->capture = SMI240_CAPTURE_OFF;
+
+ ret = regmap_read(data->regmap, SMI240_CHIP_ID_REG, &response);
+ if (ret)
+ return dev_err_probe(dev, ret, "Read chip id failed\n");
+
+ if (response != SMI240_CHIP_ID)
+ dev_info(dev, "Unknown chip id: 0x%04x\n", response);
+
+ ret = smi240_init(data);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Device initialization failed\n");
+
+ indio_dev->channels = smi240_channels;
+ indio_dev->num_channels = ARRAY_SIZE(smi240_channels);
+ indio_dev->name = "smi240";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &smi240_info;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ smi240_trigger_handler, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Setup triggered buffer failed\n");
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Register IIO device failed\n");
+
+ return 0;
+}
+
+static const struct spi_device_id smi240_spi_id[] = {
+ { "smi240" },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, smi240_spi_id);
+
+static const struct of_device_id smi240_of_match[] = {
+ { .compatible = "bosch,smi240" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, smi240_of_match);
+
+static struct spi_driver smi240_spi_driver = {
+ .probe = smi240_probe,
+ .id_table = smi240_spi_id,
+ .driver = {
+ .of_match_table = smi240_of_match,
+ .name = "smi240",
+ },
+};
+module_spi_driver(smi240_spi_driver);
+
+MODULE_AUTHOR("Markus Lochmann <markus.lochmann@de.bosch.com>");
+MODULE_AUTHOR("Stefan Gutmann <stefan.gutmann@de.bosch.com>");
+MODULE_DESCRIPTION("Bosch SMI240 SPI driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
index a3b93566533b..c225b246c8a5 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -447,7 +447,7 @@ struct st_lsm6dsx_hw {
/* Ensure natural alignment of buffer elements */
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan[ST_LSM6DSX_ID_MAX];
};
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index ed0267929725..509e0169dcd5 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -1865,7 +1865,7 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev,
return err;
}
-static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, int state)
+static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, bool state)
{
const struct st_lsm6dsx_reg *reg;
unsigned int data;
@@ -1959,7 +1959,7 @@ static int
st_lsm6dsx_write_event_config(struct iio_dev *iio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
struct st_lsm6dsx_hw *hw = sensor->hw;
@@ -2132,14 +2132,11 @@ st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw,
const struct st_lsm6dsx_reg **drdy_reg)
{
struct device *dev = hw->dev;
+ const struct st_sensors_platform_data *pdata = dev_get_platdata(dev);
int err = 0, drdy_pin;
- if (device_property_read_u32(dev, "st,drdy-int-pin", &drdy_pin) < 0) {
- struct st_sensors_platform_data *pdata;
-
- pdata = (struct st_sensors_platform_data *)dev->platform_data;
+ if (device_property_read_u32(dev, "st,drdy-int-pin", &drdy_pin) < 0)
drdy_pin = pdata ? pdata->drdy_int_pin : 1;
- }
switch (drdy_pin) {
case 1:
@@ -2162,14 +2159,13 @@ st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw,
static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw)
{
const struct st_lsm6dsx_shub_settings *hub_settings;
- struct st_sensors_platform_data *pdata;
struct device *dev = hw->dev;
+ const struct st_sensors_platform_data *pdata = dev_get_platdata(dev);
unsigned int data;
int err = 0;
hub_settings = &hw->settings->shub_settings;
- pdata = (struct st_sensors_platform_data *)dev->platform_data;
if (device_property_read_bool(dev, "st,pullups") ||
(pdata && pdata->pullups)) {
if (hub_settings->pullup_en.sec_page) {
@@ -2524,15 +2520,14 @@ static irqreturn_t st_lsm6dsx_sw_trigger_handler_thread(int irq,
static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw)
{
- struct st_sensors_platform_data *pdata;
const struct st_lsm6dsx_reg *reg;
struct device *dev = hw->dev;
+ const struct st_sensors_platform_data *pdata = dev_get_platdata(dev);
unsigned long irq_type;
bool irq_active_low;
int err;
- irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
-
+ irq_type = irq_get_trigger_type(hw->irq);
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
@@ -2554,7 +2549,6 @@ static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw)
if (err < 0)
return err;
- pdata = (struct st_sensors_platform_data *)dev->platform_data;
if (device_property_read_bool(dev, "drive-open-drain") ||
(pdata && pdata->open_drain)) {
reg = &hw->settings->irq_config.od;
@@ -2639,7 +2633,7 @@ static int st_lsm6dsx_init_regulators(struct device *dev)
int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
struct regmap *regmap)
{
- struct st_sensors_platform_data *pdata = dev->platform_data;
+ const struct st_sensors_platform_data *pdata = dev_get_platdata(dev);
const struct st_lsm6dsx_shub_settings *hub_settings;
struct st_lsm6dsx_hw *hw;
const char *name = NULL;
diff --git a/drivers/iio/industrialio-acpi.c b/drivers/iio/industrialio-acpi.c
index 981b75d40780..d67a43843799 100644
--- a/drivers/iio/industrialio-acpi.c
+++ b/drivers/iio/industrialio-acpi.c
@@ -2,7 +2,8 @@
/* IIO ACPI helper functions */
#include <linux/acpi.h>
-#include <linux/dev_printk.h>
+#include <linux/device.h>
+#include <linux/export.h>
#include <linux/iio/iio.h>
#include <linux/sprintf.h>
@@ -28,17 +29,21 @@ bool iio_read_acpi_mount_matrix(struct device *dev,
char *acpi_method)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_device *adev = ACPI_COMPANION(dev);
char *str;
union acpi_object *obj, *elements;
+ acpi_handle handle;
acpi_status status;
int i, j, val[3];
bool ret = false;
- if (!adev || !acpi_has_method(adev->handle, acpi_method))
+ handle = ACPI_HANDLE(dev);
+ if (!handle)
return false;
- status = acpi_evaluate_object(adev->handle, acpi_method, NULL, &buffer);
+ if (!acpi_has_method(handle, acpi_method))
+ return false;
+
+ status = acpi_evaluate_object(handle, acpi_method, NULL, &buffer);
if (ACPI_FAILURE(status)) {
dev_err(dev, "Failed to get ACPI mount matrix: %d\n", status);
return false;
@@ -83,3 +88,38 @@ out_free_buffer:
return ret;
}
EXPORT_SYMBOL_GPL(iio_read_acpi_mount_matrix);
+
+/**
+ * iio_get_acpi_device_name_and_data() - Return ACPI device instance name and driver data
+ * @dev: Device structure
+ * @data: Optional pointer to return driver data
+ *
+ * When device was enumerated by ACPI ID matching, the user might
+ * want to set description for the physical chip. In such cases
+ * the ACPI device instance name might be used. This call may be
+ * performed to retrieve this information.
+ *
+ * NOTE: This helper function exists only for backward compatibility,
+ * do not use in a new code!
+ *
+ * Returns: ACPI device instance name or %NULL.
+ */
+const char *iio_get_acpi_device_name_and_data(struct device *dev, const void **data)
+{
+ const struct acpi_device_id *id;
+ acpi_handle handle;
+
+ handle = ACPI_HANDLE(dev);
+ if (!handle)
+ return NULL;
+
+ id = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (!id)
+ return NULL;
+
+ if (data)
+ *data = (const void *)id->driver_data;
+
+ return dev_name(dev);
+}
+EXPORT_SYMBOL_GPL(iio_get_acpi_device_name_and_data);
diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
index 20b3b5212da7..529b1087d3fb 100644
--- a/drivers/iio/industrialio-backend.c
+++ b/drivers/iio/industrialio-backend.c
@@ -718,6 +718,84 @@ static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back)
return 0;
}
+/**
+ * iio_backend_ddr_enable - Enable interface DDR (Double Data Rate) mode
+ * @back: Backend device
+ *
+ * Enable DDR, data is generated by the IP at each front (raising and falling)
+ * of the bus clock signal.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_ddr_enable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, ddr_enable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_ddr_enable, IIO_BACKEND);
+
+/**
+ * iio_backend_ddr_disable - Disable interface DDR (Double Data Rate) mode
+ * @back: Backend device
+ *
+ * Disable DDR, setting into SDR mode (Single Data Rate).
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_ddr_disable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, ddr_disable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_ddr_disable, IIO_BACKEND);
+
+/**
+ * iio_backend_data_stream_enable - Enable data stream
+ * @back: Backend device
+ *
+ * Enable data stream over the bus interface.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_data_stream_enable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, data_stream_enable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_stream_enable, IIO_BACKEND);
+
+/**
+ * iio_backend_data_stream_disable - Disable data stream
+ * @back: Backend device
+ *
+ * Disable data stream over the bus interface.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_data_stream_disable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, data_stream_disable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_stream_disable, IIO_BACKEND);
+
+/**
+ * iio_backend_data_transfer_addr - Set data address.
+ * @back: Backend device
+ * @address: Data register address
+ *
+ * Some devices may need to inform the backend about an address
+ * where to read or write the data.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_data_transfer_addr(struct iio_backend *back, u32 address)
+{
+ return iio_backend_op_call(back, data_transfer_addr, address);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_transfer_addr, IIO_BACKEND);
+
static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, const char *name,
struct fwnode_handle *fwnode)
{
@@ -737,8 +815,8 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con
}
fwnode_back = fwnode_find_reference(fwnode, "io-backends", index);
- if (IS_ERR(fwnode))
- return dev_err_cast_probe(dev, fwnode,
+ if (IS_ERR(fwnode_back))
+ return dev_err_cast_probe(dev, fwnode_back,
"Cannot get Firmware reference\n");
guard(mutex)(&iio_back_lock);
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 6a6568d4a2cb..a2117ad1337d 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -95,6 +95,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_DELTA_VELOCITY] = "deltavelocity",
[IIO_COLORTEMP] = "colortemp",
[IIO_CHROMATICITY] = "chromaticity",
+ [IIO_ATTENTION] = "attention",
};
static const char * const iio_modifier_names[] = {
@@ -1665,7 +1666,7 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv)
indio_dev = &iio_dev_opaque->indio_dev;
if (sizeof_priv)
- indio_dev->priv = (char *)iio_dev_opaque +
+ ACCESS_PRIVATE(indio_dev, priv) = (char *)iio_dev_opaque +
ALIGN(sizeof(*iio_dev_opaque), IIO_DMA_MINALIGN);
indio_dev->dev.parent = parent;
diff --git a/drivers/iio/industrialio-gts-helper.c b/drivers/iio/industrialio-gts-helper.c
index 5f131bc1a01e..291c0fc332c9 100644
--- a/drivers/iio/industrialio-gts-helper.c
+++ b/drivers/iio/industrialio-gts-helper.c
@@ -167,7 +167,7 @@ static int iio_gts_gain_cmp(const void *a, const void *b)
static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
{
- int ret, i, j, new_idx, time_idx;
+ int i, j, new_idx, time_idx, ret = 0;
int *all_gains;
size_t gain_bytes;
@@ -205,7 +205,7 @@ static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
memcpy(all_gains, gains[time_idx], gain_bytes);
new_idx = gts->num_hwgain;
- while (time_idx--) {
+ while (time_idx-- > 0) {
for (j = 0; j < gts->num_hwgain; j++) {
int candidate = gains[time_idx][j];
int chk;
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 151099be2863..136b225b6bc8 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -20,7 +20,7 @@
struct iio_map_internal {
struct iio_dev *indio_dev;
- struct iio_map *map;
+ const struct iio_map *map;
struct list_head l;
};
@@ -42,7 +42,7 @@ static int iio_map_array_unregister_locked(struct iio_dev *indio_dev)
return ret;
}
-int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps)
+int iio_map_array_register(struct iio_dev *indio_dev, const struct iio_map *maps)
{
struct iio_map_internal *mapi;
int i = 0;
@@ -86,7 +86,8 @@ static void iio_map_array_unregister_cb(void *indio_dev)
iio_map_array_unregister(indio_dev);
}
-int devm_iio_map_array_register(struct device *dev, struct iio_dev *indio_dev, struct iio_map *maps)
+int devm_iio_map_array_register(struct device *dev, struct iio_dev *indio_dev,
+ const struct iio_map *maps)
{
int ret;
@@ -269,7 +270,7 @@ struct iio_channel *fwnode_iio_channel_get_by_name(struct fwnode_handle *fwnode,
return ERR_PTR(-ENODEV);
}
- chan = __fwnode_iio_channel_get_by_name(fwnode, name);
+ chan = __fwnode_iio_channel_get_by_name(parent, name);
if (!IS_ERR(chan) || PTR_ERR(chan) != -ENODEV) {
fwnode_handle_put(parent);
return chan;
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index f2f3e414849a..29ffa8491927 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -248,7 +248,6 @@ config SENSORS_ISL29018
tristate "Intersil 29018 light and proximity sensor"
depends on I2C
select REGMAP_I2C
- default n
help
If you say yes here you get support for ambient light sensing and
proximity infrared sensing from Intersil ISL29018.
@@ -476,7 +475,7 @@ config OPT3001
depends on I2C
help
If you say Y or M here, you get support for Texas Instruments
- OPT3001 Ambient Light Sensor.
+ OPT3001 Ambient Light Sensor, OPT3002 Light-to-Digital Sensor.
If built as a dynamically linked module, it will be called
opt3001.
@@ -670,13 +669,24 @@ config VCNL4035
To compile this driver as a module, choose M here: the
module will be called vcnl4035.
+config VEML3235
+ tristate "VEML3235 ambient light sensor"
+ select REGMAP_I2C
+ depends on I2C
+ help
+ Say Y here if you want to build a driver for the Vishay VEML3235
+ ambient light sensor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called veml3235.
+
config VEML6030
- tristate "VEML6030 ambient light sensor"
+ tristate "VEML6030 and VEML6035 ambient light sensors"
select REGMAP_I2C
depends on I2C
help
Say Y here if you want to build a driver for the Vishay VEML6030
- ambient light sensor (ALS).
+ and VEML6035 ambient light sensors (ALS).
To compile this driver as a module, choose M here: the
module will be called veml6030.
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 321010fc0b93..f14a37442712 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_TSL4531) += tsl4531.o
obj-$(CONFIG_US5182D) += us5182d.o
obj-$(CONFIG_VCNL4000) += vcnl4000.o
obj-$(CONFIG_VCNL4035) += vcnl4035.o
+obj-$(CONFIG_VEML3235) += veml3235.o
obj-$(CONFIG_VEML6030) += veml6030.o
obj-$(CONFIG_VEML6040) += veml6040.o
obj-$(CONFIG_VEML6070) += veml6070.o
diff --git a/drivers/iio/light/adux1020.c b/drivers/iio/light/adux1020.c
index 2e0170be077a..593d614b1689 100644
--- a/drivers/iio/light/adux1020.c
+++ b/drivers/iio/light/adux1020.c
@@ -502,7 +502,8 @@ fail:
static int adux1020_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct adux1020_data *data = iio_priv(indio_dev);
int ret, mask;
@@ -526,12 +527,11 @@ static int adux1020_write_event_config(struct iio_dev *indio_dev,
mask = ADUX1020_PROX_OFF1_INT;
if (state)
- state = 0;
+ ret = regmap_clear_bits(data->regmap,
+ ADUX1020_REG_INT_MASK, mask);
else
- state = mask;
-
- ret = regmap_update_bits(data->regmap, ADUX1020_REG_INT_MASK,
- mask, state);
+ ret = regmap_set_bits(data->regmap,
+ ADUX1020_REG_INT_MASK, mask);
if (ret < 0)
goto fail;
diff --git a/drivers/iio/light/al3010.c b/drivers/iio/light/al3010.c
index 53569587ccb7..7cbb8b203300 100644
--- a/drivers/iio/light/al3010.c
+++ b/drivers/iio/light/al3010.c
@@ -87,7 +87,12 @@ static int al3010_init(struct al3010_data *data)
int ret;
ret = al3010_set_pwr(data->client, true);
+ if (ret < 0)
+ return ret;
+ ret = devm_add_action_or_reset(&data->client->dev,
+ al3010_set_pwr_off,
+ data);
if (ret < 0)
return ret;
@@ -190,12 +195,6 @@ static int al3010_probe(struct i2c_client *client)
return ret;
}
- ret = devm_add_action_or_reset(&client->dev,
- al3010_set_pwr_off,
- data);
- if (ret < 0)
- return ret;
-
return devm_iio_device_register(&client->dev, indio_dev);
}
diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c
index 11f2ab4ca261..938d76f7e312 100644
--- a/drivers/iio/light/apds9300.c
+++ b/drivers/iio/light/apds9300.c
@@ -46,10 +46,10 @@
struct apds9300_data {
struct i2c_client *client;
struct mutex mutex;
- int power_state;
+ bool power_state;
int thresh_low;
int thresh_hi;
- int intr_en;
+ bool intr_en;
};
/* Lux calculation */
@@ -148,7 +148,7 @@ static int apds9300_set_thresh_hi(struct apds9300_data *data, int value)
return 0;
}
-static int apds9300_set_intr_state(struct apds9300_data *data, int state)
+static int apds9300_set_intr_state(struct apds9300_data *data, bool state)
{
int ret;
u8 cmd;
@@ -169,7 +169,7 @@ static int apds9300_set_intr_state(struct apds9300_data *data, int state)
return 0;
}
-static int apds9300_set_power_state(struct apds9300_data *data, int state)
+static int apds9300_set_power_state(struct apds9300_data *data, bool state)
{
int ret;
u8 cmd;
@@ -221,7 +221,7 @@ static int apds9300_chip_init(struct apds9300_data *data)
* Disable interrupt to ensure thai it is doesn't enable
* i.e. after device soft reset
*/
- ret = apds9300_set_intr_state(data, 0);
+ ret = apds9300_set_intr_state(data, false);
if (ret < 0)
goto err;
@@ -321,7 +321,7 @@ static int apds9300_read_interrupt_config(struct iio_dev *indio_dev,
static int apds9300_write_interrupt_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct apds9300_data *data = iio_priv(indio_dev);
int ret;
@@ -459,8 +459,8 @@ static void apds9300_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
/* Ensure that power off and interrupts are disabled */
- apds9300_set_intr_state(data, 0);
- apds9300_set_power_state(data, 0);
+ apds9300_set_intr_state(data, false);
+ apds9300_set_power_state(data, false);
}
static int apds9300_suspend(struct device *dev)
@@ -470,7 +470,7 @@ static int apds9300_suspend(struct device *dev)
int ret;
mutex_lock(&data->mutex);
- ret = apds9300_set_power_state(data, 0);
+ ret = apds9300_set_power_state(data, false);
mutex_unlock(&data->mutex);
return ret;
@@ -483,7 +483,7 @@ static int apds9300_resume(struct device *dev)
int ret;
mutex_lock(&data->mutex);
- ret = apds9300_set_power_state(data, 1);
+ ret = apds9300_set_power_state(data, true);
mutex_unlock(&data->mutex);
return ret;
diff --git a/drivers/iio/light/apds9306.c b/drivers/iio/light/apds9306.c
index 079e02be1005..9c08e7c3ad0c 100644
--- a/drivers/iio/light/apds9306.c
+++ b/drivers/iio/light/apds9306.c
@@ -1071,7 +1071,7 @@ static int apds9306_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct apds9306_data *data = iio_priv(indio_dev);
struct apds9306_regfields *rf = &data->rf;
@@ -1125,10 +1125,7 @@ static int apds9306_write_event_config(struct iio_dev *indio_dev,
}
}
case IIO_EV_TYPE_THRESH_ADAPTIVE:
- if (state)
- return regmap_field_write(rf->int_thresh_var_en, 1);
- else
- return regmap_field_write(rf->int_thresh_var_en, 0);
+ return regmap_field_write(rf->int_thresh_var_en, state);
default:
return -EINVAL;
}
diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c
index 3c14e4c30805..d30441d33703 100644
--- a/drivers/iio/light/apds9960.c
+++ b/drivers/iio/light/apds9960.c
@@ -133,8 +133,8 @@ struct apds9960_data {
struct regmap_field *reg_enable_pxs;
/* state */
- int als_int;
- int pxs_int;
+ bool als_int;
+ bool pxs_int;
int gesture_mode_running;
/* gain values */
@@ -749,21 +749,17 @@ static int apds9960_read_event_config(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
-
- return 0;
}
static int apds9960_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct apds9960_data *data = iio_priv(indio_dev);
int ret;
- state = !!state;
-
switch (chan->type) {
case IIO_PROXIMITY:
if (data->pxs_int == state)
diff --git a/drivers/iio/light/bh1745.c b/drivers/iio/light/bh1745.c
index 2e458e9d5d85..23e9f16090cc 100644
--- a/drivers/iio/light/bh1745.c
+++ b/drivers/iio/light/bh1745.c
@@ -638,46 +638,42 @@ static int bh1745_read_event_config(struct iio_dev *indio_dev,
static int bh1745_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct bh1745_data *data = iio_priv(indio_dev);
int value;
- if (state == 0)
+ if (!state)
return regmap_clear_bits(data->regmap,
BH1745_INTR, BH1745_INTR_ENABLE);
- if (state == 1) {
- /* Latch is always enabled when enabling interrupt */
- value = BH1745_INTR_ENABLE;
+ /* Latch is always enabled when enabling interrupt */
+ value = BH1745_INTR_ENABLE;
- switch (chan->channel2) {
- case IIO_MOD_LIGHT_RED:
- return regmap_write(data->regmap, BH1745_INTR,
- value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
- BH1745_INTR_SOURCE_RED));
+ switch (chan->channel2) {
+ case IIO_MOD_LIGHT_RED:
+ return regmap_write(data->regmap, BH1745_INTR,
+ value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
+ BH1745_INTR_SOURCE_RED));
- case IIO_MOD_LIGHT_GREEN:
- return regmap_write(data->regmap, BH1745_INTR,
- value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
- BH1745_INTR_SOURCE_GREEN));
+ case IIO_MOD_LIGHT_GREEN:
+ return regmap_write(data->regmap, BH1745_INTR,
+ value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
+ BH1745_INTR_SOURCE_GREEN));
- case IIO_MOD_LIGHT_BLUE:
- return regmap_write(data->regmap, BH1745_INTR,
- value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
- BH1745_INTR_SOURCE_BLUE));
+ case IIO_MOD_LIGHT_BLUE:
+ return regmap_write(data->regmap, BH1745_INTR,
+ value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
+ BH1745_INTR_SOURCE_BLUE));
- case IIO_MOD_LIGHT_CLEAR:
- return regmap_write(data->regmap, BH1745_INTR,
- value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
- BH1745_INTR_SOURCE_CLEAR));
+ case IIO_MOD_LIGHT_CLEAR:
+ return regmap_write(data->regmap, BH1745_INTR,
+ value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
+ BH1745_INTR_SOURCE_CLEAR));
- default:
- return -EINVAL;
- }
+ default:
+ return -EINVAL;
}
-
- return -EINVAL;
}
static int bh1745_read_avail(struct iio_dev *indio_dev,
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index 9df85b3999fa..aeae0566ec12 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -217,8 +217,7 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181)
cm32181->lux_per_bit = CM32181_LUX_PER_BIT;
cm32181->lux_per_bit_base_it = CM32181_LUX_PER_BIT_BASE_IT;
- if (ACPI_HANDLE(cm32181->dev))
- cm32181_acpi_parse_cpm_tables(cm32181);
+ cm32181_acpi_parse_cpm_tables(cm32181);
/* Initialize registers*/
for_each_set_bit(i, &cm32181->init_regs_bitmap, CM32181_CONF_REG_NUM) {
diff --git a/drivers/iio/light/cm3605.c b/drivers/iio/light/cm3605.c
index 22a63a89f289..675c0fd44db4 100644
--- a/drivers/iio/light/cm3605.c
+++ b/drivers/iio/light/cm3605.c
@@ -318,7 +318,7 @@ static struct platform_driver cm3605_driver = {
.pm = pm_sleep_ptr(&cm3605_dev_pm_ops),
},
.probe = cm3605_probe,
- .remove_new = cm3605_remove,
+ .remove = cm3605_remove,
};
module_platform_driver(cm3605_driver);
diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c
index a4a1505534c0..ae3fc3299eec 100644
--- a/drivers/iio/light/cm36651.c
+++ b/drivers/iio/light/cm36651.c
@@ -529,7 +529,7 @@ static int cm36651_write_prox_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct cm36651_data *cm36651 = iio_priv(indio_dev);
int cmd, ret;
diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c
index f8b1d7dd6f5f..d56ee217fe53 100644
--- a/drivers/iio/light/gp2ap002.c
+++ b/drivers/iio/light/gp2ap002.c
@@ -340,7 +340,7 @@ static int gp2ap002_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct gp2ap002 *gp2ap002 = iio_priv(indio_dev);
diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c
index 81e718cdeae3..1a352c88598e 100644
--- a/drivers/iio/light/gp2ap020a00f.c
+++ b/drivers/iio/light/gp2ap020a00f.c
@@ -1159,7 +1159,7 @@ static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
enum gp2ap020a00f_cmd cmd;
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 260281194f61..4eb692322432 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -31,7 +31,7 @@ struct als_state {
struct iio_chan_spec channels[CHANNEL_SCAN_INDEX_MAX + 1];
struct {
u32 illum[CHANNEL_SCAN_INDEX_MAX];
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -356,11 +356,11 @@ static int als_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_als_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static const char *name = "als";
struct iio_dev *indio_dev;
struct als_state *als_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state));
if (!indio_dev)
@@ -438,7 +438,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_als_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct als_state *als_state = iio_priv(indio_dev);
@@ -467,7 +467,7 @@ static struct platform_driver hid_als_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_als_probe,
- .remove_new = hid_als_remove,
+ .remove = hid_als_remove,
};
module_platform_driver(hid_als_platform_driver);
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index 26c481d2998c..e8e7b2999b4c 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -13,16 +13,32 @@
#include <linux/iio/buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
-#define CHANNEL_SCAN_INDEX_PRESENCE 0
+static const u32 prox_usage_ids[] = {
+ HID_USAGE_SENSOR_HUMAN_PRESENCE,
+ HID_USAGE_SENSOR_HUMAN_PROXIMITY,
+ HID_USAGE_SENSOR_HUMAN_ATTENTION,
+};
+
+#define MAX_CHANNELS ARRAY_SIZE(prox_usage_ids)
+
+enum {
+ HID_HUMAN_PRESENCE,
+ HID_HUMAN_PROXIMITY,
+ HID_HUMAN_ATTENTION,
+};
struct prox_state {
struct hid_sensor_hub_callbacks callbacks;
struct hid_sensor_common common_attributes;
- struct hid_sensor_hub_attribute_info prox_attr;
- u32 human_presence;
+ struct hid_sensor_hub_attribute_info prox_attr[MAX_CHANNELS];
+ struct iio_chan_spec channels[MAX_CHANNELS];
+ u32 channel2usage[MAX_CHANNELS];
+ u32 human_presence[MAX_CHANNELS];
int scale_pre_decml;
int scale_post_decml;
int scale_precision;
+ unsigned long scan_mask[2]; /* One entry plus one terminator. */
+ int num_channels;
};
static const u32 prox_sensitivity_addresses[] = {
@@ -30,17 +46,24 @@ static const u32 prox_sensitivity_addresses[] = {
HID_USAGE_SENSOR_DATA_PRESENCE,
};
-/* Channel definitions */
-static const struct iio_chan_spec prox_channels[] = {
- {
- .type = IIO_PROXIMITY,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
- BIT(IIO_CHAN_INFO_SCALE) |
- BIT(IIO_CHAN_INFO_SAMP_FREQ) |
- BIT(IIO_CHAN_INFO_HYSTERESIS),
- .scan_index = CHANNEL_SCAN_INDEX_PRESENCE,
+#define PROX_CHANNEL(_is_proximity, _channel) \
+ {\
+ .type = _is_proximity ? IIO_PROXIMITY : IIO_ATTENTION,\
+ .info_mask_separate = _is_proximity ? BIT(IIO_CHAN_INFO_RAW) :\
+ BIT(IIO_CHAN_INFO_PROCESSED),\
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |\
+ BIT(IIO_CHAN_INFO_SCALE) |\
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |\
+ BIT(IIO_CHAN_INFO_HYSTERESIS),\
+ .indexed = _is_proximity,\
+ .channel = _channel,\
}
+
+/* Channel definitions (same order as prox_usage_ids) */
+static const struct iio_chan_spec prox_channels[] = {
+ PROX_CHANNEL(true, HID_HUMAN_PRESENCE),
+ PROX_CHANNEL(true, HID_HUMAN_PROXIMITY),
+ PROX_CHANNEL(false, 0),
};
/* Adjust channel real bits based on report descriptor */
@@ -62,7 +85,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
{
struct prox_state *prox_state = iio_priv(indio_dev);
struct hid_sensor_hub_device *hsdev;
- int report_id = -1;
+ int report_id;
u32 address;
int ret_type;
s32 min;
@@ -71,29 +94,23 @@ static int prox_read_raw(struct iio_dev *indio_dev,
*val2 = 0;
switch (mask) {
case IIO_CHAN_INFO_RAW:
- switch (chan->scan_index) {
- case CHANNEL_SCAN_INDEX_PRESENCE:
- report_id = prox_state->prox_attr.report_id;
- min = prox_state->prox_attr.logical_minimum;
- address = HID_USAGE_SENSOR_HUMAN_PRESENCE;
- hsdev = prox_state->common_attributes.hsdev;
- break;
- default:
- report_id = -1;
- break;
- }
- if (report_id >= 0) {
- hid_sensor_power_state(&prox_state->common_attributes,
- true);
- *val = sensor_hub_input_attr_get_raw_value(
- hsdev, hsdev->usage, address, report_id,
- SENSOR_HUB_SYNC, min < 0);
- hid_sensor_power_state(&prox_state->common_attributes,
- false);
- } else {
- *val = 0;
+ if (chan->scan_index >= prox_state->num_channels)
return -EINVAL;
- }
+ address = prox_state->channel2usage[chan->scan_index];
+ report_id = prox_state->prox_attr[chan->scan_index].report_id;
+ hsdev = prox_state->common_attributes.hsdev;
+ min = prox_state->prox_attr[chan->scan_index].logical_minimum;
+ hid_sensor_power_state(&prox_state->common_attributes, true);
+ *val = sensor_hub_input_attr_get_raw_value(hsdev,
+ hsdev->usage,
+ address,
+ report_id,
+ SENSOR_HUB_SYNC,
+ min < 0);
+ if (prox_state->channel2usage[chan->scan_index] ==
+ HID_USAGE_SENSOR_HUMAN_ATTENTION)
+ *val *= 100;
+ hid_sensor_power_state(&prox_state->common_attributes, false);
ret_type = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SCALE:
@@ -103,7 +120,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
break;
case IIO_CHAN_INFO_OFFSET:
*val = hid_sensor_convert_exponent(
- prox_state->prox_attr.unit_expo);
+ prox_state->prox_attr[chan->scan_index].unit_expo);
ret_type = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -153,14 +170,6 @@ static const struct iio_info prox_info = {
.write_raw = &prox_write_raw,
};
-/* Function to push data to buffer */
-static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
- int len)
-{
- dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
- iio_push_to_buffers(indio_dev, data);
-}
-
/* Callback handler to send event after all samples are received and captured */
static int prox_proc_event(struct hid_sensor_hub_device *hsdev,
unsigned usage_id,
@@ -170,10 +179,10 @@ static int prox_proc_event(struct hid_sensor_hub_device *hsdev,
struct prox_state *prox_state = iio_priv(indio_dev);
dev_dbg(&indio_dev->dev, "prox_proc_event\n");
- if (atomic_read(&prox_state->common_attributes.data_ready))
- hid_sensor_push_data(indio_dev,
- &prox_state->human_presence,
- sizeof(prox_state->human_presence));
+ if (atomic_read(&prox_state->common_attributes.data_ready)) {
+ dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
+ iio_push_to_buffers(indio_dev, &prox_state->human_presence);
+ }
return 0;
}
@@ -186,58 +195,77 @@ static int prox_capture_sample(struct hid_sensor_hub_device *hsdev,
{
struct iio_dev *indio_dev = platform_get_drvdata(priv);
struct prox_state *prox_state = iio_priv(indio_dev);
- int ret = -EINVAL;
-
- switch (usage_id) {
- case HID_USAGE_SENSOR_HUMAN_PRESENCE:
- switch (raw_len) {
- case 1:
- prox_state->human_presence = *(u8 *)raw_data;
- return 0;
- case 4:
- prox_state->human_presence = *(u32 *)raw_data;
- return 0;
- default:
+ int multiplier = 1;
+ int chan;
+
+ for (chan = 0; chan < prox_state->num_channels; chan++)
+ if (prox_state->channel2usage[chan] == usage_id)
break;
- }
- break;
+ if (chan == prox_state->num_channels)
+ return -EINVAL;
+
+ if (usage_id == HID_USAGE_SENSOR_HUMAN_ATTENTION)
+ multiplier = 100;
+
+ switch (raw_len) {
+ case 1:
+ prox_state->human_presence[chan] = *(u8 *)raw_data * multiplier;
+ return 0;
+ case 4:
+ prox_state->human_presence[chan] = *(u32 *)raw_data * multiplier;
+ return 0;
}
- return ret;
+ return -EINVAL;
}
/* Parse report which is specific to an usage id*/
static int prox_parse_report(struct platform_device *pdev,
struct hid_sensor_hub_device *hsdev,
- struct iio_chan_spec *channels,
- unsigned usage_id,
struct prox_state *st)
{
+ struct iio_chan_spec *channels = st->channels;
+ int index = 0;
int ret;
+ int i;
+
+ for (i = 0; i < MAX_CHANNELS; i++) {
+ u32 usage_id = prox_usage_ids[i];
+
+ ret = sensor_hub_input_get_attribute_info(hsdev,
+ HID_INPUT_REPORT,
+ hsdev->usage,
+ usage_id,
+ &st->prox_attr[index]);
+ if (ret < 0)
+ continue;
+ st->channel2usage[index] = usage_id;
+ st->scan_mask[0] |= BIT(index);
+ channels[index] = prox_channels[i];
+ channels[index].scan_index = index;
+ prox_adjust_channel_bit_mask(channels, index,
+ st->prox_attr[index].size);
+ dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr[index].index,
+ st->prox_attr[index].report_id);
+ index++;
+ }
- ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT,
- usage_id,
- HID_USAGE_SENSOR_HUMAN_PRESENCE,
- &st->prox_attr);
- if (ret < 0)
+ if (!index)
return ret;
- prox_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_PRESENCE,
- st->prox_attr.size);
- dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr.index,
- st->prox_attr.report_id);
+ st->num_channels = index;
- return ret;
+ return 0;
}
/* Function to initialize the processing for usage id */
static int hid_prox_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static const char *name = "prox";
struct iio_dev *indio_dev;
struct prox_state *prox_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct prox_state));
@@ -258,22 +286,15 @@ static int hid_prox_probe(struct platform_device *pdev)
return ret;
}
- indio_dev->channels = devm_kmemdup(&pdev->dev, prox_channels,
- sizeof(prox_channels), GFP_KERNEL);
- if (!indio_dev->channels) {
- dev_err(&pdev->dev, "failed to duplicate channels\n");
- return -ENOMEM;
- }
-
- ret = prox_parse_report(pdev, hsdev,
- (struct iio_chan_spec *)indio_dev->channels,
- hsdev->usage, prox_state);
+ ret = prox_parse_report(pdev, hsdev, prox_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
return ret;
}
- indio_dev->num_channels = ARRAY_SIZE(prox_channels);
+ indio_dev->num_channels = prox_state->num_channels;
+ indio_dev->channels = prox_state->channels;
+ indio_dev->available_scan_masks = prox_state->scan_mask;
indio_dev->info = &prox_info;
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -315,7 +336,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_prox_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct prox_state *prox_state = iio_priv(indio_dev);
@@ -344,7 +365,7 @@ static struct platform_driver hid_prox_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_prox_probe,
- .remove_new = hid_prox_remove,
+ .remove = hid_prox_remove,
};
module_platform_driver(hid_prox_platform_driver);
diff --git a/drivers/iio/light/iqs621-als.c b/drivers/iio/light/iqs621-als.c
index 6de33feada3a..b9f230210f07 100644
--- a/drivers/iio/light/iqs621-als.c
+++ b/drivers/iio/light/iqs621-als.c
@@ -271,7 +271,7 @@ static int iqs621_als_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct iqs621_als_private *iqs621_als = iio_priv(indio_dev);
struct iqs62x_core *iqs62x = iqs621_als->iqs62x;
diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c
index 8dfc750e68c0..201eae1c4589 100644
--- a/drivers/iio/light/isl29018.c
+++ b/drivers/iio/light/isl29018.c
@@ -8,17 +8,18 @@
* Copyright (c) 2010, NVIDIA Corporation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/err.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
+
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
-#include <linux/acpi.h>
#define ISL29018_CONV_TIME_MS 100
@@ -687,20 +688,6 @@ static const struct isl29018_chip_info isl29018_chip_info_tbl[] = {
},
};
-static const char *isl29018_match_acpi_device(struct device *dev, int *data)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
-
- if (!id)
- return NULL;
-
- *data = (int)id->driver_data;
-
- return dev_name(dev);
-}
-
static void isl29018_disable_regulator_action(void *_data)
{
struct isl29018_chip *chip = _data;
@@ -716,9 +703,10 @@ static int isl29018_probe(struct i2c_client *client)
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct isl29018_chip *chip;
struct iio_dev *indio_dev;
+ const void *ddata = NULL;
+ const char *name;
+ int dev_id;
int err;
- const char *name = NULL;
- int dev_id = 0;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
if (!indio_dev)
@@ -731,11 +719,11 @@ static int isl29018_probe(struct i2c_client *client)
if (id) {
name = id->name;
dev_id = id->driver_data;
+ } else {
+ name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
+ dev_id = (intptr_t)ddata;
}
- if (ACPI_HANDLE(&client->dev))
- name = isl29018_match_acpi_device(&client->dev, &dev_id);
-
mutex_init(&chip->lock);
chip->type = dev_id;
@@ -832,15 +820,13 @@ static int isl29018_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend,
isl29018_resume);
-#ifdef CONFIG_ACPI
static const struct acpi_device_id isl29018_acpi_match[] = {
{"ISL29018", isl29018},
{"ISL29023", isl29023},
{"ISL29035", isl29035},
- {},
+ {}
};
MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match);
-#endif
static const struct i2c_device_id isl29018_id[] = {
{"isl29018", isl29018},
@@ -854,14 +840,14 @@ static const struct of_device_id isl29018_of_match[] = {
{ .compatible = "isil,isl29018", },
{ .compatible = "isil,isl29023", },
{ .compatible = "isil,isl29035", },
- { },
+ { }
};
MODULE_DEVICE_TABLE(of, isl29018_of_match);
static struct i2c_driver isl29018_driver = {
.driver = {
.name = "isl29018",
- .acpi_match_table = ACPI_PTR(isl29018_acpi_match),
+ .acpi_match_table = isl29018_acpi_match,
.pm = pm_sleep_ptr(&isl29018_pm_ops),
.of_match_table = isl29018_of_match,
},
diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c
index 7800f7fa51b7..99f0b903018c 100644
--- a/drivers/iio/light/lm3533-als.c
+++ b/drivers/iio/light/lm3533-als.c
@@ -754,7 +754,7 @@ static int lm3533_als_set_resistor(struct lm3533_als *als, u8 val)
}
static int lm3533_als_setup(struct lm3533_als *als,
- struct lm3533_als_platform_data *pdata)
+ const struct lm3533_als_platform_data *pdata)
{
int ret;
@@ -828,8 +828,8 @@ static const struct iio_info lm3533_als_info = {
static int lm3533_als_probe(struct platform_device *pdev)
{
+ const struct lm3533_als_platform_data *pdata;
struct lm3533 *lm3533;
- struct lm3533_als_platform_data *pdata;
struct lm3533_als *als;
struct iio_dev *indio_dev;
int ret;
@@ -838,7 +838,7 @@ static int lm3533_als_probe(struct platform_device *pdev)
if (!lm3533)
return -EINVAL;
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "no platform data\n");
return -EINVAL;
@@ -912,7 +912,7 @@ static struct platform_driver lm3533_als_driver = {
.name = "lm3533-als",
},
.probe = lm3533_als_probe,
- .remove_new = lm3533_als_remove,
+ .remove = lm3533_als_remove,
};
module_platform_driver(lm3533_als_driver);
diff --git a/drivers/iio/light/ltr390.c b/drivers/iio/light/ltr390.c
index 4f6975e63a8f..df664f360903 100644
--- a/drivers/iio/light/ltr390.c
+++ b/drivers/iio/light/ltr390.c
@@ -18,14 +18,18 @@
* - Interrupt support
*/
+#include <linux/bitfield.h>
+#include <linux/device.h>
#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/math.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
-#include <linux/bitfield.h>
#include <linux/iio/iio.h>
+#include <linux/iio/events.h>
#include <linux/unaligned.h>
@@ -33,18 +37,27 @@
#define LTR390_ALS_UVS_MEAS_RATE 0x04
#define LTR390_ALS_UVS_GAIN 0x05
#define LTR390_PART_ID 0x06
+#define LTR390_MAIN_STATUS 0x07
#define LTR390_ALS_DATA 0x0D
#define LTR390_UVS_DATA 0x10
#define LTR390_INT_CFG 0x19
+#define LTR390_INT_PST 0x1A
+#define LTR390_THRESH_UP 0x21
+#define LTR390_THRESH_LOW 0x24
#define LTR390_PART_NUMBER_ID 0xb
-#define LTR390_ALS_UVS_GAIN_MASK 0x07
-#define LTR390_ALS_UVS_INT_TIME_MASK 0x70
+#define LTR390_ALS_UVS_GAIN_MASK GENMASK(2, 0)
+#define LTR390_ALS_UVS_MEAS_RATE_MASK GENMASK(2, 0)
+#define LTR390_ALS_UVS_INT_TIME_MASK GENMASK(6, 4)
#define LTR390_ALS_UVS_INT_TIME(x) FIELD_PREP(LTR390_ALS_UVS_INT_TIME_MASK, (x))
+#define LTR390_INT_PST_MASK GENMASK(7, 4)
+#define LTR390_INT_PST_VAL(x) FIELD_PREP(LTR390_INT_PST_MASK, (x))
#define LTR390_SW_RESET BIT(4)
#define LTR390_UVS_MODE BIT(3)
#define LTR390_SENSOR_ENABLE BIT(1)
+#define LTR390_LS_INT_EN BIT(2)
+#define LTR390_LS_INT_SEL_UVS BIT(5)
#define LTR390_FRACTIONAL_PRECISION 100
@@ -70,6 +83,11 @@ enum ltr390_mode {
LTR390_SET_UVS_MODE,
};
+enum ltr390_meas_rate {
+ LTR390_GET_FREQ,
+ LTR390_GET_PERIOD,
+};
+
struct ltr390_data {
struct regmap *regmap;
struct i2c_client *client;
@@ -87,6 +105,18 @@ static const struct regmap_config ltr390_regmap_config = {
.val_bits = 8,
};
+/* Sampling frequency is in mili Hz and mili Seconds */
+static const int ltr390_samp_freq_table[][2] = {
+ [0] = { 40000, 25 },
+ [1] = { 20000, 50 },
+ [2] = { 10000, 100 },
+ [3] = { 5000, 200 },
+ [4] = { 2000, 500 },
+ [5] = { 1000, 1000 },
+ [6] = { 500, 2000 },
+ [7] = { 500, 2000 },
+};
+
static int ltr390_register_read(struct ltr390_data *data, u8 register_address)
{
struct device *dev = &data->client->dev;
@@ -135,6 +165,19 @@ static int ltr390_counts_per_uvi(struct ltr390_data *data)
return DIV_ROUND_CLOSEST(23 * data->gain * data->int_time_us, 10 * orig_gain * orig_int_time);
}
+static int ltr390_get_samp_freq_or_period(struct ltr390_data *data,
+ enum ltr390_meas_rate option)
+{
+ int ret, value;
+
+ ret = regmap_read(data->regmap, LTR390_ALS_UVS_MEAS_RATE, &value);
+ if (ret < 0)
+ return ret;
+ value = FIELD_GET(LTR390_ALS_UVS_MEAS_RATE_MASK, value);
+
+ return ltr390_samp_freq_table[value][option];
+}
+
static int ltr390_read_raw(struct iio_dev *iio_device,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
@@ -191,6 +234,10 @@ static int ltr390_read_raw(struct iio_dev *iio_device,
*val = data->int_time_us;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = ltr390_get_samp_freq_or_period(data, LTR390_GET_FREQ);
+ return IIO_VAL_INT;
+
default:
return -EINVAL;
}
@@ -199,6 +246,24 @@ static int ltr390_read_raw(struct iio_dev *iio_device,
/* integration time in us */
static const int ltr390_int_time_map_us[] = { 400000, 200000, 100000, 50000, 25000, 12500 };
static const int ltr390_gain_map[] = { 1, 3, 6, 9, 18 };
+static const int ltr390_freq_map[] = { 40000, 20000, 10000, 5000, 2000, 1000, 500, 500 };
+
+static const struct iio_event_spec ltr390_event_spec[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE),
+ }, {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE),
+ }, {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_EITHER,
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE) |
+ BIT(IIO_EV_INFO_PERIOD),
+ }
+};
static const struct iio_chan_spec ltr390_channels[] = {
/* UV sensor */
@@ -206,16 +271,24 @@ static const struct iio_chan_spec ltr390_channels[] = {
.type = IIO_UVINDEX,
.scan_index = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
- .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE)
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .event_spec = ltr390_event_spec,
+ .num_event_specs = ARRAY_SIZE(ltr390_event_spec),
},
/* ALS sensor */
{
.type = IIO_LIGHT,
.scan_index = 1,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
- .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE)
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .event_spec = ltr390_event_spec,
+ .num_event_specs = ARRAY_SIZE(ltr390_event_spec),
},
};
@@ -264,6 +337,23 @@ static int ltr390_set_int_time(struct ltr390_data *data, int val)
return -EINVAL;
}
+static int ltr390_set_samp_freq(struct ltr390_data *data, int val)
+{
+ int idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(ltr390_samp_freq_table); idx++) {
+ if (ltr390_samp_freq_table[idx][0] != val)
+ continue;
+
+ guard(mutex)(&data->lock);
+ return regmap_update_bits(data->regmap,
+ LTR390_ALS_UVS_MEAS_RATE,
+ LTR390_ALS_UVS_MEAS_RATE_MASK, idx);
+ }
+
+ return -EINVAL;
+}
+
static int ltr390_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
const int **vals, int *type, int *length, long mask)
{
@@ -278,6 +368,11 @@ static int ltr390_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec con
*type = IIO_VAL_INT;
*vals = ltr390_int_time_map_us;
return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *length = ARRAY_SIZE(ltr390_freq_map);
+ *type = IIO_VAL_INT;
+ *vals = ltr390_freq_map;
+ return IIO_AVAIL_LIST;
default:
return -EINVAL;
}
@@ -301,6 +396,191 @@ static int ltr390_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec cons
return ltr390_set_int_time(data, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val2 != 0)
+ return -EINVAL;
+
+ return ltr390_set_samp_freq(data, val);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_read_intr_prst(struct ltr390_data *data, int *val)
+{
+ int ret, prst, samp_period;
+
+ samp_period = ltr390_get_samp_freq_or_period(data, LTR390_GET_PERIOD);
+ ret = regmap_read(data->regmap, LTR390_INT_PST, &prst);
+ if (ret < 0)
+ return ret;
+ *val = prst * samp_period;
+
+ return IIO_VAL_INT;
+}
+
+static int ltr390_write_intr_prst(struct ltr390_data *data, int val)
+{
+ int ret, samp_period, new_val;
+
+ samp_period = ltr390_get_samp_freq_or_period(data, LTR390_GET_PERIOD);
+
+ /* persist period should be greater than or equal to samp period */
+ if (val < samp_period)
+ return -EINVAL;
+
+ new_val = DIV_ROUND_UP(val, samp_period);
+ if (new_val < 0 || new_val > 0x0f)
+ return -EINVAL;
+
+ guard(mutex)(&data->lock);
+ ret = regmap_update_bits(data->regmap,
+ LTR390_INT_PST,
+ LTR390_INT_PST_MASK,
+ LTR390_INT_PST_VAL(new_val));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int ltr390_read_threshold(struct iio_dev *indio_dev,
+ enum iio_event_direction dir,
+ int *val, int *val2)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ ret = ltr390_register_read(data, LTR390_THRESH_UP);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+
+ case IIO_EV_DIR_FALLING:
+ ret = ltr390_register_read(data, LTR390_THRESH_LOW);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_write_threshold(struct iio_dev *indio_dev,
+ enum iio_event_direction dir,
+ int val, int val2)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+
+ guard(mutex)(&data->lock);
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return regmap_bulk_write(data->regmap, LTR390_THRESH_UP, &val, 3);
+
+ case IIO_EV_DIR_FALLING:
+ return regmap_bulk_write(data->regmap, LTR390_THRESH_LOW, &val, 3);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_read_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int *val, int *val2)
+{
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ return ltr390_read_threshold(indio_dev, dir, val, val2);
+
+ case IIO_EV_INFO_PERIOD:
+ return ltr390_read_intr_prst(iio_priv(indio_dev), val);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_write_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int val, int val2)
+{
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ if (val2 != 0)
+ return -EINVAL;
+
+ return ltr390_write_threshold(indio_dev, dir, val, val2);
+
+ case IIO_EV_INFO_PERIOD:
+ if (val2 != 0)
+ return -EINVAL;
+
+ return ltr390_write_intr_prst(iio_priv(indio_dev), val);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+ int ret, status;
+
+ ret = regmap_read(data->regmap, LTR390_INT_CFG, &status);
+ if (ret < 0)
+ return ret;
+
+ return FIELD_GET(LTR390_LS_INT_EN, status);
+}
+
+static int ltr390_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ bool state)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+ int ret;
+
+ if (!state)
+ return regmap_clear_bits(data->regmap, LTR390_INT_CFG, LTR390_LS_INT_EN);
+
+ guard(mutex)(&data->lock);
+ ret = regmap_set_bits(data->regmap, LTR390_INT_CFG, LTR390_LS_INT_EN);
+ if (ret < 0)
+ return ret;
+
+ switch (chan->type) {
+ case IIO_LIGHT:
+ ret = ltr390_set_mode(data, LTR390_SET_ALS_MODE);
+ if (ret < 0)
+ return ret;
+
+ return regmap_clear_bits(data->regmap, LTR390_INT_CFG, LTR390_LS_INT_SEL_UVS);
+
+ case IIO_UVINDEX:
+ ret = ltr390_set_mode(data, LTR390_SET_UVS_MODE);
+ if (ret < 0)
+ return ret;
+
+ return regmap_set_bits(data->regmap, LTR390_INT_CFG, LTR390_LS_INT_SEL_UVS);
+
default:
return -EINVAL;
}
@@ -310,8 +590,44 @@ static const struct iio_info ltr390_info = {
.read_raw = ltr390_read_raw,
.write_raw = ltr390_write_raw,
.read_avail = ltr390_read_avail,
+ .read_event_value = ltr390_read_event_value,
+ .read_event_config = ltr390_read_event_config,
+ .write_event_value = ltr390_write_event_value,
+ .write_event_config = ltr390_write_event_config,
};
+static irqreturn_t ltr390_interrupt_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct ltr390_data *data = iio_priv(indio_dev);
+ int ret, status;
+
+ /* Reading the status register to clear the interrupt flag, Datasheet pg: 17*/
+ ret = regmap_read(data->regmap, LTR390_MAIN_STATUS, &status);
+ if (ret < 0)
+ return ret;
+
+ switch (data->mode) {
+ case LTR390_SET_ALS_MODE:
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ iio_get_time_ns(indio_dev));
+ break;
+
+ case LTR390_SET_UVS_MODE:
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_UVINDEX, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ iio_get_time_ns(indio_dev));
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
static int ltr390_probe(struct i2c_client *client)
{
struct ltr390_data *data;
@@ -365,9 +681,40 @@ static int ltr390_probe(struct i2c_client *client)
if (ret)
return dev_err_probe(dev, ret, "failed to enable the sensor\n");
+ if (client->irq) {
+ ret = devm_request_threaded_irq(dev, client->irq,
+ NULL, ltr390_interrupt_handler,
+ IRQF_ONESHOT,
+ "ltr390_thresh_event",
+ indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "request irq (%d) failed\n", client->irq);
+ }
+
return devm_iio_device_register(dev, indio_dev);
}
+static int ltr390_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ltr390_data *data = iio_priv(indio_dev);
+
+ return regmap_clear_bits(data->regmap, LTR390_MAIN_CTRL,
+ LTR390_SENSOR_ENABLE);
+}
+
+static int ltr390_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ltr390_data *data = iio_priv(indio_dev);
+
+ return regmap_set_bits(data->regmap, LTR390_MAIN_CTRL,
+ LTR390_SENSOR_ENABLE);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(ltr390_pm_ops, ltr390_suspend, ltr390_resume);
+
static const struct i2c_device_id ltr390_id[] = {
{ "ltr390" },
{ /* Sentinel */ }
@@ -384,6 +731,7 @@ static struct i2c_driver ltr390_driver = {
.driver = {
.name = "ltr390",
.of_match_table = ltr390_of_table,
+ .pm = pm_sleep_ptr(&ltr390_pm_ops),
},
.probe = ltr390_probe,
.id_table = ltr390_id,
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index 8c516ede9116..604f5f900a2e 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -15,7 +15,6 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/regmap.h>
-#include <linux/acpi.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
@@ -1078,15 +1077,11 @@ static int ltr501_read_event_config(struct iio_dev *indio_dev,
static int ltr501_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct ltr501_data *data = iio_priv(indio_dev);
int ret;
- /* only 1 and 0 are valid inputs */
- if (state != 1 && state != 0)
- return -EINVAL;
-
switch (chan->type) {
case IIO_INTENSITY:
mutex_lock(&data->lock_als);
@@ -1422,17 +1417,6 @@ static int ltr501_powerdown(struct ltr501_data *data)
data->ps_contr & ~LTR501_CONTR_ACTIVE);
}
-static const char *ltr501_match_acpi_device(struct device *dev, int *chip_idx)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
- *chip_idx = id->driver_data;
- return dev_name(dev);
-}
-
static int ltr501_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -1440,8 +1424,10 @@ static int ltr501_probe(struct i2c_client *client)
struct ltr501_data *data;
struct iio_dev *indio_dev;
struct regmap *regmap;
- int ret, partid, chip_idx = 0;
- const char *name = NULL;
+ const void *ddata = NULL;
+ int partid, chip_idx;
+ const char *name;
+ int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -1523,11 +1509,12 @@ static int ltr501_probe(struct i2c_client *client)
if (id) {
name = id->name;
chip_idx = id->driver_data;
- } else if (ACPI_HANDLE(&client->dev)) {
- name = ltr501_match_acpi_device(&client->dev, &chip_idx);
} else {
- return -ENODEV;
+ name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
+ chip_idx = (intptr_t)ddata;
}
+ if (!name)
+ return -ENODEV;
data->chip_info = &ltr501_chip_info_tbl[chip_idx];
@@ -1610,9 +1597,9 @@ static int ltr501_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(ltr501_pm_ops, ltr501_suspend, ltr501_resume);
static const struct acpi_device_id ltr_acpi_match[] = {
- { "LTER0501", ltr501 },
- { "LTER0559", ltr559 },
{ "LTER0301", ltr301 },
+ /* https://www.catalog.update.microsoft.com/Search.aspx?q=lter0303 */
+ { "LTER0303", ltr303 },
{ },
};
MODULE_DEVICE_TABLE(acpi, ltr_acpi_match);
diff --git a/drivers/iio/light/ltrf216a.c b/drivers/iio/light/ltrf216a.c
index 37eecff571b9..dbec1e7cfeb8 100644
--- a/drivers/iio/light/ltrf216a.c
+++ b/drivers/iio/light/ltrf216a.c
@@ -561,6 +561,7 @@ MODULE_DEVICE_TABLE(i2c, ltrf216a_id);
static const struct of_device_id ltrf216a_of_match[] = {
{ .compatible = "liteon,ltr308", .data = &ltr308_chip_info },
{ .compatible = "liteon,ltrf216a", .data = &ltrf216a_chip_info },
+ /* For Valve's Steamdeck device, an ACPI platform using PRP0001 */
{ .compatible = "ltr,ltrf216a", .data = &ltrf216a_chip_info },
{}
};
diff --git a/drivers/iio/light/max44009.c b/drivers/iio/light/max44009.c
index 3b92362675dc..8cd7f5664e5b 100644
--- a/drivers/iio/light/max44009.c
+++ b/drivers/iio/light/max44009.c
@@ -422,7 +422,7 @@ static int max44009_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct max44009_data *data = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index 176e54bb48c3..65b295877b41 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -70,6 +70,35 @@
#define OPT3001_RESULT_READY_SHORT 150
#define OPT3001_RESULT_READY_LONG 1000
+struct opt3001_scale {
+ int val;
+ int val2;
+};
+
+struct opt3001_chip_info {
+ const struct iio_chan_spec (*channels)[2];
+ enum iio_chan_type chan_type;
+ int num_channels;
+
+ const struct opt3001_scale (*scales)[12];
+ /*
+ * Factor as specified by conversion equation in datasheet.
+ * eg. 0.01 (scaled to integer 10) for opt3001.
+ */
+ int factor_whole;
+ /*
+ * Factor to compensate for potentially scaled factor_whole.
+ */
+ int factor_integer;
+ /*
+ * Factor used to align decimal part of proccessed value to six decimal
+ * places.
+ */
+ int factor_decimal;
+
+ bool has_id;
+};
+
struct opt3001 {
struct i2c_client *client;
struct device *dev;
@@ -79,6 +108,7 @@ struct opt3001 {
bool result_ready;
wait_queue_head_t result_ready_queue;
u16 result;
+ const struct opt3001_chip_info *chip_info;
u32 int_time;
u32 mode;
@@ -92,11 +122,6 @@ struct opt3001 {
bool use_irq;
};
-struct opt3001_scale {
- int val;
- int val2;
-};
-
static const struct opt3001_scale opt3001_scales[] = {
{
.val = 40,
@@ -148,21 +173,68 @@ static const struct opt3001_scale opt3001_scales[] = {
},
};
+static const struct opt3001_scale opt3002_scales[] = {
+ {
+ .val = 4914,
+ .val2 = 0,
+ },
+ {
+ .val = 9828,
+ .val2 = 0,
+ },
+ {
+ .val = 19656,
+ .val2 = 0,
+ },
+ {
+ .val = 39312,
+ .val2 = 0,
+ },
+ {
+ .val = 78624,
+ .val2 = 0,
+ },
+ {
+ .val = 157248,
+ .val2 = 0,
+ },
+ {
+ .val = 314496,
+ .val2 = 0,
+ },
+ {
+ .val = 628992,
+ .val2 = 0,
+ },
+ {
+ .val = 1257984,
+ .val2 = 0,
+ },
+ {
+ .val = 2515968,
+ .val2 = 0,
+ },
+ {
+ .val = 5031936,
+ .val2 = 0,
+ },
+ {
+ .val = 10063872,
+ .val2 = 0,
+ },
+};
+
static int opt3001_find_scale(const struct opt3001 *opt, int val,
int val2, u8 *exponent)
{
int i;
-
- for (i = 0; i < ARRAY_SIZE(opt3001_scales); i++) {
- const struct opt3001_scale *scale = &opt3001_scales[i];
-
+ for (i = 0; i < ARRAY_SIZE(*opt->chip_info->scales); i++) {
+ const struct opt3001_scale *scale = &(*opt->chip_info->scales)[i];
/*
- * Combine the integer and micro parts for comparison
- * purposes. Use milli lux precision to avoid 32-bit integer
- * overflows.
+ * Compare the integer and micro parts to determine value scale.
*/
- if ((val * 1000 + val2 / 1000) <=
- (scale->val * 1000 + scale->val2 / 1000)) {
+ if (val < scale->val ||
+ (val == scale->val && val2 <= scale->val2)) {
*exponent = i;
return 0;
}
@@ -174,11 +246,14 @@ static int opt3001_find_scale(const struct opt3001 *opt, int val,
static void opt3001_to_iio_ret(struct opt3001 *opt, u8 exponent,
u16 mantissa, int *val, int *val2)
{
- int lux;
+ int ret;
+ int whole = opt->chip_info->factor_whole;
+ int integer = opt->chip_info->factor_integer;
+ int decimal = opt->chip_info->factor_decimal;
- lux = 10 * (mantissa << exponent);
- *val = lux / 1000;
- *val2 = (lux - (*val * 1000)) * 1000;
+ ret = whole * (mantissa << exponent);
+ *val = ret / integer;
+ *val2 = (ret - (*val * integer)) * decimal;
}
static void opt3001_set_mode(struct opt3001 *opt, u16 *reg, u16 mode)
@@ -225,7 +300,18 @@ static const struct iio_chan_spec opt3001_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(1),
};
-static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2)
+static const struct iio_chan_spec opt3002_channels[] = {
+ {
+ .type = IIO_INTENSITY,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_INT_TIME),
+ .event_spec = opt3001_event_spec,
+ .num_event_specs = ARRAY_SIZE(opt3001_event_spec),
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2)
{
int ret;
u16 mantissa;
@@ -397,14 +483,15 @@ static int opt3001_read_raw(struct iio_dev *iio,
if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
return -EBUSY;
- if (chan->type != IIO_LIGHT)
+ if (chan->type != opt->chip_info->chan_type)
return -EINVAL;
mutex_lock(&opt->lock);
switch (mask) {
+ case IIO_CHAN_INFO_RAW:
case IIO_CHAN_INFO_PROCESSED:
- ret = opt3001_get_lux(opt, val, val2);
+ ret = opt3001_get_processed(opt, val, val2);
break;
case IIO_CHAN_INFO_INT_TIME:
ret = opt3001_get_int_time(opt, val, val2);
@@ -428,7 +515,7 @@ static int opt3001_write_raw(struct iio_dev *iio,
if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
return -EBUSY;
- if (chan->type != IIO_LIGHT)
+ if (chan->type != opt->chip_info->chan_type)
return -EINVAL;
if (mask != IIO_CHAN_INFO_INT_TIME)
@@ -479,6 +566,9 @@ static int opt3001_write_event_value(struct iio_dev *iio,
{
struct opt3001 *opt = iio_priv(iio);
int ret;
+ int whole;
+ int integer;
+ int decimal;
u16 mantissa;
u16 value;
@@ -497,7 +587,12 @@ static int opt3001_write_event_value(struct iio_dev *iio,
goto err;
}
- mantissa = (((val * 1000) + (val2 / 1000)) / 10) >> exponent;
+ whole = opt->chip_info->factor_whole;
+ integer = opt->chip_info->factor_integer;
+ decimal = opt->chip_info->factor_decimal;
+
+ mantissa = (((val * integer) + (val2 / decimal)) / whole) >> exponent;
+
value = (exponent << 12) | mantissa;
switch (dir) {
@@ -539,7 +634,7 @@ static int opt3001_read_event_config(struct iio_dev *iio,
static int opt3001_write_event_config(struct iio_dev *iio,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct opt3001 *opt = iio_priv(iio);
int ret;
@@ -610,7 +705,7 @@ static int opt3001_read_id(struct opt3001 *opt)
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_DEVICE_ID);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
- OPT3001_DEVICE_ID);
+ OPT3001_DEVICE_ID);
return ret;
}
@@ -692,6 +787,7 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
struct opt3001 *opt = iio_priv(iio);
int ret;
bool wake_result_ready_queue = false;
+ enum iio_chan_type chan_type = opt->chip_info->chan_type;
if (!opt->ok_to_ignore_lock)
mutex_lock(&opt->lock);
@@ -707,13 +803,13 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
OPT3001_CONFIGURATION_M_CONTINUOUS) {
if (ret & OPT3001_CONFIGURATION_FH)
iio_push_event(iio,
- IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+ IIO_UNMOD_EVENT_CODE(chan_type, 0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
iio_get_time_ns(iio));
if (ret & OPT3001_CONFIGURATION_FL)
iio_push_event(iio,
- IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+ IIO_UNMOD_EVENT_CODE(chan_type, 0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
iio_get_time_ns(iio));
@@ -755,22 +851,25 @@ static int opt3001_probe(struct i2c_client *client)
opt = iio_priv(iio);
opt->client = client;
opt->dev = dev;
+ opt->chip_info = i2c_get_match_data(client);
mutex_init(&opt->lock);
init_waitqueue_head(&opt->result_ready_queue);
i2c_set_clientdata(client, iio);
- ret = opt3001_read_id(opt);
- if (ret)
- return ret;
+ if (opt->chip_info->has_id) {
+ ret = opt3001_read_id(opt);
+ if (ret)
+ return ret;
+ }
ret = opt3001_configure(opt);
if (ret)
return ret;
iio->name = client->name;
- iio->channels = opt3001_channels;
- iio->num_channels = ARRAY_SIZE(opt3001_channels);
+ iio->channels = *opt->chip_info->channels;
+ iio->num_channels = opt->chip_info->num_channels;
iio->modes = INDIO_DIRECT_MODE;
iio->info = &opt3001_info;
@@ -825,14 +924,38 @@ static void opt3001_remove(struct i2c_client *client)
}
}
+static const struct opt3001_chip_info opt3001_chip_information = {
+ .channels = &opt3001_channels,
+ .chan_type = IIO_LIGHT,
+ .num_channels = ARRAY_SIZE(opt3001_channels),
+ .scales = &opt3001_scales,
+ .factor_whole = 10,
+ .factor_integer = 1000,
+ .factor_decimal = 1000,
+ .has_id = true,
+};
+
+static const struct opt3001_chip_info opt3002_chip_information = {
+ .channels = &opt3002_channels,
+ .chan_type = IIO_INTENSITY,
+ .num_channels = ARRAY_SIZE(opt3002_channels),
+ .scales = &opt3002_scales,
+ .factor_whole = 12,
+ .factor_integer = 10,
+ .factor_decimal = 100000,
+ .has_id = false,
+};
+
static const struct i2c_device_id opt3001_id[] = {
- { "opt3001" },
+ { "opt3001", (kernel_ulong_t)&opt3001_chip_information },
+ { "opt3002", (kernel_ulong_t)&opt3002_chip_information },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(i2c, opt3001_id);
static const struct of_device_id opt3001_of_match[] = {
- { .compatible = "ti,opt3001" },
+ { .compatible = "ti,opt3001", .data = &opt3001_chip_information },
+ { .compatible = "ti,opt3002", .data = &opt3002_chip_information },
{ }
};
MODULE_DEVICE_TABLE(of, opt3001_of_match);
diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c
index 78c08e0bd077..56f5fbbf79ac 100644
--- a/drivers/iio/light/rpr0521.c
+++ b/drivers/iio/light/rpr0521.c
@@ -438,18 +438,6 @@ static irqreturn_t rpr0521_drdy_irq_thread(int irq, void *private)
return IRQ_NONE;
}
-static irqreturn_t rpr0521_trigger_consumer_store_time(int irq, void *p)
-{
- struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->indio_dev;
-
- /* Other trigger polls store time here. */
- if (!iio_trigger_using_own(indio_dev))
- pf->timestamp = iio_get_time_ns(indio_dev);
-
- return IRQ_WAKE_THREAD;
-}
-
static irqreturn_t rpr0521_trigger_consumer_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
@@ -1016,7 +1004,7 @@ static int rpr0521_probe(struct i2c_client *client)
/* Trigger consumer setup */
ret = devm_iio_triggered_buffer_setup(indio_dev->dev.parent,
indio_dev,
- rpr0521_trigger_consumer_store_time,
+ iio_pollfunc_store_time,
rpr0521_trigger_consumer_handler,
&rpr0521_buffer_setup_ops);
if (ret < 0) {
diff --git a/drivers/iio/light/st_uvis25_core.c b/drivers/iio/light/st_uvis25_core.c
index fba3997574bb..f1fc8cb6f69a 100644
--- a/drivers/iio/light/st_uvis25_core.c
+++ b/drivers/iio/light/st_uvis25_core.c
@@ -174,8 +174,7 @@ static int st_uvis25_allocate_trigger(struct iio_dev *iio_dev)
unsigned long irq_type;
int err;
- irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
-
+ irq_type = irq_get_trigger_type(hw->irq);
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c
index ed20b6714546..b81cc44db43c 100644
--- a/drivers/iio/light/stk3310.c
+++ b/drivers/iio/light/stk3310.c
@@ -324,15 +324,12 @@ static int stk3310_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
int ret;
struct stk3310_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
- if (state < 0 || state > 7)
- return -EINVAL;
-
/* Set INT_PS value */
mutex_lock(&data->lock);
ret = regmap_field_write(data->reg_int_ps, state);
diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c
index 04452b4664f3..4186aac04902 100644
--- a/drivers/iio/light/tcs3472.c
+++ b/drivers/iio/light/tcs3472.c
@@ -327,7 +327,7 @@ static int tcs3472_read_event_config(struct iio_dev *indio_dev,
static int tcs3472_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct tcs3472_data *data = iio_priv(indio_dev);
int ret = 0;
diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c
index 1a6f514bced6..f1fe7640fce6 100644
--- a/drivers/iio/light/tsl2563.c
+++ b/drivers/iio/light/tsl2563.c
@@ -630,7 +630,7 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private)
static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct tsl2563_chip *chip = iio_priv(indio_dev);
int ret = 0;
diff --git a/drivers/iio/light/tsl2591.c b/drivers/iio/light/tsl2591.c
index 850c2465992f..b81ca6f73f92 100644
--- a/drivers/iio/light/tsl2591.c
+++ b/drivers/iio/light/tsl2591.c
@@ -985,7 +985,7 @@ static int tsl2591_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct tsl2591_chip *chip = iio_priv(indio_dev);
struct i2c_client *client = chip->client;
diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c
index cab468a82b61..349afdcbe30d 100644
--- a/drivers/iio/light/tsl2772.c
+++ b/drivers/iio/light/tsl2772.c
@@ -1081,14 +1081,14 @@ static int tsl2772_write_interrupt_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int val)
+ bool val)
{
struct tsl2772_chip *chip = iio_priv(indio_dev);
if (chan->type == IIO_INTENSITY)
- chip->settings.als_interrupt_en = val ? true : false;
+ chip->settings.als_interrupt_en = val;
else
- chip->settings.prox_interrupt_en = val ? true : false;
+ chip->settings.prox_interrupt_en = val;
return tsl2772_invoke_change(indio_dev);
}
diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c
index de6967ac3b0b..c83114aed6b2 100644
--- a/drivers/iio/light/us5182d.c
+++ b/drivers/iio/light/us5182d.c
@@ -627,7 +627,7 @@ static int us5182d_read_event_config(struct iio_dev *indio_dev,
static int us5182d_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct us5182d_data *data = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 4e3641ff2ed4..e19199b17f2e 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -1456,7 +1456,7 @@ static int vcnl4010_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
switch (chan->type) {
case IIO_PROXIMITY:
@@ -1501,7 +1501,8 @@ static int vcnl4040_read_event_config(struct iio_dev *indio_dev,
static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
int ret = -EINVAL;
u16 val, mask;
diff --git a/drivers/iio/light/veml3235.c b/drivers/iio/light/veml3235.c
new file mode 100644
index 000000000000..66361c3012a3
--- /dev/null
+++ b/drivers/iio/light/veml3235.c
@@ -0,0 +1,495 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * VEML3235 Ambient Light Sensor
+ *
+ * Copyright (c) 2024, Javier Carrasco <javier.carrasco.cruz@gmail.com>
+ *
+ * Datasheet: https://www.vishay.com/docs/80131/veml3235.pdf
+ * Appnote-80222: https://www.vishay.com/docs/80222/designingveml3235.pdf
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define VEML3235_REG_CONF 0x00
+#define VEML3235_REG_WH_DATA 0x04
+#define VEML3235_REG_ALS_DATA 0x05
+#define VEML3235_REG_ID 0x09
+
+#define VEML3235_CONF_SD BIT(0)
+#define VEML3235_CONF_SD0 BIT(15)
+
+struct veml3235_rf {
+ struct regmap_field *it;
+ struct regmap_field *gain;
+ struct regmap_field *id;
+};
+
+struct veml3235_data {
+ struct i2c_client *client;
+ struct device *dev;
+ struct regmap *regmap;
+ struct veml3235_rf rf;
+};
+
+static const int veml3235_it_times[][2] = {
+ { 0, 50000 },
+ { 0, 100000 },
+ { 0, 200000 },
+ { 0, 400000 },
+ { 0, 800000 },
+};
+
+static const int veml3235_scale_vals[] = { 1, 2, 4, 8 };
+
+static int veml3235_power_on(struct veml3235_data *data)
+{
+ int ret;
+
+ ret = regmap_clear_bits(data->regmap, VEML3235_REG_CONF,
+ VEML3235_CONF_SD | VEML3235_CONF_SD0);
+ if (ret)
+ return ret;
+
+ /* Wait 4 ms to let processor & oscillator start correctly */
+ fsleep(4000);
+
+ return 0;
+}
+
+static int veml3235_shut_down(struct veml3235_data *data)
+{
+ return regmap_set_bits(data->regmap, VEML3235_REG_CONF,
+ VEML3235_CONF_SD | VEML3235_CONF_SD0);
+}
+
+static void veml3235_shut_down_action(void *data)
+{
+ veml3235_shut_down(data);
+}
+
+enum veml3235_chan {
+ CH_ALS,
+ CH_WHITE,
+};
+
+static const struct iio_chan_spec veml3235_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .channel = CH_ALS,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+ {
+ .type = IIO_INTENSITY,
+ .channel = CH_WHITE,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+};
+
+static const struct regmap_config veml3235_regmap_config = {
+ .name = "veml3235_regmap",
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = VEML3235_REG_ID,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE,
+};
+
+static int veml3235_get_it(struct veml3235_data *data, int *val, int *val2)
+{
+ int ret, reg;
+
+ ret = regmap_field_read(data->rf.it, &reg);
+ if (ret)
+ return ret;
+
+ switch (reg) {
+ case 0:
+ *val2 = 50000;
+ break;
+ case 1:
+ *val2 = 100000;
+ break;
+ case 2:
+ *val2 = 200000;
+ break;
+ case 3:
+ *val2 = 400000;
+ break;
+ case 4:
+ *val2 = 800000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *val = 0;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int veml3235_set_it(struct iio_dev *indio_dev, int val, int val2)
+{
+ struct veml3235_data *data = iio_priv(indio_dev);
+ int ret, new_it;
+
+ if (val)
+ return -EINVAL;
+
+ switch (val2) {
+ case 50000:
+ new_it = 0x00;
+ break;
+ case 100000:
+ new_it = 0x01;
+ break;
+ case 200000:
+ new_it = 0x02;
+ break;
+ case 400000:
+ new_it = 0x03;
+ break;
+ case 800000:
+ new_it = 0x04;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_field_write(data->rf.it, new_it);
+ if (ret) {
+ dev_err(data->dev,
+ "failed to update integration time: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int veml3235_set_gain(struct iio_dev *indio_dev, int val, int val2)
+{
+ struct veml3235_data *data = iio_priv(indio_dev);
+ int ret, new_gain;
+
+ if (val2 != 0)
+ return -EINVAL;
+
+ switch (val) {
+ case 1:
+ new_gain = 0x00;
+ break;
+ case 2:
+ new_gain = 0x01;
+ break;
+ case 4:
+ new_gain = 0x03;
+ break;
+ case 8:
+ new_gain = 0x07;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_field_write(data->rf.gain, new_gain);
+ if (ret) {
+ dev_err(data->dev, "failed to set gain: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int veml3235_get_gain(struct veml3235_data *data, int *val)
+{
+ int ret, reg;
+
+ ret = regmap_field_read(data->rf.gain, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to read gain %d\n", ret);
+ return ret;
+ }
+
+ switch (reg & 0x03) {
+ case 0:
+ *val = 1;
+ break;
+ case 1:
+ *val = 2;
+ break;
+ case 3:
+ *val = 4;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Double gain */
+ if (reg & 0x04)
+ *val *= 2;
+
+ return IIO_VAL_INT;
+}
+
+static int veml3235_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct veml3235_data *data = iio_priv(indio_dev);
+ struct regmap *regmap = data->regmap;
+ int ret, reg;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_LIGHT:
+ ret = regmap_read(regmap, VEML3235_REG_ALS_DATA, &reg);
+ if (ret < 0)
+ return ret;
+
+ *val = reg;
+ return IIO_VAL_INT;
+ case IIO_INTENSITY:
+ ret = regmap_read(regmap, VEML3235_REG_WH_DATA, &reg);
+ if (ret < 0)
+ return ret;
+
+ *val = reg;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_INT_TIME:
+ return veml3235_get_it(data, val, val2);
+ case IIO_CHAN_INFO_SCALE:
+ return veml3235_get_gain(data, val);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int veml3235_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ *vals = (int *)&veml3235_it_times;
+ *length = 2 * ARRAY_SIZE(veml3235_it_times);
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SCALE:
+ *vals = (int *)&veml3235_scale_vals;
+ *length = ARRAY_SIZE(veml3235_scale_vals);
+ *type = IIO_VAL_INT;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int veml3235_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ return veml3235_set_it(indio_dev, val, val2);
+ case IIO_CHAN_INFO_SCALE:
+ return veml3235_set_gain(indio_dev, val, val2);
+ }
+
+ return -EINVAL;
+}
+
+static void veml3235_read_id(struct veml3235_data *data)
+{
+ int ret, reg;
+
+ ret = regmap_field_read(data->rf.id, &reg);
+ if (ret) {
+ dev_info(data->dev, "failed to read ID\n");
+ return;
+ }
+
+ if (reg != 0x35)
+ dev_info(data->dev, "Unknown ID %d\n", reg);
+}
+
+static const struct reg_field veml3235_rf_it =
+ REG_FIELD(VEML3235_REG_CONF, 4, 6);
+
+static const struct reg_field veml3235_rf_gain =
+ REG_FIELD(VEML3235_REG_CONF, 11, 13);
+
+static const struct reg_field veml3235_rf_id =
+ REG_FIELD(VEML3235_REG_ID, 0, 7);
+
+static int veml3235_regfield_init(struct veml3235_data *data)
+{
+ struct regmap *regmap = data->regmap;
+ struct device *dev = data->dev;
+ struct regmap_field *rm_field;
+ struct veml3235_rf *rf = &data->rf;
+
+ rm_field = devm_regmap_field_alloc(dev, regmap, veml3235_rf_it);
+ if (IS_ERR(rm_field))
+ return PTR_ERR(rm_field);
+ rf->it = rm_field;
+
+ rm_field = devm_regmap_field_alloc(dev, regmap, veml3235_rf_gain);
+ if (IS_ERR(rm_field))
+ return PTR_ERR(rm_field);
+ rf->gain = rm_field;
+
+ rm_field = devm_regmap_field_alloc(dev, regmap, veml3235_rf_id);
+ if (IS_ERR(rm_field))
+ return PTR_ERR(rm_field);
+ rf->id = rm_field;
+
+ return 0;
+}
+
+static int veml3235_hw_init(struct iio_dev *indio_dev)
+{
+ struct veml3235_data *data = iio_priv(indio_dev);
+ struct device *dev = data->dev;
+ int ret;
+
+ /* Set gain to 1 and integration time to 100 ms */
+ ret = regmap_field_write(data->rf.gain, 0x00);
+ if (ret)
+ return dev_err_probe(data->dev, ret, "failed to set gain\n");
+
+ ret = regmap_field_write(data->rf.it, 0x01);
+ if (ret)
+ return dev_err_probe(data->dev, ret,
+ "failed to set integration time\n");
+
+ ret = veml3235_power_on(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to power on\n");
+
+ return devm_add_action_or_reset(dev, veml3235_shut_down_action, data);
+}
+
+static const struct iio_info veml3235_info = {
+ .read_raw = veml3235_read_raw,
+ .read_avail = veml3235_read_avail,
+ .write_raw = veml3235_write_raw,
+};
+
+static int veml3235_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct veml3235_data *data;
+ struct iio_dev *indio_dev;
+ struct regmap *regmap;
+ int ret;
+
+ regmap = devm_regmap_init_i2c(client, &veml3235_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "failed to setup regmap\n");
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+ data->dev = dev;
+ data->regmap = regmap;
+
+ ret = veml3235_regfield_init(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to init regfield\n");
+
+ ret = devm_regulator_get_enable(dev, "vdd");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable regulator\n");
+
+ indio_dev->name = "veml3235";
+ indio_dev->channels = veml3235_channels;
+ indio_dev->num_channels = ARRAY_SIZE(veml3235_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &veml3235_info;
+
+ veml3235_read_id(data);
+
+ ret = veml3235_hw_init(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static int veml3235_runtime_suspend(struct device *dev)
+{
+ struct veml3235_data *data = iio_priv(dev_get_drvdata(dev));
+ int ret;
+
+ ret = veml3235_shut_down(data);
+ if (ret < 0)
+ dev_err(data->dev, "failed to suspend: %d\n", ret);
+
+ return ret;
+}
+
+static int veml3235_runtime_resume(struct device *dev)
+{
+ struct veml3235_data *data = iio_priv(dev_get_drvdata(dev));
+ int ret;
+
+ ret = veml3235_power_on(data);
+ if (ret < 0)
+ dev_err(data->dev, "failed to resume: %d\n", ret);
+
+ return ret;
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(veml3235_pm_ops, veml3235_runtime_suspend,
+ veml3235_runtime_resume, NULL);
+
+static const struct of_device_id veml3235_of_match[] = {
+ { .compatible = "vishay,veml3235" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, veml3235_of_match);
+
+static const struct i2c_device_id veml3235_id[] = {
+ { "veml3235" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, veml3235_id);
+
+static struct i2c_driver veml3235_driver = {
+ .driver = {
+ .name = "veml3235",
+ .of_match_table = veml3235_of_match,
+ .pm = pm_ptr(&veml3235_pm_ops),
+ },
+ .probe = veml3235_probe,
+ .id_table = veml3235_id,
+};
+module_i2c_driver(veml3235_driver);
+
+MODULE_AUTHOR("Javier Carrasco <javier.carrasco.cruz@gmail.com>");
+MODULE_DESCRIPTION("VEML3235 Ambient Light Sensor");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c
index 621428885455..ccb43dfd5cf7 100644
--- a/drivers/iio/light/veml6030.c
+++ b/drivers/iio/light/veml6030.c
@@ -1,19 +1,30 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * VEML6030 Ambient Light Sensor
+ * VEML6030, VMEL6035 and VEML7700 Ambient Light Sensors
*
* Copyright (c) 2019, Rishi Gupta <gupt21@gmail.com>
*
+ * VEML6030:
* Datasheet: https://www.vishay.com/docs/84366/veml6030.pdf
* Appnote-84367: https://www.vishay.com/docs/84367/designingveml6030.pdf
+ *
+ * VEML6035:
+ * Datasheet: https://www.vishay.com/docs/84889/veml6035.pdf
+ * Appnote-84944: https://www.vishay.com/docs/84944/designingveml6035.pdf
+ *
+ * VEML7700:
+ * Datasheet: https://www.vishay.com/docs/84286/veml7700.pdf
+ * Appnote-84323: https://www.vishay.com/docs/84323/designingveml7700.pdf
*/
+#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
@@ -38,16 +49,35 @@
#define VEML6030_ALS_INT_EN BIT(1)
#define VEML6030_ALS_SD BIT(0)
+#define VEML6035_GAIN_M GENMASK(12, 10)
+#define VEML6035_GAIN BIT(10)
+#define VEML6035_DG BIT(11)
+#define VEML6035_SENS BIT(12)
+#define VEML6035_INT_CHAN BIT(3)
+#define VEML6035_CHAN_EN BIT(2)
+
+struct veml603x_chip {
+ const char *name;
+ const int(*scale_vals)[][2];
+ const int num_scale_vals;
+ const struct iio_chan_spec *channels;
+ const int num_channels;
+ int (*hw_init)(struct iio_dev *indio_dev, struct device *dev);
+ int (*set_info)(struct iio_dev *indio_dev);
+ int (*set_als_gain)(struct iio_dev *indio_dev, int val, int val2);
+ int (*get_als_gain)(struct iio_dev *indio_dev, int *val, int *val2);
+};
+
/*
* The resolution depends on both gain and integration time. The
* cur_resolution stores one of the resolution mentioned in the
* table during startup and gets updated whenever integration time
* or gain is changed.
*
- * Table 'resolution and maximum detection range' in appnote 84367
+ * Table 'resolution and maximum detection range' in the appnotes
* is visualized as a 2D array. The cur_gain stores index of gain
- * in this table (0-3) while the cur_integration_time holds index
- * of integration time (0-5).
+ * in this table (0-3 for VEML6030, 0-5 for VEML6035) while the
+ * cur_integration_time holds index of integration time (0-5).
*/
struct veml6030_data {
struct i2c_client *client;
@@ -55,27 +85,37 @@ struct veml6030_data {
int cur_resolution;
int cur_gain;
int cur_integration_time;
+ const struct veml603x_chip *chip;
};
-/* Integration time available in seconds */
-static IIO_CONST_ATTR(in_illuminance_integration_time_available,
- "0.025 0.05 0.1 0.2 0.4 0.8");
+static const int veml6030_it_times[][2] = {
+ { 0, 25000 },
+ { 0, 50000 },
+ { 0, 100000 },
+ { 0, 200000 },
+ { 0, 400000 },
+ { 0, 800000 },
+};
/*
* Scale is 1/gain. Value 0.125 is ALS gain x (1/8), 0.25 is
- * ALS gain x (1/4), 1.0 = ALS gain x 1 and 2.0 is ALS gain x 2.
+ * ALS gain x (1/4), 0.5 is ALS gain x (1/2), 1.0 is ALS gain x 1,
+ * 2.0 is ALS gain x2, and 4.0 is ALS gain x 4.
*/
-static IIO_CONST_ATTR(in_illuminance_scale_available,
- "0.125 0.25 1.0 2.0");
-
-static struct attribute *veml6030_attributes[] = {
- &iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,
- &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
- NULL
+static const int veml6030_scale_vals[][2] = {
+ { 0, 125000 },
+ { 0, 250000 },
+ { 1, 0 },
+ { 2, 0 },
};
-static const struct attribute_group veml6030_attr_group = {
- .attrs = veml6030_attributes,
+static const int veml6035_scale_vals[][2] = {
+ { 0, 125000 },
+ { 0, 250000 },
+ { 0, 500000 },
+ { 1, 0 },
+ { 2, 0 },
+ { 4, 0 },
};
/*
@@ -143,14 +183,23 @@ static const struct attribute_group veml6030_event_attr_group = {
static int veml6030_als_pwr_on(struct veml6030_data *data)
{
- return regmap_clear_bits(data->regmap, VEML6030_REG_ALS_CONF,
- VEML6030_ALS_SD);
+ int ret;
+
+ ret = regmap_clear_bits(data->regmap, VEML6030_REG_ALS_CONF,
+ VEML6030_ALS_SD);
+ if (ret)
+ return ret;
+
+ /* Wait 4 ms to let processor & oscillator start correctly */
+ fsleep(4000);
+
+ return 0;
}
static int veml6030_als_shut_down(struct veml6030_data *data)
{
- return regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
- VEML6030_ALS_SD, 1);
+ return regmap_set_bits(data->regmap, VEML6030_REG_ALS_CONF,
+ VEML6030_ALS_SD);
}
static void veml6030_als_shut_down_action(void *data)
@@ -189,6 +238,8 @@ static const struct iio_chan_spec veml6030_channels[] = {
BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_INT_TIME) |
BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
.event_spec = veml6030_event_spec,
.num_event_specs = ARRAY_SIZE(veml6030_event_spec),
},
@@ -198,7 +249,34 @@ static const struct iio_chan_spec veml6030_channels[] = {
.modified = 1,
.channel2 = IIO_MOD_LIGHT_BOTH,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_PROCESSED),
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+};
+
+static const struct iio_chan_spec veml7700_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .channel = CH_ALS,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+ {
+ .type = IIO_INTENSITY,
+ .channel = CH_WHITE,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
},
};
@@ -371,6 +449,21 @@ static int veml6030_write_persistence(struct iio_dev *indio_dev,
return ret;
}
+/*
+ * Cache currently set gain & update resolution. For every
+ * increase in the gain to next level, resolution is halved
+ * and vice-versa.
+ */
+static void veml6030_update_gain_res(struct veml6030_data *data, int gain_idx)
+{
+ if (data->cur_gain < gain_idx)
+ data->cur_resolution <<= gain_idx - data->cur_gain;
+ else if (data->cur_gain > gain_idx)
+ data->cur_resolution >>= data->cur_gain - gain_idx;
+
+ data->cur_gain = gain_idx;
+}
+
static int veml6030_set_als_gain(struct iio_dev *indio_dev,
int val, int val2)
{
@@ -401,19 +494,49 @@ static int veml6030_set_als_gain(struct iio_dev *indio_dev,
return ret;
}
- /*
- * Cache currently set gain & update resolution. For every
- * increase in the gain to next level, resolution is halved
- * and vice-versa.
- */
- if (data->cur_gain < gain_idx)
- data->cur_resolution <<= gain_idx - data->cur_gain;
- else if (data->cur_gain > gain_idx)
- data->cur_resolution >>= data->cur_gain - gain_idx;
+ veml6030_update_gain_res(data, gain_idx);
- data->cur_gain = gain_idx;
+ return 0;
+}
- return ret;
+static int veml6035_set_als_gain(struct iio_dev *indio_dev, int val, int val2)
+{
+ int ret, new_gain, gain_idx;
+ struct veml6030_data *data = iio_priv(indio_dev);
+
+ if (val == 0 && val2 == 125000) {
+ new_gain = VEML6035_SENS;
+ gain_idx = 5;
+ } else if (val == 0 && val2 == 250000) {
+ new_gain = VEML6035_SENS | VEML6035_GAIN;
+ gain_idx = 4;
+ } else if (val == 0 && val2 == 500000) {
+ new_gain = VEML6035_SENS | VEML6035_GAIN |
+ VEML6035_DG;
+ gain_idx = 3;
+ } else if (val == 1 && val2 == 0) {
+ new_gain = 0x0000;
+ gain_idx = 2;
+ } else if (val == 2 && val2 == 0) {
+ new_gain = VEML6035_GAIN;
+ gain_idx = 1;
+ } else if (val == 4 && val2 == 0) {
+ new_gain = VEML6035_GAIN | VEML6035_DG;
+ gain_idx = 0;
+ } else {
+ return -EINVAL;
+ }
+
+ ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
+ VEML6035_GAIN_M, new_gain);
+ if (ret) {
+ dev_err(&data->client->dev, "can't set als gain %d\n", ret);
+ return ret;
+ }
+
+ veml6030_update_gain_res(data, gain_idx);
+
+ return 0;
}
static int veml6030_get_als_gain(struct iio_dev *indio_dev,
@@ -453,6 +576,52 @@ static int veml6030_get_als_gain(struct iio_dev *indio_dev,
return IIO_VAL_INT_PLUS_MICRO;
}
+static int veml6035_get_als_gain(struct iio_dev *indio_dev, int *val, int *val2)
+{
+ int ret, reg;
+ struct veml6030_data *data = iio_priv(indio_dev);
+
+ ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
+ if (ret) {
+ dev_err(&data->client->dev,
+ "can't read als conf register %d\n", ret);
+ return ret;
+ }
+
+ switch (FIELD_GET(VEML6035_GAIN_M, reg)) {
+ case 0:
+ *val = 1;
+ *val2 = 0;
+ break;
+ case 1:
+ case 2:
+ *val = 2;
+ *val2 = 0;
+ break;
+ case 3:
+ *val = 4;
+ *val2 = 0;
+ break;
+ case 4:
+ *val = 0;
+ *val2 = 125000;
+ break;
+ case 5:
+ case 6:
+ *val = 0;
+ *val2 = 250000;
+ break;
+ case 7:
+ *val = 0;
+ *val2 = 500000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
static int veml6030_read_thresh(struct iio_dev *indio_dev,
int *val, int *val2, int dir)
{
@@ -533,48 +702,54 @@ static int veml6030_read_raw(struct iio_dev *indio_dev,
dev_err(dev, "can't read white data %d\n", ret);
return ret;
}
- if (mask == IIO_CHAN_INFO_PROCESSED) {
- *val = (reg * data->cur_resolution) / 10000;
- *val2 = (reg * data->cur_resolution) % 10000;
- return IIO_VAL_INT_PLUS_MICRO;
- }
*val = reg;
return IIO_VAL_INT;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_INT_TIME:
- if (chan->type == IIO_LIGHT)
- return veml6030_get_intgrn_tm(indio_dev, val, val2);
- return -EINVAL;
+ return veml6030_get_intgrn_tm(indio_dev, val, val2);
case IIO_CHAN_INFO_SCALE:
- if (chan->type == IIO_LIGHT)
- return veml6030_get_als_gain(indio_dev, val, val2);
- return -EINVAL;
+ return data->chip->get_als_gain(indio_dev, val, val2);
default:
return -EINVAL;
}
}
+static int veml6030_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ struct veml6030_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ *vals = (int *)&veml6030_it_times;
+ *length = 2 * ARRAY_SIZE(veml6030_it_times);
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SCALE:
+ *vals = (int *)*data->chip->scale_vals;
+ *length = 2 * data->chip->num_scale_vals;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ }
+
+ return -EINVAL;
+}
+
static int veml6030_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
+ struct veml6030_data *data = iio_priv(indio_dev);
+
switch (mask) {
case IIO_CHAN_INFO_INT_TIME:
- switch (chan->type) {
- case IIO_LIGHT:
- return veml6030_set_intgrn_tm(indio_dev, val, val2);
- default:
- return -EINVAL;
- }
+ return veml6030_set_intgrn_tm(indio_dev, val, val2);
case IIO_CHAN_INFO_SCALE:
- switch (chan->type) {
- case IIO_LIGHT:
- return veml6030_set_als_gain(indio_dev, val, val2);
- default:
- return -EINVAL;
- }
+ return data->chip->set_als_gain(indio_dev, val, val2);
default:
return -EINVAL;
}
@@ -646,14 +821,11 @@ static int veml6030_read_interrupt_config(struct iio_dev *indio_dev,
*/
static int veml6030_write_interrupt_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
int ret;
struct veml6030_data *data = iio_priv(indio_dev);
- if (state < 0 || state > 1)
- return -EINVAL;
-
ret = veml6030_als_shut_down(data);
if (ret < 0) {
dev_err(&data->client->dev,
@@ -673,19 +845,19 @@ static int veml6030_write_interrupt_config(struct iio_dev *indio_dev,
static const struct iio_info veml6030_info = {
.read_raw = veml6030_read_raw,
+ .read_avail = veml6030_read_avail,
.write_raw = veml6030_write_raw,
.read_event_value = veml6030_read_event_val,
.write_event_value = veml6030_write_event_val,
.read_event_config = veml6030_read_interrupt_config,
.write_event_config = veml6030_write_interrupt_config,
- .attrs = &veml6030_attr_group,
.event_attrs = &veml6030_event_attr_group,
};
static const struct iio_info veml6030_info_no_irq = {
.read_raw = veml6030_read_raw,
+ .read_avail = veml6030_read_avail,
.write_raw = veml6030_write_raw,
- .attrs = &veml6030_attr_group,
};
static irqreturn_t veml6030_event_handler(int irq, void *private)
@@ -717,65 +889,82 @@ static irqreturn_t veml6030_event_handler(int irq, void *private)
return IRQ_HANDLED;
}
+static int veml6030_set_info(struct iio_dev *indio_dev)
+{
+ struct veml6030_data *data = iio_priv(indio_dev);
+ struct i2c_client *client = data->client;
+ int ret;
+
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, veml6030_event_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "irq %d request failed\n",
+ client->irq);
+
+ indio_dev->info = &veml6030_info;
+ } else {
+ indio_dev->info = &veml6030_info_no_irq;
+ }
+
+ return 0;
+}
+
+static int veml7700_set_info(struct iio_dev *indio_dev)
+{
+ indio_dev->info = &veml6030_info_no_irq;
+
+ return 0;
+}
+
/*
* Set ALS gain to 1/8, integration time to 100 ms, PSM to mode 2,
* persistence to 1 x integration time and the threshold
* interrupt disabled by default. First shutdown the sensor,
* update registers and then power on the sensor.
*/
-static int veml6030_hw_init(struct iio_dev *indio_dev)
+static int veml6030_hw_init(struct iio_dev *indio_dev, struct device *dev)
{
int ret, val;
struct veml6030_data *data = iio_priv(indio_dev);
- struct i2c_client *client = data->client;
ret = veml6030_als_shut_down(data);
- if (ret) {
- dev_err(&client->dev, "can't shutdown als %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't shutdown als\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_CONF, 0x1001);
- if (ret) {
- dev_err(&client->dev, "can't setup als configs %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup als configs\n");
ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_PSM,
VEML6030_PSM | VEML6030_PSM_EN, 0x03);
- if (ret) {
- dev_err(&client->dev, "can't setup default PSM %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup default PSM\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, 0xFFFF);
- if (ret) {
- dev_err(&client->dev, "can't setup high threshold %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup high threshold\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, 0x0000);
- if (ret) {
- dev_err(&client->dev, "can't setup low threshold %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup low threshold\n");
ret = veml6030_als_pwr_on(data);
- if (ret) {
- dev_err(&client->dev, "can't poweron als %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't poweron als\n");
- /* Wait 4 ms to let processor & oscillator start correctly */
- usleep_range(4000, 4002);
+ ret = devm_add_action_or_reset(dev, veml6030_als_shut_down_action, data);
+ if (ret < 0)
+ return ret;
/* Clear stale interrupt status bits if any during start */
ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &val);
- if (ret < 0) {
- dev_err(&client->dev,
- "can't clear als interrupt status %d\n", ret);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "can't clear als interrupt status\n");
/* Cache currently active measurement parameters */
data->cur_gain = 3;
@@ -785,6 +974,62 @@ static int veml6030_hw_init(struct iio_dev *indio_dev)
return ret;
}
+/*
+ * Set ALS gain to 1/8, integration time to 100 ms, ALS and WHITE
+ * channel enabled, ALS channel interrupt, PSM enabled,
+ * PSM_WAIT = 0.8 s, persistence to 1 x integration time and the
+ * threshold interrupt disabled by default. First shutdown the sensor,
+ * update registers and then power on the sensor.
+ */
+static int veml6035_hw_init(struct iio_dev *indio_dev, struct device *dev)
+{
+ int ret, val;
+ struct veml6030_data *data = iio_priv(indio_dev);
+
+ ret = veml6030_als_shut_down(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't shutdown als\n");
+
+ ret = regmap_write(data->regmap, VEML6030_REG_ALS_CONF,
+ VEML6035_SENS | VEML6035_CHAN_EN | VEML6030_ALS_SD);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup als configs\n");
+
+ ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_PSM,
+ VEML6030_PSM | VEML6030_PSM_EN, 0x03);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup default PSM\n");
+
+ ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, 0xFFFF);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup high threshold\n");
+
+ ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, 0x0000);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup low threshold\n");
+
+ ret = veml6030_als_pwr_on(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't poweron als\n");
+
+ ret = devm_add_action_or_reset(dev, veml6030_als_shut_down_action, data);
+ if (ret < 0)
+ return ret;
+
+ /* Clear stale interrupt status bits if any during start */
+ ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &val);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "can't clear als interrupt status\n");
+
+ /* Cache currently active measurement parameters */
+ data->cur_gain = 5;
+ data->cur_resolution = 1024;
+ data->cur_integration_time = 3;
+
+ return 0;
+}
+
static int veml6030_probe(struct i2c_client *client)
{
int ret;
@@ -792,16 +1037,14 @@ static int veml6030_probe(struct i2c_client *client)
struct iio_dev *indio_dev;
struct regmap *regmap;
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- dev_err(&client->dev, "i2c adapter doesn't support plain i2c\n");
- return -EOPNOTSUPP;
- }
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return dev_err_probe(&client->dev, -EOPNOTSUPP,
+ "i2c adapter doesn't support plain i2c\n");
regmap = devm_regmap_init_i2c(client, &veml6030_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(&client->dev, "can't setup regmap\n");
- return PTR_ERR(regmap);
- }
+ if (IS_ERR(regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(regmap),
+ "can't setup regmap\n");
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -812,32 +1055,25 @@ static int veml6030_probe(struct i2c_client *client)
data->client = client;
data->regmap = regmap;
- indio_dev->name = "veml6030";
- indio_dev->channels = veml6030_channels;
- indio_dev->num_channels = ARRAY_SIZE(veml6030_channels);
- indio_dev->modes = INDIO_DIRECT_MODE;
+ ret = devm_regulator_get_enable(&client->dev, "vdd");
+ if (ret)
+ return dev_err_probe(&client->dev, ret,
+ "failed to enable regulator\n");
- if (client->irq) {
- ret = devm_request_threaded_irq(&client->dev, client->irq,
- NULL, veml6030_event_handler,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- "veml6030", indio_dev);
- if (ret < 0) {
- dev_err(&client->dev,
- "irq %d request failed\n", client->irq);
- return ret;
- }
- indio_dev->info = &veml6030_info;
- } else {
- indio_dev->info = &veml6030_info_no_irq;
- }
+ data->chip = i2c_get_match_data(client);
+ if (!data->chip)
+ return -EINVAL;
+
+ indio_dev->name = data->chip->name;
+ indio_dev->channels = data->chip->channels;
+ indio_dev->num_channels = data->chip->num_channels;
+ indio_dev->modes = INDIO_DIRECT_MODE;
- ret = veml6030_hw_init(indio_dev);
+ ret = data->chip->set_info(indio_dev);
if (ret < 0)
return ret;
- ret = devm_add_action_or_reset(&client->dev,
- veml6030_als_shut_down_action, data);
+ ret = data->chip->hw_init(indio_dev, &client->dev);
if (ret < 0)
return ret;
@@ -873,14 +1109,63 @@ static int veml6030_runtime_resume(struct device *dev)
static DEFINE_RUNTIME_DEV_PM_OPS(veml6030_pm_ops, veml6030_runtime_suspend,
veml6030_runtime_resume, NULL);
+static const struct veml603x_chip veml6030_chip = {
+ .name = "veml6030",
+ .scale_vals = &veml6030_scale_vals,
+ .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals),
+ .channels = veml6030_channels,
+ .num_channels = ARRAY_SIZE(veml6030_channels),
+ .hw_init = veml6030_hw_init,
+ .set_info = veml6030_set_info,
+ .set_als_gain = veml6030_set_als_gain,
+ .get_als_gain = veml6030_get_als_gain,
+};
+
+static const struct veml603x_chip veml6035_chip = {
+ .name = "veml6035",
+ .scale_vals = &veml6035_scale_vals,
+ .num_scale_vals = ARRAY_SIZE(veml6035_scale_vals),
+ .channels = veml6030_channels,
+ .num_channels = ARRAY_SIZE(veml6030_channels),
+ .hw_init = veml6035_hw_init,
+ .set_info = veml6030_set_info,
+ .set_als_gain = veml6035_set_als_gain,
+ .get_als_gain = veml6035_get_als_gain,
+};
+
+static const struct veml603x_chip veml7700_chip = {
+ .name = "veml7700",
+ .scale_vals = &veml6030_scale_vals,
+ .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals),
+ .channels = veml7700_channels,
+ .num_channels = ARRAY_SIZE(veml7700_channels),
+ .hw_init = veml6030_hw_init,
+ .set_info = veml7700_set_info,
+ .set_als_gain = veml6030_set_als_gain,
+ .get_als_gain = veml6030_get_als_gain,
+};
+
static const struct of_device_id veml6030_of_match[] = {
- { .compatible = "vishay,veml6030" },
+ {
+ .compatible = "vishay,veml6030",
+ .data = &veml6030_chip,
+ },
+ {
+ .compatible = "vishay,veml6035",
+ .data = &veml6035_chip,
+ },
+ {
+ .compatible = "vishay,veml7700",
+ .data = &veml7700_chip,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, veml6030_of_match);
static const struct i2c_device_id veml6030_id[] = {
- { "veml6030" },
+ { "veml6030", (kernel_ulong_t)&veml6030_chip},
+ { "veml6035", (kernel_ulong_t)&veml6035_chip},
+ { "veml7700", (kernel_ulong_t)&veml7700_chip},
{ }
};
MODULE_DEVICE_TABLE(i2c, veml6030_id);
diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c
index f8321d346d77..6d4483c85f30 100644
--- a/drivers/iio/light/veml6070.c
+++ b/drivers/iio/light/veml6070.c
@@ -6,14 +6,16 @@
*
* IIO driver for VEML6070 (7-bit I2C slave addresses 0x38 and 0x39)
*
- * TODO: integration time, ACK signal
+ * TODO: ACK signal
*/
+#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/delay.h>
+#include <linux/units.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -28,50 +30,113 @@
#define VEML6070_COMMAND_RSRVD BIT(1) /* reserved, set to 1 */
#define VEML6070_COMMAND_SD BIT(0) /* shutdown mode when set */
-#define VEML6070_IT_10 0x04 /* integration time 1x */
+#define VEML6070_IT_05 0x00
+#define VEML6070_IT_10 0x01
+#define VEML6070_IT_20 0x02
+#define VEML6070_IT_40 0x03
+
+#define VEML6070_MIN_RSET_KOHM 75
+#define VEML6070_MIN_IT_US 15625 /* Rset = 75 kohm, IT = 1/2 */
struct veml6070_data {
struct i2c_client *client1;
struct i2c_client *client2;
u8 config;
struct mutex lock;
+ u32 rset;
+ int it[4][2];
};
+static int veml6070_calc_it(struct device *dev, struct veml6070_data *data)
+{
+ int i, tmp_it;
+
+ data->rset = 270000;
+ device_property_read_u32(dev, "vishay,rset-ohms", &data->rset);
+
+ if (data->rset < 75000 || data->rset > 1200000)
+ return dev_err_probe(dev, -EINVAL, "Rset out of range\n");
+
+ /*
+ * convert to kohm to avoid overflows and work with the same units as
+ * in the datasheet and simplify UVI operations.
+ */
+ data->rset /= KILO;
+
+ tmp_it = VEML6070_MIN_IT_US * data->rset / VEML6070_MIN_RSET_KOHM;
+ for (i = 0; i < ARRAY_SIZE(data->it); i++) {
+ data->it[i][0] = (tmp_it << i) / MICRO;
+ data->it[i][1] = (tmp_it << i) % MICRO;
+ }
+
+ return 0;
+}
+
+static int veml6070_get_it(struct veml6070_data *data, int *val, int *val2)
+{
+ int it_idx = FIELD_GET(VEML6070_COMMAND_IT, data->config);
+
+ *val = data->it[it_idx][0];
+ *val2 = data->it[it_idx][1];
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int veml6070_set_it(struct veml6070_data *data, int val, int val2)
+{
+ int it_idx;
+
+ for (it_idx = 0; it_idx < ARRAY_SIZE(data->it); it_idx++) {
+ if (data->it[it_idx][0] == val && data->it[it_idx][1] == val2)
+ break;
+ }
+
+ if (it_idx >= ARRAY_SIZE(data->it))
+ return -EINVAL;
+
+ data->config = (data->config & ~VEML6070_COMMAND_IT) |
+ FIELD_PREP(VEML6070_COMMAND_IT, it_idx);
+
+ return i2c_smbus_write_byte(data->client1, data->config);
+}
+
static int veml6070_read(struct veml6070_data *data)
{
- int ret;
+ int ret, it_ms, val, val2;
u8 msb, lsb;
- mutex_lock(&data->lock);
+ guard(mutex)(&data->lock);
/* disable shutdown */
ret = i2c_smbus_write_byte(data->client1,
data->config & ~VEML6070_COMMAND_SD);
if (ret < 0)
- goto out;
+ return ret;
- msleep(125 + 10); /* measurement takes up to 125 ms for IT 1x */
+ veml6070_get_it(data, &val, &val2);
+ it_ms = val * MILLI + val2 / (MICRO / MILLI);
+ msleep(it_ms + 10);
ret = i2c_smbus_read_byte(data->client2); /* read MSB, address 0x39 */
if (ret < 0)
- goto out;
+ return ret;
+
msb = ret;
ret = i2c_smbus_read_byte(data->client1); /* read LSB, address 0x38 */
if (ret < 0)
- goto out;
+ return ret;
+
lsb = ret;
/* shutdown again */
ret = i2c_smbus_write_byte(data->client1, data->config);
if (ret < 0)
- goto out;
+ return ret;
ret = (msb << 8) | lsb;
-out:
- mutex_unlock(&data->lock);
- return ret;
+ return 0;
}
static const struct iio_chan_spec veml6070_channels[] = {
@@ -80,26 +145,37 @@ static const struct iio_chan_spec veml6070_channels[] = {
.modified = 1,
.channel2 = IIO_MOD_LIGHT_UV,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
},
{
.type = IIO_UVINDEX,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
}
};
-static int veml6070_to_uv_index(unsigned val)
+static int veml6070_to_uv_index(struct veml6070_data *data, unsigned int val)
{
/*
* conversion of raw UV intensity values to UV index depends on
* integration time (IT) and value of the resistor connected to
- * the RSET pin (default: 270 KOhm)
+ * the RSET pin.
*/
- unsigned uvi[11] = {
+ unsigned int uvi[11] = {
187, 373, 560, /* low */
746, 933, 1120, /* moderate */
1308, 1494, /* high */
1681, 1868, 2054}; /* very high */
- int i;
+ int i, it_idx;
+
+ it_idx = FIELD_GET(VEML6070_COMMAND_IT, data->config);
+
+ if (!it_idx)
+ val = (val * 270 / data->rset) << 1;
+ else
+ val = (val * 270 / data->rset) >> (it_idx - 1);
for (i = 0; i < ARRAY_SIZE(uvi); i++)
if (val <= uvi[i])
@@ -122,10 +198,44 @@ static int veml6070_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
if (mask == IIO_CHAN_INFO_PROCESSED)
- *val = veml6070_to_uv_index(ret);
+ *val = veml6070_to_uv_index(data, ret);
else
*val = ret;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_INT_TIME:
+ return veml6070_get_it(data, val, val2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int veml6070_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ struct veml6070_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ *vals = (int *)data->it;
+ *length = 2 * ARRAY_SIZE(data->it);
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int veml6070_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct veml6070_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ return veml6070_set_it(data, val, val2);
default:
return -EINVAL;
}
@@ -133,8 +243,17 @@ static int veml6070_read_raw(struct iio_dev *indio_dev,
static const struct iio_info veml6070_info = {
.read_raw = veml6070_read_raw,
+ .read_avail = veml6070_read_avail,
+ .write_raw = veml6070_write_raw,
};
+static void veml6070_i2c_unreg(void *p)
+{
+ struct veml6070_data *data = p;
+
+ i2c_unregister_device(data->client2);
+}
+
static int veml6070_probe(struct i2c_client *client)
{
struct veml6070_data *data;
@@ -156,36 +275,30 @@ static int veml6070_probe(struct i2c_client *client)
indio_dev->name = VEML6070_DRV_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
- data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB);
- if (IS_ERR(data->client2)) {
- dev_err(&client->dev, "i2c device for second chip address failed\n");
- return PTR_ERR(data->client2);
- }
-
- data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD |
- VEML6070_COMMAND_SD;
- ret = i2c_smbus_write_byte(data->client1, data->config);
+ ret = veml6070_calc_it(&client->dev, data);
if (ret < 0)
- goto fail;
+ return ret;
- ret = iio_device_register(indio_dev);
+ ret = devm_regulator_get_enable(&client->dev, "vdd");
if (ret < 0)
- goto fail;
+ return ret;
- return ret;
+ data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB);
+ if (IS_ERR(data->client2))
+ return dev_err_probe(&client->dev, PTR_ERR(data->client2),
+ "i2c device for second chip address failed\n");
-fail:
- i2c_unregister_device(data->client2);
- return ret;
-}
+ data->config = FIELD_PREP(VEML6070_COMMAND_IT, VEML6070_IT_10) |
+ VEML6070_COMMAND_RSRVD | VEML6070_COMMAND_SD;
+ ret = i2c_smbus_write_byte(data->client1, data->config);
+ if (ret < 0)
+ return ret;
-static void veml6070_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct veml6070_data *data = iio_priv(indio_dev);
+ ret = devm_add_action_or_reset(&client->dev, veml6070_i2c_unreg, data);
+ if (ret < 0)
+ return ret;
- iio_device_unregister(indio_dev);
- i2c_unregister_device(data->client2);
+ return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id veml6070_id[] = {
@@ -194,12 +307,18 @@ static const struct i2c_device_id veml6070_id[] = {
};
MODULE_DEVICE_TABLE(i2c, veml6070_id);
+static const struct of_device_id veml6070_of_match[] = {
+ { .compatible = "vishay,veml6070" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, veml6070_of_match);
+
static struct i2c_driver veml6070_driver = {
.driver = {
.name = VEML6070_DRV_NAME,
+ .of_match_table = veml6070_of_match,
},
.probe = veml6070_probe,
- .remove = veml6070_remove,
.id_table = veml6070_id,
};
diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c
index a1b2b3c0b4c8..6e2183a4243e 100644
--- a/drivers/iio/light/vl6180.c
+++ b/drivers/iio/light/vl6180.c
@@ -25,6 +25,10 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#define VL6180_DRV_NAME "vl6180"
@@ -38,7 +42,9 @@
#define VL6180_OUT_OF_RESET 0x016
#define VL6180_HOLD 0x017
#define VL6180_RANGE_START 0x018
+#define VL6180_RANGE_INTER_MEAS_TIME 0x01b
#define VL6180_ALS_START 0x038
+#define VL6180_ALS_INTER_MEAS_TIME 0x03e
#define VL6180_ALS_GAIN 0x03f
#define VL6180_ALS_IT 0x040
@@ -84,8 +90,17 @@
struct vl6180_data {
struct i2c_client *client;
struct mutex lock;
+ struct completion completion;
+ struct iio_trigger *trig;
unsigned int als_gain_milli;
unsigned int als_it_ms;
+ unsigned int als_meas_rate;
+ unsigned int range_meas_rate;
+
+ struct {
+ u16 chan[2];
+ aligned_s64 timestamp;
+ } scan;
};
enum { VL6180_ALS, VL6180_RANGE, VL6180_PROX };
@@ -207,29 +222,40 @@ static int vl6180_write_word(struct i2c_client *client, u16 cmd, u16 val)
static int vl6180_measure(struct vl6180_data *data, int addr)
{
struct i2c_client *client = data->client;
+ unsigned long time_left;
int tries = 20, ret;
u16 value;
mutex_lock(&data->lock);
+ reinit_completion(&data->completion);
+
/* Start single shot measurement */
ret = vl6180_write_byte(client,
vl6180_chan_regs_table[addr].start_reg, VL6180_STARTSTOP);
if (ret < 0)
goto fail;
- while (tries--) {
- ret = vl6180_read_byte(client, VL6180_INTR_STATUS);
- if (ret < 0)
+ if (client->irq) {
+ time_left = wait_for_completion_timeout(&data->completion, HZ / 10);
+ if (time_left == 0) {
+ ret = -ETIMEDOUT;
goto fail;
+ }
+ } else {
+ while (tries--) {
+ ret = vl6180_read_byte(client, VL6180_INTR_STATUS);
+ if (ret < 0)
+ goto fail;
+
+ if (ret & vl6180_chan_regs_table[addr].drdy_mask)
+ break;
+ msleep(20);
+ }
- if (ret & vl6180_chan_regs_table[addr].drdy_mask)
- break;
- msleep(20);
- }
-
- if (tries < 0) {
- ret = -EIO;
- goto fail;
+ if (tries < 0) {
+ ret = -EIO;
+ goto fail;
+ }
}
/* Read result value from appropriate registers */
@@ -258,20 +284,41 @@ static const struct iio_chan_spec vl6180_channels[] = {
{
.type = IIO_LIGHT,
.address = VL6180_ALS,
+ .scan_index = VL6180_ALS,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ },
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_INT_TIME) |
BIT(IIO_CHAN_INFO_SCALE) |
- BIT(IIO_CHAN_INFO_HARDWAREGAIN),
+ BIT(IIO_CHAN_INFO_HARDWAREGAIN) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
}, {
.type = IIO_DISTANCE,
.address = VL6180_RANGE,
+ .scan_index = VL6180_RANGE,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 8,
+ .storagebits = 8,
+ },
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_SCALE),
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
}, {
.type = IIO_PROXIMITY,
.address = VL6180_PROX,
+ .scan_index = VL6180_PROX,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ },
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
- }
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(3),
};
/*
@@ -333,6 +380,18 @@ static int vl6180_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_FRACTIONAL;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ switch (chan->type) {
+ case IIO_DISTANCE:
+ *val = data->range_meas_rate;
+ return IIO_VAL_INT;
+ case IIO_LIGHT:
+ *val = data->als_meas_rate;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+
default:
return -EINVAL;
}
@@ -412,11 +471,23 @@ fail:
return ret;
}
+static int vl6180_meas_reg_val_from_mhz(unsigned int mhz)
+{
+ unsigned int period = DIV_ROUND_CLOSEST(1000 * 1000, mhz);
+ unsigned int reg_val = 0;
+
+ if (period > 10)
+ reg_val = period < 2550 ? (DIV_ROUND_CLOSEST(period, 10) - 1) : 254;
+
+ return reg_val;
+}
+
static int vl6180_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct vl6180_data *data = iio_priv(indio_dev);
+ unsigned int reg_val;
switch (mask) {
case IIO_CHAN_INFO_INT_TIME:
@@ -427,18 +498,126 @@ static int vl6180_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
return vl6180_set_als_gain(data, val, val2);
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ {
+ guard(mutex)(&data->lock);
+ switch (chan->type) {
+ case IIO_DISTANCE:
+ data->range_meas_rate = val;
+ reg_val = vl6180_meas_reg_val_from_mhz(val);
+ return vl6180_write_byte(data->client,
+ VL6180_RANGE_INTER_MEAS_TIME, reg_val);
+
+ case IIO_LIGHT:
+ data->als_meas_rate = val;
+ reg_val = vl6180_meas_reg_val_from_mhz(val);
+ return vl6180_write_byte(data->client,
+ VL6180_ALS_INTER_MEAS_TIME, reg_val);
+
+ default:
+ return -EINVAL;
+ }
+ }
+
default:
return -EINVAL;
}
}
+static irqreturn_t vl6180_threaded_irq(int irq, void *priv)
+{
+ struct iio_dev *indio_dev = priv;
+ struct vl6180_data *data = iio_priv(indio_dev);
+
+ if (iio_buffer_enabled(indio_dev))
+ iio_trigger_poll_nested(indio_dev->trig);
+ else
+ complete(&data->completion);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t vl6180_trigger_handler(int irq, void *priv)
+{
+ struct iio_poll_func *pf = priv;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct vl6180_data *data = iio_priv(indio_dev);
+ s64 time_ns = iio_get_time_ns(indio_dev);
+ int ret, bit, i = 0;
+
+ iio_for_each_active_channel(indio_dev, bit) {
+ if (vl6180_chan_regs_table[bit].word)
+ ret = vl6180_read_word(data->client,
+ vl6180_chan_regs_table[bit].value_reg);
+ else
+ ret = vl6180_read_byte(data->client,
+ vl6180_chan_regs_table[bit].value_reg);
+
+ if (ret < 0) {
+ dev_err(&data->client->dev,
+ "failed to read from value regs: %d\n", ret);
+ return IRQ_HANDLED;
+ }
+
+ data->scan.chan[i++] = ret;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, time_ns);
+ iio_trigger_notify_done(indio_dev->trig);
+
+ /* Clear the interrupt flag after data read */
+ ret = vl6180_write_byte(data->client, VL6180_INTR_CLEAR,
+ VL6180_CLEAR_ERROR | VL6180_CLEAR_ALS | VL6180_CLEAR_RANGE);
+ if (ret < 0)
+ dev_err(&data->client->dev, "failed to clear irq: %d\n", ret);
+
+ return IRQ_HANDLED;
+}
+
static const struct iio_info vl6180_info = {
.read_raw = vl6180_read_raw,
.write_raw = vl6180_write_raw,
.attrs = &vl6180_attribute_group,
+ .validate_trigger = iio_validate_own_trigger,
+};
+
+static int vl6180_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct vl6180_data *data = iio_priv(indio_dev);
+ int bit;
+
+ iio_for_each_active_channel(indio_dev, bit)
+ return vl6180_write_byte(data->client,
+ vl6180_chan_regs_table[bit].start_reg,
+ VL6180_MODE_CONT | VL6180_STARTSTOP);
+
+ return -EINVAL;
+}
+
+static int vl6180_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct vl6180_data *data = iio_priv(indio_dev);
+ int bit;
+
+ iio_for_each_active_channel(indio_dev, bit)
+ return vl6180_write_byte(data->client,
+ vl6180_chan_regs_table[bit].start_reg,
+ VL6180_STARTSTOP);
+
+ return -EINVAL;
+}
+
+static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
+ .postenable = &vl6180_buffer_postenable,
+ .postdisable = &vl6180_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops vl6180_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
};
-static int vl6180_init(struct vl6180_data *data)
+static int vl6180_init(struct vl6180_data *data, struct iio_dev *indio_dev)
{
struct i2c_client *client = data->client;
int ret;
@@ -473,6 +652,26 @@ static int vl6180_init(struct vl6180_data *data)
if (ret < 0)
return ret;
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
+ &vl6180_trigger_handler,
+ &iio_triggered_buffer_setup_ops);
+ if (ret)
+ return ret;
+
+ /* Default Range inter-measurement time: 50ms or 20000 mHz */
+ ret = vl6180_write_byte(client, VL6180_RANGE_INTER_MEAS_TIME,
+ vl6180_meas_reg_val_from_mhz(20000));
+ if (ret < 0)
+ return ret;
+ data->range_meas_rate = 20000;
+
+ /* Default ALS inter-measurement time: 10ms or 100000 mHz */
+ ret = vl6180_write_byte(client, VL6180_ALS_INTER_MEAS_TIME,
+ vl6180_meas_reg_val_from_mhz(100000));
+ if (ret < 0)
+ return ret;
+ data->als_meas_rate = 100000;
+
/* ALS integration time: 100ms */
data->als_it_ms = 100;
ret = vl6180_write_word(client, VL6180_ALS_IT, VL6180_ALS_IT_100);
@@ -513,10 +712,34 @@ static int vl6180_probe(struct i2c_client *client)
indio_dev->name = VL6180_DRV_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
- ret = vl6180_init(data);
+ ret = vl6180_init(data, indio_dev);
if (ret < 0)
return ret;
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, vl6180_threaded_irq,
+ IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret)
+ return dev_err_probe(&client->dev, ret, "devm_request_irq error \n");
+
+ init_completion(&data->completion);
+
+ data->trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
+ indio_dev->name, iio_device_id(indio_dev));
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->ops = &vl6180_trigger_ops;
+ iio_trigger_set_drvdata(data->trig, indio_dev);
+ ret = devm_iio_trigger_register(&client->dev, data->trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(data->trig);
+ }
+
return devm_iio_device_register(&client->dev, indio_dev);
}
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index f69ac75500f9..7177cd1d67cb 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -54,6 +54,19 @@ config AK09911
help
Deprecated: AK09911 is now supported by AK8975 driver.
+config ALS31300
+ tristate "Allegro MicroSystems ALS31300 3-D Linear Hall Effect Sensor"
+ depends on I2C
+ select REGMAP_I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for the Allegro MicroSystems
+ ALS31300 Hall Effect Sensor through its I2C interface.
+
+ To compile this driver as a module, choose M here: the
+ module will be called als31300.
+
config BMC150_MAGN
tristate
select IIO_BUFFER
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
index ec5c46fbf999..3e4c2ecd9adf 100644
--- a/drivers/iio/magnetometer/Makefile
+++ b/drivers/iio/magnetometer/Makefile
@@ -7,6 +7,7 @@
obj-$(CONFIG_AF8133J) += af8133j.o
obj-$(CONFIG_AK8974) += ak8974.o
obj-$(CONFIG_AK8975) += ak8975.o
+obj-$(CONFIG_ALS31300) += als31300.o
obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o
obj-$(CONFIG_BMC150_MAGN_I2C) += bmc150_magn_i2c.o
obj-$(CONFIG_BMC150_MAGN_SPI) += bmc150_magn_spi.o
diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c
index 961b1e0bfb13..8306a18706ac 100644
--- a/drivers/iio/magnetometer/ak8974.c
+++ b/drivers/iio/magnetometer/ak8974.c
@@ -910,7 +910,7 @@ static int ak8974_probe(struct i2c_client *i2c)
/* If we have a valid DRDY IRQ, make use of it */
if (irq > 0) {
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
+ irq_trig = irq_get_trigger_type(irq);
if (irq_trig == IRQF_TRIGGER_RISING) {
dev_info(&i2c->dev, "enable rising edge DRDY IRQ\n");
} else if (irq_trig == IRQF_TRIGGER_FALLING) {
diff --git a/drivers/iio/magnetometer/als31300.c b/drivers/iio/magnetometer/als31300.c
new file mode 100644
index 000000000000..87b60c4e81fa
--- /dev/null
+++ b/drivers/iio/magnetometer/als31300.c
@@ -0,0 +1,494 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for the Allegro MicroSystems ALS31300 3-D Linear Hall Effect Sensor
+ *
+ * Copyright (c) 2024 Linaro Limited
+ */
+
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/types.h>
+#include <linux/units.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+/*
+ * The Allegro MicroSystems ALS31300 has an EEPROM space to configure how
+ * the device works and how the interrupt line behaves.
+ * Only the default setup with external trigger is supported.
+ *
+ * While the bindings supports declaring an interrupt line, those
+ * events are not supported.
+ *
+ * It should be possible to adapt the driver to the current
+ * device EEPROM setup at runtime.
+ */
+
+#define ALS31300_EEPROM_CONFIG 0x02
+#define ALS31300_EEPROM_INTERRUPT 0x03
+#define ALS31300_EEPROM_CUSTOMER_1 0x0d
+#define ALS31300_EEPROM_CUSTOMER_2 0x0e
+#define ALS31300_EEPROM_CUSTOMER_3 0x0f
+#define ALS31300_VOL_MODE 0x27
+#define ALS31300_VOL_MODE_LPDCM GENMASK(6, 4)
+#define ALS31300_LPDCM_INACTIVE_0_5_MS 0
+#define ALS31300_LPDCM_INACTIVE_1_0_MS 1
+#define ALS31300_LPDCM_INACTIVE_5_0_MS 2
+#define ALS31300_LPDCM_INACTIVE_10_0_MS 3
+#define ALS31300_LPDCM_INACTIVE_50_0_MS 4
+#define ALS31300_LPDCM_INACTIVE_100_0_MS 5
+#define ALS31300_LPDCM_INACTIVE_500_0_MS 6
+#define ALS31300_LPDCM_INACTIVE_1000_0_MS 7
+#define ALS31300_VOL_MODE_SLEEP GENMASK(1, 0)
+#define ALS31300_VOL_MODE_ACTIVE_MODE 0
+#define ALS31300_VOL_MODE_SLEEP_MODE 1
+#define ALS31300_VOL_MODE_LPDCM_MODE 2
+#define ALS31300_VOL_MSB 0x28
+#define ALS31300_VOL_MSB_TEMPERATURE GENMASK(5, 0)
+#define ALS31300_VOL_MSB_INTERRUPT BIT(6)
+#define ALS31300_VOL_MSB_NEW_DATA BIT(7)
+#define ALS31300_VOL_MSB_Z_AXIS GENMASK(15, 8)
+#define ALS31300_VOL_MSB_Y_AXIS GENMASK(23, 16)
+#define ALS31300_VOL_MSB_X_AXIS GENMASK(31, 24)
+#define ALS31300_VOL_LSB 0x29
+#define ALS31300_VOL_LSB_TEMPERATURE GENMASK(5, 0)
+#define ALS31300_VOL_LSB_HALL_STATUS GENMASK(7, 7)
+#define ALS31300_VOL_LSB_Z_AXIS GENMASK(11, 8)
+#define ALS31300_VOL_LSB_Y_AXIS GENMASK(15, 12)
+#define ALS31300_VOL_LSB_X_AXIS GENMASK(19, 16)
+#define ALS31300_VOL_LSB_INTERRUPT_WRITE BIT(20)
+#define ALS31300_CUSTOMER_ACCESS 0x35
+
+#define ALS31300_DATA_X_GET(b) \
+ sign_extend32(FIELD_GET(ALS31300_VOL_MSB_X_AXIS, b[0]) << 4 | \
+ FIELD_GET(ALS31300_VOL_LSB_X_AXIS, b[1]), 11)
+#define ALS31300_DATA_Y_GET(b) \
+ sign_extend32(FIELD_GET(ALS31300_VOL_MSB_Y_AXIS, b[0]) << 4 | \
+ FIELD_GET(ALS31300_VOL_LSB_Y_AXIS, b[1]), 11)
+#define ALS31300_DATA_Z_GET(b) \
+ sign_extend32(FIELD_GET(ALS31300_VOL_MSB_Z_AXIS, b[0]) << 4 | \
+ FIELD_GET(ALS31300_VOL_LSB_Z_AXIS, b[1]), 11)
+#define ALS31300_TEMPERATURE_GET(b) \
+ (FIELD_GET(ALS31300_VOL_MSB_TEMPERATURE, b[0]) << 6 | \
+ FIELD_GET(ALS31300_VOL_LSB_TEMPERATURE, b[1]))
+
+enum als31300_channels {
+ TEMPERATURE = 0,
+ AXIS_X,
+ AXIS_Y,
+ AXIS_Z,
+};
+
+struct als31300_variant_info {
+ u8 sensitivity;
+};
+
+struct als31300_data {
+ struct device *dev;
+ /* protects power on/off the device and access HW */
+ struct mutex mutex;
+ const struct als31300_variant_info *variant_info;
+ struct regmap *map;
+};
+
+/* The whole measure is split into 2x32-bit registers, we need to read them both at once */
+static int als31300_get_measure(struct als31300_data *data,
+ u16 *t, s16 *x, s16 *y, s16 *z)
+{
+ u32 buf[2];
+ int ret, err;
+
+ guard(mutex)(&data->mutex);
+
+ ret = pm_runtime_resume_and_get(data->dev);
+ if (ret)
+ return ret;
+
+ /*
+ * Loop until data is valid, new data should have the
+ * ALS31300_VOL_MSB_NEW_DATA bit set to 1.
+ * Max update rate is 2KHz, wait up to 1ms.
+ */
+ ret = read_poll_timeout(regmap_bulk_read, err,
+ err || FIELD_GET(ALS31300_VOL_MSB_NEW_DATA, buf[0]),
+ 20, USEC_PER_MSEC, false,
+ data->map, ALS31300_VOL_MSB, buf, ARRAY_SIZE(buf));
+ /* Bail out on read_poll_timeout() error */
+ if (ret)
+ goto out;
+
+ /* Bail out on regmap_bulk_read() error */
+ if (err) {
+ dev_err(data->dev, "read data failed, error %d\n", ret);
+ ret = err;
+ goto out;
+ }
+
+ *t = ALS31300_TEMPERATURE_GET(buf);
+ *x = ALS31300_DATA_X_GET(buf);
+ *y = ALS31300_DATA_Y_GET(buf);
+ *z = ALS31300_DATA_Z_GET(buf);
+
+out:
+ pm_runtime_mark_last_busy(data->dev);
+ pm_runtime_put_autosuspend(data->dev);
+
+ return ret;
+}
+
+static int als31300_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan, int *val,
+ int *val2, long mask)
+{
+ struct als31300_data *data = iio_priv(indio_dev);
+ s16 x, y, z;
+ u16 t;
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ case IIO_CHAN_INFO_RAW:
+ ret = als31300_get_measure(data, &t, &x, &y, &z);
+ if (ret)
+ return ret;
+
+ switch (chan->address) {
+ case TEMPERATURE:
+ *val = t;
+ return IIO_VAL_INT;
+ case AXIS_X:
+ *val = x;
+ return IIO_VAL_INT;
+ case AXIS_Y:
+ *val = y;
+ return IIO_VAL_INT;
+ case AXIS_Z:
+ *val = z;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ /*
+ * Fractional part of:
+ * 1000 * 302 * (value - 1708)
+ * temp = ----------------------------
+ * 4096
+ * to convert temperature in millicelcius.
+ */
+ *val = MILLI * 302;
+ *val2 = 4096;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_MAGN:
+ /*
+ * Devices are configured in factory
+ * with different sensitivities:
+ * - 500 GAUSS <-> 4 LSB/Gauss
+ * - 1000 GAUSS <-> 2 LSB/Gauss
+ * - 2000 GAUSS <-> 1 LSB/Gauss
+ * with translates by a division of the returned
+ * value to get Gauss value.
+ * The sensitivity cannot be read at runtime
+ * so the value depends on the model compatible
+ * or device id.
+ */
+ *val = 1;
+ *val2 = data->variant_info->sensitivity;
+ return IIO_VAL_FRACTIONAL;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_OFFSET:
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val = -1708;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static irqreturn_t als31300_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct als31300_data *data = iio_priv(indio_dev);
+ struct {
+ u16 temperature;
+ s16 channels[3];
+ aligned_s64 timestamp;
+ } scan;
+ s16 x, y, z;
+ int ret;
+ u16 t;
+
+ ret = als31300_get_measure(data, &t, &x, &y, &z);
+ if (ret)
+ goto trigger_out;
+
+ scan.temperature = t;
+ scan.channels[0] = x;
+ scan.channels[1] = y;
+ scan.channels[2] = z;
+ iio_push_to_buffers_with_timestamp(indio_dev, &scan,
+ pf->timestamp);
+
+trigger_out:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+#define ALS31300_AXIS_CHANNEL(axis, index) \
+ { \
+ .type = IIO_MAGN, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .address = index, \
+ .scan_index = index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+ }
+
+static const struct iio_chan_spec als31300_channels[] = {
+ {
+ .type = IIO_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_OFFSET),
+ .address = TEMPERATURE,
+ .scan_index = TEMPERATURE,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
+ },
+ ALS31300_AXIS_CHANNEL(X, AXIS_X),
+ ALS31300_AXIS_CHANNEL(Y, AXIS_Y),
+ ALS31300_AXIS_CHANNEL(Z, AXIS_Z),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static const struct iio_info als31300_info = {
+ .read_raw = als31300_read_raw,
+};
+
+static int als31300_set_operating_mode(struct als31300_data *data,
+ unsigned int val)
+{
+ int ret;
+
+ ret = regmap_update_bits(data->map, ALS31300_VOL_MODE,
+ ALS31300_VOL_MODE_SLEEP, val);
+ if (ret) {
+ dev_err(data->dev, "failed to set operating mode (%pe)\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ /* The time it takes to exit sleep mode is equivalent to Power-On Delay Time */
+ if (val == ALS31300_VOL_MODE_ACTIVE_MODE)
+ fsleep(600);
+
+ return 0;
+}
+
+static void als31300_power_down(void *data)
+{
+ als31300_set_operating_mode(data, ALS31300_VOL_MODE_SLEEP_MODE);
+}
+
+static const struct iio_buffer_setup_ops als31300_setup_ops = {};
+
+static const unsigned long als31300_scan_masks[] = { GENMASK(3, 0), 0 };
+
+static bool als31300_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return reg == ALS31300_VOL_MSB || reg == ALS31300_VOL_LSB;
+}
+
+static const struct regmap_config als31300_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 32,
+ .max_register = ALS31300_CUSTOMER_ACCESS,
+ .volatile_reg = als31300_volatile_reg,
+};
+
+static int als31300_probe(struct i2c_client *i2c)
+{
+ struct device *dev = &i2c->dev;
+ struct als31300_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ data->dev = dev;
+ i2c_set_clientdata(i2c, indio_dev);
+
+ ret = devm_mutex_init(dev, &data->mutex);
+ if (ret)
+ return ret;
+
+ data->variant_info = i2c_get_match_data(i2c);
+ if (!data->variant_info)
+ return -EINVAL;
+
+ data->map = devm_regmap_init_i2c(i2c, &als31300_regmap_config);
+ if (IS_ERR(data->map))
+ return dev_err_probe(dev, PTR_ERR(data->map),
+ "failed to allocate register map\n");
+
+ ret = devm_regulator_get_enable(dev, "vcc");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable regulator\n");
+
+ ret = als31300_set_operating_mode(data, ALS31300_VOL_MODE_ACTIVE_MODE);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to power on device\n");
+
+ ret = devm_add_action_or_reset(dev, als31300_power_down, data);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to add powerdown action\n");
+
+ indio_dev->info = &als31300_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = i2c->name;
+ indio_dev->channels = als31300_channels;
+ indio_dev->num_channels = ARRAY_SIZE(als31300_channels);
+ indio_dev->available_scan_masks = als31300_scan_masks;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ als31300_trigger_handler,
+ &als31300_setup_ops);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "iio triggered buffer setup failed\n");
+
+ ret = pm_runtime_set_active(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ pm_runtime_get_noresume(dev);
+ pm_runtime_set_autosuspend_delay(dev, 200);
+ pm_runtime_use_autosuspend(dev);
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "device register failed\n");
+
+ return 0;
+}
+
+static int als31300_runtime_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct als31300_data *data = iio_priv(indio_dev);
+
+ return als31300_set_operating_mode(data, ALS31300_VOL_MODE_SLEEP_MODE);
+}
+
+static int als31300_runtime_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct als31300_data *data = iio_priv(indio_dev);
+
+ return als31300_set_operating_mode(data, ALS31300_VOL_MODE_ACTIVE_MODE);
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(als31300_pm_ops,
+ als31300_runtime_suspend, als31300_runtime_resume,
+ NULL);
+
+static const struct als31300_variant_info al31300_variant_500 = {
+ .sensitivity = 4,
+};
+
+static const struct als31300_variant_info al31300_variant_1000 = {
+ .sensitivity = 2,
+};
+
+static const struct als31300_variant_info al31300_variant_2000 = {
+ .sensitivity = 1,
+};
+
+static const struct i2c_device_id als31300_id[] = {
+ {
+ .name = "als31300-500",
+ .driver_data = (kernel_ulong_t)&al31300_variant_500,
+ },
+ {
+ .name = "als31300-1000",
+ .driver_data = (kernel_ulong_t)&al31300_variant_1000,
+ },
+ {
+ .name = "als31300-2000",
+ .driver_data = (kernel_ulong_t)&al31300_variant_2000,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, als31300_id);
+
+static const struct of_device_id als31300_of_match[] = {
+ {
+ .compatible = "allegromicro,als31300-500",
+ .data = &al31300_variant_500,
+ },
+ {
+ .compatible = "allegromicro,als31300-1000",
+ .data = &al31300_variant_1000,
+ },
+ {
+ .compatible = "allegromicro,als31300-2000",
+ .data = &al31300_variant_2000,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, als31300_of_match);
+
+static struct i2c_driver als31300_driver = {
+ .driver = {
+ .name = "als31300",
+ .of_match_table = als31300_of_match,
+ .pm = pm_ptr(&als31300_pm_ops),
+ },
+ .probe = als31300_probe,
+ .id_table = als31300_id,
+};
+module_i2c_driver(als31300_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ALS31300 3-D Linear Hall Effect Driver");
+MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c
index 06d5a1ef1fbd..7de18c4a0ccb 100644
--- a/drivers/iio/magnetometer/bmc150_magn.c
+++ b/drivers/iio/magnetometer/bmc150_magn.c
@@ -14,7 +14,6 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
@@ -855,17 +854,6 @@ static const struct iio_buffer_setup_ops bmc150_magn_buffer_setup_ops = {
.postdisable = bmc150_magn_buffer_postdisable,
};
-static const char *bmc150_magn_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
int bmc150_magn_probe(struct device *dev, struct regmap *regmap,
int irq, const char *name)
{
@@ -894,9 +882,6 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap,
if (ret)
return ret;
- if (!name && ACPI_HANDLE(dev))
- name = bmc150_magn_match_acpi_device(dev);
-
mutex_init(&data->mutex);
ret = bmc150_magn_init(data);
diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c
index a28d46d59875..17e10a462ac8 100644
--- a/drivers/iio/magnetometer/bmc150_magn_i2c.c
+++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c
@@ -38,14 +38,6 @@ static void bmc150_magn_i2c_remove(struct i2c_client *client)
bmc150_magn_remove(&client->dev);
}
-static const struct acpi_device_id bmc150_magn_acpi_match[] = {
- {"BMC150B", 0},
- {"BMC156B", 0},
- {"BMM150B", 0},
- {},
-};
-MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
-
static const struct i2c_device_id bmc150_magn_i2c_id[] = {
{ "bmc150_magn" },
{ "bmc156_magn" },
@@ -67,7 +59,6 @@ static struct i2c_driver bmc150_magn_driver = {
.driver = {
.name = "bmc150_magn_i2c",
.of_match_table = bmc150_magn_of_match,
- .acpi_match_table = bmc150_magn_acpi_match,
.pm = &bmc150_magn_pm_ops,
},
.probe = bmc150_magn_i2c_probe,
diff --git a/drivers/iio/magnetometer/bmc150_magn_spi.c b/drivers/iio/magnetometer/bmc150_magn_spi.c
index abc75a05c46a..c850de1bc79b 100644
--- a/drivers/iio/magnetometer/bmc150_magn_spi.c
+++ b/drivers/iio/magnetometer/bmc150_magn_spi.c
@@ -41,20 +41,11 @@ static const struct spi_device_id bmc150_magn_spi_id[] = {
};
MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id);
-static const struct acpi_device_id bmc150_magn_acpi_match[] = {
- {"BMC150B", 0},
- {"BMC156B", 0},
- {"BMM150B", 0},
- {},
-};
-MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
-
static struct spi_driver bmc150_magn_spi_driver = {
.probe = bmc150_magn_spi_probe,
.remove = bmc150_magn_spi_remove,
.id_table = bmc150_magn_spi_id,
.driver = {
- .acpi_match_table = bmc150_magn_acpi_match,
.name = "bmc150_magn_spi",
},
};
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index 5c795a430d09..1d6fcbbae1c5 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -466,11 +466,11 @@ static int magn_3d_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_magn_3d_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static char *name = "magn_3d";
struct iio_dev *indio_dev;
struct magn_3d_state *magn_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_chan_spec *channels;
int chan_count = 0;
@@ -549,7 +549,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_magn_3d_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct magn_3d_state *magn_state = iio_priv(indio_dev);
@@ -574,7 +574,7 @@ static struct platform_driver hid_magn_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_magn_3d_probe,
- .remove_new = hid_magn_3d_remove,
+ .remove = hid_magn_3d_remove,
};
module_platform_driver(hid_magn_3d_platform_driver);
diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
index 8943d5c78bc0..c74b92d53d4d 100644
--- a/drivers/iio/orientation/hid-sensor-incl-3d.c
+++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
@@ -29,7 +29,7 @@ struct incl_3d_state {
struct hid_sensor_hub_attribute_info incl[INCLI_3D_CHANNEL_MAX];
struct {
u32 incl_val[INCLI_3D_CHANNEL_MAX];
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -299,11 +299,11 @@ static int incl_3d_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_incl_3d_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret;
static char *name = "incli_3d";
struct iio_dev *indio_dev;
struct incl_3d_state *incl_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct incl_3d_state));
@@ -385,7 +385,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_incl_3d_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct incl_3d_state *incl_state = iio_priv(indio_dev);
@@ -410,7 +410,7 @@ static struct platform_driver hid_incl_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_incl_3d_probe,
- .remove_new = hid_incl_3d_remove,
+ .remove = hid_incl_3d_remove,
};
module_platform_driver(hid_incl_3d_platform_driver);
diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
index 5e8cadd5177a..343be43163e4 100644
--- a/drivers/iio/orientation/hid-sensor-rotation.c
+++ b/drivers/iio/orientation/hid-sensor-rotation.c
@@ -20,7 +20,7 @@ struct dev_rot_state {
struct hid_sensor_hub_attribute_info quaternion;
struct {
s32 sampled_vals[4] __aligned(16);
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -230,11 +230,11 @@ static int dev_rot_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_dev_rot_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret;
char *name;
struct iio_dev *indio_dev;
struct dev_rot_state *rot_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct dev_rot_state));
@@ -329,7 +329,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_dev_rot_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct dev_rot_state *rot_state = iio_priv(indio_dev);
@@ -362,7 +362,7 @@ static struct platform_driver hid_dev_rot_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_dev_rot_probe,
- .remove_new = hid_dev_rot_remove,
+ .remove = hid_dev_rot_remove,
};
module_platform_driver(hid_dev_rot_platform_driver);
diff --git a/drivers/iio/position/hid-sensor-custom-intel-hinge.c b/drivers/iio/position/hid-sensor-custom-intel-hinge.c
index 76e173850a35..3a6c7e50cc70 100644
--- a/drivers/iio/position/hid-sensor-custom-intel-hinge.c
+++ b/drivers/iio/position/hid-sensor-custom-intel-hinge.c
@@ -39,7 +39,7 @@ struct hinge_state {
const char *labels[CHANNEL_SCAN_INDEX_MAX];
struct {
u32 hinge_val[3];
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
@@ -263,9 +263,9 @@ static int hinge_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_hinge_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct hinge_state *st;
struct iio_dev *indio_dev;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
int ret;
int i;
@@ -344,7 +344,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_hinge_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct hinge_state *st = iio_priv(indio_dev);
@@ -369,7 +369,7 @@ static struct platform_driver hid_hinge_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_hinge_probe,
- .remove_new = hid_hinge_remove,
+ .remove = hid_hinge_remove,
};
module_platform_driver(hid_hinge_platform_driver);
diff --git a/drivers/iio/position/iqs624-pos.c b/drivers/iio/position/iqs624-pos.c
index 4d7452314209..8239239c6ee2 100644
--- a/drivers/iio/position/iqs624-pos.c
+++ b/drivers/iio/position/iqs624-pos.c
@@ -181,7 +181,7 @@ static int iqs624_pos_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct iqs624_pos_private *iqs624_pos = iio_priv(indio_dev);
struct iqs62x_core *iqs62x = iqs624_pos->iqs62x;
diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index a8b97b9b0461..e5ec8137961f 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -16,6 +16,11 @@
* https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp390-ds002.pdf
* https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp581-ds004.pdf
*
+ * Sensor API:
+ * https://github.com/boschsensortec/BME280_SensorAPI
+ * https://github.com/boschsensortec/BMP3_SensorAPI
+ * https://github.com/boschsensortec/BMP5_SensorAPI
+ *
* Notice:
* The link to the bmp180 datasheet points to an outdated version missing these changes:
* - Changed document referral from ANP015 to BST-MPS-AN004-00 on page 26
@@ -37,12 +42,14 @@
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/pm_runtime.h>
+#include <linux/property.h>
#include <linux/random.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
@@ -340,10 +347,19 @@ static int bmp280_read_calib(struct bmp280_data *data)
return 0;
}
+/*
+ * These enums are used for indexing into the array of humidity parameters
+ * for BME280. Due to some weird indexing, unaligned BE/LE accesses co-exist in
+ * order to prepare the FIELD_{GET/PREP}() fields. Table 16 in Section 4.2.2 of
+ * the datasheet.
+ */
+enum { H2 = 0, H3 = 2, H4 = 3, H5 = 4, H6 = 6 };
+
static int bme280_read_calib(struct bmp280_data *data)
{
struct bmp280_calib *calib = &data->calib.bmp280;
struct device *dev = data->dev;
+ s16 h4_upper, h4_lower, tmp_1, tmp_2, tmp_3;
unsigned int tmp;
int ret;
@@ -352,14 +368,6 @@ static int bme280_read_calib(struct bmp280_data *data)
if (ret)
return ret;
- /*
- * Read humidity calibration values.
- * Due to some odd register addressing we cannot just
- * do a big bulk read. Instead, we have to read each Hx
- * value separately and sometimes do some bit shifting...
- * Humidity data is only available on BME280.
- */
-
ret = regmap_read(data->regmap, BME280_REG_COMP_H1, &tmp);
if (ret) {
dev_err(dev, "failed to read H1 comp value\n");
@@ -368,43 +376,23 @@ static int bme280_read_calib(struct bmp280_data *data)
calib->H1 = tmp;
ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H2,
- &data->le16, sizeof(data->le16));
+ data->bme280_humid_cal_buf,
+ sizeof(data->bme280_humid_cal_buf));
if (ret) {
- dev_err(dev, "failed to read H2 comp value\n");
+ dev_err(dev, "failed to read humidity calibration values\n");
return ret;
}
- calib->H2 = sign_extend32(le16_to_cpu(data->le16), 15);
- ret = regmap_read(data->regmap, BME280_REG_COMP_H3, &tmp);
- if (ret) {
- dev_err(dev, "failed to read H3 comp value\n");
- return ret;
- }
- calib->H3 = tmp;
-
- ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H4,
- &data->be16, sizeof(data->be16));
- if (ret) {
- dev_err(dev, "failed to read H4 comp value\n");
- return ret;
- }
- calib->H4 = sign_extend32(((be16_to_cpu(data->be16) >> 4) & 0xff0) |
- (be16_to_cpu(data->be16) & 0xf), 11);
-
- ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H5,
- &data->le16, sizeof(data->le16));
- if (ret) {
- dev_err(dev, "failed to read H5 comp value\n");
- return ret;
- }
- calib->H5 = sign_extend32(FIELD_GET(BME280_COMP_H5_MASK, le16_to_cpu(data->le16)), 11);
-
- ret = regmap_read(data->regmap, BME280_REG_COMP_H6, &tmp);
- if (ret) {
- dev_err(dev, "failed to read H6 comp value\n");
- return ret;
- }
- calib->H6 = sign_extend32(tmp, 7);
+ calib->H2 = get_unaligned_le16(&data->bme280_humid_cal_buf[H2]);
+ calib->H3 = data->bme280_humid_cal_buf[H3];
+ tmp_1 = get_unaligned_be16(&data->bme280_humid_cal_buf[H4]);
+ tmp_2 = FIELD_GET(BME280_COMP_H4_GET_MASK_UP, tmp_1);
+ h4_upper = FIELD_PREP(BME280_COMP_H4_PREP_MASK_UP, tmp_2);
+ h4_lower = FIELD_GET(BME280_COMP_H4_MASK_LOW, tmp_1);
+ calib->H4 = sign_extend32(h4_upper | h4_lower, 11);
+ tmp_3 = get_unaligned_le16(&data->bme280_humid_cal_buf[H5]);
+ calib->H5 = sign_extend32(FIELD_GET(BME280_COMP_H5_MASK, tmp_3), 11);
+ calib->H6 = data->bme280_humid_cal_buf[H6];
return 0;
}
@@ -635,6 +623,14 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
+ ret = data->chip_info->set_mode(data, BMP280_FORCED);
+ if (ret)
+ return ret;
+
+ ret = data->chip_info->wait_conv(data);
+ if (ret)
+ return ret;
+
switch (chan->type) {
case IIO_HUMIDITYRELATIVE:
ret = data->chip_info->read_humid(data, &chan_value);
@@ -664,6 +660,14 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
return -EINVAL;
}
case IIO_CHAN_INFO_RAW:
+ ret = data->chip_info->set_mode(data, BMP280_FORCED);
+ if (ret)
+ return ret;
+
+ ret = data->chip_info->wait_conv(data);
+ if (ret)
+ return ret;
+
switch (chan->type) {
case IIO_HUMIDITYRELATIVE:
ret = data->chip_info->read_humid(data, &chan_value);
@@ -983,6 +987,92 @@ static const unsigned long bme280_avail_scan_masks[] = {
0
};
+static int bmp280_preinit(struct bmp280_data *data)
+{
+ struct device *dev = data->dev;
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_write(data->regmap, BMP280_REG_RESET, BMP280_RST_SOFT_CMD);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to reset device.\n");
+
+ /*
+ * According to the datasheet in Chapter 1: Specification, Table 2,
+ * after resetting, the device uses the complete power-on sequence so
+ * it needs to wait for the defined start-up time.
+ */
+ fsleep(data->start_up_time);
+
+ ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read status register.\n");
+
+ if (reg & BMP280_REG_STATUS_IM_UPDATE)
+ return dev_err_probe(dev, -EIO, "Failed to copy NVM contents.\n");
+
+ return 0;
+}
+
+static const u8 bmp280_operation_mode[] = {
+ [BMP280_SLEEP] = BMP280_MODE_SLEEP,
+ [BMP280_FORCED] = BMP280_MODE_FORCED,
+ [BMP280_NORMAL] = BMP280_MODE_NORMAL,
+};
+
+static int bmp280_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ int ret;
+
+ ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
+ BMP280_MODE_MASK, bmp280_operation_mode[mode]);
+ if (ret) {
+ dev_err(data->dev, "failed to write ctrl_meas register.\n");
+ return ret;
+ }
+
+ data->op_mode = mode;
+
+ return 0;
+}
+
+static int bmp280_wait_conv(struct bmp280_data *data)
+{
+ unsigned int reg, meas_time_us;
+ int ret;
+
+ /* Check if we are using a BME280 device */
+ if (data->oversampling_humid)
+ meas_time_us = BMP280_PRESS_HUMID_MEAS_OFFSET +
+ BIT(data->oversampling_humid) * BMP280_MEAS_DUR;
+
+ else
+ meas_time_us = 0;
+
+ /* Pressure measurement time */
+ meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
+ BIT(data->oversampling_press) * BMP280_MEAS_DUR;
+
+ /* Temperature measurement time */
+ meas_time_us += BIT(data->oversampling_temp) * BMP280_MEAS_DUR;
+
+ /* Waiting time according to the BM(P/E)2 Sensor API */
+ fsleep(meas_time_us);
+
+ ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to read status register.\n");
+ return ret;
+ }
+
+ if (reg & BMP280_REG_STATUS_MEAS_BIT) {
+ dev_err(data->dev, "Measurement cycle didn't complete.\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
static int bmp280_chip_config(struct bmp280_data *data)
{
u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
@@ -993,7 +1083,7 @@ static int bmp280_chip_config(struct bmp280_data *data)
BMP280_OSRS_TEMP_MASK |
BMP280_OSRS_PRESS_MASK |
BMP280_MODE_MASK,
- osrs | BMP280_MODE_NORMAL);
+ osrs | BMP280_MODE_SLEEP);
if (ret) {
dev_err(data->dev, "failed to write ctrl_meas register\n");
return ret;
@@ -1015,7 +1105,9 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- s32 adc_temp, adc_press, t_fine;
+ u32 adc_temp, adc_press, comp_press;
+ s32 t_fine, comp_temp;
+ s32 *chans = (s32 *)data->sensor_data;
int ret;
guard(mutex)(&data->lock);
@@ -1035,7 +1127,7 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p)
goto out;
}
- data->sensor_data[1] = bmp280_compensate_temp(data, adc_temp);
+ comp_temp = bmp280_compensate_temp(data, adc_temp);
/* Pressure calculations */
adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0]));
@@ -1045,10 +1137,12 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p)
}
t_fine = bmp280_calc_t_fine(data, adc_temp);
+ comp_press = bmp280_compensate_press(data, adc_press, t_fine);
- data->sensor_data[0] = bmp280_compensate_press(data, adc_press, t_fine);
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -1099,6 +1193,9 @@ const struct bmp280_chip_info bmp280_chip_info = {
.read_temp = bmp280_read_temp,
.read_press = bmp280_read_press,
.read_calib = bmp280_read_calib,
+ .set_mode = bmp280_set_mode,
+ .wait_conv = bmp280_wait_conv,
+ .preinit = bmp280_preinit,
.trigger_handler = bmp280_trigger_handler,
};
@@ -1128,7 +1225,9 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- s32 adc_temp, adc_press, adc_humidity, t_fine;
+ u32 adc_temp, adc_press, adc_humidity, comp_press, comp_humidity;
+ s32 t_fine, comp_temp;
+ s32 *chans = (s32 *)data->sensor_data;
int ret;
guard(mutex)(&data->lock);
@@ -1148,7 +1247,7 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
goto out;
}
- data->sensor_data[1] = bmp280_compensate_temp(data, adc_temp);
+ comp_temp = bmp280_compensate_temp(data, adc_temp);
/* Pressure calculations */
adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0]));
@@ -1158,8 +1257,7 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
}
t_fine = bmp280_calc_t_fine(data, adc_temp);
-
- data->sensor_data[0] = bmp280_compensate_press(data, adc_press, t_fine);
+ comp_press = bmp280_compensate_press(data, adc_press, t_fine);
/* Humidity calculations */
adc_humidity = get_unaligned_be16(&data->buf[6]);
@@ -1168,9 +1266,14 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
dev_err(data->dev, "reading humidity skipped\n");
goto out;
}
- data->sensor_data[2] = bme280_compensate_humidity(data, adc_humidity, t_fine);
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ comp_humidity = bme280_compensate_humidity(data, adc_humidity, t_fine);
+
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
+ chans[2] = comp_humidity;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -1179,6 +1282,63 @@ out:
return IRQ_HANDLED;
}
+static int __bmp280_trigger_probe(struct iio_dev *indio_dev,
+ const struct iio_trigger_ops *trigger_ops,
+ int (*int_pin_config)(struct bmp280_data *data),
+ irq_handler_t irq_thread_handler)
+{
+ struct bmp280_data *data = iio_priv(indio_dev);
+ struct device *dev = data->dev;
+ u32 irq_type;
+ int ret, irq;
+
+ irq = fwnode_irq_get(dev_fwnode(dev), 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "No interrupt found.\n");
+
+ irq_type = irq_get_trigger_type(irq);
+ switch (irq_type) {
+ case IRQF_TRIGGER_RISING:
+ data->trig_active_high = true;
+ break;
+ case IRQF_TRIGGER_FALLING:
+ data->trig_active_high = false;
+ break;
+ default:
+ return dev_err_probe(dev, -EINVAL, "Invalid interrupt type specified.\n");
+ }
+
+ data->trig_open_drain =
+ fwnode_property_read_bool(dev_fwnode(dev), "int-open-drain");
+
+ ret = int_pin_config(data);
+ if (ret)
+ return ret;
+
+ data->trig = devm_iio_trigger_alloc(data->dev, "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->ops = trigger_ops;
+ iio_trigger_set_drvdata(data->trig, data);
+
+ ret = devm_request_threaded_irq(data->dev, irq, NULL,
+ irq_thread_handler, IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "request IRQ failed.\n");
+
+ ret = devm_iio_trigger_register(data->dev, data->trig);
+ if (ret)
+ return dev_err_probe(dev, ret, "iio trigger register failed.\n");
+
+ indio_dev->trig = iio_trigger_get(data->trig);
+
+ return 0;
+}
+
static const u8 bme280_chip_ids[] = { BME280_CHIP_ID };
static const int bme280_humid_coeffs[] = { 1000, 1024 };
@@ -1216,6 +1376,9 @@ const struct bmp280_chip_info bme280_chip_info = {
.read_press = bmp280_read_press,
.read_humid = bme280_read_humid,
.read_calib = bme280_read_calib,
+ .set_mode = bmp280_set_mode,
+ .wait_conv = bmp280_wait_conv,
+ .preinit = bmp280_preinit,
.trigger_handler = bme280_trigger_handler,
};
@@ -1502,6 +1665,64 @@ static int bmp380_preinit(struct bmp280_data *data)
return bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
}
+static const u8 bmp380_operation_mode[] = {
+ [BMP280_SLEEP] = BMP380_MODE_SLEEP,
+ [BMP280_FORCED] = BMP380_MODE_FORCED,
+ [BMP280_NORMAL] = BMP380_MODE_NORMAL,
+};
+
+static int bmp380_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ int ret;
+
+ ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
+ BMP380_MODE_MASK,
+ FIELD_PREP(BMP380_MODE_MASK,
+ bmp380_operation_mode[mode]));
+ if (ret) {
+ dev_err(data->dev, "failed to write power control register.\n");
+ return ret;
+ }
+
+ data->op_mode = mode;
+
+ return 0;
+}
+
+static int bmp380_wait_conv(struct bmp280_data *data)
+{
+ unsigned int reg;
+ int ret, meas_time_us;
+
+ /* Offset measurement time */
+ meas_time_us = BMP380_MEAS_OFFSET;
+
+ /* Pressure measurement time */
+ meas_time_us += BMP380_PRESS_MEAS_OFFSET +
+ BIT(data->oversampling_press) * BMP380_MEAS_DUR;
+
+ /* Temperature measurement time */
+ meas_time_us += BMP380_TEMP_MEAS_OFFSET +
+ BIT(data->oversampling_temp) * BMP380_MEAS_DUR;
+
+ /* Measurement time defined in Datasheet Section 3.9.2 */
+ fsleep(meas_time_us);
+
+ ret = regmap_read(data->regmap, BMP380_REG_STATUS, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to read status register.\n");
+ return ret;
+ }
+
+ if (!((reg & BMP380_STATUS_DRDY_PRESS_MASK) &&
+ (reg & BMP380_STATUS_DRDY_TEMP_MASK))) {
+ dev_err(data->dev, "Measurement cycle didn't complete.\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
static int bmp380_chip_config(struct bmp280_data *data)
{
bool change = false, aux;
@@ -1545,14 +1766,12 @@ static int bmp380_chip_config(struct bmp280_data *data)
change = change || aux;
/* Set filter data */
- ret = regmap_update_bits_check(data->regmap, BMP380_REG_CONFIG, BMP380_FILTER_MASK,
- FIELD_PREP(BMP380_FILTER_MASK, data->iir_filter_coeff),
- &aux);
+ ret = regmap_update_bits(data->regmap, BMP380_REG_CONFIG, BMP380_FILTER_MASK,
+ FIELD_PREP(BMP380_FILTER_MASK, data->iir_filter_coeff));
if (ret) {
dev_err(data->dev, "failed to write config register\n");
return ret;
}
- change = change || aux;
if (change) {
/*
@@ -1564,17 +1783,19 @@ static int bmp380_chip_config(struct bmp280_data *data)
* Resets sensor measurement loop toggling between sleep and
* normal operating modes.
*/
- ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
- BMP380_MODE_MASK,
- FIELD_PREP(BMP380_MODE_MASK, BMP380_MODE_SLEEP));
+ ret = bmp380_set_mode(data, BMP280_SLEEP);
if (ret) {
dev_err(data->dev, "failed to set sleep mode\n");
return ret;
}
- usleep_range(2000, 2500);
- ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
- BMP380_MODE_MASK,
- FIELD_PREP(BMP380_MODE_MASK, BMP380_MODE_NORMAL));
+
+ /*
+ * According to the BMP3 Sensor API, the sensor needs 5ms
+ * in order to go to the sleep mode.
+ */
+ fsleep(5 * USEC_PER_MSEC);
+
+ ret = bmp380_set_mode(data, BMP280_NORMAL);
if (ret) {
dev_err(data->dev, "failed to set normal mode\n");
return ret;
@@ -1600,7 +1821,77 @@ static int bmp380_chip_config(struct bmp280_data *data)
}
}
- return 0;
+ /* Dummy read to empty data registers. */
+ ret = bmp380_read_press(data, &tmp);
+ if (ret)
+ return ret;
+
+ ret = bmp380_set_mode(data, BMP280_SLEEP);
+ if (ret)
+ dev_err(data->dev, "failed to set sleep mode.\n");
+
+ return ret;
+}
+
+static int bmp380_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct bmp280_data *data = iio_trigger_get_drvdata(trig);
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ ret = regmap_update_bits(data->regmap, BMP380_REG_INT_CONTROL,
+ BMP380_INT_CTRL_DRDY_EN,
+ FIELD_PREP(BMP380_INT_CTRL_DRDY_EN, !!state));
+ if (ret)
+ dev_err(data->dev,
+ "Could not %s interrupt.\n", str_enable_disable(state));
+ return ret;
+}
+
+static const struct iio_trigger_ops bmp380_trigger_ops = {
+ .set_trigger_state = &bmp380_data_rdy_trigger_set_state,
+};
+
+static int bmp380_int_pin_config(struct bmp280_data *data)
+{
+ int pin_drive_cfg = FIELD_PREP(BMP380_INT_CTRL_OPEN_DRAIN,
+ data->trig_open_drain);
+ int pin_level_cfg = FIELD_PREP(BMP380_INT_CTRL_LEVEL,
+ data->trig_active_high);
+ int ret, int_pin_cfg = pin_drive_cfg | pin_level_cfg;
+
+ ret = regmap_update_bits(data->regmap, BMP380_REG_INT_CONTROL,
+ BMP380_INT_CTRL_SETTINGS_MASK, int_pin_cfg);
+ if (ret)
+ dev_err(data->dev, "Could not set interrupt settings.\n");
+
+ return ret;
+}
+
+static irqreturn_t bmp380_irq_thread_handler(int irq, void *p)
+{
+ struct iio_dev *indio_dev = p;
+ struct bmp280_data *data = iio_priv(indio_dev);
+ unsigned int int_ctrl;
+ int ret;
+
+ ret = regmap_read(data->regmap, BMP380_REG_INT_STATUS, &int_ctrl);
+ if (ret)
+ return IRQ_NONE;
+
+ if (FIELD_GET(BMP380_INT_STATUS_DRDY, int_ctrl))
+ iio_trigger_poll_nested(data->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int bmp380_trigger_probe(struct iio_dev *indio_dev)
+{
+ return __bmp280_trigger_probe(indio_dev, &bmp380_trigger_ops,
+ bmp380_int_pin_config,
+ bmp380_irq_thread_handler);
}
static irqreturn_t bmp380_trigger_handler(int irq, void *p)
@@ -1608,7 +1899,9 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- s32 adc_temp, adc_press, t_fine;
+ u32 adc_temp, adc_press, comp_press;
+ s32 t_fine, comp_temp;
+ s32 *chans = (s32 *)data->sensor_data;
int ret;
guard(mutex)(&data->lock);
@@ -1628,7 +1921,7 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
goto out;
}
- data->sensor_data[1] = bmp380_compensate_temp(data, adc_temp);
+ comp_temp = bmp380_compensate_temp(data, adc_temp);
/* Pressure calculations */
adc_press = get_unaligned_le24(&data->buf[0]);
@@ -1638,10 +1931,12 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
}
t_fine = bmp380_calc_t_fine(data, adc_temp);
+ comp_press = bmp380_compensate_press(data, adc_press, t_fine);
- data->sensor_data[0] = bmp380_compensate_press(data, adc_press, t_fine);
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -1692,8 +1987,11 @@ const struct bmp280_chip_info bmp380_chip_info = {
.read_temp = bmp380_read_temp,
.read_press = bmp380_read_press,
.read_calib = bmp380_read_calib,
+ .set_mode = bmp380_set_mode,
+ .wait_conv = bmp380_wait_conv,
.preinit = bmp380_preinit,
+ .trigger_probe = bmp380_trigger_probe,
.trigger_handler = bmp380_trigger_handler,
};
EXPORT_SYMBOL_NS(bmp380_chip_info, IIO_BMP280);
@@ -2079,6 +2377,70 @@ static int bmp580_preinit(struct bmp280_data *data)
return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config));
}
+static const u8 bmp580_operation_mode[] = {
+ [BMP280_SLEEP] = BMP580_MODE_SLEEP,
+ [BMP280_FORCED] = BMP580_MODE_FORCED,
+ [BMP280_NORMAL] = BMP580_MODE_NORMAL,
+};
+
+static int bmp580_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ struct device *dev = data->dev;
+ int ret;
+
+ if (mode == BMP280_FORCED) {
+ ret = regmap_set_bits(data->regmap, BMP580_REG_DSP_CONFIG,
+ BMP580_DSP_IIR_FORCED_FLUSH);
+ if (ret) {
+ dev_err(dev, "Could not flush IIR filter constants.\n");
+ return ret;
+ }
+ }
+
+ ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG,
+ BMP580_MODE_MASK,
+ FIELD_PREP(BMP580_MODE_MASK,
+ bmp580_operation_mode[mode]));
+ if (ret) {
+ dev_err(dev, "failed to write power control register.\n");
+ return ret;
+ }
+
+ data->op_mode = mode;
+
+ return 0;
+}
+
+static int bmp580_wait_conv(struct bmp280_data *data)
+{
+ /*
+ * Taken from datasheet, Section 2 "Specification, Table 3 "Electrical
+ * characteristics.
+ */
+ static const int time_conv_press[] = {
+ 0, 1050, 1785, 3045, 5670, 10920, 21420, 42420,
+ 84420,
+ };
+ static const int time_conv_temp[] = {
+ 0, 1050, 1105, 1575, 2205, 3465, 6090, 11340,
+ 21840,
+ };
+ int meas_time_us;
+
+ meas_time_us = 4 * USEC_PER_MSEC +
+ time_conv_temp[data->oversampling_temp] +
+ time_conv_press[data->oversampling_press];
+
+ /*
+ * Measurement time mentioned in Chapter 2, Table 4 of the datasheet.
+ * The extra 4ms is the required mode change to start of measurement
+ * time.
+ */
+ fsleep(meas_time_us);
+
+ return 0;
+}
+
static int bmp580_chip_config(struct bmp280_data *data)
{
bool change = false, aux;
@@ -2141,26 +2503,13 @@ static int bmp580_chip_config(struct bmp280_data *data)
reg_val = FIELD_PREP(BMP580_DSP_IIR_PRESS_MASK, data->iir_filter_coeff) |
FIELD_PREP(BMP580_DSP_IIR_TEMP_MASK, data->iir_filter_coeff);
- ret = regmap_update_bits_check(data->regmap, BMP580_REG_DSP_IIR,
- BMP580_DSP_IIR_PRESS_MASK |
- BMP580_DSP_IIR_TEMP_MASK,
- reg_val, &aux);
+ ret = regmap_update_bits(data->regmap, BMP580_REG_DSP_IIR,
+ BMP580_DSP_IIR_PRESS_MASK | BMP580_DSP_IIR_TEMP_MASK,
+ reg_val);
if (ret) {
dev_err(data->dev, "failed to write config register\n");
return ret;
}
- change = change || aux;
-
- /* Restore sensor to normal operation mode */
- ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG,
- BMP580_MODE_MASK,
- FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_NORMAL));
- if (ret) {
- dev_err(data->dev, "failed to set normal mode\n");
- return ret;
- }
- /* From datasheet's table 4: electrical characteristics */
- usleep_range(3000, 3500);
if (change) {
/*
@@ -2185,12 +2534,80 @@ static int bmp580_chip_config(struct bmp280_data *data)
return 0;
}
+static int bmp580_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct bmp280_data *data = iio_trigger_get_drvdata(trig);
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ ret = regmap_update_bits(data->regmap, BMP580_REG_INT_CONFIG,
+ BMP580_INT_CONFIG_INT_EN,
+ FIELD_PREP(BMP580_INT_CONFIG_INT_EN, !!state));
+ if (ret)
+ dev_err(data->dev,
+ "Could not %s interrupt.\n", str_enable_disable(state));
+ return ret;
+}
+
+static const struct iio_trigger_ops bmp580_trigger_ops = {
+ .set_trigger_state = &bmp580_data_rdy_trigger_set_state,
+};
+
+static int bmp580_int_pin_config(struct bmp280_data *data)
+{
+ int pin_drive_cfg = FIELD_PREP(BMP580_INT_CONFIG_OPEN_DRAIN,
+ data->trig_open_drain);
+ int pin_level_cfg = FIELD_PREP(BMP580_INT_CONFIG_LEVEL,
+ data->trig_active_high);
+ int ret, int_pin_cfg = pin_drive_cfg | pin_level_cfg;
+
+ ret = regmap_update_bits(data->regmap, BMP580_REG_INT_CONFIG,
+ BMP580_INT_CONFIG_MASK, int_pin_cfg);
+ if (ret) {
+ dev_err(data->dev, "Could not set interrupt settings.\n");
+ return ret;
+ }
+
+ ret = regmap_set_bits(data->regmap, BMP580_REG_INT_SOURCE,
+ BMP580_INT_SOURCE_DRDY);
+ if (ret)
+ dev_err(data->dev, "Could not set interrupt source.\n");
+
+ return ret;
+}
+
+static irqreturn_t bmp580_irq_thread_handler(int irq, void *p)
+{
+ struct iio_dev *indio_dev = p;
+ struct bmp280_data *data = iio_priv(indio_dev);
+ unsigned int int_ctrl;
+ int ret;
+
+ ret = regmap_read(data->regmap, BMP580_REG_INT_STATUS, &int_ctrl);
+ if (ret)
+ return IRQ_NONE;
+
+ if (FIELD_GET(BMP580_INT_STATUS_DRDY_MASK, int_ctrl))
+ iio_trigger_poll_nested(data->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int bmp580_trigger_probe(struct iio_dev *indio_dev)
+{
+ return __bmp280_trigger_probe(indio_dev, &bmp580_trigger_ops,
+ bmp580_int_pin_config,
+ bmp580_irq_thread_handler);
+}
+
static irqreturn_t bmp580_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- int ret;
+ int ret, offset;
guard(mutex)(&data->lock);
@@ -2202,13 +2619,17 @@ static irqreturn_t bmp580_trigger_handler(int irq, void *p)
goto out;
}
- /* Temperature calculations */
- memcpy(&data->sensor_data[1], &data->buf[0], 3);
+ offset = 0;
/* Pressure calculations */
- memcpy(&data->sensor_data[0], &data->buf[3], 3);
+ memcpy(&data->sensor_data[offset], &data->buf[3], 3);
+
+ offset += sizeof(s32);
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ /* Temperature calculations */
+ memcpy(&data->sensor_data[offset], &data->buf[0], 3);
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -2257,8 +2678,11 @@ const struct bmp280_chip_info bmp580_chip_info = {
.chip_config = bmp580_chip_config,
.read_temp = bmp580_read_temp,
.read_press = bmp580_read_press,
+ .set_mode = bmp580_set_mode,
+ .wait_conv = bmp580_wait_conv,
.preinit = bmp580_preinit,
+ .trigger_probe = bmp580_trigger_probe,
.trigger_handler = bmp580_trigger_handler,
};
EXPORT_SYMBOL_NS(bmp580_chip_info, IIO_BMP280);
@@ -2504,6 +2928,19 @@ static int bmp180_read_press(struct bmp280_data *data, u32 *comp_press)
return 0;
}
+/* Keep compatibility with newer generations of the sensor */
+static int bmp180_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ return 0;
+}
+
+/* Keep compatibility with newer generations of the sensor */
+static int bmp180_wait_conv(struct bmp280_data *data)
+{
+ return 0;
+}
+
+/* Keep compatibility with newer generations of the sensor */
static int bmp180_chip_config(struct bmp280_data *data)
{
return 0;
@@ -2514,23 +2951,24 @@ static irqreturn_t bmp180_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- int ret, chan_value;
+ int ret, comp_temp, comp_press;
+ s32 *chans = (s32 *)data->sensor_data;
guard(mutex)(&data->lock);
- ret = bmp180_read_temp(data, &chan_value);
+ ret = bmp180_read_temp(data, &comp_temp);
if (ret)
goto out;
- data->sensor_data[1] = chan_value;
- ret = bmp180_read_press(data, &chan_value);
+ ret = bmp180_read_press(data, &comp_press);
if (ret)
goto out;
- data->sensor_data[0] = chan_value;
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -2574,6 +3012,8 @@ const struct bmp280_chip_info bmp180_chip_info = {
.read_temp = bmp180_read_temp,
.read_press = bmp180_read_press,
.read_calib = bmp180_read_calib,
+ .set_mode = bmp180_set_mode,
+ .wait_conv = bmp180_wait_conv,
.trigger_handler = bmp180_trigger_handler,
};
@@ -2588,15 +3028,18 @@ static irqreturn_t bmp085_eoc_irq(int irq, void *d)
return IRQ_HANDLED;
}
-static int bmp085_fetch_eoc_irq(struct device *dev,
- const char *name,
- int irq,
- struct bmp280_data *data)
+static int bmp085_trigger_probe(struct iio_dev *indio_dev)
{
+ struct bmp280_data *data = iio_priv(indio_dev);
+ struct device *dev = data->dev;
unsigned long irq_trig;
- int ret;
+ int ret, irq;
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
+ irq = fwnode_irq_get(dev_fwnode(dev), 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "No interrupt found.\n");
+
+ irq_trig = irq_get_trigger_type(irq);
if (irq_trig != IRQF_TRIGGER_RISING) {
dev_err(dev, "non-rising trigger given for EOC interrupt, trying to enforce it\n");
irq_trig = IRQF_TRIGGER_RISING;
@@ -2604,13 +3047,8 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
init_completion(&data->done);
- ret = devm_request_threaded_irq(dev,
- irq,
- bmp085_eoc_irq,
- NULL,
- irq_trig,
- name,
- data);
+ ret = devm_request_irq(dev, irq, bmp085_eoc_irq, irq_trig,
+ indio_dev->name, data);
if (ret) {
/* Bail out without IRQ but keep the driver in place */
dev_err(dev, "unable to request DRDY IRQ\n");
@@ -2618,14 +3056,54 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
}
data->use_eoc = true;
+
return 0;
}
+/* Identical to bmp180_chip_info + bmp085_trigger_probe */
+const struct bmp280_chip_info bmp085_chip_info = {
+ .id_reg = BMP280_REG_ID,
+ .chip_id = bmp180_chip_ids,
+ .num_chip_id = ARRAY_SIZE(bmp180_chip_ids),
+ .regmap_config = &bmp180_regmap_config,
+ .start_up_time = 2000,
+ .channels = bmp280_channels,
+ .num_channels = ARRAY_SIZE(bmp280_channels),
+ .avail_scan_masks = bmp280_avail_scan_masks,
+
+ .oversampling_temp_avail = bmp180_oversampling_temp_avail,
+ .num_oversampling_temp_avail =
+ ARRAY_SIZE(bmp180_oversampling_temp_avail),
+ .oversampling_temp_default = 0,
+
+ .oversampling_press_avail = bmp180_oversampling_press_avail,
+ .num_oversampling_press_avail =
+ ARRAY_SIZE(bmp180_oversampling_press_avail),
+ .oversampling_press_default = BMP180_MEAS_PRESS_8X,
+
+ .temp_coeffs = bmp180_temp_coeffs,
+ .temp_coeffs_type = IIO_VAL_FRACTIONAL,
+ .press_coeffs = bmp180_press_coeffs,
+ .press_coeffs_type = IIO_VAL_FRACTIONAL,
+
+ .chip_config = bmp180_chip_config,
+ .read_temp = bmp180_read_temp,
+ .read_press = bmp180_read_press,
+ .read_calib = bmp180_read_calib,
+ .set_mode = bmp180_set_mode,
+ .wait_conv = bmp180_wait_conv,
+
+ .trigger_probe = bmp085_trigger_probe,
+ .trigger_handler = bmp180_trigger_handler,
+};
+EXPORT_SYMBOL_NS(bmp085_chip_info, IIO_BMP280);
+
static int bmp280_buffer_preenable(struct iio_dev *indio_dev)
{
struct bmp280_data *data = iio_priv(indio_dev);
pm_runtime_get_sync(data->dev);
+ data->chip_info->set_mode(data, BMP280_NORMAL);
return 0;
}
@@ -2790,12 +3268,17 @@ int bmp280_common_probe(struct device *dev,
* however as it happens, the BMP085 shares the chip ID of BMP180
* so we look for an IRQ if we have that.
*/
- if (irq > 0 && (chip_id == BMP180_CHIP_ID)) {
- ret = bmp085_fetch_eoc_irq(dev, name, irq, data);
+ if (irq > 0) {
+ if (data->chip_info->trigger_probe)
+ ret = data->chip_info->trigger_probe(indio_dev);
if (ret)
return ret;
}
+ ret = data->chip_info->set_mode(data, BMP280_SLEEP);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to set sleep mode\n");
+
/* Enable runtime PM */
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
@@ -2821,6 +3304,9 @@ static int bmp280_runtime_suspend(struct device *dev)
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmp280_data *data = iio_priv(indio_dev);
+ data->chip_info->set_mode(data, BMP280_SLEEP);
+
+ fsleep(data->start_up_time);
return regulator_bulk_disable(BMP280_NUM_SUPPLIES, data->supplies);
}
@@ -2835,7 +3321,12 @@ static int bmp280_runtime_resume(struct device *dev)
return ret;
usleep_range(data->start_up_time, data->start_up_time + 100);
- return data->chip_info->chip_config(data);
+
+ ret = data->chip_info->chip_config(data);
+ if (ret)
+ return ret;
+
+ return data->chip_info->set_mode(data, data->op_mode);
}
EXPORT_RUNTIME_DEV_PM_OPS(bmp280_dev_pm_ops, bmp280_runtime_suspend,
diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c
index 5c3a63b4327c..2f7b25984c7b 100644
--- a/drivers/iio/pressure/bmp280-i2c.c
+++ b/drivers/iio/pressure/bmp280-i2c.c
@@ -27,7 +27,7 @@ static int bmp280_i2c_probe(struct i2c_client *client)
}
static const struct of_device_id bmp280_of_i2c_match[] = {
- { .compatible = "bosch,bmp085", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp085", .data = &bmp085_chip_info },
{ .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
{ .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
{ .compatible = "bosch,bme280", .data = &bme280_chip_info },
@@ -38,7 +38,7 @@ static const struct of_device_id bmp280_of_i2c_match[] = {
MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match);
static const struct i2c_device_id bmp280_i2c_id[] = {
- {"bmp085", (kernel_ulong_t)&bmp180_chip_info },
+ {"bmp085", (kernel_ulong_t)&bmp085_chip_info },
{"bmp180", (kernel_ulong_t)&bmp180_chip_info },
{"bmp280", (kernel_ulong_t)&bmp280_chip_info },
{"bme280", (kernel_ulong_t)&bme280_chip_info },
diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c
index d18549d9bb64..49aa8c2cd85b 100644
--- a/drivers/iio/pressure/bmp280-spi.c
+++ b/drivers/iio/pressure/bmp280-spi.c
@@ -114,7 +114,7 @@ static int bmp280_spi_probe(struct spi_device *spi)
}
static const struct of_device_id bmp280_of_spi_match[] = {
- { .compatible = "bosch,bmp085", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp085", .data = &bmp085_chip_info },
{ .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
{ .compatible = "bosch,bmp181", .data = &bmp180_chip_info },
{ .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
@@ -126,7 +126,7 @@ static const struct of_device_id bmp280_of_spi_match[] = {
MODULE_DEVICE_TABLE(of, bmp280_of_spi_match);
static const struct spi_device_id bmp280_spi_id[] = {
- { "bmp085", (kernel_ulong_t)&bmp180_chip_info },
+ { "bmp085", (kernel_ulong_t)&bmp085_chip_info },
{ "bmp180", (kernel_ulong_t)&bmp180_chip_info },
{ "bmp181", (kernel_ulong_t)&bmp180_chip_info },
{ "bmp280", (kernel_ulong_t)&bmp280_chip_info },
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index ccacc67c1473..2df1175b6b85 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -55,8 +55,17 @@
#define BMP580_CMD_NVM_WRITE_SEQ_1 0xA0
#define BMP580_CMD_SOFT_RESET 0xB6
+#define BMP580_INT_STATUS_DRDY_MASK BIT(0)
#define BMP580_INT_STATUS_POR_MASK BIT(4)
+#define BMP580_INT_SOURCE_DRDY BIT(0)
+
+#define BMP580_INT_CONFIG_MASK GENMASK(3, 0)
+#define BMP580_INT_CONFIG_LATCH BIT(0)
+#define BMP580_INT_CONFIG_LEVEL BIT(1)
+#define BMP580_INT_CONFIG_OPEN_DRAIN BIT(2)
+#define BMP580_INT_CONFIG_INT_EN BIT(3)
+
#define BMP580_STATUS_CORE_RDY_MASK BIT(0)
#define BMP580_STATUS_NVM_RDY_MASK BIT(1)
#define BMP580_STATUS_NVM_ERR_MASK BIT(2)
@@ -170,6 +179,19 @@
#define BMP380_MODE_FORCED 1
#define BMP380_MODE_NORMAL 3
+#define BMP380_MEAS_OFFSET 234
+#define BMP380_MEAS_DUR 2020
+#define BMP380_TEMP_MEAS_OFFSET 163
+#define BMP380_PRESS_MEAS_OFFSET 392
+
+#define BMP380_INT_STATUS_DRDY BIT(3)
+
+#define BMP380_INT_CTRL_SETTINGS_MASK GENMASK(2, 0)
+#define BMP380_INT_CTRL_OPEN_DRAIN BIT(0)
+#define BMP380_INT_CTRL_LEVEL BIT(1)
+#define BMP380_INT_CTRL_LATCH BIT(2)
+#define BMP380_INT_CTRL_DRDY_EN BIT(6)
+
#define BMP380_MIN_TEMP -4000
#define BMP380_MAX_TEMP 8500
#define BMP380_MIN_PRES 3000000
@@ -205,6 +227,10 @@
#define BMP280_REG_CONFIG 0xF5
#define BMP280_REG_CTRL_MEAS 0xF4
#define BMP280_REG_STATUS 0xF3
+#define BMP280_REG_STATUS_IM_UPDATE BIT(0)
+#define BMP280_REG_STATUS_MEAS_BIT BIT(3)
+#define BMP280_REG_RESET 0xE0
+#define BMP280_RST_SOFT_CMD 0xB6
#define BMP280_REG_COMP_TEMP_START 0x88
#define BMP280_COMP_TEMP_REG_COUNT 6
@@ -243,6 +269,10 @@
#define BMP280_MODE_FORCED 1
#define BMP280_MODE_NORMAL 3
+#define BMP280_MEAS_OFFSET 1250
+#define BMP280_MEAS_DUR 2300
+#define BMP280_PRESS_HUMID_MEAS_OFFSET 575
+
/* BME280 specific registers */
#define BME280_REG_HUMIDITY_LSB 0xFE
#define BME280_REG_HUMIDITY_MSB 0xFD
@@ -257,8 +287,13 @@
#define BME280_REG_COMP_H5 0xE5
#define BME280_REG_COMP_H6 0xE7
+#define BME280_COMP_H4_GET_MASK_UP GENMASK(15, 8)
+#define BME280_COMP_H4_PREP_MASK_UP GENMASK(11, 4)
+#define BME280_COMP_H4_MASK_LOW GENMASK(3, 0)
#define BME280_COMP_H5_MASK GENMASK(15, 4)
+#define BME280_CONTIGUOUS_CALIB_REGS 7
+
#define BME280_OSRS_HUMIDITY_MASK GENMASK(2, 0)
#define BME280_OSRS_HUMIDITY_SKIP 0
#define BME280_OSRS_HUMIDITY_1X 1
@@ -314,6 +349,7 @@
BMP280_NUM_TEMP_BYTES + \
BME280_NUM_HUMIDITY_BYTES)
+#define BME280_NUM_MAX_CHANNELS 3
/* Core exported structs */
static const char *const bmp280_supply_names[] = {
@@ -376,12 +412,21 @@ struct bmp380_calib {
s8 P11;
};
+enum bmp280_op_mode {
+ BMP280_SLEEP,
+ BMP280_FORCED,
+ BMP280_NORMAL,
+};
+
struct bmp280_data {
struct device *dev;
struct mutex lock;
struct regmap *regmap;
struct completion done;
bool use_eoc;
+ bool trig_open_drain;
+ bool trig_active_high;
+ struct iio_trigger *trig;
const struct bmp280_chip_info *chip_info;
union {
struct bmp180_calib bmp180;
@@ -411,7 +456,11 @@ struct bmp280_data {
* Data to push to userspace triggered buffer. Up to 3 channels and
* s64 timestamp, aligned.
*/
- s32 sensor_data[6] __aligned(8);
+ u8 sensor_data[ALIGN(sizeof(s32) * BME280_NUM_MAX_CHANNELS, sizeof(s64))
+ + sizeof(s64)] __aligned(sizeof(s64));
+
+ /* Value to hold the current operation mode of the device */
+ enum bmp280_op_mode op_mode;
/*
* DMA (thus cache coherency maintenance) may require the
@@ -423,6 +472,7 @@ struct bmp280_data {
/* Calibration data buffers */
__le16 bmp280_cal_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
__be16 bmp180_cal_buf[BMP180_REG_CALIB_COUNT / 2];
+ u8 bme280_humid_cal_buf[BME280_CONTIGUOUS_CALIB_REGS];
u8 bmp380_cal_buf[BMP380_CALIB_REG_COUNT];
/* Miscellaneous, endianness-aware data buffers */
__le16 le16;
@@ -476,11 +526,15 @@ struct bmp280_chip_info {
int (*read_humid)(struct bmp280_data *data, u32 *adc_humidity);
int (*read_calib)(struct bmp280_data *data);
int (*preinit)(struct bmp280_data *data);
+ int (*set_mode)(struct bmp280_data *data, enum bmp280_op_mode mode);
+ int (*wait_conv)(struct bmp280_data *data);
+ int (*trigger_probe)(struct iio_dev *indio_dev);
irqreturn_t (*trigger_handler)(int irq, void *p);
};
/* Chip infos for each variant */
+extern const struct bmp280_chip_info bmp085_chip_info;
extern const struct bmp280_chip_info bmp180_chip_info;
extern const struct bmp280_chip_info bmp280_chip_info;
extern const struct bmp280_chip_info bme280_chip_info;
diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
index 956045e2db29..dfc36430c467 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -24,7 +24,7 @@ struct press_state {
struct hid_sensor_hub_attribute_info press_attr;
struct {
u32 press_data;
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -241,11 +241,11 @@ static int press_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_press_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static const char *name = "press";
struct iio_dev *indio_dev;
struct press_state *press_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct press_state));
@@ -325,7 +325,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_press_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct press_state *press_state = iio_priv(indio_dev);
@@ -350,7 +350,7 @@ static struct platform_driver hid_press_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_press_probe,
- .remove_new = hid_press_remove,
+ .remove = hid_press_remove,
};
module_platform_driver(hid_press_platform_driver);
diff --git a/drivers/iio/pressure/rohm-bm1390.c b/drivers/iio/pressure/rohm-bm1390.c
index ccaa07a569c9..f24d9f927681 100644
--- a/drivers/iio/pressure/rohm-bm1390.c
+++ b/drivers/iio/pressure/rohm-bm1390.c
@@ -417,9 +417,6 @@ static int __bm1390_fifo_flush(struct iio_dev *idev, unsigned int samples,
return ret;
}
- if (ret)
- return ret;
-
for (i = 0; i < smp_lvl; i++) {
buffer[i].temp = temp;
iio_push_to_buffers(idev, &buffer[i]);
diff --git a/drivers/iio/proximity/aw96103.c b/drivers/iio/proximity/aw96103.c
index 707ba0a510aa..cdd254da9e50 100644
--- a/drivers/iio/proximity/aw96103.c
+++ b/drivers/iio/proximity/aw96103.c
@@ -422,7 +422,7 @@ static int aw96103_read_event_config(struct iio_dev *indio_dev,
static int aw96103_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct aw96103 *aw96103 = iio_priv(indio_dev);
diff --git a/drivers/iio/proximity/cros_ec_mkbp_proximity.c b/drivers/iio/proximity/cros_ec_mkbp_proximity.c
index c25472b14d4b..667369be0555 100644
--- a/drivers/iio/proximity/cros_ec_mkbp_proximity.c
+++ b/drivers/iio/proximity/cros_ec_mkbp_proximity.c
@@ -167,7 +167,7 @@ static int cros_ec_mkbp_proximity_read_event_config(struct iio_dev *indio_dev,
static int cros_ec_mkbp_proximity_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct cros_ec_mkbp_proximity_data *data = iio_priv(indio_dev);
@@ -261,7 +261,7 @@ static struct platform_driver cros_ec_mkbp_proximity_driver = {
.pm = pm_sleep_ptr(&cros_ec_mkbp_proximity_pm_ops),
},
.probe = cros_ec_mkbp_proximity_probe,
- .remove_new = cros_ec_mkbp_proximity_remove,
+ .remove = cros_ec_mkbp_proximity_remove,
};
module_platform_driver(cros_ec_mkbp_proximity_driver);
diff --git a/drivers/iio/proximity/hx9023s.c b/drivers/iio/proximity/hx9023s.c
index d8fb34060d3d..4021feb7a7ac 100644
--- a/drivers/iio/proximity/hx9023s.c
+++ b/drivers/iio/proximity/hx9023s.c
@@ -874,12 +874,12 @@ static int hx9023s_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct hx9023s_data *data = iio_priv(indio_dev);
if (test_bit(chan->channel, &data->chan_in_use)) {
- hx9023s_ch_en(data, chan->channel, !!state);
+ hx9023s_ch_en(data, chan->channel, state);
__assign_bit(chan->channel, &data->chan_event,
data->ch_data[chan->channel].enable);
}
diff --git a/drivers/iio/proximity/irsd200.c b/drivers/iio/proximity/irsd200.c
index 6e96b764fed8..b09d15230111 100644
--- a/drivers/iio/proximity/irsd200.c
+++ b/drivers/iio/proximity/irsd200.c
@@ -648,7 +648,8 @@ static int irsd200_read_event_config(struct iio_dev *indio_dev,
static int irsd200_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct irsd200_data *data = iio_priv(indio_dev);
unsigned int tmp;
@@ -662,7 +663,7 @@ static int irsd200_write_event_config(struct iio_dev *indio_dev,
return ret;
return regmap_field_write(
- data->regfields[IRS_REGF_INTR_COUNT_THR_OR], !!state);
+ data->regfields[IRS_REGF_INTR_COUNT_THR_OR], state);
default:
return -EINVAL;
}
diff --git a/drivers/iio/proximity/srf04.c b/drivers/iio/proximity/srf04.c
index 86c57672fc7e..71ad29e441b2 100644
--- a/drivers/iio/proximity/srf04.c
+++ b/drivers/iio/proximity/srf04.c
@@ -389,7 +389,7 @@ static const struct dev_pm_ops srf04_pm_ops = {
static struct platform_driver srf04_driver = {
.probe = srf04_probe,
- .remove_new = srf04_remove,
+ .remove = srf04_remove,
.driver = {
.name = "srf04-gpio",
.of_match_table = of_srf04_match,
diff --git a/drivers/iio/proximity/sx9324.c b/drivers/iio/proximity/sx9324.c
index 629f83c37d59..40747d7f6e7e 100644
--- a/drivers/iio/proximity/sx9324.c
+++ b/drivers/iio/proximity/sx9324.c
@@ -868,6 +868,26 @@ static u8 sx9324_parse_phase_prop(struct device *dev,
return raw;
}
+static void sx_common_get_raw_register_config(struct device *dev,
+ struct sx_common_reg_default *reg_def)
+{
+#ifdef CONFIG_ACPI
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+ u32 raw = 0, ret;
+ char prop[80];
+
+ if (!reg_def->property || !adev)
+ return;
+
+ snprintf(prop, ARRAY_SIZE(prop), "%s,reg_%s", acpi_device_hid(adev), reg_def->property);
+ ret = device_property_read_u32(dev, prop, &raw);
+ if (ret)
+ return;
+
+ reg_def->def = raw;
+#endif
+}
+
static const struct sx_common_reg_default *
sx9324_get_default_reg(struct device *dev, int idx,
struct sx_common_reg_default *reg_def)
diff --git a/drivers/iio/proximity/sx9360.c b/drivers/iio/proximity/sx9360.c
index 2b90bf45a201..07551e0decbd 100644
--- a/drivers/iio/proximity/sx9360.c
+++ b/drivers/iio/proximity/sx9360.c
@@ -7,7 +7,6 @@
* https://edit.wpgdadawant.com/uploads/news_file/program/2019/30184/tech_files/program_30184_suggest_other_file.pdf
*/
-#include <linux/acpi.h>
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/delay.h>
diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c
index 3f4eace05cfc..c4e94d0fb163 100644
--- a/drivers/iio/proximity/sx9500.c
+++ b/drivers/iio/proximity/sx9500.c
@@ -540,7 +540,7 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct sx9500_data *data = iio_priv(indio_dev);
int ret;
@@ -551,7 +551,7 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev,
mutex_lock(&data->mutex);
- if (state == 1) {
+ if (state) {
ret = sx9500_inc_chan_users(data, chan->channel);
if (ret < 0)
goto out_unlock;
@@ -571,7 +571,7 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev,
goto out_unlock;
out_undo_chan:
- if (state == 1)
+ if (state)
sx9500_dec_chan_users(data, chan->channel);
else
sx9500_inc_chan_users(data, chan->channel);
diff --git a/drivers/iio/proximity/sx_common.c b/drivers/iio/proximity/sx_common.c
index 71aa6dced7d3..76384c74fe01 100644
--- a/drivers/iio/proximity/sx_common.c
+++ b/drivers/iio/proximity/sx_common.c
@@ -268,7 +268,7 @@ EXPORT_SYMBOL_NS_GPL(sx_common_read_event_config, SEMTECH_PROX);
int sx_common_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct sx_common_data *data = iio_priv(indio_dev);
unsigned int eventirq = SX_COMMON_FAR_IRQ | SX_COMMON_CLOSE_IRQ;
@@ -421,27 +421,6 @@ static const struct iio_buffer_setup_ops sx_common_buffer_setup_ops = {
.postdisable = sx_common_buffer_postdisable,
};
-void sx_common_get_raw_register_config(struct device *dev,
- struct sx_common_reg_default *reg_def)
-{
-#ifdef CONFIG_ACPI
- struct acpi_device *adev = ACPI_COMPANION(dev);
- u32 raw = 0, ret;
- char prop[80];
-
- if (!reg_def->property || !adev)
- return;
-
- snprintf(prop, ARRAY_SIZE(prop), "%s,reg_%s", acpi_device_hid(adev), reg_def->property);
- ret = device_property_read_u32(dev, prop, &raw);
- if (ret)
- return;
-
- reg_def->def = raw;
-#endif
-}
-EXPORT_SYMBOL_NS_GPL(sx_common_get_raw_register_config, SEMTECH_PROX);
-
#define SX_COMMON_SOFT_RESET 0xde
static int sx_common_init_device(struct device *dev, struct iio_dev *indio_dev)
diff --git a/drivers/iio/proximity/sx_common.h b/drivers/iio/proximity/sx_common.h
index 101b90e52ff2..fb14e6f06a6d 100644
--- a/drivers/iio/proximity/sx_common.h
+++ b/drivers/iio/proximity/sx_common.h
@@ -8,7 +8,6 @@
#ifndef IIO_SX_COMMON_H
#define IIO_SX_COMMON_H
-#include <linux/acpi.h>
#include <linux/iio/iio.h>
#include <linux/iio/types.h>
#include <linux/regulator/consumer.h>
@@ -144,15 +143,12 @@ int sx_common_read_event_config(struct iio_dev *indio_dev,
int sx_common_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state);
+ enum iio_event_direction dir, bool state);
int sx_common_probe(struct i2c_client *client,
const struct sx_common_chip_info *chip_info,
const struct regmap_config *regmap_config);
-void sx_common_get_raw_register_config(struct device *dev,
- struct sx_common_reg_default *reg_def);
-
/* 3 is the number of events defined by a single phase. */
extern const struct iio_event_spec sx_common_events[3];
diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c
index d1ddf85f5383..bb6c9cc88b35 100644
--- a/drivers/iio/proximity/vcnl3020.c
+++ b/drivers/iio/proximity/vcnl3020.c
@@ -449,7 +449,7 @@ static int vcnl3020_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
switch (chan->type) {
case IIO_PROXIMITY:
diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c
index 8d4f3f849fe2..87d10faaff9b 100644
--- a/drivers/iio/proximity/vl53l0x-i2c.c
+++ b/drivers/iio/proximity/vl53l0x-i2c.c
@@ -20,8 +20,13 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/unaligned.h>
#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#define VL_REG_SYSRANGE_START 0x00
@@ -39,21 +44,74 @@
#define VL_REG_RESULT_INT_STATUS 0x13
#define VL_REG_RESULT_RANGE_STATUS 0x14
+#define VL_REG_IDENTIFICATION_MODEL_ID 0xC0
#define VL_REG_RESULT_RANGE_STATUS_COMPLETE BIT(0)
+#define VL53L0X_MODEL_ID_VAL 0xEE
+#define VL53L0X_CONTINUOUS_MODE 0x02
+#define VL53L0X_SINGLE_MODE 0x01
+
struct vl53l0x_data {
struct i2c_client *client;
struct completion completion;
struct regulator *vdd_supply;
struct gpio_desc *reset_gpio;
+ struct iio_trigger *trig;
+
+ struct {
+ u16 chan;
+ aligned_s64 timestamp;
+ } scan;
};
-static irqreturn_t vl53l0x_handle_irq(int irq, void *priv)
+static int vl53l0x_clear_irq(struct vl53l0x_data *data)
+{ int ret;
+
+ ret = i2c_smbus_write_byte_data(data->client,
+ VL_REG_SYSTEM_INTERRUPT_CLEAR, 1);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "failed to clear irq: %d\n", ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static irqreturn_t vl53l0x_trigger_handler(int irq, void *priv)
+{
+ struct iio_poll_func *pf = priv;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct vl53l0x_data *data = iio_priv(indio_dev);
+ u8 buffer[12];
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(data->client,
+ VL_REG_RESULT_RANGE_STATUS,
+ sizeof(buffer), buffer);
+ if (ret < 0)
+ return ret;
+ else if (ret != 12)
+ return -EREMOTEIO;
+
+ data->scan.chan = get_unaligned_be16(&buffer[10]);
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
+ iio_get_time_ns(indio_dev));
+
+ iio_trigger_notify_done(indio_dev->trig);
+ vl53l0x_clear_irq(data);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t vl53l0x_threaded_irq(int irq, void *priv)
{
struct iio_dev *indio_dev = priv;
struct vl53l0x_data *data = iio_priv(indio_dev);
- complete(&data->completion);
+ if (iio_buffer_enabled(indio_dev))
+ iio_trigger_poll_nested(indio_dev->trig);
+ else
+ complete(&data->completion);
return IRQ_HANDLED;
}
@@ -68,8 +126,9 @@ static int vl53l0x_configure_irq(struct i2c_client *client,
if (!irq_flags)
irq_flags = IRQF_TRIGGER_FALLING;
- ret = devm_request_irq(&client->dev, client->irq, vl53l0x_handle_irq,
- irq_flags, indio_dev->name, indio_dev);
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, vl53l0x_threaded_irq,
+ irq_flags | IRQF_ONESHOT, indio_dev->name, indio_dev);
if (ret) {
dev_err(&client->dev, "devm_request_irq error: %d\n", ret);
return ret;
@@ -84,26 +143,6 @@ static int vl53l0x_configure_irq(struct i2c_client *client,
return ret;
}
-static void vl53l0x_clear_irq(struct vl53l0x_data *data)
-{
- struct device *dev = &data->client->dev;
- int ret;
-
- ret = i2c_smbus_write_byte_data(data->client,
- VL_REG_SYSTEM_INTERRUPT_CLEAR, 1);
- if (ret < 0)
- dev_err(dev, "failed to clear error irq: %d\n", ret);
-
- ret = i2c_smbus_write_byte_data(data->client,
- VL_REG_SYSTEM_INTERRUPT_CLEAR, 0);
- if (ret < 0)
- dev_err(dev, "failed to clear range irq: %d\n", ret);
-
- ret = i2c_smbus_read_byte_data(data->client, VL_REG_RESULT_INT_STATUS);
- if (ret < 0 || ret & 0x07)
- dev_err(dev, "failed to clear irq: %d\n", ret);
-}
-
static int vl53l0x_read_proximity(struct vl53l0x_data *data,
const struct iio_chan_spec *chan,
int *val)
@@ -125,7 +164,9 @@ static int vl53l0x_read_proximity(struct vl53l0x_data *data,
if (time_left == 0)
return -ETIMEDOUT;
- vl53l0x_clear_irq(data);
+ ret = vl53l0x_clear_irq(data);
+ if (ret < 0)
+ return ret;
} else {
do {
ret = i2c_smbus_read_byte_data(client,
@@ -150,7 +191,7 @@ static int vl53l0x_read_proximity(struct vl53l0x_data *data,
return -EREMOTEIO;
/* Values should be between 30~1200 in millimeters. */
- *val = (buffer[10] << 8) + buffer[11];
+ *val = get_unaligned_be16(&buffer[10]);
return 0;
}
@@ -160,7 +201,14 @@ static const struct iio_chan_spec vl53l0x_channels[] = {
.type = IIO_DISTANCE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
},
+ IIO_CHAN_SOFT_TIMESTAMP(1),
};
static int vl53l0x_read_raw(struct iio_dev *indio_dev,
@@ -190,8 +238,16 @@ static int vl53l0x_read_raw(struct iio_dev *indio_dev,
}
}
+static int vl53l0x_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig)
+{
+ struct vl53l0x_data *data = iio_priv(indio_dev);
+
+ return data->trig == trig ? 0 : -EINVAL;
+}
+
static const struct iio_info vl53l0x_info = {
.read_raw = vl53l0x_read_raw,
+ .validate_trigger = vl53l0x_validate_trigger,
};
static void vl53l0x_power_off(void *_data)
@@ -218,11 +274,46 @@ static int vl53l0x_power_on(struct vl53l0x_data *data)
return 0;
}
+static int vl53l0x_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct vl53l0x_data *data = iio_priv(indio_dev);
+
+ return i2c_smbus_write_byte_data(data->client, VL_REG_SYSRANGE_START,
+ VL53L0X_CONTINUOUS_MODE);
+}
+
+static int vl53l0x_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct vl53l0x_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(data->client, VL_REG_SYSRANGE_START,
+ VL53L0X_SINGLE_MODE);
+ if (ret < 0)
+ return ret;
+
+ /* Let the ongoing reading finish */
+ reinit_completion(&data->completion);
+ wait_for_completion_timeout(&data->completion, HZ / 10);
+
+ return vl53l0x_clear_irq(data);
+}
+
+static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
+ .postenable = &vl53l0x_buffer_postenable,
+ .postdisable = &vl53l0x_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops vl53l0x_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
+};
+
static int vl53l0x_probe(struct i2c_client *client)
{
struct vl53l0x_data *data;
struct iio_dev *indio_dev;
int error;
+ int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -237,6 +328,13 @@ static int vl53l0x_probe(struct i2c_client *client)
I2C_FUNC_SMBUS_BYTE_DATA))
return -EOPNOTSUPP;
+ ret = i2c_smbus_read_byte_data(data->client, VL_REG_IDENTIFICATION_MODEL_ID);
+ if (ret < 0)
+ return -EINVAL;
+
+ if (ret != VL53L0X_MODEL_ID_VAL)
+ dev_info(&client->dev, "Unknown model id: 0x%x", ret);
+
data->vdd_supply = devm_regulator_get(&client->dev, "vdd");
if (IS_ERR(data->vdd_supply))
return dev_err_probe(&client->dev, PTR_ERR(data->vdd_supply),
@@ -265,13 +363,33 @@ static int vl53l0x_probe(struct i2c_client *client)
/* usage of interrupt is optional */
if (client->irq) {
- int ret;
-
init_completion(&data->completion);
+ data->trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->ops = &vl53l0x_trigger_ops;
+ iio_trigger_set_drvdata(data->trig, indio_dev);
+ ret = devm_iio_trigger_register(&client->dev, data->trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(data->trig);
+
ret = vl53l0x_configure_irq(client, indio_dev);
if (ret)
return ret;
+
+ ret = devm_iio_triggered_buffer_setup(&client->dev,
+ indio_dev,
+ NULL,
+ &vl53l0x_trigger_handler,
+ &iio_triggered_buffer_setup_ops);
+ if (ret)
+ return ret;
}
return devm_iio_device_register(&client->dev, indio_dev);
diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig
index ed0e4963362f..1244d8e17d50 100644
--- a/drivers/iio/temperature/Kconfig
+++ b/drivers/iio/temperature/Kconfig
@@ -91,6 +91,8 @@ config MLX90635
config TMP006
tristate "TMP006 infrared thermopile sensor"
depends on I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
help
If you say yes here you get support for the Texas Instruments
TMP006 infrared thermopile sensor.
diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
index 0143fd478933..0e21217472ab 100644
--- a/drivers/iio/temperature/hid-sensor-temperature.c
+++ b/drivers/iio/temperature/hid-sensor-temperature.c
@@ -18,7 +18,7 @@ struct temperature_state {
struct hid_sensor_hub_attribute_info temperature_attr;
struct {
s32 temperature_data;
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -283,7 +283,7 @@ static struct platform_driver hid_temperature_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_temperature_probe,
- .remove_new = hid_temperature_remove,
+ .remove = hid_temperature_remove,
};
module_platform_driver(hid_temperature_platform_driver);
diff --git a/drivers/iio/temperature/mcp9600.c b/drivers/iio/temperature/mcp9600.c
index f1bb0976273d..c2447860adfd 100644
--- a/drivers/iio/temperature/mcp9600.c
+++ b/drivers/iio/temperature/mcp9600.c
@@ -200,7 +200,7 @@ static int mcp9600_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct mcp9600_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c
index 6d8d661f0c82..0c844137d7aa 100644
--- a/drivers/iio/temperature/tmp006.c
+++ b/drivers/iio/temperature/tmp006.c
@@ -7,8 +7,6 @@
* Driver for the Texas Instruments I2C 16-bit IR thermopile sensor
*
* (7-bit I2C slave address 0x40, changeable via ADR pins)
- *
- * TODO: data ready irq
*/
#include <linux/err.h>
@@ -21,6 +19,9 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
#define TMP006_VOBJECT 0x00
#define TMP006_TAMBIENT 0x01
@@ -45,6 +46,7 @@
struct tmp006_data {
struct i2c_client *client;
u16 config;
+ struct iio_trigger *drdy_trig;
};
static int tmp006_read_measurement(struct tmp006_data *data, u8 reg)
@@ -83,15 +85,19 @@ static int tmp006_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_RAW:
if (channel->type == IIO_VOLTAGE) {
/* LSB is 156.25 nV */
- ret = tmp006_read_measurement(data, TMP006_VOBJECT);
- if (ret < 0)
- return ret;
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ ret = tmp006_read_measurement(data, TMP006_VOBJECT);
+ if (ret < 0)
+ return ret;
+ }
*val = sign_extend32(ret, 15);
} else if (channel->type == IIO_TEMP) {
/* LSB is 0.03125 degrees Celsius */
- ret = tmp006_read_measurement(data, TMP006_TAMBIENT);
- if (ret < 0)
- return ret;
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ ret = tmp006_read_measurement(data, TMP006_TAMBIENT);
+ if (ret < 0)
+ return ret;
+ }
*val = sign_extend32(ret, 15) >> TMP006_TAMBIENT_SHIFT;
} else {
break;
@@ -128,7 +134,7 @@ static int tmp006_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct tmp006_data *data = iio_priv(indio_dev);
- int i;
+ int ret, i;
if (mask != IIO_CHAN_INFO_SAMP_FREQ)
return -EINVAL;
@@ -136,13 +142,19 @@ static int tmp006_write_raw(struct iio_dev *indio_dev,
for (i = 0; i < ARRAY_SIZE(tmp006_freqs); i++)
if ((val == tmp006_freqs[i][0]) &&
(val2 == tmp006_freqs[i][1])) {
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
data->config &= ~TMP006_CONFIG_CR_MASK;
data->config |= i << TMP006_CONFIG_CR_SHIFT;
- return i2c_smbus_write_word_swapped(data->client,
- TMP006_CONFIG,
- data->config);
+ ret = i2c_smbus_write_word_swapped(data->client,
+ TMP006_CONFIG,
+ data->config);
+ iio_device_release_direct_mode(indio_dev);
+ return ret;
}
return -EINVAL;
}
@@ -164,13 +176,29 @@ static const struct iio_chan_spec tmp006_channels[] = {
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_BE,
+ }
},
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
- }
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ .shift = TMP006_TAMBIENT_SHIFT,
+ .endianness = IIO_BE,
+ }
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(2),
};
static const struct iio_info tmp006_info = {
@@ -213,6 +241,54 @@ static void tmp006_powerdown_cleanup(void *dev)
tmp006_power(dev, false);
}
+static irqreturn_t tmp006_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct tmp006_data *data = iio_priv(indio_dev);
+ struct {
+ s16 channels[2];
+ s64 ts __aligned(8);
+ } scan;
+ s32 ret;
+
+ ret = i2c_smbus_read_word_data(data->client, TMP006_VOBJECT);
+ if (ret < 0)
+ goto err;
+ scan.channels[0] = ret;
+
+ ret = i2c_smbus_read_word_data(data->client, TMP006_TAMBIENT);
+ if (ret < 0)
+ goto err;
+ scan.channels[1] = ret;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &scan,
+ iio_get_time_ns(indio_dev));
+err:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int tmp006_set_trigger_state(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct tmp006_data *data = iio_priv(indio_dev);
+
+ if (state)
+ data->config |= TMP006_CONFIG_DRDY_EN;
+ else
+ data->config &= ~TMP006_CONFIG_DRDY_EN;
+
+ return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG,
+ data->config);
+}
+
+static const struct iio_trigger_ops tmp006_trigger_ops = {
+ .set_trigger_state = tmp006_set_trigger_state,
+};
+
+static const unsigned long tmp006_scan_masks[] = { 0x3, 0 };
+
static int tmp006_probe(struct i2c_client *client)
{
struct iio_dev *indio_dev;
@@ -241,6 +317,7 @@ static int tmp006_probe(struct i2c_client *client)
indio_dev->channels = tmp006_channels;
indio_dev->num_channels = ARRAY_SIZE(tmp006_channels);
+ indio_dev->available_scan_masks = tmp006_scan_masks;
ret = i2c_smbus_read_word_swapped(data->client, TMP006_CONFIG);
if (ret < 0)
@@ -258,6 +335,37 @@ static int tmp006_probe(struct i2c_client *client)
if (ret < 0)
return ret;
+ if (client->irq > 0) {
+ data->drdy_trig = devm_iio_trigger_alloc(&client->dev,
+ "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!data->drdy_trig)
+ return -ENOMEM;
+
+ data->drdy_trig->ops = &tmp006_trigger_ops;
+ iio_trigger_set_drvdata(data->drdy_trig, indio_dev);
+ ret = iio_trigger_register(data->drdy_trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(data->drdy_trig);
+
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ iio_trigger_generic_data_rdy_poll,
+ NULL,
+ IRQF_ONESHOT,
+ "tmp006_irq",
+ data->drdy_trig);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
+ tmp006_trigger_handler, NULL);
+ if (ret < 0)
+ return ret;
+
return devm_iio_device_register(&client->dev, indio_dev);
}
diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c
index 9bdfa9423492..fd4d389ce1df 100644
--- a/drivers/iio/temperature/tmp007.c
+++ b/drivers/iio/temperature/tmp007.c
@@ -216,7 +216,7 @@ static irqreturn_t tmp007_interrupt_handler(int irq, void *private)
static int tmp007_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct tmp007_data *data = iio_priv(indio_dev);
unsigned int status_mask;
diff --git a/drivers/iio/trigger/iio-trig-interrupt.c b/drivers/iio/trigger/iio-trig-interrupt.c
index dec256bfbd73..21c6b6292a72 100644
--- a/drivers/iio/trigger/iio-trig-interrupt.c
+++ b/drivers/iio/trigger/iio-trig-interrupt.c
@@ -96,7 +96,7 @@ static void iio_interrupt_trigger_remove(struct platform_device *pdev)
static struct platform_driver iio_interrupt_trigger_driver = {
.probe = iio_interrupt_trigger_probe,
- .remove_new = iio_interrupt_trigger_remove,
+ .remove = iio_interrupt_trigger_remove,
.driver = {
.name = "iio_interrupt_trigger",
},
diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c
index 0684329956d9..bb60b2d7b2ec 100644
--- a/drivers/iio/trigger/stm32-timer-trigger.c
+++ b/drivers/iio/trigger/stm32-timer-trigger.c
@@ -900,7 +900,7 @@ MODULE_DEVICE_TABLE(of, stm32_trig_of_match);
static struct platform_driver stm32_timer_trigger_driver = {
.probe = stm32_timer_trigger_probe,
- .remove_new = stm32_timer_trigger_remove,
+ .remove = stm32_timer_trigger_remove,
.driver = {
.name = "stm32-timer-trigger",
.of_match_table = stm32_trig_of_match,
diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c
index 53ec7510e4eb..ba2cd68b53e6 100644
--- a/drivers/infiniband/hw/qib/qib_sysfs.c
+++ b/drivers/infiniband/hw/qib/qib_sysfs.c
@@ -283,7 +283,7 @@ static struct bin_attribute *port_ccmgta_attributes[] = {
};
static umode_t qib_ccmgta_is_bin_visible(struct kobject *kobj,
- struct bin_attribute *attr, int n)
+ const struct bin_attribute *attr, int n)
{
struct qib_pportdata *ppd = qib_get_pportdata_kobj(kobj);
diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 7e9b996b47c8..9d5404a07e8a 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -808,7 +808,7 @@ void icc_put(struct icc_path *path)
mutex_unlock(&icc_bw_lock);
mutex_unlock(&icc_lock);
- kfree_const(path->name);
+ kfree(path->name);
kfree(path);
}
EXPORT_SYMBOL_GPL(icc_put);
@@ -1081,7 +1081,7 @@ static int of_count_icc_providers(struct device_node *np)
int count = 0;
for_each_available_child_of_node(np, child) {
- if (of_property_read_bool(child, "#interconnect-cells") &&
+ if (of_property_present(child, "#interconnect-cells") &&
likely(!of_match_node(ignore_list, child)))
count++;
count += of_count_icc_providers(child);
diff --git a/drivers/interconnect/imx/imx8mm.c b/drivers/interconnect/imx/imx8mm.c
index a36aaaf106ae..efed12d635c1 100644
--- a/drivers/interconnect/imx/imx8mm.c
+++ b/drivers/interconnect/imx/imx8mm.c
@@ -88,7 +88,7 @@ static int imx8mm_icc_probe(struct platform_device *pdev)
static struct platform_driver imx8mm_icc_driver = {
.probe = imx8mm_icc_probe,
- .remove_new = imx_icc_unregister,
+ .remove = imx_icc_unregister,
.driver = {
.name = "imx8mm-interconnect",
},
diff --git a/drivers/interconnect/imx/imx8mn.c b/drivers/interconnect/imx/imx8mn.c
index 2a97c74e875b..535fae791f2e 100644
--- a/drivers/interconnect/imx/imx8mn.c
+++ b/drivers/interconnect/imx/imx8mn.c
@@ -77,7 +77,7 @@ static int imx8mn_icc_probe(struct platform_device *pdev)
static struct platform_driver imx8mn_icc_driver = {
.probe = imx8mn_icc_probe,
- .remove_new = imx_icc_unregister,
+ .remove = imx_icc_unregister,
.driver = {
.name = "imx8mn-interconnect",
},
diff --git a/drivers/interconnect/imx/imx8mp.c b/drivers/interconnect/imx/imx8mp.c
index 86d4c1517b26..c5751ed18d51 100644
--- a/drivers/interconnect/imx/imx8mp.c
+++ b/drivers/interconnect/imx/imx8mp.c
@@ -241,7 +241,7 @@ static int imx8mp_icc_probe(struct platform_device *pdev)
static struct platform_driver imx8mp_icc_driver = {
.probe = imx8mp_icc_probe,
- .remove_new = imx_icc_unregister,
+ .remove = imx_icc_unregister,
.driver = {
.name = "imx8mp-interconnect",
},
diff --git a/drivers/interconnect/imx/imx8mq.c b/drivers/interconnect/imx/imx8mq.c
index f817d24aeefb..6aa4f06b4676 100644
--- a/drivers/interconnect/imx/imx8mq.c
+++ b/drivers/interconnect/imx/imx8mq.c
@@ -87,7 +87,7 @@ static int imx8mq_icc_probe(struct platform_device *pdev)
static struct platform_driver imx8mq_icc_driver = {
.probe = imx8mq_icc_probe,
- .remove_new = imx_icc_unregister,
+ .remove = imx_icc_unregister,
.driver = {
.name = "imx8mq-interconnect",
.sync_state = icc_sync_state,
diff --git a/drivers/interconnect/mediatek/mt8183.c b/drivers/interconnect/mediatek/mt8183.c
index 24245085c7a9..c212e79334cf 100644
--- a/drivers/interconnect/mediatek/mt8183.c
+++ b/drivers/interconnect/mediatek/mt8183.c
@@ -133,7 +133,7 @@ static struct platform_driver mtk_emi_icc_mt8183_driver = {
.sync_state = icc_sync_state,
},
.probe = mtk_emi_icc_probe,
- .remove_new = mtk_emi_icc_remove,
+ .remove = mtk_emi_icc_remove,
};
module_platform_driver(mtk_emi_icc_mt8183_driver);
diff --git a/drivers/interconnect/mediatek/mt8195.c b/drivers/interconnect/mediatek/mt8195.c
index 710e14c5447c..3ca23469ab18 100644
--- a/drivers/interconnect/mediatek/mt8195.c
+++ b/drivers/interconnect/mediatek/mt8195.c
@@ -329,7 +329,7 @@ static struct platform_driver mtk_emi_icc_mt8195_driver = {
.sync_state = icc_sync_state,
},
.probe = mtk_emi_icc_probe,
- .remove_new = mtk_emi_icc_remove,
+ .remove = mtk_emi_icc_remove,
};
module_platform_driver(mtk_emi_icc_mt8195_driver);
diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig
index de96d4661340..362fb9b0a198 100644
--- a/drivers/interconnect/qcom/Kconfig
+++ b/drivers/interconnect/qcom/Kconfig
@@ -105,6 +105,26 @@ config INTERCONNECT_QCOM_QCS404
This is a driver for the Qualcomm Network-on-Chip on qcs404-based
platforms.
+config INTERCONNECT_QCOM_QCS615
+ tristate "Qualcomm QCS615 interconnect driver"
+ depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
+ select INTERCONNECT_QCOM_RPMH
+ select INTERCONNECT_QCOM_BCM_VOTER
+ help
+ This is a driver for the Qualcomm Network-on-Chip on qcs615-based
+ platforms.
+
+config INTERCONNECT_QCOM_QCS8300
+ tristate "Qualcomm QCS8300 interconnect driver"
+ depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
+ select INTERCONNECT_QCOM_RPMH
+ select INTERCONNECT_QCOM_BCM_VOTER
+ help
+ This is a driver for the Qualcomm Technologies, Inc. Network-on-Chip
+ on QCS8300-based platforms. The interconnect provider collects and
+ aggreagates the cosumer bandwidth requests to satisfy constraints
+ placed on Network-on-Chip performance states.
+
config INTERCONNECT_QCOM_QDU1000
tristate "Qualcomm QDU1000/QRU1000 interconnect driver"
depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
@@ -137,6 +157,15 @@ config INTERCONNECT_QCOM_SA8775P
This is a driver for the Qualcomm Network-on-Chip on sa8775p-based
platforms.
+config INTERCONNECT_QCOM_SAR2130P
+ tristate "Qualcomm SAR2130P interconnect driver"
+ depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
+ select INTERCONNECT_QCOM_RPMH
+ select INTERCONNECT_QCOM_BCM_VOTER
+ help
+ This is a driver for the Qualcomm Network-on-Chip on SAR2130P-based
+ platforms.
+
config INTERCONNECT_QCOM_SC7180
tristate "Qualcomm SC7180 interconnect driver"
depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile
index bfeea8416fcf..9997728c02bf 100644
--- a/drivers/interconnect/qcom/Makefile
+++ b/drivers/interconnect/qcom/Makefile
@@ -15,9 +15,12 @@ qnoc-msm8996-objs := msm8996.o
icc-osm-l3-objs := osm-l3.o
qnoc-qcm2290-objs := qcm2290.o
qnoc-qcs404-objs := qcs404.o
+qnoc-qcs615-objs := qcs615.o
+qnoc-qcs8300-objs := qcs8300.o
qnoc-qdu1000-objs := qdu1000.o
icc-rpmh-obj := icc-rpmh.o
qnoc-sa8775p-objs := sa8775p.o
+qnoc-sar2130p-objs := sar2130p.o
qnoc-sc7180-objs := sc7180.o
qnoc-sc7280-objs := sc7280.o
qnoc-sc8180x-objs := sc8180x.o
@@ -52,9 +55,12 @@ obj-$(CONFIG_INTERCONNECT_QCOM_MSM8996) += qnoc-msm8996.o
obj-$(CONFIG_INTERCONNECT_QCOM_OSM_L3) += icc-osm-l3.o
obj-$(CONFIG_INTERCONNECT_QCOM_QCM2290) += qnoc-qcm2290.o
obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o
+obj-$(CONFIG_INTERCONNECT_QCOM_QCS615) += qnoc-qcs615.o
+obj-$(CONFIG_INTERCONNECT_QCOM_QCS8300) += qnoc-qcs8300.o
obj-$(CONFIG_INTERCONNECT_QCOM_QDU1000) += qnoc-qdu1000.o
obj-$(CONFIG_INTERCONNECT_QCOM_RPMH) += icc-rpmh.o
obj-$(CONFIG_INTERCONNECT_QCOM_SA8775P) += qnoc-sa8775p.o
+obj-$(CONFIG_INTERCONNECT_QCOM_SAR2130P) += qnoc-sar2130p.o
obj-$(CONFIG_INTERCONNECT_QCOM_SC7180) += qnoc-sc7180.o
obj-$(CONFIG_INTERCONNECT_QCOM_SC7280) += qnoc-sc7280.o
obj-$(CONFIG_INTERCONNECT_QCOM_SC8180X) += qnoc-sc8180x.o
diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c
index f49a8e0cb03c..f2d63745be54 100644
--- a/drivers/interconnect/qcom/icc-rpmh.c
+++ b/drivers/interconnect/qcom/icc-rpmh.c
@@ -311,7 +311,10 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
}
qp->num_clks = devm_clk_bulk_get_all(qp->dev, &qp->clks);
- if (qp->num_clks < 0 || (!qp->num_clks && desc->qos_clks_required)) {
+ if (qp->num_clks == -EPROBE_DEFER)
+ return dev_err_probe(dev, qp->num_clks, "Failed to get QoS clocks\n");
+
+ if (qp->num_clks < 0 || (!qp->num_clks && desc->qos_requires_clocks)) {
dev_info(dev, "Skipping QoS, failed to get clk: %d\n", qp->num_clks);
goto skip_qos_config;
}
diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h
index 14db89850fb3..82344c734091 100644
--- a/drivers/interconnect/qcom/icc-rpmh.h
+++ b/drivers/interconnect/qcom/icc-rpmh.h
@@ -153,7 +153,7 @@ struct qcom_icc_desc {
size_t num_nodes;
struct qcom_icc_bcm * const *bcms;
size_t num_bcms;
- bool qos_clks_required;
+ bool qos_requires_clocks;
};
int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
diff --git a/drivers/interconnect/qcom/msm8909.c b/drivers/interconnect/qcom/msm8909.c
index 0d0cd7282f5b..dd656ce7b64d 100644
--- a/drivers/interconnect/qcom/msm8909.c
+++ b/drivers/interconnect/qcom/msm8909.c
@@ -1316,7 +1316,7 @@ MODULE_DEVICE_TABLE(of, msm8909_noc_of_match);
static struct platform_driver msm8909_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8909",
.of_match_table = msm8909_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8916.c b/drivers/interconnect/qcom/msm8916.c
index 499b1a9ac413..35148880b3e8 100644
--- a/drivers/interconnect/qcom/msm8916.c
+++ b/drivers/interconnect/qcom/msm8916.c
@@ -1344,7 +1344,7 @@ MODULE_DEVICE_TABLE(of, msm8916_noc_of_match);
static struct platform_driver msm8916_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8916",
.of_match_table = msm8916_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8937.c b/drivers/interconnect/qcom/msm8937.c
index 052b14c28ef8..58533d00266b 100644
--- a/drivers/interconnect/qcom/msm8937.c
+++ b/drivers/interconnect/qcom/msm8937.c
@@ -1175,7 +1175,7 @@ static struct qcom_icc_node slv_lpass = {
.qos.qos_mode = NOC_QOS_MODE_INVALID,
};
-static struct qcom_icc_node *msm8937_bimc_nodes[] = {
+static struct qcom_icc_node * const msm8937_bimc_nodes[] = {
[MAS_APPS_PROC] = &mas_apps_proc,
[MAS_OXILI] = &mas_oxili,
[MAS_SNOC_BIMC_0] = &mas_snoc_bimc_0,
@@ -1204,7 +1204,7 @@ static const struct qcom_icc_desc msm8937_bimc = {
.ab_coeff = 154,
};
-static struct qcom_icc_node *msm8937_pcnoc_nodes[] = {
+static struct qcom_icc_node * const msm8937_pcnoc_nodes[] = {
[MAS_SPDM] = &mas_spdm,
[MAS_BLSP_1] = &mas_blsp_1,
[MAS_BLSP_2] = &mas_blsp_2,
@@ -1268,7 +1268,7 @@ static const struct qcom_icc_desc msm8937_pcnoc = {
.regmap_cfg = &msm8937_pcnoc_regmap_config,
};
-static struct qcom_icc_node *msm8937_snoc_nodes[] = {
+static struct qcom_icc_node * const msm8937_snoc_nodes[] = {
[MAS_QDSS_BAM] = &mas_qdss_bam,
[MAS_BIMC_SNOC] = &mas_bimc_snoc,
[MAS_PCNOC_SNOC] = &mas_pcnoc_snoc,
@@ -1304,7 +1304,7 @@ static const struct qcom_icc_desc msm8937_snoc = {
.qos_offset = 0x7000,
};
-static struct qcom_icc_node *msm8937_snoc_mm_nodes[] = {
+static struct qcom_icc_node * const msm8937_snoc_mm_nodes[] = {
[MAS_JPEG] = &mas_jpeg,
[MAS_MDP] = &mas_mdp,
[MAS_VENUS] = &mas_venus,
@@ -1337,7 +1337,7 @@ MODULE_DEVICE_TABLE(of, msm8937_noc_of_match);
static struct platform_driver msm8937_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8937",
.of_match_table = msm8937_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8939.c b/drivers/interconnect/qcom/msm8939.c
index 8ff2c23b1ca0..b52c5ac1175c 100644
--- a/drivers/interconnect/qcom/msm8939.c
+++ b/drivers/interconnect/qcom/msm8939.c
@@ -1421,7 +1421,7 @@ MODULE_DEVICE_TABLE(of, msm8939_noc_of_match);
static struct platform_driver msm8939_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8939",
.of_match_table = msm8939_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8953.c b/drivers/interconnect/qcom/msm8953.c
index 62f8c0774b3e..be2b1a606612 100644
--- a/drivers/interconnect/qcom/msm8953.c
+++ b/drivers/interconnect/qcom/msm8953.c
@@ -1310,7 +1310,7 @@ static const struct of_device_id msm8953_noc_of_match[] = {
static struct platform_driver msm8953_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8953",
.of_match_table = msm8953_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8974.c b/drivers/interconnect/qcom/msm8974.c
index 241076b5f36b..469fc48ebfe9 100644
--- a/drivers/interconnect/qcom/msm8974.c
+++ b/drivers/interconnect/qcom/msm8974.c
@@ -762,7 +762,7 @@ MODULE_DEVICE_TABLE(of, msm8974_noc_of_match);
static struct platform_driver msm8974_noc_driver = {
.probe = msm8974_icc_probe,
- .remove_new = msm8974_icc_remove,
+ .remove = msm8974_icc_remove,
.driver = {
.name = "qnoc-msm8974",
.of_match_table = msm8974_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8976.c b/drivers/interconnect/qcom/msm8976.c
index ab963def77c3..4e2ac7ebe742 100644
--- a/drivers/interconnect/qcom/msm8976.c
+++ b/drivers/interconnect/qcom/msm8976.c
@@ -1427,7 +1427,7 @@ MODULE_DEVICE_TABLE(of, msm8976_noc_of_match);
static struct platform_driver msm8976_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8976",
.of_match_table = msm8976_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
index 788131400cd1..b73566c9b21f 100644
--- a/drivers/interconnect/qcom/msm8996.c
+++ b/drivers/interconnect/qcom/msm8996.c
@@ -2108,7 +2108,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8996",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/osm-l3.c b/drivers/interconnect/qcom/osm-l3.c
index 61a8695a9adc..6a656ed44d49 100644
--- a/drivers/interconnect/qcom/osm-l3.c
+++ b/drivers/interconnect/qcom/osm-l3.c
@@ -290,7 +290,7 @@ MODULE_DEVICE_TABLE(of, osm_l3_of_match);
static struct platform_driver osm_l3_driver = {
.probe = qcom_osm_l3_probe,
- .remove_new = qcom_osm_l3_remove,
+ .remove = qcom_osm_l3_remove,
.driver = {
.name = "osm-l3",
.of_match_table = osm_l3_of_match,
diff --git a/drivers/interconnect/qcom/qcm2290.c b/drivers/interconnect/qcom/qcm2290.c
index ccbdc6202c07..e120bc1395f3 100644
--- a/drivers/interconnect/qcom/qcm2290.c
+++ b/drivers/interconnect/qcom/qcm2290.c
@@ -1367,7 +1367,7 @@ MODULE_DEVICE_TABLE(of, qcm2290_noc_of_match);
static struct platform_driver qcm2290_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-qcm2290",
.of_match_table = qcm2290_noc_of_match,
diff --git a/drivers/interconnect/qcom/qcs404.c b/drivers/interconnect/qcom/qcs404.c
index 63e9ff223ac4..ceac7a698769 100644
--- a/drivers/interconnect/qcom/qcs404.c
+++ b/drivers/interconnect/qcom/qcs404.c
@@ -1204,7 +1204,7 @@ MODULE_DEVICE_TABLE(of, qcs404_noc_of_match);
static struct platform_driver qcs404_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-qcs404",
.of_match_table = qcs404_noc_of_match,
diff --git a/drivers/interconnect/qcom/qcs615.c b/drivers/interconnect/qcom/qcs615.c
new file mode 100644
index 000000000000..7e59e91ce886
--- /dev/null
+++ b/drivers/interconnect/qcom/qcs615.c
@@ -0,0 +1,1563 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <dt-bindings/interconnect/qcom,qcs615-rpmh.h>
+
+#include "bcm-voter.h"
+#include "icc-rpmh.h"
+#include "qcs615.h"
+
+static struct qcom_icc_node qhm_a1noc_cfg = {
+ .name = "qhm_a1noc_cfg",
+ .id = QCS615_MASTER_A1NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_SERVICE_A2NOC },
+};
+
+static struct qcom_icc_node qhm_qdss_bam = {
+ .name = "qhm_qdss_bam",
+ .id = QCS615_MASTER_QDSS_BAM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qspi = {
+ .name = "qhm_qspi",
+ .id = QCS615_MASTER_QSPI,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qup0 = {
+ .name = "qhm_qup0",
+ .id = QCS615_MASTER_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qup1 = {
+ .name = "qhm_qup1",
+ .id = QCS615_MASTER_BLSP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qnm_cnoc = {
+ .name = "qnm_cnoc",
+ .id = QCS615_MASTER_CNOC_A2NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_crypto = {
+ .name = "qxm_crypto",
+ .id = QCS615_MASTER_CRYPTO,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_ipa = {
+ .name = "qxm_ipa",
+ .id = QCS615_MASTER_IPA,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_LPASS_SNOC },
+};
+
+static struct qcom_icc_node xm_emac_avb = {
+ .name = "xm_emac_avb",
+ .id = QCS615_MASTER_EMAC_EVB,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_pcie = {
+ .name = "xm_pcie",
+ .id = QCS615_MASTER_PCIE,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_ANOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node xm_qdss_etr = {
+ .name = "xm_qdss_etr",
+ .id = QCS615_MASTER_QDSS_ETR,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_sdc1 = {
+ .name = "xm_sdc1",
+ .id = QCS615_MASTER_SDCC_1,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_sdc2 = {
+ .name = "xm_sdc2",
+ .id = QCS615_MASTER_SDCC_2,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_ufs_mem = {
+ .name = "xm_ufs_mem",
+ .id = QCS615_MASTER_UFS_MEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_usb2 = {
+ .name = "xm_usb2",
+ .id = QCS615_MASTER_USB2,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_usb3_0 = {
+ .name = "xm_usb3_0",
+ .id = QCS615_MASTER_USB3_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_camnoc_hf0_uncomp = {
+ .name = "qxm_camnoc_hf0_uncomp",
+ .id = QCS615_MASTER_CAMNOC_HF0_UNCOMP,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_CAMNOC_UNCOMP },
+};
+
+static struct qcom_icc_node qxm_camnoc_hf1_uncomp = {
+ .name = "qxm_camnoc_hf1_uncomp",
+ .id = QCS615_MASTER_CAMNOC_HF1_UNCOMP,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_CAMNOC_UNCOMP },
+};
+
+static struct qcom_icc_node qxm_camnoc_sf_uncomp = {
+ .name = "qxm_camnoc_sf_uncomp",
+ .id = QCS615_MASTER_CAMNOC_SF_UNCOMP,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_CAMNOC_UNCOMP },
+};
+
+static struct qcom_icc_node qhm_spdm = {
+ .name = "qhm_spdm",
+ .id = QCS615_MASTER_SPDM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_CNOC_A2NOC },
+};
+
+static struct qcom_icc_node qnm_snoc = {
+ .name = "qnm_snoc",
+ .id = QCS615_MASTER_SNOC_CNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 39,
+ .links = { QCS615_SLAVE_A1NOC_CFG, QCS615_SLAVE_AHB2PHY_EAST,
+ QCS615_SLAVE_AHB2PHY_WEST, QCS615_SLAVE_AOP,
+ QCS615_SLAVE_AOSS, QCS615_SLAVE_CAMERA_CFG,
+ QCS615_SLAVE_CLK_CTL, QCS615_SLAVE_RBCPR_CX_CFG,
+ QCS615_SLAVE_RBCPR_MX_CFG, QCS615_SLAVE_CRYPTO_0_CFG,
+ QCS615_SLAVE_CNOC_DDRSS, QCS615_SLAVE_DISPLAY_CFG,
+ QCS615_SLAVE_EMAC_AVB_CFG, QCS615_SLAVE_GLM,
+ QCS615_SLAVE_GFX3D_CFG, QCS615_SLAVE_IMEM_CFG,
+ QCS615_SLAVE_IPA_CFG, QCS615_SLAVE_CNOC_MNOC_CFG,
+ QCS615_SLAVE_PCIE_CFG, QCS615_SLAVE_PIMEM_CFG,
+ QCS615_SLAVE_PRNG, QCS615_SLAVE_QDSS_CFG,
+ QCS615_SLAVE_QSPI, QCS615_SLAVE_QUP_0,
+ QCS615_SLAVE_QUP_1, QCS615_SLAVE_SDCC_1,
+ QCS615_SLAVE_SDCC_2, QCS615_SLAVE_SNOC_CFG,
+ QCS615_SLAVE_SPDM_WRAPPER, QCS615_SLAVE_TCSR,
+ QCS615_SLAVE_TLMM_EAST, QCS615_SLAVE_TLMM_SOUTH,
+ QCS615_SLAVE_TLMM_WEST, QCS615_SLAVE_UFS_MEM_CFG,
+ QCS615_SLAVE_USB2, QCS615_SLAVE_USB3,
+ QCS615_SLAVE_VENUS_CFG, QCS615_SLAVE_VSENSE_CTRL_CFG,
+ QCS615_SLAVE_SERVICE_CNOC },
+};
+
+static struct qcom_icc_node xm_qdss_dap = {
+ .name = "xm_qdss_dap",
+ .id = QCS615_MASTER_QDSS_DAP,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 40,
+ .links = { QCS615_SLAVE_A1NOC_CFG, QCS615_SLAVE_AHB2PHY_EAST,
+ QCS615_SLAVE_AHB2PHY_WEST, QCS615_SLAVE_AOP,
+ QCS615_SLAVE_AOSS, QCS615_SLAVE_CAMERA_CFG,
+ QCS615_SLAVE_CLK_CTL, QCS615_SLAVE_RBCPR_CX_CFG,
+ QCS615_SLAVE_RBCPR_MX_CFG, QCS615_SLAVE_CRYPTO_0_CFG,
+ QCS615_SLAVE_CNOC_DDRSS, QCS615_SLAVE_DISPLAY_CFG,
+ QCS615_SLAVE_EMAC_AVB_CFG, QCS615_SLAVE_GLM,
+ QCS615_SLAVE_GFX3D_CFG, QCS615_SLAVE_IMEM_CFG,
+ QCS615_SLAVE_IPA_CFG, QCS615_SLAVE_CNOC_MNOC_CFG,
+ QCS615_SLAVE_PCIE_CFG, QCS615_SLAVE_PIMEM_CFG,
+ QCS615_SLAVE_PRNG, QCS615_SLAVE_QDSS_CFG,
+ QCS615_SLAVE_QSPI, QCS615_SLAVE_QUP_0,
+ QCS615_SLAVE_QUP_1, QCS615_SLAVE_SDCC_1,
+ QCS615_SLAVE_SDCC_2, QCS615_SLAVE_SNOC_CFG,
+ QCS615_SLAVE_SPDM_WRAPPER, QCS615_SLAVE_TCSR,
+ QCS615_SLAVE_TLMM_EAST, QCS615_SLAVE_TLMM_SOUTH,
+ QCS615_SLAVE_TLMM_WEST, QCS615_SLAVE_UFS_MEM_CFG,
+ QCS615_SLAVE_USB2, QCS615_SLAVE_USB3,
+ QCS615_SLAVE_VENUS_CFG, QCS615_SLAVE_VSENSE_CTRL_CFG,
+ QCS615_SLAVE_CNOC_A2NOC, QCS615_SLAVE_SERVICE_CNOC },
+};
+
+static struct qcom_icc_node qhm_cnoc = {
+ .name = "qhm_cnoc",
+ .id = QCS615_MASTER_CNOC_DC_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_DC_NOC_GEMNOC, QCS615_SLAVE_LLCC_CFG },
+};
+
+static struct qcom_icc_node acm_apps = {
+ .name = "acm_apps",
+ .id = QCS615_MASTER_APPSS_PROC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 3,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC,
+ QCS615_SLAVE_MEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node acm_gpu_tcu = {
+ .name = "acm_gpu_tcu",
+ .id = QCS615_MASTER_GPU_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node acm_sys_tcu = {
+ .name = "acm_sys_tcu",
+ .id = QCS615_MASTER_SYS_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qhm_gemnoc_cfg = {
+ .name = "qhm_gemnoc_cfg",
+ .id = QCS615_MASTER_GEM_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_MSS_PROC_MS_MPU_CFG, QCS615_SLAVE_SERVICE_GEM_NOC },
+};
+
+static struct qcom_icc_node qnm_gpu = {
+ .name = "qnm_gpu",
+ .id = QCS615_MASTER_GFX3D,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_mnoc_hf = {
+ .name = "qnm_mnoc_hf",
+ .id = QCS615_MASTER_MNOC_HF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_mnoc_sf = {
+ .name = "qnm_mnoc_sf",
+ .id = QCS615_MASTER_MNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_snoc_gc = {
+ .name = "qnm_snoc_gc",
+ .id = QCS615_MASTER_SNOC_GC_MEM_NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_snoc_sf = {
+ .name = "qnm_snoc_sf",
+ .id = QCS615_MASTER_SNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node ipa_core_master = {
+ .name = "ipa_core_master",
+ .id = QCS615_MASTER_IPA_CORE,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_IPA_CORE },
+};
+
+static struct qcom_icc_node llcc_mc = {
+ .name = "llcc_mc",
+ .id = QCS615_MASTER_LLCC,
+ .channels = 2,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_EBI1 },
+};
+
+static struct qcom_icc_node qhm_mnoc_cfg = {
+ .name = "qhm_mnoc_cfg",
+ .id = QCS615_MASTER_CNOC_MNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_SERVICE_MNOC },
+};
+
+static struct qcom_icc_node qxm_camnoc_hf0 = {
+ .name = "qxm_camnoc_hf0",
+ .id = QCS615_MASTER_CAMNOC_HF0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_camnoc_hf1 = {
+ .name = "qxm_camnoc_hf1",
+ .id = QCS615_MASTER_CAMNOC_HF1,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_camnoc_sf = {
+ .name = "qxm_camnoc_sf",
+ .id = QCS615_MASTER_CAMNOC_SF,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_mdp0 = {
+ .name = "qxm_mdp0",
+ .id = QCS615_MASTER_MDP0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_rot = {
+ .name = "qxm_rot",
+ .id = QCS615_MASTER_ROTATOR,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_venus0 = {
+ .name = "qxm_venus0",
+ .id = QCS615_MASTER_VIDEO_P0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_venus_arm9 = {
+ .name = "qxm_venus_arm9",
+ .id = QCS615_MASTER_VIDEO_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qhm_snoc_cfg = {
+ .name = "qhm_snoc_cfg",
+ .id = QCS615_MASTER_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_SERVICE_SNOC },
+};
+
+static struct qcom_icc_node qnm_aggre1_noc = {
+ .name = "qnm_aggre1_noc",
+ .id = QCS615_MASTER_A1NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 8,
+ .links = { QCS615_SLAVE_APPSS, QCS615_SLAVE_SNOC_CNOC,
+ QCS615_SLAVE_SNOC_GEM_NOC_SF, QCS615_SLAVE_IMEM,
+ QCS615_SLAVE_PIMEM, QCS615_SLAVE_PCIE_0,
+ QCS615_SLAVE_QDSS_STM, QCS615_SLAVE_TCU },
+};
+
+static struct qcom_icc_node qnm_gemnoc = {
+ .name = "qnm_gemnoc",
+ .id = QCS615_MASTER_GEM_NOC_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 6,
+ .links = { QCS615_SLAVE_APPSS, QCS615_SLAVE_SNOC_CNOC,
+ QCS615_SLAVE_IMEM, QCS615_SLAVE_PIMEM,
+ QCS615_SLAVE_QDSS_STM, QCS615_SLAVE_TCU },
+};
+
+static struct qcom_icc_node qnm_gemnoc_pcie = {
+ .name = "qnm_gemnoc_pcie",
+ .id = QCS615_MASTER_GEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_PCIE_0 },
+};
+
+static struct qcom_icc_node qnm_lpass_anoc = {
+ .name = "qnm_lpass_anoc",
+ .id = QCS615_MASTER_LPASS_ANOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 7,
+ .links = { QCS615_SLAVE_APPSS, QCS615_SLAVE_SNOC_CNOC,
+ QCS615_SLAVE_SNOC_GEM_NOC_SF, QCS615_SLAVE_IMEM,
+ QCS615_SLAVE_PIMEM, QCS615_SLAVE_PCIE_0,
+ QCS615_SLAVE_QDSS_STM },
+};
+
+static struct qcom_icc_node qnm_pcie_anoc = {
+ .name = "qnm_pcie_anoc",
+ .id = QCS615_MASTER_ANOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 5,
+ .links = { QCS615_SLAVE_APPSS, QCS615_SLAVE_SNOC_CNOC,
+ QCS615_SLAVE_SNOC_GEM_NOC_SF, QCS615_SLAVE_IMEM,
+ QCS615_SLAVE_QDSS_STM },
+};
+
+static struct qcom_icc_node qxm_pimem = {
+ .name = "qxm_pimem",
+ .id = QCS615_MASTER_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_SNOC_MEM_NOC_GC, QCS615_SLAVE_IMEM },
+};
+
+static struct qcom_icc_node xm_gic = {
+ .name = "xm_gic",
+ .id = QCS615_MASTER_GIC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_SNOC_MEM_NOC_GC, QCS615_SLAVE_IMEM },
+};
+
+static struct qcom_icc_node qns_a1noc_snoc = {
+ .name = "qns_a1noc_snoc",
+ .id = QCS615_SLAVE_A1NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS615_MASTER_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qns_lpass_snoc = {
+ .name = "qns_lpass_snoc",
+ .id = QCS615_SLAVE_LPASS_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_LPASS_ANOC },
+};
+
+static struct qcom_icc_node qns_pcie_snoc = {
+ .name = "qns_pcie_snoc",
+ .id = QCS615_SLAVE_ANOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_ANOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node srvc_aggre2_noc = {
+ .name = "srvc_aggre2_noc",
+ .id = QCS615_SLAVE_SERVICE_A2NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_camnoc_uncomp = {
+ .name = "qns_camnoc_uncomp",
+ .id = QCS615_SLAVE_CAMNOC_UNCOMP,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_a1_noc_cfg = {
+ .name = "qhs_a1_noc_cfg",
+ .id = QCS615_SLAVE_A1NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_A1NOC_CFG },
+};
+
+static struct qcom_icc_node qhs_ahb2phy_east = {
+ .name = "qhs_ahb2phy_east",
+ .id = QCS615_SLAVE_AHB2PHY_EAST,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ahb2phy_west = {
+ .name = "qhs_ahb2phy_west",
+ .id = QCS615_SLAVE_AHB2PHY_WEST,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_aop = {
+ .name = "qhs_aop",
+ .id = QCS615_SLAVE_AOP,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_aoss = {
+ .name = "qhs_aoss",
+ .id = QCS615_SLAVE_AOSS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_cfg = {
+ .name = "qhs_camera_cfg",
+ .id = QCS615_SLAVE_CAMERA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_clk_ctl = {
+ .name = "qhs_clk_ctl",
+ .id = QCS615_SLAVE_CLK_CTL,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_cx = {
+ .name = "qhs_cpr_cx",
+ .id = QCS615_SLAVE_RBCPR_CX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mx = {
+ .name = "qhs_cpr_mx",
+ .id = QCS615_SLAVE_RBCPR_MX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_crypto0_cfg = {
+ .name = "qhs_crypto0_cfg",
+ .id = QCS615_SLAVE_CRYPTO_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ddrss_cfg = {
+ .name = "qhs_ddrss_cfg",
+ .id = QCS615_SLAVE_CNOC_DDRSS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_CNOC_DC_NOC },
+};
+
+static struct qcom_icc_node qhs_display_cfg = {
+ .name = "qhs_display_cfg",
+ .id = QCS615_SLAVE_DISPLAY_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_emac_avb_cfg = {
+ .name = "qhs_emac_avb_cfg",
+ .id = QCS615_SLAVE_EMAC_AVB_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_glm = {
+ .name = "qhs_glm",
+ .id = QCS615_SLAVE_GLM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpuss_cfg = {
+ .name = "qhs_gpuss_cfg",
+ .id = QCS615_SLAVE_GFX3D_CFG,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_imem_cfg = {
+ .name = "qhs_imem_cfg",
+ .id = QCS615_SLAVE_IMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ipa = {
+ .name = "qhs_ipa",
+ .id = QCS615_SLAVE_IPA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_mnoc_cfg = {
+ .name = "qhs_mnoc_cfg",
+ .id = QCS615_SLAVE_CNOC_MNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_CNOC_MNOC_CFG },
+};
+
+static struct qcom_icc_node qhs_pcie_config = {
+ .name = "qhs_pcie_config",
+ .id = QCS615_SLAVE_PCIE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pimem_cfg = {
+ .name = "qhs_pimem_cfg",
+ .id = QCS615_SLAVE_PIMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_prng = {
+ .name = "qhs_prng",
+ .id = QCS615_SLAVE_PRNG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qdss_cfg = {
+ .name = "qhs_qdss_cfg",
+ .id = QCS615_SLAVE_QDSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qspi = {
+ .name = "qhs_qspi",
+ .id = QCS615_SLAVE_QSPI,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup0 = {
+ .name = "qhs_qup0",
+ .id = QCS615_SLAVE_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup1 = {
+ .name = "qhs_qup1",
+ .id = QCS615_SLAVE_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sdc1 = {
+ .name = "qhs_sdc1",
+ .id = QCS615_SLAVE_SDCC_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sdc2 = {
+ .name = "qhs_sdc2",
+ .id = QCS615_SLAVE_SDCC_2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_snoc_cfg = {
+ .name = "qhs_snoc_cfg",
+ .id = QCS615_SLAVE_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_SNOC_CFG },
+};
+
+static struct qcom_icc_node qhs_spdm = {
+ .name = "qhs_spdm",
+ .id = QCS615_SLAVE_SPDM_WRAPPER,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tcsr = {
+ .name = "qhs_tcsr",
+ .id = QCS615_SLAVE_TCSR,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm_east = {
+ .name = "qhs_tlmm_east",
+ .id = QCS615_SLAVE_TLMM_EAST,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm_south = {
+ .name = "qhs_tlmm_south",
+ .id = QCS615_SLAVE_TLMM_SOUTH,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm_west = {
+ .name = "qhs_tlmm_west",
+ .id = QCS615_SLAVE_TLMM_WEST,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ufs_mem_cfg = {
+ .name = "qhs_ufs_mem_cfg",
+ .id = QCS615_SLAVE_UFS_MEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb2 = {
+ .name = "qhs_usb2",
+ .id = QCS615_SLAVE_USB2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb3 = {
+ .name = "qhs_usb3",
+ .id = QCS615_SLAVE_USB3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_cfg = {
+ .name = "qhs_venus_cfg",
+ .id = QCS615_SLAVE_VENUS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_vsense_ctrl_cfg = {
+ .name = "qhs_vsense_ctrl_cfg",
+ .id = QCS615_SLAVE_VSENSE_CTRL_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_cnoc_a2noc = {
+ .name = "qns_cnoc_a2noc",
+ .id = QCS615_SLAVE_CNOC_A2NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_CNOC_A2NOC },
+};
+
+static struct qcom_icc_node srvc_cnoc = {
+ .name = "srvc_cnoc",
+ .id = QCS615_SLAVE_SERVICE_CNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_dc_noc_gemnoc = {
+ .name = "qhs_dc_noc_gemnoc",
+ .id = QCS615_SLAVE_DC_NOC_GEMNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_GEM_NOC_CFG },
+};
+
+static struct qcom_icc_node qhs_llcc = {
+ .name = "qhs_llcc",
+ .id = QCS615_SLAVE_LLCC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_mdsp_ms_mpu_cfg = {
+ .name = "qhs_mdsp_ms_mpu_cfg",
+ .id = QCS615_SLAVE_MSS_PROC_MS_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_gem_noc_snoc = {
+ .name = "qns_gem_noc_snoc",
+ .id = QCS615_SLAVE_GEM_NOC_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_GEM_NOC_SNOC },
+};
+
+static struct qcom_icc_node qns_llcc = {
+ .name = "qns_llcc",
+ .id = QCS615_SLAVE_LLCC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS615_MASTER_LLCC },
+};
+
+static struct qcom_icc_node qns_sys_pcie = {
+ .name = "qns_sys_pcie",
+ .id = QCS615_SLAVE_MEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_GEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node srvc_gemnoc = {
+ .name = "srvc_gemnoc",
+ .id = QCS615_SLAVE_SERVICE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node ipa_core_slave = {
+ .name = "ipa_core_slave",
+ .id = QCS615_SLAVE_IPA_CORE,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node ebi = {
+ .name = "ebi",
+ .id = QCS615_SLAVE_EBI1,
+ .channels = 2,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns2_mem_noc = {
+ .name = "qns2_mem_noc",
+ .id = QCS615_SLAVE_MNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_MASTER_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_mem_noc_hf = {
+ .name = "qns_mem_noc_hf",
+ .id = QCS615_SLAVE_MNOC_HF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_MASTER_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_mnoc = {
+ .name = "srvc_mnoc",
+ .id = QCS615_SLAVE_SERVICE_MNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_apss = {
+ .name = "qhs_apss",
+ .id = QCS615_SLAVE_APPSS,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_cnoc = {
+ .name = "qns_cnoc",
+ .id = QCS615_SLAVE_SNOC_CNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_SNOC_CNOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_sf = {
+ .name = "qns_gemnoc_sf",
+ .id = QCS615_SLAVE_SNOC_GEM_NOC_SF,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS615_MASTER_SNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_memnoc_gc = {
+ .name = "qns_memnoc_gc",
+ .id = QCS615_SLAVE_SNOC_MEM_NOC_GC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_SNOC_GC_MEM_NOC },
+};
+
+static struct qcom_icc_node qxs_imem = {
+ .name = "qxs_imem",
+ .id = QCS615_SLAVE_IMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qxs_pimem = {
+ .name = "qxs_pimem",
+ .id = QCS615_SLAVE_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_snoc = {
+ .name = "srvc_snoc",
+ .id = QCS615_SLAVE_SERVICE_SNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie = {
+ .name = "xs_pcie",
+ .id = QCS615_SLAVE_PCIE_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_qdss_stm = {
+ .name = "xs_qdss_stm",
+ .id = QCS615_SLAVE_QDSS_STM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_sys_tcu_cfg = {
+ .name = "xs_sys_tcu_cfg",
+ .id = QCS615_SLAVE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_bcm bcm_acv = {
+ .name = "ACV",
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_ce0 = {
+ .name = "CE0",
+ .num_nodes = 1,
+ .nodes = { &qxm_crypto },
+};
+
+static struct qcom_icc_bcm bcm_cn0 = {
+ .name = "CN0",
+ .keepalive = true,
+ .num_nodes = 37,
+ .nodes = { &qhm_spdm, &qnm_snoc,
+ &qhs_a1_noc_cfg, &qhs_aop,
+ &qhs_aoss, &qhs_camera_cfg,
+ &qhs_clk_ctl, &qhs_cpr_cx,
+ &qhs_cpr_mx, &qhs_crypto0_cfg,
+ &qhs_ddrss_cfg, &qhs_display_cfg,
+ &qhs_emac_avb_cfg, &qhs_glm,
+ &qhs_gpuss_cfg, &qhs_imem_cfg,
+ &qhs_ipa, &qhs_mnoc_cfg,
+ &qhs_pcie_config, &qhs_pimem_cfg,
+ &qhs_prng, &qhs_qdss_cfg,
+ &qhs_qup0, &qhs_qup1,
+ &qhs_snoc_cfg, &qhs_spdm,
+ &qhs_tcsr, &qhs_tlmm_east,
+ &qhs_tlmm_south, &qhs_tlmm_west,
+ &qhs_ufs_mem_cfg, &qhs_usb2,
+ &qhs_usb3, &qhs_venus_cfg,
+ &qhs_vsense_ctrl_cfg, &qns_cnoc_a2noc,
+ &srvc_cnoc },
+};
+
+static struct qcom_icc_bcm bcm_cn1 = {
+ .name = "CN1",
+ .num_nodes = 8,
+ .nodes = { &qhm_qspi, &xm_sdc1,
+ &xm_sdc2, &qhs_ahb2phy_east,
+ &qhs_ahb2phy_west, &qhs_qspi,
+ &qhs_sdc1, &qhs_sdc2 },
+};
+
+static struct qcom_icc_bcm bcm_ip0 = {
+ .name = "IP0",
+ .num_nodes = 1,
+ .nodes = { &ipa_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_mc0 = {
+ .name = "MC0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_mm0 = {
+ .name = "MM0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_mem_noc_hf },
+};
+
+static struct qcom_icc_bcm bcm_mm1 = {
+ .name = "MM1",
+ .num_nodes = 7,
+ .nodes = { &qxm_camnoc_hf0_uncomp, &qxm_camnoc_hf1_uncomp,
+ &qxm_camnoc_sf_uncomp, &qxm_camnoc_hf0,
+ &qxm_camnoc_hf1, &qxm_mdp0,
+ &qxm_rot },
+};
+
+static struct qcom_icc_bcm bcm_mm2 = {
+ .name = "MM2",
+ .num_nodes = 2,
+ .nodes = { &qxm_camnoc_sf, &qns2_mem_noc },
+};
+
+static struct qcom_icc_bcm bcm_mm3 = {
+ .name = "MM3",
+ .num_nodes = 2,
+ .nodes = { &qxm_venus0, &qxm_venus_arm9 },
+};
+
+static struct qcom_icc_bcm bcm_qup0 = {
+ .name = "QUP0",
+ .keepalive = true,
+ .vote_scale = 1,
+ .num_nodes = 2,
+ .nodes = { &qhm_qup0, &qhm_qup1 },
+};
+
+static struct qcom_icc_bcm bcm_sh0 = {
+ .name = "SH0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_llcc },
+};
+
+static struct qcom_icc_bcm bcm_sh2 = {
+ .name = "SH2",
+ .num_nodes = 1,
+ .nodes = { &acm_apps },
+};
+
+static struct qcom_icc_bcm bcm_sh3 = {
+ .name = "SH3",
+ .num_nodes = 1,
+ .nodes = { &qns_gem_noc_snoc },
+};
+
+static struct qcom_icc_bcm bcm_sn0 = {
+ .name = "SN0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_bcm bcm_sn1 = {
+ .name = "SN1",
+ .num_nodes = 1,
+ .nodes = { &qxs_imem },
+};
+
+static struct qcom_icc_bcm bcm_sn2 = {
+ .name = "SN2",
+ .num_nodes = 1,
+ .nodes = { &qns_memnoc_gc },
+};
+
+static struct qcom_icc_bcm bcm_sn3 = {
+ .name = "SN3",
+ .num_nodes = 2,
+ .nodes = { &srvc_aggre2_noc, &qns_cnoc },
+};
+
+static struct qcom_icc_bcm bcm_sn4 = {
+ .name = "SN4",
+ .num_nodes = 1,
+ .nodes = { &qxs_pimem },
+};
+
+static struct qcom_icc_bcm bcm_sn5 = {
+ .name = "SN5",
+ .num_nodes = 1,
+ .nodes = { &xs_qdss_stm },
+};
+
+static struct qcom_icc_bcm bcm_sn8 = {
+ .name = "SN8",
+ .num_nodes = 2,
+ .nodes = { &qnm_gemnoc_pcie, &xs_pcie },
+};
+
+static struct qcom_icc_bcm bcm_sn9 = {
+ .name = "SN9",
+ .num_nodes = 1,
+ .nodes = { &qnm_aggre1_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn12 = {
+ .name = "SN12",
+ .num_nodes = 2,
+ .nodes = { &qxm_pimem, &xm_gic },
+};
+
+static struct qcom_icc_bcm bcm_sn13 = {
+ .name = "SN13",
+ .num_nodes = 1,
+ .nodes = { &qnm_lpass_anoc },
+};
+
+static struct qcom_icc_bcm bcm_sn14 = {
+ .name = "SN14",
+ .num_nodes = 1,
+ .nodes = { &qns_pcie_snoc },
+};
+
+static struct qcom_icc_bcm bcm_sn15 = {
+ .name = "SN15",
+ .num_nodes = 1,
+ .nodes = { &qnm_gemnoc },
+};
+
+static struct qcom_icc_bcm * const aggre1_noc_bcms[] = {
+ &bcm_ce0,
+ &bcm_cn1,
+ &bcm_qup0,
+ &bcm_sn3,
+ &bcm_sn14,
+ &bcm_ip0,
+};
+
+static struct qcom_icc_node * const aggre1_noc_nodes[] = {
+ [MASTER_A1NOC_CFG] = &qhm_a1noc_cfg,
+ [MASTER_QDSS_BAM] = &qhm_qdss_bam,
+ [MASTER_QSPI] = &qhm_qspi,
+ [MASTER_QUP_0] = &qhm_qup0,
+ [MASTER_BLSP_1] = &qhm_qup1,
+ [MASTER_CNOC_A2NOC] = &qnm_cnoc,
+ [MASTER_CRYPTO] = &qxm_crypto,
+ [MASTER_IPA] = &qxm_ipa,
+ [MASTER_EMAC_EVB] = &xm_emac_avb,
+ [MASTER_PCIE] = &xm_pcie,
+ [MASTER_QDSS_ETR] = &xm_qdss_etr,
+ [MASTER_SDCC_1] = &xm_sdc1,
+ [MASTER_SDCC_2] = &xm_sdc2,
+ [MASTER_UFS_MEM] = &xm_ufs_mem,
+ [MASTER_USB2] = &xm_usb2,
+ [MASTER_USB3_0] = &xm_usb3_0,
+ [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc,
+ [SLAVE_LPASS_SNOC] = &qns_lpass_snoc,
+ [SLAVE_ANOC_PCIE_SNOC] = &qns_pcie_snoc,
+ [SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc,
+};
+
+static const struct qcom_icc_desc qcs615_aggre1_noc = {
+ .nodes = aggre1_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
+ .bcms = aggre1_noc_bcms,
+ .num_bcms = ARRAY_SIZE(aggre1_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const camnoc_virt_bcms[] = {
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const camnoc_virt_nodes[] = {
+ [MASTER_CAMNOC_HF0_UNCOMP] = &qxm_camnoc_hf0_uncomp,
+ [MASTER_CAMNOC_HF1_UNCOMP] = &qxm_camnoc_hf1_uncomp,
+ [MASTER_CAMNOC_SF_UNCOMP] = &qxm_camnoc_sf_uncomp,
+ [SLAVE_CAMNOC_UNCOMP] = &qns_camnoc_uncomp,
+};
+
+static const struct qcom_icc_desc qcs615_camnoc_virt = {
+ .nodes = camnoc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(camnoc_virt_nodes),
+ .bcms = camnoc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(camnoc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const config_noc_bcms[] = {
+ &bcm_cn0,
+ &bcm_cn1,
+};
+
+static struct qcom_icc_node * const config_noc_nodes[] = {
+ [MASTER_SPDM] = &qhm_spdm,
+ [MASTER_SNOC_CNOC] = &qnm_snoc,
+ [MASTER_QDSS_DAP] = &xm_qdss_dap,
+ [SLAVE_A1NOC_CFG] = &qhs_a1_noc_cfg,
+ [SLAVE_AHB2PHY_EAST] = &qhs_ahb2phy_east,
+ [SLAVE_AHB2PHY_WEST] = &qhs_ahb2phy_west,
+ [SLAVE_AOP] = &qhs_aop,
+ [SLAVE_AOSS] = &qhs_aoss,
+ [SLAVE_CAMERA_CFG] = &qhs_camera_cfg,
+ [SLAVE_CLK_CTL] = &qhs_clk_ctl,
+ [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx,
+ [SLAVE_RBCPR_MX_CFG] = &qhs_cpr_mx,
+ [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
+ [SLAVE_CNOC_DDRSS] = &qhs_ddrss_cfg,
+ [SLAVE_DISPLAY_CFG] = &qhs_display_cfg,
+ [SLAVE_EMAC_AVB_CFG] = &qhs_emac_avb_cfg,
+ [SLAVE_GLM] = &qhs_glm,
+ [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg,
+ [SLAVE_IMEM_CFG] = &qhs_imem_cfg,
+ [SLAVE_IPA_CFG] = &qhs_ipa,
+ [SLAVE_CNOC_MNOC_CFG] = &qhs_mnoc_cfg,
+ [SLAVE_PCIE_CFG] = &qhs_pcie_config,
+ [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg,
+ [SLAVE_PRNG] = &qhs_prng,
+ [SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
+ [SLAVE_QSPI] = &qhs_qspi,
+ [SLAVE_QUP_0] = &qhs_qup0,
+ [SLAVE_QUP_1] = &qhs_qup1,
+ [SLAVE_SDCC_1] = &qhs_sdc1,
+ [SLAVE_SDCC_2] = &qhs_sdc2,
+ [SLAVE_SNOC_CFG] = &qhs_snoc_cfg,
+ [SLAVE_SPDM_WRAPPER] = &qhs_spdm,
+ [SLAVE_TCSR] = &qhs_tcsr,
+ [SLAVE_TLMM_EAST] = &qhs_tlmm_east,
+ [SLAVE_TLMM_SOUTH] = &qhs_tlmm_south,
+ [SLAVE_TLMM_WEST] = &qhs_tlmm_west,
+ [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg,
+ [SLAVE_USB2] = &qhs_usb2,
+ [SLAVE_USB3] = &qhs_usb3,
+ [SLAVE_VENUS_CFG] = &qhs_venus_cfg,
+ [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg,
+ [SLAVE_CNOC_A2NOC] = &qns_cnoc_a2noc,
+ [SLAVE_SERVICE_CNOC] = &srvc_cnoc,
+};
+
+static const struct qcom_icc_desc qcs615_config_noc = {
+ .nodes = config_noc_nodes,
+ .num_nodes = ARRAY_SIZE(config_noc_nodes),
+ .bcms = config_noc_bcms,
+ .num_bcms = ARRAY_SIZE(config_noc_bcms),
+};
+
+static struct qcom_icc_node * const dc_noc_nodes[] = {
+ [MASTER_CNOC_DC_NOC] = &qhm_cnoc,
+ [SLAVE_DC_NOC_GEMNOC] = &qhs_dc_noc_gemnoc,
+ [SLAVE_LLCC_CFG] = &qhs_llcc,
+};
+
+static const struct qcom_icc_desc qcs615_dc_noc = {
+ .nodes = dc_noc_nodes,
+ .num_nodes = ARRAY_SIZE(dc_noc_nodes),
+};
+
+static struct qcom_icc_bcm * const gem_noc_bcms[] = {
+ &bcm_sh0,
+ &bcm_sh2,
+ &bcm_sh3,
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const gem_noc_nodes[] = {
+ [MASTER_APPSS_PROC] = &acm_apps,
+ [MASTER_GPU_TCU] = &acm_gpu_tcu,
+ [MASTER_SYS_TCU] = &acm_sys_tcu,
+ [MASTER_GEM_NOC_CFG] = &qhm_gemnoc_cfg,
+ [MASTER_GFX3D] = &qnm_gpu,
+ [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf,
+ [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf,
+ [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc,
+ [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf,
+ [SLAVE_MSS_PROC_MS_MPU_CFG] = &qhs_mdsp_ms_mpu_cfg,
+ [SLAVE_GEM_NOC_SNOC] = &qns_gem_noc_snoc,
+ [SLAVE_LLCC] = &qns_llcc,
+ [SLAVE_MEM_NOC_PCIE_SNOC] = &qns_sys_pcie,
+ [SLAVE_SERVICE_GEM_NOC] = &srvc_gemnoc,
+};
+
+static const struct qcom_icc_desc qcs615_gem_noc = {
+ .nodes = gem_noc_nodes,
+ .num_nodes = ARRAY_SIZE(gem_noc_nodes),
+ .bcms = gem_noc_bcms,
+ .num_bcms = ARRAY_SIZE(gem_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const ipa_virt_bcms[] = {
+ &bcm_ip0,
+};
+
+static struct qcom_icc_node * const ipa_virt_nodes[] = {
+ [MASTER_IPA_CORE] = &ipa_core_master,
+ [SLAVE_IPA_CORE] = &ipa_core_slave,
+};
+
+static const struct qcom_icc_desc qcs615_ipa_virt = {
+ .nodes = ipa_virt_nodes,
+ .num_nodes = ARRAY_SIZE(ipa_virt_nodes),
+ .bcms = ipa_virt_bcms,
+ .num_bcms = ARRAY_SIZE(ipa_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mc_virt_bcms[] = {
+ &bcm_acv,
+ &bcm_mc0,
+};
+
+static struct qcom_icc_node * const mc_virt_nodes[] = {
+ [MASTER_LLCC] = &llcc_mc,
+ [SLAVE_EBI1] = &ebi,
+};
+
+static const struct qcom_icc_desc qcs615_mc_virt = {
+ .nodes = mc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mc_virt_nodes),
+ .bcms = mc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(mc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mmss_noc_bcms[] = {
+ &bcm_mm0,
+ &bcm_mm1,
+ &bcm_mm2,
+ &bcm_mm3,
+};
+
+static struct qcom_icc_node * const mmss_noc_nodes[] = {
+ [MASTER_CNOC_MNOC_CFG] = &qhm_mnoc_cfg,
+ [MASTER_CAMNOC_HF0] = &qxm_camnoc_hf0,
+ [MASTER_CAMNOC_HF1] = &qxm_camnoc_hf1,
+ [MASTER_CAMNOC_SF] = &qxm_camnoc_sf,
+ [MASTER_MDP0] = &qxm_mdp0,
+ [MASTER_ROTATOR] = &qxm_rot,
+ [MASTER_VIDEO_P0] = &qxm_venus0,
+ [MASTER_VIDEO_PROC] = &qxm_venus_arm9,
+ [SLAVE_MNOC_SF_MEM_NOC] = &qns2_mem_noc,
+ [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf,
+ [SLAVE_SERVICE_MNOC] = &srvc_mnoc,
+};
+
+static const struct qcom_icc_desc qcs615_mmss_noc = {
+ .nodes = mmss_noc_nodes,
+ .num_nodes = ARRAY_SIZE(mmss_noc_nodes),
+ .bcms = mmss_noc_bcms,
+ .num_bcms = ARRAY_SIZE(mmss_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const system_noc_bcms[] = {
+ &bcm_sn0,
+ &bcm_sn1,
+ &bcm_sn2,
+ &bcm_sn3,
+ &bcm_sn4,
+ &bcm_sn5,
+ &bcm_sn8,
+ &bcm_sn9,
+ &bcm_sn12,
+ &bcm_sn13,
+ &bcm_sn15,
+};
+
+static struct qcom_icc_node * const system_noc_nodes[] = {
+ [MASTER_SNOC_CFG] = &qhm_snoc_cfg,
+ [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc,
+ [MASTER_GEM_NOC_SNOC] = &qnm_gemnoc,
+ [MASTER_GEM_NOC_PCIE_SNOC] = &qnm_gemnoc_pcie,
+ [MASTER_LPASS_ANOC] = &qnm_lpass_anoc,
+ [MASTER_ANOC_PCIE_SNOC] = &qnm_pcie_anoc,
+ [MASTER_PIMEM] = &qxm_pimem,
+ [MASTER_GIC] = &xm_gic,
+ [SLAVE_APPSS] = &qhs_apss,
+ [SLAVE_SNOC_CNOC] = &qns_cnoc,
+ [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf,
+ [SLAVE_SNOC_MEM_NOC_GC] = &qns_memnoc_gc,
+ [SLAVE_IMEM] = &qxs_imem,
+ [SLAVE_PIMEM] = &qxs_pimem,
+ [SLAVE_SERVICE_SNOC] = &srvc_snoc,
+ [SLAVE_PCIE_0] = &xs_pcie,
+ [SLAVE_QDSS_STM] = &xs_qdss_stm,
+ [SLAVE_TCU] = &xs_sys_tcu_cfg,
+};
+
+static const struct qcom_icc_desc qcs615_system_noc = {
+ .nodes = system_noc_nodes,
+ .num_nodes = ARRAY_SIZE(system_noc_nodes),
+ .bcms = system_noc_bcms,
+ .num_bcms = ARRAY_SIZE(system_noc_bcms),
+};
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,qcs615-aggre1-noc",
+ .data = &qcs615_aggre1_noc},
+ { .compatible = "qcom,qcs615-camnoc-virt",
+ .data = &qcs615_camnoc_virt},
+ { .compatible = "qcom,qcs615-config-noc",
+ .data = &qcs615_config_noc},
+ { .compatible = "qcom,qcs615-dc-noc",
+ .data = &qcs615_dc_noc},
+ { .compatible = "qcom,qcs615-gem-noc",
+ .data = &qcs615_gem_noc},
+ { .compatible = "qcom,qcs615-ipa-virt",
+ .data = &qcs615_ipa_virt},
+ { .compatible = "qcom,qcs615-mc-virt",
+ .data = &qcs615_mc_virt},
+ { .compatible = "qcom,qcs615-mmss-noc",
+ .data = &qcs615_mmss_noc},
+ { .compatible = "qcom,qcs615-system-noc",
+ .data = &qcs615_system_noc},
+ { }
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
+ .driver = {
+ .name = "qnoc-qcs615",
+ .of_match_table = qnoc_of_match,
+ .sync_state = icc_sync_state,
+ },
+};
+
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+module_exit(qnoc_driver_exit);
+
+MODULE_DESCRIPTION("qcs615 NoC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/interconnect/qcom/qcs615.h b/drivers/interconnect/qcom/qcs615.h
new file mode 100644
index 000000000000..66e66c7e23d4
--- /dev/null
+++ b/drivers/interconnect/qcom/qcs615.h
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __DRIVERS_INTERCONNECT_QCOM_QCS615_H
+#define __DRIVERS_INTERCONNECT_QCOM_QCS615_H
+
+#define QCS615_MASTER_A1NOC_CFG 1
+#define QCS615_MASTER_A1NOC_SNOC 2
+#define QCS615_MASTER_ANOC_PCIE_SNOC 3
+#define QCS615_MASTER_APPSS_PROC 4
+#define QCS615_MASTER_BLSP_1 5
+#define QCS615_MASTER_CAMNOC_HF0 6
+#define QCS615_MASTER_CAMNOC_HF0_UNCOMP 7
+#define QCS615_MASTER_CAMNOC_HF1 8
+#define QCS615_MASTER_CAMNOC_HF1_UNCOMP 9
+#define QCS615_MASTER_CAMNOC_SF 10
+#define QCS615_MASTER_CAMNOC_SF_UNCOMP 11
+#define QCS615_MASTER_CNOC_A2NOC 12
+#define QCS615_MASTER_CNOC_DC_NOC 13
+#define QCS615_MASTER_CNOC_MNOC_CFG 14
+#define QCS615_MASTER_CRYPTO 15
+#define QCS615_MASTER_EMAC_EVB 16
+#define QCS615_MASTER_GEM_NOC_CFG 17
+#define QCS615_MASTER_GEM_NOC_PCIE_SNOC 18
+#define QCS615_MASTER_GEM_NOC_SNOC 19
+#define QCS615_MASTER_GFX3D 20
+#define QCS615_MASTER_GIC 21
+#define QCS615_MASTER_GPU_TCU 22
+#define QCS615_MASTER_IPA 23
+#define QCS615_MASTER_IPA_CORE 24
+#define QCS615_MASTER_LLCC 25
+#define QCS615_MASTER_LPASS_ANOC 26
+#define QCS615_MASTER_MDP0 27
+#define QCS615_MASTER_MNOC_HF_MEM_NOC 28
+#define QCS615_MASTER_MNOC_SF_MEM_NOC 29
+#define QCS615_MASTER_PCIE 30
+#define QCS615_MASTER_PIMEM 31
+#define QCS615_MASTER_QDSS_BAM 32
+#define QCS615_MASTER_QDSS_DAP 33
+#define QCS615_MASTER_QDSS_ETR 34
+#define QCS615_MASTER_QSPI 35
+#define QCS615_MASTER_QUP_0 36
+#define QCS615_MASTER_ROTATOR 37
+#define QCS615_MASTER_SDCC_1 38
+#define QCS615_MASTER_SDCC_2 39
+#define QCS615_MASTER_SNOC_CFG 40
+#define QCS615_MASTER_SNOC_CNOC 41
+#define QCS615_MASTER_SNOC_GC_MEM_NOC 42
+#define QCS615_MASTER_SNOC_SF_MEM_NOC 43
+#define QCS615_MASTER_SPDM 44
+#define QCS615_MASTER_SYS_TCU 45
+#define QCS615_MASTER_UFS_MEM 46
+#define QCS615_MASTER_USB2 47
+#define QCS615_MASTER_USB3_0 48
+#define QCS615_MASTER_VIDEO_P0 49
+#define QCS615_MASTER_VIDEO_PROC 50
+#define QCS615_SLAVE_A1NOC_CFG 51
+#define QCS615_SLAVE_A1NOC_SNOC 52
+#define QCS615_SLAVE_AHB2PHY_EAST 53
+#define QCS615_SLAVE_AHB2PHY_WEST 54
+#define QCS615_SLAVE_ANOC_PCIE_SNOC 55
+#define QCS615_SLAVE_AOP 56
+#define QCS615_SLAVE_AOSS 57
+#define QCS615_SLAVE_APPSS 58
+#define QCS615_SLAVE_CAMERA_CFG 59
+#define QCS615_SLAVE_CAMNOC_UNCOMP 60
+#define QCS615_SLAVE_CLK_CTL 61
+#define QCS615_SLAVE_CNOC_A2NOC 62
+#define QCS615_SLAVE_CNOC_DDRSS 63
+#define QCS615_SLAVE_CNOC_MNOC_CFG 64
+#define QCS615_SLAVE_CRYPTO_0_CFG 65
+#define QCS615_SLAVE_DC_NOC_GEMNOC 66
+#define QCS615_SLAVE_DISPLAY_CFG 67
+#define QCS615_SLAVE_EBI1 68
+#define QCS615_SLAVE_EMAC_AVB_CFG 69
+#define QCS615_SLAVE_GEM_NOC_SNOC 70
+#define QCS615_SLAVE_GFX3D_CFG 71
+#define QCS615_SLAVE_GLM 72
+#define QCS615_SLAVE_IMEM 73
+#define QCS615_SLAVE_IMEM_CFG 74
+#define QCS615_SLAVE_IPA_CFG 75
+#define QCS615_SLAVE_IPA_CORE 76
+#define QCS615_SLAVE_LLCC 77
+#define QCS615_SLAVE_LLCC_CFG 78
+#define QCS615_SLAVE_LPASS_SNOC 79
+#define QCS615_SLAVE_MEM_NOC_PCIE_SNOC 80
+#define QCS615_SLAVE_MNOC_HF_MEM_NOC 81
+#define QCS615_SLAVE_MNOC_SF_MEM_NOC 82
+#define QCS615_SLAVE_MSS_PROC_MS_MPU_CFG 83
+#define QCS615_SLAVE_PCIE_0 84
+#define QCS615_SLAVE_PCIE_CFG 85
+#define QCS615_SLAVE_PIMEM 86
+#define QCS615_SLAVE_PIMEM_CFG 87
+#define QCS615_SLAVE_PRNG 88
+#define QCS615_SLAVE_QDSS_CFG 89
+#define QCS615_SLAVE_QDSS_STM 90
+#define QCS615_SLAVE_QSPI 91
+#define QCS615_SLAVE_QUP_0 92
+#define QCS615_SLAVE_QUP_1 93
+#define QCS615_SLAVE_RBCPR_CX_CFG 94
+#define QCS615_SLAVE_RBCPR_MX_CFG 95
+#define QCS615_SLAVE_SDCC_1 96
+#define QCS615_SLAVE_SDCC_2 97
+#define QCS615_SLAVE_SERVICE_A2NOC 98
+#define QCS615_SLAVE_SERVICE_CNOC 99
+#define QCS615_SLAVE_SERVICE_GEM_NOC 100
+#define QCS615_SLAVE_SERVICE_MNOC 101
+#define QCS615_SLAVE_SERVICE_SNOC 102
+#define QCS615_SLAVE_SNOC_CFG 103
+#define QCS615_SLAVE_SNOC_CNOC 104
+#define QCS615_SLAVE_SNOC_GEM_NOC_SF 105
+#define QCS615_SLAVE_SNOC_MEM_NOC_GC 106
+#define QCS615_SLAVE_SPDM_WRAPPER 107
+#define QCS615_SLAVE_TCSR 108
+#define QCS615_SLAVE_TCU 109
+#define QCS615_SLAVE_TLMM_EAST 110
+#define QCS615_SLAVE_TLMM_SOUTH 111
+#define QCS615_SLAVE_TLMM_WEST 112
+#define QCS615_SLAVE_UFS_MEM_CFG 113
+#define QCS615_SLAVE_USB2 114
+#define QCS615_SLAVE_USB3 115
+#define QCS615_SLAVE_VENUS_CFG 116
+#define QCS615_SLAVE_VSENSE_CTRL_CFG 117
+
+#endif
+
diff --git a/drivers/interconnect/qcom/qcs8300.c b/drivers/interconnect/qcom/qcs8300.c
new file mode 100644
index 000000000000..e7a1b2fc69ba
--- /dev/null
+++ b/drivers/interconnect/qcom/qcs8300.c
@@ -0,0 +1,2088 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <dt-bindings/interconnect/qcom,qcs8300-rpmh.h>
+
+#include "bcm-voter.h"
+#include "icc-rpmh.h"
+#include "qcs8300.h"
+
+static struct qcom_icc_node qxm_qup3 = {
+ .name = "qxm_qup3",
+ .id = QCS8300_MASTER_QUP_3,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_emac_0 = {
+ .name = "xm_emac_0",
+ .id = QCS8300_MASTER_EMAC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_sdc1 = {
+ .name = "xm_sdc1",
+ .id = QCS8300_MASTER_SDC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_ufs_mem = {
+ .name = "xm_ufs_mem",
+ .id = QCS8300_MASTER_UFS_MEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_usb2_2 = {
+ .name = "xm_usb2_2",
+ .id = QCS8300_MASTER_USB2,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_usb3_0 = {
+ .name = "xm_usb3_0",
+ .id = QCS8300_MASTER_USB3_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qdss_bam = {
+ .name = "qhm_qdss_bam",
+ .id = QCS8300_MASTER_QDSS_BAM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qup0 = {
+ .name = "qhm_qup0",
+ .id = QCS8300_MASTER_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qup1 = {
+ .name = "qhm_qup1",
+ .id = QCS8300_MASTER_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qnm_cnoc_datapath = {
+ .name = "qnm_cnoc_datapath",
+ .id = QCS8300_MASTER_CNOC_A2NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_crypto_0 = {
+ .name = "qxm_crypto_0",
+ .id = QCS8300_MASTER_CRYPTO_CORE0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_crypto_1 = {
+ .name = "qxm_crypto_1",
+ .id = QCS8300_MASTER_CRYPTO_CORE1,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_ipa = {
+ .name = "qxm_ipa",
+ .id = QCS8300_MASTER_IPA,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_qdss_etr_0 = {
+ .name = "xm_qdss_etr_0",
+ .id = QCS8300_MASTER_QDSS_ETR_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_qdss_etr_1 = {
+ .name = "xm_qdss_etr_1",
+ .id = QCS8300_MASTER_QDSS_ETR_1,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qup0_core_master = {
+ .name = "qup0_core_master",
+ .id = QCS8300_MASTER_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_QUP_CORE_0 },
+};
+
+static struct qcom_icc_node qup1_core_master = {
+ .name = "qup1_core_master",
+ .id = QCS8300_MASTER_QUP_CORE_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_QUP_CORE_1 },
+};
+
+static struct qcom_icc_node qup3_core_master = {
+ .name = "qup3_core_master",
+ .id = QCS8300_MASTER_QUP_CORE_3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_QUP_CORE_3 },
+};
+
+static struct qcom_icc_node qnm_gemnoc_cnoc = {
+ .name = "qnm_gemnoc_cnoc",
+ .id = QCS8300_MASTER_GEM_NOC_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 71,
+ .links = { QCS8300_SLAVE_AHB2PHY_2, QCS8300_SLAVE_AHB2PHY_3,
+ QCS8300_SLAVE_ANOC_THROTTLE_CFG, QCS8300_SLAVE_AOSS,
+ QCS8300_SLAVE_APPSS, QCS8300_SLAVE_BOOT_ROM,
+ QCS8300_SLAVE_CAMERA_CFG, QCS8300_SLAVE_CAMERA_NRT_THROTTLE_CFG,
+ QCS8300_SLAVE_CAMERA_RT_THROTTLE_CFG, QCS8300_SLAVE_CLK_CTL,
+ QCS8300_SLAVE_CDSP_CFG, QCS8300_SLAVE_RBCPR_CX_CFG,
+ QCS8300_SLAVE_RBCPR_MMCX_CFG, QCS8300_SLAVE_RBCPR_MX_CFG,
+ QCS8300_SLAVE_CPR_NSPCX, QCS8300_SLAVE_CPR_NSPHMX,
+ QCS8300_SLAVE_CRYPTO_0_CFG, QCS8300_SLAVE_CX_RDPM,
+ QCS8300_SLAVE_DISPLAY_CFG, QCS8300_SLAVE_DISPLAY_RT_THROTTLE_CFG,
+ QCS8300_SLAVE_EMAC_CFG, QCS8300_SLAVE_GP_DSP0_CFG,
+ QCS8300_SLAVE_GPDSP0_THROTTLE_CFG, QCS8300_SLAVE_GPU_TCU_THROTTLE_CFG,
+ QCS8300_SLAVE_GFX3D_CFG, QCS8300_SLAVE_HWKM,
+ QCS8300_SLAVE_IMEM_CFG, QCS8300_SLAVE_IPA_CFG,
+ QCS8300_SLAVE_IPC_ROUTER_CFG, QCS8300_SLAVE_LPASS,
+ QCS8300_SLAVE_LPASS_THROTTLE_CFG, QCS8300_SLAVE_MX_RDPM,
+ QCS8300_SLAVE_MXC_RDPM, QCS8300_SLAVE_PCIE_0_CFG,
+ QCS8300_SLAVE_PCIE_1_CFG, QCS8300_SLAVE_PCIE_TCU_THROTTLE_CFG,
+ QCS8300_SLAVE_PCIE_THROTTLE_CFG, QCS8300_SLAVE_PDM,
+ QCS8300_SLAVE_PIMEM_CFG, QCS8300_SLAVE_PKA_WRAPPER_CFG,
+ QCS8300_SLAVE_QDSS_CFG, QCS8300_SLAVE_QM_CFG,
+ QCS8300_SLAVE_QM_MPU_CFG, QCS8300_SLAVE_QUP_0,
+ QCS8300_SLAVE_QUP_1, QCS8300_SLAVE_QUP_3,
+ QCS8300_SLAVE_SAIL_THROTTLE_CFG, QCS8300_SLAVE_SDC1,
+ QCS8300_SLAVE_SECURITY, QCS8300_SLAVE_SNOC_THROTTLE_CFG,
+ QCS8300_SLAVE_TCSR, QCS8300_SLAVE_TLMM,
+ QCS8300_SLAVE_TSC_CFG, QCS8300_SLAVE_UFS_MEM_CFG,
+ QCS8300_SLAVE_USB2, QCS8300_SLAVE_USB3_0,
+ QCS8300_SLAVE_VENUS_CFG, QCS8300_SLAVE_VENUS_CVP_THROTTLE_CFG,
+ QCS8300_SLAVE_VENUS_V_CPU_THROTTLE_CFG,
+ QCS8300_SLAVE_VENUS_VCODEC_THROTTLE_CFG,
+ QCS8300_SLAVE_DDRSS_CFG, QCS8300_SLAVE_GPDSP_NOC_CFG,
+ QCS8300_SLAVE_CNOC_MNOC_HF_CFG, QCS8300_SLAVE_CNOC_MNOC_SF_CFG,
+ QCS8300_SLAVE_PCIE_ANOC_CFG, QCS8300_SLAVE_SNOC_CFG,
+ QCS8300_SLAVE_BOOT_IMEM, QCS8300_SLAVE_IMEM,
+ QCS8300_SLAVE_PIMEM, QCS8300_SLAVE_QDSS_STM,
+ QCS8300_SLAVE_TCU },
+};
+
+static struct qcom_icc_node qnm_gemnoc_pcie = {
+ .name = "qnm_gemnoc_pcie",
+ .id = QCS8300_MASTER_GEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_PCIE_0, QCS8300_SLAVE_PCIE_1 },
+};
+
+static struct qcom_icc_node qnm_cnoc_dc_noc = {
+ .name = "qnm_cnoc_dc_noc",
+ .id = QCS8300_MASTER_CNOC_DC_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_LLCC_CFG, QCS8300_SLAVE_GEM_NOC_CFG },
+};
+
+static struct qcom_icc_node alm_gpu_tcu = {
+ .name = "alm_gpu_tcu",
+ .id = QCS8300_MASTER_GPU_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node alm_pcie_tcu = {
+ .name = "alm_pcie_tcu",
+ .id = QCS8300_MASTER_PCIE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node alm_sys_tcu = {
+ .name = "alm_sys_tcu",
+ .id = QCS8300_MASTER_SYS_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node chm_apps = {
+ .name = "chm_apps",
+ .id = QCS8300_MASTER_APPSS_PROC,
+ .channels = 4,
+ .buswidth = 32,
+ .num_links = 3,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC,
+ QCS8300_SLAVE_GEM_NOC_PCIE_CNOC },
+};
+
+static struct qcom_icc_node qnm_cmpnoc0 = {
+ .name = "qnm_cmpnoc0",
+ .id = QCS8300_MASTER_COMPUTE_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_gemnoc_cfg = {
+ .name = "qnm_gemnoc_cfg",
+ .id = QCS8300_MASTER_GEM_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 4,
+ .links = { QCS8300_SLAVE_SERVICE_GEM_NOC_1, QCS8300_SLAVE_SERVICE_GEM_NOC_2,
+ QCS8300_SLAVE_SERVICE_GEM_NOC, QCS8300_SLAVE_SERVICE_GEM_NOC2 },
+};
+
+static struct qcom_icc_node qnm_gpdsp_sail = {
+ .name = "qnm_gpdsp_sail",
+ .id = QCS8300_MASTER_GPDSP_SAIL,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_gpu = {
+ .name = "qnm_gpu",
+ .id = QCS8300_MASTER_GFX3D,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_mnoc_hf = {
+ .name = "qnm_mnoc_hf",
+ .id = QCS8300_MASTER_MNOC_HF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_LLCC, QCS8300_SLAVE_GEM_NOC_PCIE_CNOC },
+};
+
+static struct qcom_icc_node qnm_mnoc_sf = {
+ .name = "qnm_mnoc_sf",
+ .id = QCS8300_MASTER_MNOC_SF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 3,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC,
+ QCS8300_SLAVE_GEM_NOC_PCIE_CNOC },
+};
+
+static struct qcom_icc_node qnm_pcie = {
+ .name = "qnm_pcie",
+ .id = QCS8300_MASTER_ANOC_PCIE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_snoc_gc = {
+ .name = "qnm_snoc_gc",
+ .id = QCS8300_MASTER_SNOC_GC_MEM_NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_snoc_sf = {
+ .name = "qnm_snoc_sf",
+ .id = QCS8300_MASTER_SNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 3,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC,
+ QCS8300_SLAVE_GEM_NOC_PCIE_CNOC },
+};
+
+static struct qcom_icc_node qnm_sailss_md0 = {
+ .name = "qnm_sailss_md0",
+ .id = QCS8300_MASTER_SAILSS_MD0,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_GP_DSP_SAIL_NOC },
+};
+
+static struct qcom_icc_node qxm_dsp0 = {
+ .name = "qxm_dsp0",
+ .id = QCS8300_MASTER_DSP0,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_GP_DSP_SAIL_NOC },
+};
+
+static struct qcom_icc_node qhm_config_noc = {
+ .name = "qhm_config_noc",
+ .id = QCS8300_MASTER_CNOC_LPASS_AG_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 6,
+ .links = { QCS8300_SLAVE_LPASS_CORE_CFG, QCS8300_SLAVE_LPASS_LPI_CFG,
+ QCS8300_SLAVE_LPASS_MPU_CFG, QCS8300_SLAVE_LPASS_TOP_CFG,
+ QCS8300_SLAVE_SERVICES_LPASS_AML_NOC, QCS8300_SLAVE_SERVICE_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node qxm_lpass_dsp = {
+ .name = "qxm_lpass_dsp",
+ .id = QCS8300_MASTER_LPASS_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 4,
+ .links = { QCS8300_SLAVE_LPASS_TOP_CFG, QCS8300_SLAVE_LPASS_SNOC,
+ QCS8300_SLAVE_SERVICES_LPASS_AML_NOC, QCS8300_SLAVE_SERVICE_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node llcc_mc = {
+ .name = "llcc_mc",
+ .id = QCS8300_MASTER_LLCC,
+ .channels = 8,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_EBI1 },
+};
+
+static struct qcom_icc_node qnm_camnoc_hf = {
+ .name = "qnm_camnoc_hf",
+ .id = QCS8300_MASTER_CAMNOC_HF,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_camnoc_icp = {
+ .name = "qnm_camnoc_icp",
+ .id = QCS8300_MASTER_CAMNOC_ICP,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_camnoc_sf = {
+ .name = "qnm_camnoc_sf",
+ .id = QCS8300_MASTER_CAMNOC_SF,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_mdp0_0 = {
+ .name = "qnm_mdp0_0",
+ .id = QCS8300_MASTER_MDP0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_mdp0_1 = {
+ .name = "qnm_mdp0_1",
+ .id = QCS8300_MASTER_MDP1,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_mnoc_hf_cfg = {
+ .name = "qnm_mnoc_hf_cfg",
+ .id = QCS8300_MASTER_CNOC_MNOC_HF_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SERVICE_MNOC_HF },
+};
+
+static struct qcom_icc_node qnm_mnoc_sf_cfg = {
+ .name = "qnm_mnoc_sf_cfg",
+ .id = QCS8300_MASTER_CNOC_MNOC_SF_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SERVICE_MNOC_SF },
+};
+
+static struct qcom_icc_node qnm_video0 = {
+ .name = "qnm_video0",
+ .id = QCS8300_MASTER_VIDEO_P0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_video_cvp = {
+ .name = "qnm_video_cvp",
+ .id = QCS8300_MASTER_VIDEO_PROC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_video_v_cpu = {
+ .name = "qnm_video_v_cpu",
+ .id = QCS8300_MASTER_VIDEO_V_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qhm_nsp_noc_config = {
+ .name = "qhm_nsp_noc_config",
+ .id = QCS8300_MASTER_CDSP_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SERVICE_NSP_NOC },
+};
+
+static struct qcom_icc_node qxm_nsp = {
+ .name = "qxm_nsp",
+ .id = QCS8300_MASTER_CDSP_PROC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_HCP_A, QCS8300_SLAVE_CDSP_MEM_NOC },
+};
+
+static struct qcom_icc_node xm_pcie3_0 = {
+ .name = "xm_pcie3_0",
+ .id = QCS8300_MASTER_PCIE_0,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_ANOC_PCIE_GEM_NOC },
+};
+
+static struct qcom_icc_node xm_pcie3_1 = {
+ .name = "xm_pcie3_1",
+ .id = QCS8300_MASTER_PCIE_1,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_ANOC_PCIE_GEM_NOC },
+};
+
+static struct qcom_icc_node qhm_gic = {
+ .name = "qhm_gic",
+ .id = QCS8300_MASTER_GIC_AHB,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_aggre1_noc = {
+ .name = "qnm_aggre1_noc",
+ .id = QCS8300_MASTER_A1NOC_SNOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_aggre2_noc = {
+ .name = "qnm_aggre2_noc",
+ .id = QCS8300_MASTER_A2NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_lpass_noc = {
+ .name = "qnm_lpass_noc",
+ .id = QCS8300_MASTER_LPASS_ANOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_snoc_cfg = {
+ .name = "qnm_snoc_cfg",
+ .id = QCS8300_MASTER_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SERVICE_SNOC },
+};
+
+static struct qcom_icc_node qxm_pimem = {
+ .name = "qxm_pimem",
+ .id = QCS8300_MASTER_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_GC },
+};
+
+static struct qcom_icc_node xm_gic = {
+ .name = "xm_gic",
+ .id = QCS8300_MASTER_GIC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_GC },
+};
+
+static struct qcom_icc_node qns_a1noc_snoc = {
+ .name = "qns_a1noc_snoc",
+ .id = QCS8300_SLAVE_A1NOC_SNOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qns_a2noc_snoc = {
+ .name = "qns_a2noc_snoc",
+ .id = QCS8300_SLAVE_A2NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qup0_core_slave = {
+ .name = "qup0_core_slave",
+ .id = QCS8300_SLAVE_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qup1_core_slave = {
+ .name = "qup1_core_slave",
+ .id = QCS8300_SLAVE_QUP_CORE_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qup3_core_slave = {
+ .name = "qup3_core_slave",
+ .id = QCS8300_SLAVE_QUP_CORE_3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ahb2phy2 = {
+ .name = "qhs_ahb2phy2",
+ .id = QCS8300_SLAVE_AHB2PHY_2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ahb2phy3 = {
+ .name = "qhs_ahb2phy3",
+ .id = QCS8300_SLAVE_AHB2PHY_3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_anoc_throttle_cfg = {
+ .name = "qhs_anoc_throttle_cfg",
+ .id = QCS8300_SLAVE_ANOC_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_aoss = {
+ .name = "qhs_aoss",
+ .id = QCS8300_SLAVE_AOSS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_apss = {
+ .name = "qhs_apss",
+ .id = QCS8300_SLAVE_APPSS,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_boot_rom = {
+ .name = "qhs_boot_rom",
+ .id = QCS8300_SLAVE_BOOT_ROM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_cfg = {
+ .name = "qhs_camera_cfg",
+ .id = QCS8300_SLAVE_CAMERA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_nrt_throttle_cfg = {
+ .name = "qhs_camera_nrt_throttle_cfg",
+ .id = QCS8300_SLAVE_CAMERA_NRT_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_rt_throttle_cfg = {
+ .name = "qhs_camera_rt_throttle_cfg",
+ .id = QCS8300_SLAVE_CAMERA_RT_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_clk_ctl = {
+ .name = "qhs_clk_ctl",
+ .id = QCS8300_SLAVE_CLK_CTL,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_compute0_cfg = {
+ .name = "qhs_compute0_cfg",
+ .id = QCS8300_SLAVE_CDSP_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CDSP_NOC_CFG },
+};
+
+static struct qcom_icc_node qhs_cpr_cx = {
+ .name = "qhs_cpr_cx",
+ .id = QCS8300_SLAVE_RBCPR_CX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mmcx = {
+ .name = "qhs_cpr_mmcx",
+ .id = QCS8300_SLAVE_RBCPR_MMCX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mx = {
+ .name = "qhs_cpr_mx",
+ .id = QCS8300_SLAVE_RBCPR_MX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_nspcx = {
+ .name = "qhs_cpr_nspcx",
+ .id = QCS8300_SLAVE_CPR_NSPCX,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_nsphmx = {
+ .name = "qhs_cpr_nsphmx",
+ .id = QCS8300_SLAVE_CPR_NSPHMX,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_crypto0_cfg = {
+ .name = "qhs_crypto0_cfg",
+ .id = QCS8300_SLAVE_CRYPTO_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cx_rdpm = {
+ .name = "qhs_cx_rdpm",
+ .id = QCS8300_SLAVE_CX_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_display0_cfg = {
+ .name = "qhs_display0_cfg",
+ .id = QCS8300_SLAVE_DISPLAY_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_display0_rt_throttle_cfg = {
+ .name = "qhs_display0_rt_throttle_cfg",
+ .id = QCS8300_SLAVE_DISPLAY_RT_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_emac0_cfg = {
+ .name = "qhs_emac0_cfg",
+ .id = QCS8300_SLAVE_EMAC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gp_dsp0_cfg = {
+ .name = "qhs_gp_dsp0_cfg",
+ .id = QCS8300_SLAVE_GP_DSP0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpdsp0_throttle_cfg = {
+ .name = "qhs_gpdsp0_throttle_cfg",
+ .id = QCS8300_SLAVE_GPDSP0_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpu_tcu_throttle_cfg = {
+ .name = "qhs_gpu_tcu_throttle_cfg",
+ .id = QCS8300_SLAVE_GPU_TCU_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpuss_cfg = {
+ .name = "qhs_gpuss_cfg",
+ .id = QCS8300_SLAVE_GFX3D_CFG,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_hwkm = {
+ .name = "qhs_hwkm",
+ .id = QCS8300_SLAVE_HWKM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_imem_cfg = {
+ .name = "qhs_imem_cfg",
+ .id = QCS8300_SLAVE_IMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ipa = {
+ .name = "qhs_ipa",
+ .id = QCS8300_SLAVE_IPA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ipc_router = {
+ .name = "qhs_ipc_router",
+ .id = QCS8300_SLAVE_IPC_ROUTER_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_cfg = {
+ .name = "qhs_lpass_cfg",
+ .id = QCS8300_SLAVE_LPASS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CNOC_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node qhs_lpass_throttle_cfg = {
+ .name = "qhs_lpass_throttle_cfg",
+ .id = QCS8300_SLAVE_LPASS_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_mx_rdpm = {
+ .name = "qhs_mx_rdpm",
+ .id = QCS8300_SLAVE_MX_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_mxc_rdpm = {
+ .name = "qhs_mxc_rdpm",
+ .id = QCS8300_SLAVE_MXC_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie0_cfg = {
+ .name = "qhs_pcie0_cfg",
+ .id = QCS8300_SLAVE_PCIE_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie1_cfg = {
+ .name = "qhs_pcie1_cfg",
+ .id = QCS8300_SLAVE_PCIE_1_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie_tcu_throttle_cfg = {
+ .name = "qhs_pcie_tcu_throttle_cfg",
+ .id = QCS8300_SLAVE_PCIE_TCU_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie_throttle_cfg = {
+ .name = "qhs_pcie_throttle_cfg",
+ .id = QCS8300_SLAVE_PCIE_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pdm = {
+ .name = "qhs_pdm",
+ .id = QCS8300_SLAVE_PDM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pimem_cfg = {
+ .name = "qhs_pimem_cfg",
+ .id = QCS8300_SLAVE_PIMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pke_wrapper_cfg = {
+ .name = "qhs_pke_wrapper_cfg",
+ .id = QCS8300_SLAVE_PKA_WRAPPER_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qdss_cfg = {
+ .name = "qhs_qdss_cfg",
+ .id = QCS8300_SLAVE_QDSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qm_cfg = {
+ .name = "qhs_qm_cfg",
+ .id = QCS8300_SLAVE_QM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qm_mpu_cfg = {
+ .name = "qhs_qm_mpu_cfg",
+ .id = QCS8300_SLAVE_QM_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup0 = {
+ .name = "qhs_qup0",
+ .id = QCS8300_SLAVE_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup1 = {
+ .name = "qhs_qup1",
+ .id = QCS8300_SLAVE_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup3 = {
+ .name = "qhs_qup3",
+ .id = QCS8300_SLAVE_QUP_3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sail_throttle_cfg = {
+ .name = "qhs_sail_throttle_cfg",
+ .id = QCS8300_SLAVE_SAIL_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sdc1 = {
+ .name = "qhs_sdc1",
+ .id = QCS8300_SLAVE_SDC1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_security = {
+ .name = "qhs_security",
+ .id = QCS8300_SLAVE_SECURITY,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_snoc_throttle_cfg = {
+ .name = "qhs_snoc_throttle_cfg",
+ .id = QCS8300_SLAVE_SNOC_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tcsr = {
+ .name = "qhs_tcsr",
+ .id = QCS8300_SLAVE_TCSR,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm = {
+ .name = "qhs_tlmm",
+ .id = QCS8300_SLAVE_TLMM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tsc_cfg = {
+ .name = "qhs_tsc_cfg",
+ .id = QCS8300_SLAVE_TSC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ufs_mem_cfg = {
+ .name = "qhs_ufs_mem_cfg",
+ .id = QCS8300_SLAVE_UFS_MEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb2_0 = {
+ .name = "qhs_usb2_0",
+ .id = QCS8300_SLAVE_USB2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb3_0 = {
+ .name = "qhs_usb3_0",
+ .id = QCS8300_SLAVE_USB3_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_cfg = {
+ .name = "qhs_venus_cfg",
+ .id = QCS8300_SLAVE_VENUS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_cvp_throttle_cfg = {
+ .name = "qhs_venus_cvp_throttle_cfg",
+ .id = QCS8300_SLAVE_VENUS_CVP_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_v_cpu_throttle_cfg = {
+ .name = "qhs_venus_v_cpu_throttle_cfg",
+ .id = QCS8300_SLAVE_VENUS_V_CPU_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_vcodec_throttle_cfg = {
+ .name = "qhs_venus_vcodec_throttle_cfg",
+ .id = QCS8300_SLAVE_VENUS_VCODEC_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_ddrss_cfg = {
+ .name = "qns_ddrss_cfg",
+ .id = QCS8300_SLAVE_DDRSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CNOC_DC_NOC },
+};
+
+static struct qcom_icc_node qns_gpdsp_noc_cfg = {
+ .name = "qns_gpdsp_noc_cfg",
+ .id = QCS8300_SLAVE_GPDSP_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_mnoc_hf_cfg = {
+ .name = "qns_mnoc_hf_cfg",
+ .id = QCS8300_SLAVE_CNOC_MNOC_HF_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CNOC_MNOC_HF_CFG },
+};
+
+static struct qcom_icc_node qns_mnoc_sf_cfg = {
+ .name = "qns_mnoc_sf_cfg",
+ .id = QCS8300_SLAVE_CNOC_MNOC_SF_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CNOC_MNOC_SF_CFG },
+};
+
+static struct qcom_icc_node qns_pcie_anoc_cfg = {
+ .name = "qns_pcie_anoc_cfg",
+ .id = QCS8300_SLAVE_PCIE_ANOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_snoc_cfg = {
+ .name = "qns_snoc_cfg",
+ .id = QCS8300_SLAVE_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_SNOC_CFG },
+};
+
+static struct qcom_icc_node qxs_boot_imem = {
+ .name = "qxs_boot_imem",
+ .id = QCS8300_SLAVE_BOOT_IMEM,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qxs_imem = {
+ .name = "qxs_imem",
+ .id = QCS8300_SLAVE_IMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qxs_pimem = {
+ .name = "qxs_pimem",
+ .id = QCS8300_SLAVE_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie_0 = {
+ .name = "xs_pcie_0",
+ .id = QCS8300_SLAVE_PCIE_0,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie_1 = {
+ .name = "xs_pcie_1",
+ .id = QCS8300_SLAVE_PCIE_1,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_qdss_stm = {
+ .name = "xs_qdss_stm",
+ .id = QCS8300_SLAVE_QDSS_STM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_sys_tcu_cfg = {
+ .name = "xs_sys_tcu_cfg",
+ .id = QCS8300_SLAVE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_llcc = {
+ .name = "qhs_llcc",
+ .id = QCS8300_SLAVE_LLCC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_gemnoc = {
+ .name = "qns_gemnoc",
+ .id = QCS8300_SLAVE_GEM_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_GEM_NOC_CFG },
+};
+
+static struct qcom_icc_node qns_gem_noc_cnoc = {
+ .name = "qns_gem_noc_cnoc",
+ .id = QCS8300_SLAVE_GEM_NOC_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_GEM_NOC_CNOC },
+};
+
+static struct qcom_icc_node qns_llcc = {
+ .name = "qns_llcc",
+ .id = QCS8300_SLAVE_LLCC,
+ .channels = 4,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_LLCC },
+};
+
+static struct qcom_icc_node qns_pcie = {
+ .name = "qns_pcie",
+ .id = QCS8300_SLAVE_GEM_NOC_PCIE_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_GEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node srvc_even_gemnoc = {
+ .name = "srvc_even_gemnoc",
+ .id = QCS8300_SLAVE_SERVICE_GEM_NOC_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_odd_gemnoc = {
+ .name = "srvc_odd_gemnoc",
+ .id = QCS8300_SLAVE_SERVICE_GEM_NOC_2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_sys_gemnoc = {
+ .name = "srvc_sys_gemnoc",
+ .id = QCS8300_SLAVE_SERVICE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_sys_gemnoc_2 = {
+ .name = "srvc_sys_gemnoc_2",
+ .id = QCS8300_SLAVE_SERVICE_GEM_NOC2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_gp_dsp_sail_noc = {
+ .name = "qns_gp_dsp_sail_noc",
+ .id = QCS8300_SLAVE_GP_DSP_SAIL_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_GPDSP_SAIL },
+};
+
+static struct qcom_icc_node qhs_lpass_core = {
+ .name = "qhs_lpass_core",
+ .id = QCS8300_SLAVE_LPASS_CORE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_lpi = {
+ .name = "qhs_lpass_lpi",
+ .id = QCS8300_SLAVE_LPASS_LPI_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_mpu = {
+ .name = "qhs_lpass_mpu",
+ .id = QCS8300_SLAVE_LPASS_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_top = {
+ .name = "qhs_lpass_top",
+ .id = QCS8300_SLAVE_LPASS_TOP_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_sysnoc = {
+ .name = "qns_sysnoc",
+ .id = QCS8300_SLAVE_LPASS_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_LPASS_ANOC },
+};
+
+static struct qcom_icc_node srvc_niu_aml_noc = {
+ .name = "srvc_niu_aml_noc",
+ .id = QCS8300_SLAVE_SERVICES_LPASS_AML_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_niu_lpass_agnoc = {
+ .name = "srvc_niu_lpass_agnoc",
+ .id = QCS8300_SLAVE_SERVICE_LPASS_AG_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node ebi = {
+ .name = "ebi",
+ .id = QCS8300_SLAVE_EBI1,
+ .channels = 8,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_mem_noc_hf = {
+ .name = "qns_mem_noc_hf",
+ .id = QCS8300_SLAVE_MNOC_HF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_mem_noc_sf = {
+ .name = "qns_mem_noc_sf",
+ .id = QCS8300_SLAVE_MNOC_SF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_mnoc_hf = {
+ .name = "srvc_mnoc_hf",
+ .id = QCS8300_SLAVE_SERVICE_MNOC_HF,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_mnoc_sf = {
+ .name = "srvc_mnoc_sf",
+ .id = QCS8300_SLAVE_SERVICE_MNOC_SF,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_hcp = {
+ .name = "qns_hcp",
+ .id = QCS8300_SLAVE_HCP_A,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_nsp_gemnoc = {
+ .name = "qns_nsp_gemnoc",
+ .id = QCS8300_SLAVE_CDSP_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_COMPUTE_NOC },
+};
+
+static struct qcom_icc_node service_nsp_noc = {
+ .name = "service_nsp_noc",
+ .id = QCS8300_SLAVE_SERVICE_NSP_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_pcie_mem_noc = {
+ .name = "qns_pcie_mem_noc",
+ .id = QCS8300_SLAVE_ANOC_PCIE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_ANOC_PCIE_GEM_NOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_gc = {
+ .name = "qns_gemnoc_gc",
+ .id = QCS8300_SLAVE_SNOC_GEM_NOC_GC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_SNOC_GC_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_sf = {
+ .name = "qns_gemnoc_sf",
+ .id = QCS8300_SLAVE_SNOC_GEM_NOC_SF,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_SNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_snoc = {
+ .name = "srvc_snoc",
+ .id = QCS8300_SLAVE_SERVICE_SNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_bcm bcm_acv = {
+ .name = "ACV",
+ .enable_mask = BIT(3),
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_ce0 = {
+ .name = "CE0",
+ .num_nodes = 2,
+ .nodes = { &qxm_crypto_0, &qxm_crypto_1 },
+};
+
+static struct qcom_icc_bcm bcm_cn0 = {
+ .name = "CN0",
+ .keepalive = true,
+ .num_nodes = 2,
+ .nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie },
+};
+
+static struct qcom_icc_bcm bcm_cn1 = {
+ .name = "CN1",
+ .num_nodes = 66,
+ .nodes = { &qhs_ahb2phy2, &qhs_ahb2phy3,
+ &qhs_anoc_throttle_cfg, &qhs_aoss,
+ &qhs_apss, &qhs_boot_rom,
+ &qhs_camera_cfg, &qhs_camera_nrt_throttle_cfg,
+ &qhs_camera_rt_throttle_cfg, &qhs_clk_ctl,
+ &qhs_compute0_cfg, &qhs_cpr_cx,
+ &qhs_cpr_mmcx, &qhs_cpr_mx,
+ &qhs_cpr_nspcx, &qhs_cpr_nsphmx,
+ &qhs_crypto0_cfg, &qhs_cx_rdpm,
+ &qhs_display0_cfg, &qhs_display0_rt_throttle_cfg,
+ &qhs_emac0_cfg, &qhs_gp_dsp0_cfg,
+ &qhs_gpdsp0_throttle_cfg, &qhs_gpu_tcu_throttle_cfg,
+ &qhs_gpuss_cfg, &qhs_hwkm,
+ &qhs_imem_cfg, &qhs_ipa,
+ &qhs_ipc_router, &qhs_lpass_cfg,
+ &qhs_lpass_throttle_cfg, &qhs_mx_rdpm,
+ &qhs_mxc_rdpm, &qhs_pcie0_cfg,
+ &qhs_pcie1_cfg, &qhs_pcie_tcu_throttle_cfg,
+ &qhs_pcie_throttle_cfg, &qhs_pdm,
+ &qhs_pimem_cfg, &qhs_pke_wrapper_cfg,
+ &qhs_qdss_cfg, &qhs_qm_cfg,
+ &qhs_qm_mpu_cfg, &qhs_sail_throttle_cfg,
+ &qhs_sdc1, &qhs_security,
+ &qhs_snoc_throttle_cfg, &qhs_tcsr,
+ &qhs_tlmm, &qhs_tsc_cfg,
+ &qhs_ufs_mem_cfg, &qhs_usb2_0,
+ &qhs_usb3_0, &qhs_venus_cfg,
+ &qhs_venus_cvp_throttle_cfg, &qhs_venus_v_cpu_throttle_cfg,
+ &qhs_venus_vcodec_throttle_cfg, &qns_ddrss_cfg,
+ &qns_gpdsp_noc_cfg, &qns_mnoc_hf_cfg,
+ &qns_mnoc_sf_cfg, &qns_pcie_anoc_cfg,
+ &qns_snoc_cfg, &qxs_boot_imem,
+ &qxs_imem, &xs_sys_tcu_cfg },
+};
+
+static struct qcom_icc_bcm bcm_cn2 = {
+ .name = "CN2",
+ .num_nodes = 3,
+ .nodes = { &qhs_qup0, &qhs_qup1,
+ &qhs_qup3 },
+};
+
+static struct qcom_icc_bcm bcm_cn3 = {
+ .name = "CN3",
+ .num_nodes = 2,
+ .nodes = { &xs_pcie_0, &xs_pcie_1 },
+};
+
+static struct qcom_icc_bcm bcm_gna0 = {
+ .name = "GNA0",
+ .num_nodes = 1,
+ .nodes = { &qxm_dsp0 },
+};
+
+static struct qcom_icc_bcm bcm_mc0 = {
+ .name = "MC0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_mm0 = {
+ .name = "MM0",
+ .keepalive = true,
+ .num_nodes = 4,
+ .nodes = { &qnm_camnoc_hf, &qnm_mdp0_0,
+ &qnm_mdp0_1, &qns_mem_noc_hf },
+};
+
+static struct qcom_icc_bcm bcm_mm1 = {
+ .name = "MM1",
+ .num_nodes = 6,
+ .nodes = { &qnm_camnoc_icp, &qnm_camnoc_sf,
+ &qnm_video0, &qnm_video_cvp,
+ &qnm_video_v_cpu, &qns_mem_noc_sf },
+};
+
+static struct qcom_icc_bcm bcm_nsa0 = {
+ .name = "NSA0",
+ .num_nodes = 2,
+ .nodes = { &qns_hcp, &qns_nsp_gemnoc },
+};
+
+static struct qcom_icc_bcm bcm_nsa1 = {
+ .name = "NSA1",
+ .num_nodes = 1,
+ .nodes = { &qxm_nsp },
+};
+
+static struct qcom_icc_bcm bcm_pci0 = {
+ .name = "PCI0",
+ .num_nodes = 1,
+ .nodes = { &qns_pcie_mem_noc },
+};
+
+static struct qcom_icc_bcm bcm_qup0 = {
+ .name = "QUP0",
+ .vote_scale = 1,
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qup0_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_qup1 = {
+ .name = "QUP1",
+ .vote_scale = 1,
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qup1_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_qup2 = {
+ .name = "QUP2",
+ .vote_scale = 1,
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qup3_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_sh0 = {
+ .name = "SH0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_llcc },
+};
+
+static struct qcom_icc_bcm bcm_sh2 = {
+ .name = "SH2",
+ .num_nodes = 1,
+ .nodes = { &chm_apps },
+};
+
+static struct qcom_icc_bcm bcm_sn0 = {
+ .name = "SN0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_bcm bcm_sn1 = {
+ .name = "SN1",
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_gc },
+};
+
+static struct qcom_icc_bcm bcm_sn2 = {
+ .name = "SN2",
+ .num_nodes = 1,
+ .nodes = { &qxs_pimem },
+};
+
+static struct qcom_icc_bcm bcm_sn3 = {
+ .name = "SN3",
+ .num_nodes = 2,
+ .nodes = { &qns_a1noc_snoc, &qnm_aggre1_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn4 = {
+ .name = "SN4",
+ .num_nodes = 2,
+ .nodes = { &qns_a2noc_snoc, &qnm_aggre2_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn9 = {
+ .name = "SN9",
+ .num_nodes = 2,
+ .nodes = { &qns_sysnoc, &qnm_lpass_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn10 = {
+ .name = "SN10",
+ .num_nodes = 1,
+ .nodes = { &xs_qdss_stm },
+};
+
+static struct qcom_icc_bcm * const aggre1_noc_bcms[] = {
+ &bcm_sn3,
+};
+
+static struct qcom_icc_node * const aggre1_noc_nodes[] = {
+ [MASTER_QUP_3] = &qxm_qup3,
+ [MASTER_EMAC] = &xm_emac_0,
+ [MASTER_SDC] = &xm_sdc1,
+ [MASTER_UFS_MEM] = &xm_ufs_mem,
+ [MASTER_USB2] = &xm_usb2_2,
+ [MASTER_USB3_0] = &xm_usb3_0,
+ [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc,
+};
+
+static const struct qcom_icc_desc qcs8300_aggre1_noc = {
+ .nodes = aggre1_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
+ .bcms = aggre1_noc_bcms,
+ .num_bcms = ARRAY_SIZE(aggre1_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const aggre2_noc_bcms[] = {
+ &bcm_ce0,
+ &bcm_sn4,
+};
+
+static struct qcom_icc_node * const aggre2_noc_nodes[] = {
+ [MASTER_QDSS_BAM] = &qhm_qdss_bam,
+ [MASTER_QUP_0] = &qhm_qup0,
+ [MASTER_QUP_1] = &qhm_qup1,
+ [MASTER_CNOC_A2NOC] = &qnm_cnoc_datapath,
+ [MASTER_CRYPTO_CORE0] = &qxm_crypto_0,
+ [MASTER_CRYPTO_CORE1] = &qxm_crypto_1,
+ [MASTER_IPA] = &qxm_ipa,
+ [MASTER_QDSS_ETR_0] = &xm_qdss_etr_0,
+ [MASTER_QDSS_ETR_1] = &xm_qdss_etr_1,
+ [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc,
+};
+
+static const struct qcom_icc_desc qcs8300_aggre2_noc = {
+ .nodes = aggre2_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre2_noc_nodes),
+ .bcms = aggre2_noc_bcms,
+ .num_bcms = ARRAY_SIZE(aggre2_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const clk_virt_bcms[] = {
+ &bcm_qup0,
+ &bcm_qup1,
+ &bcm_qup2,
+};
+
+static struct qcom_icc_node * const clk_virt_nodes[] = {
+ [MASTER_QUP_CORE_0] = &qup0_core_master,
+ [MASTER_QUP_CORE_1] = &qup1_core_master,
+ [MASTER_QUP_CORE_3] = &qup3_core_master,
+ [SLAVE_QUP_CORE_0] = &qup0_core_slave,
+ [SLAVE_QUP_CORE_1] = &qup1_core_slave,
+ [SLAVE_QUP_CORE_3] = &qup3_core_slave,
+};
+
+static const struct qcom_icc_desc qcs8300_clk_virt = {
+ .nodes = clk_virt_nodes,
+ .num_nodes = ARRAY_SIZE(clk_virt_nodes),
+ .bcms = clk_virt_bcms,
+ .num_bcms = ARRAY_SIZE(clk_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const config_noc_bcms[] = {
+ &bcm_cn0,
+ &bcm_cn1,
+ &bcm_cn2,
+ &bcm_cn3,
+ &bcm_sn2,
+ &bcm_sn10,
+};
+
+static struct qcom_icc_node * const config_noc_nodes[] = {
+ [MASTER_GEM_NOC_CNOC] = &qnm_gemnoc_cnoc,
+ [MASTER_GEM_NOC_PCIE_SNOC] = &qnm_gemnoc_pcie,
+ [SLAVE_AHB2PHY_2] = &qhs_ahb2phy2,
+ [SLAVE_AHB2PHY_3] = &qhs_ahb2phy3,
+ [SLAVE_ANOC_THROTTLE_CFG] = &qhs_anoc_throttle_cfg,
+ [SLAVE_AOSS] = &qhs_aoss,
+ [SLAVE_APPSS] = &qhs_apss,
+ [SLAVE_BOOT_ROM] = &qhs_boot_rom,
+ [SLAVE_CAMERA_CFG] = &qhs_camera_cfg,
+ [SLAVE_CAMERA_NRT_THROTTLE_CFG] = &qhs_camera_nrt_throttle_cfg,
+ [SLAVE_CAMERA_RT_THROTTLE_CFG] = &qhs_camera_rt_throttle_cfg,
+ [SLAVE_CLK_CTL] = &qhs_clk_ctl,
+ [SLAVE_CDSP_CFG] = &qhs_compute0_cfg,
+ [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx,
+ [SLAVE_RBCPR_MMCX_CFG] = &qhs_cpr_mmcx,
+ [SLAVE_RBCPR_MX_CFG] = &qhs_cpr_mx,
+ [SLAVE_CPR_NSPCX] = &qhs_cpr_nspcx,
+ [SLAVE_CPR_NSPHMX] = &qhs_cpr_nsphmx,
+ [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
+ [SLAVE_CX_RDPM] = &qhs_cx_rdpm,
+ [SLAVE_DISPLAY_CFG] = &qhs_display0_cfg,
+ [SLAVE_DISPLAY_RT_THROTTLE_CFG] = &qhs_display0_rt_throttle_cfg,
+ [SLAVE_EMAC_CFG] = &qhs_emac0_cfg,
+ [SLAVE_GP_DSP0_CFG] = &qhs_gp_dsp0_cfg,
+ [SLAVE_GPDSP0_THROTTLE_CFG] = &qhs_gpdsp0_throttle_cfg,
+ [SLAVE_GPU_TCU_THROTTLE_CFG] = &qhs_gpu_tcu_throttle_cfg,
+ [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg,
+ [SLAVE_HWKM] = &qhs_hwkm,
+ [SLAVE_IMEM_CFG] = &qhs_imem_cfg,
+ [SLAVE_IPA_CFG] = &qhs_ipa,
+ [SLAVE_IPC_ROUTER_CFG] = &qhs_ipc_router,
+ [SLAVE_LPASS] = &qhs_lpass_cfg,
+ [SLAVE_LPASS_THROTTLE_CFG] = &qhs_lpass_throttle_cfg,
+ [SLAVE_MX_RDPM] = &qhs_mx_rdpm,
+ [SLAVE_MXC_RDPM] = &qhs_mxc_rdpm,
+ [SLAVE_PCIE_0_CFG] = &qhs_pcie0_cfg,
+ [SLAVE_PCIE_1_CFG] = &qhs_pcie1_cfg,
+ [SLAVE_PCIE_TCU_THROTTLE_CFG] = &qhs_pcie_tcu_throttle_cfg,
+ [SLAVE_PCIE_THROTTLE_CFG] = &qhs_pcie_throttle_cfg,
+ [SLAVE_PDM] = &qhs_pdm,
+ [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg,
+ [SLAVE_PKA_WRAPPER_CFG] = &qhs_pke_wrapper_cfg,
+ [SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
+ [SLAVE_QM_CFG] = &qhs_qm_cfg,
+ [SLAVE_QM_MPU_CFG] = &qhs_qm_mpu_cfg,
+ [SLAVE_QUP_0] = &qhs_qup0,
+ [SLAVE_QUP_1] = &qhs_qup1,
+ [SLAVE_QUP_3] = &qhs_qup3,
+ [SLAVE_SAIL_THROTTLE_CFG] = &qhs_sail_throttle_cfg,
+ [SLAVE_SDC1] = &qhs_sdc1,
+ [SLAVE_SECURITY] = &qhs_security,
+ [SLAVE_SNOC_THROTTLE_CFG] = &qhs_snoc_throttle_cfg,
+ [SLAVE_TCSR] = &qhs_tcsr,
+ [SLAVE_TLMM] = &qhs_tlmm,
+ [SLAVE_TSC_CFG] = &qhs_tsc_cfg,
+ [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg,
+ [SLAVE_USB2] = &qhs_usb2_0,
+ [SLAVE_USB3_0] = &qhs_usb3_0,
+ [SLAVE_VENUS_CFG] = &qhs_venus_cfg,
+ [SLAVE_VENUS_CVP_THROTTLE_CFG] = &qhs_venus_cvp_throttle_cfg,
+ [SLAVE_VENUS_V_CPU_THROTTLE_CFG] = &qhs_venus_v_cpu_throttle_cfg,
+ [SLAVE_VENUS_VCODEC_THROTTLE_CFG] = &qhs_venus_vcodec_throttle_cfg,
+ [SLAVE_DDRSS_CFG] = &qns_ddrss_cfg,
+ [SLAVE_GPDSP_NOC_CFG] = &qns_gpdsp_noc_cfg,
+ [SLAVE_CNOC_MNOC_HF_CFG] = &qns_mnoc_hf_cfg,
+ [SLAVE_CNOC_MNOC_SF_CFG] = &qns_mnoc_sf_cfg,
+ [SLAVE_PCIE_ANOC_CFG] = &qns_pcie_anoc_cfg,
+ [SLAVE_SNOC_CFG] = &qns_snoc_cfg,
+ [SLAVE_BOOT_IMEM] = &qxs_boot_imem,
+ [SLAVE_IMEM] = &qxs_imem,
+ [SLAVE_PIMEM] = &qxs_pimem,
+ [SLAVE_PCIE_0] = &xs_pcie_0,
+ [SLAVE_PCIE_1] = &xs_pcie_1,
+ [SLAVE_QDSS_STM] = &xs_qdss_stm,
+ [SLAVE_TCU] = &xs_sys_tcu_cfg,
+};
+
+static const struct qcom_icc_desc qcs8300_config_noc = {
+ .nodes = config_noc_nodes,
+ .num_nodes = ARRAY_SIZE(config_noc_nodes),
+ .bcms = config_noc_bcms,
+ .num_bcms = ARRAY_SIZE(config_noc_bcms),
+};
+
+static struct qcom_icc_node * const dc_noc_nodes[] = {
+ [MASTER_CNOC_DC_NOC] = &qnm_cnoc_dc_noc,
+ [SLAVE_LLCC_CFG] = &qhs_llcc,
+ [SLAVE_GEM_NOC_CFG] = &qns_gemnoc,
+};
+
+static const struct qcom_icc_desc qcs8300_dc_noc = {
+ .nodes = dc_noc_nodes,
+ .num_nodes = ARRAY_SIZE(dc_noc_nodes),
+};
+
+static struct qcom_icc_bcm * const gem_noc_bcms[] = {
+ &bcm_sh0,
+ &bcm_sh2,
+};
+
+static struct qcom_icc_node * const gem_noc_nodes[] = {
+ [MASTER_GPU_TCU] = &alm_gpu_tcu,
+ [MASTER_PCIE_TCU] = &alm_pcie_tcu,
+ [MASTER_SYS_TCU] = &alm_sys_tcu,
+ [MASTER_APPSS_PROC] = &chm_apps,
+ [MASTER_COMPUTE_NOC] = &qnm_cmpnoc0,
+ [MASTER_GEM_NOC_CFG] = &qnm_gemnoc_cfg,
+ [MASTER_GPDSP_SAIL] = &qnm_gpdsp_sail,
+ [MASTER_GFX3D] = &qnm_gpu,
+ [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf,
+ [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf,
+ [MASTER_ANOC_PCIE_GEM_NOC] = &qnm_pcie,
+ [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc,
+ [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf,
+ [SLAVE_GEM_NOC_CNOC] = &qns_gem_noc_cnoc,
+ [SLAVE_LLCC] = &qns_llcc,
+ [SLAVE_GEM_NOC_PCIE_CNOC] = &qns_pcie,
+ [SLAVE_SERVICE_GEM_NOC_1] = &srvc_even_gemnoc,
+ [SLAVE_SERVICE_GEM_NOC_2] = &srvc_odd_gemnoc,
+ [SLAVE_SERVICE_GEM_NOC] = &srvc_sys_gemnoc,
+ [SLAVE_SERVICE_GEM_NOC2] = &srvc_sys_gemnoc_2,
+};
+
+static const struct qcom_icc_desc qcs8300_gem_noc = {
+ .nodes = gem_noc_nodes,
+ .num_nodes = ARRAY_SIZE(gem_noc_nodes),
+ .bcms = gem_noc_bcms,
+ .num_bcms = ARRAY_SIZE(gem_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const gpdsp_anoc_bcms[] = {
+ &bcm_gna0,
+};
+
+static struct qcom_icc_node * const gpdsp_anoc_nodes[] = {
+ [MASTER_SAILSS_MD0] = &qnm_sailss_md0,
+ [MASTER_DSP0] = &qxm_dsp0,
+ [SLAVE_GP_DSP_SAIL_NOC] = &qns_gp_dsp_sail_noc,
+};
+
+static const struct qcom_icc_desc qcs8300_gpdsp_anoc = {
+ .nodes = gpdsp_anoc_nodes,
+ .num_nodes = ARRAY_SIZE(gpdsp_anoc_nodes),
+ .bcms = gpdsp_anoc_bcms,
+ .num_bcms = ARRAY_SIZE(gpdsp_anoc_bcms),
+};
+
+static struct qcom_icc_bcm * const lpass_ag_noc_bcms[] = {
+ &bcm_sn9,
+};
+
+static struct qcom_icc_node * const lpass_ag_noc_nodes[] = {
+ [MASTER_CNOC_LPASS_AG_NOC] = &qhm_config_noc,
+ [MASTER_LPASS_PROC] = &qxm_lpass_dsp,
+ [SLAVE_LPASS_CORE_CFG] = &qhs_lpass_core,
+ [SLAVE_LPASS_LPI_CFG] = &qhs_lpass_lpi,
+ [SLAVE_LPASS_MPU_CFG] = &qhs_lpass_mpu,
+ [SLAVE_LPASS_TOP_CFG] = &qhs_lpass_top,
+ [SLAVE_LPASS_SNOC] = &qns_sysnoc,
+ [SLAVE_SERVICES_LPASS_AML_NOC] = &srvc_niu_aml_noc,
+ [SLAVE_SERVICE_LPASS_AG_NOC] = &srvc_niu_lpass_agnoc,
+};
+
+static const struct qcom_icc_desc qcs8300_lpass_ag_noc = {
+ .nodes = lpass_ag_noc_nodes,
+ .num_nodes = ARRAY_SIZE(lpass_ag_noc_nodes),
+ .bcms = lpass_ag_noc_bcms,
+ .num_bcms = ARRAY_SIZE(lpass_ag_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const mc_virt_bcms[] = {
+ &bcm_acv,
+ &bcm_mc0,
+};
+
+static struct qcom_icc_node * const mc_virt_nodes[] = {
+ [MASTER_LLCC] = &llcc_mc,
+ [SLAVE_EBI1] = &ebi,
+};
+
+static const struct qcom_icc_desc qcs8300_mc_virt = {
+ .nodes = mc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mc_virt_nodes),
+ .bcms = mc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(mc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mmss_noc_bcms[] = {
+ &bcm_mm0,
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const mmss_noc_nodes[] = {
+ [MASTER_CAMNOC_HF] = &qnm_camnoc_hf,
+ [MASTER_CAMNOC_ICP] = &qnm_camnoc_icp,
+ [MASTER_CAMNOC_SF] = &qnm_camnoc_sf,
+ [MASTER_MDP0] = &qnm_mdp0_0,
+ [MASTER_MDP1] = &qnm_mdp0_1,
+ [MASTER_CNOC_MNOC_HF_CFG] = &qnm_mnoc_hf_cfg,
+ [MASTER_CNOC_MNOC_SF_CFG] = &qnm_mnoc_sf_cfg,
+ [MASTER_VIDEO_P0] = &qnm_video0,
+ [MASTER_VIDEO_PROC] = &qnm_video_cvp,
+ [MASTER_VIDEO_V_PROC] = &qnm_video_v_cpu,
+ [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf,
+ [SLAVE_MNOC_SF_MEM_NOC] = &qns_mem_noc_sf,
+ [SLAVE_SERVICE_MNOC_HF] = &srvc_mnoc_hf,
+ [SLAVE_SERVICE_MNOC_SF] = &srvc_mnoc_sf,
+};
+
+static const struct qcom_icc_desc qcs8300_mmss_noc = {
+ .nodes = mmss_noc_nodes,
+ .num_nodes = ARRAY_SIZE(mmss_noc_nodes),
+ .bcms = mmss_noc_bcms,
+ .num_bcms = ARRAY_SIZE(mmss_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const nspa_noc_bcms[] = {
+ &bcm_nsa0,
+ &bcm_nsa1,
+};
+
+static struct qcom_icc_node * const nspa_noc_nodes[] = {
+ [MASTER_CDSP_NOC_CFG] = &qhm_nsp_noc_config,
+ [MASTER_CDSP_PROC] = &qxm_nsp,
+ [SLAVE_HCP_A] = &qns_hcp,
+ [SLAVE_CDSP_MEM_NOC] = &qns_nsp_gemnoc,
+ [SLAVE_SERVICE_NSP_NOC] = &service_nsp_noc,
+};
+
+static const struct qcom_icc_desc qcs8300_nspa_noc = {
+ .nodes = nspa_noc_nodes,
+ .num_nodes = ARRAY_SIZE(nspa_noc_nodes),
+ .bcms = nspa_noc_bcms,
+ .num_bcms = ARRAY_SIZE(nspa_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const pcie_anoc_bcms[] = {
+ &bcm_pci0,
+};
+
+static struct qcom_icc_node * const pcie_anoc_nodes[] = {
+ [MASTER_PCIE_0] = &xm_pcie3_0,
+ [MASTER_PCIE_1] = &xm_pcie3_1,
+ [SLAVE_ANOC_PCIE_GEM_NOC] = &qns_pcie_mem_noc,
+};
+
+static const struct qcom_icc_desc qcs8300_pcie_anoc = {
+ .nodes = pcie_anoc_nodes,
+ .num_nodes = ARRAY_SIZE(pcie_anoc_nodes),
+ .bcms = pcie_anoc_bcms,
+ .num_bcms = ARRAY_SIZE(pcie_anoc_bcms),
+};
+
+static struct qcom_icc_bcm * const system_noc_bcms[] = {
+ &bcm_sn0,
+ &bcm_sn1,
+ &bcm_sn3,
+ &bcm_sn4,
+ &bcm_sn9,
+};
+
+static struct qcom_icc_node * const system_noc_nodes[] = {
+ [MASTER_GIC_AHB] = &qhm_gic,
+ [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc,
+ [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc,
+ [MASTER_LPASS_ANOC] = &qnm_lpass_noc,
+ [MASTER_SNOC_CFG] = &qnm_snoc_cfg,
+ [MASTER_PIMEM] = &qxm_pimem,
+ [MASTER_GIC] = &xm_gic,
+ [SLAVE_SNOC_GEM_NOC_GC] = &qns_gemnoc_gc,
+ [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf,
+ [SLAVE_SERVICE_SNOC] = &srvc_snoc,
+};
+
+static const struct qcom_icc_desc qcs8300_system_noc = {
+ .nodes = system_noc_nodes,
+ .num_nodes = ARRAY_SIZE(system_noc_nodes),
+ .bcms = system_noc_bcms,
+ .num_bcms = ARRAY_SIZE(system_noc_bcms),
+};
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,qcs8300-aggre1-noc",
+ .data = &qcs8300_aggre1_noc},
+ { .compatible = "qcom,qcs8300-aggre2-noc",
+ .data = &qcs8300_aggre2_noc},
+ { .compatible = "qcom,qcs8300-clk-virt",
+ .data = &qcs8300_clk_virt},
+ { .compatible = "qcom,qcs8300-config-noc",
+ .data = &qcs8300_config_noc},
+ { .compatible = "qcom,qcs8300-dc-noc",
+ .data = &qcs8300_dc_noc},
+ { .compatible = "qcom,qcs8300-gem-noc",
+ .data = &qcs8300_gem_noc},
+ { .compatible = "qcom,qcs8300-gpdsp-anoc",
+ .data = &qcs8300_gpdsp_anoc},
+ { .compatible = "qcom,qcs8300-lpass-ag-noc",
+ .data = &qcs8300_lpass_ag_noc},
+ { .compatible = "qcom,qcs8300-mc-virt",
+ .data = &qcs8300_mc_virt},
+ { .compatible = "qcom,qcs8300-mmss-noc",
+ .data = &qcs8300_mmss_noc},
+ { .compatible = "qcom,qcs8300-nspa-noc",
+ .data = &qcs8300_nspa_noc},
+ { .compatible = "qcom,qcs8300-pcie-anoc",
+ .data = &qcs8300_pcie_anoc},
+ { .compatible = "qcom,qcs8300-system-noc",
+ .data = &qcs8300_system_noc},
+ { }
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
+ .driver = {
+ .name = "qnoc-qcs8300",
+ .of_match_table = qnoc_of_match,
+ .sync_state = icc_sync_state,
+ },
+};
+
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+module_exit(qnoc_driver_exit);
+
+MODULE_DESCRIPTION("QCS8300 NoC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/interconnect/qcom/qcs8300.h b/drivers/interconnect/qcom/qcs8300.h
new file mode 100644
index 000000000000..6b9e2b424c2a
--- /dev/null
+++ b/drivers/interconnect/qcom/qcs8300.h
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __DRIVERS_INTERCONNECT_QCOM_QCS8300_H
+#define __DRIVERS_INTERCONNECT_QCOM_QCS8300_H
+
+#define QCS8300_MASTER_GPU_TCU 0
+#define QCS8300_MASTER_PCIE_TCU 1
+#define QCS8300_MASTER_SYS_TCU 2
+#define QCS8300_MASTER_APPSS_PROC 3
+#define QCS8300_MASTER_LLCC 4
+#define QCS8300_MASTER_CNOC_LPASS_AG_NOC 5
+#define QCS8300_MASTER_GIC_AHB 6
+#define QCS8300_MASTER_CDSP_NOC_CFG 7
+#define QCS8300_MASTER_QDSS_BAM 8
+#define QCS8300_MASTER_QUP_0 9
+#define QCS8300_MASTER_QUP_1 10
+#define QCS8300_MASTER_A1NOC_SNOC 11
+#define QCS8300_MASTER_A2NOC_SNOC 12
+#define QCS8300_MASTER_CAMNOC_HF 13
+#define QCS8300_MASTER_CAMNOC_ICP 14
+#define QCS8300_MASTER_CAMNOC_SF 15
+#define QCS8300_MASTER_COMPUTE_NOC 16
+#define QCS8300_MASTER_CNOC_A2NOC 17
+#define QCS8300_MASTER_CNOC_DC_NOC 18
+#define QCS8300_MASTER_GEM_NOC_CFG 19
+#define QCS8300_MASTER_GEM_NOC_CNOC 20
+#define QCS8300_MASTER_GEM_NOC_PCIE_SNOC 21
+#define QCS8300_MASTER_GPDSP_SAIL 22
+#define QCS8300_MASTER_GFX3D 23
+#define QCS8300_MASTER_LPASS_ANOC 24
+#define QCS8300_MASTER_MDP0 25
+#define QCS8300_MASTER_MDP1 26
+#define QCS8300_MASTER_MNOC_HF_MEM_NOC 27
+#define QCS8300_MASTER_CNOC_MNOC_HF_CFG 28
+#define QCS8300_MASTER_MNOC_SF_MEM_NOC 29
+#define QCS8300_MASTER_CNOC_MNOC_SF_CFG 30
+#define QCS8300_MASTER_ANOC_PCIE_GEM_NOC 31
+#define QCS8300_MASTER_SAILSS_MD0 32
+#define QCS8300_MASTER_SNOC_CFG 33
+#define QCS8300_MASTER_SNOC_GC_MEM_NOC 34
+#define QCS8300_MASTER_SNOC_SF_MEM_NOC 35
+#define QCS8300_MASTER_VIDEO_P0 36
+#define QCS8300_MASTER_VIDEO_PROC 37
+#define QCS8300_MASTER_VIDEO_V_PROC 38
+#define QCS8300_MASTER_QUP_CORE_0 39
+#define QCS8300_MASTER_QUP_CORE_1 40
+#define QCS8300_MASTER_QUP_CORE_3 41
+#define QCS8300_MASTER_CRYPTO_CORE0 42
+#define QCS8300_MASTER_CRYPTO_CORE1 43
+#define QCS8300_MASTER_DSP0 44
+#define QCS8300_MASTER_IPA 45
+#define QCS8300_MASTER_LPASS_PROC 46
+#define QCS8300_MASTER_CDSP_PROC 47
+#define QCS8300_MASTER_PIMEM 48
+#define QCS8300_MASTER_QUP_3 49
+#define QCS8300_MASTER_EMAC 50
+#define QCS8300_MASTER_GIC 51
+#define QCS8300_MASTER_PCIE_0 52
+#define QCS8300_MASTER_PCIE_1 53
+#define QCS8300_MASTER_QDSS_ETR_0 54
+#define QCS8300_MASTER_QDSS_ETR_1 55
+#define QCS8300_MASTER_SDC 56
+#define QCS8300_MASTER_UFS_MEM 57
+#define QCS8300_MASTER_USB2 58
+#define QCS8300_MASTER_USB3_0 59
+#define QCS8300_SLAVE_EBI1 60
+#define QCS8300_SLAVE_AHB2PHY_2 61
+#define QCS8300_SLAVE_AHB2PHY_3 62
+#define QCS8300_SLAVE_ANOC_THROTTLE_CFG 63
+#define QCS8300_SLAVE_AOSS 64
+#define QCS8300_SLAVE_APPSS 65
+#define QCS8300_SLAVE_BOOT_ROM 66
+#define QCS8300_SLAVE_CAMERA_CFG 67
+#define QCS8300_SLAVE_CAMERA_NRT_THROTTLE_CFG 68
+#define QCS8300_SLAVE_CAMERA_RT_THROTTLE_CFG 69
+#define QCS8300_SLAVE_CLK_CTL 70
+#define QCS8300_SLAVE_CDSP_CFG 71
+#define QCS8300_SLAVE_RBCPR_CX_CFG 72
+#define QCS8300_SLAVE_RBCPR_MMCX_CFG 73
+#define QCS8300_SLAVE_RBCPR_MX_CFG 74
+#define QCS8300_SLAVE_CPR_NSPCX 75
+#define QCS8300_SLAVE_CPR_NSPHMX 76
+#define QCS8300_SLAVE_CRYPTO_0_CFG 77
+#define QCS8300_SLAVE_CX_RDPM 78
+#define QCS8300_SLAVE_DISPLAY_CFG 79
+#define QCS8300_SLAVE_DISPLAY_RT_THROTTLE_CFG 80
+#define QCS8300_SLAVE_EMAC_CFG 81
+#define QCS8300_SLAVE_GP_DSP0_CFG 82
+#define QCS8300_SLAVE_GPDSP0_THROTTLE_CFG 83
+#define QCS8300_SLAVE_GPU_TCU_THROTTLE_CFG 84
+#define QCS8300_SLAVE_GFX3D_CFG 85
+#define QCS8300_SLAVE_HWKM 86
+#define QCS8300_SLAVE_IMEM_CFG 87
+#define QCS8300_SLAVE_IPA_CFG 88
+#define QCS8300_SLAVE_IPC_ROUTER_CFG 89
+#define QCS8300_SLAVE_LLCC_CFG 90
+#define QCS8300_SLAVE_LPASS 91
+#define QCS8300_SLAVE_LPASS_CORE_CFG 92
+#define QCS8300_SLAVE_LPASS_LPI_CFG 93
+#define QCS8300_SLAVE_LPASS_MPU_CFG 94
+#define QCS8300_SLAVE_LPASS_THROTTLE_CFG 95
+#define QCS8300_SLAVE_LPASS_TOP_CFG 96
+#define QCS8300_SLAVE_MX_RDPM 97
+#define QCS8300_SLAVE_MXC_RDPM 98
+#define QCS8300_SLAVE_PCIE_0_CFG 99
+#define QCS8300_SLAVE_PCIE_1_CFG 100
+#define QCS8300_SLAVE_PCIE_TCU_THROTTLE_CFG 101
+#define QCS8300_SLAVE_PCIE_THROTTLE_CFG 102
+#define QCS8300_SLAVE_PDM 103
+#define QCS8300_SLAVE_PIMEM_CFG 104
+#define QCS8300_SLAVE_PKA_WRAPPER_CFG 105
+#define QCS8300_SLAVE_QDSS_CFG 106
+#define QCS8300_SLAVE_QM_CFG 107
+#define QCS8300_SLAVE_QM_MPU_CFG 108
+#define QCS8300_SLAVE_QUP_0 109
+#define QCS8300_SLAVE_QUP_1 110
+#define QCS8300_SLAVE_QUP_3 111
+#define QCS8300_SLAVE_SAIL_THROTTLE_CFG 112
+#define QCS8300_SLAVE_SDC1 113
+#define QCS8300_SLAVE_SECURITY 114
+#define QCS8300_SLAVE_SNOC_THROTTLE_CFG 115
+#define QCS8300_SLAVE_TCSR 116
+#define QCS8300_SLAVE_TLMM 117
+#define QCS8300_SLAVE_TSC_CFG 118
+#define QCS8300_SLAVE_UFS_MEM_CFG 119
+#define QCS8300_SLAVE_USB2 120
+#define QCS8300_SLAVE_USB3_0 121
+#define QCS8300_SLAVE_VENUS_CFG 122
+#define QCS8300_SLAVE_VENUS_CVP_THROTTLE_CFG 123
+#define QCS8300_SLAVE_VENUS_V_CPU_THROTTLE_CFG 124
+#define QCS8300_SLAVE_VENUS_VCODEC_THROTTLE_CFG 125
+#define QCS8300_SLAVE_A1NOC_SNOC 126
+#define QCS8300_SLAVE_A2NOC_SNOC 127
+#define QCS8300_SLAVE_DDRSS_CFG 128
+#define QCS8300_SLAVE_GEM_NOC_CNOC 129
+#define QCS8300_SLAVE_GEM_NOC_CFG 130
+#define QCS8300_SLAVE_SNOC_GEM_NOC_GC 131
+#define QCS8300_SLAVE_SNOC_GEM_NOC_SF 132
+#define QCS8300_SLAVE_GP_DSP_SAIL_NOC 133
+#define QCS8300_SLAVE_GPDSP_NOC_CFG 134
+#define QCS8300_SLAVE_HCP_A 135
+#define QCS8300_SLAVE_LLCC 136
+#define QCS8300_SLAVE_MNOC_HF_MEM_NOC 137
+#define QCS8300_SLAVE_MNOC_SF_MEM_NOC 138
+#define QCS8300_SLAVE_CNOC_MNOC_HF_CFG 139
+#define QCS8300_SLAVE_CNOC_MNOC_SF_CFG 140
+#define QCS8300_SLAVE_CDSP_MEM_NOC 141
+#define QCS8300_SLAVE_GEM_NOC_PCIE_CNOC 142
+#define QCS8300_SLAVE_PCIE_ANOC_CFG 143
+#define QCS8300_SLAVE_ANOC_PCIE_GEM_NOC 144
+#define QCS8300_SLAVE_SNOC_CFG 145
+#define QCS8300_SLAVE_LPASS_SNOC 146
+#define QCS8300_SLAVE_QUP_CORE_0 147
+#define QCS8300_SLAVE_QUP_CORE_1 148
+#define QCS8300_SLAVE_QUP_CORE_3 149
+#define QCS8300_SLAVE_BOOT_IMEM 150
+#define QCS8300_SLAVE_IMEM 151
+#define QCS8300_SLAVE_PIMEM 152
+#define QCS8300_SLAVE_SERVICE_NSP_NOC 153
+#define QCS8300_SLAVE_SERVICE_GEM_NOC_1 154
+#define QCS8300_SLAVE_SERVICE_MNOC_HF 155
+#define QCS8300_SLAVE_SERVICE_MNOC_SF 156
+#define QCS8300_SLAVE_SERVICES_LPASS_AML_NOC 157
+#define QCS8300_SLAVE_SERVICE_LPASS_AG_NOC 158
+#define QCS8300_SLAVE_SERVICE_GEM_NOC_2 159
+#define QCS8300_SLAVE_SERVICE_SNOC 160
+#define QCS8300_SLAVE_SERVICE_GEM_NOC 161
+#define QCS8300_SLAVE_SERVICE_GEM_NOC2 162
+#define QCS8300_SLAVE_PCIE_0 163
+#define QCS8300_SLAVE_PCIE_1 164
+#define QCS8300_SLAVE_QDSS_STM 165
+#define QCS8300_SLAVE_TCU 166
+
+#endif
diff --git a/drivers/interconnect/qcom/qdu1000.c b/drivers/interconnect/qcom/qdu1000.c
index 9cb477d2bdfe..a7392eb73d4a 100644
--- a/drivers/interconnect/qcom/qdu1000.c
+++ b/drivers/interconnect/qcom/qdu1000.c
@@ -1046,7 +1046,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qnoc_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-qdu1000",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sa8775p.c b/drivers/interconnect/qcom/sa8775p.c
index a729775c2aa4..e2826af3ea2e 100644
--- a/drivers/interconnect/qcom/sa8775p.c
+++ b/drivers/interconnect/qcom/sa8775p.c
@@ -2519,7 +2519,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sa8775p",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sar2130p.c b/drivers/interconnect/qcom/sar2130p.c
new file mode 100644
index 000000000000..9eac0ac76812
--- /dev/null
+++ b/drivers/interconnect/qcom/sar2130p.c
@@ -0,0 +1,1930 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2024, Linaro Ltd.
+ */
+
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/sort.h>
+#include <dt-bindings/interconnect/qcom,sar2130p-rpmh.h>
+
+#include "bcm-voter.h"
+#include "icc-common.h"
+#include "icc-rpmh.h"
+
+enum {
+ SAR2130P_MASTER_QUP_CORE_0,
+ SAR2130P_MASTER_QUP_CORE_1,
+ SAR2130P_MASTER_GEM_NOC_CNOC,
+ SAR2130P_MASTER_GEM_NOC_PCIE_SNOC,
+ SAR2130P_MASTER_QDSS_DAP,
+ SAR2130P_MASTER_GPU_TCU,
+ SAR2130P_MASTER_SYS_TCU,
+ SAR2130P_MASTER_APPSS_PROC,
+ SAR2130P_MASTER_GFX3D,
+ SAR2130P_MASTER_MNOC_HF_MEM_NOC,
+ SAR2130P_MASTER_MNOC_SF_MEM_NOC,
+ SAR2130P_MASTER_COMPUTE_NOC,
+ SAR2130P_MASTER_ANOC_PCIE_GEM_NOC,
+ SAR2130P_MASTER_SNOC_GC_MEM_NOC,
+ SAR2130P_MASTER_SNOC_SF_MEM_NOC,
+ SAR2130P_MASTER_WLAN_Q6,
+ SAR2130P_MASTER_CNOC_LPASS_AG_NOC,
+ SAR2130P_MASTER_LPASS_PROC,
+ SAR2130P_MASTER_LLCC,
+ SAR2130P_MASTER_CAMNOC_HF,
+ SAR2130P_MASTER_CAMNOC_ICP,
+ SAR2130P_MASTER_CAMNOC_SF,
+ SAR2130P_MASTER_LSR,
+ SAR2130P_MASTER_MDP,
+ SAR2130P_MASTER_CNOC_MNOC_CFG,
+ SAR2130P_MASTER_VIDEO,
+ SAR2130P_MASTER_VIDEO_CV_PROC,
+ SAR2130P_MASTER_VIDEO_PROC,
+ SAR2130P_MASTER_VIDEO_V_PROC,
+ SAR2130P_MASTER_CDSP_NOC_CFG,
+ SAR2130P_MASTER_CDSP_PROC,
+ SAR2130P_MASTER_PCIE_0,
+ SAR2130P_MASTER_PCIE_1,
+ SAR2130P_MASTER_GIC_AHB,
+ SAR2130P_MASTER_QDSS_BAM,
+ SAR2130P_MASTER_QSPI_0,
+ SAR2130P_MASTER_QUP_0,
+ SAR2130P_MASTER_QUP_1,
+ SAR2130P_MASTER_A2NOC_SNOC,
+ SAR2130P_MASTER_CNOC_DATAPATH,
+ SAR2130P_MASTER_LPASS_ANOC,
+ SAR2130P_MASTER_SNOC_CFG,
+ SAR2130P_MASTER_CRYPTO,
+ SAR2130P_MASTER_PIMEM,
+ SAR2130P_MASTER_GIC,
+ SAR2130P_MASTER_QDSS_ETR,
+ SAR2130P_MASTER_QDSS_ETR_1,
+ SAR2130P_MASTER_SDCC_1,
+ SAR2130P_MASTER_USB3_0,
+ SAR2130P_SLAVE_QUP_CORE_0,
+ SAR2130P_SLAVE_QUP_CORE_1,
+ SAR2130P_SLAVE_AHB2PHY_SOUTH,
+ SAR2130P_SLAVE_AOSS,
+ SAR2130P_SLAVE_CAMERA_CFG,
+ SAR2130P_SLAVE_CLK_CTL,
+ SAR2130P_SLAVE_CDSP_CFG,
+ SAR2130P_SLAVE_RBCPR_CX_CFG,
+ SAR2130P_SLAVE_RBCPR_MMCX_CFG,
+ SAR2130P_SLAVE_RBCPR_MXA_CFG,
+ SAR2130P_SLAVE_RBCPR_MXC_CFG,
+ SAR2130P_SLAVE_CPR_NSPCX,
+ SAR2130P_SLAVE_CRYPTO_0_CFG,
+ SAR2130P_SLAVE_CX_RDPM,
+ SAR2130P_SLAVE_DISPLAY_CFG,
+ SAR2130P_SLAVE_GFX3D_CFG,
+ SAR2130P_SLAVE_IMEM_CFG,
+ SAR2130P_SLAVE_IPC_ROUTER_CFG,
+ SAR2130P_SLAVE_LPASS,
+ SAR2130P_SLAVE_MX_RDPM,
+ SAR2130P_SLAVE_PCIE_0_CFG,
+ SAR2130P_SLAVE_PCIE_1_CFG,
+ SAR2130P_SLAVE_PDM,
+ SAR2130P_SLAVE_PIMEM_CFG,
+ SAR2130P_SLAVE_PRNG,
+ SAR2130P_SLAVE_QDSS_CFG,
+ SAR2130P_SLAVE_QSPI_0,
+ SAR2130P_SLAVE_QUP_0,
+ SAR2130P_SLAVE_QUP_1,
+ SAR2130P_SLAVE_SDCC_1,
+ SAR2130P_SLAVE_TCSR,
+ SAR2130P_SLAVE_TLMM,
+ SAR2130P_SLAVE_TME_CFG,
+ SAR2130P_SLAVE_USB3_0,
+ SAR2130P_SLAVE_VENUS_CFG,
+ SAR2130P_SLAVE_VSENSE_CTRL_CFG,
+ SAR2130P_SLAVE_WLAN_Q6_CFG,
+ SAR2130P_SLAVE_DDRSS_CFG,
+ SAR2130P_SLAVE_CNOC_MNOC_CFG,
+ SAR2130P_SLAVE_SNOC_CFG,
+ SAR2130P_SLAVE_IMEM,
+ SAR2130P_SLAVE_PIMEM,
+ SAR2130P_SLAVE_SERVICE_CNOC,
+ SAR2130P_SLAVE_PCIE_0,
+ SAR2130P_SLAVE_PCIE_1,
+ SAR2130P_SLAVE_QDSS_STM,
+ SAR2130P_SLAVE_TCU,
+ SAR2130P_SLAVE_GEM_NOC_CNOC,
+ SAR2130P_SLAVE_LLCC,
+ SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC,
+ SAR2130P_SLAVE_LPASS_CORE_CFG,
+ SAR2130P_SLAVE_LPASS_LPI_CFG,
+ SAR2130P_SLAVE_LPASS_MPU_CFG,
+ SAR2130P_SLAVE_LPASS_TOP_CFG,
+ SAR2130P_SLAVE_LPASS_SNOC,
+ SAR2130P_SLAVE_SERVICES_LPASS_AML_NOC,
+ SAR2130P_SLAVE_SERVICE_LPASS_AG_NOC,
+ SAR2130P_SLAVE_EBI1,
+ SAR2130P_SLAVE_MNOC_HF_MEM_NOC,
+ SAR2130P_SLAVE_MNOC_SF_MEM_NOC,
+ SAR2130P_SLAVE_SERVICE_MNOC,
+ SAR2130P_SLAVE_CDSP_MEM_NOC,
+ SAR2130P_SLAVE_SERVICE_NSP_NOC,
+ SAR2130P_SLAVE_ANOC_PCIE_GEM_NOC,
+ SAR2130P_SLAVE_A2NOC_SNOC,
+ SAR2130P_SLAVE_SNOC_GEM_NOC_GC,
+ SAR2130P_SLAVE_SNOC_GEM_NOC_SF,
+ SAR2130P_SLAVE_SERVICE_SNOC,
+};
+
+static const struct regmap_config icc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .fast_io = true,
+};
+
+static struct qcom_icc_node qup0_core_master = {
+ .name = "qup0_core_master",
+ .id = SAR2130P_MASTER_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_QUP_CORE_0 },
+};
+
+static struct qcom_icc_node qup1_core_master = {
+ .name = "qup1_core_master",
+ .id = SAR2130P_MASTER_QUP_CORE_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_QUP_CORE_1 },
+};
+
+static struct qcom_icc_node qnm_gemnoc_cnoc = {
+ .name = "qnm_gemnoc_cnoc",
+ .id = SAR2130P_MASTER_GEM_NOC_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 43,
+ .links = { SAR2130P_SLAVE_AHB2PHY_SOUTH, SAR2130P_SLAVE_AOSS,
+ SAR2130P_SLAVE_CAMERA_CFG, SAR2130P_SLAVE_CLK_CTL,
+ SAR2130P_SLAVE_CDSP_CFG, SAR2130P_SLAVE_RBCPR_CX_CFG,
+ SAR2130P_SLAVE_RBCPR_MMCX_CFG, SAR2130P_SLAVE_RBCPR_MXA_CFG,
+ SAR2130P_SLAVE_RBCPR_MXC_CFG, SAR2130P_SLAVE_CPR_NSPCX,
+ SAR2130P_SLAVE_CRYPTO_0_CFG, SAR2130P_SLAVE_CX_RDPM,
+ SAR2130P_SLAVE_DISPLAY_CFG, SAR2130P_SLAVE_GFX3D_CFG,
+ SAR2130P_SLAVE_IMEM_CFG, SAR2130P_SLAVE_IPC_ROUTER_CFG,
+ SAR2130P_SLAVE_LPASS, SAR2130P_SLAVE_MX_RDPM,
+ SAR2130P_SLAVE_PCIE_0_CFG, SAR2130P_SLAVE_PCIE_1_CFG,
+ SAR2130P_SLAVE_PDM, SAR2130P_SLAVE_PIMEM_CFG,
+ SAR2130P_SLAVE_PRNG, SAR2130P_SLAVE_QDSS_CFG,
+ SAR2130P_SLAVE_QSPI_0, SAR2130P_SLAVE_QUP_0,
+ SAR2130P_SLAVE_QUP_1, SAR2130P_SLAVE_SDCC_1,
+ SAR2130P_SLAVE_TCSR, SAR2130P_SLAVE_TLMM,
+ SAR2130P_SLAVE_TME_CFG, SAR2130P_SLAVE_USB3_0,
+ SAR2130P_SLAVE_VENUS_CFG, SAR2130P_SLAVE_VSENSE_CTRL_CFG,
+ SAR2130P_SLAVE_WLAN_Q6_CFG, SAR2130P_SLAVE_DDRSS_CFG,
+ SAR2130P_SLAVE_CNOC_MNOC_CFG, SAR2130P_SLAVE_SNOC_CFG,
+ SAR2130P_SLAVE_IMEM, SAR2130P_SLAVE_PIMEM,
+ SAR2130P_SLAVE_SERVICE_CNOC, SAR2130P_SLAVE_QDSS_STM,
+ SAR2130P_SLAVE_TCU },
+};
+
+static struct qcom_icc_node qnm_gemnoc_pcie = {
+ .name = "qnm_gemnoc_pcie",
+ .id = SAR2130P_MASTER_GEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_PCIE_0, SAR2130P_SLAVE_PCIE_1 },
+};
+
+static struct qcom_icc_node xm_qdss_dap = {
+ .name = "xm_qdss_dap",
+ .id = SAR2130P_MASTER_QDSS_DAP,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 43,
+ .links = { SAR2130P_SLAVE_AHB2PHY_SOUTH, SAR2130P_SLAVE_AOSS,
+ SAR2130P_SLAVE_CAMERA_CFG, SAR2130P_SLAVE_CLK_CTL,
+ SAR2130P_SLAVE_CDSP_CFG, SAR2130P_SLAVE_RBCPR_CX_CFG,
+ SAR2130P_SLAVE_RBCPR_MMCX_CFG, SAR2130P_SLAVE_RBCPR_MXA_CFG,
+ SAR2130P_SLAVE_RBCPR_MXC_CFG, SAR2130P_SLAVE_CPR_NSPCX,
+ SAR2130P_SLAVE_CRYPTO_0_CFG, SAR2130P_SLAVE_CX_RDPM,
+ SAR2130P_SLAVE_DISPLAY_CFG, SAR2130P_SLAVE_GFX3D_CFG,
+ SAR2130P_SLAVE_IMEM_CFG, SAR2130P_SLAVE_IPC_ROUTER_CFG,
+ SAR2130P_SLAVE_LPASS, SAR2130P_SLAVE_MX_RDPM,
+ SAR2130P_SLAVE_PCIE_0_CFG, SAR2130P_SLAVE_PCIE_1_CFG,
+ SAR2130P_SLAVE_PDM, SAR2130P_SLAVE_PIMEM_CFG,
+ SAR2130P_SLAVE_PRNG, SAR2130P_SLAVE_QDSS_CFG,
+ SAR2130P_SLAVE_QSPI_0, SAR2130P_SLAVE_QUP_0,
+ SAR2130P_SLAVE_QUP_1, SAR2130P_SLAVE_SDCC_1,
+ SAR2130P_SLAVE_TCSR, SAR2130P_SLAVE_TLMM,
+ SAR2130P_SLAVE_TME_CFG, SAR2130P_SLAVE_USB3_0,
+ SAR2130P_SLAVE_VENUS_CFG, SAR2130P_SLAVE_VSENSE_CTRL_CFG,
+ SAR2130P_SLAVE_WLAN_Q6_CFG, SAR2130P_SLAVE_DDRSS_CFG,
+ SAR2130P_SLAVE_CNOC_MNOC_CFG, SAR2130P_SLAVE_SNOC_CFG,
+ SAR2130P_SLAVE_IMEM, SAR2130P_SLAVE_PIMEM,
+ SAR2130P_SLAVE_SERVICE_CNOC, SAR2130P_SLAVE_QDSS_STM,
+ SAR2130P_SLAVE_TCU },
+};
+
+static const struct qcom_icc_qosbox alm_gpu_tcu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x9e000 },
+ .prio = 1,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node alm_gpu_tcu = {
+ .name = "alm_gpu_tcu",
+ .id = SAR2130P_MASTER_GPU_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &alm_gpu_tcu_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox alm_sys_tcu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x9f000 },
+ .prio = 6,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node alm_sys_tcu = {
+ .name = "alm_sys_tcu",
+ .id = SAR2130P_MASTER_SYS_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &alm_sys_tcu_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node chm_apps = {
+ .name = "chm_apps",
+ .id = SAR2130P_MASTER_APPSS_PROC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 3,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC,
+ SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC },
+};
+
+static const struct qcom_icc_qosbox qnm_gpu_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0xe000, 0x4e000 },
+ .prio = 0,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_gpu = {
+ .name = "qnm_gpu",
+ .id = SAR2130P_MASTER_GFX3D,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_gpu_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_mnoc_hf_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0xf000, 0x4f000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_mnoc_hf = {
+ .name = "qnm_mnoc_hf",
+ .id = SAR2130P_MASTER_MNOC_HF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_mnoc_hf_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_mnoc_sf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x9d000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_mnoc_sf = {
+ .name = "qnm_mnoc_sf",
+ .id = SAR2130P_MASTER_MNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &qnm_mnoc_sf_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_nsp_gemnoc_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x10000, 0x50000 },
+ .prio = 0,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_nsp_gemnoc = {
+ .name = "qnm_nsp_gemnoc",
+ .id = SAR2130P_MASTER_COMPUTE_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_nsp_gemnoc_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_pcie_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0xa2000 },
+ .prio = 2,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_pcie = {
+ .name = "qnm_pcie",
+ .id = SAR2130P_MASTER_ANOC_PCIE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &qnm_pcie_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_snoc_gc_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0xa0000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_snoc_gc = {
+ .name = "qnm_snoc_gc",
+ .id = SAR2130P_MASTER_SNOC_GC_MEM_NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_snoc_gc_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_snoc_sf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0xa1000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_snoc_sf = {
+ .name = "qnm_snoc_sf",
+ .id = SAR2130P_MASTER_SNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &qnm_snoc_sf_qos,
+ .num_links = 3,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC,
+ SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node qxm_wlan_q6 = {
+ .name = "qxm_wlan_q6",
+ .id = SAR2130P_MASTER_WLAN_Q6,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 3,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC,
+ SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node qhm_config_noc = {
+ .name = "qhm_config_noc",
+ .id = SAR2130P_MASTER_CNOC_LPASS_AG_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 6,
+ .links = { SAR2130P_SLAVE_LPASS_CORE_CFG, SAR2130P_SLAVE_LPASS_LPI_CFG,
+ SAR2130P_SLAVE_LPASS_MPU_CFG, SAR2130P_SLAVE_LPASS_TOP_CFG,
+ SAR2130P_SLAVE_SERVICES_LPASS_AML_NOC, SAR2130P_SLAVE_SERVICE_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node qxm_lpass_dsp = {
+ .name = "qxm_lpass_dsp",
+ .id = SAR2130P_MASTER_LPASS_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 4,
+ .links = { SAR2130P_SLAVE_LPASS_TOP_CFG, SAR2130P_SLAVE_LPASS_SNOC,
+ SAR2130P_SLAVE_SERVICES_LPASS_AML_NOC, SAR2130P_SLAVE_SERVICE_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node llcc_mc = {
+ .name = "llcc_mc",
+ .id = SAR2130P_MASTER_LLCC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_EBI1 },
+};
+
+static const struct qcom_icc_qosbox qnm_camnoc_hf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1c000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_camnoc_hf = {
+ .name = "qnm_camnoc_hf",
+ .id = SAR2130P_MASTER_CAMNOC_HF,
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &qnm_camnoc_hf_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_camnoc_icp_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1c080 },
+ .prio = 4,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_camnoc_icp = {
+ .name = "qnm_camnoc_icp",
+ .id = SAR2130P_MASTER_CAMNOC_ICP,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_camnoc_icp_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_camnoc_sf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1c100 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_camnoc_sf = {
+ .name = "qnm_camnoc_sf",
+ .id = SAR2130P_MASTER_CAMNOC_SF,
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &qnm_camnoc_sf_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_lsr_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x1f000, 0x1f080 },
+ .prio = 3,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_lsr = {
+ .name = "qnm_lsr",
+ .id = SAR2130P_MASTER_LSR,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_lsr_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_mdp_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x1d000, 0x1d080 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_mdp = {
+ .name = "qnm_mdp",
+ .id = SAR2130P_MASTER_MDP,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_mdp_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_mnoc_cfg = {
+ .name = "qnm_mnoc_cfg",
+ .id = SAR2130P_MASTER_CNOC_MNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SERVICE_MNOC },
+};
+
+static const struct qcom_icc_qosbox qnm_video_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x1e000, 0x1e080 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_video = {
+ .name = "qnm_video",
+ .id = SAR2130P_MASTER_VIDEO,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_video_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_video_cv_cpu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1e100 },
+ .prio = 4,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_video_cv_cpu = {
+ .name = "qnm_video_cv_cpu",
+ .id = SAR2130P_MASTER_VIDEO_CV_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_video_cv_cpu_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_video_cvp_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1e180 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_video_cvp = {
+ .name = "qnm_video_cvp",
+ .id = SAR2130P_MASTER_VIDEO_PROC,
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &qnm_video_cvp_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_video_v_cpu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1e200 },
+ .prio = 4,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_video_v_cpu = {
+ .name = "qnm_video_v_cpu",
+ .id = SAR2130P_MASTER_VIDEO_V_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_video_v_cpu_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qhm_nsp_noc_config = {
+ .name = "qhm_nsp_noc_config",
+ .id = SAR2130P_MASTER_CDSP_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SERVICE_NSP_NOC },
+};
+
+static struct qcom_icc_node qxm_nsp = {
+ .name = "qxm_nsp",
+ .id = SAR2130P_MASTER_CDSP_PROC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_CDSP_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox xm_pcie3_0_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x9000 },
+ .prio = 3,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_pcie3_0 = {
+ .name = "xm_pcie3_0",
+ .id = SAR2130P_MASTER_PCIE_0,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_pcie3_0_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_ANOC_PCIE_GEM_NOC },
+};
+
+static const struct qcom_icc_qosbox xm_pcie3_1_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0xa000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_pcie3_1 = {
+ .name = "xm_pcie3_1",
+ .id = SAR2130P_MASTER_PCIE_1,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_pcie3_1_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_ANOC_PCIE_GEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qhm_gic_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1d000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_gic = {
+ .name = "qhm_gic",
+ .id = SAR2130P_MASTER_GIC_AHB,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_gic_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static const struct qcom_icc_qosbox qhm_qdss_bam_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x22000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_qdss_bam = {
+ .name = "qhm_qdss_bam",
+ .id = SAR2130P_MASTER_QDSS_BAM,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_qdss_bam_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qhm_qspi_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x23000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_qspi = {
+ .name = "qhm_qspi",
+ .id = SAR2130P_MASTER_QSPI_0,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_qspi_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qhm_qup0_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x24000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_qup0 = {
+ .name = "qhm_qup0",
+ .id = SAR2130P_MASTER_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_qup0_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qhm_qup1_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x25000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_qup1 = {
+ .name = "qhm_qup1",
+ .id = SAR2130P_MASTER_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_qup1_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qnm_aggre2_noc = {
+ .name = "qnm_aggre2_noc",
+ .id = SAR2130P_MASTER_A2NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static const struct qcom_icc_qosbox qnm_cnoc_datapath_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x26000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_cnoc_datapath = {
+ .name = "qnm_cnoc_datapath",
+ .id = SAR2130P_MASTER_CNOC_DATAPATH,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_cnoc_datapath_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qnm_lpass_noc_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1e000 },
+ .prio = 0,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_lpass_noc = {
+ .name = "qnm_lpass_noc",
+ .id = SAR2130P_MASTER_LPASS_ANOC,
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &qnm_lpass_noc_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_snoc_cfg = {
+ .name = "qnm_snoc_cfg",
+ .id = SAR2130P_MASTER_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SERVICE_SNOC },
+};
+
+static const struct qcom_icc_qosbox qxm_crypto_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x27000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qxm_crypto = {
+ .name = "qxm_crypto",
+ .id = SAR2130P_MASTER_CRYPTO,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qxm_crypto_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qxm_pimem_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1f000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qxm_pimem = {
+ .name = "qxm_pimem",
+ .id = SAR2130P_MASTER_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qxm_pimem_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_GC },
+};
+
+static const struct qcom_icc_qosbox xm_gic_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x21000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_gic = {
+ .name = "xm_gic",
+ .id = SAR2130P_MASTER_GIC,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_gic_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_GC },
+};
+
+static const struct qcom_icc_qosbox xm_qdss_etr_0_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1b000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_qdss_etr_0 = {
+ .name = "xm_qdss_etr_0",
+ .id = SAR2130P_MASTER_QDSS_ETR,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_qdss_etr_0_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox xm_qdss_etr_1_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1c000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_qdss_etr_1 = {
+ .name = "xm_qdss_etr_1",
+ .id = SAR2130P_MASTER_QDSS_ETR_1,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_qdss_etr_1_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox xm_sdc1_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x29000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_sdc1 = {
+ .name = "xm_sdc1",
+ .id = SAR2130P_MASTER_SDCC_1,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_sdc1_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox xm_usb3_0_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x28000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_usb3_0 = {
+ .name = "xm_usb3_0",
+ .id = SAR2130P_MASTER_USB3_0,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_usb3_0_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qup0_core_slave = {
+ .name = "qup0_core_slave",
+ .id = SAR2130P_SLAVE_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qup1_core_slave = {
+ .name = "qup1_core_slave",
+ .id = SAR2130P_SLAVE_QUP_CORE_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ahb2phy0 = {
+ .name = "qhs_ahb2phy0",
+ .id = SAR2130P_SLAVE_AHB2PHY_SOUTH,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_aoss = {
+ .name = "qhs_aoss",
+ .id = SAR2130P_SLAVE_AOSS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_cfg = {
+ .name = "qhs_camera_cfg",
+ .id = SAR2130P_SLAVE_CAMERA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_clk_ctl = {
+ .name = "qhs_clk_ctl",
+ .id = SAR2130P_SLAVE_CLK_CTL,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_compute_cfg = {
+ .name = "qhs_compute_cfg",
+ .id = SAR2130P_SLAVE_CDSP_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_CDSP_NOC_CFG },
+};
+
+static struct qcom_icc_node qhs_cpr_cx = {
+ .name = "qhs_cpr_cx",
+ .id = SAR2130P_SLAVE_RBCPR_CX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mmcx = {
+ .name = "qhs_cpr_mmcx",
+ .id = SAR2130P_SLAVE_RBCPR_MMCX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mxa = {
+ .name = "qhs_cpr_mxa",
+ .id = SAR2130P_SLAVE_RBCPR_MXA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mxc = {
+ .name = "qhs_cpr_mxc",
+ .id = SAR2130P_SLAVE_RBCPR_MXC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_nspcx = {
+ .name = "qhs_cpr_nspcx",
+ .id = SAR2130P_SLAVE_CPR_NSPCX,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_crypto0_cfg = {
+ .name = "qhs_crypto0_cfg",
+ .id = SAR2130P_SLAVE_CRYPTO_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cx_rdpm = {
+ .name = "qhs_cx_rdpm",
+ .id = SAR2130P_SLAVE_CX_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_display_cfg = {
+ .name = "qhs_display_cfg",
+ .id = SAR2130P_SLAVE_DISPLAY_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpuss_cfg = {
+ .name = "qhs_gpuss_cfg",
+ .id = SAR2130P_SLAVE_GFX3D_CFG,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_imem_cfg = {
+ .name = "qhs_imem_cfg",
+ .id = SAR2130P_SLAVE_IMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ipc_router = {
+ .name = "qhs_ipc_router",
+ .id = SAR2130P_SLAVE_IPC_ROUTER_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_cfg = {
+ .name = "qhs_lpass_cfg",
+ .id = SAR2130P_SLAVE_LPASS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_CNOC_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node qhs_mx_rdpm = {
+ .name = "qhs_mx_rdpm",
+ .id = SAR2130P_SLAVE_MX_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie0_cfg = {
+ .name = "qhs_pcie0_cfg",
+ .id = SAR2130P_SLAVE_PCIE_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie1_cfg = {
+ .name = "qhs_pcie1_cfg",
+ .id = SAR2130P_SLAVE_PCIE_1_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pdm = {
+ .name = "qhs_pdm",
+ .id = SAR2130P_SLAVE_PDM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pimem_cfg = {
+ .name = "qhs_pimem_cfg",
+ .id = SAR2130P_SLAVE_PIMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_prng = {
+ .name = "qhs_prng",
+ .id = SAR2130P_SLAVE_PRNG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qdss_cfg = {
+ .name = "qhs_qdss_cfg",
+ .id = SAR2130P_SLAVE_QDSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qspi = {
+ .name = "qhs_qspi",
+ .id = SAR2130P_SLAVE_QSPI_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup0 = {
+ .name = "qhs_qup0",
+ .id = SAR2130P_SLAVE_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup1 = {
+ .name = "qhs_qup1",
+ .id = SAR2130P_SLAVE_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sdc1 = {
+ .name = "qhs_sdc1",
+ .id = SAR2130P_SLAVE_SDCC_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tcsr = {
+ .name = "qhs_tcsr",
+ .id = SAR2130P_SLAVE_TCSR,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm = {
+ .name = "qhs_tlmm",
+ .id = SAR2130P_SLAVE_TLMM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tme_cfg = {
+ .name = "qhs_tme_cfg",
+ .id = SAR2130P_SLAVE_TME_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb3_0 = {
+ .name = "qhs_usb3_0",
+ .id = SAR2130P_SLAVE_USB3_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_cfg = {
+ .name = "qhs_venus_cfg",
+ .id = SAR2130P_SLAVE_VENUS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_vsense_ctrl_cfg = {
+ .name = "qhs_vsense_ctrl_cfg",
+ .id = SAR2130P_SLAVE_VSENSE_CTRL_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_wlan_q6 = {
+ .name = "qhs_wlan_q6",
+ .id = SAR2130P_SLAVE_WLAN_Q6_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_ddrss_cfg = {
+ .name = "qns_ddrss_cfg",
+ .id = SAR2130P_SLAVE_DDRSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_mnoc_cfg = {
+ .name = "qns_mnoc_cfg",
+ .id = SAR2130P_SLAVE_CNOC_MNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_CNOC_MNOC_CFG },
+};
+
+static struct qcom_icc_node qns_snoc_cfg = {
+ .name = "qns_snoc_cfg",
+ .id = SAR2130P_SLAVE_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_SNOC_CFG },
+};
+
+static struct qcom_icc_node qxs_imem = {
+ .name = "qxs_imem",
+ .id = SAR2130P_SLAVE_IMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qxs_pimem = {
+ .name = "qxs_pimem",
+ .id = SAR2130P_SLAVE_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_cnoc = {
+ .name = "srvc_cnoc",
+ .id = SAR2130P_SLAVE_SERVICE_CNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie_0 = {
+ .name = "xs_pcie_0",
+ .id = SAR2130P_SLAVE_PCIE_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie_1 = {
+ .name = "xs_pcie_1",
+ .id = SAR2130P_SLAVE_PCIE_1,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_qdss_stm = {
+ .name = "xs_qdss_stm",
+ .id = SAR2130P_SLAVE_QDSS_STM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_sys_tcu_cfg = {
+ .name = "xs_sys_tcu_cfg",
+ .id = SAR2130P_SLAVE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_gem_noc_cnoc = {
+ .name = "qns_gem_noc_cnoc",
+ .id = SAR2130P_SLAVE_GEM_NOC_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_GEM_NOC_CNOC },
+};
+
+static struct qcom_icc_node qns_llcc = {
+ .name = "qns_llcc",
+ .id = SAR2130P_SLAVE_LLCC,
+ .channels = 2,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_LLCC },
+};
+
+static struct qcom_icc_node qns_pcie = {
+ .name = "qns_pcie",
+ .id = SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_GEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node qhs_lpass_core = {
+ .name = "qhs_lpass_core",
+ .id = SAR2130P_SLAVE_LPASS_CORE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_lpi = {
+ .name = "qhs_lpass_lpi",
+ .id = SAR2130P_SLAVE_LPASS_LPI_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_mpu = {
+ .name = "qhs_lpass_mpu",
+ .id = SAR2130P_SLAVE_LPASS_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_top = {
+ .name = "qhs_lpass_top",
+ .id = SAR2130P_SLAVE_LPASS_TOP_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_sysnoc = {
+ .name = "qns_sysnoc",
+ .id = SAR2130P_SLAVE_LPASS_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_LPASS_ANOC },
+};
+
+static struct qcom_icc_node srvc_niu_aml_noc = {
+ .name = "srvc_niu_aml_noc",
+ .id = SAR2130P_SLAVE_SERVICES_LPASS_AML_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_niu_lpass_agnoc = {
+ .name = "srvc_niu_lpass_agnoc",
+ .id = SAR2130P_SLAVE_SERVICE_LPASS_AG_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node ebi = {
+ .name = "ebi",
+ .id = SAR2130P_SLAVE_EBI1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_mem_noc_hf = {
+ .name = "qns_mem_noc_hf",
+ .id = SAR2130P_SLAVE_MNOC_HF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_mem_noc_sf = {
+ .name = "qns_mem_noc_sf",
+ .id = SAR2130P_SLAVE_MNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_mnoc = {
+ .name = "srvc_mnoc",
+ .id = SAR2130P_SLAVE_SERVICE_MNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_nsp_gemnoc = {
+ .name = "qns_nsp_gemnoc",
+ .id = SAR2130P_SLAVE_CDSP_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_COMPUTE_NOC },
+};
+
+static struct qcom_icc_node service_nsp_noc = {
+ .name = "service_nsp_noc",
+ .id = SAR2130P_SLAVE_SERVICE_NSP_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_pcie_mem_noc = {
+ .name = "qns_pcie_mem_noc",
+ .id = SAR2130P_SLAVE_ANOC_PCIE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_ANOC_PCIE_GEM_NOC },
+};
+
+static struct qcom_icc_node qns_a2noc_snoc = {
+ .name = "qns_a2noc_snoc",
+ .id = SAR2130P_SLAVE_A2NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_gc = {
+ .name = "qns_gemnoc_gc",
+ .id = SAR2130P_SLAVE_SNOC_GEM_NOC_GC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_SNOC_GC_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_sf = {
+ .name = "qns_gemnoc_sf",
+ .id = SAR2130P_SLAVE_SNOC_GEM_NOC_SF,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_SNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_snoc = {
+ .name = "srvc_snoc",
+ .id = SAR2130P_SLAVE_SERVICE_SNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_bcm bcm_acv = {
+ .name = "ACV",
+ .enable_mask = BIT(3),
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_ce0 = {
+ .name = "CE0",
+ .num_nodes = 1,
+ .nodes = { &qxm_crypto },
+};
+
+static struct qcom_icc_bcm bcm_cn0 = {
+ .name = "CN0",
+ .enable_mask = BIT(0),
+ .keepalive = true,
+ .num_nodes = 48,
+ .nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie,
+ &xm_qdss_dap, &qhs_ahb2phy0,
+ &qhs_aoss, &qhs_camera_cfg,
+ &qhs_clk_ctl, &qhs_compute_cfg,
+ &qhs_cpr_cx, &qhs_cpr_mmcx,
+ &qhs_cpr_mxa, &qhs_cpr_mxc,
+ &qhs_cpr_nspcx, &qhs_crypto0_cfg,
+ &qhs_cx_rdpm, &qhs_display_cfg,
+ &qhs_gpuss_cfg, &qhs_imem_cfg,
+ &qhs_ipc_router, &qhs_lpass_cfg,
+ &qhs_mx_rdpm, &qhs_pcie0_cfg,
+ &qhs_pcie1_cfg, &qhs_pdm,
+ &qhs_pimem_cfg, &qhs_prng,
+ &qhs_qdss_cfg, &qhs_qspi,
+ &qhs_qup0, &qhs_qup1,
+ &qhs_sdc1, &qhs_tcsr,
+ &qhs_tlmm, &qhs_tme_cfg,
+ &qhs_usb3_0, &qhs_venus_cfg,
+ &qhs_vsense_ctrl_cfg, &qhs_wlan_q6,
+ &qns_ddrss_cfg, &qns_mnoc_cfg,
+ &qns_snoc_cfg, &qxs_imem,
+ &qxs_pimem, &srvc_cnoc,
+ &xs_pcie_0, &xs_pcie_1,
+ &xs_qdss_stm, &xs_sys_tcu_cfg },
+};
+
+static struct qcom_icc_bcm bcm_co0 = {
+ .name = "CO0",
+ .enable_mask = BIT(0),
+ .num_nodes = 2,
+ .nodes = { &qxm_nsp, &qns_nsp_gemnoc },
+};
+
+static struct qcom_icc_bcm bcm_mc0 = {
+ .name = "MC0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_mm0 = {
+ .name = "MM0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_mem_noc_hf },
+};
+
+static struct qcom_icc_bcm bcm_mm1 = {
+ .name = "MM1",
+ .enable_mask = BIT(0),
+ .num_nodes = 11,
+ .nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp,
+ &qnm_camnoc_sf, &qnm_lsr,
+ &qnm_mdp, &qnm_mnoc_cfg,
+ &qnm_video, &qnm_video_cv_cpu,
+ &qnm_video_cvp, &qnm_video_v_cpu,
+ &qns_mem_noc_sf },
+};
+
+static struct qcom_icc_bcm bcm_qup0 = {
+ .name = "QUP0",
+ .keepalive = true,
+ .vote_scale = 1,
+ .num_nodes = 1,
+ .nodes = { &qup0_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_qup1 = {
+ .name = "QUP1",
+ .keepalive = true,
+ .vote_scale = 1,
+ .num_nodes = 1,
+ .nodes = { &qup1_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_sh0 = {
+ .name = "SH0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_llcc },
+};
+
+static struct qcom_icc_bcm bcm_sh1 = {
+ .name = "SH1",
+ .enable_mask = BIT(0),
+ .num_nodes = 13,
+ .nodes = { &alm_gpu_tcu, &alm_sys_tcu,
+ &chm_apps, &qnm_gpu,
+ &qnm_mnoc_hf, &qnm_mnoc_sf,
+ &qnm_nsp_gemnoc, &qnm_pcie,
+ &qnm_snoc_gc, &qnm_snoc_sf,
+ &qxm_wlan_q6, &qns_gem_noc_cnoc,
+ &qns_pcie },
+};
+
+static struct qcom_icc_bcm bcm_sn0 = {
+ .name = "SN0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_bcm bcm_sn1 = {
+ .name = "SN1",
+ .enable_mask = BIT(0),
+ .num_nodes = 4,
+ .nodes = { &qhm_gic, &qxm_pimem,
+ &xm_gic, &qns_gemnoc_gc },
+};
+
+static struct qcom_icc_bcm bcm_sn3 = {
+ .name = "SN3",
+ .num_nodes = 1,
+ .nodes = { &qnm_aggre2_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn4 = {
+ .name = "SN4",
+ .num_nodes = 1,
+ .nodes = { &qnm_lpass_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn7 = {
+ .name = "SN7",
+ .num_nodes = 1,
+ .nodes = { &qns_pcie_mem_noc },
+};
+
+static struct qcom_icc_bcm * const clk_virt_bcms[] = {
+ &bcm_qup0,
+ &bcm_qup1,
+};
+
+static struct qcom_icc_node * const clk_virt_nodes[] = {
+ [MASTER_QUP_CORE_0] = &qup0_core_master,
+ [MASTER_QUP_CORE_1] = &qup1_core_master,
+ [SLAVE_QUP_CORE_0] = &qup0_core_slave,
+ [SLAVE_QUP_CORE_1] = &qup1_core_slave,
+};
+
+static const struct qcom_icc_desc sar2130p_clk_virt = {
+ .nodes = clk_virt_nodes,
+ .num_nodes = ARRAY_SIZE(clk_virt_nodes),
+ .bcms = clk_virt_bcms,
+ .num_bcms = ARRAY_SIZE(clk_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const config_noc_bcms[] = {
+ &bcm_cn0,
+};
+
+static struct qcom_icc_node * const config_noc_nodes[] = {
+ [MASTER_GEM_NOC_CNOC] = &qnm_gemnoc_cnoc,
+ [MASTER_GEM_NOC_PCIE_SNOC] = &qnm_gemnoc_pcie,
+ [MASTER_QDSS_DAP] = &xm_qdss_dap,
+ [SLAVE_AHB2PHY_SOUTH] = &qhs_ahb2phy0,
+ [SLAVE_AOSS] = &qhs_aoss,
+ [SLAVE_CAMERA_CFG] = &qhs_camera_cfg,
+ [SLAVE_CLK_CTL] = &qhs_clk_ctl,
+ [SLAVE_CDSP_CFG] = &qhs_compute_cfg,
+ [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx,
+ [SLAVE_RBCPR_MMCX_CFG] = &qhs_cpr_mmcx,
+ [SLAVE_RBCPR_MXA_CFG] = &qhs_cpr_mxa,
+ [SLAVE_RBCPR_MXC_CFG] = &qhs_cpr_mxc,
+ [SLAVE_CPR_NSPCX] = &qhs_cpr_nspcx,
+ [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
+ [SLAVE_CX_RDPM] = &qhs_cx_rdpm,
+ [SLAVE_DISPLAY_CFG] = &qhs_display_cfg,
+ [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg,
+ [SLAVE_IMEM_CFG] = &qhs_imem_cfg,
+ [SLAVE_IPC_ROUTER_CFG] = &qhs_ipc_router,
+ [SLAVE_LPASS] = &qhs_lpass_cfg,
+ [SLAVE_MX_RDPM] = &qhs_mx_rdpm,
+ [SLAVE_PCIE_0_CFG] = &qhs_pcie0_cfg,
+ [SLAVE_PCIE_1_CFG] = &qhs_pcie1_cfg,
+ [SLAVE_PDM] = &qhs_pdm,
+ [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg,
+ [SLAVE_PRNG] = &qhs_prng,
+ [SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
+ [SLAVE_QSPI_0] = &qhs_qspi,
+ [SLAVE_QUP_0] = &qhs_qup0,
+ [SLAVE_QUP_1] = &qhs_qup1,
+ [SLAVE_SDCC_1] = &qhs_sdc1,
+ [SLAVE_TCSR] = &qhs_tcsr,
+ [SLAVE_TLMM] = &qhs_tlmm,
+ [SLAVE_TME_CFG] = &qhs_tme_cfg,
+ [SLAVE_USB3_0] = &qhs_usb3_0,
+ [SLAVE_VENUS_CFG] = &qhs_venus_cfg,
+ [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg,
+ [SLAVE_WLAN_Q6_CFG] = &qhs_wlan_q6,
+ [SLAVE_DDRSS_CFG] = &qns_ddrss_cfg,
+ [SLAVE_CNOC_MNOC_CFG] = &qns_mnoc_cfg,
+ [SLAVE_SNOC_CFG] = &qns_snoc_cfg,
+ [SLAVE_IMEM] = &qxs_imem,
+ [SLAVE_PIMEM] = &qxs_pimem,
+ [SLAVE_SERVICE_CNOC] = &srvc_cnoc,
+ [SLAVE_PCIE_0] = &xs_pcie_0,
+ [SLAVE_PCIE_1] = &xs_pcie_1,
+ [SLAVE_QDSS_STM] = &xs_qdss_stm,
+ [SLAVE_TCU] = &xs_sys_tcu_cfg,
+};
+
+static const struct qcom_icc_desc sar2130p_config_noc = {
+ .config = &icc_regmap_config,
+ .nodes = config_noc_nodes,
+ .num_nodes = ARRAY_SIZE(config_noc_nodes),
+ .bcms = config_noc_bcms,
+ .num_bcms = ARRAY_SIZE(config_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const gem_noc_bcms[] = {
+ &bcm_sh0,
+ &bcm_sh1,
+};
+
+static struct qcom_icc_node * const gem_noc_nodes[] = {
+ [MASTER_GPU_TCU] = &alm_gpu_tcu,
+ [MASTER_SYS_TCU] = &alm_sys_tcu,
+ [MASTER_APPSS_PROC] = &chm_apps,
+ [MASTER_GFX3D] = &qnm_gpu,
+ [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf,
+ [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf,
+ [MASTER_COMPUTE_NOC] = &qnm_nsp_gemnoc,
+ [MASTER_ANOC_PCIE_GEM_NOC] = &qnm_pcie,
+ [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc,
+ [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf,
+ [MASTER_WLAN_Q6] = &qxm_wlan_q6,
+ [SLAVE_GEM_NOC_CNOC] = &qns_gem_noc_cnoc,
+ [SLAVE_LLCC] = &qns_llcc,
+ [SLAVE_MEM_NOC_PCIE_SNOC] = &qns_pcie,
+};
+
+static const struct qcom_icc_desc sar2130p_gem_noc = {
+ .config = &icc_regmap_config,
+ .nodes = gem_noc_nodes,
+ .num_nodes = ARRAY_SIZE(gem_noc_nodes),
+ .bcms = gem_noc_bcms,
+ .num_bcms = ARRAY_SIZE(gem_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const lpass_ag_noc_bcms[] = {
+};
+
+static struct qcom_icc_node * const lpass_ag_noc_nodes[] = {
+ [MASTER_CNOC_LPASS_AG_NOC] = &qhm_config_noc,
+ [MASTER_LPASS_PROC] = &qxm_lpass_dsp,
+ [SLAVE_LPASS_CORE_CFG] = &qhs_lpass_core,
+ [SLAVE_LPASS_LPI_CFG] = &qhs_lpass_lpi,
+ [SLAVE_LPASS_MPU_CFG] = &qhs_lpass_mpu,
+ [SLAVE_LPASS_TOP_CFG] = &qhs_lpass_top,
+ [SLAVE_LPASS_SNOC] = &qns_sysnoc,
+ [SLAVE_SERVICES_LPASS_AML_NOC] = &srvc_niu_aml_noc,
+ [SLAVE_SERVICE_LPASS_AG_NOC] = &srvc_niu_lpass_agnoc,
+};
+
+static const struct qcom_icc_desc sar2130p_lpass_ag_noc = {
+ .config = &icc_regmap_config,
+ .nodes = lpass_ag_noc_nodes,
+ .num_nodes = ARRAY_SIZE(lpass_ag_noc_nodes),
+ .bcms = lpass_ag_noc_bcms,
+ .num_bcms = ARRAY_SIZE(lpass_ag_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const mc_virt_bcms[] = {
+ &bcm_acv,
+ &bcm_mc0,
+};
+
+static struct qcom_icc_node * const mc_virt_nodes[] = {
+ [MASTER_LLCC] = &llcc_mc,
+ [SLAVE_EBI1] = &ebi,
+};
+
+static const struct qcom_icc_desc sar2130p_mc_virt = {
+ .nodes = mc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mc_virt_nodes),
+ .bcms = mc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(mc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mmss_noc_bcms[] = {
+ &bcm_mm0,
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const mmss_noc_nodes[] = {
+ [MASTER_CAMNOC_HF] = &qnm_camnoc_hf,
+ [MASTER_CAMNOC_ICP] = &qnm_camnoc_icp,
+ [MASTER_CAMNOC_SF] = &qnm_camnoc_sf,
+ [MASTER_LSR] = &qnm_lsr,
+ [MASTER_MDP] = &qnm_mdp,
+ [MASTER_CNOC_MNOC_CFG] = &qnm_mnoc_cfg,
+ [MASTER_VIDEO] = &qnm_video,
+ [MASTER_VIDEO_CV_PROC] = &qnm_video_cv_cpu,
+ [MASTER_VIDEO_PROC] = &qnm_video_cvp,
+ [MASTER_VIDEO_V_PROC] = &qnm_video_v_cpu,
+ [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf,
+ [SLAVE_MNOC_SF_MEM_NOC] = &qns_mem_noc_sf,
+ [SLAVE_SERVICE_MNOC] = &srvc_mnoc,
+};
+
+static const struct qcom_icc_desc sar2130p_mmss_noc = {
+ .config = &icc_regmap_config,
+ .nodes = mmss_noc_nodes,
+ .num_nodes = ARRAY_SIZE(mmss_noc_nodes),
+ .bcms = mmss_noc_bcms,
+ .num_bcms = ARRAY_SIZE(mmss_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const nsp_noc_bcms[] = {
+ &bcm_co0,
+};
+
+static struct qcom_icc_node * const nsp_noc_nodes[] = {
+ [MASTER_CDSP_NOC_CFG] = &qhm_nsp_noc_config,
+ [MASTER_CDSP_PROC] = &qxm_nsp,
+ [SLAVE_CDSP_MEM_NOC] = &qns_nsp_gemnoc,
+ [SLAVE_SERVICE_NSP_NOC] = &service_nsp_noc,
+};
+
+static const struct qcom_icc_desc sar2130p_nsp_noc = {
+ .config = &icc_regmap_config,
+ .nodes = nsp_noc_nodes,
+ .num_nodes = ARRAY_SIZE(nsp_noc_nodes),
+ .bcms = nsp_noc_bcms,
+ .num_bcms = ARRAY_SIZE(nsp_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const pcie_anoc_bcms[] = {
+ &bcm_sn7,
+};
+
+static struct qcom_icc_node * const pcie_anoc_nodes[] = {
+ [MASTER_PCIE_0] = &xm_pcie3_0,
+ [MASTER_PCIE_1] = &xm_pcie3_1,
+ [SLAVE_ANOC_PCIE_GEM_NOC] = &qns_pcie_mem_noc,
+};
+
+static const struct qcom_icc_desc sar2130p_pcie_anoc = {
+ .config = &icc_regmap_config,
+ .nodes = pcie_anoc_nodes,
+ .num_nodes = ARRAY_SIZE(pcie_anoc_nodes),
+ .bcms = pcie_anoc_bcms,
+ .num_bcms = ARRAY_SIZE(pcie_anoc_bcms),
+};
+
+static struct qcom_icc_bcm * const system_noc_bcms[] = {
+ &bcm_ce0,
+ &bcm_sn0,
+ &bcm_sn1,
+ &bcm_sn3,
+ &bcm_sn4,
+};
+
+static struct qcom_icc_node * const system_noc_nodes[] = {
+ [MASTER_GIC_AHB] = &qhm_gic,
+ [MASTER_QDSS_BAM] = &qhm_qdss_bam,
+ [MASTER_QSPI_0] = &qhm_qspi,
+ [MASTER_QUP_0] = &qhm_qup0,
+ [MASTER_QUP_1] = &qhm_qup1,
+ [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc,
+ [MASTER_CNOC_DATAPATH] = &qnm_cnoc_datapath,
+ [MASTER_LPASS_ANOC] = &qnm_lpass_noc,
+ [MASTER_SNOC_CFG] = &qnm_snoc_cfg,
+ [MASTER_CRYPTO] = &qxm_crypto,
+ [MASTER_PIMEM] = &qxm_pimem,
+ [MASTER_GIC] = &xm_gic,
+ [MASTER_QDSS_ETR] = &xm_qdss_etr_0,
+ [MASTER_QDSS_ETR_1] = &xm_qdss_etr_1,
+ [MASTER_SDCC_1] = &xm_sdc1,
+ [MASTER_USB3_0] = &xm_usb3_0,
+ [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc,
+ [SLAVE_SNOC_GEM_NOC_GC] = &qns_gemnoc_gc,
+ [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf,
+ [SLAVE_SERVICE_SNOC] = &srvc_snoc,
+};
+
+static const struct qcom_icc_desc sar2130p_system_noc = {
+ .config = &icc_regmap_config,
+ .nodes = system_noc_nodes,
+ .num_nodes = ARRAY_SIZE(system_noc_nodes),
+ .bcms = system_noc_bcms,
+ .num_bcms = ARRAY_SIZE(system_noc_bcms),
+};
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,sar2130p-clk-virt", .data = &sar2130p_clk_virt},
+ { .compatible = "qcom,sar2130p-config-noc", .data = &sar2130p_config_noc},
+ { .compatible = "qcom,sar2130p-gem-noc", .data = &sar2130p_gem_noc},
+ { .compatible = "qcom,sar2130p-lpass-ag-noc", .data = &sar2130p_lpass_ag_noc},
+ { .compatible = "qcom,sar2130p-mc-virt", .data = &sar2130p_mc_virt},
+ { .compatible = "qcom,sar2130p-mmss-noc", .data = &sar2130p_mmss_noc},
+ { .compatible = "qcom,sar2130p-nsp-noc", .data = &sar2130p_nsp_noc},
+ { .compatible = "qcom,sar2130p-pcie-anoc", .data = &sar2130p_pcie_anoc},
+ { .compatible = "qcom,sar2130p-system-noc", .data = &sar2130p_system_noc},
+ { }
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
+ .driver = {
+ .name = "qnoc-sar2130p",
+ .of_match_table = qnoc_of_match,
+ .sync_state = icc_sync_state,
+ },
+};
+
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+
+module_exit(qnoc_driver_exit);
+MODULE_DESCRIPTION("Qualcomm SAR2130P NoC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/interconnect/qcom/sc7180.c b/drivers/interconnect/qcom/sc7180.c
index 34a1d163d6e1..af2be1543840 100644
--- a/drivers/interconnect/qcom/sc7180.c
+++ b/drivers/interconnect/qcom/sc7180.c
@@ -1807,7 +1807,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc7180",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sc7280.c b/drivers/interconnect/qcom/sc7280.c
index 167971f8e8be..346f18d70e9e 100644
--- a/drivers/interconnect/qcom/sc7280.c
+++ b/drivers/interconnect/qcom/sc7280.c
@@ -1691,7 +1691,7 @@ static const struct qcom_icc_desc sc7280_aggre1_noc = {
.num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
.bcms = aggre1_noc_bcms,
.num_bcms = ARRAY_SIZE(aggre1_noc_bcms),
- .qos_clks_required = true,
+ .qos_requires_clocks = true,
};
static struct qcom_icc_bcm * const aggre2_noc_bcms[] = {
@@ -1723,7 +1723,7 @@ static const struct qcom_icc_desc sc7280_aggre2_noc = {
.num_nodes = ARRAY_SIZE(aggre2_noc_nodes),
.bcms = aggre2_noc_bcms,
.num_bcms = ARRAY_SIZE(aggre2_noc_bcms),
- .qos_clks_required = true,
+ .qos_requires_clocks = true,
};
static struct qcom_icc_bcm * const clk_virt_bcms[] = {
@@ -2111,7 +2111,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc7280",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sc8180x.c b/drivers/interconnect/qcom/sc8180x.c
index 03d626776ba1..a741badaa966 100644
--- a/drivers/interconnect/qcom/sc8180x.c
+++ b/drivers/interconnect/qcom/sc8180x.c
@@ -1889,7 +1889,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc8180x",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sc8280xp.c b/drivers/interconnect/qcom/sc8280xp.c
index 7acd152bf0dd..0270f6c64481 100644
--- a/drivers/interconnect/qcom/sc8280xp.c
+++ b/drivers/interconnect/qcom/sc8280xp.c
@@ -2391,7 +2391,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc8280xp",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdm660.c b/drivers/interconnect/qcom/sdm660.c
index ab91de446da8..7392bebba334 100644
--- a/drivers/interconnect/qcom/sdm660.c
+++ b/drivers/interconnect/qcom/sdm660.c
@@ -1714,7 +1714,7 @@ MODULE_DEVICE_TABLE(of, sdm660_noc_of_match);
static struct platform_driver sdm660_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-sdm660",
.of_match_table = sdm660_noc_of_match,
diff --git a/drivers/interconnect/qcom/sdm670.c b/drivers/interconnect/qcom/sdm670.c
index e5ee7fbaa641..907e1ff4ff81 100644
--- a/drivers/interconnect/qcom/sdm670.c
+++ b/drivers/interconnect/qcom/sdm670.c
@@ -1533,7 +1533,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdm670",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c
index 584800ac871a..855802be93fe 100644
--- a/drivers/interconnect/qcom/sdm845.c
+++ b/drivers/interconnect/qcom/sdm845.c
@@ -1802,7 +1802,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdm845",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdx55.c b/drivers/interconnect/qcom/sdx55.c
index e97f28b8d2b2..4117db046fa0 100644
--- a/drivers/interconnect/qcom/sdx55.c
+++ b/drivers/interconnect/qcom/sdx55.c
@@ -913,7 +913,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdx55",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdx65.c b/drivers/interconnect/qcom/sdx65.c
index 2f3f5479d8a5..d3a6c6c148e5 100644
--- a/drivers/interconnect/qcom/sdx65.c
+++ b/drivers/interconnect/qcom/sdx65.c
@@ -897,7 +897,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdx65",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdx75.c b/drivers/interconnect/qcom/sdx75.c
index 7f422c27488d..7ef1f17f3292 100644
--- a/drivers/interconnect/qcom/sdx75.c
+++ b/drivers/interconnect/qcom/sdx75.c
@@ -1083,7 +1083,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdx75",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm6115.c b/drivers/interconnect/qcom/sm6115.c
index 271b07c74862..3ee12c8a4d56 100644
--- a/drivers/interconnect/qcom/sm6115.c
+++ b/drivers/interconnect/qcom/sm6115.c
@@ -1402,7 +1402,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-sm6115",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm6350.c b/drivers/interconnect/qcom/sm6350.c
index 20923e8e6110..f41d7e19ba26 100644
--- a/drivers/interconnect/qcom/sm6350.c
+++ b/drivers/interconnect/qcom/sm6350.c
@@ -1702,7 +1702,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm6350",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm7150.c b/drivers/interconnect/qcom/sm7150.c
index dc0d1343f510..c8c77407cd50 100644
--- a/drivers/interconnect/qcom/sm7150.c
+++ b/drivers/interconnect/qcom/sm7150.c
@@ -1730,7 +1730,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm7150",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8150.c b/drivers/interconnect/qcom/sm8150.c
index f29b77556a79..edfe824cad35 100644
--- a/drivers/interconnect/qcom/sm8150.c
+++ b/drivers/interconnect/qcom/sm8150.c
@@ -1864,7 +1864,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8150",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8250.c b/drivers/interconnect/qcom/sm8250.c
index 1879fa15761f..cc1b14c13529 100644
--- a/drivers/interconnect/qcom/sm8250.c
+++ b/drivers/interconnect/qcom/sm8250.c
@@ -1991,7 +1991,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8250",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8350.c b/drivers/interconnect/qcom/sm8350.c
index 4236a43dc256..38105ead4f29 100644
--- a/drivers/interconnect/qcom/sm8350.c
+++ b/drivers/interconnect/qcom/sm8350.c
@@ -1807,7 +1807,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8350",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8450.c b/drivers/interconnect/qcom/sm8450.c
index b3cd0087377c..eb7e17df32ba 100644
--- a/drivers/interconnect/qcom/sm8450.c
+++ b/drivers/interconnect/qcom/sm8450.c
@@ -1884,7 +1884,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8450",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8550.c b/drivers/interconnect/qcom/sm8550.c
index 4d0e6fa9e003..fdb97d1f1d07 100644
--- a/drivers/interconnect/qcom/sm8550.c
+++ b/drivers/interconnect/qcom/sm8550.c
@@ -1645,7 +1645,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8550",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8650.c b/drivers/interconnect/qcom/sm8650.c
index b962e6c233ef..20ac5bc5e1fb 100644
--- a/drivers/interconnect/qcom/sm8650.c
+++ b/drivers/interconnect/qcom/sm8650.c
@@ -1650,7 +1650,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8650",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/smd-rpm.c b/drivers/interconnect/qcom/smd-rpm.c
index 3816bfb4e2f3..8316c87a2c60 100644
--- a/drivers/interconnect/qcom/smd-rpm.c
+++ b/drivers/interconnect/qcom/smd-rpm.c
@@ -85,7 +85,7 @@ static struct platform_driver qcom_interconnect_rpm_smd_driver = {
.name = "icc_smd_rpm",
},
.probe = qcom_icc_rpm_smd_probe,
- .remove_new = qcom_icc_rpm_smd_remove,
+ .remove = qcom_icc_rpm_smd_remove,
};
module_platform_driver(qcom_interconnect_rpm_smd_driver);
MODULE_AUTHOR("Georgi Djakov <georgi.djakov@linaro.org>");
diff --git a/drivers/interconnect/qcom/x1e80100.c b/drivers/interconnect/qcom/x1e80100.c
index 654abb9ce08e..2c46fdb4a054 100644
--- a/drivers/interconnect/qcom/x1e80100.c
+++ b/drivers/interconnect/qcom/x1e80100.c
@@ -1964,7 +1964,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-x1e80100",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/samsung/exynos.c b/drivers/interconnect/samsung/exynos.c
index c9e5361e17c5..9e041365d909 100644
--- a/drivers/interconnect/samsung/exynos.c
+++ b/drivers/interconnect/samsung/exynos.c
@@ -180,7 +180,7 @@ static struct platform_driver exynos_generic_icc_driver = {
.sync_state = icc_sync_state,
},
.probe = exynos_generic_icc_probe,
- .remove_new = exynos_generic_icc_remove,
+ .remove = exynos_generic_icc_remove,
};
module_platform_driver(exynos_generic_icc_driver);
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 5ce8e6504ba7..3f691e1fd22c 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -2407,9 +2407,8 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned int type)
}
static struct iommu_domain *
-amd_iommu_domain_alloc_user(struct device *dev, u32 flags,
- struct iommu_domain *parent,
- const struct iommu_user_data *user_data)
+amd_iommu_domain_alloc_paging_flags(struct device *dev, u32 flags,
+ const struct iommu_user_data *user_data)
{
unsigned int type = IOMMU_DOMAIN_UNMANAGED;
@@ -2420,7 +2419,7 @@ amd_iommu_domain_alloc_user(struct device *dev, u32 flags,
if (dev)
iommu = get_amd_iommu_from_dev(dev);
- if ((flags & ~supported_flags) || parent || user_data)
+ if ((flags & ~supported_flags) || user_data)
return ERR_PTR(-EOPNOTSUPP);
/* Allocate domain with v2 page table if IOMMU supports PASID. */
@@ -2884,7 +2883,7 @@ const struct iommu_ops amd_iommu_ops = {
.release_domain = &release_domain,
.identity_domain = &identity_domain.domain,
.domain_alloc = amd_iommu_domain_alloc,
- .domain_alloc_user = amd_iommu_domain_alloc_user,
+ .domain_alloc_paging_flags = amd_iommu_domain_alloc_paging_flags,
.domain_alloc_sva = amd_iommu_domain_alloc_sva,
.probe_device = amd_iommu_probe_device,
.release_device = amd_iommu_release_device,
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 04630dbfedd9..e4ebd9e12ad4 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3132,9 +3132,8 @@ static struct iommu_domain arm_smmu_blocked_domain = {
};
static struct iommu_domain *
-arm_smmu_domain_alloc_user(struct device *dev, u32 flags,
- struct iommu_domain *parent,
- const struct iommu_user_data *user_data)
+arm_smmu_domain_alloc_paging_flags(struct device *dev, u32 flags,
+ const struct iommu_user_data *user_data)
{
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
@@ -3145,7 +3144,7 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags,
if (flags & ~PAGING_FLAGS)
return ERR_PTR(-EOPNOTSUPP);
- if (parent || user_data)
+ if (user_data)
return ERR_PTR(-EOPNOTSUPP);
if (flags & IOMMU_HWPT_ALLOC_PASID)
@@ -3546,7 +3545,7 @@ static struct iommu_ops arm_smmu_ops = {
.hw_info = arm_smmu_hw_info,
.domain_alloc_paging = arm_smmu_domain_alloc_paging,
.domain_alloc_sva = arm_smmu_sva_domain_alloc,
- .domain_alloc_user = arm_smmu_domain_alloc_user,
+ .domain_alloc_paging_flags = arm_smmu_domain_alloc_paging_flags,
.probe_device = arm_smmu_probe_device,
.release_device = arm_smmu_release_device,
.device_group = arm_smmu_device_group,
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 527f6f89d8a1..7d0acb74d5a5 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -3328,9 +3328,8 @@ static struct dmar_domain *paging_domain_alloc(struct device *dev, bool first_st
}
static struct iommu_domain *
-intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
- struct iommu_domain *parent,
- const struct iommu_user_data *user_data)
+intel_iommu_domain_alloc_paging_flags(struct device *dev, u32 flags,
+ const struct iommu_user_data *user_data)
{
struct device_domain_info *info = dev_iommu_priv_get(dev);
bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
@@ -3340,13 +3339,6 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
struct iommu_domain *domain;
bool first_stage;
- /* Must be NESTING domain */
- if (parent) {
- if (!nested_supported(iommu) || flags)
- return ERR_PTR(-EOPNOTSUPP);
- return intel_nested_domain_alloc(parent, user_data);
- }
-
if (flags &
(~(IOMMU_HWPT_ALLOC_NEST_PARENT | IOMMU_HWPT_ALLOC_DIRTY_TRACKING
| IOMMU_HWPT_FAULT_ID_VALID)))
@@ -4472,9 +4464,10 @@ const struct iommu_ops intel_iommu_ops = {
.identity_domain = &identity_domain,
.capable = intel_iommu_capable,
.hw_info = intel_iommu_hw_info,
- .domain_alloc_user = intel_iommu_domain_alloc_user,
+ .domain_alloc_paging_flags = intel_iommu_domain_alloc_paging_flags,
.domain_alloc_sva = intel_svm_domain_alloc,
.domain_alloc_paging = intel_iommu_domain_alloc_paging,
+ .domain_alloc_nested = intel_iommu_domain_alloc_nested,
.probe_device = intel_iommu_probe_device,
.release_device = intel_iommu_release_device,
.get_resv_regions = intel_iommu_get_resv_regions,
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 2cca094c259d..6ea7bbe26b19 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -1265,8 +1265,10 @@ int __domain_setup_first_level(struct intel_iommu *iommu,
int dmar_ir_support(void);
void iommu_flush_write_buffer(struct intel_iommu *iommu);
-struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
- const struct iommu_user_data *user_data);
+struct iommu_domain *
+intel_iommu_domain_alloc_nested(struct device *dev, struct iommu_domain *parent,
+ u32 flags,
+ const struct iommu_user_data *user_data);
struct device *device_rbtree_find(struct intel_iommu *iommu, u16 rid);
enum cache_tag_type {
diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c
index 42c4533a6ea2..aba92c00b427 100644
--- a/drivers/iommu/intel/nested.c
+++ b/drivers/iommu/intel/nested.c
@@ -186,14 +186,21 @@ static const struct iommu_domain_ops intel_nested_domain_ops = {
.cache_invalidate_user = intel_nested_cache_invalidate_user,
};
-struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
- const struct iommu_user_data *user_data)
+struct iommu_domain *
+intel_iommu_domain_alloc_nested(struct device *dev, struct iommu_domain *parent,
+ u32 flags,
+ const struct iommu_user_data *user_data)
{
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
struct dmar_domain *s2_domain = to_dmar_domain(parent);
+ struct intel_iommu *iommu = info->iommu;
struct iommu_hwpt_vtd_s1 vtd;
struct dmar_domain *domain;
int ret;
+ if (!nested_supported(iommu) || flags)
+ return ERR_PTR(-EOPNOTSUPP);
+
/* Must be nested domain */
if (user_data->type != IOMMU_HWPT_DATA_VTD_S1)
return ERR_PTR(-EOPNOTSUPP);
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 7618e9c65d3f..9bc0c74cca3c 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1987,8 +1987,8 @@ __iommu_paging_domain_alloc_flags(struct device *dev, unsigned int type,
if (ops->domain_alloc_paging && !flags)
domain = ops->domain_alloc_paging(dev);
- else if (ops->domain_alloc_user)
- domain = ops->domain_alloc_user(dev, flags, NULL, NULL);
+ else if (ops->domain_alloc_paging_flags)
+ domain = ops->domain_alloc_paging_flags(dev, flags, NULL);
else if (ops->domain_alloc && !flags)
domain = ops->domain_alloc(IOMMU_DOMAIN_UNMANAGED);
else
diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c
index 9236e8ca9aa8..ce03c3804651 100644
--- a/drivers/iommu/iommufd/hw_pagetable.c
+++ b/drivers/iommu/iommufd/hw_pagetable.c
@@ -119,7 +119,7 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
lockdep_assert_held(&ioas->mutex);
- if ((flags || user_data) && !ops->domain_alloc_user)
+ if ((flags || user_data) && !ops->domain_alloc_paging_flags)
return ERR_PTR(-EOPNOTSUPP);
if (flags & ~valid_flags)
return ERR_PTR(-EOPNOTSUPP);
@@ -139,9 +139,9 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
hwpt_paging->ioas = ioas;
hwpt_paging->nest_parent = flags & IOMMU_HWPT_ALLOC_NEST_PARENT;
- if (ops->domain_alloc_user) {
- hwpt->domain = ops->domain_alloc_user(idev->dev, flags, NULL,
- user_data);
+ if (ops->domain_alloc_paging_flags) {
+ hwpt->domain = ops->domain_alloc_paging_flags(idev->dev, flags,
+ user_data);
if (IS_ERR(hwpt->domain)) {
rc = PTR_ERR(hwpt->domain);
hwpt->domain = NULL;
@@ -227,7 +227,7 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx,
int rc;
if ((flags & ~IOMMU_HWPT_FAULT_ID_VALID) ||
- !user_data->len || !ops->domain_alloc_user)
+ !user_data->len || !ops->domain_alloc_nested)
return ERR_PTR(-EOPNOTSUPP);
if (parent->auto_domain || !parent->nest_parent ||
parent->common.domain->owner != ops)
@@ -242,9 +242,9 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx,
refcount_inc(&parent->common.obj.users);
hwpt_nested->parent = parent;
- hwpt->domain = ops->domain_alloc_user(idev->dev,
- flags & ~IOMMU_HWPT_FAULT_ID_VALID,
- parent->common.domain, user_data);
+ hwpt->domain = ops->domain_alloc_nested(
+ idev->dev, parent->common.domain,
+ flags & ~IOMMU_HWPT_FAULT_ID_VALID, user_data);
if (IS_ERR(hwpt->domain)) {
rc = PTR_ERR(hwpt->domain);
hwpt->domain = NULL;
diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index 2f9de177dffc..a0de6d6d4e68 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -356,8 +356,8 @@ __mock_domain_alloc_nested(const struct iommu_user_data *user_data)
}
static struct iommu_domain *
-mock_domain_alloc_nested(struct iommu_domain *parent, u32 flags,
- const struct iommu_user_data *user_data)
+mock_domain_alloc_nested(struct device *dev, struct iommu_domain *parent,
+ u32 flags, const struct iommu_user_data *user_data)
{
struct mock_iommu_domain_nested *mock_nested;
struct mock_iommu_domain *mock_parent;
@@ -379,9 +379,8 @@ mock_domain_alloc_nested(struct iommu_domain *parent, u32 flags,
}
static struct iommu_domain *
-mock_domain_alloc_user(struct device *dev, u32 flags,
- struct iommu_domain *parent,
- const struct iommu_user_data *user_data)
+mock_domain_alloc_paging_flags(struct device *dev, u32 flags,
+ const struct iommu_user_data *user_data)
{
bool has_dirty_flag = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
@@ -390,9 +389,6 @@ mock_domain_alloc_user(struct device *dev, u32 flags,
MOCK_FLAGS_DEVICE_NO_DIRTY;
struct iommu_domain *domain;
- if (parent)
- return mock_domain_alloc_nested(parent, flags, user_data);
-
if (user_data)
return ERR_PTR(-EOPNOTSUPP);
if ((flags & ~PAGING_FLAGS) || (has_dirty_flag && no_dirty_ops))
@@ -718,7 +714,8 @@ static const struct iommu_ops mock_ops = {
.pgsize_bitmap = MOCK_IO_PAGE_SIZE,
.hw_info = mock_domain_hw_info,
.domain_alloc_paging = mock_domain_alloc_paging,
- .domain_alloc_user = mock_domain_alloc_user,
+ .domain_alloc_paging_flags = mock_domain_alloc_paging_flags,
+ .domain_alloc_nested = mock_domain_alloc_nested,
.capable = mock_domain_capable,
.device_group = generic_device_group,
.probe_device = mock_probe_device,
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 16acce0f102d..92244cfa0464 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -47,6 +47,7 @@
#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1)
#define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2)
#define ITS_FLAGS_FORCE_NON_SHAREABLE (1ULL << 3)
+#define ITS_FLAGS_WORKAROUND_HISILICON_162100801 (1ULL << 4)
#define RD_LOCAL_LPI_ENABLED BIT(0)
#define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1)
@@ -64,6 +65,7 @@ static u32 lpi_id_bits;
#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)
static u8 __ro_after_init lpi_prop_prio;
+static struct its_node *find_4_1_its(void);
/*
* Collection structure - just an ID, and a redistributor address to
@@ -3883,6 +3885,20 @@ static void its_vpe_db_proxy_move(struct its_vpe *vpe, int from, int to)
raw_spin_unlock_irqrestore(&vpe_proxy.lock, flags);
}
+static void its_vpe_4_1_invall_locked(int cpu, struct its_vpe *vpe)
+{
+ void __iomem *rdbase;
+ u64 val;
+
+ val = GICR_INVALLR_V;
+ val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id);
+
+ guard(raw_spinlock)(&gic_data_rdist_cpu(cpu)->rd_lock);
+ rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
+ gic_write_lpir(val, rdbase + GICR_INVALLR);
+ wait_for_syncr(rdbase);
+}
+
static int its_vpe_set_affinity(struct irq_data *d,
const struct cpumask *mask_val,
bool force)
@@ -3890,6 +3906,7 @@ static int its_vpe_set_affinity(struct irq_data *d,
struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
unsigned int from, cpu = nr_cpu_ids;
struct cpumask *table_mask;
+ struct its_node *its;
unsigned long flags;
/*
@@ -3952,6 +3969,11 @@ static int its_vpe_set_affinity(struct irq_data *d,
vpe->col_idx = cpu;
its_send_vmovp(vpe);
+
+ its = find_4_1_its();
+ if (its && its->flags & ITS_FLAGS_WORKAROUND_HISILICON_162100801)
+ its_vpe_4_1_invall_locked(cpu, vpe);
+
its_vpe_db_proxy_move(vpe, from, cpu);
out:
@@ -4259,22 +4281,12 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe,
static void its_vpe_4_1_invall(struct its_vpe *vpe)
{
- void __iomem *rdbase;
unsigned long flags;
- u64 val;
int cpu;
- val = GICR_INVALLR_V;
- val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id);
-
/* Target the redistributor this vPE is currently known on */
cpu = vpe_to_cpuid_lock(vpe, &flags);
- raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
- rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
- gic_write_lpir(val, rdbase + GICR_INVALLR);
-
- wait_for_syncr(rdbase);
- raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
+ its_vpe_4_1_invall_locked(cpu, vpe);
vpe_to_cpuid_unlock(vpe, flags);
}
@@ -4867,6 +4879,14 @@ static bool its_set_non_coherent(void *data)
return true;
}
+static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data)
+{
+ struct its_node *its = data;
+
+ its->flags |= ITS_FLAGS_WORKAROUND_HISILICON_162100801;
+ return true;
+}
+
static const struct gic_quirk its_quirks[] = {
#ifdef CONFIG_CAVIUM_ERRATUM_22375
{
@@ -4913,6 +4933,14 @@ static const struct gic_quirk its_quirks[] = {
.init = its_enable_quirk_hip07_161600802,
},
#endif
+#ifdef CONFIG_HISILICON_ERRATUM_162100801
+ {
+ .desc = "ITS: Hip09 erratum 162100801",
+ .iidr = 0x00051736,
+ .mask = 0xffffffff,
+ .init = its_enable_quirk_hip09_162100801,
+ },
+#endif
#ifdef CONFIG_ROCKCHIP_ERRATUM_3588001
{
.desc = "ITS: Rockchip erratum RK3588001",
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 3be7bd8cd8cd..8fae6dc01024 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -400,7 +400,7 @@ static void gic_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gic_chip_data *gic = irq_data_get_irq_chip_data(d);
if (gic->domain->pm_dev)
- seq_printf(p, gic->domain->pm_dev->of_node->name);
+ seq_puts(p, gic->domain->pm_dev->of_node->name);
else
seq_printf(p, "GIC-%d", (int)(gic - &gic_data[0]));
}
diff --git a/drivers/irqchip/irq-imgpdc.c b/drivers/irqchip/irq-imgpdc.c
index b42ed68acfa6..85f80bac0961 100644
--- a/drivers/irqchip/irq-imgpdc.c
+++ b/drivers/irqchip/irq-imgpdc.c
@@ -479,7 +479,7 @@ static struct platform_driver pdc_intc_driver = {
.of_match_table = pdc_intc_match,
},
.probe = pdc_intc_probe,
- .remove_new = pdc_intc_remove,
+ .remove = pdc_intc_remove,
};
static int __init pdc_intc_init(void)
diff --git a/drivers/irqchip/irq-imx-intmux.c b/drivers/irqchip/irq-imx-intmux.c
index 511adfaeec82..787543d07565 100644
--- a/drivers/irqchip/irq-imx-intmux.c
+++ b/drivers/irqchip/irq-imx-intmux.c
@@ -361,6 +361,6 @@ static struct platform_driver imx_intmux_driver = {
.pm = &imx_intmux_pm_ops,
},
.probe = imx_intmux_probe,
- .remove_new = imx_intmux_remove,
+ .remove = imx_intmux_remove,
};
builtin_platform_driver(imx_intmux_driver);
diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index 75a0e980ff35..b0e9788c0045 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -328,6 +328,6 @@ static struct platform_driver imx_irqsteer_driver = {
.pm = &imx_irqsteer_pm_ops,
},
.probe = imx_irqsteer_probe,
- .remove_new = imx_irqsteer_remove,
+ .remove = imx_irqsteer_remove,
};
builtin_platform_driver(imx_irqsteer_driver);
diff --git a/drivers/irqchip/irq-keystone.c b/drivers/irqchip/irq-keystone.c
index 30f1979fa124..808c781e2548 100644
--- a/drivers/irqchip/irq-keystone.c
+++ b/drivers/irqchip/irq-keystone.c
@@ -211,7 +211,7 @@ MODULE_DEVICE_TABLE(of, keystone_irq_dt_ids);
static struct platform_driver keystone_irq_device_driver = {
.probe = keystone_irq_probe,
- .remove_new = keystone_irq_remove,
+ .remove = keystone_irq_remove,
.driver = {
.name = "keystone_irq",
.of_match_table = of_match_ptr(keystone_irq_dt_ids),
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index 1aef5c4d27c6..c0e1aafe468c 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -418,7 +418,7 @@ static struct platform_driver ls_scfg_msi_driver = {
.of_match_table = ls_scfg_msi_id,
},
.probe = ls_scfg_msi_probe,
- .remove_new = ls_scfg_msi_remove,
+ .remove = ls_scfg_msi_remove,
};
module_platform_driver(ls_scfg_msi_driver);
diff --git a/drivers/irqchip/irq-madera.c b/drivers/irqchip/irq-madera.c
index acceb6e7fa95..b32982c11515 100644
--- a/drivers/irqchip/irq-madera.c
+++ b/drivers/irqchip/irq-madera.c
@@ -236,7 +236,7 @@ static void madera_irq_remove(struct platform_device *pdev)
static struct platform_driver madera_irq_driver = {
.probe = madera_irq_probe,
- .remove_new = madera_irq_remove,
+ .remove = madera_irq_remove,
.driver = {
.name = "madera-irq",
.pm = &madera_irq_pm_ops,
diff --git a/drivers/irqchip/irq-mvebu-pic.c b/drivers/irqchip/irq-mvebu-pic.c
index 08b0cc862adf..3888b7585981 100644
--- a/drivers/irqchip/irq-mvebu-pic.c
+++ b/drivers/irqchip/irq-mvebu-pic.c
@@ -71,7 +71,7 @@ static void mvebu_pic_print_chip(struct irq_data *d, struct seq_file *p)
{
struct mvebu_pic *pic = irq_data_get_irq_chip_data(d);
- seq_printf(p, dev_name(&pic->pdev->dev));
+ seq_puts(p, dev_name(&pic->pdev->dev));
}
static const struct irq_chip mvebu_pic_chip = {
@@ -183,7 +183,7 @@ MODULE_DEVICE_TABLE(of, mvebu_pic_of_match);
static struct platform_driver mvebu_pic_driver = {
.probe = mvebu_pic_probe,
- .remove_new = mvebu_pic_remove,
+ .remove = mvebu_pic_remove,
.driver = {
.name = "mvebu-pic",
.of_match_table = mvebu_pic_of_match,
diff --git a/drivers/irqchip/irq-mvebu-sei.c b/drivers/irqchip/irq-mvebu-sei.c
index f8c70f2d100a..065166ab5dbc 100644
--- a/drivers/irqchip/irq-mvebu-sei.c
+++ b/drivers/irqchip/irq-mvebu-sei.c
@@ -192,7 +192,6 @@ static void mvebu_sei_domain_free(struct irq_domain *domain, unsigned int virq,
}
static const struct irq_domain_ops mvebu_sei_domain_ops = {
- .select = msi_lib_irq_domain_select,
.alloc = mvebu_sei_domain_alloc,
.free = mvebu_sei_domain_free,
};
@@ -306,6 +305,7 @@ static void mvebu_sei_cp_domain_free(struct irq_domain *domain,
}
static const struct irq_domain_ops mvebu_sei_cp_domain_ops = {
+ .select = msi_lib_irq_domain_select,
.alloc = mvebu_sei_cp_domain_alloc,
.free = mvebu_sei_cp_domain_free,
};
diff --git a/drivers/irqchip/irq-pruss-intc.c b/drivers/irqchip/irq-pruss-intc.c
index 060eb000e9d3..bee01980b463 100644
--- a/drivers/irqchip/irq-pruss-intc.c
+++ b/drivers/irqchip/irq-pruss-intc.c
@@ -648,7 +648,7 @@ static struct platform_driver pruss_intc_driver = {
.suppress_bind_attrs = true,
},
.probe = pruss_intc_probe,
- .remove_new = pruss_intc_remove,
+ .remove = pruss_intc_remove,
};
module_platform_driver(pruss_intc_driver);
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index 9ad37237ba95..954419f2460d 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -584,7 +584,7 @@ static SIMPLE_DEV_PM_OPS(intc_irqpin_pm_ops, intc_irqpin_suspend, NULL);
static struct platform_driver intc_irqpin_device_driver = {
.probe = intc_irqpin_probe,
- .remove_new = intc_irqpin_remove,
+ .remove = intc_irqpin_remove,
.driver = {
.name = "renesas_intc_irqpin",
.of_match_table = intc_irqpin_dt_ids,
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
index 76026e0b8e20..cbce8ffc7de4 100644
--- a/drivers/irqchip/irq-renesas-irqc.c
+++ b/drivers/irqchip/irq-renesas-irqc.c
@@ -247,7 +247,7 @@ MODULE_DEVICE_TABLE(of, irqc_dt_ids);
static struct platform_driver irqc_device_driver = {
.probe = irqc_probe,
- .remove_new = irqc_remove,
+ .remove = irqc_remove,
.driver = {
.name = "renesas_irqc",
.of_match_table = irqc_dt_ids,
diff --git a/drivers/irqchip/irq-renesas-rza1.c b/drivers/irqchip/irq-renesas-rza1.c
index f05afe82db4d..d4e6a68889ec 100644
--- a/drivers/irqchip/irq-renesas-rza1.c
+++ b/drivers/irqchip/irq-renesas-rza1.c
@@ -259,7 +259,7 @@ MODULE_DEVICE_TABLE(of, rza1_irqc_dt_ids);
static struct platform_driver rza1_irqc_device_driver = {
.probe = rza1_irqc_probe,
- .remove_new = rza1_irqc_remove,
+ .remove = rza1_irqc_remove,
.driver = {
.name = "renesas_rza1_irqc",
.of_match_table = rza1_irqc_dt_ids,
diff --git a/drivers/irqchip/irq-ts4800.c b/drivers/irqchip/irq-ts4800.c
index b5dddb3c1568..cc219f28d317 100644
--- a/drivers/irqchip/irq-ts4800.c
+++ b/drivers/irqchip/irq-ts4800.c
@@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(of, ts4800_ic_of_match);
static struct platform_driver ts4800_ic_driver = {
.probe = ts4800_ic_probe,
- .remove_new = ts4800_ic_remove,
+ .remove = ts4800_ic_remove,
.driver = {
.name = "ts4800-irqc",
.of_match_table = ts4800_ic_of_match,
diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c
index ca471c6fee99..0abc8934c2ee 100644
--- a/drivers/irqchip/irq-versatile-fpga.c
+++ b/drivers/irqchip/irq-versatile-fpga.c
@@ -69,7 +69,7 @@ static void fpga_irq_print_chip(struct irq_data *d, struct seq_file *p)
{
struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
- seq_printf(p, irq_domain_get_of_node(f->domain)->name);
+ seq_puts(p, irq_domain_get_of_node(f->domain)->name);
}
static const struct irq_chip fpga_chip = {
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index 6797770474a5..680243751d62 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/kfifo.h>
#include <linux/err.h>
+#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index baaf5f8b80ae..7049ec7fb8eb 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -384,6 +384,7 @@ static int raid0_set_limits(struct mddev *mddev)
lim.max_write_zeroes_sectors = mddev->chunk_sectors;
lim.io_min = mddev->chunk_sectors << 9;
lim.io_opt = lim.io_min * mddev->raid_disks;
+ lim.features |= BLK_FEAT_ATOMIC_WRITES_STACKED;
err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
if (err) {
queue_limits_cancel_update(mddev->gendisk->queue);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index a5adf08ee174..519c56f0ee3d 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1571,7 +1571,21 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
continue;
}
if (is_bad) {
- int good_sectors = first_bad - r1_bio->sector;
+ int good_sectors;
+
+ /*
+ * We cannot atomically write this, so just
+ * error in that case. It could be possible to
+ * atomically write other mirrors, but the
+ * complexity of supporting that is not worth
+ * the benefit.
+ */
+ if (bio->bi_opf & REQ_ATOMIC) {
+ error = -EIO;
+ goto err_handle;
+ }
+
+ good_sectors = first_bad - r1_bio->sector;
if (good_sectors < max_sectors)
max_sectors = good_sectors;
}
@@ -1657,7 +1671,8 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
mbio->bi_iter.bi_sector = (r1_bio->sector + rdev->data_offset);
mbio->bi_end_io = raid1_end_write_request;
- mbio->bi_opf = bio_op(bio) | (bio->bi_opf & (REQ_SYNC | REQ_FUA));
+ mbio->bi_opf = bio_op(bio) |
+ (bio->bi_opf & (REQ_SYNC | REQ_FUA | REQ_ATOMIC));
if (test_bit(FailFast, &rdev->flags) &&
!test_bit(WriteMostly, &rdev->flags) &&
conf->raid_disks - mddev->degraded > 1)
@@ -3224,6 +3239,7 @@ static int raid1_set_limits(struct mddev *mddev)
md_init_stacking_limits(&lim);
lim.max_write_zeroes_sectors = 0;
+ lim.features |= BLK_FEAT_ATOMIC_WRITES_STACKED;
err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
if (err) {
queue_limits_cancel_update(mddev->gendisk->queue);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 18989231791a..7d7a8a2524dc 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1255,6 +1255,7 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
const enum req_op op = bio_op(bio);
const blk_opf_t do_sync = bio->bi_opf & REQ_SYNC;
const blk_opf_t do_fua = bio->bi_opf & REQ_FUA;
+ const blk_opf_t do_atomic = bio->bi_opf & REQ_ATOMIC;
unsigned long flags;
struct r10conf *conf = mddev->private;
struct md_rdev *rdev;
@@ -1273,7 +1274,7 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
mbio->bi_iter.bi_sector = (r10_bio->devs[n_copy].addr +
choose_data_offset(r10_bio, rdev));
mbio->bi_end_io = raid10_end_write_request;
- mbio->bi_opf = op | do_sync | do_fua;
+ mbio->bi_opf = op | do_sync | do_fua | do_atomic;
if (!replacement && test_bit(FailFast,
&conf->mirrors[devnum].rdev->flags)
&& enough(conf, devnum))
@@ -1468,7 +1469,21 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
continue;
}
if (is_bad) {
- int good_sectors = first_bad - dev_sector;
+ int good_sectors;
+
+ /*
+ * We cannot atomically write this, so just
+ * error in that case. It could be possible to
+ * atomically write other mirrors, but the
+ * complexity of supporting that is not worth
+ * the benefit.
+ */
+ if (bio->bi_opf & REQ_ATOMIC) {
+ error = -EIO;
+ goto err_handle;
+ }
+
+ good_sectors = first_bad - dev_sector;
if (good_sectors < max_sectors)
max_sectors = good_sectors;
}
@@ -4025,6 +4040,7 @@ static int raid10_set_queue_limits(struct mddev *mddev)
lim.max_write_zeroes_sectors = 0;
lim.io_min = mddev->chunk_sectors << 9;
lim.io_opt = lim.io_min * raid10_nr_stripes(conf);
+ lim.features |= BLK_FEAT_ATOMIC_WRITES_STACKED;
err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
if (err) {
queue_limits_cancel_update(mddev->gendisk->queue);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 902c306bc972..09cbe3f0ab1e 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -637,7 +637,6 @@ config MCHP_LAN966X_PCI
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
-source "drivers/misc/ti-st/Kconfig"
source "drivers/misc/lis3lv02d/Kconfig"
source "drivers/misc/altera-stapl/Kconfig"
source "drivers/misc/mei/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 885b22989580..40bf953185c7 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -40,7 +40,6 @@ obj-y += eeprom/
obj-y += cb710/
obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o
obj-$(CONFIG_PCH_PHUB) += pch_phub.o
-obj-y += ti-st/
obj-y += lis3lv02d/
obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
obj-$(CONFIG_INTEL_MEI) += mei/
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
index 6d4edd69db12..e7d73c972f65 100644
--- a/drivers/misc/apds990x.c
+++ b/drivers/misc/apds990x.c
@@ -1147,7 +1147,7 @@ static int apds990x_probe(struct i2c_client *client)
err = chip->pdata->setup_resources();
if (err) {
err = -EINVAL;
- goto fail3;
+ goto fail4;
}
}
@@ -1155,7 +1155,7 @@ static int apds990x_probe(struct i2c_client *client)
apds990x_attribute_group);
if (err < 0) {
dev_err(&chip->client->dev, "Sysfs registration failed\n");
- goto fail4;
+ goto fail5;
}
err = request_threaded_irq(client->irq, NULL,
@@ -1166,15 +1166,17 @@ static int apds990x_probe(struct i2c_client *client)
if (err) {
dev_err(&client->dev, "could not get IRQ %d\n",
client->irq);
- goto fail5;
+ goto fail6;
}
return err;
-fail5:
+fail6:
sysfs_remove_group(&chip->client->dev.kobj,
&apds990x_attribute_group[0]);
-fail4:
+fail5:
if (chip->pdata && chip->pdata->release_resources)
chip->pdata->release_resources();
+fail4:
+ pm_runtime_disable(&client->dev);
fail3:
regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
fail2:
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 6eac0f335915..1d0322dfaf79 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -153,7 +153,7 @@ static int ssc_sound_dai_probe(struct ssc_device *ssc)
ssc->sound_dai = false;
- if (!of_property_read_bool(np, "#sound-dai-cells"))
+ if (!of_property_present(np, "#sound-dai-cells"))
return 0;
id = of_alias_get_id(np, "ssc");
@@ -176,7 +176,7 @@ static void ssc_sound_dai_remove(struct ssc_device *ssc)
#else
static inline int ssc_sound_dai_probe(struct ssc_device *ssc)
{
- if (of_property_read_bool(ssc->pdev->dev.of_node, "#sound-dai-cells"))
+ if (of_property_present(ssc->pdev->dev.of_node, "#sound-dai-cells"))
return -ENOTSUPP;
return 0;
diff --git a/drivers/misc/cardreader/alcor_pci.c b/drivers/misc/cardreader/alcor_pci.c
index 0142c4bf4f42..a5549eaf52d0 100644
--- a/drivers/misc/cardreader/alcor_pci.c
+++ b/drivers/misc/cardreader/alcor_pci.c
@@ -17,8 +17,6 @@
#include <linux/alcor_pci.h>
-#define DRV_NAME_ALCOR_PCI "alcor_pci"
-
static DEFINE_IDA(alcor_pci_idr);
static struct mfd_cell alcor_pci_cells[] = {
diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c
index f150d8769f19..77b0490a1b38 100644
--- a/drivers/misc/cardreader/rtsx_usb.c
+++ b/drivers/misc/cardreader/rtsx_usb.c
@@ -20,11 +20,11 @@ MODULE_PARM_DESC(polling_pipe, "polling pipe (0: ctl, 1: bulk)");
static const struct mfd_cell rtsx_usb_cells[] = {
[RTSX_USB_SD_CARD] = {
- .name = "rtsx_usb_sdmmc",
+ .name = DRV_NAME_RTSX_USB_SDMMC,
.pdata_size = 0,
},
[RTSX_USB_MS_CARD] = {
- .name = "rtsx_usb_ms",
+ .name = DRV_NAME_RTSX_USB_MS,
.pdata_size = 0,
},
};
@@ -780,7 +780,7 @@ static const struct usb_device_id rtsx_usb_usb_ids[] = {
MODULE_DEVICE_TABLE(usb, rtsx_usb_usb_ids);
static struct usb_driver rtsx_usb_driver = {
- .name = "rtsx_usb",
+ .name = DRV_NAME_RTSX_USB,
.probe = rtsx_usb_probe,
.disconnect = rtsx_usb_disconnect,
.suspend = rtsx_usb_suspend,
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9df12399bda3..cb1c4b8e7fd3 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -97,11 +97,11 @@ config EEPROM_DIGSY_MTC_CFG
If unsure, say N.
config EEPROM_IDT_89HPESX
- tristate "IDT 89HPESx PCIe-swtiches EEPROM / CSR support"
+ tristate "IDT 89HPESx PCIe-switches EEPROM / CSR support"
depends on I2C && SYSFS
help
Enable this driver to get read/write access to EEPROM / CSRs
- over IDT PCIe-swtich i2c-slave interface.
+ over IDT PCIe-switch i2c-slave interface.
This driver can also be built as a module. If so, the module
will be called idt_89hpesx.
diff --git a/drivers/misc/eeprom/eeprom_93cx6.c b/drivers/misc/eeprom/eeprom_93cx6.c
index 9627294fe3e9..e6f0e0fc1ca2 100644
--- a/drivers/misc/eeprom/eeprom_93cx6.c
+++ b/drivers/misc/eeprom/eeprom_93cx6.c
@@ -8,6 +8,7 @@
* Supported chipsets: 93c46 & 93c66.
*/
+#include <linux/bits.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -102,7 +103,7 @@ static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
/*
* Check if this bit needs to be set.
*/
- eeprom->reg_data_in = !!(data & (1 << (i - 1)));
+ eeprom->reg_data_in = !!(data & BIT(i - 1));
/*
* Write the bit to the eeprom register.
@@ -152,7 +153,7 @@ static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
* Read if the bit has been set.
*/
if (eeprom->reg_data_out)
- buf |= (1 << (i - 1));
+ buf |= BIT(i - 1);
eeprom_93cx6_pulse_low(eeprom);
}
@@ -186,6 +187,11 @@ void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
eeprom_93cx6_write_bits(eeprom, command,
PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
+ if (has_quirk_extra_read_cycle(eeprom)) {
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+ }
+
/*
* Read the requested 16 bits.
*/
@@ -252,6 +258,11 @@ void eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom, const u8 byte,
eeprom_93cx6_write_bits(eeprom, command,
PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1);
+ if (has_quirk_extra_read_cycle(eeprom)) {
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+ }
+
/*
* Read the requested 8 bits.
*/
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index e2221be88445..9cae6f530679 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -229,7 +229,7 @@ static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on)
static ssize_t
eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
- const char *buf, unsigned off)
+ const char *buf, unsigned int off)
{
struct spi_message m;
struct spi_transfer t[2] = {};
diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c
index 1643ba2ff964..c288aeec16c0 100644
--- a/drivers/misc/isl29020.c
+++ b/drivers/misc/isl29020.c
@@ -68,7 +68,7 @@ static ssize_t als_lux_input_data_show(struct device *dev,
if (val < 0)
return val;
lux = ((((1 << (2 * (val & 3))))*1000) * ret_val) / 65536;
- return sprintf(buf, "%ld\n", lux);
+ return sprintf(buf, "%lu\n", lux);
}
static ssize_t als_sensing_range_store(struct device *dev,
diff --git a/drivers/misc/keba/Kconfig b/drivers/misc/keba/Kconfig
index 5fbcbc2252ac..d6d47197a963 100644
--- a/drivers/misc/keba/Kconfig
+++ b/drivers/misc/keba/Kconfig
@@ -1,7 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
config KEBA_CP500
tristate "KEBA CP500 system FPGA support"
+ depends on X86_64 || ARM64 || COMPILE_TEST
depends on PCI
+ depends on I2C
select AUXILIARY_BUS
help
This driver supports the KEBA CP500 system FPGA, which is used in
@@ -11,3 +13,14 @@ config KEBA_CP500
This driver can also be built as a module. If so, the module will be
called cp500.
+
+config KEBA_LAN9252
+ tristate "KEBA CP500 LAN9252 configuration"
+ depends on SPI
+ depends on KEBA_CP500 || COMPILE_TEST
+ help
+ This driver is used for updating the configuration of the LAN9252
+ controller on KEBA CP500 devices.
+
+ This driver can also be built as a module. If so, the module will be
+ called lan9252.
diff --git a/drivers/misc/keba/Makefile b/drivers/misc/keba/Makefile
index 0a8b846cda7d..05e9efcad54f 100644
--- a/drivers/misc/keba/Makefile
+++ b/drivers/misc/keba/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_KEBA_CP500) += cp500.o
+obj-$(CONFIG_KEBA_LAN9252) += lan9252.o
diff --git a/drivers/misc/keba/cp500.c b/drivers/misc/keba/cp500.c
index ae0922817881..255d3022dae8 100644
--- a/drivers/misc/keba/cp500.c
+++ b/drivers/misc/keba/cp500.c
@@ -12,7 +12,12 @@
#include <linux/i2c.h>
#include <linux/misc/keba.h>
#include <linux/module.h>
+#include <linux/mtd/partitions.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/nvmem-provider.h>
#include <linux/pci.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
#define CP500 "cp500"
@@ -27,6 +32,7 @@
/* BAR 0 registers */
#define CP500_VERSION_REG 0x00
#define CP500_RECONFIG_REG 0x11 /* upper 8-bits of STARTUP register */
+#define CP500_PRESENT_REG 0x20
#define CP500_AXI_REG 0x40
/* Bits in BUILD_REG */
@@ -35,14 +41,35 @@
/* Bits in RECONFIG_REG */
#define CP500_RECFG_REQ 0x01 /* reconfigure FPGA on next reset */
+/* Bits in PRESENT_REG */
+#define CP500_PRESENT_FAN0 0x01
+
/* MSIX */
#define CP500_AXI_MSIX 3
+#define CP500_RFB_UART_MSIX 4
+#define CP500_DEBUG_UART_MSIX 5
+#define CP500_SI1_UART_MSIX 6
#define CP500_NUM_MSIX 8
#define CP500_NUM_MSIX_NO_MMI 2
#define CP500_NUM_MSIX_NO_AXI 3
/* EEPROM */
-#define CP500_HW_CPU_EEPROM_NAME "cp500_cpu_eeprom"
+#define CP500_EEPROM_DA_OFFSET 0x016F
+#define CP500_EEPROM_DA_ESC_TYPE_MASK 0x01
+#define CP500_EEPROM_ESC_LAN9252 0x00
+#define CP500_EEPROM_ESC_ET1100 0x01
+#define CP500_EEPROM_CPU_NAME "cpu_eeprom"
+#define CP500_EEPROM_CPU_OFFSET 0
+#define CP500_EEPROM_CPU_SIZE 3072
+#define CP500_EEPROM_USER_NAME "user_eeprom"
+#define CP500_EEPROM_USER_OFFSET 3072
+#define CP500_EEPROM_USER_SIZE 1024
+
+/* SPI flash running at full speed */
+#define CP500_FLASH_HZ (33 * 1000 * 1000)
+
+/* LAN9252 */
+#define CP500_LAN9252_HZ (10 * 1000 * 1000)
#define CP500_IS_CP035(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP035)
#define CP500_IS_CP505(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP505)
@@ -51,29 +78,56 @@
struct cp500_dev_info {
off_t offset;
size_t size;
+ unsigned int msix;
};
struct cp500_devs {
struct cp500_dev_info startup;
+ struct cp500_dev_info spi;
struct cp500_dev_info i2c;
+ struct cp500_dev_info fan;
+ struct cp500_dev_info batt;
+ struct cp500_dev_info uart0_rfb;
+ struct cp500_dev_info uart1_dbg;
+ struct cp500_dev_info uart2_si1;
};
/* list of devices within FPGA of CP035 family (CP035, CP056, CP057) */
static struct cp500_devs cp035_devices = {
.startup = { 0x0000, SZ_4K },
+ .spi = { 0x1000, SZ_4K },
.i2c = { 0x4000, SZ_4K },
+ .fan = { 0x9000, SZ_4K },
+ .batt = { 0xA000, SZ_4K },
+ .uart0_rfb = { 0xB000, SZ_4K, CP500_RFB_UART_MSIX },
+ .uart2_si1 = { 0xD000, SZ_4K, CP500_SI1_UART_MSIX },
};
/* list of devices within FPGA of CP505 family (CP503, CP505, CP507) */
static struct cp500_devs cp505_devices = {
.startup = { 0x0000, SZ_4K },
+ .spi = { 0x4000, SZ_4K },
.i2c = { 0x5000, SZ_4K },
+ .fan = { 0x9000, SZ_4K },
+ .batt = { 0xA000, SZ_4K },
+ .uart0_rfb = { 0xB000, SZ_4K, CP500_RFB_UART_MSIX },
+ .uart2_si1 = { 0xD000, SZ_4K, CP500_SI1_UART_MSIX },
};
/* list of devices within FPGA of CP520 family (CP520, CP530) */
static struct cp500_devs cp520_devices = {
- .startup = { 0x0000, SZ_4K },
- .i2c = { 0x5000, SZ_4K },
+ .startup = { 0x0000, SZ_4K },
+ .spi = { 0x4000, SZ_4K },
+ .i2c = { 0x5000, SZ_4K },
+ .fan = { 0x8000, SZ_4K },
+ .batt = { 0x9000, SZ_4K },
+ .uart0_rfb = { 0xC000, SZ_4K, CP500_RFB_UART_MSIX },
+ .uart1_dbg = { 0xD000, SZ_4K, CP500_DEBUG_UART_MSIX },
+};
+
+struct cp500_nvmem {
+ struct nvmem_device *nvmem;
+ unsigned int offset;
};
struct cp500 {
@@ -85,18 +139,31 @@ struct cp500 {
int minor;
int build;
} version;
+ struct notifier_block nvmem_notifier;
+ atomic_t nvmem_notified;
/* system FPGA BAR */
resource_size_t sys_hwbase;
+ struct keba_spi_auxdev *spi;
struct keba_i2c_auxdev *i2c;
+ struct keba_fan_auxdev *fan;
+ struct keba_batt_auxdev *batt;
+ struct keba_uart_auxdev *uart0_rfb;
+ struct keba_uart_auxdev *uart1_dbg;
+ struct keba_uart_auxdev *uart2_si1;
/* ECM EtherCAT BAR */
resource_size_t ecm_hwbase;
+ /* NVMEM devices */
+ struct cp500_nvmem nvmem_cpu;
+ struct cp500_nvmem nvmem_user;
+
void __iomem *system_startup_addr;
};
/* I2C devices */
+#define CP500_EEPROM_ADDR 0x50
static struct i2c_board_info cp500_i2c_info[] = {
{ /* temperature sensor */
I2C_BOARD_INFO("emc1403", 0x4c),
@@ -107,30 +174,66 @@ static struct i2c_board_info cp500_i2c_info[] = {
* CP505 family: bridge board
* CP520 family: carrier board
*/
- I2C_BOARD_INFO("24c32", 0x50),
- .dev_name = CP500_HW_CPU_EEPROM_NAME,
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR),
},
{ /* interface board EEPROM */
- I2C_BOARD_INFO("24c32", 0x51),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 1),
},
{ /*
* EEPROM (optional)
* CP505 family: CPU board
* CP520 family: MMI board
*/
- I2C_BOARD_INFO("24c32", 0x52),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 2),
},
{ /* extension module 0 EEPROM (optional) */
- I2C_BOARD_INFO("24c32", 0x53),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 3),
},
{ /* extension module 1 EEPROM (optional) */
- I2C_BOARD_INFO("24c32", 0x54),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 4),
},
{ /* extension module 2 EEPROM (optional) */
- I2C_BOARD_INFO("24c32", 0x55),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 5),
},
{ /* extension module 3 EEPROM (optional) */
- I2C_BOARD_INFO("24c32", 0x56),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 6),
+ }
+};
+
+/* SPI devices */
+static struct mtd_partition cp500_partitions[] = {
+ {
+ .name = "system-flash-parts",
+ .size = MTDPART_SIZ_FULL,
+ .offset = 0,
+ .mask_flags = 0
+ }
+};
+static const struct flash_platform_data cp500_w25q32 = {
+ .type = "w25q32",
+ .name = "system-flash",
+ .parts = cp500_partitions,
+ .nr_parts = ARRAY_SIZE(cp500_partitions),
+};
+static const struct flash_platform_data cp500_m25p16 = {
+ .type = "m25p16",
+ .name = "system-flash",
+ .parts = cp500_partitions,
+ .nr_parts = ARRAY_SIZE(cp500_partitions),
+};
+static struct spi_board_info cp500_spi_info[] = {
+ { /* system FPGA configuration bitstream flash */
+ .modalias = "m25p80",
+ .platform_data = &cp500_m25p16,
+ .max_speed_hz = CP500_FLASH_HZ,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ }, { /* LAN9252 EtherCAT slave controller */
+ .modalias = "lan9252",
+ .platform_data = NULL,
+ .max_speed_hz = CP500_LAN9252_HZ,
+ .chip_select = 1,
+ .mode = SPI_MODE_3,
}
};
@@ -229,7 +332,7 @@ static void cp500_i2c_release(struct device *dev)
static int cp500_register_i2c(struct cp500 *cp500)
{
- int retval;
+ int ret;
cp500->i2c = kzalloc(sizeof(*cp500->i2c), GFP_KERNEL);
if (!cp500->i2c)
@@ -251,30 +354,412 @@ static int cp500_register_i2c(struct cp500 *cp500)
cp500->i2c->info_size = ARRAY_SIZE(cp500_i2c_info);
cp500->i2c->info = cp500_i2c_info;
- retval = auxiliary_device_init(&cp500->i2c->auxdev);
- if (retval) {
+ ret = auxiliary_device_init(&cp500->i2c->auxdev);
+ if (ret) {
kfree(cp500->i2c);
cp500->i2c = NULL;
- return retval;
+ return ret;
}
- retval = __auxiliary_device_add(&cp500->i2c->auxdev, "keba");
- if (retval) {
+ ret = __auxiliary_device_add(&cp500->i2c->auxdev, "keba");
+ if (ret) {
auxiliary_device_uninit(&cp500->i2c->auxdev);
cp500->i2c = NULL;
- return retval;
+ return ret;
+ }
+
+ return 0;
+}
+
+static void cp500_spi_release(struct device *dev)
+{
+ struct keba_spi_auxdev *spi =
+ container_of(dev, struct keba_spi_auxdev, auxdev.dev);
+
+ kfree(spi);
+}
+
+static int cp500_register_spi(struct cp500 *cp500, u8 esc_type)
+{
+ int info_size;
+ int ret;
+
+ cp500->spi = kzalloc(sizeof(*cp500->spi), GFP_KERNEL);
+ if (!cp500->spi)
+ return -ENOMEM;
+
+ if (CP500_IS_CP035(cp500))
+ cp500_spi_info[0].platform_data = &cp500_w25q32;
+ if (esc_type == CP500_EEPROM_ESC_LAN9252)
+ info_size = ARRAY_SIZE(cp500_spi_info);
+ else
+ info_size = ARRAY_SIZE(cp500_spi_info) - 1;
+
+ cp500->spi->auxdev.name = "spi";
+ cp500->spi->auxdev.id = 0;
+ cp500->spi->auxdev.dev.release = cp500_spi_release;
+ cp500->spi->auxdev.dev.parent = &cp500->pci_dev->dev;
+ cp500->spi->io = (struct resource) {
+ /* SPI register area */
+ .start = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->spi.offset,
+ .end = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->spi.offset +
+ cp500->devs->spi.size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+ cp500->spi->info_size = info_size;
+ cp500->spi->info = cp500_spi_info;
+
+ ret = auxiliary_device_init(&cp500->spi->auxdev);
+ if (ret) {
+ kfree(cp500->spi);
+ cp500->spi = NULL;
+
+ return ret;
+ }
+ ret = __auxiliary_device_add(&cp500->spi->auxdev, "keba");
+ if (ret) {
+ auxiliary_device_uninit(&cp500->spi->auxdev);
+ cp500->spi = NULL;
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static void cp500_fan_release(struct device *dev)
+{
+ struct keba_fan_auxdev *fan =
+ container_of(dev, struct keba_fan_auxdev, auxdev.dev);
+
+ kfree(fan);
+}
+
+static int cp500_register_fan(struct cp500 *cp500)
+{
+ int ret;
+
+ cp500->fan = kzalloc(sizeof(*cp500->fan), GFP_KERNEL);
+ if (!cp500->fan)
+ return -ENOMEM;
+
+ cp500->fan->auxdev.name = "fan";
+ cp500->fan->auxdev.id = 0;
+ cp500->fan->auxdev.dev.release = cp500_fan_release;
+ cp500->fan->auxdev.dev.parent = &cp500->pci_dev->dev;
+ cp500->fan->io = (struct resource) {
+ /* fan register area */
+ .start = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->fan.offset,
+ .end = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->fan.offset +
+ cp500->devs->fan.size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+
+ ret = auxiliary_device_init(&cp500->fan->auxdev);
+ if (ret) {
+ kfree(cp500->fan);
+ cp500->fan = NULL;
+
+ return ret;
+ }
+ ret = __auxiliary_device_add(&cp500->fan->auxdev, "keba");
+ if (ret) {
+ auxiliary_device_uninit(&cp500->fan->auxdev);
+ cp500->fan = NULL;
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static void cp500_batt_release(struct device *dev)
+{
+ struct keba_batt_auxdev *fan =
+ container_of(dev, struct keba_batt_auxdev, auxdev.dev);
+
+ kfree(fan);
+}
+
+static int cp500_register_batt(struct cp500 *cp500)
+{
+ int ret;
+
+ cp500->batt = kzalloc(sizeof(*cp500->batt), GFP_KERNEL);
+ if (!cp500->batt)
+ return -ENOMEM;
+
+ cp500->batt->auxdev.name = "batt";
+ cp500->batt->auxdev.id = 0;
+ cp500->batt->auxdev.dev.release = cp500_batt_release;
+ cp500->batt->auxdev.dev.parent = &cp500->pci_dev->dev;
+ cp500->batt->io = (struct resource) {
+ /* battery register area */
+ .start = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->batt.offset,
+ .end = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->batt.offset +
+ cp500->devs->batt.size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+
+ ret = auxiliary_device_init(&cp500->batt->auxdev);
+ if (ret) {
+ kfree(cp500->batt);
+ cp500->batt = NULL;
+
+ return ret;
+ }
+ ret = __auxiliary_device_add(&cp500->batt->auxdev, "keba");
+ if (ret) {
+ auxiliary_device_uninit(&cp500->batt->auxdev);
+ cp500->batt = NULL;
+
+ return ret;
}
return 0;
}
+static void cp500_uart_release(struct device *dev)
+{
+ struct keba_uart_auxdev *uart =
+ container_of(dev, struct keba_uart_auxdev, auxdev.dev);
+
+ kfree(uart);
+}
+
+static int cp500_register_uart(struct cp500 *cp500,
+ struct keba_uart_auxdev **uart, const char *name,
+ struct cp500_dev_info *info, unsigned int irq)
+{
+ int ret;
+
+ *uart = kzalloc(sizeof(**uart), GFP_KERNEL);
+ if (!*uart)
+ return -ENOMEM;
+
+ (*uart)->auxdev.name = name;
+ (*uart)->auxdev.id = 0;
+ (*uart)->auxdev.dev.release = cp500_uart_release;
+ (*uart)->auxdev.dev.parent = &cp500->pci_dev->dev;
+ (*uart)->io = (struct resource) {
+ /* UART register area */
+ .start = (resource_size_t) cp500->sys_hwbase + info->offset,
+ .end = (resource_size_t) cp500->sys_hwbase + info->offset +
+ info->size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+ (*uart)->irq = irq;
+
+ ret = auxiliary_device_init(&(*uart)->auxdev);
+ if (ret) {
+ kfree(*uart);
+ *uart = NULL;
+
+ return ret;
+ }
+ ret = __auxiliary_device_add(&(*uart)->auxdev, "keba");
+ if (ret) {
+ auxiliary_device_uninit(&(*uart)->auxdev);
+ *uart = NULL;
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cp500_nvmem_read(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct cp500_nvmem *nvmem = priv;
+ int ret;
+
+ ret = nvmem_device_read(nvmem->nvmem, nvmem->offset + offset, bytes,
+ val);
+ if (ret != bytes)
+ return ret;
+
+ return 0;
+}
+
+static int cp500_nvmem_write(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct cp500_nvmem *nvmem = priv;
+ int ret;
+
+ ret = nvmem_device_write(nvmem->nvmem, nvmem->offset + offset, bytes,
+ val);
+ if (ret != bytes)
+ return ret;
+
+ return 0;
+}
+
+static int cp500_nvmem_register(struct cp500 *cp500, struct nvmem_device *nvmem)
+{
+ struct device *dev = &cp500->pci_dev->dev;
+ struct nvmem_config nvmem_config = {};
+ struct nvmem_device *tmp;
+
+ /*
+ * The main EEPROM of CP500 devices is logically split into two EEPROMs.
+ * The first logical EEPROM with 3 kB contains the type label which is
+ * programmed during production of the device. The second logical EEPROM
+ * with 1 kB is not programmed during production and can be used for
+ * arbitrary user data.
+ */
+
+ nvmem_config.dev = dev;
+ nvmem_config.owner = THIS_MODULE;
+ nvmem_config.id = NVMEM_DEVID_NONE;
+ nvmem_config.type = NVMEM_TYPE_EEPROM;
+ nvmem_config.root_only = true;
+ nvmem_config.reg_read = cp500_nvmem_read;
+ nvmem_config.reg_write = cp500_nvmem_write;
+
+ cp500->nvmem_cpu.nvmem = nvmem;
+ cp500->nvmem_cpu.offset = CP500_EEPROM_CPU_OFFSET;
+ nvmem_config.name = CP500_EEPROM_CPU_NAME;
+ nvmem_config.size = CP500_EEPROM_CPU_SIZE;
+ nvmem_config.priv = &cp500->nvmem_cpu;
+ tmp = devm_nvmem_register(dev, &nvmem_config);
+ if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+
+ cp500->nvmem_user.nvmem = nvmem;
+ cp500->nvmem_user.offset = CP500_EEPROM_USER_OFFSET;
+ nvmem_config.name = CP500_EEPROM_USER_NAME;
+ nvmem_config.size = CP500_EEPROM_USER_SIZE;
+ nvmem_config.priv = &cp500->nvmem_user;
+ tmp = devm_nvmem_register(dev, &nvmem_config);
+ if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+
+ return 0;
+}
+
+static int cp500_nvmem_match(struct device *dev, const void *data)
+{
+ const struct cp500 *cp500 = data;
+ struct i2c_client *client;
+
+ /* match only CPU EEPROM below the cp500 device */
+ dev = dev->parent;
+ client = i2c_verify_client(dev);
+ if (!client || client->addr != CP500_EEPROM_ADDR)
+ return 0;
+ while ((dev = dev->parent))
+ if (dev == &cp500->pci_dev->dev)
+ return 1;
+
+ return 0;
+}
+
+static void cp500_devm_nvmem_put(void *data)
+{
+ struct nvmem_device *nvmem = data;
+
+ nvmem_device_put(nvmem);
+}
+
+static int cp500_nvmem(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct nvmem_device *nvmem;
+ struct cp500 *cp500;
+ struct device *dev;
+ int notified;
+ u8 esc_type;
+ int ret;
+
+ if (action != NVMEM_ADD)
+ return NOTIFY_DONE;
+ cp500 = container_of(nb, struct cp500, nvmem_notifier);
+ dev = &cp500->pci_dev->dev;
+
+ /* process CPU EEPROM content only once */
+ notified = atomic_read(&cp500->nvmem_notified);
+ if (notified)
+ return NOTIFY_DONE;
+ nvmem = nvmem_device_find(cp500, cp500_nvmem_match);
+ if (IS_ERR_OR_NULL(nvmem))
+ return NOTIFY_DONE;
+ if (!atomic_try_cmpxchg_relaxed(&cp500->nvmem_notified, &notified, 1)) {
+ nvmem_device_put(nvmem);
+
+ return NOTIFY_DONE;
+ }
+
+ ret = devm_add_action_or_reset(dev, cp500_devm_nvmem_put, nvmem);
+ if (ret)
+ return ret;
+
+ ret = cp500_nvmem_register(cp500, nvmem);
+ if (ret)
+ return ret;
+
+ ret = nvmem_device_read(nvmem, CP500_EEPROM_DA_OFFSET, sizeof(esc_type),
+ (void *)&esc_type);
+ if (ret != sizeof(esc_type)) {
+ dev_warn(dev, "Failed to read device assembly!\n");
+
+ return NOTIFY_DONE;
+ }
+ esc_type &= CP500_EEPROM_DA_ESC_TYPE_MASK;
+
+ if (cp500_register_spi(cp500, esc_type))
+ dev_warn(dev, "Failed to register SPI!\n");
+
+ return NOTIFY_OK;
+}
+
static void cp500_register_auxiliary_devs(struct cp500 *cp500)
{
struct device *dev = &cp500->pci_dev->dev;
+ u8 present = ioread8(cp500->system_startup_addr + CP500_PRESENT_REG);
if (cp500_register_i2c(cp500))
- dev_warn(dev, "Failed to register i2c!\n");
+ dev_warn(dev, "Failed to register I2C!\n");
+ if (present & CP500_PRESENT_FAN0)
+ if (cp500_register_fan(cp500))
+ dev_warn(dev, "Failed to register fan!\n");
+ if (cp500_register_batt(cp500))
+ dev_warn(dev, "Failed to register battery!\n");
+ if (cp500->devs->uart0_rfb.size &&
+ cp500->devs->uart0_rfb.msix < cp500->msix_num) {
+ int irq = pci_irq_vector(cp500->pci_dev,
+ cp500->devs->uart0_rfb.msix);
+
+ if (cp500_register_uart(cp500, &cp500->uart0_rfb, "rs485-uart",
+ &cp500->devs->uart0_rfb, irq))
+ dev_warn(dev, "Failed to register RFB UART!\n");
+ }
+ if (cp500->devs->uart1_dbg.size &&
+ cp500->devs->uart1_dbg.msix < cp500->msix_num) {
+ int irq = pci_irq_vector(cp500->pci_dev,
+ cp500->devs->uart1_dbg.msix);
+
+ if (cp500_register_uart(cp500, &cp500->uart1_dbg, "rs232-uart",
+ &cp500->devs->uart1_dbg, irq))
+ dev_warn(dev, "Failed to register debug UART!\n");
+ }
+ if (cp500->devs->uart2_si1.size &&
+ cp500->devs->uart2_si1.msix < cp500->msix_num) {
+ int irq = pci_irq_vector(cp500->pci_dev,
+ cp500->devs->uart2_si1.msix);
+
+ if (cp500_register_uart(cp500, &cp500->uart2_si1, "uart",
+ &cp500->devs->uart2_si1, irq))
+ dev_warn(dev, "Failed to register SI1 UART!\n");
+ }
}
static void cp500_unregister_dev(struct auxiliary_device *auxdev)
@@ -285,11 +770,34 @@ static void cp500_unregister_dev(struct auxiliary_device *auxdev)
static void cp500_unregister_auxiliary_devs(struct cp500 *cp500)
{
-
+ if (cp500->spi) {
+ cp500_unregister_dev(&cp500->spi->auxdev);
+ cp500->spi = NULL;
+ }
if (cp500->i2c) {
cp500_unregister_dev(&cp500->i2c->auxdev);
cp500->i2c = NULL;
}
+ if (cp500->fan) {
+ cp500_unregister_dev(&cp500->fan->auxdev);
+ cp500->fan = NULL;
+ }
+ if (cp500->batt) {
+ cp500_unregister_dev(&cp500->batt->auxdev);
+ cp500->batt = NULL;
+ }
+ if (cp500->uart0_rfb) {
+ cp500_unregister_dev(&cp500->uart0_rfb->auxdev);
+ cp500->uart0_rfb = NULL;
+ }
+ if (cp500->uart1_dbg) {
+ cp500_unregister_dev(&cp500->uart1_dbg->auxdev);
+ cp500->uart1_dbg = NULL;
+ }
+ if (cp500->uart2_si1) {
+ cp500_unregister_dev(&cp500->uart2_si1->auxdev);
+ cp500->uart2_si1 = NULL;
+ }
}
static irqreturn_t cp500_axi_handler(int irq, void *dev)
@@ -396,15 +904,21 @@ static int cp500_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
pci_set_drvdata(pci_dev, cp500);
+ cp500->nvmem_notifier.notifier_call = cp500_nvmem;
+ ret = nvmem_register_notifier(&cp500->nvmem_notifier);
+ if (ret != 0)
+ goto out_free_irq;
ret = cp500_enable(cp500);
if (ret != 0)
- goto out_free_irq;
+ goto out_unregister_nvmem;
cp500_register_auxiliary_devs(cp500);
return 0;
+out_unregister_nvmem:
+ nvmem_unregister_notifier(&cp500->nvmem_notifier);
out_free_irq:
pci_free_irq_vectors(pci_dev);
out_disable:
@@ -422,6 +936,8 @@ static void cp500_remove(struct pci_dev *pci_dev)
cp500_disable(cp500);
+ nvmem_unregister_notifier(&cp500->nvmem_notifier);
+
pci_set_drvdata(pci_dev, 0);
pci_free_irq_vectors(pci_dev);
diff --git a/drivers/misc/keba/lan9252.c b/drivers/misc/keba/lan9252.c
new file mode 100644
index 000000000000..fc54afd1d05b
--- /dev/null
+++ b/drivers/misc/keba/lan9252.c
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) KEBA Industrial Automation Gmbh 2024
+ *
+ * Driver for LAN9252 on KEBA CP500 devices
+ *
+ * This driver is used for updating the configuration of the LAN9252 controller
+ * on KEBA CP500 devices. The LAN9252 is connected over SPI, which is also named
+ * PDI.
+ */
+
+#include <linux/spi/spi.h>
+#include <linux/mii.h>
+
+/* SPI commands */
+#define LAN9252_SPI_READ 0x3
+#define LAN9252_SPI_WRITE 0x2
+
+struct lan9252_read_cmd {
+ u8 cmd;
+ u8 addr_0;
+ u8 addr_1;
+} __packed;
+
+struct lan9252_write_cmd {
+ u8 cmd;
+ u8 addr_0;
+ u8 addr_1;
+ u32 data;
+} __packed;
+
+/* byte test register */
+#define LAN9252_BYTE_TEST 0x64
+#define LAN9252_BYTE_TEST_VALUE 0x87654321
+
+/* hardware configuration register */
+#define LAN9252_HW_CFG 0x74
+#define LAN9252_HW_CFG_READY 0x08000000
+
+/* EtherCAT CSR interface data register */
+#define LAN9252_ECAT_CSR_DATA 0x300
+
+/* EtherCAT CSR interface command register */
+#define LAN9252_ECAT_CSR_CMD 0x304
+#define LAN9252_ECAT_CSR_BUSY 0x80000000
+#define LAN9252_ECAT_CSR_READ 0x40000000
+
+/* EtherCAT slave controller MII register */
+#define LAN9252_ESC_MII 0x510
+#define LAN9252_ESC_MII_BUSY 0x8000
+#define LAN9252_ESC_MII_CMD_ERR 0x4000
+#define LAN9252_ESC_MII_READ_ERR 0x2000
+#define LAN9252_ESC_MII_ERR_MASK (LAN9252_ESC_MII_CMD_ERR | \
+ LAN9252_ESC_MII_READ_ERR)
+#define LAN9252_ESC_MII_WRITE 0x0200
+#define LAN9252_ESC_MII_READ 0x0100
+
+/* EtherCAT slave controller PHY address register */
+#define LAN9252_ESC_PHY_ADDR 0x512
+
+/* EtherCAT slave controller PHY register address register */
+#define LAN9252_ESC_PHY_REG_ADDR 0x513
+
+/* EtherCAT slave controller PHY data register */
+#define LAN9252_ESC_PHY_DATA 0x514
+
+/* EtherCAT slave controller PDI access state register */
+#define LAN9252_ESC_MII_PDI 0x517
+#define LAN9252_ESC_MII_ACCESS_PDI 0x01
+#define LAN9252_ESC_MII_ACCESS_ECAT 0x00
+
+/* PHY address */
+#define PHY_ADDRESS 2
+
+#define SPI_RETRY_COUNT 10
+#define SPI_WAIT_US 100
+#define SPI_CSR_WAIT_US 500
+
+static int lan9252_spi_read(struct spi_device *spi, u16 addr, u32 *data)
+{
+ struct lan9252_read_cmd cmd;
+
+ cmd.cmd = LAN9252_SPI_READ;
+ cmd.addr_0 = (addr >> 8) & 0xFF;
+ cmd.addr_1 = addr & 0xFF;
+
+ return spi_write_then_read(spi, (u8 *)&cmd,
+ sizeof(struct lan9252_read_cmd),
+ (u8 *)data, sizeof(u32));
+}
+
+static int lan9252_spi_write(struct spi_device *spi, u16 addr, u32 data)
+{
+ struct lan9252_write_cmd cmd;
+
+ cmd.cmd = LAN9252_SPI_WRITE;
+ cmd.addr_0 = (addr >> 8) & 0xFF;
+ cmd.addr_1 = addr & 0xFF;
+ cmd.data = data;
+
+ return spi_write(spi, (u8 *)&cmd, sizeof(struct lan9252_write_cmd));
+}
+
+static bool lan9252_init(struct spi_device *spi)
+{
+ u32 data;
+ int ret;
+
+ ret = lan9252_spi_read(spi, LAN9252_BYTE_TEST, &data);
+ if (ret || data != LAN9252_BYTE_TEST_VALUE)
+ return false;
+
+ ret = lan9252_spi_read(spi, LAN9252_HW_CFG, &data);
+ if (ret || !(data & LAN9252_HW_CFG_READY))
+ return false;
+
+ return true;
+}
+
+static u8 lan9252_esc_get_size(u16 addr)
+{
+ if (addr == LAN9252_ESC_MII || addr == LAN9252_ESC_PHY_DATA)
+ return 2;
+
+ return 1;
+}
+
+static int lan9252_esc_wait(struct spi_device *spi)
+{
+ ktime_t timeout = ktime_add_us(ktime_get(), SPI_WAIT_US);
+ u32 data;
+ int ret;
+
+ /* wait while CSR command is busy */
+ for (;;) {
+ ret = lan9252_spi_read(spi, LAN9252_ECAT_CSR_CMD, &data);
+ if (ret)
+ return ret;
+ if (!(data & LAN9252_ECAT_CSR_BUSY))
+ return 0;
+
+ if (ktime_compare(ktime_get(), timeout) > 0) {
+ ret = lan9252_spi_read(spi, LAN9252_ECAT_CSR_CMD, &data);
+ if (ret)
+ return ret;
+ break;
+ }
+ }
+
+ return (!(data & LAN9252_ECAT_CSR_BUSY)) ? 0 : -ETIMEDOUT;
+}
+
+static int lan9252_esc_read(struct spi_device *spi, u16 addr, u32 *data)
+{
+ u32 csr_cmd;
+ u8 size;
+ int ret;
+
+ size = lan9252_esc_get_size(addr);
+ csr_cmd = LAN9252_ECAT_CSR_BUSY | LAN9252_ECAT_CSR_READ;
+ csr_cmd |= (size << 16) | addr;
+ ret = lan9252_spi_write(spi, LAN9252_ECAT_CSR_CMD, csr_cmd);
+ if (ret)
+ return ret;
+
+ ret = lan9252_esc_wait(spi);
+ if (ret)
+ return ret;
+
+ ret = lan9252_spi_read(spi, LAN9252_ECAT_CSR_DATA, data);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int lan9252_esc_write(struct spi_device *spi, u16 addr, u32 data)
+{
+ u32 csr_cmd;
+ u8 size;
+ int ret;
+
+ ret = lan9252_spi_write(spi, LAN9252_ECAT_CSR_DATA, data);
+ if (ret)
+ return ret;
+
+ size = lan9252_esc_get_size(addr);
+ csr_cmd = LAN9252_ECAT_CSR_BUSY;
+ csr_cmd |= (size << 16) | addr;
+ ret = lan9252_spi_write(spi, LAN9252_ECAT_CSR_CMD, csr_cmd);
+ if (ret)
+ return ret;
+
+ ret = lan9252_esc_wait(spi);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int lan9252_access_mii(struct spi_device *spi, bool access)
+{
+ u32 data;
+
+ if (access)
+ data = LAN9252_ESC_MII_ACCESS_PDI;
+ else
+ data = LAN9252_ESC_MII_ACCESS_ECAT;
+
+ return lan9252_esc_write(spi, LAN9252_ESC_MII_PDI, data);
+}
+
+static int lan9252_mii_wait(struct spi_device *spi)
+{
+ ktime_t timeout = ktime_add_us(ktime_get(), SPI_CSR_WAIT_US);
+ u32 data;
+ int ret;
+
+ /* wait while MII control state machine is busy */
+ for (;;) {
+ ret = lan9252_esc_read(spi, LAN9252_ESC_MII, &data);
+ if (ret)
+ return ret;
+ if (data & LAN9252_ESC_MII_ERR_MASK)
+ return -EIO;
+ if (!(data & LAN9252_ESC_MII_BUSY))
+ return 0;
+
+ if (ktime_compare(ktime_get(), timeout) > 0) {
+ ret = lan9252_esc_read(spi, LAN9252_ESC_MII, &data);
+ if (ret)
+ return ret;
+ if (data & LAN9252_ESC_MII_ERR_MASK)
+ return -EIO;
+ break;
+ }
+ }
+
+ return (!(data & LAN9252_ESC_MII_BUSY)) ? 0 : -ETIMEDOUT;
+}
+
+static int lan9252_mii_read(struct spi_device *spi, u8 phy_addr, u8 reg_addr,
+ u32 *data)
+{
+ int ret;
+
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_ADDR, phy_addr);
+ if (ret)
+ return ret;
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_REG_ADDR, reg_addr);
+ if (ret)
+ return ret;
+
+ ret = lan9252_esc_write(spi, LAN9252_ESC_MII, LAN9252_ESC_MII_READ);
+ if (ret)
+ return ret;
+
+ ret = lan9252_mii_wait(spi);
+ if (ret)
+ return ret;
+
+ return lan9252_esc_read(spi, LAN9252_ESC_PHY_DATA, data);
+}
+
+static int lan9252_mii_write(struct spi_device *spi, u8 phy_addr, u8 reg_addr,
+ u32 data)
+{
+ int ret;
+
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_ADDR, phy_addr);
+ if (ret)
+ return ret;
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_REG_ADDR, reg_addr);
+ if (ret)
+ return ret;
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_DATA, data);
+ if (ret)
+ return ret;
+
+ ret = lan9252_esc_write(spi, LAN9252_ESC_MII, LAN9252_ESC_MII_WRITE);
+ if (ret)
+ return ret;
+
+ return lan9252_mii_wait(spi);
+}
+
+static int lan9252_probe(struct spi_device *spi)
+{
+ u32 data;
+ int retry = SPI_RETRY_COUNT;
+ int ret;
+
+ /* execute specified initialization sequence */
+ while (retry && !lan9252_init(spi))
+ retry--;
+ if (retry == 0) {
+ dev_err(&spi->dev,
+ "Can't initialize LAN9252 SPI communication!");
+ return -EIO;
+ }
+
+ /* enable access to MII management for PDI */
+ ret = lan9252_access_mii(spi, true);
+ if (ret) {
+ dev_err(&spi->dev, "Can't enable access to MII management!");
+ return ret;
+ }
+
+ /*
+ * check PHY configuration and configure if necessary
+ * - full duplex
+ * - auto negotiation disabled
+ * - 100 Mbps
+ */
+ ret = lan9252_mii_read(spi, PHY_ADDRESS, MII_BMCR, &data);
+ if (ret) {
+ dev_err(&spi->dev, "Can't read LAN9252 configuration!");
+ goto out;
+ }
+ if (!(data & BMCR_FULLDPLX) || (data & BMCR_ANENABLE) ||
+ !(data & BMCR_SPEED100)) {
+ /*
+ */
+ data &= ~(BMCR_ANENABLE);
+ data |= (BMCR_FULLDPLX | BMCR_SPEED100);
+ ret = lan9252_mii_write(spi, PHY_ADDRESS, MII_BMCR, data);
+ if (ret)
+ dev_err(&spi->dev,
+ "Can't write LAN9252 configuration!");
+ }
+
+ dev_info(&spi->dev, "LAN9252 PHY configuration");
+
+out:
+ /* disable access to MII management for PDI */
+ lan9252_access_mii(spi, false);
+
+ return ret;
+}
+
+static const struct spi_device_id lan9252_id[] = {
+ {"lan9252"},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, lan9252_id);
+
+static struct spi_driver lan9252_driver = {
+ .driver = {
+ .name = "lan9252",
+ },
+ .probe = lan9252_probe,
+ .id_table = lan9252_id,
+};
+module_spi_driver(lan9252_driver);
+
+MODULE_AUTHOR("Petar Bojanic <boja@keba.com>");
+MODULE_AUTHOR("Gerhard Engleder <eg@keba.com>");
+MODULE_DESCRIPTION("KEBA LAN9252 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 5576146ab13b..718ec5d81d94 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -145,8 +145,8 @@ out:
* @cl: host client
* @buf: buffer to receive
* @length: buffer length
- * @mode: io mode
* @vtag: virtual tag
+ * @mode: io mode
* @timeout: recv timeout, 0 for infinite timeout
*
* Return: read size in bytes of < 0 on error
diff --git a/drivers/misc/mei/platform-vsc.c b/drivers/misc/mei/platform-vsc.c
index 20a11b299bcd..71f9994da2cc 100644
--- a/drivers/misc/mei/platform-vsc.c
+++ b/drivers/misc/mei/platform-vsc.c
@@ -256,8 +256,6 @@ static int mei_vsc_hw_reset(struct mei_device *mei_dev, bool intr_enable)
vsc_tp_reset(hw->tp);
- vsc_tp_intr_disable(hw->tp);
-
return vsc_tp_init(hw->tp, mei_dev->dev);
}
diff --git a/drivers/misc/mei/vsc-fw-loader.c b/drivers/misc/mei/vsc-fw-loader.c
index 9f129bc641f6..308b090d81bb 100644
--- a/drivers/misc/mei/vsc-fw-loader.c
+++ b/drivers/misc/mei/vsc-fw-loader.c
@@ -317,28 +317,34 @@ static int vsc_identify_silicon(struct vsc_fw_loader *fw_loader)
cmd->data.dump_mem.addr = cpu_to_le32(VSC_EFUSE_ADDR);
cmd->data.dump_mem.len = cpu_to_le16(sizeof(__le32));
ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE);
- if (ret)
- return ret;
- if (ack->token == VSC_TOKEN_ERROR)
- return -EINVAL;
+ if (ret || ack->token == VSC_TOKEN_ERROR) {
+ dev_err(fw_loader->dev, "CMD_DUMP_MEM error %d token %d\n", ret, ack->token);
+ return ret ?: -EINVAL;
+ }
cmd->magic = cpu_to_le32(VSC_MAGIC_NUM);
cmd->cmd_id = VSC_CMD_GET_CONT;
ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE);
- if (ret)
- return ret;
- if (ack->token != VSC_TOKEN_DUMP_RESP)
- return -EINVAL;
+ if (ret || ack->token != VSC_TOKEN_DUMP_RESP) {
+ dev_err(fw_loader->dev, "CMD_GETCONT error %d token %d\n", ret, ack->token);
+ return ret ?: -EINVAL;
+ }
version = FIELD_GET(VSC_MAINSTEPPING_VERSION_MASK, ack->payload[0]);
sub_version = FIELD_GET(VSC_SUBSTEPPING_VERSION_MASK, ack->payload[0]);
- if (version != VSC_MAINSTEPPING_VERSION_A)
+ if (version != VSC_MAINSTEPPING_VERSION_A) {
+ dev_err(fw_loader->dev, "mainstepping mismatch expected %d got %d\n",
+ VSC_MAINSTEPPING_VERSION_A, version);
return -EINVAL;
+ }
if (sub_version != VSC_SUBSTEPPING_VERSION_0 &&
- sub_version != VSC_SUBSTEPPING_VERSION_1)
+ sub_version != VSC_SUBSTEPPING_VERSION_1) {
+ dev_err(fw_loader->dev, "substepping %d is out of supported range %d - %d\n",
+ sub_version, VSC_SUBSTEPPING_VERSION_0, VSC_SUBSTEPPING_VERSION_1);
return -EINVAL;
+ }
dev_info(fw_loader->dev, "silicon stepping version is %u:%u\n",
version, sub_version);
diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c
index 1618cca9a731..107177b05dcd 100644
--- a/drivers/misc/mei/vsc-tp.c
+++ b/drivers/misc/mei/vsc-tp.c
@@ -364,8 +364,6 @@ void vsc_tp_reset(struct vsc_tp *tp)
gpiod_set_value_cansleep(tp->wakeupfw, 1);
atomic_set(&tp->assert_cnt, 0);
-
- enable_irq(tp->spi->irq);
}
EXPORT_SYMBOL_NS_GPL(vsc_tp_reset, VSC_TP);
diff --git a/drivers/misc/ocxl/sysfs.c b/drivers/misc/ocxl/sysfs.c
index 405180d47d9b..07520d6e6dc5 100644
--- a/drivers/misc/ocxl/sysfs.c
+++ b/drivers/misc/ocxl/sysfs.c
@@ -125,7 +125,7 @@ static const struct vm_operations_struct global_mmio_vmops = {
};
static int global_mmio_mmap(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
+ const struct bin_attribute *bin_attr,
struct vm_area_struct *vma)
{
struct ocxl_afu *afu = to_afu(kobj_to_dev(kobj));
diff --git a/drivers/misc/rpmb-core.c b/drivers/misc/rpmb-core.c
index bc68cde1a8bf..2d653926cdbb 100644
--- a/drivers/misc/rpmb-core.c
+++ b/drivers/misc/rpmb-core.c
@@ -13,7 +13,6 @@
#include <linux/slab.h>
static DEFINE_IDA(rpmb_ida);
-static DEFINE_MUTEX(rpmb_mutex);
/**
* rpmb_dev_get() - increase rpmb device ref counter
@@ -63,9 +62,7 @@ static void rpmb_dev_release(struct device *dev)
{
struct rpmb_dev *rdev = to_rpmb_dev(dev);
- mutex_lock(&rpmb_mutex);
- ida_simple_remove(&rpmb_ida, rdev->id);
- mutex_unlock(&rpmb_mutex);
+ ida_free(&rpmb_ida, rdev->id);
kfree(rdev->descr.dev_id);
kfree(rdev);
}
@@ -175,9 +172,7 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev,
goto err_free_rdev;
}
- mutex_lock(&rpmb_mutex);
- ret = ida_simple_get(&rpmb_ida, 0, 0, GFP_KERNEL);
- mutex_unlock(&rpmb_mutex);
+ ret = ida_alloc(&rpmb_ida, GFP_KERNEL);
if (ret < 0)
goto err_free_dev_id;
rdev->id = ret;
diff --git a/drivers/misc/ti-st/Kconfig b/drivers/misc/ti-st/Kconfig
deleted file mode 100644
index 1503a6496f63..000000000000
--- a/drivers/misc/ti-st/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# TI's shared transport line discipline and the protocol
-# drivers (BT, FM and GPS)
-#
-menu "Texas Instruments shared transport line discipline"
-config TI_ST
- tristate "Shared transport core driver"
- depends on NET && TTY
- depends on GPIOLIB || COMPILE_TEST
- select FW_LOADER
- help
- This enables the shared transport core driver for TI
- BT / FM and GPS combo chips. This enables protocol drivers
- to register themselves with core and send data, the responses
- are returned to relevant protocol drivers based on their
- packet types.
-
-endmenu
diff --git a/drivers/misc/ti-st/Makefile b/drivers/misc/ti-st/Makefile
deleted file mode 100644
index 93393100952e..000000000000
--- a/drivers/misc/ti-st/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for TI's shared transport line discipline
-# and its protocol drivers (BT, FM, GPS)
-#
-obj-$(CONFIG_TI_ST) += st_drv.o
-st_drv-objs := st_core.o st_kim.o st_ll.o
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
deleted file mode 100644
index b878431553ab..000000000000
--- a/drivers/misc/ti-st/st_core.c
+++ /dev/null
@@ -1,918 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Shared Transport Line discipline driver Core
- * This hooks up ST KIM driver and ST LL driver
- * Copyright (C) 2009-2010 Texas Instruments
- * Author: Pavan Savoy <pavan_savoy@ti.com>
- */
-
-#define pr_fmt(fmt) "(stc): " fmt
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-
-#include <linux/seq_file.h>
-#include <linux/skbuff.h>
-
-#include <linux/ti_wilink_st.h>
-#include <linux/netdevice.h>
-
-/*
- * function pointer pointing to either,
- * st_kim_recv during registration to receive fw download responses
- * st_int_recv after registration to receive proto stack responses
- */
-static void (*st_recv)(void *disc_data, const u8 *ptr, size_t count);
-
-/********************************************************************/
-static void add_channel_to_table(struct st_data_s *st_gdata,
- struct st_proto_s *new_proto)
-{
- pr_info("%s: id %d\n", __func__, new_proto->chnl_id);
- /* list now has the channel id as index itself */
- st_gdata->list[new_proto->chnl_id] = new_proto;
- st_gdata->is_registered[new_proto->chnl_id] = true;
-}
-
-static void remove_channel_from_table(struct st_data_s *st_gdata,
- struct st_proto_s *proto)
-{
- pr_info("%s: id %d\n", __func__, proto->chnl_id);
-/* st_gdata->list[proto->chnl_id] = NULL; */
- st_gdata->is_registered[proto->chnl_id] = false;
-}
-
-/*
- * called from KIM during firmware download.
- *
- * This is a wrapper function to tty->ops->write_room.
- * It returns number of free space available in
- * uart tx buffer.
- */
-int st_get_uart_wr_room(struct st_data_s *st_gdata)
-{
- if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
- pr_err("tty unavailable to perform write");
- return -1;
- }
-
- return tty_write_room(st_gdata->tty);
-}
-
-/*
- * can be called in from
- * -- KIM (during fw download)
- * -- ST Core (during st_write)
- *
- * This is the internal write function - a wrapper
- * to tty->ops->write
- */
-int st_int_write(struct st_data_s *st_gdata,
- const unsigned char *data, int count)
-{
- struct tty_struct *tty;
- if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
- pr_err("tty unavailable to perform write");
- return -EINVAL;
- }
- tty = st_gdata->tty;
-#ifdef VERBOSE
- print_hex_dump(KERN_DEBUG, "<out<", DUMP_PREFIX_NONE,
- 16, 1, data, count, 0);
-#endif
- return tty->ops->write(tty, data, count);
-
-}
-
-/*
- * push the skb received to relevant
- * protocol stacks
- */
-static void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
-{
- pr_debug(" %s(prot:%d) ", __func__, chnl_id);
-
- if (unlikely
- (st_gdata == NULL || st_gdata->rx_skb == NULL
- || st_gdata->is_registered[chnl_id] == false)) {
- pr_err("chnl_id %d not registered, no data to send?",
- chnl_id);
- kfree_skb(st_gdata->rx_skb);
- return;
- }
- /*
- * this cannot fail
- * this shouldn't take long
- * - should be just skb_queue_tail for the
- * protocol stack driver
- */
- if (likely(st_gdata->list[chnl_id]->recv != NULL)) {
- if (unlikely
- (st_gdata->list[chnl_id]->recv
- (st_gdata->list[chnl_id]->priv_data, st_gdata->rx_skb)
- != 0)) {
- pr_err(" proto stack %d's ->recv failed", chnl_id);
- kfree_skb(st_gdata->rx_skb);
- return;
- }
- } else {
- pr_err(" proto stack %d's ->recv null", chnl_id);
- kfree_skb(st_gdata->rx_skb);
- }
- return;
-}
-
-/*
- * st_reg_complete - to call registration complete callbacks
- * of all protocol stack drivers
- * This function is being called with spin lock held, protocol drivers are
- * only expected to complete their waits and do nothing more than that.
- */
-static void st_reg_complete(struct st_data_s *st_gdata, int err)
-{
- unsigned char i = 0;
- pr_info(" %s ", __func__);
- for (i = 0; i < ST_MAX_CHANNELS; i++) {
- if (likely(st_gdata != NULL &&
- st_gdata->is_registered[i] == true &&
- st_gdata->list[i]->reg_complete_cb != NULL)) {
- st_gdata->list[i]->reg_complete_cb
- (st_gdata->list[i]->priv_data, err);
- pr_info("protocol %d's cb sent %d\n", i, err);
- if (err) { /* cleanup registered protocol */
- st_gdata->is_registered[i] = false;
- if (st_gdata->protos_registered)
- st_gdata->protos_registered--;
- }
- }
- }
-}
-
-static inline int st_check_data_len(struct st_data_s *st_gdata,
- unsigned char chnl_id, int len)
-{
- int room = skb_tailroom(st_gdata->rx_skb);
-
- pr_debug("len %d room %d", len, room);
-
- if (!len) {
- /*
- * Received packet has only packet header and
- * has zero length payload. So, ask ST CORE to
- * forward the packet to protocol driver (BT/FM/GPS)
- */
- st_send_frame(chnl_id, st_gdata);
-
- } else if (len > room) {
- /*
- * Received packet's payload length is larger.
- * We can't accommodate it in created skb.
- */
- pr_err("Data length is too large len %d room %d", len,
- room);
- kfree_skb(st_gdata->rx_skb);
- } else {
- /*
- * Packet header has non-zero payload length and
- * we have enough space in created skb. Lets read
- * payload data */
- st_gdata->rx_state = ST_W4_DATA;
- st_gdata->rx_count = len;
- return len;
- }
-
- /* Change ST state to continue to process next packet */
- st_gdata->rx_state = ST_W4_PACKET_TYPE;
- st_gdata->rx_skb = NULL;
- st_gdata->rx_count = 0;
- st_gdata->rx_chnl = 0;
-
- return 0;
-}
-
-/*
- * st_wakeup_ack - internal function for action when wake-up ack
- * received
- */
-static inline void st_wakeup_ack(struct st_data_s *st_gdata,
- unsigned char cmd)
-{
- struct sk_buff *waiting_skb;
- unsigned long flags = 0;
-
- spin_lock_irqsave(&st_gdata->lock, flags);
- /*
- * de-Q from waitQ and Q in txQ now that the
- * chip is awake
- */
- while ((waiting_skb = skb_dequeue(&st_gdata->tx_waitq)))
- skb_queue_tail(&st_gdata->txq, waiting_skb);
-
- /* state forwarded to ST LL */
- st_ll_sleep_state(st_gdata, (unsigned long)cmd);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
-
- /* wake up to send the recently copied skbs from waitQ */
- st_tx_wakeup(st_gdata);
-}
-
-/*
- * st_int_recv - ST's internal receive function.
- * Decodes received RAW data and forwards to corresponding
- * client drivers (Bluetooth,FM,GPS..etc).
- * This can receive various types of packets,
- * HCI-Events, ACL, SCO, 4 types of HCI-LL PM packets
- * CH-8 packets from FM, CH-9 packets from GPS cores.
- */
-static void st_int_recv(void *disc_data, const u8 *ptr, size_t count)
-{
- struct st_proto_s *proto;
- unsigned short payload_len = 0;
- int len = 0;
- unsigned char type = 0;
- unsigned char *plen;
- struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
- unsigned long flags;
-
- if (st_gdata == NULL) {
- pr_err(" received null from TTY ");
- return;
- }
-
- pr_debug("count %zu rx_state %ld"
- "rx_count %ld", count, st_gdata->rx_state,
- st_gdata->rx_count);
-
- spin_lock_irqsave(&st_gdata->lock, flags);
- /* Decode received bytes here */
- while (count) {
- if (st_gdata->rx_count) {
- len = min_t(unsigned int, st_gdata->rx_count, count);
- skb_put_data(st_gdata->rx_skb, ptr, len);
- st_gdata->rx_count -= len;
- count -= len;
- ptr += len;
-
- if (st_gdata->rx_count)
- continue;
-
- /* Check ST RX state machine , where are we? */
- switch (st_gdata->rx_state) {
- /* Waiting for complete packet ? */
- case ST_W4_DATA:
- pr_debug("Complete pkt received");
- /*
- * Ask ST CORE to forward
- * the packet to protocol driver
- */
- st_send_frame(st_gdata->rx_chnl, st_gdata);
-
- st_gdata->rx_state = ST_W4_PACKET_TYPE;
- st_gdata->rx_skb = NULL;
- continue;
- /* parse the header to know details */
- case ST_W4_HEADER:
- proto = st_gdata->list[st_gdata->rx_chnl];
- plen =
- &st_gdata->rx_skb->data
- [proto->offset_len_in_hdr];
- pr_debug("plen pointing to %x\n", *plen);
- if (proto->len_size == 1) /* 1 byte len field */
- payload_len = *(unsigned char *)plen;
- else if (proto->len_size == 2)
- payload_len =
- __le16_to_cpu(*(unsigned short *)plen);
- else
- pr_info("%s: invalid length "
- "for id %d\n",
- __func__, proto->chnl_id);
- st_check_data_len(st_gdata, proto->chnl_id,
- payload_len);
- pr_debug("off %d, pay len %d\n",
- proto->offset_len_in_hdr, payload_len);
- continue;
- } /* end of switch rx_state */
- }
-
- /* end of if rx_count */
-
- /*
- * Check first byte of packet and identify module
- * owner (BT/FM/GPS)
- */
- switch (*ptr) {
- case LL_SLEEP_IND:
- case LL_SLEEP_ACK:
- case LL_WAKE_UP_IND:
- pr_debug("PM packet");
- /*
- * this takes appropriate action based on
- * sleep state received --
- */
- st_ll_sleep_state(st_gdata, *ptr);
- /*
- * if WAKEUP_IND collides copy from waitq to txq
- * and assume chip awake
- */
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- if (st_ll_getstate(st_gdata) == ST_LL_AWAKE)
- st_wakeup_ack(st_gdata, LL_WAKE_UP_ACK);
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- ptr++;
- count--;
- continue;
- case LL_WAKE_UP_ACK:
- pr_debug("PM packet");
-
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- /* wake up ack received */
- st_wakeup_ack(st_gdata, *ptr);
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- ptr++;
- count--;
- continue;
- /* Unknown packet? */
- default:
- type = *ptr;
-
- /*
- * Default case means non-HCILL packets,
- * possibilities are packets for:
- * (a) valid protocol - Supported Protocols within
- * the ST_MAX_CHANNELS.
- * (b) registered protocol - Checked by
- * "st_gdata->list[type] == NULL)" are supported
- * protocols only.
- * Rules out any invalid protocol and
- * unregistered protocols with channel ID < 16.
- */
-
- if ((type >= ST_MAX_CHANNELS) ||
- (st_gdata->list[type] == NULL)) {
- pr_err("chip/interface misbehavior: "
- "dropping frame starting "
- "with 0x%02x\n", type);
- goto done;
- }
-
- st_gdata->rx_skb = alloc_skb(
- st_gdata->list[type]->max_frame_size,
- GFP_ATOMIC);
- if (st_gdata->rx_skb == NULL) {
- pr_err("out of memory: dropping\n");
- goto done;
- }
-
- skb_reserve(st_gdata->rx_skb,
- st_gdata->list[type]->reserve);
- /* next 2 required for BT only */
- st_gdata->rx_skb->cb[0] = type; /*pkt_type*/
- st_gdata->rx_skb->cb[1] = 0; /*incoming*/
- st_gdata->rx_chnl = *ptr;
- st_gdata->rx_state = ST_W4_HEADER;
- st_gdata->rx_count = st_gdata->list[type]->hdr_len;
- pr_debug("rx_count %ld\n", st_gdata->rx_count);
- }
- ptr++;
- count--;
- }
-done:
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- pr_debug("done %s", __func__);
- return;
-}
-
-/*
- * st_int_dequeue - internal de-Q function.
- * If the previous data set was not written
- * completely, return that skb which has the pending data.
- * In normal cases, return top of txq.
- */
-static struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata)
-{
- struct sk_buff *returning_skb;
-
- pr_debug("%s", __func__);
- if (st_gdata->tx_skb != NULL) {
- returning_skb = st_gdata->tx_skb;
- st_gdata->tx_skb = NULL;
- return returning_skb;
- }
- return skb_dequeue(&st_gdata->txq);
-}
-
-/*
- * st_int_enqueue - internal Q-ing function.
- * Will either Q the skb to txq or the tx_waitq
- * depending on the ST LL state.
- * If the chip is asleep, then Q it onto waitq and
- * wakeup the chip.
- * txq and waitq needs protection since the other contexts
- * may be sending data, waking up chip.
- */
-static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
-{
- unsigned long flags = 0;
-
- pr_debug("%s", __func__);
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- switch (st_ll_getstate(st_gdata)) {
- case ST_LL_AWAKE:
- pr_debug("ST LL is AWAKE, sending normally");
- skb_queue_tail(&st_gdata->txq, skb);
- break;
- case ST_LL_ASLEEP_TO_AWAKE:
- skb_queue_tail(&st_gdata->tx_waitq, skb);
- break;
- case ST_LL_AWAKE_TO_ASLEEP:
- pr_err("ST LL is illegal state(%ld),"
- "purging received skb.", st_ll_getstate(st_gdata));
- dev_kfree_skb_irq(skb);
- break;
- case ST_LL_ASLEEP:
- skb_queue_tail(&st_gdata->tx_waitq, skb);
- st_ll_wakeup(st_gdata);
- break;
- default:
- pr_err("ST LL is illegal state(%ld),"
- "purging received skb.", st_ll_getstate(st_gdata));
- dev_kfree_skb_irq(skb);
- break;
- }
-
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- pr_debug("done %s", __func__);
- return;
-}
-
-/*
- * internal wakeup function
- * called from either
- * - TTY layer when write's finished
- * - st_write (in context of the protocol stack)
- */
-static void work_fn_write_wakeup(struct work_struct *work)
-{
- struct st_data_s *st_gdata = container_of(work, struct st_data_s,
- work_write_wakeup);
-
- st_tx_wakeup((void *)st_gdata);
-}
-void st_tx_wakeup(struct st_data_s *st_data)
-{
- struct sk_buff *skb;
- unsigned long flags; /* for irq save flags */
- pr_debug("%s", __func__);
- /* check for sending & set flag sending here */
- if (test_and_set_bit(ST_TX_SENDING, &st_data->tx_state)) {
- pr_debug("ST already sending");
- /* keep sending */
- set_bit(ST_TX_WAKEUP, &st_data->tx_state);
- return;
- /* TX_WAKEUP will be checked in another
- * context
- */
- }
- do { /* come back if st_tx_wakeup is set */
- /* woke-up to write */
- clear_bit(ST_TX_WAKEUP, &st_data->tx_state);
- while ((skb = st_int_dequeue(st_data))) {
- int len;
- spin_lock_irqsave(&st_data->lock, flags);
- /* enable wake-up from TTY */
- set_bit(TTY_DO_WRITE_WAKEUP, &st_data->tty->flags);
- len = st_int_write(st_data, skb->data, skb->len);
- skb_pull(skb, len);
- /* if skb->len = len as expected, skb->len=0 */
- if (skb->len) {
- /* would be the next skb to be sent */
- st_data->tx_skb = skb;
- spin_unlock_irqrestore(&st_data->lock, flags);
- break;
- }
- dev_kfree_skb_irq(skb);
- spin_unlock_irqrestore(&st_data->lock, flags);
- }
- /* if wake-up is set in another context- restart sending */
- } while (test_bit(ST_TX_WAKEUP, &st_data->tx_state));
-
- /* clear flag sending */
- clear_bit(ST_TX_SENDING, &st_data->tx_state);
-}
-
-/********************************************************************/
-/* functions called from ST KIM
-*/
-void kim_st_list_protocols(struct st_data_s *st_gdata, void *buf)
-{
- seq_printf(buf, "[%d]\nBT=%c\nFM=%c\nGPS=%c\n",
- st_gdata->protos_registered,
- st_gdata->is_registered[0x04] == true ? 'R' : 'U',
- st_gdata->is_registered[0x08] == true ? 'R' : 'U',
- st_gdata->is_registered[0x09] == true ? 'R' : 'U');
-}
-
-/********************************************************************/
-/*
- * functions called from protocol stack drivers
- * to be EXPORT-ed
- */
-long st_register(struct st_proto_s *new_proto)
-{
- struct st_data_s *st_gdata;
- long err = 0;
- unsigned long flags = 0;
-
- st_kim_ref(&st_gdata, 0);
- if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL
- || new_proto->reg_complete_cb == NULL) {
- pr_err("gdata/new_proto/recv or reg_complete_cb not ready");
- return -EINVAL;
- }
-
- if (new_proto->chnl_id >= ST_MAX_CHANNELS) {
- pr_err("chnl_id %d not supported", new_proto->chnl_id);
- return -EPROTONOSUPPORT;
- }
-
- if (st_gdata->is_registered[new_proto->chnl_id] == true) {
- pr_err("chnl_id %d already registered", new_proto->chnl_id);
- return -EALREADY;
- }
-
- /* can be from process context only */
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- if (test_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state)) {
- pr_info(" ST_REG_IN_PROGRESS:%d ", new_proto->chnl_id);
- /* fw download in progress */
-
- add_channel_to_table(st_gdata, new_proto);
- st_gdata->protos_registered++;
- new_proto->write = st_write;
-
- set_bit(ST_REG_PENDING, &st_gdata->st_state);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return -EINPROGRESS;
- } else if (st_gdata->protos_registered == ST_EMPTY) {
- pr_info(" chnl_id list empty :%d ", new_proto->chnl_id);
- set_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
- st_recv = st_kim_recv;
-
- /* enable the ST LL - to set default chip state */
- st_ll_enable(st_gdata);
-
- /* release lock previously held - re-locked below */
- spin_unlock_irqrestore(&st_gdata->lock, flags);
-
- /*
- * this may take a while to complete
- * since it involves BT fw download
- */
- err = st_kim_start(st_gdata->kim_data);
- if (err != 0) {
- clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
- if ((st_gdata->protos_registered != ST_EMPTY) &&
- (test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
- pr_err(" KIM failure complete callback ");
- spin_lock_irqsave(&st_gdata->lock, flags);
- st_reg_complete(st_gdata, err);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- clear_bit(ST_REG_PENDING, &st_gdata->st_state);
- }
- return -EINVAL;
- }
-
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
- st_recv = st_int_recv;
-
- /*
- * this is where all pending registration
- * are signalled to be complete by calling callback functions
- */
- if ((st_gdata->protos_registered != ST_EMPTY) &&
- (test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
- pr_debug(" call reg complete callback ");
- st_reg_complete(st_gdata, 0);
- }
- clear_bit(ST_REG_PENDING, &st_gdata->st_state);
-
- /*
- * check for already registered once more,
- * since the above check is old
- */
- if (st_gdata->is_registered[new_proto->chnl_id] == true) {
- pr_err(" proto %d already registered ",
- new_proto->chnl_id);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return -EALREADY;
- }
-
- add_channel_to_table(st_gdata, new_proto);
- st_gdata->protos_registered++;
- new_proto->write = st_write;
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return err;
- }
- /* if fw is already downloaded & new stack registers protocol */
- else {
- add_channel_to_table(st_gdata, new_proto);
- st_gdata->protos_registered++;
- new_proto->write = st_write;
-
- /* lock already held before entering else */
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return err;
- }
-}
-EXPORT_SYMBOL_GPL(st_register);
-
-/*
- * to unregister a protocol -
- * to be called from protocol stack driver
- */
-long st_unregister(struct st_proto_s *proto)
-{
- long err = 0;
- unsigned long flags = 0;
- struct st_data_s *st_gdata;
-
- pr_debug("%s: %d ", __func__, proto->chnl_id);
-
- st_kim_ref(&st_gdata, 0);
- if (!st_gdata || proto->chnl_id >= ST_MAX_CHANNELS) {
- pr_err(" chnl_id %d not supported", proto->chnl_id);
- return -EPROTONOSUPPORT;
- }
-
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- if (st_gdata->is_registered[proto->chnl_id] == false) {
- pr_err(" chnl_id %d not registered", proto->chnl_id);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return -EPROTONOSUPPORT;
- }
-
- if (st_gdata->protos_registered)
- st_gdata->protos_registered--;
-
- remove_channel_from_table(st_gdata, proto);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
-
- if ((st_gdata->protos_registered == ST_EMPTY) &&
- (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
- pr_info(" all chnl_ids unregistered ");
-
- /* stop traffic on tty */
- if (st_gdata->tty) {
- tty_ldisc_flush(st_gdata->tty);
- stop_tty(st_gdata->tty);
- }
-
- /* all chnl_ids now unregistered */
- st_kim_stop(st_gdata->kim_data);
- /* disable ST LL */
- st_ll_disable(st_gdata);
- }
- return err;
-}
-
-/*
- * called in protocol stack drivers
- * via the write function pointer
- */
-long st_write(struct sk_buff *skb)
-{
- struct st_data_s *st_gdata;
- long len;
-
- st_kim_ref(&st_gdata, 0);
- if (unlikely(skb == NULL || st_gdata == NULL
- || st_gdata->tty == NULL)) {
- pr_err("data/tty unavailable to perform write");
- return -EINVAL;
- }
-
- pr_debug("%d to be written", skb->len);
- len = skb->len;
-
- /* st_ll to decide where to enqueue the skb */
- st_int_enqueue(st_gdata, skb);
- /* wake up */
- st_tx_wakeup(st_gdata);
-
- /* return number of bytes written */
- return len;
-}
-
-/* for protocols making use of shared transport */
-EXPORT_SYMBOL_GPL(st_unregister);
-
-/********************************************************************/
-/*
- * functions called from TTY layer
- */
-static int st_tty_open(struct tty_struct *tty)
-{
- struct st_data_s *st_gdata;
- pr_info("%s ", __func__);
-
- st_kim_ref(&st_gdata, 0);
- st_gdata->tty = tty;
- tty->disc_data = st_gdata;
-
- /* don't do an wakeup for now */
- clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-
- /* mem already allocated
- */
- tty->receive_room = 65536;
- /* Flush any pending characters in the driver and discipline. */
- tty_ldisc_flush(tty);
- tty_driver_flush_buffer(tty);
- /*
- * signal to UIM via KIM that -
- * installation of N_TI_WL ldisc is complete
- */
- st_kim_complete(st_gdata->kim_data);
- pr_debug("done %s", __func__);
-
- return 0;
-}
-
-static void st_tty_close(struct tty_struct *tty)
-{
- unsigned char i;
- unsigned long flags;
- struct st_data_s *st_gdata = tty->disc_data;
-
- pr_info("%s ", __func__);
-
- /*
- * TODO:
- * if a protocol has been registered & line discipline
- * un-installed for some reason - what should be done ?
- */
- spin_lock_irqsave(&st_gdata->lock, flags);
- for (i = ST_BT; i < ST_MAX_CHANNELS; i++) {
- if (st_gdata->is_registered[i] == true)
- pr_err("%d not un-registered", i);
- st_gdata->list[i] = NULL;
- st_gdata->is_registered[i] = false;
- }
- st_gdata->protos_registered = 0;
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- /*
- * signal to UIM via KIM that -
- * N_TI_WL ldisc is un-installed
- */
- st_kim_complete(st_gdata->kim_data);
- st_gdata->tty = NULL;
- /* Flush any pending characters in the driver and discipline. */
- tty_ldisc_flush(tty);
- tty_driver_flush_buffer(tty);
-
- spin_lock_irqsave(&st_gdata->lock, flags);
- /* empty out txq and tx_waitq */
- skb_queue_purge(&st_gdata->txq);
- skb_queue_purge(&st_gdata->tx_waitq);
- /* reset the TTY Rx states of ST */
- st_gdata->rx_count = 0;
- st_gdata->rx_state = ST_W4_PACKET_TYPE;
- kfree_skb(st_gdata->rx_skb);
- st_gdata->rx_skb = NULL;
- spin_unlock_irqrestore(&st_gdata->lock, flags);
-
- pr_debug("%s: done ", __func__);
-}
-
-static void st_tty_receive(struct tty_struct *tty, const u8 *data,
- const u8 *tty_flags, size_t count)
-{
-#ifdef VERBOSE
- print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE,
- 16, 1, data, count, 0);
-#endif
-
- /*
- * if fw download is in progress then route incoming data
- * to KIM for validation
- */
- st_recv(tty->disc_data, data, count);
- pr_debug("done %s", __func__);
-}
-
-/*
- * wake-up function called in from the TTY layer
- * inside the internal wakeup function will be called
- */
-static void st_tty_wakeup(struct tty_struct *tty)
-{
- struct st_data_s *st_gdata = tty->disc_data;
- pr_debug("%s ", __func__);
- /* don't do an wakeup for now */
- clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-
- /*
- * schedule the internal wakeup instead of calling directly to
- * avoid lockup (port->lock needed in tty->ops->write is
- * already taken here
- */
- schedule_work(&st_gdata->work_write_wakeup);
-}
-
-static void st_tty_flush_buffer(struct tty_struct *tty)
-{
- struct st_data_s *st_gdata = tty->disc_data;
- pr_debug("%s ", __func__);
-
- kfree_skb(st_gdata->tx_skb);
- st_gdata->tx_skb = NULL;
-
- tty_driver_flush_buffer(tty);
- return;
-}
-
-static struct tty_ldisc_ops st_ldisc_ops = {
- .num = N_TI_WL,
- .name = "n_st",
- .open = st_tty_open,
- .close = st_tty_close,
- .receive_buf = st_tty_receive,
- .write_wakeup = st_tty_wakeup,
- .flush_buffer = st_tty_flush_buffer,
- .owner = THIS_MODULE
-};
-
-/********************************************************************/
-int st_core_init(struct st_data_s **core_data)
-{
- struct st_data_s *st_gdata;
- long err;
-
- err = tty_register_ldisc(&st_ldisc_ops);
- if (err) {
- pr_err("error registering %d line discipline %ld",
- N_TI_WL, err);
- return err;
- }
- pr_debug("registered n_shared line discipline");
-
- st_gdata = kzalloc(sizeof(struct st_data_s), GFP_KERNEL);
- if (!st_gdata) {
- pr_err("memory allocation failed");
- err = -ENOMEM;
- goto err_unreg_ldisc;
- }
-
- /* Initialize ST TxQ and Tx waitQ queue head. All BT/FM/GPS module skb's
- * will be pushed in this queue for actual transmission.
- */
- skb_queue_head_init(&st_gdata->txq);
- skb_queue_head_init(&st_gdata->tx_waitq);
-
- /* Locking used in st_int_enqueue() to avoid multiple execution */
- spin_lock_init(&st_gdata->lock);
-
- err = st_ll_init(st_gdata);
- if (err) {
- pr_err("error during st_ll initialization(%ld)", err);
- goto err_free_gdata;
- }
-
- INIT_WORK(&st_gdata->work_write_wakeup, work_fn_write_wakeup);
-
- *core_data = st_gdata;
- return 0;
-err_free_gdata:
- kfree(st_gdata);
-err_unreg_ldisc:
- tty_unregister_ldisc(&st_ldisc_ops);
- return err;
-}
-
-void st_core_exit(struct st_data_s *st_gdata)
-{
- long err;
- /* internal module cleanup */
- err = st_ll_deinit(st_gdata);
- if (err)
- pr_err("error during deinit of ST LL %ld", err);
-
- if (st_gdata != NULL) {
- /* Free ST Tx Qs and skbs */
- skb_queue_purge(&st_gdata->txq);
- skb_queue_purge(&st_gdata->tx_waitq);
- kfree_skb(st_gdata->rx_skb);
- kfree_skb(st_gdata->tx_skb);
- /* TTY ldisc cleanup */
- tty_unregister_ldisc(&st_ldisc_ops);
- /* free the global data pointer */
- kfree(st_gdata);
- }
-}
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
deleted file mode 100644
index ff172cf4614d..000000000000
--- a/drivers/misc/ti-st/st_kim.c
+++ /dev/null
@@ -1,839 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Shared Transport Line discipline driver Core
- * Init Manager module responsible for GPIO control
- * and firmware download
- * Copyright (C) 2009-2010 Texas Instruments
- * Author: Pavan Savoy <pavan_savoy@ti.com>
- */
-
-#define pr_fmt(fmt) "(stk) :" fmt
-#include <linux/platform_device.h>
-#include <linux/jiffies.h>
-#include <linux/firmware.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/gpio.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/sched.h>
-#include <linux/sysfs.h>
-#include <linux/tty.h>
-
-#include <linux/skbuff.h>
-#include <linux/ti_wilink_st.h>
-#include <linux/module.h>
-
-#define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */
-static struct platform_device *st_kim_devices[MAX_ST_DEVICES];
-
-/**********************************************************************/
-/* internal functions */
-
-/*
- * st_get_plat_device -
- * function which returns the reference to the platform device
- * requested by id. As of now only 1 such device exists (id=0)
- * the context requesting for reference can get the id to be
- * requested by a. The protocol driver which is registering or
- * b. the tty device which is opened.
- */
-static struct platform_device *st_get_plat_device(int id)
-{
- return st_kim_devices[id];
-}
-
-/*
- * validate_firmware_response -
- * function to return whether the firmware response was proper
- * in case of error don't complete so that waiting for proper
- * response times out
- */
-static void validate_firmware_response(struct kim_data_s *kim_gdata)
-{
- struct sk_buff *skb = kim_gdata->rx_skb;
- if (!skb)
- return;
-
- /*
- * these magic numbers are the position in the response buffer which
- * allows us to distinguish whether the response is for the read
- * version info. command
- */
- if (skb->data[2] == 0x01 && skb->data[3] == 0x01 &&
- skb->data[4] == 0x10 && skb->data[5] == 0x00) {
- /* fw version response */
- memcpy(kim_gdata->resp_buffer,
- kim_gdata->rx_skb->data,
- kim_gdata->rx_skb->len);
- kim_gdata->rx_state = ST_W4_PACKET_TYPE;
- kim_gdata->rx_skb = NULL;
- kim_gdata->rx_count = 0;
- } else if (unlikely(skb->data[5] != 0)) {
- pr_err("no proper response during fw download");
- pr_err("data6 %x", skb->data[5]);
- kfree_skb(skb);
- return; /* keep waiting for the proper response */
- }
- /* becos of all the script being downloaded */
- complete_all(&kim_gdata->kim_rcvd);
- kfree_skb(skb);
-}
-
-/*
- * check for data len received inside kim_int_recv
- * most often hit the last case to update state to waiting for data
- */
-static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len)
-{
- register int room = skb_tailroom(kim_gdata->rx_skb);
-
- pr_debug("len %d room %d", len, room);
-
- if (!len) {
- validate_firmware_response(kim_gdata);
- } else if (len > room) {
- /*
- * Received packet's payload length is larger.
- * We can't accommodate it in created skb.
- */
- pr_err("Data length is too large len %d room %d", len,
- room);
- kfree_skb(kim_gdata->rx_skb);
- } else {
- /*
- * Packet header has non-zero payload length and
- * we have enough space in created skb. Lets read
- * payload data */
- kim_gdata->rx_state = ST_W4_DATA;
- kim_gdata->rx_count = len;
- return len;
- }
-
- /*
- * Change ST LL state to continue to process next
- * packet
- */
- kim_gdata->rx_state = ST_W4_PACKET_TYPE;
- kim_gdata->rx_skb = NULL;
- kim_gdata->rx_count = 0;
-
- return 0;
-}
-
-/*
- * kim_int_recv - receive function called during firmware download
- * firmware download responses on different UART drivers
- * have been observed to come in bursts of different
- * tty_receive and hence the logic
- */
-static void kim_int_recv(struct kim_data_s *kim_gdata, const u8 *ptr,
- size_t count)
-{
- int len = 0;
- unsigned char *plen;
-
- pr_debug("%s", __func__);
- /* Decode received bytes here */
- while (count) {
- if (kim_gdata->rx_count) {
- len = min_t(unsigned int, kim_gdata->rx_count, count);
- skb_put_data(kim_gdata->rx_skb, ptr, len);
- kim_gdata->rx_count -= len;
- count -= len;
- ptr += len;
-
- if (kim_gdata->rx_count)
- continue;
-
- /* Check ST RX state machine , where are we? */
- switch (kim_gdata->rx_state) {
- /* Waiting for complete packet ? */
- case ST_W4_DATA:
- pr_debug("Complete pkt received");
- validate_firmware_response(kim_gdata);
- kim_gdata->rx_state = ST_W4_PACKET_TYPE;
- kim_gdata->rx_skb = NULL;
- continue;
- /* Waiting for Bluetooth event header ? */
- case ST_W4_HEADER:
- plen =
- (unsigned char *)&kim_gdata->rx_skb->data[1];
- pr_debug("event hdr: plen 0x%02x\n", *plen);
- kim_check_data_len(kim_gdata, *plen);
- continue;
- } /* end of switch */
- } /* end of if rx_state */
- switch (*ptr) {
- /* Bluetooth event packet? */
- case 0x04:
- kim_gdata->rx_state = ST_W4_HEADER;
- kim_gdata->rx_count = 2;
- break;
- default:
- pr_info("unknown packet");
- ptr++;
- count--;
- continue;
- }
- ptr++;
- count--;
- kim_gdata->rx_skb =
- alloc_skb(1024+8, GFP_ATOMIC);
- if (!kim_gdata->rx_skb) {
- pr_err("can't allocate mem for new packet");
- kim_gdata->rx_state = ST_W4_PACKET_TYPE;
- kim_gdata->rx_count = 0;
- return;
- }
- skb_reserve(kim_gdata->rx_skb, 8);
- kim_gdata->rx_skb->cb[0] = 4;
- kim_gdata->rx_skb->cb[1] = 0;
-
- }
- return;
-}
-
-static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
-{
- unsigned short version = 0, chip = 0, min_ver = 0, maj_ver = 0;
- static const char read_ver_cmd[] = { 0x01, 0x01, 0x10, 0x00 };
- long time_left;
-
- pr_debug("%s", __func__);
-
- reinit_completion(&kim_gdata->kim_rcvd);
- if (4 != st_int_write(kim_gdata->core_data, read_ver_cmd, 4)) {
- pr_err("kim: couldn't write 4 bytes");
- return -EIO;
- }
-
- time_left = wait_for_completion_interruptible_timeout(
- &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME));
- if (time_left <= 0) {
- pr_err(" waiting for ver info- timed out or received signal");
- return time_left ? -ERESTARTSYS : -ETIMEDOUT;
- }
- reinit_completion(&kim_gdata->kim_rcvd);
- /*
- * the positions 12 & 13 in the response buffer provide with the
- * chip, major & minor numbers
- */
-
- version =
- MAKEWORD(kim_gdata->resp_buffer[12],
- kim_gdata->resp_buffer[13]);
- chip = (version & 0x7C00) >> 10;
- min_ver = (version & 0x007F);
- maj_ver = (version & 0x0380) >> 7;
-
- if (version & 0x8000)
- maj_ver |= 0x0008;
-
- sprintf(bts_scr_name, "ti-connectivity/TIInit_%d.%d.%d.bts",
- chip, maj_ver, min_ver);
-
- /* to be accessed later via sysfs entry */
- kim_gdata->version.full = version;
- kim_gdata->version.chip = chip;
- kim_gdata->version.maj_ver = maj_ver;
- kim_gdata->version.min_ver = min_ver;
-
- pr_info("%s", bts_scr_name);
- return 0;
-}
-
-static void skip_change_remote_baud(unsigned char **ptr, long *len)
-{
- unsigned char *nxt_action, *cur_action;
- cur_action = *ptr;
-
- nxt_action = cur_action + sizeof(struct bts_action) +
- ((struct bts_action *) cur_action)->size;
-
- if (((struct bts_action *) nxt_action)->type != ACTION_WAIT_EVENT) {
- pr_err("invalid action after change remote baud command");
- } else {
- *ptr = *ptr + sizeof(struct bts_action) +
- ((struct bts_action *)cur_action)->size;
- *len = *len - (sizeof(struct bts_action) +
- ((struct bts_action *)cur_action)->size);
- /* warn user on not commenting these in firmware */
- pr_warn("skipping the wait event of change remote baud");
- }
-}
-
-/*
- * download_firmware -
- * internal function which parses through the .bts firmware
- * script file intreprets SEND, DELAY actions only as of now
- */
-static long download_firmware(struct kim_data_s *kim_gdata)
-{
- long err = 0;
- long len = 0;
- unsigned char *ptr = NULL;
- unsigned char *action_ptr = NULL;
- unsigned char bts_scr_name[40] = { 0 }; /* 40 char long bts scr name? */
- int wr_room_space;
- int cmd_size;
- unsigned long timeout;
-
- err = read_local_version(kim_gdata, bts_scr_name);
- if (err != 0) {
- pr_err("kim: failed to read local ver");
- return err;
- }
- err =
- request_firmware(&kim_gdata->fw_entry, bts_scr_name,
- &kim_gdata->kim_pdev->dev);
- if (unlikely((err != 0) || (kim_gdata->fw_entry->data == NULL) ||
- (kim_gdata->fw_entry->size == 0))) {
- pr_err(" request_firmware failed(errno %ld) for %s", err,
- bts_scr_name);
- return -EINVAL;
- }
- ptr = (void *)kim_gdata->fw_entry->data;
- len = kim_gdata->fw_entry->size;
- /*
- * bts_header to remove out magic number and
- * version
- */
- ptr += sizeof(struct bts_header);
- len -= sizeof(struct bts_header);
-
- while (len > 0 && ptr) {
- pr_debug(" action size %d, type %d ",
- ((struct bts_action *)ptr)->size,
- ((struct bts_action *)ptr)->type);
-
- switch (((struct bts_action *)ptr)->type) {
- case ACTION_SEND_COMMAND: /* action send */
- pr_debug("S");
- action_ptr = &(((struct bts_action *)ptr)->data[0]);
- if (unlikely
- (((struct hci_command *)action_ptr)->opcode ==
- 0xFF36)) {
- /*
- * ignore remote change
- * baud rate HCI VS command
- */
- pr_warn("change remote baud"
- " rate command in firmware");
- skip_change_remote_baud(&ptr, &len);
- break;
- }
- /*
- * Make sure we have enough free space in uart
- * tx buffer to write current firmware command
- */
- cmd_size = ((struct bts_action *)ptr)->size;
- timeout = jiffies + msecs_to_jiffies(CMD_WR_TIME);
- do {
- wr_room_space =
- st_get_uart_wr_room(kim_gdata->core_data);
- if (wr_room_space < 0) {
- pr_err("Unable to get free "
- "space info from uart tx buffer");
- release_firmware(kim_gdata->fw_entry);
- return wr_room_space;
- }
- mdelay(1); /* wait 1ms before checking room */
- } while ((wr_room_space < cmd_size) &&
- time_before(jiffies, timeout));
-
- /* Timeout happened ? */
- if (time_after_eq(jiffies, timeout)) {
- pr_err("Timeout while waiting for free "
- "free space in uart tx buffer");
- release_firmware(kim_gdata->fw_entry);
- return -ETIMEDOUT;
- }
- /*
- * reinit completion before sending for the
- * relevant wait
- */
- reinit_completion(&kim_gdata->kim_rcvd);
-
- /*
- * Free space found in uart buffer, call st_int_write
- * to send current firmware command to the uart tx
- * buffer.
- */
- err = st_int_write(kim_gdata->core_data,
- ((struct bts_action_send *)action_ptr)->data,
- ((struct bts_action *)ptr)->size);
- if (unlikely(err < 0)) {
- release_firmware(kim_gdata->fw_entry);
- return err;
- }
- /*
- * Check number of bytes written to the uart tx buffer
- * and requested command write size
- */
- if (err != cmd_size) {
- pr_err("Number of bytes written to uart "
- "tx buffer are not matching with "
- "requested cmd write size");
- release_firmware(kim_gdata->fw_entry);
- return -EIO;
- }
- break;
- case ACTION_WAIT_EVENT: /* wait */
- pr_debug("W");
- err = wait_for_completion_interruptible_timeout(
- &kim_gdata->kim_rcvd,
- msecs_to_jiffies(CMD_RESP_TIME));
- if (err <= 0) {
- pr_err("response timeout/signaled during fw download ");
- /* timed out */
- release_firmware(kim_gdata->fw_entry);
- return err ? -ERESTARTSYS : -ETIMEDOUT;
- }
- reinit_completion(&kim_gdata->kim_rcvd);
- break;
- case ACTION_DELAY: /* sleep */
- pr_info("sleep command in scr");
- action_ptr = &(((struct bts_action *)ptr)->data[0]);
- mdelay(((struct bts_action_delay *)action_ptr)->msec);
- break;
- }
- len =
- len - (sizeof(struct bts_action) +
- ((struct bts_action *)ptr)->size);
- ptr =
- ptr + sizeof(struct bts_action) +
- ((struct bts_action *)ptr)->size;
- }
- /* fw download complete */
- release_firmware(kim_gdata->fw_entry);
- return 0;
-}
-
-/**********************************************************************/
-/* functions called from ST core */
-/* called from ST Core, when REG_IN_PROGRESS (registration in progress)
- * can be because of
- * 1. response to read local version
- * 2. during send/recv's of firmware download
- */
-void st_kim_recv(void *disc_data, const u8 *data, size_t count)
-{
- struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
- struct kim_data_s *kim_gdata = st_gdata->kim_data;
-
- /*
- * proceed to gather all data and distinguish read fw version response
- * from other fw responses when data gathering is complete
- */
- kim_int_recv(kim_gdata, data, count);
- return;
-}
-
-/*
- * to signal completion of line discipline installation
- * called from ST Core, upon tty_open
- */
-void st_kim_complete(void *kim_data)
-{
- struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
- complete(&kim_gdata->ldisc_installed);
-}
-
-/*
- * st_kim_start - called from ST Core upon 1st registration
- * This involves toggling the chip enable gpio, reading
- * the firmware version from chip, forming the fw file name
- * based on the chip version, requesting the fw, parsing it
- * and perform download(send/recv).
- */
-long st_kim_start(void *kim_data)
-{
- long err = 0;
- long retry = POR_RETRY_COUNT;
- struct ti_st_plat_data *pdata;
- struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
-
- pr_info(" %s", __func__);
- pdata = kim_gdata->kim_pdev->dev.platform_data;
-
- do {
- /* platform specific enabling code here */
- if (pdata->chip_enable)
- pdata->chip_enable(kim_gdata);
-
- /* Configure BT nShutdown to HIGH state */
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
- mdelay(5); /* FIXME: a proper toggle */
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_HIGH);
- mdelay(100);
- /* re-initialize the completion */
- reinit_completion(&kim_gdata->ldisc_installed);
- /* send notification to UIM */
- kim_gdata->ldisc_install = 1;
- pr_info("ldisc_install = 1");
- sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
- NULL, "install");
- /* wait for ldisc to be installed */
- err = wait_for_completion_interruptible_timeout(
- &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
- if (!err) {
- /*
- * ldisc installation timeout,
- * flush uart, power cycle BT_EN
- */
- pr_err("ldisc installation timeout");
- err = st_kim_stop(kim_gdata);
- continue;
- } else {
- /* ldisc installed now */
- pr_info("line discipline installed");
- err = download_firmware(kim_gdata);
- if (err != 0) {
- /*
- * ldisc installed but fw download failed,
- * flush uart & power cycle BT_EN
- */
- pr_err("download firmware failed");
- err = st_kim_stop(kim_gdata);
- continue;
- } else { /* on success don't retry */
- break;
- }
- }
- } while (retry--);
- return err;
-}
-
-/*
- * st_kim_stop - stop communication with chip.
- * This can be called from ST Core/KIM, on the-
- * (a) last un-register when chip need not be powered there-after,
- * (b) upon failure to either install ldisc or download firmware.
- * The function is responsible to (a) notify UIM about un-installation,
- * (b) flush UART if the ldisc was installed.
- * (c) reset BT_EN - pull down nshutdown at the end.
- * (d) invoke platform's chip disabling routine.
- */
-long st_kim_stop(void *kim_data)
-{
- long err = 0;
- struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
- struct ti_st_plat_data *pdata =
- kim_gdata->kim_pdev->dev.platform_data;
- struct tty_struct *tty = kim_gdata->core_data->tty;
-
- reinit_completion(&kim_gdata->ldisc_installed);
-
- if (tty) { /* can be called before ldisc is installed */
- /* Flush any pending characters in the driver and discipline. */
- tty_ldisc_flush(tty);
- tty_driver_flush_buffer(tty);
- }
-
- /* send uninstall notification to UIM */
- pr_info("ldisc_install = 0");
- kim_gdata->ldisc_install = 0;
- sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install");
-
- /* wait for ldisc to be un-installed */
- err = wait_for_completion_interruptible_timeout(
- &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
- if (!err) { /* timeout */
- pr_err(" timed out waiting for ldisc to be un-installed");
- err = -ETIMEDOUT;
- }
-
- /* By default configure BT nShutdown to LOW state */
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
- mdelay(1);
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_HIGH);
- mdelay(1);
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
-
- /* platform specific disable */
- if (pdata->chip_disable)
- pdata->chip_disable(kim_gdata);
- return err;
-}
-
-/**********************************************************************/
-/* functions called from subsystems */
-/* called when debugfs entry is read from */
-
-static int version_show(struct seq_file *s, void *unused)
-{
- struct kim_data_s *kim_gdata = s->private;
- seq_printf(s, "%04X %d.%d.%d\n", kim_gdata->version.full,
- kim_gdata->version.chip, kim_gdata->version.maj_ver,
- kim_gdata->version.min_ver);
- return 0;
-}
-
-static int list_show(struct seq_file *s, void *unused)
-{
- struct kim_data_s *kim_gdata = s->private;
- kim_st_list_protocols(kim_gdata->core_data, s);
- return 0;
-}
-
-static ssize_t show_install(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", kim_data->ldisc_install);
-}
-
-#ifdef DEBUG
-static ssize_t store_dev_name(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- pr_debug("storing dev name >%s<", buf);
- strscpy(kim_data->dev_name, buf, sizeof(kim_data->dev_name));
- pr_debug("stored dev name >%s<", kim_data->dev_name);
- return count;
-}
-
-static ssize_t store_baud_rate(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- pr_debug("storing baud rate >%s<", buf);
- sscanf(buf, "%ld", &kim_data->baud_rate);
- pr_debug("stored baud rate >%ld<", kim_data->baud_rate);
- return count;
-}
-#endif /* if DEBUG */
-
-static ssize_t show_dev_name(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- return sprintf(buf, "%s\n", kim_data->dev_name);
-}
-
-static ssize_t show_baud_rate(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", kim_data->baud_rate);
-}
-
-static ssize_t show_flow_cntrl(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", kim_data->flow_cntrl);
-}
-
-/* structures specific for sysfs entries */
-static struct kobj_attribute ldisc_install =
-__ATTR(install, 0444, (void *)show_install, NULL);
-
-static struct kobj_attribute uart_dev_name =
-#ifdef DEBUG /* TODO: move this to debug-fs if possible */
-__ATTR(dev_name, 0644, (void *)show_dev_name, (void *)store_dev_name);
-#else
-__ATTR(dev_name, 0444, (void *)show_dev_name, NULL);
-#endif
-
-static struct kobj_attribute uart_baud_rate =
-#ifdef DEBUG /* TODO: move to debugfs */
-__ATTR(baud_rate, 0644, (void *)show_baud_rate, (void *)store_baud_rate);
-#else
-__ATTR(baud_rate, 0444, (void *)show_baud_rate, NULL);
-#endif
-
-static struct kobj_attribute uart_flow_cntrl =
-__ATTR(flow_cntrl, 0444, (void *)show_flow_cntrl, NULL);
-
-static struct attribute *uim_attrs[] = {
- &ldisc_install.attr,
- &uart_dev_name.attr,
- &uart_baud_rate.attr,
- &uart_flow_cntrl.attr,
- NULL,
-};
-
-static const struct attribute_group uim_attr_grp = {
- .attrs = uim_attrs,
-};
-
-/*
- * st_kim_ref - reference the core's data
- * This references the per-ST platform device in the arch/xx/
- * board-xx.c file.
- * This would enable multiple such platform devices to exist
- * on a given platform
- */
-void st_kim_ref(struct st_data_s **core_data, int id)
-{
- struct platform_device *pdev;
- struct kim_data_s *kim_gdata;
- /* get kim_gdata reference from platform device */
- pdev = st_get_plat_device(id);
- if (!pdev)
- goto err;
- kim_gdata = platform_get_drvdata(pdev);
- if (!kim_gdata)
- goto err;
-
- *core_data = kim_gdata->core_data;
- return;
-err:
- *core_data = NULL;
-}
-
-DEFINE_SHOW_ATTRIBUTE(version);
-DEFINE_SHOW_ATTRIBUTE(list);
-
-/**********************************************************************/
-/* functions called from platform device driver subsystem
- * need to have a relevant platform device entry in the platform's
- * board-*.c file
- */
-
-static struct dentry *kim_debugfs_dir;
-static int kim_probe(struct platform_device *pdev)
-{
- struct kim_data_s *kim_gdata;
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
- int err;
-
- if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) {
- /* multiple devices could exist */
- st_kim_devices[pdev->id] = pdev;
- } else {
- /* platform's sure about existence of 1 device */
- st_kim_devices[0] = pdev;
- }
-
- kim_gdata = kzalloc(sizeof(struct kim_data_s), GFP_KERNEL);
- if (!kim_gdata) {
- pr_err("no mem to allocate");
- return -ENOMEM;
- }
- platform_set_drvdata(pdev, kim_gdata);
-
- err = st_core_init(&kim_gdata->core_data);
- if (err != 0) {
- pr_err(" ST core init failed");
- err = -EIO;
- goto err_core_init;
- }
- /* refer to itself */
- kim_gdata->core_data->kim_data = kim_gdata;
-
- /* Claim the chip enable nShutdown gpio from the system */
- kim_gdata->nshutdown = pdata->nshutdown_gpio;
- err = gpio_request(kim_gdata->nshutdown, "kim");
- if (unlikely(err)) {
- pr_err(" gpio %d request failed ", kim_gdata->nshutdown);
- goto err_sysfs_group;
- }
-
- /* Configure nShutdown GPIO as output=0 */
- err = gpio_direction_output(kim_gdata->nshutdown, 0);
- if (unlikely(err)) {
- pr_err(" unable to configure gpio %d", kim_gdata->nshutdown);
- goto err_sysfs_group;
- }
- /* get reference of pdev for request_firmware */
- kim_gdata->kim_pdev = pdev;
- init_completion(&kim_gdata->kim_rcvd);
- init_completion(&kim_gdata->ldisc_installed);
-
- err = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp);
- if (err) {
- pr_err("failed to create sysfs entries");
- goto err_sysfs_group;
- }
-
- /* copying platform data */
- strscpy(kim_gdata->dev_name, pdata->dev_name,
- sizeof(kim_gdata->dev_name));
- kim_gdata->flow_cntrl = pdata->flow_cntrl;
- kim_gdata->baud_rate = pdata->baud_rate;
- pr_info("sysfs entries created\n");
-
- kim_debugfs_dir = debugfs_create_dir("ti-st", NULL);
-
- debugfs_create_file("version", S_IRUGO, kim_debugfs_dir,
- kim_gdata, &version_fops);
- debugfs_create_file("protocols", S_IRUGO, kim_debugfs_dir,
- kim_gdata, &list_fops);
- return 0;
-
-err_sysfs_group:
- st_core_exit(kim_gdata->core_data);
-
-err_core_init:
- kfree(kim_gdata);
-
- return err;
-}
-
-static void kim_remove(struct platform_device *pdev)
-{
- /* free the GPIOs requested */
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
- struct kim_data_s *kim_gdata;
-
- kim_gdata = platform_get_drvdata(pdev);
-
- /*
- * Free the Bluetooth/FM/GPIO
- * nShutdown gpio from the system
- */
- gpio_free(pdata->nshutdown_gpio);
- pr_info("nshutdown GPIO Freed");
-
- debugfs_remove_recursive(kim_debugfs_dir);
- sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
- pr_info("sysfs entries removed");
-
- kim_gdata->kim_pdev = NULL;
- st_core_exit(kim_gdata->core_data);
-
- kfree(kim_gdata);
- kim_gdata = NULL;
-}
-
-static int kim_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
-
- if (pdata->suspend)
- return pdata->suspend(pdev, state);
-
- return 0;
-}
-
-static int kim_resume(struct platform_device *pdev)
-{
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
-
- if (pdata->resume)
- return pdata->resume(pdev);
-
- return 0;
-}
-
-/**********************************************************************/
-/* entry point for ST KIM module, called in from ST Core */
-static struct platform_driver kim_platform_driver = {
- .probe = kim_probe,
- .remove_new = kim_remove,
- .suspend = kim_suspend,
- .resume = kim_resume,
- .driver = {
- .name = "kim",
- },
-};
-
-module_platform_driver(kim_platform_driver);
-
-MODULE_AUTHOR("Pavan Savoy <pavan_savoy@ti.com>");
-MODULE_DESCRIPTION("Shared Transport Driver for TI BT/FM/GPS combo chips ");
-MODULE_LICENSE("GPL");
diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c
deleted file mode 100644
index 07406140d277..000000000000
--- a/drivers/misc/ti-st/st_ll.c
+++ /dev/null
@@ -1,156 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Shared Transport driver
- * HCI-LL module responsible for TI proprietary HCI_LL protocol
- * Copyright (C) 2009-2010 Texas Instruments
- * Author: Pavan Savoy <pavan_savoy@ti.com>
- */
-
-#define pr_fmt(fmt) "(stll) :" fmt
-#include <linux/skbuff.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/ti_wilink_st.h>
-
-/**********************************************************************/
-/* internal functions */
-static void send_ll_cmd(struct st_data_s *st_data,
- unsigned char cmd)
-{
-
- pr_debug("%s: writing %x", __func__, cmd);
- st_int_write(st_data, &cmd, 1);
- return;
-}
-
-static void ll_device_want_to_sleep(struct st_data_s *st_data)
-{
- struct kim_data_s *kim_data;
- struct ti_st_plat_data *pdata;
-
- pr_debug("%s", __func__);
- /* sanity check */
- if (st_data->ll_state != ST_LL_AWAKE)
- pr_err("ERR hcill: ST_LL_GO_TO_SLEEP_IND"
- "in state %ld", st_data->ll_state);
-
- send_ll_cmd(st_data, LL_SLEEP_ACK);
- /* update state */
- st_data->ll_state = ST_LL_ASLEEP;
-
- /* communicate to platform about chip asleep */
- kim_data = st_data->kim_data;
- pdata = kim_data->kim_pdev->dev.platform_data;
- if (pdata->chip_asleep)
- pdata->chip_asleep(NULL);
-}
-
-static void ll_device_want_to_wakeup(struct st_data_s *st_data)
-{
- struct kim_data_s *kim_data;
- struct ti_st_plat_data *pdata;
-
- /* diff actions in diff states */
- switch (st_data->ll_state) {
- case ST_LL_ASLEEP:
- send_ll_cmd(st_data, LL_WAKE_UP_ACK); /* send wake_ack */
- break;
- case ST_LL_ASLEEP_TO_AWAKE:
- /* duplicate wake_ind */
- pr_err("duplicate wake_ind while waiting for Wake ack");
- break;
- case ST_LL_AWAKE:
- /* duplicate wake_ind */
- pr_err("duplicate wake_ind already AWAKE");
- break;
- case ST_LL_AWAKE_TO_ASLEEP:
- /* duplicate wake_ind */
- pr_err("duplicate wake_ind");
- break;
- }
- /* update state */
- st_data->ll_state = ST_LL_AWAKE;
-
- /* communicate to platform about chip wakeup */
- kim_data = st_data->kim_data;
- pdata = kim_data->kim_pdev->dev.platform_data;
- if (pdata->chip_awake)
- pdata->chip_awake(NULL);
-}
-
-/**********************************************************************/
-/* functions invoked by ST Core */
-
-/* called when ST Core wants to
- * enable ST LL */
-void st_ll_enable(struct st_data_s *ll)
-{
- ll->ll_state = ST_LL_AWAKE;
-}
-
-/* called when ST Core /local module wants to
- * disable ST LL */
-void st_ll_disable(struct st_data_s *ll)
-{
- ll->ll_state = ST_LL_INVALID;
-}
-
-/* called when ST Core wants to update the state */
-void st_ll_wakeup(struct st_data_s *ll)
-{
- if (likely(ll->ll_state != ST_LL_AWAKE)) {
- send_ll_cmd(ll, LL_WAKE_UP_IND); /* WAKE_IND */
- ll->ll_state = ST_LL_ASLEEP_TO_AWAKE;
- } else {
- /* don't send the duplicate wake_indication */
- pr_err(" Chip already AWAKE ");
- }
-}
-
-/* called when ST Core wants the state */
-unsigned long st_ll_getstate(struct st_data_s *ll)
-{
- pr_debug(" returning state %ld", ll->ll_state);
- return ll->ll_state;
-}
-
-/* called from ST Core, when a PM related packet arrives */
-unsigned long st_ll_sleep_state(struct st_data_s *st_data,
- unsigned char cmd)
-{
- switch (cmd) {
- case LL_SLEEP_IND: /* sleep ind */
- pr_debug("sleep indication recvd");
- ll_device_want_to_sleep(st_data);
- break;
- case LL_SLEEP_ACK: /* sleep ack */
- pr_err("sleep ack rcvd: host shouldn't");
- break;
- case LL_WAKE_UP_IND: /* wake ind */
- pr_debug("wake indication recvd");
- ll_device_want_to_wakeup(st_data);
- break;
- case LL_WAKE_UP_ACK: /* wake ack */
- pr_debug("wake ack rcvd");
- st_data->ll_state = ST_LL_AWAKE;
- break;
- default:
- pr_err(" unknown input/state ");
- return -EINVAL;
- }
- return 0;
-}
-
-/* Called from ST CORE to initialize ST LL */
-long st_ll_init(struct st_data_s *ll)
-{
- /* set state to invalid */
- ll->ll_state = ST_LL_INVALID;
- return 0;
-}
-
-/* Called from ST CORE to de-initialize ST LL */
-long st_ll_deinit(struct st_data_s *ll)
-{
- return 0;
-}
diff --git a/drivers/mtd/spi-nor/sysfs.c b/drivers/mtd/spi-nor/sysfs.c
index 96064e4babf0..5e9eb268073d 100644
--- a/drivers/mtd/spi-nor/sysfs.c
+++ b/drivers/mtd/spi-nor/sysfs.c
@@ -87,7 +87,7 @@ static umode_t spi_nor_sysfs_is_visible(struct kobject *kobj,
}
static umode_t spi_nor_sysfs_is_bin_visible(struct kobject *kobj,
- struct bin_attribute *attr, int n)
+ const struct bin_attribute *attr, int n)
{
struct spi_device *spi = to_spi_device(kobj_to_dev(kobj));
struct spi_mem *spimem = spi_get_drvdata(spi);
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index ae5abe492b52..adc47b87b38a 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1447,7 +1447,7 @@ out_ech:
return err;
}
-static struct ubi_attach_info *alloc_ai(void)
+static struct ubi_attach_info *alloc_ai(const char *slab_name)
{
struct ubi_attach_info *ai;
@@ -1461,7 +1461,7 @@ static struct ubi_attach_info *alloc_ai(void)
INIT_LIST_HEAD(&ai->alien);
INIT_LIST_HEAD(&ai->fastmap);
ai->volumes = RB_ROOT;
- ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
+ ai->aeb_slab_cache = kmem_cache_create(slab_name,
sizeof(struct ubi_ainf_peb),
0, 0, NULL);
if (!ai->aeb_slab_cache) {
@@ -1491,7 +1491,7 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai)
err = -ENOMEM;
- scan_ai = alloc_ai();
+ scan_ai = alloc_ai("ubi_aeb_slab_cache_fastmap");
if (!scan_ai)
goto out;
@@ -1557,7 +1557,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
int err;
struct ubi_attach_info *ai;
- ai = alloc_ai();
+ ai = alloc_ai("ubi_aeb_slab_cache");
if (!ai)
return -ENOMEM;
@@ -1575,7 +1575,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
if (err > 0 || mtd_is_eccerr(err)) {
if (err != UBI_NO_FASTMAP) {
destroy_ai(ai);
- ai = alloc_ai();
+ ai = alloc_ai("ubi_aeb_slab_cache");
if (!ai)
return -ENOMEM;
@@ -1614,7 +1614,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
if (ubi->fm && ubi_dbg_chk_fastmap(ubi)) {
struct ubi_attach_info *scan_ai;
- scan_ai = alloc_ai();
+ scan_ai = alloc_ai("ubi_aeb_slab_cache_dbg_chk_fastmap");
if (!scan_ai) {
err = -ENOMEM;
goto out_wl;
diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c
index 2a9cc9413c42..9bdb6525f128 100644
--- a/drivers/mtd/ubi/fastmap-wl.c
+++ b/drivers/mtd/ubi/fastmap-wl.c
@@ -346,14 +346,27 @@ out:
* WL sub-system.
*
* @ubi: UBI device description object
+ * @need_fill: whether to fill wear-leveling pool when no PEBs are found
*/
-static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi)
+static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
+ bool need_fill)
{
struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
int pnum;
- if (pool->used == pool->size)
+ if (pool->used == pool->size) {
+ if (need_fill && !ubi->fm_work_scheduled) {
+ /*
+ * We cannot update the fastmap here because this
+ * function is called in atomic context.
+ * Let's fail here and refill/update it as soon as
+ * possible.
+ */
+ ubi->fm_work_scheduled = 1;
+ schedule_work(&ubi->fm_work);
+ }
return NULL;
+ }
pnum = pool->pebs[pool->used];
return ubi->lookuptbl[pnum];
@@ -375,7 +388,7 @@ static bool need_wear_leveling(struct ubi_device *ubi)
if (!ubi->used.rb_node)
return false;
- e = next_peb_for_wl(ubi);
+ e = next_peb_for_wl(ubi, false);
if (!e) {
if (!ubi->free.rb_node)
return false;
diff --git a/drivers/mtd/ubi/nvmem.c b/drivers/mtd/ubi/nvmem.c
index a94a1a9aaec1..34f8c1d3cdee 100644
--- a/drivers/mtd/ubi/nvmem.c
+++ b/drivers/mtd/ubi/nvmem.c
@@ -55,7 +55,7 @@ static int ubi_nvmem_reg_read(void *priv, unsigned int from,
if (err)
return err;
- return bytes_left == 0 ? 0 : -EIO;
+ return 0;
}
static int ubi_nvmem_add(struct ubi_volume_info *vi)
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 1c9e874e8ede..26cc53ad34ec 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -549,6 +549,7 @@ struct ubi_debug_info {
* @peb_buf: a buffer of PEB size used for different purposes
* @buf_mutex: protects @peb_buf
* @ckvol_mutex: serializes static volume checking when opening
+ * @wl_reboot_notifier: close all wear-leveling work before reboot
*
* @dbg: debugging information for this UBI device
*/
@@ -651,6 +652,7 @@ struct ubi_device {
void *peb_buf;
struct mutex buf_mutex;
struct mutex ckvol_mutex;
+ struct notifier_block wl_reboot_notifier;
struct ubi_debug_info dbg;
};
@@ -831,7 +833,6 @@ void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);
struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
struct ubi_attach_info *ai);
int ubi_attach(struct ubi_device *ubi, int force_scan);
-void ubi_destroy_ai(struct ubi_attach_info *ai);
/* vtbl.c */
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 5a3558bbb903..e5cf3bdca3b0 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -143,8 +143,10 @@ static struct fwnode_handle *find_volume_fwnode(struct ubi_volume *vol)
vol->vol_id != volid)
continue;
+ fwnode_handle_put(fw_vols);
return fw_vol;
}
+ fwnode_handle_put(fw_vols);
return NULL;
}
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index a357f3d27f2f..4f6f339d8fb8 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -89,6 +89,7 @@
#include <linux/crc32.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
+#include <linux/reboot.h>
#include "ubi.h"
#include "wl.h"
@@ -127,6 +128,8 @@ static int self_check_in_wl_tree(const struct ubi_device *ubi,
struct ubi_wl_entry *e, struct rb_root *root);
static int self_check_in_pq(const struct ubi_device *ubi,
struct ubi_wl_entry *e);
+static int ubi_wl_reboot_notifier(struct notifier_block *n,
+ unsigned long state, void *cmd);
/**
* wl_tree_add - add a wear-leveling entry to a WL RB-tree.
@@ -683,7 +686,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
ubi_assert(!ubi->move_to_put);
#ifdef CONFIG_MTD_UBI_FASTMAP
- if (!next_peb_for_wl(ubi) ||
+ if (!next_peb_for_wl(ubi, true) ||
#else
if (!ubi->free.rb_node ||
#endif
@@ -846,7 +849,14 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
goto out_not_moved;
}
if (err == MOVE_RETRY) {
- scrubbing = 1;
+ /*
+ * For source PEB:
+ * 1. The scrubbing is set for scrub type PEB, it will
+ * be put back into ubi->scrub list.
+ * 2. Non-scrub type PEB will be put back into ubi->used
+ * list.
+ */
+ keep = 1;
dst_leb_clean = 1;
goto out_not_moved;
}
@@ -1943,6 +1953,13 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (!ubi->ro_mode && !ubi->fm_disabled)
ubi_ensure_anchor_pebs(ubi);
#endif
+
+ if (!ubi->wl_reboot_notifier.notifier_call) {
+ ubi->wl_reboot_notifier.notifier_call = ubi_wl_reboot_notifier;
+ ubi->wl_reboot_notifier.priority = 1; /* Higher than MTD */
+ register_reboot_notifier(&ubi->wl_reboot_notifier);
+ }
+
return 0;
out_free:
@@ -1988,6 +2005,17 @@ void ubi_wl_close(struct ubi_device *ubi)
kfree(ubi->lookuptbl);
}
+static int ubi_wl_reboot_notifier(struct notifier_block *n,
+ unsigned long state, void *cmd)
+{
+ struct ubi_device *ubi;
+
+ ubi = container_of(n, struct ubi_device, wl_reboot_notifier);
+ ubi_wl_close(ubi);
+
+ return NOTIFY_DONE;
+}
+
/**
* self_check_ec - make sure that the erase counter of a PEB is correct.
* @ubi: UBI device description object
diff --git a/drivers/mtd/ubi/wl.h b/drivers/mtd/ubi/wl.h
index 7b6715ef6d4a..a69169c35e31 100644
--- a/drivers/mtd/ubi/wl.h
+++ b/drivers/mtd/ubi/wl.h
@@ -5,7 +5,8 @@
static void update_fastmap_work_fn(struct work_struct *wrk);
static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root);
static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi);
-static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi);
+static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
+ bool need_fill);
static bool need_wear_leveling(struct ubi_device *ubi);
static void ubi_fastmap_close(struct ubi_device *ubi);
static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index b826d0255ecf..4ec4934a4edd 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -4661,7 +4661,7 @@ int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
struct net_device *dev = bp->dev;
if (page_mode) {
- bp->flags &= ~BNXT_FLAG_AGG_RINGS;
+ bp->flags &= ~(BNXT_FLAG_AGG_RINGS | BNXT_FLAG_NO_AGG_RINGS);
bp->flags |= BNXT_FLAG_RX_PAGE_MODE;
if (bp->xdp_prog->aux->xdp_has_frags)
@@ -9299,7 +9299,6 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
struct hwrm_port_mac_ptp_qcfg_output *resp;
struct hwrm_port_mac_ptp_qcfg_input *req;
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
- bool phc_cfg;
u8 flags;
int rc;
@@ -9346,8 +9345,9 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
rc = -ENODEV;
goto exit;
}
- phc_cfg = (flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_RTC_CONFIGURED) != 0;
- rc = bnxt_ptp_init(bp, phc_cfg);
+ ptp->rtc_configured =
+ (flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_RTC_CONFIGURED) != 0;
+ rc = bnxt_ptp_init(bp);
if (rc)
netdev_warn(bp->dev, "PTP initialization failed.\n");
exit:
@@ -14746,6 +14746,14 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu)
bnxt_close_nic(bp, true, false);
WRITE_ONCE(dev->mtu, new_mtu);
+
+ /* MTU change may change the AGG ring settings if an XDP multi-buffer
+ * program is attached. We need to set the AGG rings settings and
+ * rx_skb_func accordingly.
+ */
+ if (READ_ONCE(bp->xdp_prog))
+ bnxt_set_rx_skb_mode(bp, true);
+
bnxt_set_ring_params(bp);
if (netif_running(dev))
@@ -15483,6 +15491,13 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx)
for (i = 0; i <= BNXT_VNIC_NTUPLE; i++) {
vnic = &bp->vnic_info[i];
+
+ rc = bnxt_hwrm_vnic_set_rss_p5(bp, vnic, true);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm vnic %d set rss failure rc: %d\n",
+ vnic->vnic_id, rc);
+ return rc;
+ }
vnic->mru = bp->dev->mtu + ETH_HLEN + VLAN_HLEN;
bnxt_hwrm_vnic_update(bp, vnic,
VNIC_UPDATE_REQ_ENABLES_MRU_VALID);
@@ -16236,6 +16251,7 @@ static void bnxt_shutdown(struct pci_dev *pdev)
if (netif_running(dev))
dev_close(dev);
+ bnxt_ptp_clear(bp);
bnxt_clear_int_mode(bp);
pci_disable_device(pdev);
@@ -16263,6 +16279,7 @@ static int bnxt_suspend(struct device *device)
rc = bnxt_close(dev);
}
bnxt_hwrm_func_drv_unrgtr(bp);
+ bnxt_ptp_clear(bp);
pci_disable_device(bp->pdev);
bnxt_free_ctx_mem(bp, false);
rtnl_unlock();
@@ -16306,6 +16323,10 @@ static int bnxt_resume(struct device *device)
if (bp->fw_crash_mem)
bnxt_hwrm_crash_dump_mem_cfg(bp);
+ if (bnxt_ptp_init(bp)) {
+ kfree(bp->ptp_cfg);
+ bp->ptp_cfg = NULL;
+ }
bnxt_get_wol_settings(bp);
if (netif_running(dev)) {
rc = bnxt_open(dev);
@@ -16484,8 +16505,12 @@ static void bnxt_io_resume(struct pci_dev *pdev)
rtnl_lock();
err = bnxt_hwrm_func_qcaps(bp);
- if (!err && netif_running(netdev))
- err = bnxt_open(netdev);
+ if (!err) {
+ if (netif_running(netdev))
+ err = bnxt_open(netdev);
+ else
+ err = bnxt_reserve_rings(bp, true);
+ }
if (!err)
netif_device_attach(netdev);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index 2f4987ec7464..f1f6bb328a55 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -2837,19 +2837,24 @@ static int bnxt_get_link_ksettings(struct net_device *dev,
}
base->port = PORT_NONE;
- if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) {
+ if (media == BNXT_MEDIA_TP) {
base->port = PORT_TP;
linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT,
lk_ksettings->link_modes.supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT,
lk_ksettings->link_modes.advertising);
+ } else if (media == BNXT_MEDIA_KR) {
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Backplane_BIT,
+ lk_ksettings->link_modes.supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Backplane_BIT,
+ lk_ksettings->link_modes.advertising);
} else {
linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
lk_ksettings->link_modes.supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
lk_ksettings->link_modes.advertising);
- if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC)
+ if (media == BNXT_MEDIA_CR)
base->port = PORT_DA;
else
base->port = PORT_FIBRE;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
index 075ccd589845..2d4e19b96ee7 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
@@ -1038,7 +1038,7 @@ static void bnxt_ptp_free(struct bnxt *bp)
}
}
-int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg)
+int bnxt_ptp_init(struct bnxt *bp)
{
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
int rc;
@@ -1061,7 +1061,7 @@ int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg)
if (BNXT_PTP_USE_RTC(bp)) {
bnxt_ptp_timecounter_init(bp, false);
- rc = bnxt_ptp_init_rtc(bp, phc_cfg);
+ rc = bnxt_ptp_init_rtc(bp, ptp->rtc_configured);
if (rc)
goto out;
} else {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
index c7851f8c971c..a95f05e9c579 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
@@ -135,6 +135,7 @@ struct bnxt_ptp_cfg {
BNXT_PTP_MSG_PDELAY_REQ | \
BNXT_PTP_MSG_PDELAY_RESP)
u8 tx_tstamp_en:1;
+ u8 rtc_configured:1;
int rx_filter;
u32 tstamp_filters;
@@ -168,7 +169,7 @@ void bnxt_tx_ts_cmp(struct bnxt *bp, struct bnxt_napi *bnapi,
struct tx_ts_cmp *tscmp);
void bnxt_ptp_rtc_timecounter_init(struct bnxt_ptp_cfg *ptp, u64 ns);
int bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg);
-int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg);
+int bnxt_ptp_init(struct bnxt *bp);
void bnxt_ptp_clear(struct bnxt *bp);
static inline u64 bnxt_timecounter_cyc2time(struct bnxt_ptp_cfg *ptp, u64 ts)
{
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 01dfec115942..9cc8db10a8d6 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -17839,6 +17839,9 @@ static int tg3_init_one(struct pci_dev *pdev,
} else
persist_dma_mask = dma_mask = DMA_BIT_MASK(64);
+ if (tg3_asic_rev(tp) == ASIC_REV_57766)
+ persist_dma_mask = DMA_BIT_MASK(31);
+
/* Configure DMA attributes. */
if (dma_mask > DMA_BIT_MASK(32)) {
err = dma_set_mask(&pdev->dev, dma_mask);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
index 27935c54b91b..8216f843a7cd 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
@@ -112,6 +112,11 @@ struct mac_ops *get_mac_ops(void *cgxd)
return ((struct cgx *)cgxd)->mac_ops;
}
+u32 cgx_get_fifo_len(void *cgxd)
+{
+ return ((struct cgx *)cgxd)->fifo_len;
+}
+
void cgx_write(struct cgx *cgx, u64 lmac, u64 offset, u64 val)
{
writeq(val, cgx->reg_base + (lmac << cgx->mac_ops->lmac_offset) +
@@ -209,6 +214,24 @@ u8 cgx_lmac_get_p2x(int cgx_id, int lmac_id)
return (cfg & CMR_P2X_SEL_MASK) >> CMR_P2X_SEL_SHIFT;
}
+static u8 cgx_get_nix_resetbit(struct cgx *cgx)
+{
+ int first_lmac;
+ u8 p2x;
+
+ /* non 98XX silicons supports only NIX0 block */
+ if (cgx->pdev->subsystem_device != PCI_SUBSYS_DEVID_98XX)
+ return CGX_NIX0_RESET;
+
+ first_lmac = find_first_bit(&cgx->lmac_bmap, cgx->max_lmac_per_mac);
+ p2x = cgx_lmac_get_p2x(cgx->cgx_id, first_lmac);
+
+ if (p2x == CMR_P2X_SEL_NIX1)
+ return CGX_NIX1_RESET;
+ else
+ return CGX_NIX0_RESET;
+}
+
/* Ensure the required lock for event queue(where asynchronous events are
* posted) is acquired before calling this API. Else an asynchronous event(with
* latest link status) can reach the destination before this function returns
@@ -501,7 +524,7 @@ static u32 cgx_get_lmac_fifo_len(void *cgxd, int lmac_id)
u8 num_lmacs;
u32 fifo_len;
- fifo_len = cgx->mac_ops->fifo_len;
+ fifo_len = cgx->fifo_len;
num_lmacs = cgx->mac_ops->get_nr_lmacs(cgx);
switch (num_lmacs) {
@@ -1719,6 +1742,8 @@ static int cgx_lmac_init(struct cgx *cgx)
lmac->lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac->lmac_id);
}
+ /* Start X2P reset on given MAC block */
+ cgx->mac_ops->mac_x2p_reset(cgx, true);
return cgx_lmac_verify_fwi_version(cgx);
err_bitmap_free:
@@ -1764,7 +1789,7 @@ static void cgx_populate_features(struct cgx *cgx)
u64 cfg;
cfg = cgx_read(cgx, 0, CGX_CONST);
- cgx->mac_ops->fifo_len = FIELD_GET(CGX_CONST_RXFIFO_SIZE, cfg);
+ cgx->fifo_len = FIELD_GET(CGX_CONST_RXFIFO_SIZE, cfg);
cgx->max_lmac_per_mac = FIELD_GET(CGX_CONST_MAX_LMACS, cfg);
if (is_dev_rpm(cgx))
@@ -1784,6 +1809,45 @@ static u8 cgx_get_rxid_mapoffset(struct cgx *cgx)
return 0x60;
}
+static void cgx_x2p_reset(void *cgxd, bool enable)
+{
+ struct cgx *cgx = cgxd;
+ int lmac_id;
+ u64 cfg;
+
+ if (enable) {
+ for_each_set_bit(lmac_id, &cgx->lmac_bmap, cgx->max_lmac_per_mac)
+ cgx->mac_ops->mac_enadis_rx(cgx, lmac_id, false);
+
+ usleep_range(1000, 2000);
+
+ cfg = cgx_read(cgx, 0, CGXX_CMR_GLOBAL_CONFIG);
+ cfg |= cgx_get_nix_resetbit(cgx) | CGX_NSCI_DROP;
+ cgx_write(cgx, 0, CGXX_CMR_GLOBAL_CONFIG, cfg);
+ } else {
+ cfg = cgx_read(cgx, 0, CGXX_CMR_GLOBAL_CONFIG);
+ cfg &= ~(cgx_get_nix_resetbit(cgx) | CGX_NSCI_DROP);
+ cgx_write(cgx, 0, CGXX_CMR_GLOBAL_CONFIG, cfg);
+ }
+}
+
+static int cgx_enadis_rx(void *cgxd, int lmac_id, bool enable)
+{
+ struct cgx *cgx = cgxd;
+ u64 cfg;
+
+ if (!is_lmac_valid(cgx, lmac_id))
+ return -ENODEV;
+
+ cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_CFG);
+ if (enable)
+ cfg |= DATA_PKT_RX_EN;
+ else
+ cfg &= ~DATA_PKT_RX_EN;
+ cgx_write(cgx, lmac_id, CGXX_CMRX_CFG, cfg);
+ return 0;
+}
+
static struct mac_ops cgx_mac_ops = {
.name = "cgx",
.csr_offset = 0,
@@ -1815,6 +1879,8 @@ static struct mac_ops cgx_mac_ops = {
.mac_get_pfc_frm_cfg = cgx_lmac_get_pfc_frm_cfg,
.mac_reset = cgx_lmac_reset,
.mac_stats_reset = cgx_stats_reset,
+ .mac_x2p_reset = cgx_x2p_reset,
+ .mac_enadis_rx = cgx_enadis_rx,
};
static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
index dc9ace30554a..1cf12e5c7da8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
@@ -32,6 +32,10 @@
#define CGX_LMAC_TYPE_MASK 0xF
#define CGXX_CMRX_INT 0x040
#define FW_CGX_INT BIT_ULL(1)
+#define CGXX_CMR_GLOBAL_CONFIG 0x08
+#define CGX_NIX0_RESET BIT_ULL(2)
+#define CGX_NIX1_RESET BIT_ULL(3)
+#define CGX_NSCI_DROP BIT_ULL(9)
#define CGXX_CMRX_INT_ENA_W1S 0x058
#define CGXX_CMRX_RX_ID_MAP 0x060
#define CGXX_CMRX_RX_STAT0 0x070
@@ -185,4 +189,5 @@ int cgx_lmac_get_pfc_frm_cfg(void *cgxd, int lmac_id, u8 *tx_pause,
int verify_lmac_fc_cfg(void *cgxd, int lmac_id, u8 tx_pause, u8 rx_pause,
int pfvf_idx);
int cgx_lmac_reset(void *cgxd, int lmac_id, u8 pf_req_flr);
+u32 cgx_get_fifo_len(void *cgxd);
#endif /* CGX_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
index 9ffc6790c513..6180e68e1765 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
@@ -72,7 +72,6 @@ struct mac_ops {
u8 irq_offset;
u8 int_ena_bit;
u8 lmac_fwi;
- u32 fifo_len;
bool non_contiguous_serdes_lane;
/* RPM & CGX differs in number of Receive/transmit stats */
u8 rx_stats_cnt;
@@ -133,6 +132,8 @@ struct mac_ops {
int (*get_fec_stats)(void *cgxd, int lmac_id,
struct cgx_fec_stats_rsp *rsp);
int (*mac_stats_reset)(void *cgxd, int lmac_id);
+ void (*mac_x2p_reset)(void *cgxd, bool enable);
+ int (*mac_enadis_rx)(void *cgxd, int lmac_id, bool enable);
};
struct cgx {
@@ -142,6 +143,10 @@ struct cgx {
u8 lmac_count;
/* number of LMACs per MAC could be 4 or 8 */
u8 max_lmac_per_mac;
+ /* length of fifo varies depending on the number
+ * of LMACS
+ */
+ u32 fifo_len;
#define MAX_LMAC_COUNT 8
struct lmac *lmac_idmap[MAX_LMAC_COUNT];
struct work_struct cgx_cmd_work;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
index 1b34cf9c9703..2e9945446199 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
@@ -39,6 +39,8 @@ static struct mac_ops rpm_mac_ops = {
.mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg,
.mac_reset = rpm_lmac_reset,
.mac_stats_reset = rpm_stats_reset,
+ .mac_x2p_reset = rpm_x2p_reset,
+ .mac_enadis_rx = rpm_enadis_rx,
};
static struct mac_ops rpm2_mac_ops = {
@@ -72,6 +74,8 @@ static struct mac_ops rpm2_mac_ops = {
.mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg,
.mac_reset = rpm_lmac_reset,
.mac_stats_reset = rpm_stats_reset,
+ .mac_x2p_reset = rpm_x2p_reset,
+ .mac_enadis_rx = rpm_enadis_rx,
};
bool is_dev_rpm2(void *rpmd)
@@ -467,7 +471,7 @@ u8 rpm_get_lmac_type(void *rpmd, int lmac_id)
int err;
req = FIELD_SET(CMDREG_ID, CGX_CMD_GET_LINK_STS, req);
- err = cgx_fwi_cmd_generic(req, &resp, rpm, 0);
+ err = cgx_fwi_cmd_generic(req, &resp, rpm, lmac_id);
if (!err)
return FIELD_GET(RESP_LINKSTAT_LMAC_TYPE, resp);
return err;
@@ -480,7 +484,7 @@ u32 rpm_get_lmac_fifo_len(void *rpmd, int lmac_id)
u8 num_lmacs;
u32 fifo_len;
- fifo_len = rpm->mac_ops->fifo_len;
+ fifo_len = rpm->fifo_len;
num_lmacs = rpm->mac_ops->get_nr_lmacs(rpm);
switch (num_lmacs) {
@@ -533,9 +537,9 @@ u32 rpm2_get_lmac_fifo_len(void *rpmd, int lmac_id)
*/
max_lmac = (rpm_read(rpm, 0, CGX_CONST) >> 24) & 0xFF;
if (max_lmac > 4)
- fifo_len = rpm->mac_ops->fifo_len / 2;
+ fifo_len = rpm->fifo_len / 2;
else
- fifo_len = rpm->mac_ops->fifo_len;
+ fifo_len = rpm->fifo_len;
if (lmac_id < 4) {
num_lmacs = hweight8(lmac_info & 0xF);
@@ -699,46 +703,51 @@ int rpm_get_fec_stats(void *rpmd, int lmac_id, struct cgx_fec_stats_rsp *rsp)
if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_NONE)
return 0;
+ /* latched registers FCFECX_CW_HI/RSFEC_STAT_FAST_DATA_HI_CDC are common
+ * for all counters. Acquire lock to ensure serialized reads
+ */
+ mutex_lock(&rpm->lock);
if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_BASER) {
- val_lo = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_VL0_CCW_LO);
- val_hi = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_CW_HI);
+ val_lo = rpm_read(rpm, 0, RPMX_MTI_FCFECX_VL0_CCW_LO(lmac_id));
+ val_hi = rpm_read(rpm, 0, RPMX_MTI_FCFECX_CW_HI(lmac_id));
rsp->fec_corr_blks = (val_hi << 16 | val_lo);
- val_lo = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_VL0_NCCW_LO);
- val_hi = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_CW_HI);
+ val_lo = rpm_read(rpm, 0, RPMX_MTI_FCFECX_VL0_NCCW_LO(lmac_id));
+ val_hi = rpm_read(rpm, 0, RPMX_MTI_FCFECX_CW_HI(lmac_id));
rsp->fec_uncorr_blks = (val_hi << 16 | val_lo);
/* 50G uses 2 Physical serdes lines */
if (rpm->lmac_idmap[lmac_id]->link_info.lmac_type_id ==
LMAC_MODE_50G_R) {
- val_lo = rpm_read(rpm, lmac_id,
- RPMX_MTI_FCFECX_VL1_CCW_LO);
- val_hi = rpm_read(rpm, lmac_id,
- RPMX_MTI_FCFECX_CW_HI);
+ val_lo = rpm_read(rpm, 0,
+ RPMX_MTI_FCFECX_VL1_CCW_LO(lmac_id));
+ val_hi = rpm_read(rpm, 0,
+ RPMX_MTI_FCFECX_CW_HI(lmac_id));
rsp->fec_corr_blks += (val_hi << 16 | val_lo);
- val_lo = rpm_read(rpm, lmac_id,
- RPMX_MTI_FCFECX_VL1_NCCW_LO);
- val_hi = rpm_read(rpm, lmac_id,
- RPMX_MTI_FCFECX_CW_HI);
+ val_lo = rpm_read(rpm, 0,
+ RPMX_MTI_FCFECX_VL1_NCCW_LO(lmac_id));
+ val_hi = rpm_read(rpm, 0,
+ RPMX_MTI_FCFECX_CW_HI(lmac_id));
rsp->fec_uncorr_blks += (val_hi << 16 | val_lo);
}
} else {
/* enable RS-FEC capture */
- cfg = rpm_read(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL);
+ cfg = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_STATN_CONTROL);
cfg |= RPMX_RSFEC_RX_CAPTURE | BIT(lmac_id);
- rpm_write(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL, cfg);
+ rpm_write(rpm, 0, RPMX_MTI_RSFEC_STAT_STATN_CONTROL, cfg);
val_lo = rpm_read(rpm, 0,
RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_2);
- val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC);
+ val_hi = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC);
rsp->fec_corr_blks = (val_hi << 32 | val_lo);
val_lo = rpm_read(rpm, 0,
RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_3);
- val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC);
+ val_hi = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC);
rsp->fec_uncorr_blks = (val_hi << 32 | val_lo);
}
+ mutex_unlock(&rpm->lock);
return 0;
}
@@ -763,3 +772,41 @@ int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr)
return 0;
}
+
+void rpm_x2p_reset(void *rpmd, bool enable)
+{
+ rpm_t *rpm = rpmd;
+ int lmac_id;
+ u64 cfg;
+
+ if (enable) {
+ for_each_set_bit(lmac_id, &rpm->lmac_bmap, rpm->max_lmac_per_mac)
+ rpm->mac_ops->mac_enadis_rx(rpm, lmac_id, false);
+
+ usleep_range(1000, 2000);
+
+ cfg = rpm_read(rpm, 0, RPMX_CMR_GLOBAL_CFG);
+ rpm_write(rpm, 0, RPMX_CMR_GLOBAL_CFG, cfg | RPM_NIX0_RESET);
+ } else {
+ cfg = rpm_read(rpm, 0, RPMX_CMR_GLOBAL_CFG);
+ cfg &= ~RPM_NIX0_RESET;
+ rpm_write(rpm, 0, RPMX_CMR_GLOBAL_CFG, cfg);
+ }
+}
+
+int rpm_enadis_rx(void *rpmd, int lmac_id, bool enable)
+{
+ rpm_t *rpm = rpmd;
+ u64 cfg;
+
+ if (!is_lmac_valid(rpm, lmac_id))
+ return -ENODEV;
+
+ cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
+ if (enable)
+ cfg |= RPM_RX_EN;
+ else
+ cfg &= ~RPM_RX_EN;
+ rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
+ return 0;
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
index 34b11deb0f3c..b8d3972e096a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
@@ -17,6 +17,8 @@
/* Registers */
#define RPMX_CMRX_CFG 0x00
+#define RPMX_CMR_GLOBAL_CFG 0x08
+#define RPM_NIX0_RESET BIT_ULL(3)
#define RPMX_RX_TS_PREPEND BIT_ULL(22)
#define RPMX_TX_PTP_1S_SUPPORT BIT_ULL(17)
#define RPMX_CMRX_RX_ID_MAP 0x80
@@ -84,16 +86,18 @@
/* FEC stats */
#define RPMX_MTI_STAT_STATN_CONTROL 0x10018
#define RPMX_MTI_STAT_DATA_HI_CDC 0x10038
-#define RPMX_RSFEC_RX_CAPTURE BIT_ULL(27)
+#define RPMX_RSFEC_RX_CAPTURE BIT_ULL(28)
#define RPMX_CMD_CLEAR_RX BIT_ULL(30)
#define RPMX_CMD_CLEAR_TX BIT_ULL(31)
+#define RPMX_MTI_RSFEC_STAT_STATN_CONTROL 0x40018
+#define RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC 0x40000
#define RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_2 0x40050
#define RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_3 0x40058
-#define RPMX_MTI_FCFECX_VL0_CCW_LO 0x38618
-#define RPMX_MTI_FCFECX_VL0_NCCW_LO 0x38620
-#define RPMX_MTI_FCFECX_VL1_CCW_LO 0x38628
-#define RPMX_MTI_FCFECX_VL1_NCCW_LO 0x38630
-#define RPMX_MTI_FCFECX_CW_HI 0x38638
+#define RPMX_MTI_FCFECX_VL0_CCW_LO(a) (0x38618 + ((a) * 0x40))
+#define RPMX_MTI_FCFECX_VL0_NCCW_LO(a) (0x38620 + ((a) * 0x40))
+#define RPMX_MTI_FCFECX_VL1_CCW_LO(a) (0x38628 + ((a) * 0x40))
+#define RPMX_MTI_FCFECX_VL1_NCCW_LO(a) (0x38630 + ((a) * 0x40))
+#define RPMX_MTI_FCFECX_CW_HI(a) (0x38638 + ((a) * 0x40))
/* CN10KB CSR Declaration */
#define RPM2_CMRX_SW_INT 0x1b0
@@ -137,4 +141,6 @@ bool is_dev_rpm2(void *rpmd);
int rpm_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp);
int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr);
int rpm_stats_reset(void *rpmd, int lmac_id);
+void rpm_x2p_reset(void *rpmd, bool enable);
+int rpm_enadis_rx(void *rpmd, int lmac_id, bool enable);
#endif /* RPM_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
index 1a97fb9032fa..cd0d7b7774f1 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -1162,6 +1162,7 @@ cpt:
}
rvu_program_channels(rvu);
+ cgx_start_linkup(rvu);
err = rvu_mcs_init(rvu);
if (err) {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
index b897845e25fd..a383b5ef5b2d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
@@ -1025,6 +1025,7 @@ int rvu_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_
int rvu_cgx_cfg_pause_frm(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause);
void rvu_mac_reset(struct rvu *rvu, u16 pcifunc);
u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac);
+void cgx_start_linkup(struct rvu *rvu);
int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf,
int type);
bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr,
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
index 266ecbc1b97a..992fa0b82e8d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
@@ -349,6 +349,7 @@ static void rvu_cgx_wq_destroy(struct rvu *rvu)
int rvu_cgx_init(struct rvu *rvu)
{
+ struct mac_ops *mac_ops;
int cgx, err;
void *cgxd;
@@ -375,6 +376,15 @@ int rvu_cgx_init(struct rvu *rvu)
if (err)
return err;
+ /* Clear X2P reset on all MAC blocks */
+ for (cgx = 0; cgx < rvu->cgx_cnt_max; cgx++) {
+ cgxd = rvu_cgx_pdata(cgx, rvu);
+ if (!cgxd)
+ continue;
+ mac_ops = get_mac_ops(cgxd);
+ mac_ops->mac_x2p_reset(cgxd, false);
+ }
+
/* Register for CGX events */
err = cgx_lmac_event_handler_init(rvu);
if (err)
@@ -382,10 +392,26 @@ int rvu_cgx_init(struct rvu *rvu)
mutex_init(&rvu->cgx_cfg_lock);
- /* Ensure event handler registration is completed, before
- * we turn on the links
- */
- mb();
+ return 0;
+}
+
+void cgx_start_linkup(struct rvu *rvu)
+{
+ unsigned long lmac_bmap;
+ struct mac_ops *mac_ops;
+ int cgx, lmac, err;
+ void *cgxd;
+
+ /* Enable receive on all LMACS */
+ for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) {
+ cgxd = rvu_cgx_pdata(cgx, rvu);
+ if (!cgxd)
+ continue;
+ mac_ops = get_mac_ops(cgxd);
+ lmac_bmap = cgx_get_lmac_bmap(cgxd);
+ for_each_set_bit(lmac, &lmac_bmap, rvu->hw->lmac_per_cgx)
+ mac_ops->mac_enadis_rx(cgxd, lmac, true);
+ }
/* Do link up for all CGX ports */
for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) {
@@ -398,8 +424,6 @@ int rvu_cgx_init(struct rvu *rvu)
"Link up process failed to start on cgx %d\n",
cgx);
}
-
- return 0;
}
int rvu_cgx_exit(struct rvu *rvu)
@@ -923,13 +947,12 @@ int rvu_mbox_handler_cgx_features_get(struct rvu *rvu,
u32 rvu_cgx_get_fifolen(struct rvu *rvu)
{
- struct mac_ops *mac_ops;
- u32 fifo_len;
+ void *cgxd = rvu_first_cgx_pdata(rvu);
- mac_ops = get_mac_ops(rvu_first_cgx_pdata(rvu));
- fifo_len = mac_ops ? mac_ops->fifo_len : 0;
+ if (!cgxd)
+ return 0;
- return fifo_len;
+ return cgx_get_fifo_len(cgxd);
}
u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac)
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index fe38426ec42d..2bf426cea6dd 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1394,18 +1394,15 @@ static int pxa168_eth_probe(struct platform_device *pdev)
printk(KERN_NOTICE "PXA168 10/100 Ethernet Driver\n");
- clk = devm_clk_get(&pdev->dev, NULL);
+ clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "Fast Ethernet failed to get clock\n");
+ dev_err(&pdev->dev, "Fast Ethernet failed to get and enable clock\n");
return -ENODEV;
}
- clk_prepare_enable(clk);
dev = alloc_etherdev(sizeof(struct pxa168_eth_private));
- if (!dev) {
- err = -ENOMEM;
- goto err_clk;
- }
+ if (!dev)
+ return -ENOMEM;
platform_set_drvdata(pdev, dev);
pep = netdev_priv(dev);
@@ -1523,8 +1520,6 @@ err_free_mdio:
mdiobus_free(pep->smi_bus);
err_netdev:
free_netdev(dev);
-err_clk:
- clk_disable_unprepare(clk);
return err;
}
@@ -1542,7 +1537,6 @@ static void pxa168_eth_remove(struct platform_device *pdev)
if (dev->phydev)
phy_disconnect(dev->phydev);
- clk_disable_unprepare(pep->clk);
mdiobus_unregister(pep->smi_bus);
mdiobus_free(pep->smi_bus);
unregister_netdev(dev);
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
index 7251121ab196..16eb3de60eb6 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
@@ -366,12 +366,13 @@ static void vcap_api_iterator_init_test(struct kunit *test)
struct vcap_typegroup typegroups[] = {
{ .offset = 0, .width = 2, .value = 2, },
{ .offset = 156, .width = 1, .value = 0, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
struct vcap_typegroup typegroups2[] = {
{ .offset = 0, .width = 3, .value = 4, },
{ .offset = 49, .width = 2, .value = 0, },
{ .offset = 98, .width = 2, .value = 0, },
+ { }
};
vcap_iter_init(&iter, 52, typegroups, 86);
@@ -399,6 +400,7 @@ static void vcap_api_iterator_next_test(struct kunit *test)
{ .offset = 147, .width = 3, .value = 0, },
{ .offset = 196, .width = 2, .value = 0, },
{ .offset = 245, .width = 1, .value = 0, },
+ { }
};
int idx;
@@ -433,7 +435,7 @@ static void vcap_api_encode_typegroups_test(struct kunit *test)
{ .offset = 147, .width = 3, .value = 5, },
{ .offset = 196, .width = 2, .value = 2, },
{ .offset = 245, .width = 5, .value = 27, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
vcap_encode_typegroups(stream, 49, typegroups, false);
@@ -463,6 +465,7 @@ static void vcap_api_encode_bit_test(struct kunit *test)
{ .offset = 147, .width = 3, .value = 5, },
{ .offset = 196, .width = 2, .value = 2, },
{ .offset = 245, .width = 1, .value = 0, },
+ { }
};
vcap_iter_init(&iter, 49, typegroups, 44);
@@ -489,7 +492,7 @@ static void vcap_api_encode_field_test(struct kunit *test)
{ .offset = 147, .width = 3, .value = 5, },
{ .offset = 196, .width = 2, .value = 2, },
{ .offset = 245, .width = 5, .value = 27, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
struct vcap_field rf = {
.type = VCAP_FIELD_U32,
@@ -538,7 +541,7 @@ static void vcap_api_encode_short_field_test(struct kunit *test)
{ .offset = 0, .width = 3, .value = 7, },
{ .offset = 21, .width = 2, .value = 3, },
{ .offset = 42, .width = 1, .value = 1, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
struct vcap_field rf = {
.type = VCAP_FIELD_U32,
@@ -608,7 +611,7 @@ static void vcap_api_encode_keyfield_test(struct kunit *test)
struct vcap_typegroup tgt[] = {
{ .offset = 0, .width = 2, .value = 2, },
{ .offset = 156, .width = 1, .value = 1, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
vcap_test_api_init(&admin);
@@ -671,7 +674,7 @@ static void vcap_api_encode_max_keyfield_test(struct kunit *test)
struct vcap_typegroup tgt[] = {
{ .offset = 0, .width = 2, .value = 2, },
{ .offset = 156, .width = 1, .value = 1, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
u32 keyres[] = {
0x928e8a84,
@@ -732,7 +735,7 @@ static void vcap_api_encode_actionfield_test(struct kunit *test)
{ .offset = 0, .width = 2, .value = 2, },
{ .offset = 21, .width = 1, .value = 1, },
{ .offset = 42, .width = 1, .value = 0, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
vcap_encode_actionfield(&rule, &caf, &rf, tgt);
diff --git a/drivers/net/ethernet/realtek/rtase/rtase.h b/drivers/net/ethernet/realtek/rtase/rtase.h
index 942f1e531a85..dbc3f92eebc4 100644
--- a/drivers/net/ethernet/realtek/rtase/rtase.h
+++ b/drivers/net/ethernet/realtek/rtase/rtase.h
@@ -9,7 +9,10 @@
#ifndef RTASE_H
#define RTASE_H
-#define RTASE_HW_VER_MASK 0x7C800000
+#define RTASE_HW_VER_MASK 0x7C800000
+#define RTASE_HW_VER_906X_7XA 0x00800000
+#define RTASE_HW_VER_906X_7XC 0x04000000
+#define RTASE_HW_VER_907XD_V1 0x04800000
#define RTASE_RX_DMA_BURST_256 4
#define RTASE_TX_DMA_BURST_UNLIMITED 7
@@ -327,6 +330,8 @@ struct rtase_private {
u16 int_nums;
u16 tx_int_mit;
u16 rx_int_mit;
+
+ u32 hw_ver;
};
#define RTASE_LSO_64K 64000
diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c
index 874994d9ceb9..de7f11232593 100644
--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
+++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
@@ -1714,10 +1714,21 @@ static int rtase_get_settings(struct net_device *dev,
struct ethtool_link_ksettings *cmd)
{
u32 supported = SUPPORTED_MII | SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ const struct rtase_private *tp = netdev_priv(dev);
ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
supported);
- cmd->base.speed = SPEED_5000;
+
+ switch (tp->hw_ver) {
+ case RTASE_HW_VER_906X_7XA:
+ case RTASE_HW_VER_906X_7XC:
+ cmd->base.speed = SPEED_5000;
+ break;
+ case RTASE_HW_VER_907XD_V1:
+ cmd->base.speed = SPEED_10000;
+ break;
+ }
+
cmd->base.duplex = DUPLEX_FULL;
cmd->base.port = PORT_MII;
cmd->base.autoneg = AUTONEG_DISABLE;
@@ -1972,20 +1983,21 @@ static void rtase_init_software_variable(struct pci_dev *pdev,
tp->dev->max_mtu = RTASE_MAX_JUMBO_SIZE;
}
-static bool rtase_check_mac_version_valid(struct rtase_private *tp)
+static int rtase_check_mac_version_valid(struct rtase_private *tp)
{
- u32 hw_ver = rtase_r32(tp, RTASE_TX_CONFIG_0) & RTASE_HW_VER_MASK;
- bool known_ver = false;
+ int ret = -ENODEV;
+
+ tp->hw_ver = rtase_r32(tp, RTASE_TX_CONFIG_0) & RTASE_HW_VER_MASK;
- switch (hw_ver) {
- case 0x00800000:
- case 0x04000000:
- case 0x04800000:
- known_ver = true;
+ switch (tp->hw_ver) {
+ case RTASE_HW_VER_906X_7XA:
+ case RTASE_HW_VER_906X_7XC:
+ case RTASE_HW_VER_907XD_V1:
+ ret = 0;
break;
}
- return known_ver;
+ return ret;
}
static int rtase_init_board(struct pci_dev *pdev, struct net_device **dev_out,
@@ -2105,9 +2117,13 @@ static int rtase_init_one(struct pci_dev *pdev,
tp->pdev = pdev;
/* identify chip attached to board */
- if (!rtase_check_mac_version_valid(tp))
- return dev_err_probe(&pdev->dev, -ENODEV,
- "unknown chip version, contact rtase maintainers (see MAINTAINERS file)\n");
+ ret = rtase_check_mac_version_valid(tp);
+ if (ret != 0) {
+ dev_err(&pdev->dev,
+ "unknown chip version: 0x%08x, contact rtase maintainers (see MAINTAINERS file)\n",
+ tp->hw_ver);
+ goto err_out_release_board;
+ }
rtase_init_software_variable(pdev, tp);
rtase_init_hardware(tp);
@@ -2181,6 +2197,7 @@ err_out_del_napi:
netif_napi_del(&ivec->napi);
}
+err_out_release_board:
rtase_release_board(pdev, dev, ioaddr);
return ret;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index 248b30d7b864..16020b72dec8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -487,6 +487,8 @@ static int socfpga_dwmac_probe(struct platform_device *pdev)
plat_dat->select_pcs = socfpga_dwmac_select_pcs;
plat_dat->has_gmac = true;
+ plat_dat->riwt_off = 1;
+
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
return ret;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3cdc3910f3a0..9b262cdad60b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1177,6 +1177,9 @@ static int stmmac_init_phy(struct net_device *dev)
return -ENODEV;
}
+ if (priv->dma_cap.eee)
+ phy_support_eee(phydev);
+
ret = phylink_connect_phy(priv->phylink, phydev);
} else {
fwnode_handle_put(phy_fwnode);
diff --git a/drivers/net/mdio/mdio-ipq4019.c b/drivers/net/mdio/mdio-ipq4019.c
index dd3ed2d6430b..d9a94df482d9 100644
--- a/drivers/net/mdio/mdio-ipq4019.c
+++ b/drivers/net/mdio/mdio-ipq4019.c
@@ -352,8 +352,11 @@ static int ipq4019_mdio_probe(struct platform_device *pdev)
/* The platform resource is provided on the chipset IPQ5018 */
/* This resource is optional */
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (res)
+ if (res) {
priv->eth_ldo_rdy = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->eth_ldo_rdy))
+ return PTR_ERR(priv->eth_ldo_rdy);
+ }
bus->name = "ipq4019_mdio";
bus->read = ipq4019_mdio_read_c22;
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 96d0b3a5a9d3..944ae98ad110 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -1530,7 +1530,7 @@ int genphy_c45_ethtool_get_eee(struct phy_device *phydev,
return ret;
data->eee_enabled = is_enabled;
- data->eee_active = ret;
+ data->eee_active = phydev->eee_active;
linkmode_copy(data->supported, phydev->supported_eee);
return 0;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 4f3e742907cb..0d20b534122b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -990,14 +990,14 @@ static int phy_check_link_status(struct phy_device *phydev)
phydev->state = PHY_RUNNING;
err = genphy_c45_eee_is_active(phydev,
NULL, NULL, NULL);
- if (err <= 0)
- phydev->enable_tx_lpi = false;
- else
- phydev->enable_tx_lpi = phydev->eee_cfg.tx_lpi_enabled;
+ phydev->eee_active = err > 0;
+ phydev->enable_tx_lpi = phydev->eee_cfg.tx_lpi_enabled &&
+ phydev->eee_active;
phy_link_up(phydev);
} else if (!phydev->link && phydev->state != PHY_NOLINK) {
phydev->state = PHY_NOLINK;
+ phydev->eee_active = false;
phydev->enable_tx_lpi = false;
phy_link_down(phydev);
}
@@ -1672,7 +1672,7 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
* phy_ethtool_set_eee_noneg - Adjusts MAC LPI configuration without PHY
* renegotiation
* @phydev: pointer to the target PHY device structure
- * @data: pointer to the ethtool_keee structure containing the new EEE settings
+ * @old_cfg: pointer to the eee_config structure containing the old EEE settings
*
* This function updates the Energy Efficient Ethernet (EEE) configuration
* for cases where only the MAC's Low Power Idle (LPI) configuration changes,
@@ -1683,18 +1683,23 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
* configuration.
*/
static void phy_ethtool_set_eee_noneg(struct phy_device *phydev,
- struct ethtool_keee *data)
+ const struct eee_config *old_cfg)
{
- if (phydev->eee_cfg.tx_lpi_enabled != data->tx_lpi_enabled ||
- phydev->eee_cfg.tx_lpi_timer != data->tx_lpi_timer) {
- eee_to_eeecfg(&phydev->eee_cfg, data);
- phydev->enable_tx_lpi = eeecfg_mac_can_tx_lpi(&phydev->eee_cfg);
- if (phydev->link) {
- phydev->link = false;
- phy_link_down(phydev);
- phydev->link = true;
- phy_link_up(phydev);
- }
+ bool enable_tx_lpi;
+
+ if (!phydev->link)
+ return;
+
+ enable_tx_lpi = phydev->eee_cfg.tx_lpi_enabled && phydev->eee_active;
+
+ if (phydev->enable_tx_lpi != enable_tx_lpi ||
+ phydev->eee_cfg.tx_lpi_timer != old_cfg->tx_lpi_timer) {
+ phydev->enable_tx_lpi = false;
+ phydev->link = false;
+ phy_link_down(phydev);
+ phydev->enable_tx_lpi = enable_tx_lpi;
+ phydev->link = true;
+ phy_link_up(phydev);
}
}
@@ -1707,18 +1712,23 @@ static void phy_ethtool_set_eee_noneg(struct phy_device *phydev,
*/
int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data)
{
+ struct eee_config old_cfg;
int ret;
if (!phydev->drv)
return -EIO;
mutex_lock(&phydev->lock);
+
+ old_cfg = phydev->eee_cfg;
+ eee_to_eeecfg(&phydev->eee_cfg, data);
+
ret = genphy_c45_ethtool_set_eee(phydev, data);
- if (ret >= 0) {
- if (ret == 0)
- phy_ethtool_set_eee_noneg(phydev, data);
- eee_to_eeecfg(&phydev->eee_cfg, data);
- }
+ if (ret == 0)
+ phy_ethtool_set_eee_noneg(phydev, &old_cfg);
+ else if (ret < 0)
+ phydev->eee_cfg = old_cfg;
+
mutex_unlock(&phydev->lock);
return ret < 0 ? ret : 0;
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index 8adf77e3557e..531b1b6a37d1 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -1652,13 +1652,13 @@ static int lan78xx_set_wol(struct net_device *netdev,
struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
int ret;
+ if (wol->wolopts & ~WAKE_ALL)
+ return -EINVAL;
+
ret = usb_autopm_get_interface(dev->intf);
if (ret < 0)
return ret;
- if (wol->wolopts & ~WAKE_ALL)
- return -EINVAL;
-
pdata->wol = wol->wolopts;
device_set_wakeup_enable(&dev->udev->dev, (bool)wol->wolopts);
@@ -2380,6 +2380,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
if (dev->chipid == ID_REV_CHIP_ID_7801_) {
if (phy_is_pseudo_fixed_link(phydev)) {
fixed_phy_unregister(phydev);
+ phy_device_free(phydev);
} else {
phy_unregister_fixup_for_uid(PHY_KSZ9031RNX,
0xfffffff0);
@@ -4246,8 +4247,10 @@ static void lan78xx_disconnect(struct usb_interface *intf)
phy_disconnect(net->phydev);
- if (phy_is_pseudo_fixed_link(phydev))
+ if (phy_is_pseudo_fixed_link(phydev)) {
fixed_phy_unregister(phydev);
+ phy_device_free(phydev);
+ }
usb_scuttle_anchored_urbs(&dev->deferred);
@@ -4414,29 +4417,30 @@ static int lan78xx_probe(struct usb_interface *intf,
period = ep_intr->desc.bInterval;
maxp = usb_maxpacket(dev->udev, dev->pipe_intr);
- buf = kmalloc(maxp, GFP_KERNEL);
- if (!buf) {
+
+ dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->urb_intr) {
ret = -ENOMEM;
goto out5;
}
- dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL);
- if (!dev->urb_intr) {
+ buf = kmalloc(maxp, GFP_KERNEL);
+ if (!buf) {
ret = -ENOMEM;
- goto out6;
- } else {
- usb_fill_int_urb(dev->urb_intr, dev->udev,
- dev->pipe_intr, buf, maxp,
- intr_complete, dev, period);
- dev->urb_intr->transfer_flags |= URB_FREE_BUFFER;
+ goto free_urbs;
}
+ usb_fill_int_urb(dev->urb_intr, dev->udev,
+ dev->pipe_intr, buf, maxp,
+ intr_complete, dev, period);
+ dev->urb_intr->transfer_flags |= URB_FREE_BUFFER;
+
dev->maxpacket = usb_maxpacket(dev->udev, dev->pipe_out);
/* Reject broken descriptors. */
if (dev->maxpacket == 0) {
ret = -ENODEV;
- goto out6;
+ goto free_urbs;
}
/* driver requires remote-wakeup capability during autosuspend. */
@@ -4444,7 +4448,7 @@ static int lan78xx_probe(struct usb_interface *intf,
ret = lan78xx_phy_init(dev);
if (ret < 0)
- goto out7;
+ goto free_urbs;
ret = register_netdev(netdev);
if (ret != 0) {
@@ -4466,10 +4470,8 @@ static int lan78xx_probe(struct usb_interface *intf,
out8:
phy_disconnect(netdev->phydev);
-out7:
+free_urbs:
usb_free_urb(dev->urb_intr);
-out6:
- kfree(buf);
out5:
lan78xx_unbind(dev, intf);
out4:
diff --git a/drivers/nvdimm/virtio_pmem.c b/drivers/nvdimm/virtio_pmem.c
index c9b97aeabf85..2396d19ce549 100644
--- a/drivers/nvdimm/virtio_pmem.c
+++ b/drivers/nvdimm/virtio_pmem.c
@@ -143,6 +143,28 @@ static void virtio_pmem_remove(struct virtio_device *vdev)
virtio_reset_device(vdev);
}
+static int virtio_pmem_freeze(struct virtio_device *vdev)
+{
+ vdev->config->del_vqs(vdev);
+ virtio_reset_device(vdev);
+
+ return 0;
+}
+
+static int virtio_pmem_restore(struct virtio_device *vdev)
+{
+ int ret;
+
+ ret = init_vq(vdev->priv);
+ if (ret) {
+ dev_err(&vdev->dev, "failed to initialize virtio pmem's vq\n");
+ return ret;
+ }
+ virtio_device_ready(vdev);
+
+ return 0;
+}
+
static unsigned int features[] = {
VIRTIO_PMEM_F_SHMEM_REGION,
};
@@ -155,6 +177,8 @@ static struct virtio_driver virtio_pmem_driver = {
.validate = virtio_pmem_validate,
.probe = virtio_pmem_probe,
.remove = virtio_pmem_remove,
+ .freeze = virtio_pmem_freeze,
+ .restore = virtio_pmem_restore,
};
module_virtio_driver(virtio_pmem_driver);
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 1a8d32a4a5c3..40e7be3b0339 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1305,9 +1305,10 @@ static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
queue_delayed_work(nvme_wq, &ctrl->ka_work, delay);
}
-static void nvme_keep_alive_finish(struct request *rq,
- blk_status_t status, struct nvme_ctrl *ctrl)
+static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
+ blk_status_t status)
{
+ struct nvme_ctrl *ctrl = rq->end_io_data;
unsigned long rtt = jiffies - (rq->deadline - rq->timeout);
unsigned long delay = nvme_keep_alive_work_period(ctrl);
enum nvme_ctrl_state state = nvme_ctrl_state(ctrl);
@@ -1324,17 +1325,20 @@ static void nvme_keep_alive_finish(struct request *rq,
delay = 0;
}
+ blk_mq_free_request(rq);
+
if (status) {
dev_err(ctrl->device,
"failed nvme_keep_alive_end_io error=%d\n",
status);
- return;
+ return RQ_END_IO_NONE;
}
ctrl->ka_last_check_time = jiffies;
ctrl->comp_seen = false;
if (state == NVME_CTRL_LIVE || state == NVME_CTRL_CONNECTING)
queue_delayed_work(nvme_wq, &ctrl->ka_work, delay);
+ return RQ_END_IO_NONE;
}
static void nvme_keep_alive_work(struct work_struct *work)
@@ -1343,7 +1347,6 @@ static void nvme_keep_alive_work(struct work_struct *work)
struct nvme_ctrl, ka_work);
bool comp_seen = ctrl->comp_seen;
struct request *rq;
- blk_status_t status;
ctrl->ka_last_check_time = jiffies;
@@ -1366,9 +1369,9 @@ static void nvme_keep_alive_work(struct work_struct *work)
nvme_init_request(rq, &ctrl->ka_cmd);
rq->timeout = ctrl->kato * HZ;
- status = blk_execute_rq(rq, false);
- nvme_keep_alive_finish(rq, status, ctrl);
- blk_mq_free_request(rq);
+ rq->end_io = nvme_keep_alive_end_io;
+ rq->end_io_data = ctrl;
+ blk_execute_rq_nowait(rq, false);
}
static void nvme_start_keep_alive(struct nvme_ctrl *ctrl)
@@ -4600,6 +4603,11 @@ EXPORT_SYMBOL_GPL(nvme_alloc_admin_tag_set);
void nvme_remove_admin_tag_set(struct nvme_ctrl *ctrl)
{
+ /*
+ * As we're about to destroy the queue and free tagset
+ * we can not have keep-alive work running.
+ */
+ nvme_stop_keep_alive(ctrl);
blk_mq_destroy_queue(ctrl->admin_q);
blk_put_queue(ctrl->admin_q);
if (ctrl->ops->flags & NVME_F_FABRICS) {
diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index 6522ae16531c..e8930146847a 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -120,12 +120,20 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
struct nvme_ns *ns = q->queuedata;
struct block_device *bdev = ns ? ns->disk->part0 : NULL;
bool supports_metadata = bdev && blk_get_integrity(bdev->bd_disk);
+ struct nvme_ctrl *ctrl = nvme_req(req)->ctrl;
bool has_metadata = meta_buffer && meta_len;
struct bio *bio = NULL;
int ret;
- if (has_metadata && !supports_metadata)
- return -EINVAL;
+ if (!nvme_ctrl_sgl_supported(ctrl))
+ dev_warn_once(ctrl->device, "using unchecked data buffer\n");
+ if (has_metadata) {
+ if (!supports_metadata)
+ return -EINVAL;
+ if (!nvme_ctrl_meta_sgl_supported(ctrl))
+ dev_warn_once(ctrl->device,
+ "using unchecked metadata buffer\n");
+ }
if (ioucmd && (ioucmd->flags & IORING_URING_CMD_FIXED)) {
struct iov_iter iter;
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index f04cfe3fb936..a85d190942bd 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -165,7 +165,8 @@ void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
if (!ns->head->disk)
continue;
kblockd_schedule_work(&ns->head->requeue_work);
@@ -209,7 +210,8 @@ void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
nvme_mpath_clear_current_path(ns);
kblockd_schedule_work(&ns->head->requeue_work);
}
@@ -224,7 +226,8 @@ void nvme_mpath_revalidate_paths(struct nvme_ns *ns)
int srcu_idx;
srcu_idx = srcu_read_lock(&head->srcu);
- list_for_each_entry_rcu(ns, &head->list, siblings) {
+ list_for_each_entry_srcu(ns, &head->list, siblings,
+ srcu_read_lock_held(&head->srcu)) {
if (capacity != get_capacity(ns->disk))
clear_bit(NVME_NS_READY, &ns->flags);
}
@@ -257,7 +260,8 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node)
int found_distance = INT_MAX, fallback_distance = INT_MAX, distance;
struct nvme_ns *found = NULL, *fallback = NULL, *ns;
- list_for_each_entry_rcu(ns, &head->list, siblings) {
+ list_for_each_entry_srcu(ns, &head->list, siblings,
+ srcu_read_lock_held(&head->srcu)) {
if (nvme_path_is_disabled(ns))
continue;
@@ -356,7 +360,8 @@ static struct nvme_ns *nvme_queue_depth_path(struct nvme_ns_head *head)
unsigned int min_depth_opt = UINT_MAX, min_depth_nonopt = UINT_MAX;
unsigned int depth;
- list_for_each_entry_rcu(ns, &head->list, siblings) {
+ list_for_each_entry_srcu(ns, &head->list, siblings,
+ srcu_read_lock_held(&head->srcu)) {
if (nvme_path_is_disabled(ns))
continue;
@@ -424,7 +429,8 @@ static bool nvme_available_path(struct nvme_ns_head *head)
if (!test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags))
return NULL;
- list_for_each_entry_rcu(ns, &head->list, siblings) {
+ list_for_each_entry_srcu(ns, &head->list, siblings,
+ srcu_read_lock_held(&head->srcu)) {
if (test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ns->ctrl->flags))
continue;
switch (nvme_ctrl_state(ns->ctrl)) {
@@ -783,7 +789,8 @@ static int nvme_update_ana_state(struct nvme_ctrl *ctrl,
return 0;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
unsigned nsid;
again:
nsid = le32_to_cpu(desc->nsids[n]);
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 900719c4c70c..611b02c8a8b3 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -1123,7 +1123,15 @@ static inline void nvme_start_request(struct request *rq)
static inline bool nvme_ctrl_sgl_supported(struct nvme_ctrl *ctrl)
{
- return ctrl->sgls & ((1 << 0) | (1 << 1));
+ return ctrl->sgls & (NVME_CTRL_SGLS_BYTE_ALIGNED |
+ NVME_CTRL_SGLS_DWORD_ALIGNED);
+}
+
+static inline bool nvme_ctrl_meta_sgl_supported(struct nvme_ctrl *ctrl)
+{
+ if (ctrl->ops->flags & NVME_F_FABRICS)
+ return true;
+ return ctrl->sgls & NVME_CTRL_SGLS_MSDS;
}
#ifdef CONFIG_NVME_HOST_AUTH
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 5f2e3ad2cc52..4c644bb7f069 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -43,6 +43,7 @@
*/
#define NVME_MAX_KB_SZ 8192
#define NVME_MAX_SEGS 128
+#define NVME_MAX_META_SEGS 15
#define NVME_MAX_NR_ALLOCATIONS 5
static int use_threaded_interrupts;
@@ -144,6 +145,7 @@ struct nvme_dev {
struct sg_table *hmb_sgt;
mempool_t *iod_mempool;
+ mempool_t *iod_meta_mempool;
/* shadow doorbell buffer support: */
__le32 *dbbuf_dbs;
@@ -239,6 +241,8 @@ struct nvme_iod {
dma_addr_t first_dma;
dma_addr_t meta_dma;
struct sg_table sgt;
+ struct sg_table meta_sgt;
+ union nvme_descriptor meta_list;
union nvme_descriptor list[NVME_MAX_NR_ALLOCATIONS];
};
@@ -506,6 +510,15 @@ static void nvme_commit_rqs(struct blk_mq_hw_ctx *hctx)
spin_unlock(&nvmeq->sq_lock);
}
+static inline bool nvme_pci_metadata_use_sgls(struct nvme_dev *dev,
+ struct request *req)
+{
+ if (!nvme_ctrl_meta_sgl_supported(&dev->ctrl))
+ return false;
+ return req->nr_integrity_segments > 1 ||
+ nvme_req(req)->flags & NVME_REQ_USERCMD;
+}
+
static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req,
int nseg)
{
@@ -518,8 +531,10 @@ static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req,
return false;
if (!nvmeq->qid)
return false;
+ if (nvme_pci_metadata_use_sgls(dev, req))
+ return true;
if (!sgl_threshold || avg_seg_size < sgl_threshold)
- return false;
+ return nvme_req(req)->flags & NVME_REQ_USERCMD;
return true;
}
@@ -780,7 +795,8 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
struct bio_vec bv = req_bvec(req);
if (!is_pci_p2pdma_page(bv.bv_page)) {
- if ((bv.bv_offset & (NVME_CTRL_PAGE_SIZE - 1)) +
+ if (!nvme_pci_metadata_use_sgls(dev, req) &&
+ (bv.bv_offset & (NVME_CTRL_PAGE_SIZE - 1)) +
bv.bv_len <= NVME_CTRL_PAGE_SIZE * 2)
return nvme_setup_prp_simple(dev, req,
&cmnd->rw, &bv);
@@ -824,11 +840,69 @@ out_free_sg:
return ret;
}
-static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req,
- struct nvme_command *cmnd)
+static blk_status_t nvme_pci_setup_meta_sgls(struct nvme_dev *dev,
+ struct request *req)
+{
+ struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+ struct nvme_rw_command *cmnd = &iod->cmd.rw;
+ struct nvme_sgl_desc *sg_list;
+ struct scatterlist *sgl, *sg;
+ unsigned int entries;
+ dma_addr_t sgl_dma;
+ int rc, i;
+
+ iod->meta_sgt.sgl = mempool_alloc(dev->iod_meta_mempool, GFP_ATOMIC);
+ if (!iod->meta_sgt.sgl)
+ return BLK_STS_RESOURCE;
+
+ sg_init_table(iod->meta_sgt.sgl, req->nr_integrity_segments);
+ iod->meta_sgt.orig_nents = blk_rq_map_integrity_sg(req,
+ iod->meta_sgt.sgl);
+ if (!iod->meta_sgt.orig_nents)
+ goto out_free_sg;
+
+ rc = dma_map_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req),
+ DMA_ATTR_NO_WARN);
+ if (rc)
+ goto out_free_sg;
+
+ sg_list = dma_pool_alloc(dev->prp_small_pool, GFP_ATOMIC, &sgl_dma);
+ if (!sg_list)
+ goto out_unmap_sg;
+
+ entries = iod->meta_sgt.nents;
+ iod->meta_list.sg_list = sg_list;
+ iod->meta_dma = sgl_dma;
+
+ cmnd->flags = NVME_CMD_SGL_METASEG;
+ cmnd->metadata = cpu_to_le64(sgl_dma);
+
+ sgl = iod->meta_sgt.sgl;
+ if (entries == 1) {
+ nvme_pci_sgl_set_data(sg_list, sgl);
+ return BLK_STS_OK;
+ }
+
+ sgl_dma += sizeof(*sg_list);
+ nvme_pci_sgl_set_seg(sg_list, sgl_dma, entries);
+ for_each_sg(sgl, sg, entries, i)
+ nvme_pci_sgl_set_data(&sg_list[i + 1], sg);
+
+ return BLK_STS_OK;
+
+out_unmap_sg:
+ dma_unmap_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req), 0);
+out_free_sg:
+ mempool_free(iod->meta_sgt.sgl, dev->iod_meta_mempool);
+ return BLK_STS_RESOURCE;
+}
+
+static blk_status_t nvme_pci_setup_meta_mptr(struct nvme_dev *dev,
+ struct request *req)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
struct bio_vec bv = rq_integrity_vec(req);
+ struct nvme_command *cmnd = &iod->cmd;
iod->meta_dma = dma_map_bvec(dev->dev, &bv, rq_dma_dir(req), 0);
if (dma_mapping_error(dev->dev, iod->meta_dma))
@@ -837,6 +911,13 @@ static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req,
return BLK_STS_OK;
}
+static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req)
+{
+ if (nvme_pci_metadata_use_sgls(dev, req))
+ return nvme_pci_setup_meta_sgls(dev, req);
+ return nvme_pci_setup_meta_mptr(dev, req);
+}
+
static blk_status_t nvme_prep_rq(struct nvme_dev *dev, struct request *req)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
@@ -845,6 +926,7 @@ static blk_status_t nvme_prep_rq(struct nvme_dev *dev, struct request *req)
iod->aborted = false;
iod->nr_allocations = -1;
iod->sgt.nents = 0;
+ iod->meta_sgt.nents = 0;
ret = nvme_setup_cmd(req->q->queuedata, req);
if (ret)
@@ -857,7 +939,7 @@ static blk_status_t nvme_prep_rq(struct nvme_dev *dev, struct request *req)
}
if (blk_integrity_rq(req)) {
- ret = nvme_map_metadata(dev, req, &iod->cmd);
+ ret = nvme_map_metadata(dev, req);
if (ret)
goto out_unmap_data;
}
@@ -955,17 +1037,31 @@ static void nvme_queue_rqs(struct rq_list *rqlist)
*rqlist = requeue_list;
}
+static __always_inline void nvme_unmap_metadata(struct nvme_dev *dev,
+ struct request *req)
+{
+ struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+
+ if (!iod->meta_sgt.nents) {
+ dma_unmap_page(dev->dev, iod->meta_dma,
+ rq_integrity_vec(req).bv_len,
+ rq_dma_dir(req));
+ return;
+ }
+
+ dma_pool_free(dev->prp_small_pool, iod->meta_list.sg_list,
+ iod->meta_dma);
+ dma_unmap_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req), 0);
+ mempool_free(iod->meta_sgt.sgl, dev->iod_meta_mempool);
+}
+
static __always_inline void nvme_pci_unmap_rq(struct request *req)
{
struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
struct nvme_dev *dev = nvmeq->dev;
- if (blk_integrity_rq(req)) {
- struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
-
- dma_unmap_page(dev->dev, iod->meta_dma,
- rq_integrity_vec(req).bv_len, rq_dma_dir(req));
- }
+ if (blk_integrity_rq(req))
+ nvme_unmap_metadata(dev, req);
if (blk_rq_nr_phys_segments(req))
nvme_unmap_data(dev, req);
@@ -2761,6 +2857,7 @@ static void nvme_release_prp_pools(struct nvme_dev *dev)
static int nvme_pci_alloc_iod_mempool(struct nvme_dev *dev)
{
+ size_t meta_size = sizeof(struct scatterlist) * (NVME_MAX_META_SEGS + 1);
size_t alloc_size = sizeof(struct scatterlist) * NVME_MAX_SEGS;
dev->iod_mempool = mempool_create_node(1,
@@ -2769,7 +2866,18 @@ static int nvme_pci_alloc_iod_mempool(struct nvme_dev *dev)
dev_to_node(dev->dev));
if (!dev->iod_mempool)
return -ENOMEM;
+
+ dev->iod_meta_mempool = mempool_create_node(1,
+ mempool_kmalloc, mempool_kfree,
+ (void *)meta_size, GFP_KERNEL,
+ dev_to_node(dev->dev));
+ if (!dev->iod_meta_mempool)
+ goto free;
+
return 0;
+free:
+ mempool_destroy(dev->iod_mempool);
+ return -ENOMEM;
}
static void nvme_free_tagset(struct nvme_dev *dev)
@@ -2834,6 +2942,11 @@ static void nvme_reset_work(struct work_struct *work)
if (result)
goto out;
+ if (nvme_ctrl_meta_sgl_supported(&dev->ctrl))
+ dev->ctrl.max_integrity_segments = NVME_MAX_META_SEGS;
+ else
+ dev->ctrl.max_integrity_segments = 1;
+
nvme_dbbuf_dma_alloc(dev);
result = nvme_setup_host_mem(dev);
@@ -3101,11 +3214,6 @@ static struct nvme_dev *nvme_pci_alloc_dev(struct pci_dev *pdev,
dev->ctrl.max_hw_sectors = min_t(u32,
NVME_MAX_KB_SZ << 1, dma_opt_mapping_size(&pdev->dev) >> 9);
dev->ctrl.max_segments = NVME_MAX_SEGS;
-
- /*
- * There is no support for SGLs for metadata (yet), so we are limited to
- * a single integrity segment for the separate metadata pointer.
- */
dev->ctrl.max_integrity_segments = 1;
return dev;
@@ -3168,6 +3276,11 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (result)
goto out_disable;
+ if (nvme_ctrl_meta_sgl_supported(&dev->ctrl))
+ dev->ctrl.max_integrity_segments = NVME_MAX_META_SEGS;
+ else
+ dev->ctrl.max_integrity_segments = 1;
+
nvme_dbbuf_dma_alloc(dev);
result = nvme_setup_host_mem(dev);
@@ -3210,6 +3323,7 @@ out_disable:
nvme_free_queues(dev, 0);
out_release_iod_mempool:
mempool_destroy(dev->iod_mempool);
+ mempool_destroy(dev->iod_meta_mempool);
out_release_prp_pools:
nvme_release_prp_pools(dev);
out_dev_unmap:
@@ -3275,6 +3389,7 @@ static void nvme_remove(struct pci_dev *pdev)
nvme_dbbuf_dma_free(dev);
nvme_free_queues(dev, 0);
mempool_destroy(dev->iod_mempool);
+ mempool_destroy(dev->iod_meta_mempool);
nvme_release_prp_pools(dev);
nvme_dev_unmap(dev);
nvme_uninit_ctrl(&dev->ctrl);
diff --git a/drivers/nvme/host/pr.c b/drivers/nvme/host/pr.c
index dc7922f22600..cf2d2c5039dd 100644
--- a/drivers/nvme/host/pr.c
+++ b/drivers/nvme/host/pr.c
@@ -94,109 +94,137 @@ static int nvme_status_to_pr_err(int status)
}
}
-static int nvme_send_pr_command(struct block_device *bdev,
- struct nvme_command *c, void *data, unsigned int data_len)
+static int __nvme_send_pr_command(struct block_device *bdev, u32 cdw10,
+ u32 cdw11, u8 op, void *data, unsigned int data_len)
{
- if (nvme_disk_is_ns_head(bdev->bd_disk))
- return nvme_send_ns_head_pr_command(bdev, c, data, data_len);
+ struct nvme_command c = { 0 };
- return nvme_send_ns_pr_command(bdev->bd_disk->private_data, c, data,
- data_len);
+ c.common.opcode = op;
+ c.common.cdw10 = cpu_to_le32(cdw10);
+ c.common.cdw11 = cpu_to_le32(cdw11);
+
+ if (nvme_disk_is_ns_head(bdev->bd_disk))
+ return nvme_send_ns_head_pr_command(bdev, &c, data, data_len);
+ return nvme_send_ns_pr_command(bdev->bd_disk->private_data, &c,
+ data, data_len);
}
-static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
- u64 key, u64 sa_key, u8 op)
+static int nvme_send_pr_command(struct block_device *bdev, u32 cdw10, u32 cdw11,
+ u8 op, void *data, unsigned int data_len)
{
- struct nvme_command c = { };
- u8 data[16] = { 0, };
int ret;
- put_unaligned_le64(key, &data[0]);
- put_unaligned_le64(sa_key, &data[8]);
-
- c.common.opcode = op;
- c.common.cdw10 = cpu_to_le32(cdw10);
-
- ret = nvme_send_pr_command(bdev, &c, data, sizeof(data));
- if (ret < 0)
- return ret;
-
- return nvme_status_to_pr_err(ret);
+ ret = __nvme_send_pr_command(bdev, cdw10, cdw11, op, data, data_len);
+ return ret < 0 ? ret : nvme_status_to_pr_err(ret);
}
-static int nvme_pr_register(struct block_device *bdev, u64 old,
- u64 new, unsigned flags)
+static int nvme_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
+ unsigned int flags)
{
+ struct nvmet_pr_register_data data = { 0 };
u32 cdw10;
if (flags & ~PR_FL_IGNORE_KEY)
return -EOPNOTSUPP;
- cdw10 = old ? 2 : 0;
- cdw10 |= (flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0;
- cdw10 |= (1 << 30) | (1 << 31); /* PTPL=1 */
- return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_register);
+ data.crkey = cpu_to_le64(old_key);
+ data.nrkey = cpu_to_le64(new_key);
+
+ cdw10 = old_key ? NVME_PR_REGISTER_ACT_REPLACE :
+ NVME_PR_REGISTER_ACT_REG;
+ cdw10 |= (flags & PR_FL_IGNORE_KEY) ? NVME_PR_IGNORE_KEY : 0;
+ cdw10 |= NVME_PR_CPTPL_PERSIST;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_register,
+ &data, sizeof(data));
}
static int nvme_pr_reserve(struct block_device *bdev, u64 key,
enum pr_type type, unsigned flags)
{
+ struct nvmet_pr_acquire_data data = { 0 };
u32 cdw10;
if (flags & ~PR_FL_IGNORE_KEY)
return -EOPNOTSUPP;
- cdw10 = nvme_pr_type_from_blk(type) << 8;
- cdw10 |= ((flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_acquire);
+ data.crkey = cpu_to_le64(key);
+
+ cdw10 = NVME_PR_ACQUIRE_ACT_ACQUIRE;
+ cdw10 |= nvme_pr_type_from_blk(type) << 8;
+ cdw10 |= (flags & PR_FL_IGNORE_KEY) ? NVME_PR_IGNORE_KEY : 0;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_acquire,
+ &data, sizeof(data));
}
static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new,
enum pr_type type, bool abort)
{
- u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (abort ? 2 : 1);
+ struct nvmet_pr_acquire_data data = { 0 };
+ u32 cdw10;
+
+ data.crkey = cpu_to_le64(old);
+ data.prkey = cpu_to_le64(new);
- return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire);
+ cdw10 = abort ? NVME_PR_ACQUIRE_ACT_PREEMPT_AND_ABORT :
+ NVME_PR_ACQUIRE_ACT_PREEMPT;
+ cdw10 |= nvme_pr_type_from_blk(type) << 8;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_acquire,
+ &data, sizeof(data));
}
static int nvme_pr_clear(struct block_device *bdev, u64 key)
{
- u32 cdw10 = 1 | (key ? 0 : 1 << 3);
+ struct nvmet_pr_release_data data = { 0 };
+ u32 cdw10;
+
+ data.crkey = cpu_to_le64(key);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+ cdw10 = NVME_PR_RELEASE_ACT_CLEAR;
+ cdw10 |= key ? 0 : NVME_PR_IGNORE_KEY;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_release,
+ &data, sizeof(data));
}
static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
{
- u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (key ? 0 : 1 << 3);
+ struct nvmet_pr_release_data data = { 0 };
+ u32 cdw10;
+
+ data.crkey = cpu_to_le64(key);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+ cdw10 = NVME_PR_RELEASE_ACT_RELEASE;
+ cdw10 |= nvme_pr_type_from_blk(type) << 8;
+ cdw10 |= key ? 0 : NVME_PR_IGNORE_KEY;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_release,
+ &data, sizeof(data));
}
static int nvme_pr_resv_report(struct block_device *bdev, void *data,
u32 data_len, bool *eds)
{
- struct nvme_command c = { };
+ u32 cdw10, cdw11;
int ret;
- c.common.opcode = nvme_cmd_resv_report;
- c.common.cdw10 = cpu_to_le32(nvme_bytes_to_numd(data_len));
- c.common.cdw11 = cpu_to_le32(NVME_EXTENDED_DATA_STRUCT);
+ cdw10 = nvme_bytes_to_numd(data_len);
+ cdw11 = NVME_EXTENDED_DATA_STRUCT;
*eds = true;
retry:
- ret = nvme_send_pr_command(bdev, &c, data, data_len);
+ ret = __nvme_send_pr_command(bdev, cdw10, cdw11, nvme_cmd_resv_report,
+ data, data_len);
if (ret == NVME_SC_HOST_ID_INCONSIST &&
- c.common.cdw11 == cpu_to_le32(NVME_EXTENDED_DATA_STRUCT)) {
- c.common.cdw11 = 0;
+ cdw11 == NVME_EXTENDED_DATA_STRUCT) {
+ cdw11 = 0;
*eds = false;
goto retry;
}
- if (ret < 0)
- return ret;
-
- return nvme_status_to_pr_err(ret);
+ return ret < 0 ? ret : nvme_status_to_pr_err(ret);
}
static int nvme_pr_read_keys(struct block_device *bdev,
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 24a2759798d0..baf7d2490152 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -1019,7 +1019,7 @@ static int nvme_rdma_setup_ctrl(struct nvme_rdma_ctrl *ctrl, bool new)
goto destroy_admin;
}
- if (!(ctrl->ctrl.sgls & (1 << 2))) {
+ if (!(ctrl->ctrl.sgls & NVME_CTRL_SGLS_KSDBDS)) {
ret = -EOPNOTSUPP;
dev_err(ctrl->ctrl.device,
"Mandatory keyed sgls are not supported!\n");
@@ -1051,7 +1051,7 @@ static int nvme_rdma_setup_ctrl(struct nvme_rdma_ctrl *ctrl, bool new)
ctrl->ctrl.sqsize = ctrl->ctrl.maxcmd - 1;
}
- if (ctrl->ctrl.sgls & (1 << 20))
+ if (ctrl->ctrl.sgls & NVME_CTRL_SGLS_SAOS)
ctrl->use_inline_data = true;
if (ctrl->ctrl.queue_count > 1) {
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index 934b401fbc2f..4fa8496a4d96 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -601,11 +601,12 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
id->awun = 0;
id->awupf = 0;
- id->sgls = cpu_to_le32(1 << 0); /* we always support SGLs */
+ /* we always support SGLs */
+ id->sgls = cpu_to_le32(NVME_CTRL_SGLS_BYTE_ALIGNED);
if (ctrl->ops->flags & NVMF_KEYED_SGLS)
- id->sgls |= cpu_to_le32(1 << 2);
+ id->sgls |= cpu_to_le32(NVME_CTRL_SGLS_KSDBDS);
if (req->port->inline_data_size)
- id->sgls |= cpu_to_le32(1 << 20);
+ id->sgls |= cpu_to_le32(NVME_CTRL_SGLS_SAOS);
strscpy(id->subnqn, ctrl->subsys->subsysnqn, sizeof(id->subnqn));
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index d2c384f58028..8671b7c974b9 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -246,6 +246,17 @@ config NVMEM_RAVE_SP_EEPROM
help
Say y here to enable Rave SP EEPROM support.
+config NVMEM_RCAR_EFUSE
+ tristate "Renesas R-Car Gen4 E-FUSE support"
+ depends on (ARCH_RENESAS && ARM64) || COMPILE_TEST
+ depends on NVMEM
+ help
+ Enable support for reading the fuses in the E-FUSE or OTP
+ non-volatile memory block on Renesas R-Car Gen4 SoCs.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-rcar-efuse.
+
config NVMEM_RMEM
tristate "Reserved Memory Based Driver Support"
depends on HAS_IOMEM
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index cdd01fbf1313..5b77bbb6488b 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -52,6 +52,8 @@ obj-$(CONFIG_NVMEM_QCOM_SEC_QFPROM) += nvmem_sec_qfprom.o
nvmem_sec_qfprom-y := sec-qfprom.o
obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
+obj-$(CONFIG_NVMEM_RCAR_EFUSE) += nvmem-rcar-efuse.o
+nvmem-rcar-efuse-y := rcar-efuse.o
obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o
nvmem-rmem-y := rmem.o
obj-$(CONFIG_NVMEM_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
diff --git a/drivers/nvmem/brcm_nvram.c b/drivers/nvmem/brcm_nvram.c
index 3d8c87835f4d..b810df727b44 100644
--- a/drivers/nvmem/brcm_nvram.c
+++ b/drivers/nvmem/brcm_nvram.c
@@ -22,7 +22,7 @@
*
* @dev: NVMEM device pointer
* @nvmem_size: Size of the whole space available for NVRAM
- * @data: NVRAM data copy stored to avoid poking underlaying flash controller
+ * @data: NVRAM data copy stored to avoid poking underlying flash controller
* @data_len: NVRAM data size
* @padding_byte: Padding value used to fill remaining space
* @cells: Array of discovered NVMEM cells
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 33ffa2aa4c11..d6494dfc20a7 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -267,7 +267,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
count = round_down(count, nvmem->word_size);
- if (!nvmem->reg_write)
+ if (!nvmem->reg_write || nvmem->read_only)
return -EPERM;
rc = nvmem_reg_write(nvmem, pos, buf, count);
@@ -298,16 +298,25 @@ static umode_t nvmem_bin_attr_get_umode(struct nvmem_device *nvmem)
}
static umode_t nvmem_bin_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *attr, int i)
+ const struct bin_attribute *attr,
+ int i)
{
struct device *dev = kobj_to_dev(kobj);
struct nvmem_device *nvmem = to_nvmem_device(dev);
- attr->size = nvmem->size;
-
return nvmem_bin_attr_get_umode(nvmem);
}
+static size_t nvmem_bin_attr_size(struct kobject *kobj,
+ const struct bin_attribute *attr,
+ int i)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct nvmem_device *nvmem = to_nvmem_device(dev);
+
+ return nvmem->size;
+}
+
static umode_t nvmem_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int i)
{
@@ -383,6 +392,7 @@ static const struct attribute_group nvmem_bin_group = {
.bin_attrs = nvmem_bin_attributes,
.attrs = nvmem_attrs,
.is_bin_visible = nvmem_bin_attr_is_visible,
+ .bin_size = nvmem_bin_attr_size,
.is_visible = nvmem_attr_is_visible,
};
@@ -1247,7 +1257,7 @@ static void devm_nvmem_device_release(struct device *dev, void *res)
}
/**
- * devm_nvmem_device_put() - put alredy got nvmem device
+ * devm_nvmem_device_put() - put already got nvmem device
*
* @dev: Device that uses the nvmem device.
* @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
@@ -1265,7 +1275,7 @@ void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
/**
- * nvmem_device_put() - put alredy got nvmem device
+ * nvmem_device_put() - put already got nvmem device
*
* @nvmem: pointer to nvmem device that needs to be released.
*/
diff --git a/drivers/nvmem/imx-iim.c b/drivers/nvmem/imx-iim.c
index f13bbd164086..8cfbe55a56cb 100644
--- a/drivers/nvmem/imx-iim.c
+++ b/drivers/nvmem/imx-iim.c
@@ -115,11 +115,11 @@ static int imx_iim_probe(struct platform_device *pdev)
if (IS_ERR(iim->clk))
return PTR_ERR(iim->clk);
- cfg.name = "imx-iim",
- cfg.read_only = true,
- cfg.word_size = 1,
- cfg.stride = 1,
- cfg.reg_read = imx_iim_read,
+ cfg.name = "imx-iim";
+ cfg.read_only = true;
+ cfg.word_size = 1;
+ cfg.stride = 1;
+ cfg.reg_read = imx_iim_read;
cfg.dev = dev;
cfg.size = drvdata->nregs;
cfg.priv = iim;
diff --git a/drivers/nvmem/lpc18xx_otp.c b/drivers/nvmem/lpc18xx_otp.c
index adc9948e7b2e..c41a0c58bec7 100644
--- a/drivers/nvmem/lpc18xx_otp.c
+++ b/drivers/nvmem/lpc18xx_otp.c
@@ -21,7 +21,7 @@
* LPC18xx OTP memory contains 4 banks with 4 32-bit words. Bank 0 starts
* at offset 0 from the base.
*
- * Bank 0 contains the part ID for Flashless devices and is reseverd for
+ * Bank 0 contains the part ID for Flashless devices and is reserved for
* devices with Flash.
* Bank 1/2 is generale purpose or AES key storage for secure devices.
* Bank 3 contains control data, USB ID and generale purpose words.
diff --git a/drivers/nvmem/microchip-otpc.c b/drivers/nvmem/microchip-otpc.c
index 7cf81738a3e0..df979e8549fd 100644
--- a/drivers/nvmem/microchip-otpc.c
+++ b/drivers/nvmem/microchip-otpc.c
@@ -156,7 +156,7 @@ static int mchp_otpc_read(void *priv, unsigned int off, void *val,
/*
* We reach this point with off being multiple of stride = 4 to
* be able to cross the subsystem. Inside the driver we use continuous
- * unsigned integer numbers for packet id, thus devide off by 4
+ * unsigned integer numbers for packet id, thus divide off by 4
* before passing it to mchp_otpc_id_to_packet().
*/
packet = mchp_otpc_id_to_packet(otpc, off / 4);
diff --git a/drivers/nvmem/rcar-efuse.c b/drivers/nvmem/rcar-efuse.c
new file mode 100644
index 000000000000..f24bdb9cb5a7
--- /dev/null
+++ b/drivers/nvmem/rcar-efuse.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Renesas R-Car E-FUSE/OTP Driver
+ *
+ * Copyright (C) 2024 Glider bv
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/nvmem-provider.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/property.h>
+
+struct rcar_fuse {
+ struct nvmem_keepout keepouts[2];
+ struct nvmem_device *nvmem;
+ struct device *dev;
+ void __iomem *base;
+};
+
+struct rcar_fuse_data {
+ unsigned int bank; /* 0: PFC + E-FUSE, 1: OPT_MEM + E-FUSE */
+ unsigned int start; /* inclusive */
+ unsigned int end; /* exclusive */
+};
+
+static int rcar_fuse_reg_read(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct rcar_fuse *fuse = priv;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(fuse->dev);
+ if (ret < 0)
+ return ret;
+
+ __ioread32_copy(val, fuse->base + offset, bytes / 4);
+
+ pm_runtime_put(fuse->dev);
+
+ return 0;
+}
+
+static int rcar_fuse_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct rcar_fuse_data *data = device_get_match_data(dev);
+ struct nvmem_config config = {
+ .dev = dev,
+ .name = "rcar-fuse",
+ .id = NVMEM_DEVID_NONE,
+ .owner = THIS_MODULE,
+ .type = NVMEM_TYPE_OTP,
+ .read_only = true,
+ .root_only = true,
+ .reg_read = rcar_fuse_reg_read,
+ .word_size = 4,
+ .stride = 4,
+ };
+ struct rcar_fuse *fuse;
+ struct resource *res;
+ int ret;
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret < 0)
+ return ret;
+
+ fuse = devm_kzalloc(dev, sizeof(*fuse), GFP_KERNEL);
+ if (!fuse)
+ return -ENOMEM;
+
+ fuse->base = devm_platform_get_and_ioremap_resource(pdev, data->bank,
+ &res);
+ if (IS_ERR(fuse->base))
+ return PTR_ERR(fuse->base);
+
+ fuse->dev = dev;
+ fuse->keepouts[0].start = 0;
+ fuse->keepouts[0].end = data->start;
+ fuse->keepouts[1].start = data->end;
+ fuse->keepouts[1].end = resource_size(res);
+
+ config.keepout = fuse->keepouts;
+ config.nkeepout = ARRAY_SIZE(fuse->keepouts);
+ config.size = resource_size(res);
+ config.priv = fuse;
+
+ fuse->nvmem = devm_nvmem_register(dev, &config);
+ if (IS_ERR(fuse->nvmem))
+ return dev_err_probe(dev, PTR_ERR(fuse->nvmem),
+ "Failed to register NVMEM device\n");
+
+ return 0;
+}
+
+static const struct rcar_fuse_data rcar_fuse_v3u = {
+ .bank = 0,
+ .start = 0x0c0,
+ .end = 0x0e8,
+};
+
+static const struct rcar_fuse_data rcar_fuse_s4 = {
+ .bank = 0,
+ .start = 0x0c0,
+ .end = 0x14c,
+};
+
+static const struct rcar_fuse_data rcar_fuse_v4h = {
+ .bank = 1,
+ .start = 0x100,
+ .end = 0x1a0,
+};
+
+static const struct rcar_fuse_data rcar_fuse_v4m = {
+ .bank = 1,
+ .start = 0x100,
+ .end = 0x110,
+};
+
+static const struct of_device_id rcar_fuse_match[] = {
+ { .compatible = "renesas,r8a779a0-efuse", .data = &rcar_fuse_v3u },
+ { .compatible = "renesas,r8a779f0-efuse", .data = &rcar_fuse_s4 },
+ { .compatible = "renesas,r8a779g0-otp", .data = &rcar_fuse_v4h },
+ { .compatible = "renesas,r8a779h0-otp", .data = &rcar_fuse_v4m },
+ { /* sentinel */ }
+};
+
+static struct platform_driver rcar_fuse_driver = {
+ .probe = rcar_fuse_probe,
+ .driver = {
+ .name = "rcar_fuse",
+ .of_match_table = rcar_fuse_match,
+ },
+};
+module_platform_driver(rcar_fuse_driver);
+
+MODULE_DESCRIPTION("Renesas R-Car E-FUSE/OTP driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Geert Uytterhoeven");
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index f0b8cc23c46d..50697cc3b07e 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -2,6 +2,12 @@
config DTC
bool
+config GENERIC_BUILTIN_DTB
+ bool
+
+config BUILTIN_DTB_ALL
+ bool
+
menuconfig OF
bool "Device Tree and Open Firmware support"
help
diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
index 4bdb79ffa101..430651e7424a 100644
--- a/drivers/opp/opp.h
+++ b/drivers/opp/opp.h
@@ -263,9 +263,7 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *o
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, struct dev_pm_opp_data *data, bool dynamic);
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
-void _put_opp_list_kref(struct opp_table *opp_table);
void _required_opps_available(struct dev_pm_opp *opp, int count);
-void _update_set_required_opps(struct opp_table *opp_table);
static inline bool lazy_linking_pending(struct opp_table *opp_table)
{
diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 4f47a13cb500..7abd4f546d3c 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -90,7 +90,7 @@ static ssize_t published_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RO(published);
static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, struct vm_area_struct *vma)
+ const struct bin_attribute *attr, struct vm_area_struct *vma)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
size_t len = vma->vm_end - vma->vm_start;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 3e5a117f5b5d..7679d75d71e5 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -844,21 +844,20 @@ static struct bin_attribute *pci_dev_config_attrs[] = {
NULL,
};
-static umode_t pci_dev_config_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *a, int n)
+static size_t pci_dev_config_attr_bin_size(struct kobject *kobj,
+ const struct bin_attribute *a,
+ int n)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
- a->size = PCI_CFG_SPACE_SIZE;
if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
- a->size = PCI_CFG_SPACE_EXP_SIZE;
-
- return a->attr.mode;
+ return PCI_CFG_SPACE_EXP_SIZE;
+ return PCI_CFG_SPACE_SIZE;
}
static const struct attribute_group pci_dev_config_attr_group = {
.bin_attrs = pci_dev_config_attrs,
- .is_bin_visible = pci_dev_config_attr_is_visible,
+ .bin_size = pci_dev_config_attr_bin_size,
};
/*
@@ -868,7 +867,7 @@ static const struct attribute_group pci_dev_config_attr_group = {
static __maybe_unused loff_t
pci_llseek_resource(struct file *filep,
struct kobject *kobj __always_unused,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
loff_t offset, int whence)
{
return fixed_size_llseek(filep, offset, whence, attr->size);
@@ -937,7 +936,7 @@ static ssize_t pci_write_legacy_io(struct file *filp, struct kobject *kobj,
* memory space.
*/
static int pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
@@ -957,7 +956,7 @@ static int pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj,
* memory space. Returns -ENOSYS if the operation isn't supported
*/
static int pci_mmap_legacy_io(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
@@ -1061,7 +1060,7 @@ void pci_remove_legacy_files(struct pci_bus *b)
*
* Use the regular PCI mapping routines to map a PCI resource into userspace.
*/
-static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
+static int pci_mmap_resource(struct kobject *kobj, const struct bin_attribute *attr,
struct vm_area_struct *vma, int write_combine)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
@@ -1086,14 +1085,14 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
}
static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
return pci_mmap_resource(kobj, attr, vma, 0);
}
static int pci_mmap_resource_wc(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
return pci_mmap_resource(kobj, attr, vma, 1);
@@ -1353,24 +1352,29 @@ static struct bin_attribute *pci_dev_rom_attrs[] = {
};
static umode_t pci_dev_rom_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *a, int n)
+ const struct bin_attribute *a, int n)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
- size_t rom_size;
/* If the device has a ROM, try to expose it in sysfs. */
- rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
- if (!rom_size)
+ if (!pci_resource_end(pdev, PCI_ROM_RESOURCE))
return 0;
- a->size = rom_size;
-
return a->attr.mode;
}
+static size_t pci_dev_rom_attr_bin_size(struct kobject *kobj,
+ const struct bin_attribute *a, int n)
+{
+ struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
+
+ return pci_resource_len(pdev, PCI_ROM_RESOURCE);
+}
+
static const struct attribute_group pci_dev_rom_attr_group = {
.bin_attrs = pci_dev_rom_attrs,
.is_bin_visible = pci_dev_rom_attr_is_visible,
+ .bin_size = pci_dev_rom_attr_bin_size,
};
static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 963b8d2855c1..efc37fcb73e2 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -19,14 +19,19 @@ static void pci_free_resources(struct pci_dev *dev)
static void pci_pwrctrl_unregister(struct device *dev)
{
+ struct device_node *np;
struct platform_device *pdev;
- pdev = of_find_device_by_node(dev_of_node(dev));
+ np = dev_of_node(dev);
+ if (!np)
+ return;
+
+ pdev = of_find_device_by_node(np);
if (!pdev)
return;
of_device_unregister(pdev);
- of_node_clear_flag(dev_of_node(dev), OF_POPULATED);
+ of_node_clear_flag(np, OF_POPULATED);
}
static void pci_stop_dev(struct pci_dev *dev)
diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c
index e4300f5f304f..a469bcbc0da7 100644
--- a/drivers/pci/vpd.c
+++ b/drivers/pci/vpd.c
@@ -325,7 +325,7 @@ static struct bin_attribute *vpd_attrs[] = {
};
static umode_t vpd_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *a, int n)
+ const struct bin_attribute *a, int n)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
diff --git a/drivers/peci/controller/peci-npcm.c b/drivers/peci/controller/peci-npcm.c
index ec613d35c796..fa91be58f6f3 100644
--- a/drivers/peci/controller/peci-npcm.c
+++ b/drivers/peci/controller/peci-npcm.c
@@ -224,7 +224,7 @@ static const struct regmap_config npcm_peci_regmap_config = {
.fast_io = true,
};
-static struct peci_controller_ops npcm_ops = {
+static const struct peci_controller_ops npcm_ops = {
.xfer = npcm_peci_xfer,
};
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 49bd811c6fd6..b20fa600e510 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -2178,8 +2178,6 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
continue;
xp = arm_cmn_node_to_xp(cmn, dn);
- dn->portid_bits = xp->portid_bits;
- dn->deviceid_bits = xp->deviceid_bits;
dn->dtc = xp->dtc;
dn->dtm = xp->dtm;
if (cmn->multi_dtm)
@@ -2420,6 +2418,8 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
}
arm_cmn_init_node_info(cmn, reg & CMN_CHILD_NODE_ADDR, dn);
+ dn->portid_bits = xp->portid_bits;
+ dn->deviceid_bits = xp->deviceid_bits;
switch (dn->type) {
case CMN_TYPE_DTC:
diff --git a/drivers/perf/arm-ni.c b/drivers/perf/arm-ni.c
index 90fcfe693439..fd7a5e60e963 100644
--- a/drivers/perf/arm-ni.c
+++ b/drivers/perf/arm-ni.c
@@ -247,7 +247,6 @@ static struct attribute *arm_ni_other_attrs[] = {
static const struct attribute_group arm_ni_other_attr_group = {
.attrs = arm_ni_other_attrs,
- NULL
};
static const struct attribute_group *arm_ni_attr_groups[] = {
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index b1510f660c7a..621f02a7f43b 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -431,6 +431,17 @@ static int smmu_pmu_event_init(struct perf_event *event)
return -EINVAL;
}
+ /*
+ * Ensure all events are on the same cpu so all events are in the
+ * same cpu context, to avoid races on pmu_enable etc.
+ */
+ event->cpu = smmu_pmu->on_cpu;
+
+ hwc->idx = -1;
+
+ if (event->group_leader == event)
+ return 0;
+
for_each_sibling_event(sibling, event->group_leader) {
if (is_software_event(sibling))
continue;
@@ -442,14 +453,6 @@ static int smmu_pmu_event_init(struct perf_event *event)
return -EINVAL;
}
- hwc->idx = -1;
-
- /*
- * Ensure all events are on the same cpu so all events are in the
- * same cpu context, to avoid races on pmu_enable etc.
- */
- event->cpu = smmu_pmu->on_cpu;
-
return 0;
}
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index f73abff416be..8d58efe998ec 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -82,6 +82,17 @@ config PHY_AIROHA_PCIE
This driver create the basic PHY instance and provides initialize
callback for PCIe GEN3 port.
+config PHY_NXP_PTN3222
+ tristate "NXP PTN3222 1-port eUSB2 to USB2 redriver"
+ depends on I2C
+ depends on OF
+ select GENERIC_PHY
+ help
+ Enable this to support NXP PTN3222 1-port eUSB2 to USB2 Redriver.
+ This redriver performs translation between eUSB2 and USB2 signalling
+ schemes. It supports all three USB 2.0 data rates: Low Speed, Full
+ Speed and High Speed.
+
source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/broadcom/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index ebc399560da4..e281442acc75 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o
obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
+obj-$(CONFIG_PHY_NXP_PTN3222) += phy-nxp-ptn3222.o
obj-y += allwinner/ \
amlogic/ \
broadcom/ \
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index b0f19e950601..cd159a71b23c 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -1049,11 +1049,11 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
static struct platform_driver sun4i_usb_phy_driver = {
- .probe = sun4i_usb_phy_probe,
- .remove_new = sun4i_usb_phy_remove,
+ .probe = sun4i_usb_phy_probe,
+ .remove = sun4i_usb_phy_remove,
.driver = {
- .of_match_table = sun4i_usb_phy_of_match,
- .name = "sun4i-usb-phy",
+ .of_match_table= sun4i_usb_phy_of_match,
+ .name = "sun4i-usb-phy",
}
};
module_platform_driver(sun4i_usb_phy_driver);
diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb2.c b/drivers/phy/broadcom/phy-bcm-ns-usb2.c
index 5213c75b6da6..c5d35031b398 100644
--- a/drivers/phy/broadcom/phy-bcm-ns-usb2.c
+++ b/drivers/phy/broadcom/phy-bcm-ns-usb2.c
@@ -24,9 +24,6 @@ struct bcm_ns_usb2 {
struct phy *phy;
struct regmap *clkset;
void __iomem *base;
-
- /* Deprecated binding */
- void __iomem *dmu;
};
static int bcm_ns_usb2_phy_init(struct phy *phy)
@@ -49,10 +46,7 @@ static int bcm_ns_usb2_phy_init(struct phy *phy)
goto err_clk_off;
}
- if (usb2->base)
- usb2ctl = readl(usb2->base);
- else
- usb2ctl = readl(usb2->dmu + BCMA_DMU_CRU_USB2_CONTROL);
+ usb2ctl = readl(usb2->base);
if (usb2ctl & BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK) {
usb_pll_pdiv = usb2ctl;
@@ -66,24 +60,16 @@ static int bcm_ns_usb2_phy_init(struct phy *phy)
usb_pll_ndiv = (1920000000 * usb_pll_pdiv) / ref_clk_rate;
/* Unlock DMU PLL settings with some magic value */
- if (usb2->clkset)
- regmap_write(usb2->clkset, 0, 0x0000ea68);
- else
- writel(0x0000ea68, usb2->dmu + BCMA_DMU_CRU_CLKSET_KEY);
+ regmap_write(usb2->clkset, 0, 0x0000ea68);
/* Write USB 2.0 PLL control setting */
usb2ctl &= ~BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK;
usb2ctl |= usb_pll_ndiv << BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT;
- if (usb2->base)
- writel(usb2ctl, usb2->base);
- else
- writel(usb2ctl, usb2->dmu + BCMA_DMU_CRU_USB2_CONTROL);
+
+ writel(usb2ctl, usb2->base);
/* Lock DMU PLL settings */
- if (usb2->clkset)
- regmap_write(usb2->clkset, 0, 0x00000000);
- else
- writel(0x00000000, usb2->dmu + BCMA_DMU_CRU_CLKSET_KEY);
+ regmap_write(usb2->clkset, 0, 0x00000000);
err_clk_off:
clk_disable_unprepare(usb2->ref_clk);
@@ -107,27 +93,17 @@ static int bcm_ns_usb2_probe(struct platform_device *pdev)
return -ENOMEM;
usb2->dev = dev;
- if (of_property_present(dev->of_node, "brcm,syscon-clkset")) {
- usb2->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(usb2->base)) {
- dev_err(dev, "Failed to map control reg\n");
- return PTR_ERR(usb2->base);
- }
-
- usb2->clkset = syscon_regmap_lookup_by_phandle(dev->of_node,
- "brcm,syscon-clkset");
- if (IS_ERR(usb2->clkset)) {
- dev_err(dev, "Failed to lookup clkset regmap\n");
- return PTR_ERR(usb2->clkset);
- }
- } else {
- usb2->dmu = devm_platform_ioremap_resource_byname(pdev, "dmu");
- if (IS_ERR(usb2->dmu)) {
- dev_err(dev, "Failed to map DMU regs\n");
- return PTR_ERR(usb2->dmu);
- }
+ usb2->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(usb2->base)) {
+ dev_err(dev, "Failed to map control reg\n");
+ return PTR_ERR(usb2->base);
+ }
- dev_warn(dev, "using deprecated DT binding\n");
+ usb2->clkset = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "brcm,syscon-clkset");
+ if (IS_ERR(usb2->clkset)) {
+ dev_err(dev, "Failed to lookup clkset regmap\n");
+ return PTR_ERR(usb2->clkset);
}
usb2->ref_clk = devm_clk_get(dev, "phy-ref-clk");
diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.c b/drivers/phy/broadcom/phy-brcm-usb-init.c
index 5ebb3a616115..da23078878a9 100644
--- a/drivers/phy/broadcom/phy-brcm-usb-init.c
+++ b/drivers/phy/broadcom/phy-brcm-usb-init.c
@@ -193,256 +193,251 @@ static const u32
usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
/* 3390B0 */
[BRCM_FAMILY_3390A0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 4908 */
[BRCM_FAMILY_4908] = {
- 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
- 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
- 0, /* USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- 0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK */
- 0, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
},
/* 7250b0 */
[BRCM_FAMILY_7250B0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
- 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR] =
+ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7271a0 */
[BRCM_FAMILY_7271A0] = {
- 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
- 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- USB_CTRL_USB_PM_SOFT_RESET_MASK,
- USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
- USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_SOFT_RESET_SELECTOR] =
+ USB_CTRL_USB_PM_SOFT_RESET_MASK,
+ [USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_SELECTOR] =
+ USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
+ [USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7364a0 */
[BRCM_FAMILY_7364A0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
- 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR] =
+ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7366c0 */
[BRCM_FAMILY_7366C0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 74371A0 */
[BRCM_FAMILY_74371A0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */
- USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
- USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB30_CTL1_USB3_IOC_MASK,
- USB_CTRL_USB30_CTL1_USB3_IPP_MASK,
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- 0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_MASK */
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
+ [USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR] =
+ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+ [USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB30_CTL1_USB3_IOC_SELECTOR] =
+ USB_CTRL_USB30_CTL1_USB3_IOC_MASK,
+ [USB_CTRL_USB30_CTL1_USB3_IPP_SELECTOR] =
+ USB_CTRL_USB30_CTL1_USB3_IPP_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7439B0 */
[BRCM_FAMILY_7439B0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7445d0 */
[BRCM_FAMILY_7445D0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
- USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR] =
+ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+ [USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7260a0 */
[BRCM_FAMILY_7260A0] = {
- 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
- 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- USB_CTRL_USB_PM_SOFT_RESET_MASK,
- USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
- USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_SOFT_RESET_SELECTOR] =
+ USB_CTRL_USB_PM_SOFT_RESET_MASK,
+ [USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_SELECTOR] =
+ USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
+ [USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7278a0 */
[BRCM_FAMILY_7278A0] = {
- 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
- 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
- 0, /*USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- USB_CTRL_USB_PM_SOFT_RESET_MASK,
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- 0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_MASK */
- 0, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_SOFT_RESET_SELECTOR] =
+ USB_CTRL_USB_PM_SOFT_RESET_MASK,
},
};
diff --git a/drivers/phy/broadcom/phy-brcm-usb.c b/drivers/phy/broadcom/phy-brcm-usb.c
index ad2eec095601..6362ca5b7fb6 100644
--- a/drivers/phy/broadcom/phy-brcm-usb.c
+++ b/drivers/phy/broadcom/phy-brcm-usb.c
@@ -667,7 +667,7 @@ MODULE_DEVICE_TABLE(of, brcm_usb_dt_ids);
static struct platform_driver brcm_usb_driver = {
.probe = brcm_usb_phy_probe,
- .remove_new = brcm_usb_phy_remove,
+ .remove = brcm_usb_phy_remove,
.driver = {
.name = "brcmstb-usb-phy",
.pm = &brcm_usb_phy_pm_ops,
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
index dddb66de6dba..ed87a3970f83 100644
--- a/drivers/phy/cadence/cdns-dphy.c
+++ b/drivers/phy/cadence/cdns-dphy.c
@@ -472,7 +472,7 @@ MODULE_DEVICE_TABLE(of, cdns_dphy_of_match);
static struct platform_driver cdns_dphy_platform_driver = {
.probe = cdns_dphy_probe,
- .remove_new = cdns_dphy_remove,
+ .remove = cdns_dphy_remove,
.driver = {
.name = "cdns-mipi-dphy",
.of_match_table = cdns_dphy_of_match,
diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c
index dfc4f55d112e..45a5c00843bf 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -2731,7 +2731,7 @@ MODULE_DEVICE_TABLE(of, cdns_sierra_id_table);
static struct platform_driver cdns_sierra_driver = {
.probe = cdns_sierra_phy_probe,
- .remove_new = cdns_sierra_phy_remove,
+ .remove = cdns_sierra_phy_remove,
.driver = {
.name = "cdns-sierra-phy",
.of_match_table = cdns_sierra_id_table,
diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c
index 8bbbbb87bb22..a281c0dfae97 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -5440,8 +5440,8 @@ MODULE_DEVICE_TABLE(of, cdns_torrent_phy_of_match);
static struct platform_driver cdns_torrent_phy_driver = {
.probe = cdns_torrent_phy_probe,
- .remove_new = cdns_torrent_phy_remove,
- .driver = {
+ .remove = cdns_torrent_phy_remove,
+ .driver = {
.name = "cdns-torrent-phy",
.of_match_table = cdns_torrent_phy_of_match,
.pm = pm_sleep_ptr(&cdns_torrent_phy_pm_ops),
diff --git a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
index 38388dd04bdc..7aef2f59e8eb 100644
--- a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
+++ b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
@@ -433,12 +433,12 @@ static const struct of_device_id mixel_lvds_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, mixel_lvds_phy_of_match);
static struct platform_driver mixel_lvds_phy_driver = {
- .probe = mixel_lvds_phy_probe,
- .remove_new = mixel_lvds_phy_remove,
+ .probe = mixel_lvds_phy_probe,
+ .remove = mixel_lvds_phy_remove,
.driver = {
.pm = &mixel_lvds_phy_pm_ops,
.name = "mixel-lvds-phy",
- .of_match_table = mixel_lvds_phy_of_match,
+ .of_match_table = mixel_lvds_phy_of_match,
}
};
module_platform_driver(mixel_lvds_phy_driver);
diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c
index b86da8e9daa4..f7994e8983c8 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-28g.c
+++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c
@@ -631,9 +631,9 @@ static const struct of_device_id lynx_28g_of_match_table[] = {
MODULE_DEVICE_TABLE(of, lynx_28g_of_match_table);
static struct platform_driver lynx_28g_driver = {
- .probe = lynx_28g_probe,
- .remove_new = lynx_28g_remove,
- .driver = {
+ .probe = lynx_28g_probe,
+ .remove = lynx_28g_remove,
+ .driver = {
.name = "lynx-28g",
.of_match_table = lynx_28g_of_match_table,
},
diff --git a/drivers/phy/freescale/phy-fsl-samsung-hdmi.c b/drivers/phy/freescale/phy-fsl-samsung-hdmi.c
index 9048cdc760c2..2c8038864357 100644
--- a/drivers/phy/freescale/phy-fsl-samsung-hdmi.c
+++ b/drivers/phy/freescale/phy-fsl-samsung-hdmi.c
@@ -14,352 +14,265 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#define PHY_REG_00 0x00
-#define PHY_REG_01 0x04
-#define PHY_REG_02 0x08
-#define PHY_REG_08 0x20
-#define PHY_REG_09 0x24
-#define PHY_REG_10 0x28
-#define PHY_REG_11 0x2c
-
-#define PHY_REG_12 0x30
-#define REG12_CK_DIV_MASK GENMASK(5, 4)
-
-#define PHY_REG_13 0x34
-#define REG13_TG_CODE_LOW_MASK GENMASK(7, 0)
-
-#define PHY_REG_14 0x38
-#define REG14_TOL_MASK GENMASK(7, 4)
-#define REG14_RP_CODE_MASK GENMASK(3, 1)
-#define REG14_TG_CODE_HIGH_MASK GENMASK(0, 0)
-
-#define PHY_REG_15 0x3c
-#define PHY_REG_16 0x40
-#define PHY_REG_17 0x44
-#define PHY_REG_18 0x48
-#define PHY_REG_19 0x4c
-#define PHY_REG_20 0x50
-
-#define PHY_REG_21 0x54
-#define REG21_SEL_TX_CK_INV BIT(7)
-#define REG21_PMS_S_MASK GENMASK(3, 0)
-
-#define PHY_REG_22 0x58
-#define PHY_REG_23 0x5c
-#define PHY_REG_24 0x60
-#define PHY_REG_25 0x64
-#define PHY_REG_26 0x68
-#define PHY_REG_27 0x6c
-#define PHY_REG_28 0x70
-#define PHY_REG_29 0x74
-#define PHY_REG_30 0x78
-#define PHY_REG_31 0x7c
-#define PHY_REG_32 0x80
+#define PHY_REG(reg) (reg * 4)
+#define REG01_PMS_P_MASK GENMASK(3, 0)
+#define REG03_PMS_S_MASK GENMASK(7, 4)
+#define REG12_CK_DIV_MASK GENMASK(5, 4)
+
+#define REG13_TG_CODE_LOW_MASK GENMASK(7, 0)
+
+#define REG14_TOL_MASK GENMASK(7, 4)
+#define REG14_RP_CODE_MASK GENMASK(3, 1)
+#define REG14_TG_CODE_HIGH_MASK GENMASK(0, 0)
+
+#define REG21_SEL_TX_CK_INV BIT(7)
+#define REG21_PMS_S_MASK GENMASK(3, 0)
/*
* REG33 does not match the ref manual. According to Sandor Yu from NXP,
* "There is a doc issue on the i.MX8MP latest RM"
* REG33 is being used per guidance from Sandor
*/
+#define REG33_MODE_SET_DONE BIT(7)
+#define REG33_FIX_DA BIT(1)
+
+#define REG34_PHY_READY BIT(7)
+#define REG34_PLL_LOCK BIT(6)
+#define REG34_PHY_CLK_READY BIT(5)
-#define PHY_REG_33 0x84
-#define REG33_MODE_SET_DONE BIT(7)
-#define REG33_FIX_DA BIT(1)
-
-#define PHY_REG_34 0x88
-#define REG34_PHY_READY BIT(7)
-#define REG34_PLL_LOCK BIT(6)
-#define REG34_PHY_CLK_READY BIT(5)
-
-#define PHY_REG_35 0x8c
-#define PHY_REG_36 0x90
-#define PHY_REG_37 0x94
-#define PHY_REG_38 0x98
-#define PHY_REG_39 0x9c
-#define PHY_REG_40 0xa0
-#define PHY_REG_41 0xa4
-#define PHY_REG_42 0xa8
-#define PHY_REG_43 0xac
-#define PHY_REG_44 0xb0
-#define PHY_REG_45 0xb4
-#define PHY_REG_46 0xb8
-#define PHY_REG_47 0xbc
-
-#define PHY_PLL_DIV_REGS_NUM 6
+#ifndef MHZ
+#define MHZ (1000UL * 1000UL)
+#endif
+
+#define PHY_PLL_DIV_REGS_NUM 7
struct phy_config {
u32 pixclk;
u8 pll_div_regs[PHY_PLL_DIV_REGS_NUM];
};
+/*
+ * The calculated_phy_pll_cfg only handles integer divider for PMS,
+ * meaning the last four entries will be fixed, but the first three will
+ * be calculated by the PMS calculator.
+ */
+static struct phy_config calculated_phy_pll_cfg = {
+ .pixclk = 0,
+ .pll_div_regs = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+};
+
+/* The lookup table contains values for which the fractional divder is used */
static const struct phy_config phy_pll_cfg[] = {
{
.pixclk = 22250000,
- .pll_div_regs = { 0x4b, 0xf1, 0x89, 0x88, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x4b, 0xf1, 0x89, 0x88, 0x80, 0x40 },
}, {
.pixclk = 23750000,
- .pll_div_regs = { 0x50, 0xf1, 0x86, 0x85, 0x80, 0x40 },
- }, {
- .pixclk = 24000000,
- .pll_div_regs = { 0x50, 0xf0, 0x00, 0x00, 0x80, 0x00 },
+ .pll_div_regs = { 0xd1, 0x50, 0xf1, 0x86, 0x85, 0x80, 0x40 },
}, {
.pixclk = 24024000,
- .pll_div_regs = { 0x50, 0xf1, 0x99, 0x02, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x50, 0xf1, 0x99, 0x02, 0x80, 0x40 },
}, {
.pixclk = 25175000,
- .pll_div_regs = { 0x54, 0xfc, 0xcc, 0x91, 0x80, 0x40 },
- }, {
- .pixclk = 25200000,
- .pll_div_regs = { 0x54, 0xf0, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x54, 0xfc, 0xcc, 0x91, 0x80, 0x40 },
+ }, {
.pixclk = 26750000,
- .pll_div_regs = { 0x5a, 0xf2, 0x89, 0x88, 0x80, 0x40 },
- }, {
- .pixclk = 27000000,
- .pll_div_regs = { 0x5a, 0xf0, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x5a, 0xf2, 0x89, 0x88, 0x80, 0x40 },
+ }, {
.pixclk = 27027000,
- .pll_div_regs = { 0x5a, 0xf2, 0xfd, 0x0c, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x5a, 0xf2, 0xfd, 0x0c, 0x80, 0x40 },
}, {
.pixclk = 29500000,
- .pll_div_regs = { 0x62, 0xf4, 0x95, 0x08, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x62, 0xf4, 0x95, 0x08, 0x80, 0x40 },
}, {
.pixclk = 30750000,
- .pll_div_regs = { 0x66, 0xf4, 0x82, 0x01, 0x88, 0x45 },
+ .pll_div_regs = { 0xd1, 0x66, 0xf4, 0x82, 0x01, 0x88, 0x45 },
}, {
.pixclk = 30888000,
- .pll_div_regs = { 0x66, 0xf4, 0x99, 0x18, 0x88, 0x45 },
+ .pll_div_regs = { 0xd1, 0x66, 0xf4, 0x99, 0x18, 0x88, 0x45 },
}, {
.pixclk = 33750000,
- .pll_div_regs = { 0x70, 0xf4, 0x82, 0x01, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x70, 0xf4, 0x82, 0x01, 0x80, 0x40 },
}, {
.pixclk = 35000000,
- .pll_div_regs = { 0x58, 0xb8, 0x8b, 0x88, 0x80, 0x40 },
- }, {
- .pixclk = 36000000,
- .pll_div_regs = { 0x5a, 0xb0, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x58, 0xb8, 0x8b, 0x88, 0x80, 0x40 },
+ }, {
.pixclk = 36036000,
- .pll_div_regs = { 0x5a, 0xb2, 0xfd, 0x0c, 0x80, 0x40 },
- }, {
- .pixclk = 40000000,
- .pll_div_regs = { 0x64, 0xb0, 0x00, 0x00, 0x80, 0x00 },
- }, {
- .pixclk = 43200000,
- .pll_div_regs = { 0x5a, 0x90, 0x00, 0x00, 0x80, 0x00 },
+ .pll_div_regs = { 0xd1, 0x5a, 0xb2, 0xfd, 0x0c, 0x80, 0x40 },
}, {
.pixclk = 43243200,
- .pll_div_regs = { 0x5a, 0x92, 0xfd, 0x0c, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x5a, 0x92, 0xfd, 0x0c, 0x80, 0x40 },
}, {
.pixclk = 44500000,
- .pll_div_regs = { 0x5c, 0x92, 0x98, 0x11, 0x84, 0x41 },
+ .pll_div_regs = { 0xd1, 0x5c, 0x92, 0x98, 0x11, 0x84, 0x41 },
}, {
.pixclk = 47000000,
- .pll_div_regs = { 0x62, 0x94, 0x95, 0x82, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x62, 0x94, 0x95, 0x82, 0x80, 0x40 },
}, {
.pixclk = 47500000,
- .pll_div_regs = { 0x63, 0x96, 0xa1, 0x82, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x63, 0x96, 0xa1, 0x82, 0x80, 0x40 },
}, {
.pixclk = 50349650,
- .pll_div_regs = { 0x54, 0x7c, 0xc3, 0x8f, 0x80, 0x40 },
- }, {
- .pixclk = 50400000,
- .pll_div_regs = { 0x54, 0x70, 0x00, 0x00, 0x80, 0x00 },
+ .pll_div_regs = { 0xd1, 0x54, 0x7c, 0xc3, 0x8f, 0x80, 0x40 },
}, {
.pixclk = 53250000,
- .pll_div_regs = { 0x58, 0x72, 0x84, 0x03, 0x82, 0x41 },
+ .pll_div_regs = { 0xd1, 0x58, 0x72, 0x84, 0x03, 0x82, 0x41 },
}, {
.pixclk = 53500000,
- .pll_div_regs = { 0x5a, 0x72, 0x89, 0x88, 0x80, 0x40 },
- }, {
- .pixclk = 54000000,
- .pll_div_regs = { 0x5a, 0x70, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x5a, 0x72, 0x89, 0x88, 0x80, 0x40 },
+ }, {
.pixclk = 54054000,
- .pll_div_regs = { 0x5a, 0x72, 0xfd, 0x0c, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x5a, 0x72, 0xfd, 0x0c, 0x80, 0x40 },
}, {
.pixclk = 59000000,
- .pll_div_regs = { 0x62, 0x74, 0x95, 0x08, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x62, 0x74, 0x95, 0x08, 0x80, 0x40 },
}, {
.pixclk = 59340659,
- .pll_div_regs = { 0x62, 0x74, 0xdb, 0x52, 0x88, 0x47 },
- }, {
- .pixclk = 59400000,
- .pll_div_regs = { 0x63, 0x70, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x62, 0x74, 0xdb, 0x52, 0x88, 0x47 },
+ }, {
.pixclk = 61500000,
- .pll_div_regs = { 0x66, 0x74, 0x82, 0x01, 0x88, 0x45 },
+ .pll_div_regs = { 0xd1, 0x66, 0x74, 0x82, 0x01, 0x88, 0x45 },
}, {
.pixclk = 63500000,
- .pll_div_regs = { 0x69, 0x74, 0x89, 0x08, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x69, 0x74, 0x89, 0x08, 0x80, 0x40 },
}, {
.pixclk = 67500000,
- .pll_div_regs = { 0x54, 0x52, 0x87, 0x03, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x54, 0x52, 0x87, 0x03, 0x80, 0x40 },
}, {
.pixclk = 70000000,
- .pll_div_regs = { 0x58, 0x58, 0x8b, 0x88, 0x80, 0x40 },
- }, {
- .pixclk = 72000000,
- .pll_div_regs = { 0x5a, 0x50, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x58, 0x58, 0x8b, 0x88, 0x80, 0x40 },
+ }, {
.pixclk = 72072000,
- .pll_div_regs = { 0x5a, 0x52, 0xfd, 0x0c, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x5a, 0x52, 0xfd, 0x0c, 0x80, 0x40 },
}, {
.pixclk = 74176000,
- .pll_div_regs = { 0x5d, 0x58, 0xdb, 0xA2, 0x88, 0x41 },
+ .pll_div_regs = { 0xd1, 0x5d, 0x58, 0xdb, 0xA2, 0x88, 0x41 },
}, {
.pixclk = 74250000,
- .pll_div_regs = { 0x5c, 0x52, 0x90, 0x0d, 0x84, 0x41 },
+ .pll_div_regs = { 0xd1, 0x5c, 0x52, 0x90, 0x0d, 0x84, 0x41 },
}, {
.pixclk = 78500000,
- .pll_div_regs = { 0x62, 0x54, 0x87, 0x01, 0x80, 0x40 },
- }, {
- .pixclk = 80000000,
- .pll_div_regs = { 0x64, 0x50, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x62, 0x54, 0x87, 0x01, 0x80, 0x40 },
+ }, {
.pixclk = 82000000,
- .pll_div_regs = { 0x66, 0x54, 0x82, 0x01, 0x88, 0x45 },
+ .pll_div_regs = { 0xd1, 0x66, 0x54, 0x82, 0x01, 0x88, 0x45 },
}, {
.pixclk = 82500000,
- .pll_div_regs = { 0x67, 0x54, 0x88, 0x01, 0x90, 0x49 },
+ .pll_div_regs = { 0xd1, 0x67, 0x54, 0x88, 0x01, 0x90, 0x49 },
}, {
.pixclk = 89000000,
- .pll_div_regs = { 0x70, 0x54, 0x84, 0x83, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x70, 0x54, 0x84, 0x83, 0x80, 0x40 },
}, {
.pixclk = 90000000,
- .pll_div_regs = { 0x70, 0x54, 0x82, 0x01, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x70, 0x54, 0x82, 0x01, 0x80, 0x40 },
}, {
.pixclk = 94000000,
- .pll_div_regs = { 0x4e, 0x32, 0xa7, 0x10, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x4e, 0x32, 0xa7, 0x10, 0x80, 0x40 },
}, {
.pixclk = 95000000,
- .pll_div_regs = { 0x50, 0x31, 0x86, 0x85, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x50, 0x31, 0x86, 0x85, 0x80, 0x40 },
}, {
.pixclk = 98901099,
- .pll_div_regs = { 0x52, 0x3a, 0xdb, 0x4c, 0x88, 0x47 },
+ .pll_div_regs = { 0xd1, 0x52, 0x3a, 0xdb, 0x4c, 0x88, 0x47 },
}, {
.pixclk = 99000000,
- .pll_div_regs = { 0x52, 0x32, 0x82, 0x01, 0x88, 0x47 },
+ .pll_div_regs = { 0xd1, 0x52, 0x32, 0x82, 0x01, 0x88, 0x47 },
}, {
.pixclk = 100699300,
- .pll_div_regs = { 0x54, 0x3c, 0xc3, 0x8f, 0x80, 0x40 },
- }, {
- .pixclk = 100800000,
- .pll_div_regs = { 0x54, 0x30, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x54, 0x3c, 0xc3, 0x8f, 0x80, 0x40 },
+ }, {
.pixclk = 102500000,
- .pll_div_regs = { 0x55, 0x32, 0x8c, 0x05, 0x90, 0x4b },
+ .pll_div_regs = { 0xd1, 0x55, 0x32, 0x8c, 0x05, 0x90, 0x4b },
}, {
.pixclk = 104750000,
- .pll_div_regs = { 0x57, 0x32, 0x98, 0x07, 0x90, 0x49 },
+ .pll_div_regs = { 0xd1, 0x57, 0x32, 0x98, 0x07, 0x90, 0x49 },
}, {
.pixclk = 106500000,
- .pll_div_regs = { 0x58, 0x32, 0x84, 0x03, 0x82, 0x41 },
+ .pll_div_regs = { 0xd1, 0x58, 0x32, 0x84, 0x03, 0x82, 0x41 },
}, {
.pixclk = 107000000,
- .pll_div_regs = { 0x5a, 0x32, 0x89, 0x88, 0x80, 0x40 },
- }, {
- .pixclk = 108000000,
- .pll_div_regs = { 0x5a, 0x30, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x5a, 0x32, 0x89, 0x88, 0x80, 0x40 },
+ }, {
.pixclk = 108108000,
- .pll_div_regs = { 0x5a, 0x32, 0xfd, 0x0c, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x5a, 0x32, 0xfd, 0x0c, 0x80, 0x40 },
}, {
.pixclk = 118000000,
- .pll_div_regs = { 0x62, 0x34, 0x95, 0x08, 0x80, 0x40 },
- }, {
- .pixclk = 118800000,
- .pll_div_regs = { 0x63, 0x30, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x62, 0x34, 0x95, 0x08, 0x80, 0x40 },
+ }, {
.pixclk = 123000000,
- .pll_div_regs = { 0x66, 0x34, 0x82, 0x01, 0x88, 0x45 },
+ .pll_div_regs = { 0xd1, 0x66, 0x34, 0x82, 0x01, 0x88, 0x45 },
}, {
.pixclk = 127000000,
- .pll_div_regs = { 0x69, 0x34, 0x89, 0x08, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x69, 0x34, 0x89, 0x08, 0x80, 0x40 },
}, {
.pixclk = 135000000,
- .pll_div_regs = { 0x70, 0x34, 0x82, 0x01, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x70, 0x34, 0x82, 0x01, 0x80, 0x40 },
}, {
.pixclk = 135580000,
- .pll_div_regs = { 0x71, 0x39, 0xe9, 0x82, 0x9c, 0x5b },
+ .pll_div_regs = { 0xd1, 0x71, 0x39, 0xe9, 0x82, 0x9c, 0x5b },
}, {
.pixclk = 137520000,
- .pll_div_regs = { 0x72, 0x38, 0x99, 0x10, 0x85, 0x41 },
+ .pll_div_regs = { 0xd1, 0x72, 0x38, 0x99, 0x10, 0x85, 0x41 },
}, {
.pixclk = 138750000,
- .pll_div_regs = { 0x73, 0x35, 0x88, 0x05, 0x90, 0x4d },
+ .pll_div_regs = { 0xd1, 0x73, 0x35, 0x88, 0x05, 0x90, 0x4d },
}, {
.pixclk = 140000000,
- .pll_div_regs = { 0x75, 0x36, 0xa7, 0x90, 0x80, 0x40 },
- }, {
- .pixclk = 144000000,
- .pll_div_regs = { 0x78, 0x30, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x75, 0x36, 0xa7, 0x90, 0x80, 0x40 },
+ }, {
.pixclk = 148352000,
- .pll_div_regs = { 0x7b, 0x35, 0xdb, 0x39, 0x90, 0x45 },
+ .pll_div_regs = { 0xd1, 0x7b, 0x35, 0xdb, 0x39, 0x90, 0x45 },
}, {
.pixclk = 148500000,
- .pll_div_regs = { 0x7b, 0x35, 0x84, 0x03, 0x90, 0x45 },
+ .pll_div_regs = { 0xd1, 0x7b, 0x35, 0x84, 0x03, 0x90, 0x45 },
}, {
.pixclk = 154000000,
- .pll_div_regs = { 0x40, 0x18, 0x83, 0x01, 0x00, 0x40 },
+ .pll_div_regs = { 0xd1, 0x40, 0x18, 0x83, 0x01, 0x00, 0x40 },
}, {
.pixclk = 157000000,
- .pll_div_regs = { 0x41, 0x11, 0xa7, 0x14, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x41, 0x11, 0xa7, 0x14, 0x80, 0x40 },
}, {
.pixclk = 160000000,
- .pll_div_regs = { 0x42, 0x12, 0xa1, 0x20, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x42, 0x12, 0xa1, 0x20, 0x80, 0x40 },
}, {
.pixclk = 162000000,
- .pll_div_regs = { 0x43, 0x18, 0x8b, 0x08, 0x96, 0x55 },
+ .pll_div_regs = { 0xd1, 0x43, 0x18, 0x8b, 0x08, 0x96, 0x55 },
}, {
.pixclk = 164000000,
- .pll_div_regs = { 0x45, 0x11, 0x83, 0x82, 0x90, 0x4b },
+ .pll_div_regs = { 0xd1, 0x45, 0x11, 0x83, 0x82, 0x90, 0x4b },
}, {
.pixclk = 165000000,
- .pll_div_regs = { 0x45, 0x11, 0x84, 0x81, 0x90, 0x4b },
- }, {
- .pixclk = 180000000,
- .pll_div_regs = { 0x4b, 0x10, 0x00, 0x00, 0x80, 0x00 },
+ .pll_div_regs = { 0xd1, 0x45, 0x11, 0x84, 0x81, 0x90, 0x4b },
}, {
.pixclk = 185625000,
- .pll_div_regs = { 0x4e, 0x12, 0x9a, 0x95, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x4e, 0x12, 0x9a, 0x95, 0x80, 0x40 },
}, {
.pixclk = 188000000,
- .pll_div_regs = { 0x4e, 0x12, 0xa7, 0x10, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x4e, 0x12, 0xa7, 0x10, 0x80, 0x40 },
}, {
.pixclk = 198000000,
- .pll_div_regs = { 0x52, 0x12, 0x82, 0x01, 0x88, 0x47 },
+ .pll_div_regs = { 0xd1, 0x52, 0x12, 0x82, 0x01, 0x88, 0x47 },
}, {
.pixclk = 205000000,
- .pll_div_regs = { 0x55, 0x12, 0x8c, 0x05, 0x90, 0x4b },
+ .pll_div_regs = { 0xd1, 0x55, 0x12, 0x8c, 0x05, 0x90, 0x4b },
}, {
.pixclk = 209500000,
- .pll_div_regs = { 0x57, 0x12, 0x98, 0x07, 0x90, 0x49 },
+ .pll_div_regs = { 0xd1, 0x57, 0x12, 0x98, 0x07, 0x90, 0x49 },
}, {
.pixclk = 213000000,
- .pll_div_regs = { 0x58, 0x12, 0x84, 0x03, 0x82, 0x41 },
- }, {
- .pixclk = 216000000,
- .pll_div_regs = { 0x5a, 0x10, 0x00, 0x00, 0x80, 0x00 },
+ .pll_div_regs = { 0xd1, 0x58, 0x12, 0x84, 0x03, 0x82, 0x41 },
}, {
.pixclk = 216216000,
- .pll_div_regs = { 0x5a, 0x12, 0xfd, 0x0c, 0x80, 0x40 },
- }, {
- .pixclk = 237600000,
- .pll_div_regs = { 0x63, 0x10, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x5a, 0x12, 0xfd, 0x0c, 0x80, 0x40 },
+ }, {
.pixclk = 254000000,
- .pll_div_regs = { 0x69, 0x14, 0x89, 0x08, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x69, 0x14, 0x89, 0x08, 0x80, 0x40 },
}, {
.pixclk = 277500000,
- .pll_div_regs = { 0x73, 0x15, 0x88, 0x05, 0x90, 0x4d },
- }, {
- .pixclk = 288000000,
- .pll_div_regs = { 0x78, 0x10, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x73, 0x15, 0x88, 0x05, 0x90, 0x4d },
+ }, {
.pixclk = 297000000,
- .pll_div_regs = { 0x7b, 0x15, 0x84, 0x03, 0x90, 0x45 },
+ .pll_div_regs = { 0xd1, 0x7b, 0x15, 0x84, 0x03, 0x90, 0x45 },
},
};
@@ -369,29 +282,30 @@ struct reg_settings {
};
static const struct reg_settings common_phy_cfg[] = {
- { PHY_REG_00, 0x00 }, { PHY_REG_01, 0xd1 },
- { PHY_REG_08, 0x4f }, { PHY_REG_09, 0x30 },
- { PHY_REG_10, 0x33 }, { PHY_REG_11, 0x65 },
+ { PHY_REG(0), 0x00 },
+ /* PHY_REG(1-7) pix clk specific */
+ { PHY_REG(8), 0x4f }, { PHY_REG(9), 0x30 },
+ { PHY_REG(10), 0x33 }, { PHY_REG(11), 0x65 },
/* REG12 pixclk specific */
/* REG13 pixclk specific */
/* REG14 pixclk specific */
- { PHY_REG_15, 0x80 }, { PHY_REG_16, 0x6c },
- { PHY_REG_17, 0xf2 }, { PHY_REG_18, 0x67 },
- { PHY_REG_19, 0x00 }, { PHY_REG_20, 0x10 },
+ { PHY_REG(15), 0x80 }, { PHY_REG(16), 0x6c },
+ { PHY_REG(17), 0xf2 }, { PHY_REG(18), 0x67 },
+ { PHY_REG(19), 0x00 }, { PHY_REG(20), 0x10 },
/* REG21 pixclk specific */
- { PHY_REG_22, 0x30 }, { PHY_REG_23, 0x32 },
- { PHY_REG_24, 0x60 }, { PHY_REG_25, 0x8f },
- { PHY_REG_26, 0x00 }, { PHY_REG_27, 0x00 },
- { PHY_REG_28, 0x08 }, { PHY_REG_29, 0x00 },
- { PHY_REG_30, 0x00 }, { PHY_REG_31, 0x00 },
- { PHY_REG_32, 0x00 }, { PHY_REG_33, 0x80 },
- { PHY_REG_34, 0x00 }, { PHY_REG_35, 0x00 },
- { PHY_REG_36, 0x00 }, { PHY_REG_37, 0x00 },
- { PHY_REG_38, 0x00 }, { PHY_REG_39, 0x00 },
- { PHY_REG_40, 0x00 }, { PHY_REG_41, 0xe0 },
- { PHY_REG_42, 0x83 }, { PHY_REG_43, 0x0f },
- { PHY_REG_44, 0x3E }, { PHY_REG_45, 0xf8 },
- { PHY_REG_46, 0x00 }, { PHY_REG_47, 0x00 }
+ { PHY_REG(22), 0x30 }, { PHY_REG(23), 0x32 },
+ { PHY_REG(24), 0x60 }, { PHY_REG(25), 0x8f },
+ { PHY_REG(26), 0x00 }, { PHY_REG(27), 0x00 },
+ { PHY_REG(28), 0x08 }, { PHY_REG(29), 0x00 },
+ { PHY_REG(30), 0x00 }, { PHY_REG(31), 0x00 },
+ { PHY_REG(32), 0x00 }, { PHY_REG(33), 0x80 },
+ { PHY_REG(34), 0x00 }, { PHY_REG(35), 0x00 },
+ { PHY_REG(36), 0x00 }, { PHY_REG(37), 0x00 },
+ { PHY_REG(38), 0x00 }, { PHY_REG(39), 0x00 },
+ { PHY_REG(40), 0x00 }, { PHY_REG(41), 0xe0 },
+ { PHY_REG(42), 0x83 }, { PHY_REG(43), 0x0f },
+ { PHY_REG(44), 0x3E }, { PHY_REG(45), 0xf8 },
+ { PHY_REG(46), 0x00 }, { PHY_REG(47), 0x00 }
};
struct fsl_samsung_hdmi_phy {
@@ -412,40 +326,6 @@ to_fsl_samsung_hdmi_phy(struct clk_hw *hw)
}
static void
-fsl_samsung_hdmi_phy_configure_pixclk(struct fsl_samsung_hdmi_phy *phy,
- const struct phy_config *cfg)
-{
- u8 div = 0x1;
-
- switch (cfg->pixclk) {
- case 22250000 ... 33750000:
- div = 0xf;
- break;
- case 35000000 ... 40000000:
- div = 0xb;
- break;
- case 43200000 ... 47500000:
- div = 0x9;
- break;
- case 50349650 ... 63500000:
- div = 0x7;
- break;
- case 67500000 ... 90000000:
- div = 0x5;
- break;
- case 94000000 ... 148500000:
- div = 0x3;
- break;
- case 154000000 ... 297000000:
- div = 0x1;
- break;
- }
-
- writeb(REG21_SEL_TX_CK_INV | FIELD_PREP(REG21_PMS_S_MASK, div),
- phy->regs + PHY_REG_21);
-}
-
-static void
fsl_samsung_hdmi_phy_configure_pll_lock_det(struct fsl_samsung_hdmi_phy *phy,
const struct phy_config *cfg)
{
@@ -469,7 +349,7 @@ fsl_samsung_hdmi_phy_configure_pll_lock_det(struct fsl_samsung_hdmi_phy *phy,
break;
}
- writeb(FIELD_PREP(REG12_CK_DIV_MASK, ilog2(div)), phy->regs + PHY_REG_12);
+ writeb(FIELD_PREP(REG12_CK_DIV_MASK, ilog2(div)), phy->regs + PHY_REG(12));
/*
* Calculation for the frequency lock detector target code (fld_tg_code)
@@ -489,11 +369,88 @@ fsl_samsung_hdmi_phy_configure_pll_lock_det(struct fsl_samsung_hdmi_phy *phy,
/* FLD_TOL and FLD_RP_CODE taken from downstream driver */
writeb(FIELD_PREP(REG13_TG_CODE_LOW_MASK, fld_tg_code),
- phy->regs + PHY_REG_13);
+ phy->regs + PHY_REG(13));
writeb(FIELD_PREP(REG14_TOL_MASK, 2) |
FIELD_PREP(REG14_RP_CODE_MASK, 2) |
FIELD_PREP(REG14_TG_CODE_HIGH_MASK, fld_tg_code >> 8),
- phy->regs + PHY_REG_14);
+ phy->regs + PHY_REG(14));
+}
+
+static unsigned long fsl_samsung_hdmi_phy_find_pms(unsigned long fout, u8 *p, u16 *m, u8 *s)
+{
+ unsigned long best_freq = 0;
+ u32 min_delta = 0xffffffff;
+ u8 _p, best_p;
+ u16 _m, best_m;
+ u8 _s, best_s;
+
+ /*
+ * Figure 13-78 of the reference manual states the PLL should be TMDS x 5
+ * while the TMDS_CLKO should be the PLL / 5. So to calculate the PLL,
+ * take the pix clock x 5, then return the value of the PLL / 5.
+ */
+ fout *= 5;
+
+ /* The ref manual states the values of 'P' range from 1 to 11 */
+ for (_p = 1; _p <= 11; ++_p) {
+ for (_s = 1; _s <= 16; ++_s) {
+ u64 tmp;
+ u32 delta;
+
+ /* s must be one or even */
+ if (_s > 1 && (_s & 0x01) == 1)
+ _s++;
+
+ /* _s cannot be 14 per the TRM */
+ if (_s == 14)
+ continue;
+
+ /*
+ * TODO: Ref Manual doesn't state the range of _m
+ * so this should be further refined if possible.
+ * This range was set based on the original values
+ * in the lookup table
+ */
+ tmp = (u64)fout * (_p * _s);
+ do_div(tmp, 24 * MHZ);
+ _m = tmp;
+ if (_m < 0x30 || _m > 0x7b)
+ continue;
+
+ /*
+ * Rev 2 of the Ref Manual states the
+ * VCO can range between 750MHz and
+ * 3GHz. The VCO is assumed to be
+ * Fvco = (M * f_ref) / P,
+ * where f_ref is 24MHz.
+ */
+ tmp = (u64)_m * 24 * MHZ;
+ do_div(tmp, _p);
+ if (tmp < 750 * MHZ ||
+ tmp > 3000 * MHZ)
+ continue;
+
+ /* Final frequency after post-divider */
+ do_div(tmp, _s);
+
+ delta = abs(fout - tmp);
+ if (delta < min_delta) {
+ best_p = _p;
+ best_s = _s;
+ best_m = _m;
+ min_delta = delta;
+ best_freq = tmp;
+ }
+ }
+ }
+
+ if (best_freq) {
+ *p = best_p;
+ *m = best_m;
+ *s = best_s;
+ }
+
+ return best_freq / 5;
}
static int fsl_samsung_hdmi_phy_configure(struct fsl_samsung_hdmi_phy *phy,
@@ -503,22 +460,25 @@ static int fsl_samsung_hdmi_phy_configure(struct fsl_samsung_hdmi_phy *phy,
u8 val;
/* HDMI PHY init */
- writeb(REG33_FIX_DA, phy->regs + PHY_REG_33);
+ writeb(REG33_FIX_DA, phy->regs + PHY_REG(33));
/* common PHY registers */
for (i = 0; i < ARRAY_SIZE(common_phy_cfg); i++)
writeb(common_phy_cfg[i].val, phy->regs + common_phy_cfg[i].reg);
- /* set individual PLL registers PHY_REG2 ... PHY_REG7 */
+ /* set individual PLL registers PHY_REG1 ... PHY_REG7 */
for (i = 0; i < PHY_PLL_DIV_REGS_NUM; i++)
- writeb(cfg->pll_div_regs[i], phy->regs + PHY_REG_02 + i * 4);
+ writeb(cfg->pll_div_regs[i], phy->regs + PHY_REG(1) + i * 4);
+
+ /* High nibble of PHY_REG3 and low nibble of PHY_REG21 both contain 'S' */
+ writeb(REG21_SEL_TX_CK_INV | FIELD_PREP(REG21_PMS_S_MASK,
+ cfg->pll_div_regs[2] >> 4), phy->regs + PHY_REG(21));
- fsl_samsung_hdmi_phy_configure_pixclk(phy, cfg);
fsl_samsung_hdmi_phy_configure_pll_lock_det(phy, cfg);
- writeb(REG33_FIX_DA | REG33_MODE_SET_DONE, phy->regs + PHY_REG_33);
+ writeb(REG33_FIX_DA | REG33_MODE_SET_DONE, phy->regs + PHY_REG(33));
- ret = readb_poll_timeout(phy->regs + PHY_REG_34, val,
+ ret = readb_poll_timeout(phy->regs + PHY_REG(34), val,
val & REG34_PLL_LOCK, 50, 20000);
if (ret)
dev_err(phy->dev, "PLL failed to lock\n");
@@ -537,34 +497,120 @@ static unsigned long phy_clk_recalc_rate(struct clk_hw *hw,
return phy->cur_cfg->pixclk;
}
-static long phy_clk_round_rate(struct clk_hw *hw,
- unsigned long rate, unsigned long *parent_rate)
+/* Helper function to lookup the available fractional-divider rate */
+static const struct phy_config *fsl_samsung_hdmi_phy_lookup_rate(unsigned long rate)
{
int i;
+ /* Search the lookup table */
for (i = ARRAY_SIZE(phy_pll_cfg) - 1; i >= 0; i--)
if (phy_pll_cfg[i].pixclk <= rate)
- return phy_pll_cfg[i].pixclk;
+ break;
- return -EINVAL;
+ return &phy_pll_cfg[i];
+}
+
+static void fsl_samsung_hdmi_calculate_phy(struct phy_config *cal_phy, unsigned long rate,
+ u8 p, u16 m, u8 s)
+{
+ cal_phy->pixclk = rate;
+ cal_phy->pll_div_regs[0] = FIELD_PREP(REG01_PMS_P_MASK, p);
+ cal_phy->pll_div_regs[1] = m;
+ cal_phy->pll_div_regs[2] = FIELD_PREP(REG03_PMS_S_MASK, s-1);
+ /* pll_div_regs 3-6 are fixed and pre-defined already */
+}
+
+static u32 fsl_samsung_hdmi_phy_get_closest_rate(unsigned long rate,
+ u32 int_div_clk, u32 frac_div_clk)
+{
+ /* Calculate the absolute value of the differences and return whichever is closest */
+ if (abs((long)rate - (long)int_div_clk) < abs((long)(rate - (long)frac_div_clk)))
+ return int_div_clk;
+
+ return frac_div_clk;
+}
+
+static long phy_clk_round_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long *parent_rate)
+{
+ const struct phy_config *fract_div_phy;
+ u32 int_div_clk;
+ u16 m;
+ u8 p, s;
+
+ /* If the clock is out of range return error instead of searching */
+ if (rate > 297000000 || rate < 22250000)
+ return -EINVAL;
+
+ /* Search the fractional divider lookup table */
+ fract_div_phy = fsl_samsung_hdmi_phy_lookup_rate(rate);
+
+ /* If the rate is an exact match, return that value */
+ if (rate == fract_div_phy->pixclk)
+ return fract_div_phy->pixclk;
+
+ /* If the exact match isn't found, calculate the integer divider */
+ int_div_clk = fsl_samsung_hdmi_phy_find_pms(rate, &p, &m, &s);
+
+ /* If the int_div_clk rate is an exact match, return that value */
+ if (int_div_clk == rate)
+ return int_div_clk;
+
+ /* If neither rate is an exact match, use the value from the LUT */
+ return fract_div_phy->pixclk;
+}
+
+static int phy_use_fract_div(struct fsl_samsung_hdmi_phy *phy, const struct phy_config *fract_div_phy)
+{
+ phy->cur_cfg = fract_div_phy;
+ dev_dbg(phy->dev, "fsl_samsung_hdmi_phy: using fractional divider rate = %u\n",
+ phy->cur_cfg->pixclk);
+ return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
+}
+
+static int phy_use_integer_div(struct fsl_samsung_hdmi_phy *phy,
+ const struct phy_config *int_div_clk)
+{
+ phy->cur_cfg = &calculated_phy_pll_cfg;
+ dev_dbg(phy->dev, "fsl_samsung_hdmi_phy: integer divider rate = %u\n",
+ phy->cur_cfg->pixclk);
+ return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
}
static int phy_clk_set_rate(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate)
{
struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw);
- int i;
+ const struct phy_config *fract_div_phy;
+ u32 int_div_clk;
+ u16 m;
+ u8 p, s;
- for (i = ARRAY_SIZE(phy_pll_cfg) - 1; i >= 0; i--)
- if (phy_pll_cfg[i].pixclk <= rate)
- break;
+ /* Search the fractional divider lookup table */
+ fract_div_phy = fsl_samsung_hdmi_phy_lookup_rate(rate);
- if (i < 0)
- return -EINVAL;
+ /* If the rate is an exact match, use that value */
+ if (fract_div_phy->pixclk == rate)
+ return phy_use_fract_div(phy, fract_div_phy);
- phy->cur_cfg = &phy_pll_cfg[i];
+ /*
+ * If the rate from the fractional divider is not exact, check the integer divider,
+ * and use it if that value is an exact match.
+ */
+ int_div_clk = fsl_samsung_hdmi_phy_find_pms(rate, &p, &m, &s);
+ fsl_samsung_hdmi_calculate_phy(&calculated_phy_pll_cfg, int_div_clk, p, m, s);
+ if (int_div_clk == rate)
+ return phy_use_integer_div(phy, &calculated_phy_pll_cfg);
- return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
+ /*
+ * Compare the difference between the integer clock and the fractional clock against
+ * the desired clock and which whichever is closest.
+ */
+ if (fsl_samsung_hdmi_phy_get_closest_rate(rate, int_div_clk,
+ fract_div_phy->pixclk) == fract_div_phy->pixclk)
+ return phy_use_fract_div(phy, fract_div_phy);
+ else
+ return phy_use_integer_div(phy, &calculated_phy_pll_cfg);
}
static const struct clk_ops phy_clk_ops = {
@@ -703,8 +749,8 @@ static const struct of_device_id fsl_samsung_hdmi_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, fsl_samsung_hdmi_phy_of_match);
static struct platform_driver fsl_samsung_hdmi_phy_driver = {
- .probe = fsl_samsung_hdmi_phy_probe,
- .remove_new = fsl_samsung_hdmi_phy_remove,
+ .probe = fsl_samsung_hdmi_phy_probe,
+ .remove = fsl_samsung_hdmi_phy_remove,
.driver = {
.name = "fsl-samsung-hdmi-phy",
.of_match_table = fsl_samsung_hdmi_phy_of_match,
diff --git a/drivers/phy/intel/phy-intel-lgm-combo.c b/drivers/phy/intel/phy-intel-lgm-combo.c
index f8e3054a9e59..9ee3cf61cdd0 100644
--- a/drivers/phy/intel/phy-intel-lgm-combo.c
+++ b/drivers/phy/intel/phy-intel-lgm-combo.c
@@ -605,7 +605,7 @@ static const struct of_device_id of_intel_cbphy_match[] = {
static struct platform_driver intel_cbphy_driver = {
.probe = intel_cbphy_probe,
- .remove_new = intel_cbphy_remove,
+ .remove = intel_cbphy_remove,
.driver = {
.name = "intel-combo-phy",
.of_match_table = of_intel_cbphy_match,
diff --git a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c
index 4922a5f3327d..59903f86b13f 100644
--- a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c
+++ b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c
@@ -62,6 +62,8 @@
#define SQ_AMP_CAL_MASK GENMASK(2, 0)
#define SQ_AMP_CAL_VAL 1
#define SQ_AMP_CAL_EN BIT(3)
+#define UTMI_DIG_CTRL1_REG 0x20
+#define SWAP_DPDM BIT(15)
#define UTMI_CTRL_STATUS0_REG 0x24
#define SUSPENDM BIT(22)
#define TEST_SEL BIT(25)
@@ -99,11 +101,13 @@ struct mvebu_cp110_utmi {
* @priv: PHY driver data
* @id: PHY port ID
* @dr_mode: PHY connection: USB_DR_MODE_HOST or USB_DR_MODE_PERIPHERAL
+ * @swap_dx: whether to swap d+/d- signals
*/
struct mvebu_cp110_utmi_port {
struct mvebu_cp110_utmi *priv;
u32 id;
enum usb_dr_mode dr_mode;
+ bool swap_dx;
};
static void mvebu_cp110_utmi_port_setup(struct mvebu_cp110_utmi_port *port)
@@ -159,6 +163,13 @@ static void mvebu_cp110_utmi_port_setup(struct mvebu_cp110_utmi_port *port)
reg &= ~(VDAT_MASK | VSRC_MASK);
reg |= (VDAT_VAL << VDAT_OFFSET) | (VSRC_VAL << VSRC_OFFSET);
writel(reg, PORT_REGS(port) + UTMI_CHGDTC_CTRL_REG);
+
+ /* Swap D+/D- */
+ reg = readl(PORT_REGS(port) + UTMI_DIG_CTRL1_REG);
+ reg &= ~(SWAP_DPDM);
+ if (port->swap_dx)
+ reg |= SWAP_DPDM;
+ writel(reg, PORT_REGS(port) + UTMI_DIG_CTRL1_REG);
}
static int mvebu_cp110_utmi_phy_power_off(struct phy *phy)
@@ -286,6 +297,7 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
struct phy_provider *provider;
struct device_node *child;
u32 usb_devices = 0;
+ u32 swap_dx = 0;
utmi = devm_kzalloc(dev, sizeof(*utmi), GFP_KERNEL);
if (!utmi)
@@ -345,6 +357,10 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
}
}
+ of_property_for_each_u32(dev->of_node, "swap-dx-lanes", swap_dx)
+ if (swap_dx == port_id)
+ port->swap_dx = 1;
+
/* Retrieve PHY capabilities */
utmi->ops = &mvebu_cp110_utmi_phy_ops;
diff --git a/drivers/phy/microchip/sparx5_serdes.c b/drivers/phy/microchip/sparx5_serdes.c
index 7cb85029fab3..320cf5b50a8c 100644
--- a/drivers/phy/microchip/sparx5_serdes.c
+++ b/drivers/phy/microchip/sparx5_serdes.c
@@ -21,23 +21,33 @@
#include "sparx5_serdes.h"
-#define SPX5_CMU_MAX 14
-
#define SPX5_SERDES_10G_START 13
#define SPX5_SERDES_25G_START 25
#define SPX5_SERDES_6G10G_CNT SPX5_SERDES_25G_START
+#define LAN969X_SERDES_10G_CNT 10
+
/* Optimal power settings from GUC */
#define SPX5_SERDES_QUIET_MODE_VAL 0x01ef4e0c
-enum sparx5_10g28cmu_mode {
- SPX5_SD10G28_CMU_MAIN = 0,
- SPX5_SD10G28_CMU_AUX1 = 1,
- SPX5_SD10G28_CMU_AUX2 = 3,
- SPX5_SD10G28_CMU_NONE = 4,
- SPX5_SD10G28_CMU_MAX,
+/* Register target sizes */
+const unsigned int sparx5_serdes_tsize[TSIZE_LAST] = {
+ [TC_SD10G_LANE] = 12,
+ [TC_SD_CMU] = 14,
+ [TC_SD_CMU_CFG] = 14,
+ [TC_SD_LANE] = 25,
+};
+
+const unsigned int lan969x_serdes_tsize[TSIZE_LAST] = {
+ [TC_SD10G_LANE] = 10,
+ [TC_SD_CMU] = 6,
+ [TC_SD_CMU_CFG] = 6,
+ [TC_SD_LANE] = 10,
};
+/* Pointer to the register target size table */
+const unsigned int *tsize;
+
enum sparx5_sd25g28_mode_preset_type {
SPX5_SD25G28_MODE_PRESET_25000,
SPX5_SD25G28_MODE_PRESET_10000,
@@ -1095,13 +1105,31 @@ static int sparx5_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index)
return sparx5_serdes_cmu_map[mode][sd_index];
}
+/* Map of 6G/10G serdes mode and index to CMU index. */
+static const int
+lan969x_serdes_cmu_map[SPX5_SD10G28_CMU_MAX][LAN969X_SERDES_10G_CNT] = {
+ [SPX5_SD10G28_CMU_MAIN] = { 2, 2, 2, 2, 2,
+ 2, 2, 2, 5, 5 },
+ [SPX5_SD10G28_CMU_AUX1] = { 0, 0, 3, 3, 3,
+ 3, 3, 3, 3, 3 },
+ [SPX5_SD10G28_CMU_AUX2] = { 1, 1, 1, 1, 4,
+ 4, 4, 4, 4, 4 },
+ [SPX5_SD10G28_CMU_NONE] = { 1, 1, 1, 1, 4,
+ 4, 4, 4, 4, 4 },
+};
+
+static int lan969x_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index)
+{
+ return lan969x_serdes_cmu_map[mode][sd_index];
+}
+
static void sparx5_serdes_cmu_power_off(struct sparx5_serdes_private *priv)
{
void __iomem *cmu_inst, *cmu_cfg_inst;
int i;
/* Power down each CMU */
- for (i = 0; i < SPX5_CMU_MAX; i++) {
+ for (i = 0; i < priv->data->consts.cmu_max; i++) {
cmu_inst = sdx5_inst_get(priv, TARGET_SD_CMU, i);
cmu_cfg_inst = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, i);
@@ -1650,7 +1678,7 @@ static int sparx5_sd10g28_apply_params(struct sparx5_serdes_macro *macro,
if (params->skip_cmu_cfg)
return 0;
- cmu_idx = sparx5_serdes_cmu_get(params->cmu_sel, lane_index);
+ cmu_idx = priv->data->ops.serdes_cmu_get(params->cmu_sel, macro->sidx);
err = sparx5_cmu_cfg(priv, cmu_idx);
if (err)
return err;
@@ -2183,6 +2211,10 @@ static int sparx5_serdes_clock_config(struct sparx5_serdes_macro *macro)
{
struct sparx5_serdes_private *priv = macro->priv;
+ /* Clock is auto-detected in 100Base-FX mode on lan969x */
+ if (priv->data->type == SPX5_TARGET_LAN969X)
+ return 0;
+
if (macro->serdesmode == SPX5_SD_MODE_100FX) {
u32 freq = priv->coreclock == 250000000 ? 2 :
priv->coreclock == 500000000 ? 1 : 0;
@@ -2297,10 +2329,12 @@ static int sparx5_serdes_set_speed(struct phy *phy, int speed)
{
struct sparx5_serdes_macro *macro = phy_get_drvdata(phy);
- if (macro->sidx < SPX5_SERDES_10G_START && speed > SPEED_5000)
- return -EINVAL;
- if (macro->sidx < SPX5_SERDES_25G_START && speed > SPEED_10000)
- return -EINVAL;
+ if (macro->priv->data->type == SPX5_TARGET_SPARX5) {
+ if (macro->sidx < SPX5_SERDES_10G_START && speed > SPEED_5000)
+ return -EINVAL;
+ if (macro->sidx < SPX5_SERDES_25G_START && speed > SPEED_10000)
+ return -EINVAL;
+ }
if (speed != macro->speed) {
macro->speed = speed;
if (macro->serdesmode != SPX5_SD_MODE_NONE)
@@ -2337,11 +2371,14 @@ static int sparx5_serdes_validate(struct phy *phy, enum phy_mode mode,
if (macro->speed == 0)
return -EINVAL;
- if (macro->sidx < SPX5_SERDES_10G_START && macro->speed > SPEED_5000)
- return -EINVAL;
- if (macro->sidx < SPX5_SERDES_25G_START && macro->speed > SPEED_10000)
- return -EINVAL;
-
+ if (macro->priv->data->type == SPX5_TARGET_SPARX5) {
+ if (macro->sidx < SPX5_SERDES_10G_START &&
+ macro->speed > SPEED_5000)
+ return -EINVAL;
+ if (macro->sidx < SPX5_SERDES_25G_START &&
+ macro->speed > SPEED_10000)
+ return -EINVAL;
+ }
switch (submode) {
case PHY_INTERFACE_MODE_1000BASEX:
if (macro->speed != SPEED_100 && /* This is for 100BASE-FX */
@@ -2375,6 +2412,26 @@ static const struct phy_ops sparx5_serdes_ops = {
.owner = THIS_MODULE,
};
+static void sparx5_serdes_type_set(struct sparx5_serdes_macro *macro, int sidx)
+{
+ if (sidx < SPX5_SERDES_10G_START) {
+ macro->serdestype = SPX5_SDT_6G;
+ macro->stpidx = macro->sidx;
+ } else if (sidx < SPX5_SERDES_25G_START) {
+ macro->serdestype = SPX5_SDT_10G;
+ macro->stpidx = macro->sidx - SPX5_SERDES_10G_START;
+ } else {
+ macro->serdestype = SPX5_SDT_25G;
+ macro->stpidx = macro->sidx - SPX5_SERDES_25G_START;
+ }
+}
+
+static void lan969x_serdes_type_set(struct sparx5_serdes_macro *macro, int sidx)
+{
+ macro->serdestype = SPX5_SDT_10G;
+ macro->stpidx = macro->sidx;
+}
+
static int sparx5_phy_create(struct sparx5_serdes_private *priv,
int idx, struct phy **phy)
{
@@ -2391,16 +2448,8 @@ static int sparx5_phy_create(struct sparx5_serdes_private *priv,
macro->sidx = idx;
macro->priv = priv;
macro->speed = SPEED_UNKNOWN;
- if (idx < SPX5_SERDES_10G_START) {
- macro->serdestype = SPX5_SDT_6G;
- macro->stpidx = macro->sidx;
- } else if (idx < SPX5_SERDES_25G_START) {
- macro->serdestype = SPX5_SDT_10G;
- macro->stpidx = macro->sidx - SPX5_SERDES_10G_START;
- } else {
- macro->serdestype = SPX5_SDT_25G;
- macro->stpidx = macro->sidx - SPX5_SERDES_25G_START;
- }
+
+ priv->data->ops.serdes_type_set(macro, idx);
phy_set_drvdata(*phy, macro);
@@ -2507,6 +2556,71 @@ static struct sparx5_serdes_io_resource sparx5_serdes_iomap[] = {
{ TARGET_SD_LANE_25G + 7, 0x5c8000 }, /* 0x610dd0000: sd_lane_25g_32 */
};
+static const struct sparx5_serdes_io_resource lan969x_serdes_iomap[] = {
+ { TARGET_SD_CMU, 0x0 }, /* 0xe3410000 */
+ { TARGET_SD_CMU + 1, 0x8000 }, /* 0xe3418000 */
+ { TARGET_SD_CMU + 2, 0x10000 }, /* 0xe3420000 */
+ { TARGET_SD_CMU + 3, 0x18000 }, /* 0xe3428000 */
+ { TARGET_SD_CMU + 4, 0x20000 }, /* 0xe3430000 */
+ { TARGET_SD_CMU + 5, 0x28000 }, /* 0xe3438000 */
+ { TARGET_SD_CMU_CFG, 0x30000 }, /* 0xe3440000 */
+ { TARGET_SD_CMU_CFG + 1, 0x38000 }, /* 0xe3448000 */
+ { TARGET_SD_CMU_CFG + 2, 0x40000 }, /* 0xe3450000 */
+ { TARGET_SD_CMU_CFG + 3, 0x48000 }, /* 0xe3458000 */
+ { TARGET_SD_CMU_CFG + 4, 0x50000 }, /* 0xe3460000 */
+ { TARGET_SD_CMU_CFG + 5, 0x58000 }, /* 0xe3468000 */
+ { TARGET_SD10G_LANE, 0x60000 }, /* 0xe3470000 */
+ { TARGET_SD10G_LANE + 1, 0x68000 }, /* 0xe3478000 */
+ { TARGET_SD10G_LANE + 2, 0x70000 }, /* 0xe3480000 */
+ { TARGET_SD10G_LANE + 3, 0x78000 }, /* 0xe3488000 */
+ { TARGET_SD10G_LANE + 4, 0x80000 }, /* 0xe3490000 */
+ { TARGET_SD10G_LANE + 5, 0x88000 }, /* 0xe3498000 */
+ { TARGET_SD10G_LANE + 6, 0x90000 }, /* 0xe34a0000 */
+ { TARGET_SD10G_LANE + 7, 0x98000 }, /* 0xe34a8000 */
+ { TARGET_SD10G_LANE + 8, 0xa0000 }, /* 0xe34b0000 */
+ { TARGET_SD10G_LANE + 9, 0xa8000 }, /* 0xe34b8000 */
+ { TARGET_SD_LANE, 0x100000 }, /* 0xe3510000 */
+ { TARGET_SD_LANE + 1, 0x108000 }, /* 0xe3518000 */
+ { TARGET_SD_LANE + 2, 0x110000 }, /* 0xe3520000 */
+ { TARGET_SD_LANE + 3, 0x118000 }, /* 0xe3528000 */
+ { TARGET_SD_LANE + 4, 0x120000 }, /* 0xe3530000 */
+ { TARGET_SD_LANE + 5, 0x128000 }, /* 0xe3538000 */
+ { TARGET_SD_LANE + 6, 0x130000 }, /* 0xe3540000 */
+ { TARGET_SD_LANE + 7, 0x138000 }, /* 0xe3548000 */
+ { TARGET_SD_LANE + 8, 0x140000 }, /* 0xe3550000 */
+ { TARGET_SD_LANE + 9, 0x148000 }, /* 0xe3558000 */
+};
+
+static const struct sparx5_serdes_match_data sparx5_desc = {
+ .type = SPX5_TARGET_SPARX5,
+ .iomap = sparx5_serdes_iomap,
+ .iomap_size = ARRAY_SIZE(sparx5_serdes_iomap),
+ .tsize = sparx5_serdes_tsize,
+ .consts = {
+ .sd_max = 33,
+ .cmu_max = 14,
+ },
+ .ops = {
+ .serdes_type_set = &sparx5_serdes_type_set,
+ .serdes_cmu_get = &sparx5_serdes_cmu_get,
+ },
+};
+
+static const struct sparx5_serdes_match_data lan969x_desc = {
+ .type = SPX5_TARGET_LAN969X,
+ .iomap = lan969x_serdes_iomap,
+ .iomap_size = ARRAY_SIZE(lan969x_serdes_iomap),
+ .tsize = lan969x_serdes_tsize,
+ .consts = {
+ .sd_max = 10,
+ .cmu_max = 6,
+ },
+ .ops = {
+ .serdes_type_set = &lan969x_serdes_type_set,
+ .serdes_cmu_get = &lan969x_serdes_cmu_get,
+ }
+};
+
/* Client lookup function, uses serdes index */
static struct phy *sparx5_serdes_xlate(struct device *dev,
const struct of_phandle_args *args)
@@ -2521,7 +2635,7 @@ static struct phy *sparx5_serdes_xlate(struct device *dev,
sidx = args->args[0];
/* Check validity: ERR_PTR(-ENODEV) if not valid */
- for (idx = 0; idx < SPX5_SERDES_MAX; idx++) {
+ for (idx = 0; idx < priv->data->consts.sd_max; idx++) {
struct sparx5_serdes_macro *macro =
phy_get_drvdata(priv->phys[idx]);
@@ -2555,6 +2669,12 @@ static int sparx5_serdes_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
priv->dev = &pdev->dev;
+ priv->data = device_get_match_data(priv->dev);
+ if (!priv->data)
+ return -EINVAL;
+
+ tsize = priv->data->tsize;
+
/* Get coreclock */
clk = devm_clk_get(priv->dev, NULL);
if (IS_ERR(clk)) {
@@ -2579,19 +2699,21 @@ static int sparx5_serdes_probe(struct platform_device *pdev)
iores->name);
return -ENOMEM;
}
- for (idx = 0; idx < ARRAY_SIZE(sparx5_serdes_iomap); idx++) {
- struct sparx5_serdes_io_resource *iomap = &sparx5_serdes_iomap[idx];
+ for (idx = 0; idx < priv->data->iomap_size; idx++) {
+ const struct sparx5_serdes_io_resource *iomap =
+ &priv->data->iomap[idx];
priv->regs[iomap->id] = iomem + iomap->offset;
}
- for (idx = 0; idx < SPX5_SERDES_MAX; idx++) {
+ for (idx = 0; idx < priv->data->consts.sd_max; idx++) {
err = sparx5_phy_create(priv, idx, &priv->phys[idx]);
if (err)
return err;
}
- /* Power down all CMUs by default */
- sparx5_serdes_cmu_power_off(priv);
+ /* Power down all CMU's by default */
+ if (priv->data->type == SPX5_TARGET_SPARX5)
+ sparx5_serdes_cmu_power_off(priv);
provider = devm_of_phy_provider_register(priv->dev, sparx5_serdes_xlate);
@@ -2599,7 +2721,8 @@ static int sparx5_serdes_probe(struct platform_device *pdev)
}
static const struct of_device_id sparx5_serdes_match[] = {
- { .compatible = "microchip,sparx5-serdes" },
+ { .compatible = "microchip,sparx5-serdes", .data = &sparx5_desc },
+ { .compatible = "microchip,lan9691-serdes", .data = &lan969x_desc },
{ }
};
MODULE_DEVICE_TABLE(of, sparx5_serdes_match);
diff --git a/drivers/phy/microchip/sparx5_serdes.h b/drivers/phy/microchip/sparx5_serdes.h
index 13f94a29225a..d7093d0b09c0 100644
--- a/drivers/phy/microchip/sparx5_serdes.h
+++ b/drivers/phy/microchip/sparx5_serdes.h
@@ -26,11 +26,18 @@ enum sparx5_serdes_mode {
SPX5_SD_MODE_SFI,
};
-struct sparx5_serdes_private {
- struct device *dev;
- void __iomem *regs[NUM_TARGETS];
- struct phy *phys[SPX5_SERDES_MAX];
- unsigned long coreclock;
+enum sparx5_10g28cmu_mode {
+ SPX5_SD10G28_CMU_MAIN = 0,
+ SPX5_SD10G28_CMU_AUX1 = 1,
+ SPX5_SD10G28_CMU_AUX2 = 3,
+ SPX5_SD10G28_CMU_NONE = 4,
+ SPX5_SD10G28_CMU_MAX,
+};
+
+enum sparx5_target {
+ SPX5_TARGET_SPARX5,
+ SPX5_TARGET_LAN969X,
+
};
struct sparx5_serdes_macro {
@@ -44,6 +51,33 @@ struct sparx5_serdes_macro {
enum phy_media media;
};
+struct sparx5_serdes_consts {
+ int sd_max;
+ int cmu_max;
+};
+
+struct sparx5_serdes_ops {
+ void (*serdes_type_set)(struct sparx5_serdes_macro *macro, int sidx);
+ int (*serdes_cmu_get)(enum sparx5_10g28cmu_mode mode, int sd_index);
+};
+
+struct sparx5_serdes_match_data {
+ enum sparx5_target type;
+ const struct sparx5_serdes_consts consts;
+ const struct sparx5_serdes_ops ops;
+ const struct sparx5_serdes_io_resource *iomap;
+ int iomap_size;
+ const unsigned int *tsize;
+};
+
+struct sparx5_serdes_private {
+ struct device *dev;
+ void __iomem *regs[NUM_TARGETS];
+ struct phy *phys[SPX5_SERDES_MAX];
+ unsigned long coreclock;
+ const struct sparx5_serdes_match_data *data;
+};
+
/* Read, Write and modify registers content.
* The register definition macros start at the id
*/
diff --git a/drivers/phy/microchip/sparx5_serdes_regs.h b/drivers/phy/microchip/sparx5_serdes_regs.h
index d0543fd3dc94..11c4fdc593fa 100644
--- a/drivers/phy/microchip/sparx5_serdes_regs.h
+++ b/drivers/phy/microchip/sparx5_serdes_regs.h
@@ -1,11 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0+
* Microchip Sparx5 SerDes driver
*
- * Copyright (c) 2020 Microchip Technology Inc.
+ * Copyright (c) 2024 Microchip Technology Inc.
*/
-/* This file is autogenerated by cml-utils 2020-11-16 13:11:27 +0100.
- * Commit ID: 13bdf073131d8bf40c54901df6988ae4e9c8f29f
+/* This file is autogenerated by cml-utils 2023-04-13 15:02:00 +0200.
+ * Commit ID: 5ac560288d46048f872ecdb8add53717f1efc0e1
*/
#ifndef _SPARX5_SERDES_REGS_H_
@@ -26,10 +26,25 @@ enum sparx5_serdes_target {
NUM_TARGETS = 332
};
+enum sparx5_serdes_tsize_enum {
+ TC_SD10G_LANE,
+ TC_SD_CMU,
+ TC_SD_CMU_CFG,
+ TC_SD_LANE,
+ TSIZE_LAST,
+};
+
+/* sparx5_serdes.c */
+extern const unsigned int *tsize;
+
+#define TSIZE(o) tsize[o]
+
#define __REG(...) __VA_ARGS__
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_01 */
-#define SD10G_LANE_LANE_01(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 4, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_01 */
+#define SD10G_LANE_LANE_01(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 4, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_01_CFG_PMA_TX_CK_BITWIDTH_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_01_CFG_PMA_TX_CK_BITWIDTH_2_0_SET(x)\
@@ -49,8 +64,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_01_CFG_RXDET_STR_GET(x)\
FIELD_GET(SD10G_LANE_LANE_01_CFG_RXDET_STR, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_02 */
-#define SD10G_LANE_LANE_02(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 8, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_02 */
+#define SD10G_LANE_LANE_02(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 8, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_02_CFG_EN_ADV BIT(0)
#define SD10G_LANE_LANE_02_CFG_EN_ADV_SET(x)\
@@ -82,8 +99,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_02_CFG_TAP_ADV_3_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_02_CFG_TAP_ADV_3_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_03 */
-#define SD10G_LANE_LANE_03(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 12, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_03 */
+#define SD10G_LANE_LANE_03(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 12, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_03_CFG_TAP_MAIN BIT(0)
#define SD10G_LANE_LANE_03_CFG_TAP_MAIN_SET(x)\
@@ -91,8 +110,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_03_CFG_TAP_MAIN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_03_CFG_TAP_MAIN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_04 */
-#define SD10G_LANE_LANE_04(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 16, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_04 */
+#define SD10G_LANE_LANE_04(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 16, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0 GENMASK(4, 0)
#define SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0_SET(x)\
@@ -100,8 +121,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_06 */
-#define SD10G_LANE_LANE_06(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 24, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_06 */
+#define SD10G_LANE_LANE_06(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 24, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_06_CFG_PD_DRIVER BIT(0)
#define SD10G_LANE_LANE_06_CFG_PD_DRIVER_SET(x)\
@@ -139,8 +162,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_06_CFG_EN_PREEMPH_GET(x)\
FIELD_GET(SD10G_LANE_LANE_06_CFG_EN_PREEMPH, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0B */
-#define SD10G_LANE_LANE_0B(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 44, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0B */
+#define SD10G_LANE_LANE_0B(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 44, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0B_CFG_EQ_RES_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_0B_CFG_EQ_RES_3_0_SET(x)\
@@ -172,8 +197,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0B_CFG_RESETB_OSCAL_SQ_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0B_CFG_RESETB_OSCAL_SQ, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0C */
-#define SD10G_LANE_LANE_0C(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 48, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0C */
+#define SD10G_LANE_LANE_0C(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 48, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0C_CFG_OSCAL_AFE BIT(0)
#define SD10G_LANE_LANE_0C_CFG_OSCAL_AFE_SET(x)\
@@ -223,8 +250,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0C_CFG_RX_PCIE_GEN12_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0C_CFG_RX_PCIE_GEN12, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0D */
-#define SD10G_LANE_LANE_0D(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 52, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0D */
+#define SD10G_LANE_LANE_0D(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 52, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0D_CFG_CTLE_M_THR_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_0D_CFG_CTLE_M_THR_1_0_SET(x)\
@@ -238,8 +267,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0D_CFG_EQR_BYP_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0D_CFG_EQR_BYP, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0E */
-#define SD10G_LANE_LANE_0E(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 56, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0E */
+#define SD10G_LANE_LANE_0E(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 56, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0E_CFG_EQC_FORCE_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_0E_CFG_EQC_FORCE_3_0_SET(x)\
@@ -265,8 +296,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0E_CFG_SUM_SETCM_EN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0E_CFG_SUM_SETCM_EN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0F */
-#define SD10G_LANE_LANE_0F(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 60, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0F */
+#define SD10G_LANE_LANE_0F(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 60, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0 GENMASK(7, 0)
#define SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0_SET(x)\
@@ -274,8 +307,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_13 */
-#define SD10G_LANE_LANE_13(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 76, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_13 */
+#define SD10G_LANE_LANE_13(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 76, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_13_CFG_DCDR_PD BIT(0)
#define SD10G_LANE_LANE_13_CFG_DCDR_PD_SET(x)\
@@ -295,8 +330,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_13_CFG_CDRCK_EN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_13_CFG_CDRCK_EN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_14 */
-#define SD10G_LANE_LANE_14(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 80, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_14 */
+#define SD10G_LANE_LANE_14(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 80, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0 GENMASK(7, 0)
#define SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0_SET(x)\
@@ -304,8 +341,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_15 */
-#define SD10G_LANE_LANE_15(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 84, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_15 */
+#define SD10G_LANE_LANE_15(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 84, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8 GENMASK(7, 0)
#define SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8_SET(x)\
@@ -313,8 +352,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8_GET(x)\
FIELD_GET(SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_16 */
-#define SD10G_LANE_LANE_16(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 88, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_16 */
+#define SD10G_LANE_LANE_16(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 88, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16 GENMASK(7, 0)
#define SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16_SET(x)\
@@ -322,8 +363,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16_GET(x)\
FIELD_GET(SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_1A */
-#define SD10G_LANE_LANE_1A(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 104, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_1A */
+#define SD10G_LANE_LANE_1A(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 104, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_1A_CFG_PI_R_SCAN_EN BIT(0)
#define SD10G_LANE_LANE_1A_CFG_PI_R_SCAN_EN_SET(x)\
@@ -355,8 +398,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_1A_CFG_PI_FLOOP_STEPS_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_1A_CFG_PI_FLOOP_STEPS_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_22 */
-#define SD10G_LANE_LANE_22(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 136, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_22 */
+#define SD10G_LANE_LANE_22(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 136, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1 GENMASK(4, 0)
#define SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1_SET(x)\
@@ -364,8 +409,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1_GET(x)\
FIELD_GET(SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_23 */
-#define SD10G_LANE_LANE_23(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 140, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_23 */
+#define SD10G_LANE_LANE_23(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 140, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_23_CFG_DFE_PD BIT(0)
#define SD10G_LANE_LANE_23_CFG_DFE_PD_SET(x)\
@@ -397,8 +444,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_23_CFG_DFEDIG_M_2_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_23_CFG_DFEDIG_M_2_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_24 */
-#define SD10G_LANE_LANE_24(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 144, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_24 */
+#define SD10G_LANE_LANE_24(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 144, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_24_CFG_PI_BW_GEN1_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_24_CFG_PI_BW_GEN1_3_0_SET(x)\
@@ -412,8 +461,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_24_CFG_PI_BW_GEN2_3_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_24_CFG_PI_BW_GEN2_3_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_26 */
-#define SD10G_LANE_LANE_26(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 152, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_26 */
+#define SD10G_LANE_LANE_26(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 152, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0 GENMASK(7, 0)
#define SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0_SET(x)\
@@ -421,8 +472,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_2F */
-#define SD10G_LANE_LANE_2F(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 188, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_2F */
+#define SD10G_LANE_LANE_2F(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 188, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_2F_CFG_VGA_CP_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_2F_CFG_VGA_CP_2_0_SET(x)\
@@ -436,8 +489,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_2F_CFG_VGA_CTRL_3_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_2F_CFG_VGA_CTRL_3_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_30 */
-#define SD10G_LANE_LANE_30(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 192, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_30 */
+#define SD10G_LANE_LANE_30(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 192, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_30_CFG_SUMMER_EN BIT(0)
#define SD10G_LANE_LANE_30_CFG_SUMMER_EN_SET(x)\
@@ -451,8 +506,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_30_CFG_RXDIV_SEL_2_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_30_CFG_RXDIV_SEL_2_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_31 */
-#define SD10G_LANE_LANE_31(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 196, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_31 */
+#define SD10G_LANE_LANE_31(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 196, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_31_CFG_PI_RSTN BIT(0)
#define SD10G_LANE_LANE_31_CFG_PI_RSTN_SET(x)\
@@ -490,8 +547,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_31_CFG_R50_EN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_31_CFG_R50_EN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_32 */
-#define SD10G_LANE_LANE_32(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 200, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_32 */
+#define SD10G_LANE_LANE_32(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 200, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_32_CFG_ITX_IPCLK_BASE_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_32_CFG_ITX_IPCLK_BASE_1_0_SET(x)\
@@ -505,8 +564,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_32_CFG_ITX_IPCML_BASE_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_32_CFG_ITX_IPCML_BASE_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_33 */
-#define SD10G_LANE_LANE_33(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 204, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_33 */
+#define SD10G_LANE_LANE_33(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 204, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_33_CFG_ITX_IPDRIVER_BASE_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_33_CFG_ITX_IPDRIVER_BASE_2_0_SET(x)\
@@ -520,8 +581,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_33_CFG_ITX_IPPREEMP_BASE_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_33_CFG_ITX_IPPREEMP_BASE_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_35 */
-#define SD10G_LANE_LANE_35(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 212, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_35 */
+#define SD10G_LANE_LANE_35(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 212, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_35_CFG_TXRATE_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_35_CFG_TXRATE_1_0_SET(x)\
@@ -535,8 +598,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_35_CFG_RXRATE_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_35_CFG_RXRATE_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_36 */
-#define SD10G_LANE_LANE_36(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 216, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_36 */
+#define SD10G_LANE_LANE_36(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 216, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_36_CFG_PREDRV_SLEWRATE_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_36_CFG_PREDRV_SLEWRATE_1_0_SET(x)\
@@ -568,8 +633,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_36_CFG_PRBS_SETB_GET(x)\
FIELD_GET(SD10G_LANE_LANE_36_CFG_PRBS_SETB, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_37 */
-#define SD10G_LANE_LANE_37(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 220, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_37 */
+#define SD10G_LANE_LANE_37(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 220, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_37_CFG_RXDET_COMP_PD BIT(0)
#define SD10G_LANE_LANE_37_CFG_RXDET_COMP_PD_SET(x)\
@@ -595,8 +662,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_37_CFG_IP_PRE_BASE_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_37_CFG_IP_PRE_BASE_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_39 */
-#define SD10G_LANE_LANE_39(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 228, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_39 */
+#define SD10G_LANE_LANE_39(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 228, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_39_CFG_RXFILT_Y_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_39_CFG_RXFILT_Y_2_0_SET(x)\
@@ -610,8 +679,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_39_CFG_RX_SSC_LH_GET(x)\
FIELD_GET(SD10G_LANE_LANE_39_CFG_RX_SSC_LH, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_3A */
-#define SD10G_LANE_LANE_3A(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 232, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_3A */
+#define SD10G_LANE_LANE_3A(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 232, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_3A_CFG_MP_MIN_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_3A_CFG_MP_MIN_3_0_SET(x)\
@@ -625,8 +696,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_3A_CFG_MP_MAX_3_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_3A_CFG_MP_MAX_3_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_3C */
-#define SD10G_LANE_LANE_3C(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 240, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_3C */
+#define SD10G_LANE_LANE_3C(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 240, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_3C_CFG_DIS_ACC BIT(0)
#define SD10G_LANE_LANE_3C_CFG_DIS_ACC_SET(x)\
@@ -640,8 +713,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_3C_CFG_DIS_2NDORDER_GET(x)\
FIELD_GET(SD10G_LANE_LANE_3C_CFG_DIS_2NDORDER, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_40 */
-#define SD10G_LANE_LANE_40(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 256, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_40 */
+#define SD10G_LANE_LANE_40(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 256, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0 GENMASK(7, 0)
#define SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0_SET(x)\
@@ -649,8 +724,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_41 */
-#define SD10G_LANE_LANE_41(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 260, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_41 */
+#define SD10G_LANE_LANE_41(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 260, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8 GENMASK(7, 0)
#define SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8_SET(x)\
@@ -658,8 +735,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8_GET(x)\
FIELD_GET(SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_42 */
-#define SD10G_LANE_LANE_42(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 264, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_42 */
+#define SD10G_LANE_LANE_42(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 264, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_42_CFG_CDR_KF_GEN1_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_42_CFG_CDR_KF_GEN1_2_0_SET(x)\
@@ -673,8 +752,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_42_CFG_CDR_KF_GEN2_2_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_42_CFG_CDR_KF_GEN2_2_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_1:LANE_48 */
-#define SD10G_LANE_LANE_48(t) __REG(TARGET_SD10G_LANE, t, 12, 288, 0, 1, 40, 0, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_1:LANE_48 */
+#define SD10G_LANE_LANE_48(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 288, 0, 1, 40, 0, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_48_CFG_ALOS_THR_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_48_CFG_ALOS_THR_3_0_SET(x)\
@@ -694,8 +775,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_48_CFG_CLK_ENQ_GET(x)\
FIELD_GET(SD10G_LANE_LANE_48_CFG_CLK_ENQ, x)
-/* SD10G_LANE_TARGET:LANE_GRP_1:LANE_50 */
-#define SD10G_LANE_LANE_50(t) __REG(TARGET_SD10G_LANE, t, 12, 288, 0, 1, 40, 32, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_1:LANE_50 */
+#define SD10G_LANE_LANE_50(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 288, 0, 1, 40, 32, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_50_CFG_SSC_PI_STEP_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_50_CFG_SSC_PI_STEP_1_0_SET(x)\
@@ -727,8 +810,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_50_CFG_JT_EN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_50_CFG_JT_EN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_2:LANE_52 */
-#define SD10G_LANE_LANE_52(t) __REG(TARGET_SD10G_LANE, t, 12, 328, 0, 1, 24, 0, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_2:LANE_52 */
+#define SD10G_LANE_LANE_52(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 328, 0, 1, 24, 0, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0 GENMASK(5, 0)
#define SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0_SET(x)\
@@ -736,8 +821,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_4:LANE_83 */
-#define SD10G_LANE_LANE_83(t) __REG(TARGET_SD10G_LANE, t, 12, 464, 0, 1, 112, 60, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_4:LANE_83 */
+#define SD10G_LANE_LANE_83(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 464, 0, 1, 112, 60, \
+ 0, 1, 4)
#define SD10G_LANE_LANE_83_R_TX_BIT_REVERSE BIT(0)
#define SD10G_LANE_LANE_83_R_TX_BIT_REVERSE_SET(x)\
@@ -781,8 +868,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_83_R_CTLE_RSTN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_83_R_CTLE_RSTN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_93 */
-#define SD10G_LANE_LANE_93(t) __REG(TARGET_SD10G_LANE, t, 12, 576, 0, 1, 64, 12, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_93 */
+#define SD10G_LANE_LANE_93(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 576, 0, 1, 64, 12, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_93_R_RXEI_FIFO_RST_EN BIT(0)
#define SD10G_LANE_LANE_93_R_RXEI_FIFO_RST_EN_SET(x)\
@@ -832,8 +921,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_93_R_RX_PCIE_GEN12_FROM_HWT_GET(x)\
FIELD_GET(SD10G_LANE_LANE_93_R_RX_PCIE_GEN12_FROM_HWT, x)
-/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_94 */
-#define SD10G_LANE_LANE_94(t) __REG(TARGET_SD10G_LANE, t, 12, 576, 0, 1, 64, 16, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_94 */
+#define SD10G_LANE_LANE_94(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 576, 0, 1, 64, 16, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_94_R_DWIDTHCTRL_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_94_R_DWIDTHCTRL_2_0_SET(x)\
@@ -865,8 +956,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_94_R_SWING_REG_GET(x)\
FIELD_GET(SD10G_LANE_LANE_94_R_SWING_REG, x)
-/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_9E */
-#define SD10G_LANE_LANE_9E(t) __REG(TARGET_SD10G_LANE, t, 12, 576, 0, 1, 64, 56, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_9E */
+#define SD10G_LANE_LANE_9E(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 576, 0, 1, 64, 56, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_9E_R_RXEQ_REG BIT(0)
#define SD10G_LANE_LANE_9E_R_RXEQ_REG_SET(x)\
@@ -886,8 +979,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_9E_R_EN_AUTO_CDR_RSTN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_9E_R_EN_AUTO_CDR_RSTN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_6:LANE_A1 */
-#define SD10G_LANE_LANE_A1(t) __REG(TARGET_SD10G_LANE, t, 12, 640, 0, 1, 128, 4, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_6:LANE_A1 */
+#define SD10G_LANE_LANE_A1(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 640, 0, 1, 128, 4, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_A1_R_PMA_TXCK_DIV_SEL_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_A1_R_PMA_TXCK_DIV_SEL_1_0_SET(x)\
@@ -919,8 +1014,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_A1_R_PCLK_GATING_GET(x)\
FIELD_GET(SD10G_LANE_LANE_A1_R_PCLK_GATING, x)
-/* SD10G_LANE_TARGET:LANE_GRP_6:LANE_A2 */
-#define SD10G_LANE_LANE_A2(t) __REG(TARGET_SD10G_LANE, t, 12, 640, 0, 1, 128, 8, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_6:LANE_A2 */
+#define SD10G_LANE_LANE_A2(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 640, 0, 1, 128, 8, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0 GENMASK(4, 0)
#define SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0_SET(x)\
@@ -928,8 +1025,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_8:LANE_DF */
-#define SD10G_LANE_LANE_DF(t) __REG(TARGET_SD10G_LANE, t, 12, 832, 0, 1, 84, 60, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_8:LANE_DF */
+#define SD10G_LANE_LANE_DF(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 832, 0, 1, 84, 60, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_DF_LOL_UDL BIT(0)
#define SD10G_LANE_LANE_DF_LOL_UDL_SET(x)\
@@ -955,8 +1054,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_DF_SQUELCH_GET(x)\
FIELD_GET(SD10G_LANE_LANE_DF_SQUELCH, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_09 */
-#define SD25G_LANE_CMU_09(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 36, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_09 */
+#define SD25G_LANE_CMU_09(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 36, 0, 1, 4)
#define SD25G_LANE_CMU_09_CFG_REFCK_TERM_EN BIT(0)
#define SD25G_LANE_CMU_09_CFG_REFCK_TERM_EN_SET(x)\
@@ -988,8 +1089,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_09_CFG_PLL_TP_SEL_1_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_09_CFG_PLL_TP_SEL_1_0, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_0B */
-#define SD25G_LANE_CMU_0B(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 44, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_0B */
+#define SD25G_LANE_CMU_0B(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 44, 0, 1, 4)
#define SD25G_LANE_CMU_0B_CFG_FORCE_RX_FILT BIT(0)
#define SD25G_LANE_CMU_0B_CFG_FORCE_RX_FILT_SET(x)\
@@ -1039,8 +1142,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_0B_CFG_RST_TREE_PD_MAN_GET(x)\
FIELD_GET(SD25G_LANE_CMU_0B_CFG_RST_TREE_PD_MAN, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_0C */
-#define SD25G_LANE_CMU_0C(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 48, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_0C */
+#define SD25G_LANE_CMU_0C(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 48, 0, 1, 4)
#define SD25G_LANE_CMU_0C_CFG_PLL_LOL_SET BIT(0)
#define SD25G_LANE_CMU_0C_CFG_PLL_LOL_SET_SET(x)\
@@ -1072,8 +1177,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_0C_CFG_VCO_DIV_MODE_1_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_0C_CFG_VCO_DIV_MODE_1_0, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_0D */
-#define SD25G_LANE_CMU_0D(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 52, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_0D */
+#define SD25G_LANE_CMU_0D(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 52, 0, 1, 4)
#define SD25G_LANE_CMU_0D_CFG_CK_TREE_PD BIT(0)
#define SD25G_LANE_CMU_0D_CFG_CK_TREE_PD_SET(x)\
@@ -1105,8 +1212,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_0D_CFG_PRE_DIVSEL_1_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_0D_CFG_PRE_DIVSEL_1_0, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_0E */
-#define SD25G_LANE_CMU_0E(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 56, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_0E */
+#define SD25G_LANE_CMU_0E(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 56, 0, 1, 4)
#define SD25G_LANE_CMU_0E_CFG_SEL_DIV_3_0 GENMASK(3, 0)
#define SD25G_LANE_CMU_0E_CFG_SEL_DIV_3_0_SET(x)\
@@ -1120,8 +1229,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_0E_CFG_PMAA_CENTR_CK_PD_GET(x)\
FIELD_GET(SD25G_LANE_CMU_0E_CFG_PMAA_CENTR_CK_PD, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_13 */
-#define SD25G_LANE_CMU_13(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 76, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_13 */
+#define SD25G_LANE_CMU_13(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 76, 0, 1, 4)
#define SD25G_LANE_CMU_13_CFG_PLL_RESERVE_3_0 GENMASK(3, 0)
#define SD25G_LANE_CMU_13_CFG_PLL_RESERVE_3_0_SET(x)\
@@ -1135,8 +1246,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_13_CFG_JT_EN_GET(x)\
FIELD_GET(SD25G_LANE_CMU_13_CFG_JT_EN, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_18 */
-#define SD25G_LANE_CMU_18(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 96, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_18 */
+#define SD25G_LANE_CMU_18(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 96, 0, 1, 4)
#define SD25G_LANE_CMU_18_R_PLL_RSTN BIT(0)
#define SD25G_LANE_CMU_18_R_PLL_RSTN_SET(x)\
@@ -1162,8 +1275,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_18_R_PLL_TP_SEL_1_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_18_R_PLL_TP_SEL_1_0, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_19 */
-#define SD25G_LANE_CMU_19(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 100, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_19 */
+#define SD25G_LANE_CMU_19(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 100, 0, 1, 4)
#define SD25G_LANE_CMU_19_R_CK_RESETB BIT(0)
#define SD25G_LANE_CMU_19_R_CK_RESETB_SET(x)\
@@ -1177,8 +1292,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_19_R_PLL_DLOL_EN_GET(x)\
FIELD_GET(SD25G_LANE_CMU_19_R_PLL_DLOL_EN, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_1A */
-#define SD25G_LANE_CMU_1A(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 104, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_1A */
+#define SD25G_LANE_CMU_1A(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 104, 0, 1, 4)
#define SD25G_LANE_CMU_1A_R_DWIDTHCTRL_2_0 GENMASK(2, 0)
#define SD25G_LANE_CMU_1A_R_DWIDTHCTRL_2_0_SET(x)\
@@ -1204,8 +1321,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_1A_R_REG_MANUAL_GET(x)\
FIELD_GET(SD25G_LANE_CMU_1A_R_REG_MANUAL, x)
-/* SD25G_TARGET:CMU_GRP_1:CMU_2A */
-#define SD25G_LANE_CMU_2A(t) __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 36, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_1:CMU_2A */
+#define SD25G_LANE_CMU_2A(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 36, 0, 1, 4)
#define SD25G_LANE_CMU_2A_R_DBG_SEL_1_0 GENMASK(1, 0)
#define SD25G_LANE_CMU_2A_R_DBG_SEL_1_0_SET(x)\
@@ -1225,8 +1344,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_2A_R_DBG_LOL_STATUS_GET(x)\
FIELD_GET(SD25G_LANE_CMU_2A_R_DBG_LOL_STATUS, x)
-/* SD25G_TARGET:CMU_GRP_1:CMU_30 */
-#define SD25G_LANE_CMU_30(t) __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 60, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_1:CMU_30 */
+#define SD25G_LANE_CMU_30(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 60, 0, 1, 4)
#define SD25G_LANE_CMU_30_R_TXFIFO_CK_DIV_PMAD_2_0 GENMASK(2, 0)
#define SD25G_LANE_CMU_30_R_TXFIFO_CK_DIV_PMAD_2_0_SET(x)\
@@ -1240,8 +1361,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_30_R_RXFIFO_CK_DIV_PMAD_2_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_30_R_RXFIFO_CK_DIV_PMAD_2_0, x)
-/* SD25G_TARGET:CMU_GRP_1:CMU_31 */
-#define SD25G_LANE_CMU_31(t) __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 64, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_1:CMU_31 */
+#define SD25G_LANE_CMU_31(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 64, 0, 1, 4)
#define SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0 GENMASK(7, 0)
#define SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0_SET(x)\
@@ -1249,8 +1372,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0, x)
-/* SD25G_TARGET:CMU_GRP_2:CMU_40 */
-#define SD25G_LANE_CMU_40(t) __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_2:CMU_40 */
+#define SD25G_LANE_CMU_40(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 0, 0, 1, 4)
#define SD25G_LANE_CMU_40_L0_CFG_CKSKEW_CTRL BIT(0)
#define SD25G_LANE_CMU_40_L0_CFG_CKSKEW_CTRL_SET(x)\
@@ -1288,8 +1413,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_40_L0_CFG_TXCAL_RST_GET(x)\
FIELD_GET(SD25G_LANE_CMU_40_L0_CFG_TXCAL_RST, x)
-/* SD25G_TARGET:CMU_GRP_2:CMU_45 */
-#define SD25G_LANE_CMU_45(t) __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 20, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_2:CMU_45 */
+#define SD25G_LANE_CMU_45(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 20, 0, 1, 4)
#define SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0 GENMASK(7, 0)
#define SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0_SET(x)\
@@ -1297,8 +1424,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0, x)
-/* SD25G_TARGET:CMU_GRP_2:CMU_46 */
-#define SD25G_LANE_CMU_46(t) __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 24, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_2:CMU_46 */
+#define SD25G_LANE_CMU_46(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 24, 0, 1, 4)
#define SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8 GENMASK(7, 0)
#define SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8_SET(x)\
@@ -1306,8 +1435,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8_GET(x)\
FIELD_GET(SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8, x)
-/* SD25G_TARGET:CMU_GRP_3:CMU_C0 */
-#define SD25G_LANE_CMU_C0(t) __REG(TARGET_SD25G_LANE, t, 8, 768, 0, 1, 252, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_3:CMU_C0 */
+#define SD25G_LANE_CMU_C0(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 768, 0, 1, 252, 0, 0, 1, 4)
#define SD25G_LANE_CMU_C0_READ_VCO_CTUNE_3_0 GENMASK(3, 0)
#define SD25G_LANE_CMU_C0_READ_VCO_CTUNE_3_0_SET(x)\
@@ -1321,8 +1452,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_C0_PLL_LOL_UDL_GET(x)\
FIELD_GET(SD25G_LANE_CMU_C0_PLL_LOL_UDL, x)
-/* SD25G_TARGET:CMU_GRP_4:CMU_FF */
-#define SD25G_LANE_CMU_FF(t) __REG(TARGET_SD25G_LANE, t, 8, 1020, 0, 1, 4, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_4:CMU_FF */
+#define SD25G_LANE_CMU_FF(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1020, 0, 1, 4, 0, 0, 1, 4)
#define SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX GENMASK(7, 0)
#define SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX_SET(x)\
@@ -1330,8 +1463,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX_GET(x)\
FIELD_GET(SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_00 */
-#define SD25G_LANE_LANE_00(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_00 */
+#define SD25G_LANE_LANE_00(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 0, 0, 1, 4)
#define SD25G_LANE_LANE_00_LN_CFG_ITX_VC_DRIVER_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_00_LN_CFG_ITX_VC_DRIVER_3_0_SET(x)\
@@ -1345,8 +1480,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_00_LN_CFG_ITX_IPCML_BASE_1_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_00_LN_CFG_ITX_IPCML_BASE_1_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_01 */
-#define SD25G_LANE_LANE_01(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_01 */
+#define SD25G_LANE_LANE_01(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 4, 0, 1, 4)
#define SD25G_LANE_LANE_01_LN_CFG_ITX_IPDRIVER_BASE_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_01_LN_CFG_ITX_IPDRIVER_BASE_2_0_SET(x)\
@@ -1360,8 +1497,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_01_LN_CFG_TX_PREDIV_1_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_01_LN_CFG_TX_PREDIV_1_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_03 */
-#define SD25G_LANE_LANE_03(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 12, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_03 */
+#define SD25G_LANE_LANE_03(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 12, 0, 1, 4)
#define SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0 GENMASK(4, 0)
#define SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0_SET(x)\
@@ -1369,8 +1508,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_04 */
-#define SD25G_LANE_LANE_04(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 16, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_04 */
+#define SD25G_LANE_LANE_04(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 16, 0, 1, 4)
#define SD25G_LANE_LANE_04_LN_CFG_TX2RX_LP_EN BIT(0)
#define SD25G_LANE_LANE_04_LN_CFG_TX2RX_LP_EN_SET(x)\
@@ -1408,8 +1549,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_04_LN_CFG_TAP_MAIN_GET(x)\
FIELD_GET(SD25G_LANE_LANE_04_LN_CFG_TAP_MAIN, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_05 */
-#define SD25G_LANE_LANE_05(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 20, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_05 */
+#define SD25G_LANE_LANE_05(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 20, 0, 1, 4)
#define SD25G_LANE_LANE_05_LN_CFG_TAP_DLY2_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_05_LN_CFG_TAP_DLY2_3_0_SET(x)\
@@ -1423,8 +1566,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_05_LN_CFG_BW_1_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_05_LN_CFG_BW_1_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_06 */
-#define SD25G_LANE_LANE_06(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 24, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_06 */
+#define SD25G_LANE_LANE_06(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 24, 0, 1, 4)
#define SD25G_LANE_LANE_06_LN_CFG_EN_MAIN BIT(0)
#define SD25G_LANE_LANE_06_LN_CFG_EN_MAIN_SET(x)\
@@ -1438,8 +1583,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_06_LN_CFG_TAP_ADV_3_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_06_LN_CFG_TAP_ADV_3_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_07 */
-#define SD25G_LANE_LANE_07(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 28, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_07 */
+#define SD25G_LANE_LANE_07(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 28, 0, 1, 4)
#define SD25G_LANE_LANE_07_LN_CFG_EN_ADV BIT(0)
#define SD25G_LANE_LANE_07_LN_CFG_EN_ADV_SET(x)\
@@ -1459,8 +1606,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_07_LN_CFG_EN_DLY_GET(x)\
FIELD_GET(SD25G_LANE_LANE_07_LN_CFG_EN_DLY, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_09 */
-#define SD25G_LANE_LANE_09(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 36, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_09 */
+#define SD25G_LANE_LANE_09(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 36, 0, 1, 4)
#define SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0_SET(x)\
@@ -1468,8 +1617,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0A */
-#define SD25G_LANE_LANE_0A(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 40, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0A */
+#define SD25G_LANE_LANE_0A(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 40, 0, 1, 4)
#define SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0 GENMASK(5, 0)
#define SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0_SET(x)\
@@ -1477,8 +1628,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0B */
-#define SD25G_LANE_LANE_0B(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 44, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0B */
+#define SD25G_LANE_LANE_0B(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 44, 0, 1, 4)
#define SD25G_LANE_LANE_0B_LN_CFG_TXCAL_MAN_EN BIT(0)
#define SD25G_LANE_LANE_0B_LN_CFG_TXCAL_MAN_EN_SET(x)\
@@ -1498,8 +1651,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0B_LN_CFG_QUAD_MAN_1_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0B_LN_CFG_QUAD_MAN_1_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0C */
-#define SD25G_LANE_LANE_0C(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 48, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0C */
+#define SD25G_LANE_LANE_0C(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 48, 0, 1, 4)
#define SD25G_LANE_LANE_0C_LN_CFG_PMA_TX_CK_BITWIDTH_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_0C_LN_CFG_PMA_TX_CK_BITWIDTH_2_0_SET(x)\
@@ -1519,8 +1674,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0C_LN_CFG_RXTERM_PD_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0C_LN_CFG_RXTERM_PD, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0D */
-#define SD25G_LANE_LANE_0D(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 52, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0D */
+#define SD25G_LANE_LANE_0D(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 52, 0, 1, 4)
#define SD25G_LANE_LANE_0D_LN_CFG_RXTERM_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_0D_LN_CFG_RXTERM_2_0_SET(x)\
@@ -1552,8 +1709,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0D_LN_CFG_DFECK_EN_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0D_LN_CFG_DFECK_EN, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0E */
-#define SD25G_LANE_LANE_0E(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 56, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0E */
+#define SD25G_LANE_LANE_0E(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 56, 0, 1, 4)
#define SD25G_LANE_LANE_0E_LN_CFG_ISCAN_EN BIT(0)
#define SD25G_LANE_LANE_0E_LN_CFG_ISCAN_EN_SET(x)\
@@ -1579,8 +1738,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0E_LN_CFG_DFEDIG_M_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0E_LN_CFG_DFEDIG_M_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0F */
-#define SD25G_LANE_LANE_0F(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 60, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0F */
+#define SD25G_LANE_LANE_0F(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 60, 0, 1, 4)
#define SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1 GENMASK(4, 0)
#define SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1_SET(x)\
@@ -1588,8 +1749,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_18 */
-#define SD25G_LANE_LANE_18(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 96, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_18 */
+#define SD25G_LANE_LANE_18(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 96, 0, 1, 4)
#define SD25G_LANE_LANE_18_LN_CFG_CDRCK_EN BIT(0)
#define SD25G_LANE_LANE_18_LN_CFG_CDRCK_EN_SET(x)\
@@ -1621,8 +1784,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_18_LN_CFG_RXDIV_SEL_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_18_LN_CFG_RXDIV_SEL_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_19 */
-#define SD25G_LANE_LANE_19(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 100, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_19 */
+#define SD25G_LANE_LANE_19(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 100, 0, 1, 4)
#define SD25G_LANE_LANE_19_LN_CFG_DCDR_PD BIT(0)
#define SD25G_LANE_LANE_19_LN_CFG_DCDR_PD_SET(x)\
@@ -1672,8 +1837,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_19_LN_CFG_PD_CTLE_GET(x)\
FIELD_GET(SD25G_LANE_LANE_19_LN_CFG_PD_CTLE, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1A */
-#define SD25G_LANE_LANE_1A(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 104, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1A */
+#define SD25G_LANE_LANE_1A(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 104, 0, 1, 4)
#define SD25G_LANE_LANE_1A_LN_CFG_CTLE_TP_EN BIT(0)
#define SD25G_LANE_LANE_1A_LN_CFG_CTLE_TP_EN_SET(x)\
@@ -1687,8 +1854,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1A_LN_CFG_CDR_KF_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1A_LN_CFG_CDR_KF_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1B */
-#define SD25G_LANE_LANE_1B(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 108, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1B */
+#define SD25G_LANE_LANE_1B(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 108, 0, 1, 4)
#define SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0 GENMASK(7, 0)
#define SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0_SET(x)\
@@ -1696,8 +1865,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1C */
-#define SD25G_LANE_LANE_1C(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 112, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1C */
+#define SD25G_LANE_LANE_1C(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 112, 0, 1, 4)
#define SD25G_LANE_LANE_1C_LN_CFG_CDR_RSTN BIT(0)
#define SD25G_LANE_LANE_1C_LN_CFG_CDR_RSTN_SET(x)\
@@ -1723,8 +1894,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1C_LN_CFG_EQC_FORCE_3_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1C_LN_CFG_EQC_FORCE_3_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1D */
-#define SD25G_LANE_LANE_1D(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 116, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1D */
+#define SD25G_LANE_LANE_1D(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 116, 0, 1, 4)
#define SD25G_LANE_LANE_1D_LN_CFG_ISCAN_EXT_OVR BIT(0)
#define SD25G_LANE_LANE_1D_LN_CFG_ISCAN_EXT_OVR_SET(x)\
@@ -1774,8 +1947,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1D_LN_CFG_PI_HOLD_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1D_LN_CFG_PI_HOLD, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1E */
-#define SD25G_LANE_LANE_1E(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 120, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1E */
+#define SD25G_LANE_LANE_1E(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 120, 0, 1, 4)
#define SD25G_LANE_LANE_1E_LN_CFG_PI_STEPS_1_0 GENMASK(1, 0)
#define SD25G_LANE_LANE_1E_LN_CFG_PI_STEPS_1_0_SET(x)\
@@ -1807,8 +1982,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1E_LN_CFG_PMAD_CK_PD_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1E_LN_CFG_PMAD_CK_PD, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_21 */
-#define SD25G_LANE_LANE_21(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 132, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_21 */
+#define SD25G_LANE_LANE_21(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 132, 0, 1, 4)
#define SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0 GENMASK(4, 0)
#define SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0_SET(x)\
@@ -1816,8 +1993,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_22 */
-#define SD25G_LANE_LANE_22(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 136, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_22 */
+#define SD25G_LANE_LANE_22(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 136, 0, 1, 4)
#define SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0_SET(x)\
@@ -1825,8 +2004,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_25 */
-#define SD25G_LANE_LANE_25(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 148, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_25 */
+#define SD25G_LANE_LANE_25(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 148, 0, 1, 4)
#define SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0 GENMASK(6, 0)
#define SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0_SET(x)\
@@ -1834,8 +2015,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_26 */
-#define SD25G_LANE_LANE_26(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 152, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_26 */
+#define SD25G_LANE_LANE_26(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 152, 0, 1, 4)
#define SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0 GENMASK(6, 0)
#define SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0_SET(x)\
@@ -1843,8 +2026,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_28 */
-#define SD25G_LANE_LANE_28(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 160, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_28 */
+#define SD25G_LANE_LANE_28(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 160, 0, 1, 4)
#define SD25G_LANE_LANE_28_LN_CFG_ISCAN_MODE_EN BIT(0)
#define SD25G_LANE_LANE_28_LN_CFG_ISCAN_MODE_EN_SET(x)\
@@ -1870,8 +2055,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_28_LN_CFG_RX_SUBRATE_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_28_LN_CFG_RX_SUBRATE_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_2B */
-#define SD25G_LANE_LANE_2B(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 172, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_2B */
+#define SD25G_LANE_LANE_2B(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 172, 0, 1, 4)
#define SD25G_LANE_LANE_2B_LN_CFG_PI_BW_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_2B_LN_CFG_PI_BW_3_0_SET(x)\
@@ -1891,8 +2078,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_2B_LN_CFG_RSTN_TXDUPU_GET(x)\
FIELD_GET(SD25G_LANE_LANE_2B_LN_CFG_RSTN_TXDUPU, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_2C */
-#define SD25G_LANE_LANE_2C(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 176, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_2C */
+#define SD25G_LANE_LANE_2C(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 176, 0, 1, 4)
#define SD25G_LANE_LANE_2C_LN_CFG_TX_SUBRATE_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_2C_LN_CFG_TX_SUBRATE_2_0_SET(x)\
@@ -1906,8 +2095,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_2C_LN_CFG_DIS_2NDORDER_GET(x)\
FIELD_GET(SD25G_LANE_LANE_2C_LN_CFG_DIS_2NDORDER, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_2D */
-#define SD25G_LANE_LANE_2D(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 180, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_2D */
+#define SD25G_LANE_LANE_2D(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 180, 0, 1, 4)
#define SD25G_LANE_LANE_2D_LN_CFG_ALOS_THR_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_2D_LN_CFG_ALOS_THR_2_0_SET(x)\
@@ -1921,8 +2112,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_2D_LN_CFG_SAT_CNTSEL_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_2D_LN_CFG_SAT_CNTSEL_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_2E */
-#define SD25G_LANE_LANE_2E(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 184, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_2E */
+#define SD25G_LANE_LANE_2E(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 184, 0, 1, 4)
#define SD25G_LANE_LANE_2E_LN_CFG_EN_FAST_ISCAN BIT(0)
#define SD25G_LANE_LANE_2E_LN_CFG_EN_FAST_ISCAN_SET(x)\
@@ -1972,8 +2165,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_2E_LN_CFG_CTLE_RSTN_GET(x)\
FIELD_GET(SD25G_LANE_LANE_2E_LN_CFG_CTLE_RSTN, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_40 */
-#define SD25G_LANE_LANE_40(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 256, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_40 */
+#define SD25G_LANE_LANE_40(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 256, 0, 1, 4)
#define SD25G_LANE_LANE_40_LN_R_TX_BIT_REVERSE BIT(0)
#define SD25G_LANE_LANE_40_LN_R_TX_BIT_REVERSE_SET(x)\
@@ -2017,8 +2212,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_40_LN_R_CTLE_RSTN_GET(x)\
FIELD_GET(SD25G_LANE_LANE_40_LN_R_CTLE_RSTN, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_42 */
-#define SD25G_LANE_LANE_42(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 264, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_42 */
+#define SD25G_LANE_LANE_42(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 264, 0, 1, 4)
#define SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0 GENMASK(7, 0)
#define SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0_SET(x)\
@@ -2026,8 +2223,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_43 */
-#define SD25G_LANE_LANE_43(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 268, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_43 */
+#define SD25G_LANE_LANE_43(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 268, 0, 1, 4)
#define SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8 GENMASK(7, 0)
#define SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8_SET(x)\
@@ -2035,8 +2234,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8_GET(x)\
FIELD_GET(SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_44 */
-#define SD25G_LANE_LANE_44(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 272, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_44 */
+#define SD25G_LANE_LANE_44(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 272, 0, 1, 4)
#define SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0 GENMASK(7, 0)
#define SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0_SET(x)\
@@ -2044,8 +2245,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_45 */
-#define SD25G_LANE_LANE_45(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 276, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_45 */
+#define SD25G_LANE_LANE_45(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 276, 0, 1, 4)
#define SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8 GENMASK(7, 0)
#define SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8_SET(x)\
@@ -2053,8 +2256,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8_GET(x)\
FIELD_GET(SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8, x)
-/* SD25G_TARGET:LANE_GRP_1:LANE_DE */
-#define SD25G_LANE_LANE_DE(t) __REG(TARGET_SD25G_LANE, t, 8, 1792, 0, 1, 128, 120, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_1:LANE_DE */
+#define SD25G_LANE_LANE_DE(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1792, 0, 1, 128, 120, 0, 1, 4)
#define SD25G_LANE_LANE_DE_LN_LOL_UDL BIT(0)
#define SD25G_LANE_LANE_DE_LN_LOL_UDL_SET(x)\
@@ -2080,8 +2285,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_DE_LN_PMA_RXEI_GET(x)\
FIELD_GET(SD25G_LANE_LANE_DE_LN_PMA_RXEI, x)
-/* SD10G_LANE_TARGET:LANE_GRP_8:LANE_DF */
-#define SD6G_LANE_LANE_DF(t) __REG(TARGET_SD6G_LANE, t, 13, 832, 0, 1, 84, 60, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD10G_LANE_TARGET:LANE_GRP_8:LANE_DF */
+#define SD6G_LANE_LANE_DF(t) \
+ __REG(TARGET_SD6G_LANE, t, 13, 832, 0, 1, 84, 60, 0, 1, 4)
#define SD6G_LANE_LANE_DF_LOL_UDL BIT(0)
#define SD6G_LANE_LANE_DF_LOL_UDL_SET(x)\
@@ -2107,8 +2314,9 @@ enum sparx5_serdes_target {
#define SD6G_LANE_LANE_DF_SQUELCH_GET(x)\
FIELD_GET(SD6G_LANE_LANE_DF_SQUELCH, x)
-/* SD10G_CMU_TARGET:CMU_GRP_0:CMU_00 */
-#define SD_CMU_CMU_00(t) __REG(TARGET_SD_CMU, t, 14, 0, 0, 1, 20, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_0:CMU_00 */
+#define SD_CMU_CMU_00(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 0, 0, 1, 20, 0, 0, 1, 4)
#define SD_CMU_CMU_00_R_HWT_SIMULATION_MODE BIT(0)
#define SD_CMU_CMU_00_R_HWT_SIMULATION_MODE_SET(x)\
@@ -2134,8 +2342,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0_GET(x)\
FIELD_GET(SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_05 */
-#define SD_CMU_CMU_05(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_05 */
+#define SD_CMU_CMU_05(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 0, 0, 1, 4)
#define SD_CMU_CMU_05_CFG_REFCK_TERM_EN BIT(0)
#define SD_CMU_CMU_05_CFG_REFCK_TERM_EN_SET(x)\
@@ -2149,9 +2358,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_GET(x)\
FIELD_GET(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_06 */
-#define SD_CMU_CMU_06(t) \
- __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 4, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_06 */
+#define SD_CMU_CMU_06(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 4, 0, 1, 4)
#define SD_CMU_CMU_06_CFG_DISLOS BIT(0)
#define SD_CMU_CMU_06_CFG_DISLOS_SET(x)\
@@ -2201,9 +2410,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_06_CFG_VCO_CAL_BYP_GET(x)\
FIELD_GET(SD_CMU_CMU_06_CFG_VCO_CAL_BYP, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_08 */
-#define SD_CMU_CMU_08(t) \
- __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 12, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_08 */
+#define SD_CMU_CMU_08(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 12, 0, 1, 4)
#define SD_CMU_CMU_08_CFG_VFILT2PAD BIT(0)
#define SD_CMU_CMU_08_CFG_VFILT2PAD_SET(x)\
@@ -2235,8 +2444,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN_GET(x)\
FIELD_GET(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_09 */
-#define SD_CMU_CMU_09(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 16, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_09 */
+#define SD_CMU_CMU_09(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 16, 0, 1, 4)
#define SD_CMU_CMU_09_CFG_EN_TX_CK_UP BIT(0)
#define SD_CMU_CMU_09_CFG_EN_TX_CK_UP_SET(x)\
@@ -2262,8 +2472,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_09_CFG_SW_10G_GET(x)\
FIELD_GET(SD_CMU_CMU_09_CFG_SW_10G, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_0D */
-#define SD_CMU_CMU_0D(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 32, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_0D */
+#define SD_CMU_CMU_0D(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 32, 0, 1, 4)
#define SD_CMU_CMU_0D_CFG_PD_DIV64 BIT(0)
#define SD_CMU_CMU_0D_CFG_PD_DIV64_SET(x)\
@@ -2295,8 +2506,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_0D_CFG_REFCK_PD_GET(x)\
FIELD_GET(SD_CMU_CMU_0D_CFG_REFCK_PD, x)
-/* SD10G_CMU_TARGET:CMU_GRP_3:CMU_1B */
-#define SD_CMU_CMU_1B(t) __REG(TARGET_SD_CMU, t, 14, 104, 0, 1, 20, 4, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_3:CMU_1B */
+#define SD_CMU_CMU_1B(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 104, 0, 1, 20, 4, 0, 1, 4)
#define SD_CMU_CMU_1B_CFG_RESERVE_7_0 GENMASK(7, 0)
#define SD_CMU_CMU_1B_CFG_RESERVE_7_0_SET(x)\
@@ -2304,8 +2516,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_1B_CFG_RESERVE_7_0_GET(x)\
FIELD_GET(SD_CMU_CMU_1B_CFG_RESERVE_7_0, x)
-/* SD10G_CMU_TARGET:CMU_GRP_4:CMU_1F */
-#define SD_CMU_CMU_1F(t) __REG(TARGET_SD_CMU, t, 14, 124, 0, 1, 68, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_4:CMU_1F */
+#define SD_CMU_CMU_1F(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 124, 0, 1, 68, 0, 0, 1, 4)
#define SD_CMU_CMU_1F_CFG_BIAS_DN_EN BIT(0)
#define SD_CMU_CMU_1F_CFG_BIAS_DN_EN_SET(x)\
@@ -2331,8 +2544,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_1F_CFG_VTUNE_SEL_GET(x)\
FIELD_GET(SD_CMU_CMU_1F_CFG_VTUNE_SEL, x)
-/* SD10G_CMU_TARGET:CMU_GRP_5:CMU_30 */
-#define SD_CMU_CMU_30(t) __REG(TARGET_SD_CMU, t, 14, 192, 0, 1, 72, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_5:CMU_30 */
+#define SD_CMU_CMU_30(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 192, 0, 1, 72, 0, 0, 1, 4)
#define SD_CMU_CMU_30_R_PLL_DLOL_EN BIT(0)
#define SD_CMU_CMU_30_R_PLL_DLOL_EN_SET(x)\
@@ -2340,8 +2554,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_30_R_PLL_DLOL_EN_GET(x)\
FIELD_GET(SD_CMU_CMU_30_R_PLL_DLOL_EN, x)
-/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_44 */
-#define SD_CMU_CMU_44(t) __REG(TARGET_SD_CMU, t, 14, 264, 0, 1, 632, 8, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_44 */
+#define SD_CMU_CMU_44(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 264, 0, 1, 632, 8, 0, 1, 4)
#define SD_CMU_CMU_44_R_PLL_RSTN BIT(0)
#define SD_CMU_CMU_44_R_PLL_RSTN_SET(x)\
@@ -2355,8 +2570,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_44_R_CK_RESETB_GET(x)\
FIELD_GET(SD_CMU_CMU_44_R_CK_RESETB, x)
-/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_45 */
-#define SD_CMU_CMU_45(t) __REG(TARGET_SD_CMU, t, 14, 264, 0, 1, 632, 12, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_45 */
+#define SD_CMU_CMU_45(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 264, 0, 1, 632, 12, 0, 1, 4)
#define SD_CMU_CMU_45_R_EN_RATECHG_CTRL BIT(0)
#define SD_CMU_CMU_45_R_EN_RATECHG_CTRL_SET(x)\
@@ -2406,8 +2622,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_45_R_AUTO_RST_TREE_PD_MAN_GET(x)\
FIELD_GET(SD_CMU_CMU_45_R_AUTO_RST_TREE_PD_MAN, x)
-/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_47 */
-#define SD_CMU_CMU_47(t) __REG(TARGET_SD_CMU, t, 14, 264, 0, 1, 632, 20, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_47 */
+#define SD_CMU_CMU_47(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 264, 0, 1, 632, 20, 0, 1, 4)
#define SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0 GENMASK(4, 0)
#define SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_SET(x)\
@@ -2415,8 +2632,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_GET(x)\
FIELD_GET(SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0, x)
-/* SD10G_CMU_TARGET:CMU_GRP_7:CMU_E0 */
-#define SD_CMU_CMU_E0(t) __REG(TARGET_SD_CMU, t, 14, 896, 0, 1, 8, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_7:CMU_E0 */
+#define SD_CMU_CMU_E0(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 896, 0, 1, 8, 0, 0, 1, 4)
#define SD_CMU_CMU_E0_READ_VCO_CTUNE_3_0 GENMASK(3, 0)
#define SD_CMU_CMU_E0_READ_VCO_CTUNE_3_0_SET(x)\
@@ -2430,8 +2648,10 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_E0_PLL_LOL_UDL_GET(x)\
FIELD_GET(SD_CMU_CMU_E0_PLL_LOL_UDL, x)
-/* SD_CMU_TARGET:SD_CMU_CFG:SD_CMU_CFG */
-#define SD_CMU_CFG_SD_CMU_CFG(t) __REG(TARGET_SD_CMU_CFG, t, 14, 0, 0, 1, 8, 0, 0, 1, 4)
+/* SD_CMU_TARGET:SD_CMU_CFG:SD_CMU_CFG */
+#define SD_CMU_CFG_SD_CMU_CFG(t) \
+ __REG(TARGET_SD_CMU_CFG, t, TSIZE(TC_SD_CMU_CFG), 0, 0, 1, 8, 0, 0, 1, \
+ 4)
#define SD_CMU_CFG_SD_CMU_CFG_CMU_RST BIT(0)
#define SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(x)\
@@ -2445,8 +2665,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_GET(x)\
FIELD_GET(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, x)
-/* SD_LANE_TARGET:SD_RESET:SD_SER_RST */
-#define SD_LANE_SD_SER_RST(t) __REG(TARGET_SD_LANE, t, 25, 0, 0, 1, 8, 0, 0, 1, 4)
+/* SD_LANE_TARGET:SD_RESET:SD_SER_RST */
+#define SD_LANE_SD_SER_RST(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 0, 0, 1, 8, 0, 0, 1, 4)
#define SD_LANE_SD_SER_RST_SER_RST BIT(0)
#define SD_LANE_SD_SER_RST_SER_RST_SET(x)\
@@ -2454,8 +2675,9 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_SER_RST_SER_RST_GET(x)\
FIELD_GET(SD_LANE_SD_SER_RST_SER_RST, x)
-/* SD_LANE_TARGET:SD_RESET:SD_DES_RST */
-#define SD_LANE_SD_DES_RST(t) __REG(TARGET_SD_LANE, t, 25, 0, 0, 1, 8, 4, 0, 1, 4)
+/* SD_LANE_TARGET:SD_RESET:SD_DES_RST */
+#define SD_LANE_SD_DES_RST(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 0, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_SD_DES_RST_DES_RST BIT(0)
#define SD_LANE_SD_DES_RST_DES_RST_SET(x)\
@@ -2463,8 +2685,9 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_DES_RST_DES_RST_GET(x)\
FIELD_GET(SD_LANE_SD_DES_RST_DES_RST, x)
-/* SD_LANE_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG */
-#define SD_LANE_SD_LANE_CFG(t) __REG(TARGET_SD_LANE, t, 25, 8, 0, 1, 8, 0, 0, 1, 4)
+/* SD_LANE_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG */
+#define SD_LANE_SD_LANE_CFG(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 8, 0, 1, 8, 0, 0, 1, 4)
#define SD_LANE_SD_LANE_CFG_MACRO_RST BIT(0)
#define SD_LANE_SD_LANE_CFG_MACRO_RST_SET(x)\
@@ -2508,8 +2731,9 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_LANE_CFG_LANE_RX_RST_GET(x)\
FIELD_GET(SD_LANE_SD_LANE_CFG_LANE_RX_RST, x)
-/* SD_LANE_TARGET:SD_LANE_CFG_STAT:SD_LANE_STAT */
-#define SD_LANE_SD_LANE_STAT(t) __REG(TARGET_SD_LANE, t, 25, 8, 0, 1, 8, 4, 0, 1, 4)
+/* SD_LANE_TARGET:SD_LANE_CFG_STAT:SD_LANE_STAT */
+#define SD_LANE_SD_LANE_STAT(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 8, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_SD_LANE_STAT_PMA_RST_DONE BIT(0)
#define SD_LANE_SD_LANE_STAT_PMA_RST_DONE_SET(x)\
@@ -2529,9 +2753,9 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_LANE_STAT_DBG_OBS_GET(x)\
FIELD_GET(SD_LANE_SD_LANE_STAT_DBG_OBS, x)
-/* SD_LANE_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
-#define SD_LANE_QUIET_MODE_6G(t) \
- __REG(TARGET_SD_LANE, t, 25, 24, 0, 1, 8, 4, 0, 1, 4)
+/* SD_LANE_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
+#define SD_LANE_QUIET_MODE_6G(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 24, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0)
#define SD_LANE_QUIET_MODE_6G_QUIET_MODE_SET(x)\
@@ -2539,8 +2763,9 @@ enum sparx5_serdes_target {
#define SD_LANE_QUIET_MODE_6G_QUIET_MODE_GET(x)\
FIELD_GET(SD_LANE_QUIET_MODE_6G_QUIET_MODE, x)
-/* SD_LANE_TARGET:CFG_STAT_FX100:MISC */
-#define SD_LANE_MISC(t) __REG(TARGET_SD_LANE, t, 25, 56, 0, 1, 56, 0, 0, 1, 4)
+/* SD_LANE_TARGET:CFG_STAT_FX100:MISC */
+#define SD_LANE_MISC(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 56, 0, 1, 56, 0, 0, 1, 4)
#define SD_LANE_MISC_SD_125_RST_DIS BIT(0)
#define SD_LANE_MISC_SD_125_RST_DIS_SET(x)\
@@ -2560,14 +2785,16 @@ enum sparx5_serdes_target {
#define SD_LANE_MISC_MUX_ENA_GET(x)\
FIELD_GET(SD_LANE_MISC_MUX_ENA, x)
+/* SPARX5 ONLY */
#define SD_LANE_MISC_CORE_CLK_FREQ GENMASK(5, 4)
#define SD_LANE_MISC_CORE_CLK_FREQ_SET(x)\
FIELD_PREP(SD_LANE_MISC_CORE_CLK_FREQ, x)
#define SD_LANE_MISC_CORE_CLK_FREQ_GET(x)\
FIELD_GET(SD_LANE_MISC_CORE_CLK_FREQ, x)
-/* SD_LANE_TARGET:CFG_STAT_FX100:M_STAT_MISC */
-#define SD_LANE_M_STAT_MISC(t) __REG(TARGET_SD_LANE, t, 25, 56, 0, 1, 56, 36, 0, 1, 4)
+/* SD_LANE_TARGET:CFG_STAT_FX100:M_STAT_MISC */
+#define SD_LANE_M_STAT_MISC(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 56, 0, 1, 56, 36, 0, 1, 4)
#define SD_LANE_M_STAT_MISC_M_RIS_EDGE_PTR_ADJ_SUM GENMASK(21, 0)
#define SD_LANE_M_STAT_MISC_M_RIS_EDGE_PTR_ADJ_SUM_SET(x)\
@@ -2581,8 +2808,10 @@ enum sparx5_serdes_target {
#define SD_LANE_M_STAT_MISC_M_LOCK_CNT_GET(x)\
FIELD_GET(SD_LANE_M_STAT_MISC_M_LOCK_CNT, x)
-/* SD25G_CFG_TARGET:SD_RESET:SD_SER_RST */
-#define SD_LANE_25G_SD_SER_RST(t) __REG(TARGET_SD_LANE_25G, t, 8, 0, 0, 1, 8, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_RESET:SD_SER_RST */
+#define SD_LANE_25G_SD_SER_RST(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 0, 0, 1, 8, 0, 0, 1, 4)
#define SD_LANE_25G_SD_SER_RST_SER_RST BIT(0)
#define SD_LANE_25G_SD_SER_RST_SER_RST_SET(x)\
@@ -2590,8 +2819,10 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_SER_RST_SER_RST_GET(x)\
FIELD_GET(SD_LANE_25G_SD_SER_RST_SER_RST, x)
-/* SD25G_CFG_TARGET:SD_RESET:SD_DES_RST */
-#define SD_LANE_25G_SD_DES_RST(t) __REG(TARGET_SD_LANE_25G, t, 8, 0, 0, 1, 8, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_RESET:SD_DES_RST */
+#define SD_LANE_25G_SD_DES_RST(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 0, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_25G_SD_DES_RST_DES_RST BIT(0)
#define SD_LANE_25G_SD_DES_RST_DES_RST_SET(x)\
@@ -2599,8 +2830,10 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_DES_RST_DES_RST_GET(x)\
FIELD_GET(SD_LANE_25G_SD_DES_RST_DES_RST, x)
-/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG */
-#define SD_LANE_25G_SD_LANE_CFG(t) __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG */
+#define SD_LANE_25G_SD_LANE_CFG(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 0, 0, 1, 4)
#define SD_LANE_25G_SD_LANE_CFG_MACRO_RST BIT(0)
#define SD_LANE_25G_SD_LANE_CFG_MACRO_RST_SET(x)\
@@ -2698,8 +2931,10 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_LANE_CFG_PCS2PMA_TXMARGIN_GET(x)\
FIELD_GET(SD_LANE_25G_SD_LANE_CFG_PCS2PMA_TXMARGIN, x)
-/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG2 */
-#define SD_LANE_25G_SD_LANE_CFG2(t) __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG2 */
+#define SD_LANE_25G_SD_LANE_CFG2(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 4, 0, 1, 4)
#define SD_LANE_25G_SD_LANE_CFG2_DATA_WIDTH_SEL GENMASK(2, 0)
#define SD_LANE_25G_SD_LANE_CFG2_DATA_WIDTH_SEL_SET(x)\
@@ -2767,8 +3002,10 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_LANE_CFG2_RXRATE_SEL_GET(x)\
FIELD_GET(SD_LANE_25G_SD_LANE_CFG2_RXRATE_SEL, x)
-/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_STAT */
-#define SD_LANE_25G_SD_LANE_STAT(t) __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 8, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_STAT */
+#define SD_LANE_25G_SD_LANE_STAT(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 8, 0, 1, 4)
#define SD_LANE_25G_SD_LANE_STAT_PMA_RST_DONE BIT(0)
#define SD_LANE_25G_SD_LANE_STAT_PMA_RST_DONE_SET(x)\
@@ -2788,8 +3025,9 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_LANE_STAT_DBG_OBS_GET(x)\
FIELD_GET(SD_LANE_25G_SD_LANE_STAT_DBG_OBS, x)
-/* SD25G_CFG_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
-#define SD_LANE_25G_QUIET_MODE_6G(t) \
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
+#define SD_LANE_25G_QUIET_MODE_6G(t) \
__REG(TARGET_SD_LANE_25G, t, 8, 28, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0)
diff --git a/drivers/phy/motorola/phy-cpcap-usb.c b/drivers/phy/motorola/phy-cpcap-usb.c
index 7bbf729a7c90..7cb020dd3423 100644
--- a/drivers/phy/motorola/phy-cpcap-usb.c
+++ b/drivers/phy/motorola/phy-cpcap-usb.c
@@ -704,7 +704,7 @@ static void cpcap_usb_phy_remove(struct platform_device *pdev)
static struct platform_driver cpcap_usb_phy_driver = {
.probe = cpcap_usb_phy_probe,
- .remove_new = cpcap_usb_phy_remove,
+ .remove = cpcap_usb_phy_remove,
.driver = {
.name = "cpcap-usb-phy",
.of_match_table = of_match_ptr(cpcap_usb_phy_id_table),
diff --git a/drivers/phy/motorola/phy-mapphone-mdm6600.c b/drivers/phy/motorola/phy-mapphone-mdm6600.c
index 376d023a0aa9..152344e4f7e4 100644
--- a/drivers/phy/motorola/phy-mapphone-mdm6600.c
+++ b/drivers/phy/motorola/phy-mapphone-mdm6600.c
@@ -655,7 +655,7 @@ static void phy_mdm6600_remove(struct platform_device *pdev)
static struct platform_driver phy_mdm6600_driver = {
.probe = phy_mdm6600_probe,
- .remove_new = phy_mdm6600_remove,
+ .remove = phy_mdm6600_remove,
.driver = {
.name = "phy-mapphone-mdm6600",
.pm = &phy_mdm6600_pm_ops,
diff --git a/drivers/phy/phy-airoha-pcie-regs.h b/drivers/phy/phy-airoha-pcie-regs.h
index bb1f679ca1df..b938a7b468fe 100644
--- a/drivers/phy/phy-airoha-pcie-regs.h
+++ b/drivers/phy/phy-airoha-pcie-regs.h
@@ -197,9 +197,9 @@
#define CSR_2L_PXP_TX1_MULTLANE_EN BIT(0)
#define REG_CSR_2L_RX0_REV0 0x00fc
-#define CSR_2L_PXP_VOS_PNINV GENMASK(3, 2)
-#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(6, 4)
-#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(10, 8)
+#define CSR_2L_PXP_VOS_PNINV GENMASK(19, 18)
+#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(22, 20)
+#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(26, 24)
#define REG_CSR_2L_RX0_PHYCK_DIV 0x0100
#define CSR_2L_PXP_RX0_PHYCK_SEL GENMASK(9, 8)
diff --git a/drivers/phy/phy-airoha-pcie.c b/drivers/phy/phy-airoha-pcie.c
index 1e410eb41058..56e9ade8a9fd 100644
--- a/drivers/phy/phy-airoha-pcie.c
+++ b/drivers/phy/phy-airoha-pcie.c
@@ -459,7 +459,7 @@ static void airoha_pcie_phy_init_clk_out(struct airoha_pcie_phy *pcie_phy)
airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
CSR_2L_PXP_CLKTX1_SR);
airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_PLL_CMN_RESERVE0,
- CSR_2L_PXP_PLL_RESERVE_MASK, 0xdd);
+ CSR_2L_PXP_PLL_RESERVE_MASK, 0xd0d);
}
static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy)
@@ -471,9 +471,9 @@ static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy)
PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST |
PCIE_SW_RX_RST);
airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
- PCIE_TX_TOP_RST | REG_PCIE_PMA_TX_RESET);
+ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
- PCIE_TX_TOP_RST | REG_PCIE_PMA_TX_RESET);
+ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
}
static void airoha_pcie_phy_init_rx(struct airoha_pcie_phy *pcie_phy)
@@ -802,7 +802,7 @@ static void airoha_pcie_phy_init_ssc_jcpll(struct airoha_pcie_phy *pcie_phy)
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_IFM,
CSR_2L_PXP_JCPLL_SDM_IFM);
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
- REG_CSR_2L_JCPLL_SDM_HREN);
+ CSR_2L_PXP_JCPLL_SDM_HREN);
airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
CSR_2L_PXP_JCPLL_SDM_DI_EN);
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
diff --git a/drivers/phy/phy-lgm-usb.c b/drivers/phy/phy-lgm-usb.c
index 410729c7f513..eb7c6fed20d3 100644
--- a/drivers/phy/phy-lgm-usb.c
+++ b/drivers/phy/phy-lgm-usb.c
@@ -271,7 +271,7 @@ static struct platform_driver lgm_phy_driver = {
.of_match_table = intel_usb_phy_dt_ids,
},
.probe = phy_probe,
- .remove_new = phy_remove,
+ .remove = phy_remove,
};
module_platform_driver(lgm_phy_driver);
diff --git a/drivers/phy/phy-nxp-ptn3222.c b/drivers/phy/phy-nxp-ptn3222.c
new file mode 100644
index 000000000000..c6179d8701e6
--- /dev/null
+++ b/drivers/phy/phy-nxp-ptn3222.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define NUM_SUPPLIES 2
+
+struct ptn3222 {
+ struct i2c_client *client;
+ struct phy *phy;
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data *supplies;
+};
+
+static int ptn3222_init(struct phy *phy)
+{
+ struct ptn3222 *ptn3222 = phy_get_drvdata(phy);
+ int ret;
+
+ ret = regulator_bulk_enable(NUM_SUPPLIES, ptn3222->supplies);
+ if (ret)
+ return ret;
+
+ gpiod_set_value_cansleep(ptn3222->reset_gpio, 0);
+
+ return 0;
+}
+
+static int ptn3222_exit(struct phy *phy)
+{
+ struct ptn3222 *ptn3222 = phy_get_drvdata(phy);
+
+ gpiod_set_value_cansleep(ptn3222->reset_gpio, 1);
+
+ return regulator_bulk_disable(NUM_SUPPLIES, ptn3222->supplies);
+}
+
+static const struct phy_ops ptn3222_ops = {
+ .init = ptn3222_init,
+ .exit = ptn3222_exit,
+ .owner = THIS_MODULE,
+};
+
+static const struct regulator_bulk_data ptn3222_supplies[NUM_SUPPLIES] = {
+ {
+ .supply = "vdd3v3",
+ .init_load_uA = 11000,
+ }, {
+ .supply = "vdd1v8",
+ .init_load_uA = 55000,
+ }
+};
+
+static int ptn3222_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct phy_provider *phy_provider;
+ struct ptn3222 *ptn3222;
+ int ret;
+
+ ptn3222 = devm_kzalloc(dev, sizeof(*ptn3222), GFP_KERNEL);
+ if (!ptn3222)
+ return -ENOMEM;
+
+ ptn3222->client = client;
+
+ ptn3222->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(ptn3222->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ptn3222->reset_gpio),
+ "unable to acquire reset gpio\n");
+
+ ret = devm_regulator_bulk_get_const(dev, NUM_SUPPLIES, ptn3222_supplies,
+ &ptn3222->supplies);
+ if (ret)
+ return ret;
+
+ ptn3222->phy = devm_phy_create(dev, dev->of_node, &ptn3222_ops);
+ if (IS_ERR(ptn3222->phy)) {
+ dev_err(dev, "failed to create PHY: %d\n", ret);
+ return PTR_ERR(ptn3222->phy);
+ }
+
+ phy_set_drvdata(ptn3222->phy, ptn3222);
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct i2c_device_id ptn3222_table[] = {
+ { "ptn3222" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ptn3222_table);
+
+static const struct of_device_id ptn3222_of_table[] = {
+ { .compatible = "nxp,ptn3222" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ptn3222_of_table);
+
+static struct i2c_driver ptn3222_driver = {
+ .driver = {
+ .name = "ptn3222",
+ .of_match_table = ptn3222_of_table,
+ },
+ .probe = ptn3222_probe,
+ .id_table = ptn3222_table,
+};
+
+module_i2c_driver(ptn3222_driver);
+
+MODULE_DESCRIPTION("NXP PTN3222 eUSB2 Redriver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
index 3642a5d4f2f3..cae290a6e19f 100644
--- a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
+++ b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
@@ -257,12 +257,12 @@ static const struct of_device_id qcom_apq8064_sata_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, qcom_apq8064_sata_phy_of_match);
static struct platform_driver qcom_apq8064_sata_phy_driver = {
- .probe = qcom_apq8064_sata_phy_probe,
- .remove_new = qcom_apq8064_sata_phy_remove,
+ .probe = qcom_apq8064_sata_phy_probe,
+ .remove = qcom_apq8064_sata_phy_remove,
.driver = {
- .name = "qcom-apq8064-sata-phy",
- .of_match_table = qcom_apq8064_sata_phy_of_match,
- }
+ .name = "qcom-apq8064-sata-phy",
+ .of_match_table = qcom_apq8064_sata_phy_of_match,
+ },
};
module_platform_driver(qcom_apq8064_sata_phy_driver);
diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c
index da2b32fb5b45..f1b51018683d 100644
--- a/drivers/phy/qualcomm/phy-qcom-edp.c
+++ b/drivers/phy/qualcomm/phy-qcom-edp.c
@@ -32,16 +32,8 @@
#define DP_PHY_PD_CTL 0x001c
#define DP_PHY_MODE 0x0020
-#define DP_PHY_AUX_CFG0 0x0024
-#define DP_PHY_AUX_CFG1 0x0028
-#define DP_PHY_AUX_CFG2 0x002C
-#define DP_PHY_AUX_CFG3 0x0030
-#define DP_PHY_AUX_CFG4 0x0034
-#define DP_PHY_AUX_CFG5 0x0038
-#define DP_PHY_AUX_CFG6 0x003C
-#define DP_PHY_AUX_CFG7 0x0040
-#define DP_PHY_AUX_CFG8 0x0044
-#define DP_PHY_AUX_CFG9 0x0048
+#define DP_AUX_CFG_SIZE 10
+#define DP_PHY_AUX_CFG(n) (0x24 + (0x04 * (n)))
#define DP_PHY_AUX_INTERRUPT_MASK 0x0058
@@ -90,6 +82,7 @@ struct phy_ver_ops {
struct qcom_edp_phy_cfg {
bool is_edp;
+ const u8 *aux_cfg;
const struct qcom_edp_swing_pre_emph_cfg *swing_pre_emph_cfg;
const struct phy_ver_ops *ver_ops;
};
@@ -186,11 +179,40 @@ static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg = {
.pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3,
};
+static const u8 edp_phy_aux_cfg_v4[10] = {
+ 0x00, 0x13, 0x24, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03
+};
+
+static const u8 edp_pre_emp_hbr_rbr_v5[4][4] = {
+ { 0x05, 0x11, 0x17, 0x1d },
+ { 0x05, 0x11, 0x18, 0xff },
+ { 0x06, 0x11, 0xff, 0xff },
+ { 0x00, 0xff, 0xff, 0xff }
+};
+
+static const u8 edp_pre_emp_hbr2_hbr3_v5[4][4] = {
+ { 0x0c, 0x15, 0x19, 0x1e },
+ { 0x0b, 0x15, 0x19, 0xff },
+ { 0x0e, 0x14, 0xff, 0xff },
+ { 0x0d, 0xff, 0xff, 0xff }
+};
+
+static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v5 = {
+ .swing_hbr_rbr = &edp_swing_hbr_rbr,
+ .swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3,
+ .pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr_v5,
+ .pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3_v5,
+};
+
+static const u8 edp_phy_aux_cfg_v5[10] = {
+ 0x00, 0x13, 0xa4, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03
+};
+
static int qcom_edp_phy_init(struct phy *phy)
{
struct qcom_edp *edp = phy_get_drvdata(phy);
+ u8 aux_cfg[DP_AUX_CFG_SIZE];
int ret;
- u8 cfg8;
ret = regulator_bulk_enable(ARRAY_SIZE(edp->supplies), edp->supplies);
if (ret)
@@ -200,6 +222,8 @@ static int qcom_edp_phy_init(struct phy *phy)
if (ret)
goto out_disable_supplies;
+ memcpy(aux_cfg, edp->cfg->aux_cfg, sizeof(aux_cfg));
+
writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
edp->edp + DP_PHY_PD_CTL);
@@ -222,22 +246,12 @@ static int qcom_edp_phy_init(struct phy *phy)
* even needed.
*/
if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp)
- cfg8 = 0xb7;
- else
- cfg8 = 0x37;
+ aux_cfg[8] = 0xb7;
writel(0xfc, edp->edp + DP_PHY_MODE);
- writel(0x00, edp->edp + DP_PHY_AUX_CFG0);
- writel(0x13, edp->edp + DP_PHY_AUX_CFG1);
- writel(0x24, edp->edp + DP_PHY_AUX_CFG2);
- writel(0x00, edp->edp + DP_PHY_AUX_CFG3);
- writel(0x0a, edp->edp + DP_PHY_AUX_CFG4);
- writel(0x26, edp->edp + DP_PHY_AUX_CFG5);
- writel(0x0a, edp->edp + DP_PHY_AUX_CFG6);
- writel(0x03, edp->edp + DP_PHY_AUX_CFG7);
- writel(cfg8, edp->edp + DP_PHY_AUX_CFG8);
- writel(0x03, edp->edp + DP_PHY_AUX_CFG9);
+ for (int i = 0; i < DP_AUX_CFG_SIZE; i++)
+ writel(aux_cfg[i], edp->edp + DP_PHY_AUX_CFG(i));
writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
@@ -518,17 +532,27 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v4 = {
.com_configure_ssc = qcom_edp_com_configure_ssc_v4,
};
+static const struct qcom_edp_phy_cfg sa8775p_dp_phy_cfg = {
+ .is_edp = false,
+ .aux_cfg = edp_phy_aux_cfg_v5,
+ .swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v5,
+ .ver_ops = &qcom_edp_phy_ops_v4,
+};
+
static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = {
+ .aux_cfg = edp_phy_aux_cfg_v4,
.ver_ops = &qcom_edp_phy_ops_v4,
};
static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = {
+ .aux_cfg = edp_phy_aux_cfg_v4,
.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
.ver_ops = &qcom_edp_phy_ops_v4,
};
static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = {
.is_edp = true,
+ .aux_cfg = edp_phy_aux_cfg_v4,
.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
.ver_ops = &qcom_edp_phy_ops_v4,
};
@@ -707,6 +731,7 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v6 = {
};
static struct qcom_edp_phy_cfg x1e80100_phy_cfg = {
+ .aux_cfg = edp_phy_aux_cfg_v4,
.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
.ver_ops = &qcom_edp_phy_ops_v6,
};
@@ -1108,6 +1133,7 @@ static int qcom_edp_phy_probe(struct platform_device *pdev)
}
static const struct of_device_id qcom_edp_phy_match_table[] = {
+ { .compatible = "qcom,sa8775p-edp-phy", .data = &sa8775p_dp_phy_cfg, },
{ .compatible = "qcom,sc7280-edp-phy", .data = &sc7280_dp_phy_cfg, },
{ .compatible = "qcom,sc8180x-edp-phy", .data = &sc7280_dp_phy_cfg, },
{ .compatible = "qcom,sc8280xp-dp-phy", .data = &sc8280xp_dp_phy_cfg, },
diff --git a/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c b/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c
index 68cc8e24f383..6bd1b3c75c77 100644
--- a/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c
+++ b/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c
@@ -294,7 +294,7 @@ MODULE_DEVICE_TABLE(of, eusb2_repeater_of_match_table);
static struct platform_driver eusb2_repeater_driver = {
.probe = eusb2_repeater_probe,
- .remove_new = eusb2_repeater_remove,
+ .remove = eusb2_repeater_remove,
.driver = {
.name = "qcom-eusb2-repeater",
.of_match_table = eusb2_repeater_of_match_table,
diff --git a/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
index f0a72b82c770..f5eb0bdac418 100644
--- a/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
+++ b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
@@ -184,11 +184,11 @@ static const struct of_device_id qcom_ipq806x_sata_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, qcom_ipq806x_sata_phy_of_match);
static struct platform_driver qcom_ipq806x_sata_phy_driver = {
- .probe = qcom_ipq806x_sata_phy_probe,
- .remove_new = qcom_ipq806x_sata_phy_remove,
+ .probe = qcom_ipq806x_sata_phy_probe,
+ .remove = qcom_ipq806x_sata_phy_remove,
.driver = {
- .name = "qcom-ipq806x-sata-phy",
- .of_match_table = qcom_ipq806x_sata_phy_of_match,
+ .name = "qcom-ipq806x-sata-phy",
+ .of_match_table = qcom_ipq806x_sata_phy_of_match,
}
};
module_platform_driver(qcom_ipq806x_sata_phy_driver);
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index 643045c9024e..3bae39381fd0 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -3483,7 +3483,7 @@ static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
}
#endif
-static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np)
+static int qmp_combo_parse_dt_legacy_dp(struct qmp_combo *qmp, struct device_node *np)
{
struct device *dev = qmp->dev;
@@ -3510,7 +3510,7 @@ static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_nod
return 0;
}
-static int qmp_combo_parse_dt_lecacy_usb(struct qmp_combo *qmp, struct device_node *np)
+static int qmp_combo_parse_dt_legacy_usb(struct qmp_combo *qmp, struct device_node *np)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
struct device *dev = qmp->dev;
@@ -3576,11 +3576,11 @@ static int qmp_combo_parse_dt_legacy(struct qmp_combo *qmp, struct device_node *
if (IS_ERR(qmp->dp_serdes))
return PTR_ERR(qmp->dp_serdes);
- ret = qmp_combo_parse_dt_lecacy_usb(qmp, usb_np);
+ ret = qmp_combo_parse_dt_legacy_usb(qmp, usb_np);
if (ret)
return ret;
- ret = qmp_combo_parse_dt_lecacy_dp(qmp, dp_np);
+ ret = qmp_combo_parse_dt_legacy_dp(qmp, dp_np);
if (ret)
return ret;
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
index 36aaac34e6c6..873f2f9844c6 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
@@ -34,6 +34,8 @@
#include "phy-qcom-qmp-pcs-pcie-v5_20.h"
#include "phy-qcom-qmp-pcs-pcie-v6.h"
#include "phy-qcom-qmp-pcs-pcie-v6_20.h"
+#include "phy-qcom-qmp-pcs-pcie-v6_30.h"
+#include "phy-qcom-qmp-pcs-v6_30.h"
#include "phy-qcom-qmp-pcie-qhp.h"
#define PHY_INIT_COMPLETE_TIMEOUT 10000
@@ -1344,6 +1346,154 @@ static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_FOM_EQ_CONFIG5, 0x8a),
};
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x26),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x68),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0xf8),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x62),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_POST_DIV_MUX, 0x40),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x90),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x46),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_CFG, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MISC_1, 0x88),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MODE, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_VCO_DC_LEVEL_CTRL, 0x0f),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_ln_shrd_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RXCLK_DIV2_CTRL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_SUMMER_CAL_SPD_MODE, 0x5b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_DFE_DAC_ENABLE1, 0x88),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH2, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B0, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B1, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B2, 0xdb),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B3, 0x9a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B4, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B5, 0xb6),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B6, 0x64),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH4_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH5_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH6_RATE3, 0x1f),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_txz_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_TX, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_RX, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_2, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_3, 0x51),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_TRAN_DRVR_EMP_EN, 0x34),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_rxz_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_2, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_GAIN_RATE_2, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_3, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_PI_CONTROLS, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_CAL_CTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_POSTCAL_OFFSET, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_BKUP_CTRL1, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_3, 0x45),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_VGA_CAL_CNTRL1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_GM_CAL, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_EQU_ADAPTOR_CNTRL4, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_SIGDET_ENABLES, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_PHPRE_CTRL, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_Q_PI_INTRINSIC_BIAS_RATE32, 0x39),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B0, 0xd4),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B1, 0x23),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B2, 0x58),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B3, 0x9a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B4, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B5, 0xb6),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B6, 0xee),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B0, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B1, 0xe4),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B2, 0x60),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B3, 0xdf),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B4, 0x69),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B5, 0x76),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B6, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_TX_ADPT_CTRL, 0x10),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_rx_tbl[] = {
+ QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x3a, BIT(0)),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_LOCK_DETECT_CONFIG2, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_G3S2_PRE_GAIN, 0x2e),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_RX_SIGDET_LVL, 0x99),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_ALIGN_DETECT_CONFIG7, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_EQ_CONFIG4, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_EQ_CONFIG5, 0x22),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_TX_RX_CONFIG, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_TX_RX_CONFIG2, 0x02),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_ENDPOINT_REFCLK_DRIVE, 0xc1),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_OSC_DTCT_ACTIONS, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_EQ_CONFIG1, 0x16),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G4_EQ_CONFIG5, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G4_PRE_GAIN, 0x2e),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG1, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG3, 0x28),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG5, 0x18),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G3_FOM_EQ_CONFIG5, 0x7a),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G4_FOM_EQ_CONFIG5, 0x8a),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G3_RXEQEVAL_TIME, 0x27),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G4_RXEQEVAL_TIME, 0x27),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_TX_RX_CONFIG, 0xc0),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_POWER_STATE_CONFIG2, 0x1d),
+};
+
static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34),
@@ -2582,6 +2732,8 @@ struct qmp_pcie_offsets {
u16 rx;
u16 tx2;
u16 rx2;
+ u16 txz;
+ u16 rxz;
u16 ln_shrd;
};
@@ -2592,6 +2744,10 @@ struct qmp_phy_cfg_tbls {
int tx_num;
const struct qmp_phy_init_tbl *rx;
int rx_num;
+ const struct qmp_phy_init_tbl *txz;
+ int txz_num;
+ const struct qmp_phy_init_tbl *rxz;
+ int rxz_num;
const struct qmp_phy_init_tbl *pcs;
int pcs_num;
const struct qmp_phy_init_tbl *pcs_misc;
@@ -2659,6 +2815,8 @@ struct qmp_pcie {
void __iomem *rx;
void __iomem *tx2;
void __iomem *rx2;
+ void __iomem *txz;
+ void __iomem *rxz;
void __iomem *ln_shrd;
void __iomem *port_b;
@@ -2826,6 +2984,17 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v6_20 = {
.ln_shrd = 0x0e00,
};
+static const struct qmp_pcie_offsets qmp_pcie_offsets_v6_30 = {
+ .serdes = 0x8800,
+ .pcs = 0x9000,
+ .pcs_misc = 0x9800,
+ .tx = 0x0000,
+ .rx = 0x0200,
+ .txz = 0xe000,
+ .rxz = 0xe200,
+ .ln_shrd = 0x8000,
+};
+
static const struct qmp_phy_cfg ipq8074_pciephy_cfg = {
.lanes = 1,
@@ -3704,6 +3873,38 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x4_pciephy_cfg = {
.has_nocsr_reset = true,
};
+static const struct qmp_phy_cfg x1e80100_qmp_gen4x8_pciephy_cfg = {
+ .lanes = 8,
+
+ .offsets = &qmp_pcie_offsets_v6_30,
+ .tbls = {
+ .serdes = x1e80100_qmp_gen4x8_pcie_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_serdes_tbl),
+ .rx = x1e80100_qmp_gen4x8_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_rx_tbl),
+ .txz = x1e80100_qmp_gen4x8_pcie_txz_tbl,
+ .txz_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_txz_tbl),
+ .rxz = x1e80100_qmp_gen4x8_pcie_rxz_tbl,
+ .rxz_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_rxz_tbl),
+ .pcs = x1e80100_qmp_gen4x8_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_pcs_tbl),
+ .pcs_misc = x1e80100_qmp_gen4x8_pcie_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_pcs_misc_tbl),
+ .ln_shrd = x1e80100_qmp_gen4x8_pcie_ln_shrd_tbl,
+ .ln_shrd_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_ln_shrd_tbl),
+ },
+
+ .reset_list = sdm845_pciephy_reset_l,
+ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .vreg_list = sm8550_qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
+ .regs = pciephy_v6_regs_layout,
+
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS_4_20,
+ .has_nocsr_reset = true,
+};
+
static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -3751,6 +3952,13 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c
qmp_configure(qmp->dev, serdes, tbls->serdes, tbls->serdes_num);
+ /*
+ * Tx/Rx registers that require different settings than
+ * txz/rxz must be programmed after txz/rxz.
+ */
+ qmp_configure(qmp->dev, qmp->txz, tbls->txz, tbls->txz_num);
+ qmp_configure(qmp->dev, qmp->rxz, tbls->rxz, tbls->rxz_num);
+
qmp_configure_lane(qmp->dev, tx, tbls->tx, tbls->tx_num, 1);
qmp_configure_lane(qmp->dev, rx, tbls->rx, tbls->rx_num, 1);
@@ -4293,6 +4501,9 @@ static int qmp_pcie_parse_dt(struct qmp_pcie *qmp)
return PTR_ERR(qmp->port_b);
}
+ qmp->txz = base + offs->txz;
+ qmp->rxz = base + offs->rxz;
+
if (cfg->tbls.ln_shrd)
qmp->ln_shrd = base + offs->ln_shrd;
@@ -4478,6 +4689,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
}, {
.compatible = "qcom,x1e80100-qmp-gen4x4-pcie-phy",
.data = &x1e80100_qmp_gen4x4_pciephy_cfg,
+ }, {
+ .compatible = "qcom,x1e80100-qmp-gen4x8-pcie-phy",
+ .data = &x1e80100_qmp_gen4x8_pciephy_cfg,
},
{ },
};
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_30.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_30.h
new file mode 100644
index 000000000000..5a58ff197e6e
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_30.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_PCIE_V6_30_H_
+#define QCOM_PHY_QMP_PCS_PCIE_V6_30_H_
+
+/* Only for QMP V6_30 PHY - PCIE have different offsets than V6 */
+#define QPHY_PCIE_V6_30_PCS_POWER_STATE_CONFIG2 0x014
+#define QPHY_PCIE_V6_30_PCS_TX_RX_CONFIG 0x020
+#define QPHY_PCIE_V6_30_PCS_ENDPOINT_REFCLK_DRIVE 0x024
+#define QPHY_PCIE_V6_30_PCS_OSC_DTCT_ACTIONS 0x098
+#define QPHY_PCIE_V6_30_PCS_EQ_CONFIG1 0x0a8
+#define QPHY_PCIE_V6_30_PCS_G3_RXEQEVAL_TIME 0x0f8
+#define QPHY_PCIE_V6_30_PCS_G4_RXEQEVAL_TIME 0x0fc
+#define QPHY_PCIE_V6_30_PCS_G4_EQ_CONFIG5 0x110
+#define QPHY_PCIE_V6_30_PCS_G4_PRE_GAIN 0x164
+#define QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG1 0x184
+#define QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG3 0x18c
+#define QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG5 0x194
+#define QPHY_PCIE_V6_30_PCS_G3_FOM_EQ_CONFIG5 0x1b4
+#define QPHY_PCIE_V6_30_PCS_G4_FOM_EQ_CONFIG5 0x1c8
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_30.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_30.h
new file mode 100644
index 000000000000..369120d88bc2
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_30.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_V6_30_H_
+#define QCOM_PHY_QMP_PCS_V6_30_H_
+
+/* Only for QMP V6_30 PHY - PCIe PCS registers */
+#define QPHY_V6_30_PCS_LOCK_DETECT_CONFIG2 0x0cc
+#define QPHY_V6_30_PCS_G3S2_PRE_GAIN 0x17c
+#define QPHY_V6_30_PCS_RX_SIGDET_LVL 0x194
+#define QPHY_V6_30_PCS_ALIGN_DETECT_CONFIG7 0x1dc
+#define QPHY_V6_30_PCS_TX_RX_CONFIG 0x1e0
+#define QPHY_V6_30_PCS_TX_RX_CONFIG2 0x1e4
+#define QPHY_V6_30_PCS_EQ_CONFIG4 0x1fc
+#define QPHY_V6_30_PCS_EQ_CONFIG5 0x200
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
index 1246d3bc8b92..acd6075bf6d9 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
@@ -871,6 +871,16 @@ static const struct qmp_phy_init_tbl sdx75_usb3_uniphy_pcs_usb_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V6_PCS_USB3_RCVR_DTCT_DLY_U3_H, 0x00),
};
+static const struct qmp_phy_init_tbl qcs8300_usb3_uniphy_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0xf2),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e),
+};
+
static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5),
QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82),
@@ -989,6 +999,40 @@ static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e),
};
+static const struct qmp_phy_init_tbl qcs8300_usb3_uniphy_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xec),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0x7f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x19),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00),
+};
+
static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdc),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd),
@@ -1462,6 +1506,24 @@ static const struct qmp_phy_cfg sa8775p_usb3_uniphy_cfg = {
.regs = qmp_v5_usb3phy_regs_layout,
};
+static const struct qmp_phy_cfg qcs8300_usb3_uniphy_cfg = {
+ .offsets = &qmp_usb_offsets_v5,
+
+ .serdes_tbl = sc8280xp_usb3_uniphy_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_serdes_tbl),
+ .tx_tbl = qcs8300_usb3_uniphy_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(qcs8300_usb3_uniphy_tx_tbl),
+ .rx_tbl = qcs8300_usb3_uniphy_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(qcs8300_usb3_uniphy_rx_tbl),
+ .pcs_tbl = sa8775p_usb3_uniphy_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(sa8775p_usb3_uniphy_pcs_tbl),
+ .pcs_usb_tbl = sa8775p_usb3_uniphy_pcs_usb_tbl,
+ .pcs_usb_tbl_num = ARRAY_SIZE(sa8775p_usb3_uniphy_pcs_usb_tbl),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = qmp_v5_usb3phy_regs_layout,
+};
+
static const struct qmp_phy_cfg sc8280xp_usb3_uniphy_cfg = {
.offsets = &qmp_usb_offsets_v5,
@@ -2248,6 +2310,9 @@ static const struct of_device_id qmp_usb_of_match_table[] = {
.compatible = "qcom,msm8996-qmp-usb3-phy",
.data = &msm8996_usb3phy_cfg,
}, {
+ .compatible = "qcom,qcs8300-qmp-usb3-uni-phy",
+ .data = &qcs8300_usb3_uniphy_cfg,
+ }, {
.compatible = "qcom,qdu1000-qmp-usb3-uni-phy",
.data = &qdu1000_usb3_uniphy_cfg,
}, {
diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
index e3ad7cea5109..248550ef98ca 100644
--- a/drivers/phy/realtek/phy-rtk-usb2.c
+++ b/drivers/phy/realtek/phy-rtk-usb2.c
@@ -1023,6 +1023,8 @@ static int rtk_usb2phy_probe(struct platform_device *pdev)
rtk_phy->dev = &pdev->dev;
rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
+ if (!rtk_phy->phy_cfg)
+ return -ENOMEM;
memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
@@ -1298,7 +1300,7 @@ MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
static struct platform_driver rtk_usb2phy_driver = {
.probe = rtk_usb2phy_probe,
- .remove_new = rtk_usb2phy_remove,
+ .remove = rtk_usb2phy_remove,
.driver = {
.name = "rtk-usb2phy",
.of_match_table = usbphy_rtk_dt_match,
diff --git a/drivers/phy/realtek/phy-rtk-usb3.c b/drivers/phy/realtek/phy-rtk-usb3.c
index dfcf4b921bba..cce453686db2 100644
--- a/drivers/phy/realtek/phy-rtk-usb3.c
+++ b/drivers/phy/realtek/phy-rtk-usb3.c
@@ -577,6 +577,8 @@ static int rtk_usb3phy_probe(struct platform_device *pdev)
rtk_phy->dev = &pdev->dev;
rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
+ if (!rtk_phy->phy_cfg)
+ return -ENOMEM;
memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
@@ -734,7 +736,7 @@ MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
static struct platform_driver rtk_usb3phy_driver = {
.probe = rtk_usb3phy_probe,
- .remove_new = rtk_usb3phy_remove,
+ .remove = rtk_usb3phy_remove,
.driver = {
.name = "rtk-usb3phy",
.of_match_table = usbphy_rtk_dt_match,
diff --git a/drivers/phy/renesas/phy-rcar-gen3-pcie.c b/drivers/phy/renesas/phy-rcar-gen3-pcie.c
index 0ce7e9c94444..feca4cb2ff4d 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-pcie.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-pcie.c
@@ -132,11 +132,11 @@ static void rcar_gen3_phy_pcie_remove(struct platform_device *pdev)
static struct platform_driver rcar_gen3_phy_driver = {
.driver = {
- .name = "phy_rcar_gen3_pcie",
- .of_match_table = rcar_gen3_phy_pcie_match_table,
+ .name = "phy_rcar_gen3_pcie",
+ .of_match_table = rcar_gen3_phy_pcie_match_table,
},
- .probe = rcar_gen3_phy_pcie_probe,
- .remove_new = rcar_gen3_phy_pcie_remove,
+ .probe = rcar_gen3_phy_pcie_probe,
+ .remove = rcar_gen3_phy_pcie_remove,
};
module_platform_driver(rcar_gen3_phy_driver);
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index 58e123305152..775f4f973a6c 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -825,7 +825,7 @@ static struct platform_driver rcar_gen3_phy_usb2_driver = {
.of_match_table = rcar_gen3_phy_usb2_match_table,
},
.probe = rcar_gen3_phy_usb2_probe,
- .remove_new = rcar_gen3_phy_usb2_remove,
+ .remove = rcar_gen3_phy_usb2_remove,
};
module_platform_driver(rcar_gen3_phy_usb2_driver);
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb3.c b/drivers/phy/renesas/phy-rcar-gen3-usb3.c
index e2d630edd992..5c267d148c90 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb3.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb3.c
@@ -206,11 +206,11 @@ static void rcar_gen3_phy_usb3_remove(struct platform_device *pdev)
static struct platform_driver rcar_gen3_phy_usb3_driver = {
.driver = {
- .name = "phy_rcar_gen3_usb3",
- .of_match_table = rcar_gen3_phy_usb3_match_table,
+ .name = "phy_rcar_gen3_usb3",
+ .of_match_table = rcar_gen3_phy_usb3_match_table,
},
- .probe = rcar_gen3_phy_usb3_probe,
- .remove_new = rcar_gen3_phy_usb3_remove,
+ .probe = rcar_gen3_phy_usb3_probe,
+ .remove = rcar_gen3_phy_usb3_remove,
};
module_platform_driver(rcar_gen3_phy_usb3_driver);
diff --git a/drivers/phy/renesas/r8a779f0-ether-serdes.c b/drivers/phy/renesas/r8a779f0-ether-serdes.c
index f1f1da4a0b1f..3b2d8cef75e5 100644
--- a/drivers/phy/renesas/r8a779f0-ether-serdes.c
+++ b/drivers/phy/renesas/r8a779f0-ether-serdes.c
@@ -404,7 +404,7 @@ static void r8a779f0_eth_serdes_remove(struct platform_device *pdev)
static struct platform_driver r8a779f0_eth_serdes_driver_platform = {
.probe = r8a779f0_eth_serdes_probe,
- .remove_new = r8a779f0_eth_serdes_remove,
+ .remove = r8a779f0_eth_serdes_remove,
.driver = {
.name = "r8a779f0_eth_serdes",
.of_match_table = r8a779f0_eth_serdes_of_table,
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c
index 98c92d6c482f..2ab99e1d47eb 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c
@@ -472,7 +472,7 @@ static struct platform_driver rockchip_inno_csidphy_driver = {
.of_match_table = rockchip_inno_csidphy_match_id,
},
.probe = rockchip_inno_csidphy_probe,
- .remove_new = rockchip_inno_csidphy_remove,
+ .remove = rockchip_inno_csidphy_remove,
};
module_platform_driver(rockchip_inno_csidphy_driver);
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
index 6405943a2676..d5b1a4e2f7d3 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
@@ -784,7 +784,7 @@ static struct platform_driver inno_dsidphy_driver = {
.of_match_table = of_match_ptr(inno_dsidphy_of_match),
},
.probe = inno_dsidphy_probe,
- .remove_new = inno_dsidphy_remove,
+ .remove = inno_dsidphy_remove,
};
module_platform_driver(inno_dsidphy_driver);
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
index 053bd62e31ba..8dcc2bb777b5 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -1424,8 +1424,8 @@ static const struct of_device_id inno_hdmi_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, inno_hdmi_phy_of_match);
static struct platform_driver inno_hdmi_phy_driver = {
- .probe = inno_hdmi_phy_probe,
- .remove_new = inno_hdmi_phy_remove,
+ .probe = inno_hdmi_phy_probe,
+ .remove = inno_hdmi_phy_remove,
.driver = {
.name = "inno-hdmi-phy",
.of_match_table = inno_hdmi_phy_of_match,
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index 4f71373ae6e1..96f3d868a526 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -229,9 +229,10 @@ struct rockchip_usb2phy_port {
* @dev: pointer to device.
* @grf: General Register Files regmap.
* @usbgrf: USB General Register Files regmap.
- * @clk: clock struct of phy input clk.
+ * @clks: array of phy input clocks.
* @clk480m: clock struct of phy output clk.
* @clk480m_hw: clock struct of phy output clk management.
+ * @num_clks: number of phy input clocks.
* @phy_reset: phy reset control.
* @chg_state: states involved in USB charger detection.
* @chg_type: USB charger types.
@@ -246,9 +247,10 @@ struct rockchip_usb2phy {
struct device *dev;
struct regmap *grf;
struct regmap *usbgrf;
- struct clk *clk;
+ struct clk_bulk_data *clks;
struct clk *clk480m;
struct clk_hw clk480m_hw;
+ int num_clks;
struct reset_control *phy_reset;
enum usb_chg_state chg_state;
enum power_supply_type chg_type;
@@ -310,6 +312,13 @@ static int rockchip_usb2phy_reset(struct rockchip_usb2phy *rphy)
return 0;
}
+static void rockchip_usb2phy_clk_bulk_disable(void *data)
+{
+ struct rockchip_usb2phy *rphy = data;
+
+ clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks);
+}
+
static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
{
struct rockchip_usb2phy *rphy =
@@ -376,7 +385,9 @@ rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
{
struct device_node *node = rphy->dev->of_node;
struct clk_init_data init;
+ struct clk *refclk = NULL;
const char *clk_name;
+ int i;
int ret = 0;
init.flags = 0;
@@ -386,8 +397,15 @@ rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
/* optional override of the clockname */
of_property_read_string(node, "clock-output-names", &init.name);
- if (rphy->clk) {
- clk_name = __clk_get_name(rphy->clk);
+ for (i = 0; i < rphy->num_clks; i++) {
+ if (!strncmp(rphy->clks[i].id, "phyclk", 6)) {
+ refclk = rphy->clks[i].clk;
+ break;
+ }
+ }
+
+ if (!IS_ERR(refclk)) {
+ clk_name = __clk_get_name(refclk);
init.parent_names = &clk_name;
init.num_parents = 1;
} else {
@@ -418,30 +436,28 @@ err_ret:
static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy)
{
- int ret;
struct device_node *node = rphy->dev->of_node;
struct extcon_dev *edev;
+ int ret;
if (of_property_read_bool(node, "extcon")) {
edev = extcon_get_edev_by_phandle(rphy->dev, 0);
- if (IS_ERR(edev)) {
- if (PTR_ERR(edev) != -EPROBE_DEFER)
- dev_err(rphy->dev, "Invalid or missing extcon\n");
- return PTR_ERR(edev);
- }
+ if (IS_ERR(edev))
+ return dev_err_probe(rphy->dev, PTR_ERR(edev),
+ "invalid or missing extcon\n");
} else {
/* Initialize extcon device */
edev = devm_extcon_dev_allocate(rphy->dev,
rockchip_usb2phy_extcon_cable);
if (IS_ERR(edev))
- return -ENOMEM;
+ return dev_err_probe(rphy->dev, PTR_ERR(edev),
+ "failed to allocate extcon device\n");
ret = devm_extcon_dev_register(rphy->dev, edev);
- if (ret) {
- dev_err(rphy->dev, "failed to register extcon device\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(rphy->dev, ret,
+ "failed to register extcon device\n");
}
rphy->edev = edev;
@@ -1327,7 +1343,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
struct rockchip_usb2phy *rphy;
const struct rockchip_usb2phy_cfg *phy_cfgs;
unsigned int reg;
- int index, ret;
+ int index = 0, ret;
rphy = devm_kzalloc(dev, sizeof(*rphy), GFP_KERNEL);
if (!rphy)
@@ -1339,9 +1355,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
dev_err(dev, "failed to locate usbgrf\n");
return PTR_ERR(rphy->grf);
}
- }
-
- else {
+ } else {
rphy->grf = syscon_node_to_regmap(dev->parent->of_node);
if (IS_ERR(rphy->grf))
return PTR_ERR(rphy->grf);
@@ -1358,16 +1372,14 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
}
if (of_property_read_u32_index(np, "reg", 0, &reg)) {
- dev_err(dev, "the reg property is not assigned in %pOFn node\n",
- np);
+ dev_err(dev, "the reg property is not assigned in %pOFn node\n", np);
return -EINVAL;
}
/* support address_cells=2 */
if (of_property_count_u32_elems(np, "reg") > 2 && reg == 0) {
if (of_property_read_u32_index(np, "reg", 1, &reg)) {
- dev_err(dev, "the reg property is not assigned in %pOFn node\n",
- np);
+ dev_err(dev, "the reg property is not assigned in %pOFn node\n", np);
return -EINVAL;
}
}
@@ -1386,8 +1398,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
if (ret)
return ret;
- /* find out a proper config which can be matched with dt. */
- index = 0;
+ /* find a proper config that can be matched with the DT */
do {
if (phy_cfgs[index].reg == reg) {
rphy->phy_cfg = &phy_cfgs[index];
@@ -1406,17 +1417,25 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
if (IS_ERR(rphy->phy_reset))
return PTR_ERR(rphy->phy_reset);
- rphy->clk = devm_clk_get_optional_enabled(dev, "phyclk");
- if (IS_ERR(rphy->clk)) {
- return dev_err_probe(&pdev->dev, PTR_ERR(rphy->clk),
- "failed to get phyclk\n");
- }
+ ret = devm_clk_bulk_get_all(dev, &rphy->clks);
+ if (ret == -EPROBE_DEFER)
+ return dev_err_probe(&pdev->dev, -EPROBE_DEFER,
+ "failed to get phy clock\n");
+
+ /* Clocks are optional */
+ rphy->num_clks = ret < 0 ? 0 : ret;
ret = rockchip_usb2phy_clk480m_register(rphy);
- if (ret) {
- dev_err(dev, "failed to register 480m output clock\n");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register 480m output clock\n");
+
+ ret = clk_bulk_prepare_enable(rphy->num_clks, rphy->clks);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable phy clock\n");
+
+ ret = devm_add_action_or_reset(dev, rockchip_usb2phy_clk_bulk_disable, rphy);
+ if (ret)
return ret;
- }
if (rphy->phy_cfg->phy_tuning) {
ret = rphy->phy_cfg->phy_tuning(rphy);
@@ -1436,8 +1455,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops);
if (IS_ERR(phy)) {
- dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
- ret = PTR_ERR(phy);
+ ret = dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
goto put_child;
}
@@ -1446,13 +1464,11 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
/* initialize otg/host port separately */
if (of_node_name_eq(child_np, "host-port")) {
- ret = rockchip_usb2phy_host_port_init(rphy, rport,
- child_np);
+ ret = rockchip_usb2phy_host_port_init(rphy, rport, child_np);
if (ret)
goto put_child;
} else {
- ret = rockchip_usb2phy_otg_port_init(rphy, rport,
- child_np);
+ ret = rockchip_usb2phy_otg_port_init(rphy, rport, child_np);
if (ret)
goto put_child;
}
@@ -1474,8 +1490,7 @@ next_child:
"rockchip_usb2phy",
rphy);
if (ret) {
- dev_err(rphy->dev,
- "failed to request usb2phy irq handle\n");
+ dev_err_probe(rphy->dev, ret, "failed to request usb2phy irq handle\n");
goto put_child;
}
}
@@ -1495,6 +1510,30 @@ static int rk3128_usb2phy_tuning(struct rockchip_usb2phy *rphy)
BIT(2) << BIT_WRITEABLE_SHIFT | 0);
}
+static int rk3576_usb2phy_tuning(struct rockchip_usb2phy *rphy)
+{
+ int ret;
+ u32 reg = rphy->phy_cfg->reg;
+
+ /* Deassert SIDDQ to power on analog block */
+ ret = regmap_write(rphy->grf, reg + 0x0010, GENMASK(29, 29) | 0x0000);
+ if (ret)
+ return ret;
+
+ /* Do reset after exit IDDQ mode */
+ ret = rockchip_usb2phy_reset(rphy);
+ if (ret)
+ return ret;
+
+ /* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */
+ ret |= regmap_write(rphy->grf, reg + 0x000c, GENMASK(27, 24) | 0x0900);
+
+ /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */
+ ret |= regmap_write(rphy->grf, reg + 0x0010, GENMASK(20, 19) | 0x0010);
+
+ return ret;
+}
+
static int rk3588_usb2phy_tuning(struct rockchip_usb2phy *rphy)
{
int ret;
@@ -1923,6 +1962,84 @@ static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = {
{ /* sentinel */ }
};
+static const struct rockchip_usb2phy_cfg rk3576_phy_cfgs[] = {
+ {
+ .reg = 0x0,
+ .num_ports = 1,
+ .phy_tuning = rk3576_usb2phy_tuning,
+ .clkout_ctl = { 0x0008, 0, 0, 1, 0 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x0000, 8, 0, 0, 0x1d1 },
+ .bvalid_det_en = { 0x00c0, 1, 1, 0, 1 },
+ .bvalid_det_st = { 0x00c4, 1, 1, 0, 1 },
+ .bvalid_det_clr = { 0x00c8, 1, 1, 0, 1 },
+ .ls_det_en = { 0x00c0, 0, 0, 0, 1 },
+ .ls_det_st = { 0x00c4, 0, 0, 0, 1 },
+ .ls_det_clr = { 0x00c8, 0, 0, 0, 1 },
+ .disfall_en = { 0x00c0, 6, 6, 0, 1 },
+ .disfall_st = { 0x00c4, 6, 6, 0, 1 },
+ .disfall_clr = { 0x00c8, 6, 6, 0, 1 },
+ .disrise_en = { 0x00c0, 5, 5, 0, 1 },
+ .disrise_st = { 0x00c4, 5, 5, 0, 1 },
+ .disrise_clr = { 0x00c8, 5, 5, 0, 1 },
+ .utmi_avalid = { 0x0080, 1, 1, 0, 1 },
+ .utmi_bvalid = { 0x0080, 0, 0, 0, 1 },
+ .utmi_ls = { 0x0080, 5, 4, 0, 1 },
+ }
+ },
+ .chg_det = {
+ .cp_det = { 0x0080, 8, 8, 0, 1 },
+ .dcp_det = { 0x0080, 8, 8, 0, 1 },
+ .dp_det = { 0x0080, 9, 9, 1, 0 },
+ .idm_sink_en = { 0x0010, 5, 5, 1, 0 },
+ .idp_sink_en = { 0x0010, 5, 5, 0, 1 },
+ .idp_src_en = { 0x0010, 14, 14, 0, 1 },
+ .rdm_pdwn_en = { 0x0010, 14, 14, 0, 1 },
+ .vdm_src_en = { 0x0010, 7, 6, 0, 3 },
+ .vdp_src_en = { 0x0010, 7, 6, 0, 3 },
+ },
+ },
+ {
+ .reg = 0x2000,
+ .num_ports = 1,
+ .phy_tuning = rk3576_usb2phy_tuning,
+ .clkout_ctl = { 0x2008, 0, 0, 1, 0 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x2000, 8, 0, 0, 0x1d1 },
+ .bvalid_det_en = { 0x20c0, 1, 1, 0, 1 },
+ .bvalid_det_st = { 0x20c4, 1, 1, 0, 1 },
+ .bvalid_det_clr = { 0x20c8, 1, 1, 0, 1 },
+ .ls_det_en = { 0x20c0, 0, 0, 0, 1 },
+ .ls_det_st = { 0x20c4, 0, 0, 0, 1 },
+ .ls_det_clr = { 0x20c8, 0, 0, 0, 1 },
+ .disfall_en = { 0x20c0, 6, 6, 0, 1 },
+ .disfall_st = { 0x20c4, 6, 6, 0, 1 },
+ .disfall_clr = { 0x20c8, 6, 6, 0, 1 },
+ .disrise_en = { 0x20c0, 5, 5, 0, 1 },
+ .disrise_st = { 0x20c4, 5, 5, 0, 1 },
+ .disrise_clr = { 0x20c8, 5, 5, 0, 1 },
+ .utmi_avalid = { 0x2080, 1, 1, 0, 1 },
+ .utmi_bvalid = { 0x2080, 0, 0, 0, 1 },
+ .utmi_ls = { 0x2080, 5, 4, 0, 1 },
+ }
+ },
+ .chg_det = {
+ .cp_det = { 0x2080, 8, 8, 0, 1 },
+ .dcp_det = { 0x2080, 8, 8, 0, 1 },
+ .dp_det = { 0x2080, 9, 9, 1, 0 },
+ .idm_sink_en = { 0x2010, 5, 5, 1, 0 },
+ .idp_sink_en = { 0x2010, 5, 5, 0, 1 },
+ .idp_src_en = { 0x2010, 14, 14, 0, 1 },
+ .rdm_pdwn_en = { 0x2010, 14, 14, 0, 1 },
+ .vdm_src_en = { 0x2010, 7, 6, 0, 3 },
+ .vdp_src_en = { 0x2010, 7, 6, 0, 3 },
+ },
+ },
+ { /* sentinel */ }
+};
+
static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = {
{
.reg = 0x0000,
@@ -2094,6 +2211,7 @@ static const struct of_device_id rockchip_usb2phy_dt_match[] = {
{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
{ .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
+ { .compatible = "rockchip,rk3576-usb2phy", .data = &rk3576_phy_cfgs },
{ .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs },
{ .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
{}
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 9f084697dd05..ceab9c71d3b5 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -256,13 +256,10 @@ struct ropll_config {
};
enum rk_hdptx_reset {
- RST_PHY = 0,
- RST_APB,
+ RST_APB = 0,
RST_INIT,
RST_CMN,
RST_LANE,
- RST_ROPLL,
- RST_LCPLL,
RST_MAX
};
@@ -665,11 +662,6 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
{
u32 val;
- /* reset phy and apb, or phy locked flag may keep 1 */
- reset_control_assert(hdptx->rsts[RST_PHY].rstc);
- usleep_range(20, 30);
- reset_control_deassert(hdptx->rsts[RST_PHY].rstc);
-
reset_control_assert(hdptx->rsts[RST_APB].rstc);
usleep_range(20, 30);
reset_control_deassert(hdptx->rsts[RST_APB].rstc);
@@ -792,10 +784,6 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
rk_hdptx_pre_power_up(hdptx);
- reset_control_assert(hdptx->rsts[RST_ROPLL].rstc);
- usleep_range(20, 30);
- reset_control_deassert(hdptx->rsts[RST_ROPLL].rstc);
-
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_cmn_init_seq);
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_cmn_init_seq);
@@ -1098,13 +1086,10 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(hdptx->regmap),
"Failed to init regmap\n");
- hdptx->rsts[RST_PHY].id = "phy";
hdptx->rsts[RST_APB].id = "apb";
hdptx->rsts[RST_INIT].id = "init";
hdptx->rsts[RST_CMN].id = "cmn";
hdptx->rsts[RST_LANE].id = "lane";
- hdptx->rsts[RST_ROPLL].id = "ropll";
- hdptx->rsts[RST_LCPLL].id = "lcpll";
ret = devm_reset_control_bulk_get_exclusive(dev, RST_MAX, hdptx->rsts);
if (ret)
diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
index 4efcb78b0ab1..122ae0fdc785 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -1210,7 +1210,7 @@ MODULE_DEVICE_TABLE(of, rockchip_typec_phy_dt_ids);
static struct platform_driver rockchip_typec_phy_driver = {
.probe = rockchip_typec_phy_probe,
- .remove_new = rockchip_typec_phy_remove,
+ .remove = rockchip_typec_phy_remove,
.driver = {
.name = "rockchip-typec-phy",
.of_match_table = rockchip_typec_phy_dt_ids,
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 2c51e5c62d3e..5b1e8a3806ed 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -1538,6 +1538,43 @@ static const char * const rk_udphy_rst_list[] = {
"init", "cmn", "lane", "pcs_apb", "pma_apb"
};
+static const struct rk_udphy_cfg rk3576_udphy_cfgs = {
+ .num_phys = 1,
+ .phy_ids = { 0x2b010000 },
+ .num_rsts = ARRAY_SIZE(rk_udphy_rst_list),
+ .rst_list = rk_udphy_rst_list,
+ .grfcfg = {
+ /* u2phy-grf */
+ .bvalid_phy_con = RK_UDPHY_GEN_GRF_REG(0x0010, 1, 0, 0x2, 0x3),
+ .bvalid_grf_con = RK_UDPHY_GEN_GRF_REG(0x0000, 15, 14, 0x1, 0x3),
+
+ /* usb-grf */
+ .usb3otg0_cfg = RK_UDPHY_GEN_GRF_REG(0x0030, 15, 0, 0x1100, 0x0188),
+
+ /* usbdpphy-grf */
+ .low_pwrn = RK_UDPHY_GEN_GRF_REG(0x0004, 13, 13, 0, 1),
+ .rx_lfps = RK_UDPHY_GEN_GRF_REG(0x0004, 14, 14, 0, 1),
+ },
+ .vogrfcfg = {
+ {
+ .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0000, 11, 10, 1, 3),
+ .dp_lane_reg = 0x0000,
+ },
+ },
+ .dp_tx_ctrl_cfg = {
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_hbr2,
+ rk3588_dp_tx_drv_ctrl_hbr3,
+ },
+ .dp_tx_ctrl_cfg_typec = {
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_hbr2,
+ rk3588_dp_tx_drv_ctrl_hbr3,
+ },
+};
+
static const struct rk_udphy_cfg rk3588_udphy_cfgs = {
.num_phys = 2,
.phy_ids = {
@@ -1585,6 +1622,10 @@ static const struct rk_udphy_cfg rk3588_udphy_cfgs = {
static const struct of_device_id rk_udphy_dt_match[] = {
{
+ .compatible = "rockchip,rk3576-usbdp-phy",
+ .data = &rk3576_udphy_cfgs
+ },
+ {
.compatible = "rockchip,rk3588-usbdp-phy",
.data = &rk3588_udphy_cfgs
},
diff --git a/drivers/phy/st/Kconfig b/drivers/phy/st/Kconfig
index 3fc3d0781fb8..304614b6dabf 100644
--- a/drivers/phy/st/Kconfig
+++ b/drivers/phy/st/Kconfig
@@ -33,6 +33,17 @@ config PHY_STIH407_USB
Enable this support to enable the picoPHY device used by USB2
and USB3 controllers on STMicroelectronics STiH407 SoC families.
+config PHY_STM32_COMBOPHY
+ tristate "STMicroelectronics COMBOPHY driver for STM32MP25"
+ depends on ARCH_STM32 || COMPILE_TEST
+ select GENERIC_PHY
+ help
+ Enable this to support the COMBOPHY device used by USB3 or PCIe
+ controllers on STMicroelectronics STM32MP25 SoC.
+ This driver controls the COMBOPHY block to generate the PCIe 100Mhz
+ reference clock from either the external clock generator or HSE
+ internal SoC clock source.
+
config PHY_STM32_USBPHYC
tristate "STMicroelectronics STM32 USB HS PHY Controller driver"
depends on ARCH_STM32 || COMPILE_TEST
diff --git a/drivers/phy/st/Makefile b/drivers/phy/st/Makefile
index c862dd937b64..cb80e954ea9f 100644
--- a/drivers/phy/st/Makefile
+++ b/drivers/phy/st/Makefile
@@ -3,4 +3,5 @@ obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o
obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o
obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o
obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o
+obj-$(CONFIG_PHY_STM32_COMBOPHY) += phy-stm32-combophy.o
obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
diff --git a/drivers/phy/st/phy-stm32-combophy.c b/drivers/phy/st/phy-stm32-combophy.c
new file mode 100644
index 000000000000..765bb34fe358
--- /dev/null
+++ b/drivers/phy/st/phy-stm32-combophy.c
@@ -0,0 +1,598 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * STMicroelectronics COMBOPHY STM32MP25 Controller driver.
+ *
+ * Copyright (C) 2024 STMicroelectronics
+ * Author: Christian Bruel <christian.bruel@foss.st.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <dt-bindings/phy/phy.h>
+
+#define SYSCFG_COMBOPHY_CR1 0x4c00
+#define SYSCFG_COMBOPHY_CR2 0x4c04
+#define SYSCFG_COMBOPHY_CR4 0x4c0c
+#define SYSCFG_COMBOPHY_CR5 0x4c10
+#define SYSCFG_COMBOPHY_SR 0x4c14
+#define SYSCFG_PCIEPRGCR 0x6080
+
+/* SYSCFG PCIEPRGCR */
+#define STM32MP25_PCIEPRGCR_EN BIT(0)
+#define STM32MP25_PCIEPRG_IMPCTRL_OHM GENMASK(3, 1)
+#define STM32MP25_PCIEPRG_IMPCTRL_VSWING GENMASK(5, 4)
+
+/* SYSCFG SYSCFG_COMBOPHY_SR */
+#define STM32MP25_PIPE0_PHYSTATUS BIT(1)
+
+/* SYSCFG CR1 */
+#define SYSCFG_COMBOPHY_CR1_REFUSEPAD BIT(0)
+#define SYSCFG_COMBOPHY_CR1_MPLLMULT GENMASK(7, 1)
+#define SYSCFG_COMBOPHY_CR1_REFCLKSEL GENMASK(16, 8)
+#define SYSCFG_COMBOPHY_CR1_REFCLKDIV2 BIT(17)
+#define SYSCFG_COMBOPHY_CR1_REFSSPEN BIT(18)
+#define SYSCFG_COMBOPHY_CR1_SSCEN BIT(19)
+
+/* SYSCFG CR4 */
+#define SYSCFG_COMBOPHY_CR4_RX0_EQ GENMASK(2, 0)
+
+#define MPLLMULT_19_2 (0x02u << 1)
+#define MPLLMULT_20 (0x7du << 1)
+#define MPLLMULT_24 (0x68u << 1)
+#define MPLLMULT_25 (0x64u << 1)
+#define MPLLMULT_26 (0x60u << 1)
+#define MPLLMULT_38_4 (0x41u << 1)
+#define MPLLMULT_48 (0x6cu << 1)
+#define MPLLMULT_50 (0x32u << 1)
+#define MPLLMULT_52 (0x30u << 1)
+#define MPLLMULT_100 (0x19u << 1)
+
+#define REFCLKSEL_0 0
+#define REFCLKSEL_1 (0x108u << 8)
+
+#define REFCLDIV_0 0
+
+/* SYSCFG CR2 */
+#define SYSCFG_COMBOPHY_CR2_MODESEL GENMASK(1, 0)
+#define SYSCFG_COMBOPHY_CR2_ISO_DIS BIT(15)
+
+#define COMBOPHY_MODESEL_PCIE 0
+#define COMBOPHY_MODESEL_USB 3
+
+/* SYSCFG CR5 */
+#define SYSCFG_COMBOPHY_CR5_COMMON_CLOCKS BIT(12)
+
+#define COMBOPHY_SUP_ANA_MPLL_LOOP_CTL 0xc0
+#define COMBOPHY_PROP_CNTRL GENMASK(7, 4)
+
+/* Required apb/ker clocks first, optional pad last. */
+static const char * const combophy_clks[] = {"apb", "ker", "pad"};
+#define APB_CLK 0
+#define KER_CLK 1
+#define PAD_CLK 2
+
+struct stm32_combophy {
+ struct phy *phy;
+ struct regmap *regmap;
+ struct device *dev;
+ void __iomem *base;
+ struct reset_control *phy_reset;
+ struct clk_bulk_data clks[ARRAY_SIZE(combophy_clks)];
+ int num_clks;
+ bool have_pad_clk;
+ unsigned int type;
+ bool is_init;
+ int irq_wakeup;
+};
+
+struct clk_impedance {
+ u32 microohm;
+ u32 vswing[4];
+};
+
+/*
+ * lookup table to hold the settings needed for a ref clock frequency
+ * impedance, the offset is used to set the IMP_CTL and DE_EMP bit of the
+ * PRG_IMP_CTRL register. Use ordered discrete values in the table
+ */
+static const struct clk_impedance imp_lookup[] = {
+ { 6090000, { 442000, 564000, 684000, 802000 } },
+ { 5662000, { 528000, 621000, 712000, 803000 } },
+ { 5292000, { 491000, 596000, 700000, 802000 } },
+ { 4968000, { 558000, 640000, 722000, 803000 } },
+ { 4684000, { 468000, 581000, 692000, 802000 } },
+ { 4429000, { 554000, 613000, 717000, 803000 } },
+ { 4204000, { 511000, 609000, 706000, 802000 } },
+ { 3999000, { 571000, 648000, 726000, 803000 } }
+};
+
+static int stm32_impedance_tune(struct stm32_combophy *combophy)
+{
+ u8 imp_size = ARRAY_SIZE(imp_lookup);
+ u8 vswing_size = ARRAY_SIZE(imp_lookup[0].vswing);
+ u8 imp_of, vswing_of;
+ u32 max_imp = imp_lookup[0].microohm;
+ u32 min_imp = imp_lookup[imp_size - 1].microohm;
+ u32 max_vswing = imp_lookup[imp_size - 1].vswing[vswing_size - 1];
+ u32 min_vswing = imp_lookup[0].vswing[0];
+ u32 val;
+
+ if (!of_property_read_u32(combophy->dev->of_node, "st,output-micro-ohms", &val)) {
+ if (val < min_imp || val > max_imp) {
+ dev_err(combophy->dev, "Invalid value %u for output ohm\n", val);
+ return -EINVAL;
+ }
+
+ for (imp_of = 0; imp_of < ARRAY_SIZE(imp_lookup); imp_of++)
+ if (imp_lookup[imp_of].microohm <= val)
+ break;
+
+ dev_dbg(combophy->dev, "Set %u micro-ohms output impedance\n",
+ imp_lookup[imp_of].microohm);
+
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRG_IMPCTRL_OHM,
+ FIELD_PREP(STM32MP25_PCIEPRG_IMPCTRL_OHM, imp_of));
+ } else {
+ regmap_read(combophy->regmap, SYSCFG_PCIEPRGCR, &val);
+ imp_of = FIELD_GET(STM32MP25_PCIEPRG_IMPCTRL_OHM, val);
+ }
+
+ if (!of_property_read_u32(combophy->dev->of_node, "st,output-vswing-microvolt", &val)) {
+ if (val < min_vswing || val > max_vswing) {
+ dev_err(combophy->dev, "Invalid value %u for output vswing\n", val);
+ return -EINVAL;
+ }
+
+ for (vswing_of = 0; vswing_of < ARRAY_SIZE(imp_lookup[imp_of].vswing); vswing_of++)
+ if (imp_lookup[imp_of].vswing[vswing_of] >= val)
+ break;
+
+ dev_dbg(combophy->dev, "Set %u microvolt swing\n",
+ imp_lookup[imp_of].vswing[vswing_of]);
+
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRG_IMPCTRL_VSWING,
+ FIELD_PREP(STM32MP25_PCIEPRG_IMPCTRL_VSWING, vswing_of));
+ }
+
+ return 0;
+}
+
+static int stm32_combophy_pll_init(struct stm32_combophy *combophy)
+{
+ int ret;
+ u32 refclksel, pllmult, propcntrl, val;
+ u32 clk_rate;
+ struct clk *clk;
+ u32 cr1_val = 0, cr1_mask = 0;
+
+ if (combophy->have_pad_clk)
+ clk = combophy->clks[PAD_CLK].clk;
+ else
+ clk = combophy->clks[KER_CLK].clk;
+
+ clk_rate = clk_get_rate(clk);
+
+ dev_dbg(combophy->dev, "%s pll init rate %d\n",
+ combophy->have_pad_clk ? "External" : "Ker", clk_rate);
+
+ if (combophy->type != PHY_TYPE_PCIE) {
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_REFSSPEN;
+ cr1_val |= SYSCFG_COMBOPHY_CR1_REFSSPEN;
+ }
+
+ if (of_property_present(combophy->dev->of_node, "st,ssc-on")) {
+ dev_dbg(combophy->dev, "Enabling clock with SSC\n");
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_SSCEN;
+ cr1_val |= SYSCFG_COMBOPHY_CR1_SSCEN;
+ }
+
+ switch (clk_rate) {
+ case 100000000:
+ pllmult = MPLLMULT_100;
+ refclksel = REFCLKSEL_0;
+ propcntrl = 0x8u << 4;
+ break;
+ case 19200000:
+ pllmult = MPLLMULT_19_2;
+ refclksel = REFCLKSEL_1;
+ propcntrl = 0x8u << 4;
+ break;
+ case 25000000:
+ pllmult = MPLLMULT_25;
+ refclksel = REFCLKSEL_0;
+ propcntrl = 0xeu << 4;
+ break;
+ case 24000000:
+ pllmult = MPLLMULT_24;
+ refclksel = REFCLKSEL_1;
+ propcntrl = 0xeu << 4;
+ break;
+ case 20000000:
+ pllmult = MPLLMULT_20;
+ refclksel = REFCLKSEL_0;
+ propcntrl = 0xeu << 4;
+ break;
+ default:
+ dev_err(combophy->dev, "Invalid rate 0x%x\n", clk_rate);
+ return -EINVAL;
+ }
+
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_REFCLKDIV2;
+ cr1_val |= REFCLDIV_0;
+
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_REFCLKSEL;
+ cr1_val |= refclksel;
+
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_MPLLMULT;
+ cr1_val |= pllmult;
+
+ /*
+ * vddcombophy is interconnected with vddcore. Isolation bit should be unset
+ * before using the ComboPHY.
+ */
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
+ SYSCFG_COMBOPHY_CR2_ISO_DIS, SYSCFG_COMBOPHY_CR2_ISO_DIS);
+
+ reset_control_assert(combophy->phy_reset);
+
+ if (combophy->type == PHY_TYPE_PCIE) {
+ ret = stm32_impedance_tune(combophy);
+ if (ret)
+ goto out_iso;
+
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_REFUSEPAD;
+ cr1_val |= combophy->have_pad_clk ? SYSCFG_COMBOPHY_CR1_REFUSEPAD : 0;
+ }
+
+ if (!of_property_read_u32(combophy->dev->of_node, "st,rx-equalizer", &val)) {
+ dev_dbg(combophy->dev, "Set RX equalizer %u\n", val);
+ if (val > SYSCFG_COMBOPHY_CR4_RX0_EQ) {
+ dev_err(combophy->dev, "Invalid value %u for rx0 equalizer\n", val);
+ ret = -EINVAL;
+ goto out_iso;
+ }
+
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR4,
+ SYSCFG_COMBOPHY_CR4_RX0_EQ, val);
+ }
+
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1, cr1_mask, cr1_val);
+
+ /*
+ * Force elasticity buffer to be tuned for the reference clock as
+ * the separated clock model is not supported
+ */
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR5,
+ SYSCFG_COMBOPHY_CR5_COMMON_CLOCKS, SYSCFG_COMBOPHY_CR5_COMMON_CLOCKS);
+
+ reset_control_deassert(combophy->phy_reset);
+
+ ret = regmap_read_poll_timeout(combophy->regmap, SYSCFG_COMBOPHY_SR, val,
+ !(val & STM32MP25_PIPE0_PHYSTATUS),
+ 10, 1000);
+ if (ret) {
+ dev_err(combophy->dev, "timeout, cannot lock PLL\n");
+ if (combophy->type == PHY_TYPE_PCIE && !combophy->have_pad_clk)
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRGCR_EN, 0);
+
+ if (combophy->type != PHY_TYPE_PCIE)
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1,
+ SYSCFG_COMBOPHY_CR1_REFSSPEN, 0);
+
+ goto out;
+ }
+
+
+ if (combophy->type == PHY_TYPE_PCIE) {
+ if (!combophy->have_pad_clk)
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRGCR_EN, STM32MP25_PCIEPRGCR_EN);
+
+ val = readl_relaxed(combophy->base + COMBOPHY_SUP_ANA_MPLL_LOOP_CTL);
+ val &= ~COMBOPHY_PROP_CNTRL;
+ val |= propcntrl;
+ writel_relaxed(val, combophy->base + COMBOPHY_SUP_ANA_MPLL_LOOP_CTL);
+ }
+
+ return 0;
+
+out_iso:
+ reset_control_deassert(combophy->phy_reset);
+
+out:
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
+ SYSCFG_COMBOPHY_CR2_ISO_DIS, 0);
+
+ return ret;
+}
+
+static struct phy *stm32_combophy_xlate(struct device *dev,
+ const struct of_phandle_args *args)
+{
+ struct stm32_combophy *combophy = dev_get_drvdata(dev);
+ unsigned int type;
+
+ if (args->args_count != 1) {
+ dev_err(dev, "invalid number of cells in 'phy' property\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ type = args->args[0];
+ if (type != PHY_TYPE_USB3 && type != PHY_TYPE_PCIE) {
+ dev_err(dev, "unsupported device type: %d\n", type);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (combophy->have_pad_clk && type != PHY_TYPE_PCIE) {
+ dev_err(dev, "Invalid use of clk_pad for USB3 mode\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ combophy->type = type;
+
+ return combophy->phy;
+}
+
+static int stm32_combophy_set_mode(struct stm32_combophy *combophy)
+{
+ int type = combophy->type;
+ u32 val;
+
+ switch (type) {
+ case PHY_TYPE_PCIE:
+ dev_dbg(combophy->dev, "setting PCIe ComboPHY\n");
+ val = COMBOPHY_MODESEL_PCIE;
+ break;
+ case PHY_TYPE_USB3:
+ dev_dbg(combophy->dev, "setting USB3 ComboPHY\n");
+ val = COMBOPHY_MODESEL_USB;
+ break;
+ default:
+ dev_err(combophy->dev, "Invalid PHY mode %d\n", type);
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
+ SYSCFG_COMBOPHY_CR2_MODESEL, val);
+}
+
+static int stm32_combophy_suspend_noirq(struct device *dev)
+{
+ struct stm32_combophy *combophy = dev_get_drvdata(dev);
+
+ /*
+ * Clocks should be turned off since it is not needed for
+ * wakeup capability. In case usb-remote wakeup is not enabled,
+ * combo-phy is already turned off by HCD driver using exit callback
+ */
+ if (combophy->is_init) {
+ clk_bulk_disable_unprepare(combophy->num_clks, combophy->clks);
+
+ /* since wakeup is enabled for ctrl */
+ enable_irq_wake(combophy->irq_wakeup);
+ }
+
+ return 0;
+}
+
+static int stm32_combophy_resume_noirq(struct device *dev)
+{
+ struct stm32_combophy *combophy = dev_get_drvdata(dev);
+ int ret;
+
+ /*
+ * If clocks was turned off by suspend call for wakeup then needs
+ * to be turned back ON in resume. In case usb-remote wakeup is not
+ * enabled, clocks already turned ON by HCD driver using init callback
+ */
+ if (combophy->is_init) {
+ /* since wakeup was enabled for ctrl */
+ disable_irq_wake(combophy->irq_wakeup);
+
+ ret = clk_bulk_prepare_enable(combophy->num_clks, combophy->clks);
+ if (ret) {
+ dev_err(dev, "can't enable clocks (%d)\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int stm32_combophy_exit(struct phy *phy)
+{
+ struct stm32_combophy *combophy = phy_get_drvdata(phy);
+ struct device *dev = combophy->dev;
+
+ combophy->is_init = false;
+
+ if (combophy->type == PHY_TYPE_PCIE && !combophy->have_pad_clk)
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRGCR_EN, 0);
+
+ if (combophy->type != PHY_TYPE_PCIE)
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1,
+ SYSCFG_COMBOPHY_CR1_REFSSPEN, 0);
+
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
+ SYSCFG_COMBOPHY_CR2_ISO_DIS, 0);
+
+ clk_bulk_disable_unprepare(combophy->num_clks, combophy->clks);
+
+ pm_runtime_put_noidle(dev);
+
+ return 0;
+}
+
+static int stm32_combophy_init(struct phy *phy)
+{
+ struct stm32_combophy *combophy = phy_get_drvdata(phy);
+ struct device *dev = combophy->dev;
+ int ret;
+
+ pm_runtime_get_noresume(dev);
+
+ ret = clk_bulk_prepare_enable(combophy->num_clks, combophy->clks);
+ if (ret) {
+ dev_err(dev, "can't enable clocks (%d)\n", ret);
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ ret = stm32_combophy_set_mode(combophy);
+ if (ret) {
+ dev_err(dev, "combophy mode not set\n");
+ clk_bulk_disable_unprepare(combophy->num_clks, combophy->clks);
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ ret = stm32_combophy_pll_init(combophy);
+ if (ret) {
+ clk_bulk_disable_unprepare(combophy->num_clks, combophy->clks);
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ combophy->is_init = true;
+
+ return ret;
+}
+
+static const struct phy_ops stm32_combophy_phy_data = {
+ .init = stm32_combophy_init,
+ .exit = stm32_combophy_exit,
+ .owner = THIS_MODULE
+};
+
+static irqreturn_t stm32_combophy_irq_wakeup_handler(int irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+
+static int stm32_combophy_get_clocks(struct stm32_combophy *combophy)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(combophy_clks); i++)
+ combophy->clks[i].id = combophy_clks[i];
+
+ combophy->num_clks = ARRAY_SIZE(combophy_clks) - 1;
+
+ ret = devm_clk_bulk_get(combophy->dev, combophy->num_clks, combophy->clks);
+ if (ret)
+ return ret;
+
+ ret = devm_clk_bulk_get_optional(combophy->dev, 1, combophy->clks + combophy->num_clks);
+ if (ret)
+ return ret;
+
+ if (combophy->clks[combophy->num_clks].clk != NULL) {
+ combophy->have_pad_clk = true;
+ combophy->num_clks++;
+ }
+
+ return 0;
+}
+
+static int stm32_combophy_probe(struct platform_device *pdev)
+{
+ struct stm32_combophy *combophy;
+ struct device *dev = &pdev->dev;
+ struct phy_provider *phy_provider;
+ int ret, irq;
+
+ combophy = devm_kzalloc(dev, sizeof(*combophy), GFP_KERNEL);
+ if (!combophy)
+ return -ENOMEM;
+
+ combophy->dev = dev;
+
+ dev_set_drvdata(dev, combophy);
+
+ combophy->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(combophy->base))
+ return PTR_ERR(combophy->base);
+
+ ret = stm32_combophy_get_clocks(combophy);
+ if (ret)
+ return ret;
+
+ combophy->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
+ if (IS_ERR(combophy->phy_reset))
+ return dev_err_probe(dev, PTR_ERR(combophy->phy_reset),
+ "Failed to get PHY reset\n");
+
+ combophy->regmap = syscon_regmap_lookup_by_compatible("st,stm32mp25-syscfg");
+ if (IS_ERR(combophy->regmap))
+ return dev_err_probe(dev, PTR_ERR(combophy->regmap),
+ "No syscfg specified\n");
+
+ combophy->phy = devm_phy_create(dev, NULL, &stm32_combophy_phy_data);
+ if (IS_ERR(combophy->phy))
+ return dev_err_probe(dev, PTR_ERR(combophy->phy),
+ "failed to create PCIe/USB3 ComboPHY\n");
+
+ if (device_property_read_bool(dev, "wakeup-source")) {
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "failed to get IRQ\n");
+ combophy->irq_wakeup = irq;
+
+ ret = devm_request_threaded_irq(dev, combophy->irq_wakeup, NULL,
+ stm32_combophy_irq_wakeup_handler, IRQF_ONESHOT,
+ NULL, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret, "unable to request wake IRQ %d\n",
+ combophy->irq_wakeup);
+ }
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable pm runtime\n");
+
+ phy_set_drvdata(combophy->phy, combophy);
+
+ phy_provider = devm_of_phy_provider_register(dev, stm32_combophy_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct dev_pm_ops stm32_combophy_pm_ops = {
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_combophy_suspend_noirq,
+ stm32_combophy_resume_noirq)
+};
+
+static const struct of_device_id stm32_combophy_of_match[] = {
+ { .compatible = "st,stm32mp25-combophy", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, stm32_combophy_of_match);
+
+static struct platform_driver stm32_combophy_driver = {
+ .probe = stm32_combophy_probe,
+ .driver = {
+ .name = "stm32-combophy",
+ .of_match_table = stm32_combophy_of_match,
+ .pm = pm_sleep_ptr(&stm32_combophy_pm_ops)
+ }
+};
+
+module_platform_driver(stm32_combophy_driver);
+
+MODULE_AUTHOR("Christian Bruel <christian.bruel@foss.st.com>");
+MODULE_DESCRIPTION("STM32MP25 Combophy USB3/PCIe controller driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/st/phy-stm32-usbphyc.c b/drivers/phy/st/phy-stm32-usbphyc.c
index 9dbe60dcf319..b917cd413de7 100644
--- a/drivers/phy/st/phy-stm32-usbphyc.c
+++ b/drivers/phy/st/phy-stm32-usbphyc.c
@@ -812,7 +812,7 @@ MODULE_DEVICE_TABLE(of, stm32_usbphyc_of_match);
static struct platform_driver stm32_usbphyc_driver = {
.probe = stm32_usbphyc_probe,
- .remove_new = stm32_usbphyc_remove,
+ .remove = stm32_usbphyc_remove,
.driver = {
.of_match_table = stm32_usbphyc_of_match,
.name = "stm32-usbphyc",
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index 342f5ccf611d..79d4814d758d 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -543,7 +543,7 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
device_initialize(&port->dev);
port->dev.type = &tegra_xusb_port_type;
- port->dev.of_node = of_node_get(np);
+ device_set_node(&port->dev, of_fwnode_handle(of_node_get(np)));
port->dev.parent = padctl->dev;
err = dev_set_name(&port->dev, "%s-%u", name, index);
@@ -1327,7 +1327,7 @@ static struct platform_driver tegra_xusb_padctl_driver = {
.pm = &tegra_xusb_padctl_pm_ops,
},
.probe = tegra_xusb_padctl_probe,
- .remove_new = tegra_xusb_padctl_remove,
+ .remove = tegra_xusb_padctl_remove,
};
module_platform_driver(tegra_xusb_padctl_driver);
diff --git a/drivers/phy/ti/phy-am654-serdes.c b/drivers/phy/ti/phy-am654-serdes.c
index 3bf3aff4b1c7..431b223996e0 100644
--- a/drivers/phy/ti/phy-am654-serdes.c
+++ b/drivers/phy/ti/phy-am654-serdes.c
@@ -837,7 +837,7 @@ static void serdes_am654_remove(struct platform_device *pdev)
static struct platform_driver serdes_am654_driver = {
.probe = serdes_am654_probe,
- .remove_new = serdes_am654_remove,
+ .remove = serdes_am654_remove,
.driver = {
.name = "phy-am654",
.of_match_table = serdes_am654_id_table,
diff --git a/drivers/phy/ti/phy-da8xx-usb.c b/drivers/phy/ti/phy-da8xx-usb.c
index 68aa595b6ad8..1d81a1e6ec6b 100644
--- a/drivers/phy/ti/phy-da8xx-usb.c
+++ b/drivers/phy/ti/phy-da8xx-usb.c
@@ -277,11 +277,11 @@ MODULE_DEVICE_TABLE(of, da8xx_usb_phy_ids);
static struct platform_driver da8xx_usb_phy_driver = {
.probe = da8xx_usb_phy_probe,
- .remove_new = da8xx_usb_phy_remove,
+ .remove = da8xx_usb_phy_remove,
.driver = {
.name = "da8xx-usb-phy",
.pm = &da8xx_usb_phy_pm_ops,
- .of_match_table = da8xx_usb_phy_ids,
+ .of_match_table = da8xx_usb_phy_ids,
},
};
diff --git a/drivers/phy/ti/phy-dm816x-usb.c b/drivers/phy/ti/phy-dm816x-usb.c
index d5ae972a31fb..e8f842d4e841 100644
--- a/drivers/phy/ti/phy-dm816x-usb.c
+++ b/drivers/phy/ti/phy-dm816x-usb.c
@@ -259,7 +259,7 @@ static void dm816x_usb_phy_remove(struct platform_device *pdev)
static struct platform_driver dm816x_usb_phy_driver = {
.probe = dm816x_usb_phy_probe,
- .remove_new = dm816x_usb_phy_remove,
+ .remove = dm816x_usb_phy_remove,
.driver = {
.name = "dm816x-usb-phy",
.pm = &dm816x_usb_phy_pm_ops,
diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c
index 103b266fec77..e0ca59ae3153 100644
--- a/drivers/phy/ti/phy-gmii-sel.c
+++ b/drivers/phy/ti/phy-gmii-sel.c
@@ -230,7 +230,8 @@ static const
struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = {
.use_of_data = true,
.regfields = phy_gmii_sel_fields_am654,
- .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII),
+ .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) |
+ BIT(PHY_INTERFACE_MODE_USXGMII),
.num_ports = 4,
.num_qsgmii_main_ports = 1,
};
diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index c6e846d385d2..ab2a4f2c0a5b 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -1685,7 +1685,7 @@ static DEFINE_NOIRQ_DEV_PM_OPS(wiz_pm_ops, NULL, wiz_resume_noirq);
static struct platform_driver wiz_driver = {
.probe = wiz_probe,
- .remove_new = wiz_remove,
+ .remove = wiz_remove,
.driver = {
.name = "wiz",
.of_match_table = wiz_id_table,
diff --git a/drivers/phy/ti/phy-omap-usb2.c b/drivers/phy/ti/phy-omap-usb2.c
index 78e19b128962..c1a0ef979142 100644
--- a/drivers/phy/ti/phy-omap-usb2.c
+++ b/drivers/phy/ti/phy-omap-usb2.c
@@ -511,7 +511,7 @@ static void omap_usb2_remove(struct platform_device *pdev)
static struct platform_driver omap_usb2_driver = {
.probe = omap_usb2_probe,
- .remove_new = omap_usb2_remove,
+ .remove = omap_usb2_remove,
.driver = {
.name = "omap-usb2",
.of_match_table = omap_usb2_id_table,
diff --git a/drivers/phy/ti/phy-ti-pipe3.c b/drivers/phy/ti/phy-ti-pipe3.c
index 874c1a25ce36..da2cbacb982c 100644
--- a/drivers/phy/ti/phy-ti-pipe3.c
+++ b/drivers/phy/ti/phy-ti-pipe3.c
@@ -920,7 +920,7 @@ MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
static struct platform_driver ti_pipe3_driver = {
.probe = ti_pipe3_probe,
- .remove_new = ti_pipe3_remove,
+ .remove = ti_pipe3_remove,
.driver = {
.name = "ti-pipe3",
.of_match_table = ti_pipe3_id_table,
diff --git a/drivers/phy/ti/phy-twl4030-usb.c b/drivers/phy/ti/phy-twl4030-usb.c
index 6b265992d988..6f12b38cd894 100644
--- a/drivers/phy/ti/phy-twl4030-usb.c
+++ b/drivers/phy/ti/phy-twl4030-usb.c
@@ -834,7 +834,7 @@ MODULE_DEVICE_TABLE(of, twl4030_usb_id_table);
static struct platform_driver twl4030_usb_driver = {
.probe = twl4030_usb_probe,
- .remove_new = twl4030_usb_remove,
+ .remove = twl4030_usb_remove,
.driver = {
.name = "twl4030_usb",
.pm = &twl4030_usb_pm_ops,
diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c
index e6579002f114..05a4a59f7c40 100644
--- a/drivers/phy/xilinx/phy-zynqmp.c
+++ b/drivers/phy/xilinx/phy-zynqmp.c
@@ -1071,7 +1071,7 @@ MODULE_DEVICE_TABLE(of, xpsgtr_of_match);
static struct platform_driver xpsgtr_driver = {
.probe = xpsgtr_probe,
- .remove_new = xpsgtr_remove,
+ .remove = xpsgtr_remove,
.driver = {
.name = "xilinx-psgtr",
.of_match_table = xpsgtr_of_match,
diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
index fd5ce52d05b1..c9a3d3aa8c10 100644
--- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
+++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
@@ -309,7 +309,7 @@ static void iproc_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct iproc_gpio *chip = gpiochip_get_data(gc);
- seq_printf(p, dev_name(chip->dev));
+ seq_puts(p, dev_name(chip->dev));
}
static const struct irq_chip iproc_gpio_irq_chip = {
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index 4c4ada06423d..335744ac8310 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -734,7 +734,7 @@ static void armada_37xx_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
struct armada_37xx_pinctrl *info = gpiochip_get_data(chip);
- seq_printf(p, info->data->name);
+ seq_puts(p, info->data->name);
}
static const struct irq_chip armada_37xx_irqchip = {
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
index 737d0ae3d0b6..d66c3a3e8429 100644
--- a/drivers/pinctrl/pinctrl-mcp23s08.c
+++ b/drivers/pinctrl/pinctrl-mcp23s08.c
@@ -569,7 +569,7 @@ static void mcp23s08_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct mcp23s08 *mcp = gpiochip_get_data(gc);
- seq_printf(p, dev_name(mcp->dev));
+ seq_puts(p, dev_name(mcp->dev));
}
static const struct irq_chip mcp23s08_irq_chip = {
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
index bfeb2edbeec5..521f6fef0b9f 100644
--- a/drivers/pinctrl/pinctrl-stmfx.c
+++ b/drivers/pinctrl/pinctrl-stmfx.c
@@ -599,7 +599,7 @@ static void stmfx_pinctrl_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(d);
struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip);
- seq_printf(p, dev_name(pctl->dev));
+ seq_puts(p, dev_name(pctl->dev));
}
static const struct irq_chip stmfx_pinctrl_irq_chip = {
diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c
index ab87de319ad8..98262b8ce43a 100644
--- a/drivers/pinctrl/pinctrl-sx150x.c
+++ b/drivers/pinctrl/pinctrl-sx150x.c
@@ -584,7 +584,7 @@ static void sx150x_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct sx150x_pinctrl *pctl = gpiochip_get_data(gc);
- seq_printf(p, pctl->client->name);
+ seq_puts(p, pctl->client->name);
}
static const struct irq_chip sx150x_irq_chip = {
diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
index 8ffb9430a134..1df9cec2873f 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
+++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
@@ -2332,7 +2332,7 @@ static void rzg2l_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static int rzg2l_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c
index c2aab0cfab33..ca78e5833136 100644
--- a/drivers/platform/goldfish/goldfish_pipe.c
+++ b/drivers/platform/goldfish/goldfish_pipe.c
@@ -61,7 +61,6 @@
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/mm.h>
-#include <linux/acpi.h>
#include <linux/bug.h>
#include "goldfish_pipe_qemu.h"
@@ -940,7 +939,7 @@ static struct platform_driver goldfish_pipe_driver = {
.driver = {
.name = "goldfish_pipe",
.of_match_table = goldfish_pipe_of_match,
- .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match),
+ .acpi_match_table = goldfish_pipe_acpi_match,
}
};
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 4aa4d66f491a..dd5b5773328a 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -236,7 +236,7 @@ static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj
}
static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
- struct bin_attribute *battr, int id)
+ const struct bin_attribute *battr, int id)
{
if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6)
return battr->attr.mode;
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index f8e74c0392ba..748bbc356484 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -75,7 +75,7 @@ static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj
}
static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
- struct bin_attribute *battr, int id)
+ const struct bin_attribute *battr, int id)
{
u16 sock_ind;
diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index 375695cc0d60..3c53cab03327 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -105,7 +105,7 @@ intel_pmt_read(struct file *filp, struct kobject *kobj,
static int
intel_pmt_mmap(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, struct vm_area_struct *vma)
+ const struct bin_attribute *attr, struct vm_area_struct *vma)
{
struct intel_pmt_entry *entry = container_of(attr,
struct intel_pmt_entry,
diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
index 9d137621f0e6..33f33b1070fd 100644
--- a/drivers/platform/x86/intel/sdsi.c
+++ b/drivers/platform/x86/intel/sdsi.c
@@ -541,7 +541,7 @@ static struct bin_attribute *sdsi_bin_attrs[] = {
};
static umode_t
-sdsi_battr_is_visible(struct kobject *kobj, struct bin_attribute *attr, int n)
+sdsi_battr_is_visible(struct kobject *kobj, const struct bin_attribute *attr, int n)
{
struct device *dev = kobj_to_dev(kobj);
struct sdsi_priv *priv = dev_get_drvdata(dev);
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 389d5a193e5d..f5fc33a8bf44 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -79,6 +79,7 @@ config POWER_RESET_EP93XX
bool "Cirrus EP93XX reset driver" if COMPILE_TEST
depends on MFD_SYSCON
default ARCH_EP93XX
+ select AUXILIARY_BUS
help
This driver provides restart support for Cirrus EP93XX SoC.
diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c
index 93eece027865..7bc779055cf3 100644
--- a/drivers/power/reset/at91-poweroff.c
+++ b/drivers/power/reset/at91-poweroff.c
@@ -223,7 +223,7 @@ MODULE_DEVICE_TABLE(of, at91_poweroff_of_match);
static struct platform_driver at91_poweroff_driver = {
.probe = at91_poweroff_probe,
- .remove_new = at91_poweroff_remove,
+ .remove = at91_poweroff_remove,
.driver = {
.name = "at91-poweroff",
.of_match_table = at91_poweroff_of_match,
diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c
index 16512654295f..036b18a1f90f 100644
--- a/drivers/power/reset/at91-reset.c
+++ b/drivers/power/reset/at91-reset.c
@@ -427,7 +427,7 @@ static void at91_reset_remove(struct platform_device *pdev)
static struct platform_driver at91_reset_driver = {
.probe = at91_reset_probe,
- .remove_new = at91_reset_remove,
+ .remove = at91_reset_remove,
.driver = {
.name = "at91-reset",
.of_match_table = at91_reset_of_match,
diff --git a/drivers/power/reset/at91-sama5d2_shdwc.c b/drivers/power/reset/at91-sama5d2_shdwc.c
index 959ce0dbe91d..edb0df86aff4 100644
--- a/drivers/power/reset/at91-sama5d2_shdwc.c
+++ b/drivers/power/reset/at91-sama5d2_shdwc.c
@@ -441,7 +441,7 @@ static void at91_shdwc_remove(struct platform_device *pdev)
static struct platform_driver at91_shdwc_driver = {
.probe = at91_shdwc_probe,
- .remove_new = at91_shdwc_remove,
+ .remove = at91_shdwc_remove,
.driver = {
.name = "at91-shdwc",
.of_match_table = at91_shdwc_of_match,
diff --git a/drivers/power/reset/keystone-reset.c b/drivers/power/reset/keystone-reset.c
index dbc4ff61cd74..cfaa54ced0d0 100644
--- a/drivers/power/reset/keystone-reset.c
+++ b/drivers/power/reset/keystone-reset.c
@@ -16,7 +16,6 @@
#include <linux/mfd/syscon.h>
#include <linux/of.h>
-#define RSTYPE_RG 0x0
#define RSCTRL_RG 0x4
#define RSCFG_RG 0x8
#define RSISO_RG 0xc
@@ -28,7 +27,6 @@
#define RSMUX_OMODE_MASK 0xe
#define RSMUX_OMODE_RESET_ON 0xa
#define RSMUX_OMODE_RESET_OFF 0x0
-#define RSMUX_LOCK_MASK 0x1
#define RSMUX_LOCK_SET 0x1
#define RSCFG_RSTYPE_SOFT 0x300f
diff --git a/drivers/power/reset/ltc2952-poweroff.c b/drivers/power/reset/ltc2952-poweroff.c
index fa25fbd53934..1a6fc8d38e20 100644
--- a/drivers/power/reset/ltc2952-poweroff.c
+++ b/drivers/power/reset/ltc2952-poweroff.c
@@ -305,7 +305,7 @@ MODULE_DEVICE_TABLE(of, of_ltc2952_poweroff_match);
static struct platform_driver ltc2952_poweroff_driver = {
.probe = ltc2952_poweroff_probe,
- .remove_new = ltc2952_poweroff_remove,
+ .remove = ltc2952_poweroff_remove,
.driver = {
.name = "ltc2952-poweroff",
.of_match_table = of_ltc2952_poweroff_match,
diff --git a/drivers/power/reset/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c
index e0f2ff6b147c..f7d8fc935d51 100644
--- a/drivers/power/reset/qnap-poweroff.c
+++ b/drivers/power/reset/qnap-poweroff.c
@@ -118,7 +118,7 @@ static void qnap_power_off_remove(struct platform_device *pdev)
static struct platform_driver qnap_power_off_driver = {
.probe = qnap_power_off_probe,
- .remove_new = qnap_power_off_remove,
+ .remove = qnap_power_off_remove,
.driver = {
.name = "qnap_power_off",
.of_match_table = of_match_ptr(qnap_power_off_of_match_table),
diff --git a/drivers/power/reset/syscon-reboot.c b/drivers/power/reset/syscon-reboot.c
index 4d622c19bc48..d623d77e657e 100644
--- a/drivers/power/reset/syscon-reboot.c
+++ b/drivers/power/reset/syscon-reboot.c
@@ -61,7 +61,8 @@ static int syscon_reboot_probe(struct platform_device *pdev)
priority = 192;
if (of_property_read_u32(pdev->dev.of_node, "offset", &ctx->offset))
- return -EINVAL;
+ if (of_property_read_u32(pdev->dev.of_node, "reg", &ctx->offset))
+ return -EINVAL;
value_err = of_property_read_u32(pdev->dev.of_node, "value", &ctx->value);
mask_err = of_property_read_u32(pdev->dev.of_node, "mask", &ctx->mask);
diff --git a/drivers/power/supply/88pm860x_battery.c b/drivers/power/supply/88pm860x_battery.c
index 34619c4d4ece..b7938fbb24a5 100644
--- a/drivers/power/supply/88pm860x_battery.c
+++ b/drivers/power/supply/88pm860x_battery.c
@@ -422,7 +422,7 @@ static irqreturn_t pm860x_batt_handler(int irq, void *data)
info->temp_type = PM860X_TEMP_TINT;
}
mutex_unlock(&info->lock);
- /* clear ccnt since battery is attached or dettached */
+ /* clear ccnt since battery is attached or detached */
clear_ccnt(info, &ccnt_data);
return IRQ_HANDLED;
}
@@ -566,7 +566,7 @@ static int measure_temp(struct pm860x_battery_info *info, int *data)
ret = measure_12bit_voltage(info, PM8607_GPADC1_MEAS1, data);
if (ret)
return ret;
- /* meausered Vtbat(mV) / Ibias_current(11uA)*/
+ /* measured Vtbat(mV) / Ibias_current(11uA)*/
*data = (*data * 1000) / GPBIAS2_GPADC1_UA;
if (*data > TBAT_NEG_25D) {
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index bcfa63fb9f1e..9f2eef6787f7 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -493,6 +493,16 @@ config CHARGER_TWL4030
help
Say Y here to enable support for TWL4030 Battery Charge Interface.
+config CHARGER_TWL6030
+ tristate "OMAP TWL6030 BCI charger driver"
+ depends on IIO && TWL4030_CORE
+ help
+ Say Y here to enable support for TWL6030/6032 Battery Charge
+ Interface.
+
+ This driver can be build as a module. If so, the module will be
+ called twl6030_charger.
+
config CHARGER_LP8727
tristate "TI/National Semiconductor LP8727 charger driver"
depends on I2C
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 8dcb41545317..59c4a9f40d28 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_CHARGER_CPCAP) += cpcap-charger.o
obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
+obj-$(CONFIG_CHARGER_TWL6030) += twl6030_charger.o
obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o
obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o
obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
diff --git a/drivers/power/supply/ab8500_bmdata.c b/drivers/power/supply/ab8500_bmdata.c
index 3e6ea22372b2..19ed52852804 100644
--- a/drivers/power/supply/ab8500_bmdata.c
+++ b/drivers/power/supply/ab8500_bmdata.c
@@ -16,7 +16,7 @@
/* Default: temperature hysteresis */
#define AB8500_TEMP_HYSTERESIS 3
-static struct power_supply_battery_ocv_table ocv_cap_tbl[] = {
+static const struct power_supply_battery_ocv_table ocv_cap_tbl[] = {
{ .ocv = 4186000, .capacity = 100},
{ .ocv = 4163000, .capacity = 99},
{ .ocv = 4114000, .capacity = 95},
@@ -48,7 +48,7 @@ static struct power_supply_battery_ocv_table ocv_cap_tbl[] = {
* temperature values to work. Factory resistance is 300 mOhm and the
* resistance values to the right are percentages of 300 mOhm.
*/
-static struct power_supply_resistance_temp_table temp_to_batres_tbl_thermistor[] = {
+static const struct power_supply_resistance_temp_table temp_to_batres_tbl_thermistor[] = {
{ .temp = 40, .resistance = 40 /* 120 mOhm */ },
{ .temp = 30, .resistance = 45 /* 135 mOhm */ },
{ .temp = 20, .resistance = 55 /* 165 mOhm */ },
diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c
index 56f136b2d071..37039e28fc4b 100644
--- a/drivers/power/supply/ab8500_btemp.c
+++ b/drivers/power/supply/ab8500_btemp.c
@@ -283,7 +283,7 @@ static void ab8500_btemp_periodic_work(struct work_struct *work)
dev_warn(di->dev, "failed to identify the battery\n");
}
- /* Failover if a reading is erroneous, use last meausurement */
+ /* Failover if a reading is erroneous, use last measurement */
ret = thermal_zone_get_temp(di->tz, &bat_temp);
if (ret) {
dev_err(di->dev, "error reading temperature\n");
@@ -818,7 +818,7 @@ MODULE_DEVICE_TABLE(of, ab8500_btemp_match);
struct platform_driver ab8500_btemp_driver = {
.probe = ab8500_btemp_probe,
- .remove_new = ab8500_btemp_remove,
+ .remove = ab8500_btemp_remove,
.driver = {
.name = "ab8500-btemp",
.of_match_table = ab8500_btemp_match,
diff --git a/drivers/power/supply/ab8500_chargalg.c b/drivers/power/supply/ab8500_chargalg.c
index 854491ad3ecd..14e1b448bd39 100644
--- a/drivers/power/supply/ab8500_chargalg.c
+++ b/drivers/power/supply/ab8500_chargalg.c
@@ -1837,7 +1837,7 @@ static const struct of_device_id ab8500_chargalg_match[] = {
struct platform_driver ab8500_chargalg_driver = {
.probe = ab8500_chargalg_probe,
- .remove_new = ab8500_chargalg_remove,
+ .remove = ab8500_chargalg_remove,
.driver = {
.name = "ab8500_chargalg",
.of_match_table = ab8500_chargalg_match,
diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c
index 93181ebfb324..cece8d6753ac 100644
--- a/drivers/power/supply/ab8500_charger.c
+++ b/drivers/power/supply/ab8500_charger.c
@@ -3711,7 +3711,7 @@ MODULE_DEVICE_TABLE(of, ab8500_charger_match);
static struct platform_driver ab8500_charger_driver = {
.probe = ab8500_charger_probe,
- .remove_new = ab8500_charger_remove,
+ .remove = ab8500_charger_remove,
.driver = {
.name = "ab8500-charger",
.of_match_table = ab8500_charger_match,
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index a71903b1bf78..78871a2143de 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -3242,7 +3242,7 @@ MODULE_DEVICE_TABLE(of, ab8500_fg_match);
struct platform_driver ab8500_fg_driver = {
.probe = ab8500_fg_probe,
- .remove_new = ab8500_fg_remove,
+ .remove = ab8500_fg_remove,
.driver = {
.name = "ab8500-fg",
.of_match_table = ab8500_fg_match,
diff --git a/drivers/power/supply/acer_a500_battery.c b/drivers/power/supply/acer_a500_battery.c
index ef5c419b1b7f..39d85b11a13c 100644
--- a/drivers/power/supply/acer_a500_battery.c
+++ b/drivers/power/supply/acer_a500_battery.c
@@ -233,14 +233,15 @@ static int a500_battery_probe(struct platform_device *pdev)
psy_cfg.of_node = pdev->dev.parent->of_node;
psy_cfg.drv_data = bat;
+ psy_cfg.no_wakeup_source = true;
bat->regmap = dev_get_regmap(pdev->dev.parent, "KB930");
if (!bat->regmap)
return -EINVAL;
- bat->psy = devm_power_supply_register_no_ws(&pdev->dev,
- &a500_battery_desc,
- &psy_cfg);
+ bat->psy = devm_power_supply_register(&pdev->dev,
+ &a500_battery_desc,
+ &psy_cfg);
if (IS_ERR(bat->psy))
return dev_err_probe(&pdev->dev, PTR_ERR(bat->psy),
"failed to register battery\n");
@@ -285,7 +286,7 @@ static struct platform_driver a500_battery_driver = {
.pm = &a500_battery_pm_ops,
},
.probe = a500_battery_probe,
- .remove_new = a500_battery_remove,
+ .remove = a500_battery_remove,
};
module_platform_driver(a500_battery_driver);
diff --git a/drivers/power/supply/act8945a_charger.c b/drivers/power/supply/act8945a_charger.c
index 51122bfbf196..b2b82f97a471 100644
--- a/drivers/power/supply/act8945a_charger.c
+++ b/drivers/power/supply/act8945a_charger.c
@@ -651,7 +651,7 @@ static struct platform_driver act8945a_charger_driver = {
.name = "act8945a-charger",
},
.probe = act8945a_charger_probe,
- .remove_new = act8945a_charger_remove,
+ .remove = act8945a_charger_remove,
};
module_platform_driver(act8945a_charger_driver);
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
index dac9875d993c..458fd3024373 100644
--- a/drivers/power/supply/adp5061.c
+++ b/drivers/power/supply/adp5061.c
@@ -590,7 +590,7 @@ static int adp5061_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
/*
* This property is used to set the VWEAK threshold
- * bellow this value, weak charge mode is entered
+ * below this value, weak charge mode is entered
* above this value, fast chargerge mode is entered
*/
return adp5061_get_vweak_th(st, val);
diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c
index f71cc90fea12..fa27195f074e 100644
--- a/drivers/power/supply/axp20x_battery.c
+++ b/drivers/power/supply/axp20x_battery.c
@@ -354,17 +354,18 @@ static int axp20x_battery_get_prop(struct power_supply *psy,
if (ret)
return ret;
+ /* IIO framework gives mA but Power Supply framework gives uA */
if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
- ret = iio_read_channel_processed(axp20x_batt->batt_chrg_i, &val->intval);
+ ret = iio_read_channel_processed_scale(axp20x_batt->batt_chrg_i,
+ &val->intval, 1000);
} else {
- ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i, &val1);
+ ret = iio_read_channel_processed_scale(axp20x_batt->batt_dischrg_i,
+ &val1, 1000);
val->intval = -val1;
}
if (ret)
return ret;
- /* IIO framework gives mA but Power Supply framework gives uA */
- val->intval *= 1000;
break;
case POWER_SUPPLY_PROP_CAPACITY:
@@ -406,13 +407,12 @@ static int axp20x_battery_get_prop(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- ret = iio_read_channel_processed(axp20x_batt->batt_v,
- &val->intval);
+ /* IIO framework gives mV but Power Supply framework gives uV */
+ ret = iio_read_channel_processed_scale(axp20x_batt->batt_v,
+ &val->intval, 1000);
if (ret)
return ret;
- /* IIO framework gives mV but Power Supply framework gives uV */
- val->intval *= 1000;
break;
default:
@@ -519,13 +519,15 @@ static int axp717_battery_get_prop(struct power_supply *psy,
* The offset of this value is currently unknown and is
* not documented in the datasheet. Based on
* observation it's assumed to be somewhere around
- * 450ma. I will leave the value raw for now.
+ * 450ma. I will leave the value raw for now. Note that
+ * IIO framework gives mA but Power Supply framework
+ * gives uA.
*/
- ret = iio_read_channel_processed(axp20x_batt->batt_chrg_i, &val->intval);
+ ret = iio_read_channel_processed_scale(axp20x_batt->batt_chrg_i,
+ &val->intval, 1000);
if (ret)
return ret;
- /* IIO framework gives mA but Power Supply framework gives uA */
- val->intval *= 1000;
+
return 0;
case POWER_SUPPLY_PROP_CAPACITY:
@@ -564,13 +566,12 @@ static int axp717_battery_get_prop(struct power_supply *psy,
return 0;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- ret = iio_read_channel_processed(axp20x_batt->batt_v,
- &val->intval);
+ /* IIO framework gives mV but Power Supply framework gives uV */
+ ret = iio_read_channel_processed_scale(axp20x_batt->batt_v,
+ &val->intval, 1000);
if (ret)
return ret;
- /* IIO framework gives mV but Power Supply framework gives uV */
- val->intval *= 1000;
return 0;
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index 2766352ab737..9722912268fe 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -220,16 +220,15 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
return 0;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
- ret = iio_read_channel_processed(power->vbus_v,
- &val->intval);
- if (ret)
- return ret;
-
/*
* IIO framework gives mV but Power Supply framework
* gives uV.
*/
- val->intval *= 1000;
+ ret = iio_read_channel_processed_scale(power->vbus_v,
+ &val->intval, 1000);
+ if (ret)
+ return ret;
+
return 0;
}
@@ -253,16 +252,15 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
return 0;
case POWER_SUPPLY_PROP_CURRENT_NOW:
if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
- ret = iio_read_channel_processed(power->vbus_i,
- &val->intval);
- if (ret)
- return ret;
-
/*
* IIO framework gives mA but Power Supply framework
* gives uA.
*/
- val->intval *= 1000;
+ ret = iio_read_channel_processed_scale(power->vbus_i,
+ &val->intval, 1000);
+ if (ret)
+ return ret;
+
return 0;
}
@@ -374,16 +372,15 @@ static int axp717_usb_power_get_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
- ret = iio_read_channel_processed(power->vbus_v,
- &val->intval);
- if (ret)
- return ret;
-
/*
* IIO framework gives mV but Power Supply framework
* gives uV.
*/
- val->intval *= 1000;
+ ret = iio_read_channel_processed_scale(power->vbus_v,
+ &val->intval, 1000);
+ if (ret)
+ return ret;
+
return 0;
}
diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
index 750fda543308..40c5ac7a1118 100644
--- a/drivers/power/supply/bq27xxx_battery.c
+++ b/drivers/power/supply/bq27xxx_battery.c
@@ -449,9 +449,29 @@ static u8
[BQ27XXX_REG_AP] = 0x18,
BQ27XXX_DM_REG_ROWS,
},
+ bq27426_regs[BQ27XXX_REG_MAX] = {
+ [BQ27XXX_REG_CTRL] = 0x00,
+ [BQ27XXX_REG_TEMP] = 0x02,
+ [BQ27XXX_REG_INT_TEMP] = 0x1e,
+ [BQ27XXX_REG_VOLT] = 0x04,
+ [BQ27XXX_REG_AI] = 0x10,
+ [BQ27XXX_REG_FLAGS] = 0x06,
+ [BQ27XXX_REG_TTE] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_TTF] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_TTES] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_NAC] = 0x08,
+ [BQ27XXX_REG_RC] = 0x0c,
+ [BQ27XXX_REG_FCC] = 0x0e,
+ [BQ27XXX_REG_CYCT] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_AE] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_SOC] = 0x1c,
+ [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_AP] = 0x18,
+ BQ27XXX_DM_REG_ROWS,
+ },
#define bq27411_regs bq27421_regs
#define bq27425_regs bq27421_regs
-#define bq27426_regs bq27421_regs
#define bq27441_regs bq27421_regs
#define bq27621_regs bq27421_regs
bq27z561_regs[BQ27XXX_REG_MAX] = {
@@ -769,10 +789,23 @@ static enum power_supply_property bq27421_props[] = {
};
#define bq27411_props bq27421_props
#define bq27425_props bq27421_props
-#define bq27426_props bq27421_props
#define bq27441_props bq27421_props
#define bq27621_props bq27421_props
+static enum power_supply_property bq27426_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
static enum power_supply_property bq27z561_props[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_PRESENT,
@@ -2131,6 +2164,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
struct power_supply_config psy_cfg = {
.of_node = di->dev->of_node,
.drv_data = di,
+ .no_wakeup_source = true,
};
int ret;
@@ -2157,7 +2191,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
psy_desc->get_property = bq27xxx_battery_get_property;
psy_desc->external_power_changed = bq27xxx_external_power_changed;
- di->bat = devm_power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
+ di->bat = devm_power_supply_register(di->dev, psy_desc, &psy_cfg);
if (IS_ERR(di->bat))
return dev_err_probe(di->dev, PTR_ERR(di->bat),
"failed to register battery\n");
diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c
index 09ec0ecf1486..a69faef444c0 100644
--- a/drivers/power/supply/charger-manager.c
+++ b/drivers/power/supply/charger-manager.c
@@ -221,7 +221,7 @@ static bool is_charging(struct charger_manager *cm)
/* If at least one of the charger is charging, return yes */
for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
- /* 1. The charger sholuld not be DISABLED */
+ /* 1. The charger should not be DISABLED */
if (cm->emergency_stop)
continue;
if (!cm->charger_enabled)
@@ -1739,7 +1739,7 @@ static struct platform_driver charger_manager_driver = {
.of_match_table = charger_manager_match,
},
.probe = charger_manager_probe,
- .remove_new = charger_manager_remove,
+ .remove = charger_manager_remove,
.id_table = charger_manager_id,
};
diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c
index 30ec76cdf34b..813037c00ded 100644
--- a/drivers/power/supply/cpcap-battery.c
+++ b/drivers/power/supply/cpcap-battery.c
@@ -1169,7 +1169,7 @@ static struct platform_driver cpcap_battery_driver = {
.of_match_table = of_match_ptr(cpcap_battery_id_table),
},
.probe = cpcap_battery_probe,
- .remove_new = cpcap_battery_remove,
+ .remove = cpcap_battery_remove,
};
module_platform_driver(cpcap_battery_driver);
diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c
index 91e7292d86bb..7781b45a67a7 100644
--- a/drivers/power/supply/cpcap-charger.c
+++ b/drivers/power/supply/cpcap-charger.c
@@ -969,7 +969,7 @@ static struct platform_driver cpcap_charger_driver = {
.of_match_table = cpcap_charger_id_table,
},
.shutdown = cpcap_charger_shutdown,
- .remove_new = cpcap_charger_remove,
+ .remove = cpcap_charger_remove,
};
module_platform_driver(cpcap_charger_driver);
diff --git a/drivers/power/supply/cros_usbpd-charger.c b/drivers/power/supply/cros_usbpd-charger.c
index bed3e2e9bfea..47d3f58aa15c 100644
--- a/drivers/power/supply/cros_usbpd-charger.c
+++ b/drivers/power/supply/cros_usbpd-charger.c
@@ -618,6 +618,7 @@ static int cros_usbpd_charger_probe(struct platform_device *pd)
psy_desc->external_power_changed =
cros_usbpd_charger_power_changed;
psy_cfg.drv_data = port;
+ psy_cfg.no_wakeup_source = true;
if (cros_usbpd_charger_port_is_dedicated(port)) {
sprintf(port->name, CHARGER_DEDICATED_DIR_NAME);
@@ -644,8 +645,7 @@ static int cros_usbpd_charger_probe(struct platform_device *pd)
psy_desc->name = port->name;
- psy = devm_power_supply_register_no_ws(dev, psy_desc,
- &psy_cfg);
+ psy = devm_power_supply_register(dev, psy_desc, &psy_cfg);
if (IS_ERR(psy)) {
dev_err(dev, "Failed to register power supply\n");
continue;
diff --git a/drivers/power/supply/da9030_battery.c b/drivers/power/supply/da9030_battery.c
index 04e0f4162d42..34328f5d556e 100644
--- a/drivers/power/supply/da9030_battery.c
+++ b/drivers/power/supply/da9030_battery.c
@@ -269,7 +269,7 @@ static void da9030_charger_check_state(struct da9030_charger *charger)
}
if (charger->adc.vchmax_res > charger->thresholds.vcharge_max ||
charger->adc.vchmin_res < charger->thresholds.vcharge_min ||
- /* Tempreture readings are negative */
+ /* Temperature readings are negative */
charger->adc.tbat_res < charger->thresholds.tbat_high ||
charger->adc.tbat_res > charger->thresholds.tbat_low) {
/* disable charger */
@@ -470,7 +470,7 @@ static int da9030_battery_charger_init(struct da9030_charger *charger)
if (ret)
return ret;
- /* enable auto ADC measuremnts */
+ /* enable auto ADC measurements */
return da903x_write(charger->master, DA9030_ADC_AUTO_CONTROL,
DA9030_ADC_TBAT_ENABLE | DA9030_ADC_VBAT_IN_TXON |
DA9030_ADC_VCH_ENABLE | DA9030_ADC_ICH_ENABLE |
@@ -571,7 +571,7 @@ static struct platform_driver da903x_battery_driver = {
.name = "da903x-battery",
},
.probe = da9030_battery_probe,
- .remove_new = da9030_battery_remove,
+ .remove = da9030_battery_remove,
};
module_platform_driver(da903x_battery_driver);
diff --git a/drivers/power/supply/da9052-battery.c b/drivers/power/supply/da9052-battery.c
index 0d84c42c624e..6f17e2fa1a28 100644
--- a/drivers/power/supply/da9052-battery.c
+++ b/drivers/power/supply/da9052-battery.c
@@ -648,7 +648,7 @@ static void da9052_bat_remove(struct platform_device *pdev)
static struct platform_driver da9052_bat_driver = {
.probe = da9052_bat_probe,
- .remove_new = da9052_bat_remove,
+ .remove = da9052_bat_remove,
.driver = {
.name = "da9052-bat",
},
diff --git a/drivers/power/supply/da9150-charger.c b/drivers/power/supply/da9150-charger.c
index b13cecd84f58..27f36ef5b88d 100644
--- a/drivers/power/supply/da9150-charger.c
+++ b/drivers/power/supply/da9150-charger.c
@@ -636,7 +636,7 @@ static struct platform_driver da9150_charger_driver = {
.name = "da9150-charger",
},
.probe = da9150_charger_probe,
- .remove_new = da9150_charger_remove,
+ .remove = da9150_charger_remove,
};
module_platform_driver(da9150_charger_driver);
diff --git a/drivers/power/supply/generic-adc-battery.c b/drivers/power/supply/generic-adc-battery.c
index 7bdc6b263609..d5d215f5ad8b 100644
--- a/drivers/power/supply/generic-adc-battery.c
+++ b/drivers/power/supply/generic-adc-battery.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Generic battery driver using IIO
- * Copyright (C) 2012, Anish Kumar <anish198519851985@gmail.com>
+ * Copyright (C) 2012, Anish Kumar <yesanishhere@gmail.com>
* Copyright (c) 2023, Sebastian Reichel <sre@kernel.org>
*/
#include <linux/interrupt.h>
@@ -295,6 +295,6 @@ static struct platform_driver gab_driver = {
};
module_platform_driver(gab_driver);
-MODULE_AUTHOR("anish kumar <anish198519851985@gmail.com>");
+MODULE_AUTHOR("anish kumar <yesanishhere@gmail.com>");
MODULE_DESCRIPTION("generic battery driver using IIO");
MODULE_LICENSE("GPL");
diff --git a/drivers/power/supply/ipaq_micro_battery.c b/drivers/power/supply/ipaq_micro_battery.c
index 66cc649f702a..7e0568a5353f 100644
--- a/drivers/power/supply/ipaq_micro_battery.c
+++ b/drivers/power/supply/ipaq_micro_battery.c
@@ -302,7 +302,7 @@ static struct platform_driver micro_batt_device_driver = {
.pm = &micro_batt_dev_pm_ops,
},
.probe = micro_batt_probe,
- .remove_new = micro_batt_remove,
+ .remove = micro_batt_remove,
};
module_platform_driver(micro_batt_device_driver);
diff --git a/drivers/power/supply/isp1704_charger.c b/drivers/power/supply/isp1704_charger.c
index 860d8614c98f..237912a92272 100644
--- a/drivers/power/supply/isp1704_charger.c
+++ b/drivers/power/supply/isp1704_charger.c
@@ -501,7 +501,7 @@ static struct platform_driver isp1704_charger_driver = {
.of_match_table = of_match_ptr(omap_isp1704_of_match),
},
.probe = isp1704_charger_probe,
- .remove_new = isp1704_charger_remove,
+ .remove = isp1704_charger_remove,
};
module_platform_driver(isp1704_charger_driver);
diff --git a/drivers/power/supply/lenovo_yoga_c630_battery.c b/drivers/power/supply/lenovo_yoga_c630_battery.c
index f98f65e00831..7a6c8af9e8c2 100644
--- a/drivers/power/supply/lenovo_yoga_c630_battery.c
+++ b/drivers/power/supply/lenovo_yoga_c630_battery.c
@@ -368,11 +368,12 @@ static int yoga_c630_psy_register_bat_psy(struct yoga_c630_psy *ecbat)
bat_cfg.drv_data = ecbat;
bat_cfg.fwnode = ecbat->fwnode;
- ecbat->bat_psy = power_supply_register_no_ws(ecbat->dev,
- ecbat->unit_mA ?
- &yoga_c630_psy_bat_psy_desc_mA :
- &yoga_c630_psy_bat_psy_desc_mWh,
- &bat_cfg);
+ bat_cfg.no_wakeup_source = true;
+ ecbat->bat_psy = power_supply_register(ecbat->dev,
+ ecbat->unit_mA ?
+ &yoga_c630_psy_bat_psy_desc_mA :
+ &yoga_c630_psy_bat_psy_desc_mWh,
+ &bat_cfg);
if (IS_ERR(ecbat->bat_psy)) {
dev_err(ecbat->dev, "failed to register battery supply\n");
return PTR_ERR(ecbat->bat_psy);
@@ -442,7 +443,8 @@ static int yoga_c630_psy_probe(struct auxiliary_device *adev,
adp_cfg.fwnode = ecbat->fwnode;
adp_cfg.supplied_to = (char **)&yoga_c630_psy_bat_psy_desc_mA.name;
adp_cfg.num_supplicants = 1;
- ecbat->adp_psy = devm_power_supply_register_no_ws(dev, &yoga_c630_psy_adpt_psy_desc, &adp_cfg);
+ adp_cfg.no_wakeup_source = true;
+ ecbat->adp_psy = devm_power_supply_register(dev, &yoga_c630_psy_adpt_psy_desc, &adp_cfg);
if (IS_ERR(ecbat->adp_psy)) {
dev_err(dev, "failed to register AC adapter supply\n");
return PTR_ERR(ecbat->adp_psy);
diff --git a/drivers/power/supply/lp8788-charger.c b/drivers/power/supply/lp8788-charger.c
index 72b170b4ac46..f0a680c155c4 100644
--- a/drivers/power/supply/lp8788-charger.c
+++ b/drivers/power/supply/lp8788-charger.c
@@ -716,7 +716,7 @@ static void lp8788_charger_remove(struct platform_device *pdev)
static struct platform_driver lp8788_charger_driver = {
.probe = lp8788_charger_probe,
- .remove_new = lp8788_charger_remove,
+ .remove = lp8788_charger_remove,
.driver = {
.name = LP8788_DEV_CHARGER,
},
diff --git a/drivers/power/supply/max14577_charger.c b/drivers/power/supply/max14577_charger.c
index b28c04157709..1cef2f860b5f 100644
--- a/drivers/power/supply/max14577_charger.c
+++ b/drivers/power/supply/max14577_charger.c
@@ -634,7 +634,7 @@ static struct platform_driver max14577_charger_driver = {
.of_match_table = of_max14577_charger_dt_match,
},
.probe = max14577_charger_probe,
- .remove_new = max14577_charger_remove,
+ .remove = max14577_charger_remove,
.id_table = max14577_charger_id,
};
module_platform_driver(max14577_charger_driver);
diff --git a/drivers/power/supply/max77650-charger.c b/drivers/power/supply/max77650-charger.c
index 818e13c613e3..5f58c0c24b4d 100644
--- a/drivers/power/supply/max77650-charger.c
+++ b/drivers/power/supply/max77650-charger.c
@@ -364,7 +364,7 @@ static struct platform_driver max77650_charger_driver = {
.of_match_table = max77650_charger_of_match,
},
.probe = max77650_charger_probe,
- .remove_new = max77650_charger_remove,
+ .remove = max77650_charger_remove,
};
module_platform_driver(max77650_charger_driver);
diff --git a/drivers/power/supply/max77693_charger.c b/drivers/power/supply/max77693_charger.c
index 4caac142c428..cdea35c0d1de 100644
--- a/drivers/power/supply/max77693_charger.c
+++ b/drivers/power/supply/max77693_charger.c
@@ -798,7 +798,7 @@ static struct platform_driver max77693_charger_driver = {
.name = "max77693-charger",
},
.probe = max77693_charger_probe,
- .remove_new = max77693_charger_remove,
+ .remove = max77693_charger_remove,
.id_table = max77693_charger_id,
};
module_platform_driver(max77693_charger_driver);
diff --git a/drivers/power/supply/max77976_charger.c b/drivers/power/supply/max77976_charger.c
index d7e520da7688..e6fe68cebc32 100644
--- a/drivers/power/supply/max77976_charger.c
+++ b/drivers/power/supply/max77976_charger.c
@@ -452,6 +452,7 @@ static int max77976_probe(struct i2c_client *client)
i2c_set_clientdata(client, chg);
psy_cfg.drv_data = chg;
+ psy_cfg.no_wakeup_source = true;
chg->client = client;
chg->regmap = devm_regmap_init_i2c(client, &max77976_regmap_config);
@@ -475,7 +476,7 @@ static int max77976_probe(struct i2c_client *client)
if (err)
return err;
- psy = devm_power_supply_register_no_ws(dev, &max77976_psy_desc, &psy_cfg);
+ psy = devm_power_supply_register(dev, &max77976_psy_desc, &psy_cfg);
if (IS_ERR(psy))
return dev_err_probe(dev, PTR_ERR(psy), "cannot register\n");
diff --git a/drivers/power/supply/max8925_power.c b/drivers/power/supply/max8925_power.c
index 621a006d52a9..d753145de3bb 100644
--- a/drivers/power/supply/max8925_power.c
+++ b/drivers/power/supply/max8925_power.c
@@ -73,7 +73,7 @@ struct max8925_power_info {
unsigned usb_online:1;
unsigned bat_online:1;
unsigned chg_mode:2;
- unsigned batt_detect:1; /* detecing MB by ID pin */
+ unsigned batt_detect:1; /* detecting MB by ID pin */
unsigned topoff_threshold:2;
unsigned fast_charge:3;
unsigned no_temp_support:1;
@@ -563,7 +563,7 @@ static void max8925_power_remove(struct platform_device *pdev)
static struct platform_driver max8925_power_driver = {
.probe = max8925_power_probe,
- .remove_new = max8925_power_remove,
+ .remove = max8925_power_remove,
.driver = {
.name = "max8925-power",
},
diff --git a/drivers/power/supply/pcf50633-charger.c b/drivers/power/supply/pcf50633-charger.c
index 0e980522fee5..0136bc87b105 100644
--- a/drivers/power/supply/pcf50633-charger.c
+++ b/drivers/power/supply/pcf50633-charger.c
@@ -455,7 +455,7 @@ static struct platform_driver pcf50633_mbc_driver = {
.name = "pcf50633-mbc",
},
.probe = pcf50633_mbc_probe,
- .remove_new = pcf50633_mbc_remove,
+ .remove = pcf50633_mbc_remove,
};
module_platform_driver(pcf50633_mbc_driver);
diff --git a/drivers/power/supply/pmu_battery.c b/drivers/power/supply/pmu_battery.c
index eaab7500d99b..ed83c5e05ca3 100644
--- a/drivers/power/supply/pmu_battery.c
+++ b/drivers/power/supply/pmu_battery.c
@@ -170,6 +170,7 @@ static int __init pmu_bat_init(void)
pbat->bat_desc.properties = pmu_bat_props;
pbat->bat_desc.num_properties = ARRAY_SIZE(pmu_bat_props);
pbat->bat_desc.get_property = pmu_bat_get_property;
+ pbat->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
pbat->pbi = &pmu_batteries[i];
psy_cfg.drv_data = pbat;
diff --git a/drivers/power/supply/power_supply.h b/drivers/power/supply/power_supply.h
index 3cbafc58bdad..7434a6f24775 100644
--- a/drivers/power/supply/power_supply.h
+++ b/drivers/power/supply/power_supply.h
@@ -13,9 +13,12 @@ struct device;
struct device_type;
struct power_supply;
+extern int power_supply_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp);
+
#ifdef CONFIG_SYSFS
-extern void power_supply_init_attrs(void);
+extern void __init power_supply_init_attrs(void);
extern int power_supply_uevent(const struct device *dev, struct kobj_uevent_env *env);
extern const struct attribute_group *power_supply_attr_groups[];
@@ -41,3 +44,20 @@ static inline int power_supply_create_triggers(struct power_supply *psy)
static inline void power_supply_remove_triggers(struct power_supply *psy) {}
#endif /* CONFIG_LEDS_TRIGGERS */
+
+#ifdef CONFIG_POWER_SUPPLY_HWMON
+
+int power_supply_add_hwmon_sysfs(struct power_supply *psy);
+void power_supply_remove_hwmon_sysfs(struct power_supply *psy);
+
+#else
+
+static inline int power_supply_add_hwmon_sysfs(struct power_supply *psy)
+{
+ return 0;
+}
+
+static inline
+void power_supply_remove_hwmon_sysfs(struct power_supply *psy) {}
+
+#endif /* CONFIG_POWER_SUPPLY_HWMON */
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index 49534458a9f7..16085eff0084 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -152,7 +152,7 @@ static void power_supply_deferred_register_work(struct work_struct *work)
deferred_register_work.work);
if (psy->dev.parent) {
- while (!mutex_trylock(&psy->dev.parent->mutex)) {
+ while (!device_trylock(psy->dev.parent)) {
if (psy->removing)
return;
msleep(10);
@@ -162,7 +162,7 @@ static void power_supply_deferred_register_work(struct work_struct *work)
power_supply_changed(psy);
if (psy->dev.parent)
- mutex_unlock(&psy->dev.parent->mutex);
+ device_unlock(psy->dev.parent);
}
#ifdef CONFIG_OF
@@ -484,8 +484,6 @@ EXPORT_SYMBOL_GPL(power_supply_get_by_name);
*/
void power_supply_put(struct power_supply *psy)
{
- might_sleep();
-
atomic_dec(&psy->use_cnt);
put_device(&psy->dev);
}
@@ -777,7 +775,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
tab_len = size / (2 * sizeof(__be32));
info->ocv_table_size[index] = tab_len;
- table = info->ocv_table[index] =
+ info->ocv_table[index] = table =
devm_kcalloc(&psy->dev, tab_len, sizeof(*table), GFP_KERNEL);
if (!info->ocv_table[index]) {
power_supply_put_battery_info(psy, info);
@@ -798,7 +796,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
goto out_ret_pointer;
info->resist_table_size = len / (2 * sizeof(__be32));
- resist_table = info->resist_table = devm_kcalloc(&psy->dev,
+ info->resist_table = resist_table = devm_kcalloc(&psy->dev,
info->resist_table_size,
sizeof(*resist_table),
GFP_KERNEL);
@@ -982,7 +980,7 @@ EXPORT_SYMBOL_GPL(power_supply_battery_info_get_prop);
*
* Return: the battery internal resistance percent
*/
-int power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *table,
+int power_supply_temp2resist_simple(const struct power_supply_resistance_temp_table *table,
int table_len, int temp)
{
int i, high, low;
@@ -1093,7 +1091,7 @@ EXPORT_SYMBOL_GPL(power_supply_get_maintenance_charging_setting);
*
* Return: the battery capacity.
*/
-int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table,
+int power_supply_ocv2cap_simple(const struct power_supply_battery_ocv_table *table,
int table_len, int ocv)
{
int i, high, low;
@@ -1118,7 +1116,7 @@ int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table,
}
EXPORT_SYMBOL_GPL(power_supply_ocv2cap_simple);
-struct power_supply_battery_ocv_table *
+const struct power_supply_battery_ocv_table *
power_supply_find_ocv2cap_table(struct power_supply_battery_info *info,
int temp, int *table_len)
{
@@ -1149,7 +1147,7 @@ EXPORT_SYMBOL_GPL(power_supply_find_ocv2cap_table);
int power_supply_batinfo_ocv2cap(struct power_supply_battery_info *info,
int ocv, int temp)
{
- struct power_supply_battery_ocv_table *table;
+ const struct power_supply_battery_ocv_table *table;
int table_len;
table = power_supply_find_ocv2cap_table(info, temp, &table_len);
@@ -1233,7 +1231,6 @@ int power_supply_property_is_writeable(struct power_supply *psy,
{
return psy->desc->property_is_writeable && psy->desc->property_is_writeable(psy, psp);
}
-EXPORT_SYMBOL_GPL(power_supply_property_is_writeable);
void power_supply_external_power_changed(struct power_supply *psy)
{
@@ -1342,8 +1339,7 @@ static void psy_unregister_thermal(struct power_supply *psy)
static struct power_supply *__must_check
__power_supply_register(struct device *parent,
const struct power_supply_desc *desc,
- const struct power_supply_config *cfg,
- bool ws)
+ const struct power_supply_config *cfg)
{
struct device *dev;
struct power_supply *psy;
@@ -1410,7 +1406,7 @@ __power_supply_register(struct device *parent,
if (rc)
goto device_add_failed;
- rc = device_init_wakeup(dev, ws);
+ rc = device_init_wakeup(dev, cfg ? !cfg->no_wakeup_source : true);
if (rc)
goto wakeup_init_failed;
@@ -1476,33 +1472,10 @@ struct power_supply *__must_check power_supply_register(struct device *parent,
const struct power_supply_desc *desc,
const struct power_supply_config *cfg)
{
- return __power_supply_register(parent, desc, cfg, true);
+ return __power_supply_register(parent, desc, cfg);
}
EXPORT_SYMBOL_GPL(power_supply_register);
-/**
- * power_supply_register_no_ws() - Register new non-waking-source power supply
- * @parent: Device to be a parent of power supply's device, usually
- * the device which probe function calls this
- * @desc: Description of power supply, must be valid through whole
- * lifetime of this power supply
- * @cfg: Run-time specific configuration accessed during registering,
- * may be NULL
- *
- * Return: A pointer to newly allocated power_supply on success
- * or ERR_PTR otherwise.
- * Use power_supply_unregister() on returned power_supply pointer to release
- * resources.
- */
-struct power_supply *__must_check
-power_supply_register_no_ws(struct device *parent,
- const struct power_supply_desc *desc,
- const struct power_supply_config *cfg)
-{
- return __power_supply_register(parent, desc, cfg, false);
-}
-EXPORT_SYMBOL_GPL(power_supply_register_no_ws);
-
static void devm_power_supply_release(struct device *dev, void *res)
{
struct power_supply **psy = res;
@@ -1535,7 +1508,7 @@ devm_power_supply_register(struct device *parent,
if (!ptr)
return ERR_PTR(-ENOMEM);
- psy = __power_supply_register(parent, desc, cfg, true);
+ psy = __power_supply_register(parent, desc, cfg);
if (IS_ERR(psy)) {
devres_free(ptr);
} else {
@@ -1547,42 +1520,6 @@ devm_power_supply_register(struct device *parent,
EXPORT_SYMBOL_GPL(devm_power_supply_register);
/**
- * devm_power_supply_register_no_ws() - Register managed non-waking-source power supply
- * @parent: Device to be a parent of power supply's device, usually
- * the device which probe function calls this
- * @desc: Description of power supply, must be valid through whole
- * lifetime of this power supply
- * @cfg: Run-time specific configuration accessed during registering,
- * may be NULL
- *
- * Return: A pointer to newly allocated power_supply on success
- * or ERR_PTR otherwise.
- * The returned power_supply pointer will be automatically unregistered
- * on driver detach.
- */
-struct power_supply *__must_check
-devm_power_supply_register_no_ws(struct device *parent,
- const struct power_supply_desc *desc,
- const struct power_supply_config *cfg)
-{
- struct power_supply **ptr, *psy;
-
- ptr = devres_alloc(devm_power_supply_release, sizeof(*ptr), GFP_KERNEL);
-
- if (!ptr)
- return ERR_PTR(-ENOMEM);
- psy = __power_supply_register(parent, desc, cfg, false);
- if (IS_ERR(psy)) {
- devres_free(ptr);
- } else {
- *ptr = psy;
- devres_add(parent, ptr);
- }
- return psy;
-}
-EXPORT_SYMBOL_GPL(devm_power_supply_register_no_ws);
-
-/**
* power_supply_unregister() - Remove this power supply from system
* @psy: Pointer to power supply to unregister
*
diff --git a/drivers/power/supply/power_supply_hwmon.c b/drivers/power/supply/power_supply_hwmon.c
index 6fbbfb1c685e..01be04903d7d 100644
--- a/drivers/power/supply/power_supply_hwmon.c
+++ b/drivers/power/supply/power_supply_hwmon.c
@@ -7,6 +7,7 @@
#include <linux/hwmon.h>
#include <linux/power_supply.h>
#include <linux/slab.h>
+#include "power_supply.h"
struct power_supply_hwmon {
struct power_supply *psy;
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 16b3c5880cd8..571de43fcca9 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -142,7 +142,7 @@ static const char * const POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[] = {
[POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE] = "force-discharge",
};
-static struct power_supply_attr power_supply_attrs[] = {
+static struct power_supply_attr power_supply_attrs[] __ro_after_init = {
/* Properties of type `int' */
POWER_SUPPLY_ENUM_ATTR(STATUS),
POWER_SUPPLY_ENUM_ATTR(CHARGE_TYPE),
@@ -225,9 +225,9 @@ static struct power_supply_attr power_supply_attrs[] = {
#define POWER_SUPPLY_ATTR_CNT ARRAY_SIZE(power_supply_attrs)
static struct attribute *
-__power_supply_attrs[POWER_SUPPLY_ATTR_CNT + 1];
+__power_supply_attrs[POWER_SUPPLY_ATTR_CNT + 1] __ro_after_init;
-static struct power_supply_attr *to_ps_attr(struct device_attribute *attr)
+static const struct power_supply_attr *to_ps_attr(struct device_attribute *attr)
{
return container_of(attr, struct power_supply_attr, dev_attr);
}
@@ -273,7 +273,7 @@ static ssize_t power_supply_show_property(struct device *dev,
char *buf) {
ssize_t ret;
struct power_supply *psy = dev_get_drvdata(dev);
- struct power_supply_attr *ps_attr = to_ps_attr(attr);
+ const struct power_supply_attr *ps_attr = to_ps_attr(attr);
enum power_supply_property psp = dev_attr_psp(attr);
union power_supply_propval value;
@@ -326,7 +326,7 @@ static ssize_t power_supply_store_property(struct device *dev,
const char *buf, size_t count) {
ssize_t ret;
struct power_supply *psy = dev_get_drvdata(dev);
- struct power_supply_attr *ps_attr = to_ps_attr(attr);
+ const struct power_supply_attr *ps_attr = to_ps_attr(attr);
enum power_supply_property psp = dev_attr_psp(attr);
union power_supply_propval value;
@@ -401,7 +401,7 @@ const struct attribute_group *power_supply_attr_groups[] = {
NULL
};
-void power_supply_init_attrs(void)
+void __init power_supply_init_attrs(void)
{
int i;
diff --git a/drivers/power/supply/qcom_battmgr.c b/drivers/power/supply/qcom_battmgr.c
index f0a64c00ddaa..47d29271ddf4 100644
--- a/drivers/power/supply/qcom_battmgr.c
+++ b/drivers/power/supply/qcom_battmgr.c
@@ -151,7 +151,7 @@ struct qcom_battmgr_message {
__le32 capacity_low;
__le32 capacity_warning;
__le32 cycle_count;
- /* thousandth of persent */
+ /* thousandth of percent */
__le32 accuracy;
__le32 max_sample_time_ms;
__le32 min_sample_time_ms;
diff --git a/drivers/power/supply/qcom_pmi8998_charger.c b/drivers/power/supply/qcom_pmi8998_charger.c
index 81acbd8b2169..3b4132376649 100644
--- a/drivers/power/supply/qcom_pmi8998_charger.c
+++ b/drivers/power/supply/qcom_pmi8998_charger.c
@@ -832,7 +832,7 @@ static const struct smb2_register smb2_init_seq[] = {
AUTO_RECHG_BIT | EN_ANALOG_DROP_IN_VBATT_BIT |
CHARGER_INHIBIT_BIT,
.val = CHARGER_INHIBIT_BIT },
- /* STAT pin software override, match downstream. Parallell charging? */
+ /* STAT pin software override, match downstream. Parallel charging? */
{ .addr = STAT_CFG,
.mask = STAT_SW_OVERRIDE_CFG_BIT,
.val = STAT_SW_OVERRIDE_CFG_BIT },
diff --git a/drivers/power/supply/qcom_smbb.c b/drivers/power/supply/qcom_smbb.c
index 4e57762e27ba..a79563f6ff7a 100644
--- a/drivers/power/supply/qcom_smbb.c
+++ b/drivers/power/supply/qcom_smbb.c
@@ -1017,10 +1017,10 @@ static const struct of_device_id smbb_charger_id_table[] = {
MODULE_DEVICE_TABLE(of, smbb_charger_id_table);
static struct platform_driver smbb_charger_driver = {
- .probe = smbb_charger_probe,
- .remove_new = smbb_charger_remove,
- .driver = {
- .name = "qcom-smbb",
+ .probe = smbb_charger_probe,
+ .remove = smbb_charger_remove,
+ .driver = {
+ .name = "qcom-smbb",
.of_match_table = smbb_charger_id_table,
},
};
diff --git a/drivers/power/supply/rk817_charger.c b/drivers/power/supply/rk817_charger.c
index 57b6ddefad28..e5f35d083c23 100644
--- a/drivers/power/supply/rk817_charger.c
+++ b/drivers/power/supply/rk817_charger.c
@@ -240,9 +240,32 @@ static int rk817_record_battery_nvram_values(struct rk817_charger *charger)
static int rk817_bat_calib_cap(struct rk817_charger *charger)
{
struct rk808 *rk808 = charger->rk808;
- int tmp, charge_now, charge_now_adc, volt_avg;
+ int charge_now, charge_now_adc;
u8 bulk_reg[4];
+ /* Don't do anything if there's no battery. */
+ if (!charger->battery_present)
+ return 0;
+
+ /*
+ * When resuming from suspend, sometimes the voltage value would be
+ * incorrect. BSP would simply wait two seconds and try reading the
+ * values again. Do not do any sort of calibration activity when the
+ * reported value is incorrect. The next scheduled update of battery
+ * vaules should then return valid data and the driver can continue.
+ * Use 2.7v as the sanity value because per the datasheet the PMIC
+ * can in no way support a battery voltage lower than this. BSP only
+ * checked for values too low, but I'm adding in a check for values
+ * too high just in case; again the PMIC can in no way support
+ * voltages above 4.45v, so this seems like a good value.
+ */
+ if ((charger->volt_avg_uv < 2700000) || (charger->volt_avg_uv > 4450000)) {
+ dev_dbg(charger->dev,
+ "Battery voltage of %d is invalid, ignoring.\n",
+ charger->volt_avg_uv);
+ return -EINVAL;
+ }
+
/* Calibrate the soc and fcc on a fully charged battery */
if (charger->charge_status == CHARGE_FINISH && (!charger->soc_cal)) {
@@ -304,51 +327,6 @@ static int rk817_bat_calib_cap(struct rk817_charger *charger)
}
}
- /*
- * Calibrate the fully charged capacity when we previously had a full
- * battery (soc_cal = 1) and are now empty (at or below minimum design
- * voltage). If our columb counter is still positive, subtract that
- * from our fcc value to get a calibrated fcc, and if our columb
- * counter is negative add that to our fcc (but not to exceed our
- * design capacity).
- */
- regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_BAT_VOL_H,
- bulk_reg, 2);
- tmp = get_unaligned_be16(bulk_reg);
- volt_avg = (charger->voltage_k * tmp) + 1000 * charger->voltage_b;
- if (volt_avg <= charger->bat_voltage_min_design_uv &&
- charger->soc_cal) {
- regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3,
- bulk_reg, 4);
- charge_now_adc = get_unaligned_be32(bulk_reg);
- charge_now = ADC_TO_CHARGE_UAH(charge_now_adc,
- charger->res_div);
- /*
- * Note, if charge_now is negative this will add it (what we
- * want) and if it's positive this will subtract (also what
- * we want).
- */
- charger->fcc_mah = charger->fcc_mah - (charge_now / 1000);
-
- dev_dbg(charger->dev,
- "Recalibrating full charge capacity to %d uah\n",
- charger->fcc_mah * 1000);
- }
-
- /*
- * Set the SOC to 0 if we are below the minimum system voltage.
- */
- if (volt_avg <= charger->bat_voltage_min_design_uv) {
- charger->soc = 0;
- charge_now_adc = CHARGE_TO_ADC(0, charger->res_div);
- put_unaligned_be32(charge_now_adc, bulk_reg);
- regmap_bulk_write(rk808->regmap,
- RK817_GAS_GAUGE_Q_INIT_H3, bulk_reg, 4);
- dev_warn(charger->dev,
- "Battery voltage %d below minimum voltage %d\n",
- volt_avg, charger->bat_voltage_min_design_uv);
- }
-
rk817_record_battery_nvram_values(charger);
return 0;
@@ -648,6 +626,24 @@ static irqreturn_t rk817_plug_out_isr(int irq, void *cg)
return IRQ_HANDLED;
}
+static int rk817_bat_set_prop(struct power_supply *ps,
+ enum power_supply_property prop,
+ const union power_supply_propval *val)
+{
+ struct rk817_charger *charger = power_supply_get_drvdata(ps);
+
+ switch (prop) {
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ if ((val->intval < 500000) ||
+ (val->intval > charger->bat_charge_full_design_uah))
+ return -EINVAL;
+ charger->fcc_mah = val->intval / 1000;
+ return rk817_bat_calib_cap(charger);
+ default:
+ return -EINVAL;
+ }
+}
+
static enum power_supply_property rk817_bat_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_STATUS,
@@ -673,12 +669,25 @@ static enum power_supply_property rk817_chg_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_AVG,
};
+static int rk817_bat_prop_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
static const struct power_supply_desc rk817_bat_desc = {
.name = "rk817-battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
.properties = rk817_bat_props,
+ .property_is_writeable = rk817_bat_prop_writeable,
.num_properties = ARRAY_SIZE(rk817_bat_props),
.get_property = rk817_bat_get_prop,
+ .set_property = rk817_bat_set_prop,
};
static const struct power_supply_desc rk817_chg_desc = {
@@ -1202,6 +1211,15 @@ static int rk817_charger_probe(struct platform_device *pdev)
return 0;
}
+static int __maybe_unused rk817_suspend(struct device *dev)
+{
+ struct rk817_charger *charger = dev_get_drvdata(dev);
+
+ cancel_delayed_work_sync(&charger->work);
+
+ return 0;
+}
+
static int __maybe_unused rk817_resume(struct device *dev)
{
@@ -1213,7 +1231,7 @@ static int __maybe_unused rk817_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(rk817_charger_pm, NULL, rk817_resume);
+static SIMPLE_DEV_PM_OPS(rk817_charger_pm, rk817_suspend, rk817_resume);
static struct platform_driver rk817_charger_driver = {
.probe = rk817_charger_probe,
diff --git a/drivers/power/supply/rt9471.c b/drivers/power/supply/rt9471.c
index c04af1ee89c6..67b86ac91a21 100644
--- a/drivers/power/supply/rt9471.c
+++ b/drivers/power/supply/rt9471.c
@@ -139,6 +139,19 @@ enum {
RT9471_PORTSTAT_DCP,
};
+enum {
+ RT9471_ICSTAT_SLEEP = 0,
+ RT9471_ICSTAT_VBUSRDY,
+ RT9471_ICSTAT_TRICKLECHG,
+ RT9471_ICSTAT_PRECHG,
+ RT9471_ICSTAT_FASTCHG,
+ RT9471_ICSTAT_IEOC,
+ RT9471_ICSTAT_BGCHG,
+ RT9471_ICSTAT_CHGDONE,
+ RT9471_ICSTAT_CHGFAULT,
+ RT9471_ICSTAT_OTG = 15,
+};
+
struct rt9471_chip {
struct device *dev;
struct regmap *regmap;
@@ -153,8 +166,8 @@ struct rt9471_chip {
};
static const struct reg_field rt9471_reg_fields[F_MAX_FIELDS] = {
- [F_WDT] = REG_FIELD(RT9471_REG_TOP, 0, 0),
- [F_WDT_RST] = REG_FIELD(RT9471_REG_TOP, 1, 1),
+ [F_WDT] = REG_FIELD(RT9471_REG_TOP, 0, 1),
+ [F_WDT_RST] = REG_FIELD(RT9471_REG_TOP, 2, 2),
[F_CHG_EN] = REG_FIELD(RT9471_REG_FUNC, 0, 0),
[F_HZ] = REG_FIELD(RT9471_REG_FUNC, 5, 5),
[F_BATFET_DIS] = REG_FIELD(RT9471_REG_FUNC, 7, 7),
@@ -255,31 +268,32 @@ static int rt9471_get_ieoc(struct rt9471_chip *chip, int *microamp)
static int rt9471_get_status(struct rt9471_chip *chip, int *status)
{
- unsigned int chg_ready, chg_done, fault_stat;
+ unsigned int ic_stat;
int ret;
- ret = regmap_field_read(chip->rm_fields[F_ST_CHG_RDY], &chg_ready);
- if (ret)
- return ret;
-
- ret = regmap_field_read(chip->rm_fields[F_ST_CHG_DONE], &chg_done);
+ ret = regmap_field_read(chip->rm_fields[F_IC_STAT], &ic_stat);
if (ret)
return ret;
- ret = regmap_read(chip->regmap, RT9471_REG_STAT1, &fault_stat);
- if (ret)
- return ret;
-
- fault_stat &= RT9471_CHGFAULT_MASK;
-
- if (chg_ready && chg_done)
- *status = POWER_SUPPLY_STATUS_FULL;
- else if (chg_ready && fault_stat)
+ switch (ic_stat) {
+ case RT9471_ICSTAT_VBUSRDY:
+ case RT9471_ICSTAT_CHGFAULT:
*status = POWER_SUPPLY_STATUS_NOT_CHARGING;
- else if (chg_ready && !fault_stat)
+ break;
+ case RT9471_ICSTAT_TRICKLECHG ... RT9471_ICSTAT_BGCHG:
*status = POWER_SUPPLY_STATUS_CHARGING;
- else
+ break;
+ case RT9471_ICSTAT_CHGDONE:
+ *status = POWER_SUPPLY_STATUS_FULL;
+ break;
+ case RT9471_ICSTAT_SLEEP:
+ case RT9471_ICSTAT_OTG:
*status = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ default:
+ *status = POWER_SUPPLY_STATUS_UNKNOWN;
+ break;
+ }
return 0;
}
diff --git a/drivers/power/supply/samsung-sdi-battery.c b/drivers/power/supply/samsung-sdi-battery.c
index b63fd2758c2f..33565002ee27 100644
--- a/drivers/power/supply/samsung-sdi-battery.c
+++ b/drivers/power/supply/samsung-sdi-battery.c
@@ -431,7 +431,7 @@ static const struct power_supply_vbat_ri_table samsung_vbat2res_charging_eb58515
* temperature compensation tables so we just state 100% for every temperature.
* If you have the datasheets, please provide these tables.
*/
-static struct power_supply_resistance_temp_table samsung_temp2res[] = {
+static const struct power_supply_resistance_temp_table samsung_temp2res[] = {
{ .temp = 50, .resistance = 100 },
{ .temp = 40, .resistance = 100 },
{ .temp = 30, .resistance = 100 },
@@ -447,7 +447,7 @@ static struct power_supply_resistance_temp_table samsung_temp2res[] = {
* These must be sorted by falling OCV value.
*/
-static struct power_supply_battery_ocv_table samsung_ocv_cap_eb485159lu[] = {
+static const struct power_supply_battery_ocv_table samsung_ocv_cap_eb485159lu[] = {
{ .ocv = 4330000, .capacity = 100},
{ .ocv = 4320000, .capacity = 99},
{ .ocv = 4283000, .capacity = 95},
@@ -499,7 +499,7 @@ static struct power_supply_battery_ocv_table samsung_ocv_cap_eb485159lu[] = {
};
/* Same capacity table is used by eb-l1m7flu, eb425161la, eb425161lu */
-static struct power_supply_battery_ocv_table samsung_ocv_cap_1500mah[] = {
+static const struct power_supply_battery_ocv_table samsung_ocv_cap_1500mah[] = {
{ .ocv = 4328000, .capacity = 100},
{ .ocv = 4299000, .capacity = 99},
{ .ocv = 4281000, .capacity = 98},
@@ -540,7 +540,7 @@ static struct power_supply_battery_ocv_table samsung_ocv_cap_1500mah[] = {
{ .ocv = 3300000, .capacity = 0},
};
-static struct power_supply_battery_ocv_table samsung_ocv_cap_eb535151vu[] = {
+static const struct power_supply_battery_ocv_table samsung_ocv_cap_eb535151vu[] = {
{ .ocv = 4178000, .capacity = 100},
{ .ocv = 4148000, .capacity = 99},
{ .ocv = 4105000, .capacity = 95},
@@ -572,7 +572,7 @@ static struct power_supply_battery_ocv_table samsung_ocv_cap_eb535151vu[] = {
{ .ocv = 3300000, .capacity = 0},
};
-static struct power_supply_battery_ocv_table samsung_ocv_cap_eb585157lu[] = {
+static const struct power_supply_battery_ocv_table samsung_ocv_cap_eb585157lu[] = {
{ .ocv = 4320000, .capacity = 100},
{ .ocv = 4296000, .capacity = 99},
{ .ocv = 4283000, .capacity = 98},
diff --git a/drivers/power/supply/sc2731_charger.c b/drivers/power/supply/sc2731_charger.c
index b3d8b1ca97da..50d5157af927 100644
--- a/drivers/power/supply/sc2731_charger.c
+++ b/drivers/power/supply/sc2731_charger.c
@@ -530,7 +530,7 @@ static struct platform_driver sc2731_charger_driver = {
.of_match_table = sc2731_charger_of_match,
},
.probe = sc2731_charger_probe,
- .remove_new = sc2731_charger_remove,
+ .remove = sc2731_charger_remove,
};
module_platform_driver(sc2731_charger_driver);
diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c
index bd23c4d9fed4..f36edc2ba708 100644
--- a/drivers/power/supply/sc27xx_fuel_gauge.c
+++ b/drivers/power/supply/sc27xx_fuel_gauge.c
@@ -992,7 +992,7 @@ static int sc27xx_fgu_calibration(struct sc27xx_fgu_data *data)
static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
{
struct power_supply_battery_info *info;
- struct power_supply_battery_ocv_table *table;
+ const struct power_supply_battery_ocv_table *table;
int ret, delta_clbcnt, alarm_adc;
ret = power_supply_get_battery_info(data->battery, &info);
@@ -1183,10 +1183,14 @@ static int sc27xx_fgu_probe(struct platform_device *pdev)
return PTR_ERR(data->charge_chan);
}
- data->gpiod = devm_gpiod_get(dev, "bat-detect", GPIOD_IN);
+ data->gpiod = devm_gpiod_get(dev, "battery-detect", GPIOD_IN);
if (IS_ERR(data->gpiod)) {
- dev_err(dev, "failed to get battery detection GPIO\n");
- return PTR_ERR(data->gpiod);
+ data->gpiod = devm_gpiod_get(dev, "bat-detect", GPIOD_IN);
+ if (IS_ERR(data->gpiod)) {
+ dev_err(dev, "failed to get battery detection GPIO\n");
+ return PTR_ERR(data->gpiod);
+ }
+ dev_warn(dev, "bat-detect is deprecated, please use battery-detect\n");
}
ret = gpiod_get_value_cansleep(data->gpiod);
diff --git a/drivers/power/supply/tps65090-charger.c b/drivers/power/supply/tps65090-charger.c
index d41595764caa..d65193e410a6 100644
--- a/drivers/power/supply/tps65090-charger.c
+++ b/drivers/power/supply/tps65090-charger.c
@@ -343,7 +343,7 @@ static struct platform_driver tps65090_charger_driver = {
.of_match_table = of_tps65090_charger_match,
},
.probe = tps65090_charger_probe,
- .remove_new = tps65090_charger_remove,
+ .remove = tps65090_charger_remove,
};
module_platform_driver(tps65090_charger_driver);
diff --git a/drivers/power/supply/tps65217_charger.c b/drivers/power/supply/tps65217_charger.c
index 2382749a2f53..6fff44e1ecac 100644
--- a/drivers/power/supply/tps65217_charger.c
+++ b/drivers/power/supply/tps65217_charger.c
@@ -269,7 +269,7 @@ MODULE_DEVICE_TABLE(of, tps65217_charger_match_table);
static struct platform_driver tps65217_charger_driver = {
.probe = tps65217_charger_probe,
- .remove_new = tps65217_charger_remove,
+ .remove = tps65217_charger_remove,
.driver = {
.name = "tps65217-charger",
.of_match_table = of_match_ptr(tps65217_charger_match_table),
diff --git a/drivers/power/supply/twl4030_charger.c b/drivers/power/supply/twl4030_charger.c
index f3f1a0862e93..9dcb5457bef4 100644
--- a/drivers/power/supply/twl4030_charger.c
+++ b/drivers/power/supply/twl4030_charger.c
@@ -1133,7 +1133,7 @@ MODULE_DEVICE_TABLE(of, twl_bci_of_match);
static struct platform_driver twl4030_bci_driver = {
.probe = twl4030_bci_probe,
- .remove_new = twl4030_bci_remove,
+ .remove = twl4030_bci_remove,
.driver = {
.name = "twl4030_bci",
.of_match_table = of_match_ptr(twl_bci_of_match),
diff --git a/drivers/power/supply/twl6030_charger.c b/drivers/power/supply/twl6030_charger.c
new file mode 100644
index 000000000000..b4ec26ff257c
--- /dev/null
+++ b/drivers/power/supply/twl6030_charger.c
@@ -0,0 +1,581 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TWL6030 charger
+ *
+ * Copyright (C) 2024 Andreas Kemnade <andreas@kemnade.info>
+ *
+ * based on older 6030 driver found in a v3.0 vendor kernel
+ *
+ * based on twl4030_bci_battery.c by TI
+ * Copyright (C) 2008 Texas Instruments, Inc.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/bits.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/twl.h>
+#include <linux/power_supply.h>
+#include <linux/notifier.h>
+#include <linux/usb/otg.h>
+#include <linux/iio/consumer.h>
+#include <linux/devm-helpers.h>
+
+#define CONTROLLER_INT_MASK 0x00
+#define CONTROLLER_CTRL1 0x01
+#define CONTROLLER_WDG 0x02
+#define CONTROLLER_STAT1 0x03
+#define CHARGERUSB_INT_STATUS 0x04
+#define CHARGERUSB_INT_MASK 0x05
+#define CHARGERUSB_STATUS_INT1 0x06
+#define CHARGERUSB_STATUS_INT2 0x07
+#define CHARGERUSB_CTRL1 0x08
+#define CHARGERUSB_CTRL2 0x09
+#define CHARGERUSB_CTRL3 0x0A
+#define CHARGERUSB_STAT1 0x0B
+#define CHARGERUSB_VOREG 0x0C
+#define CHARGERUSB_VICHRG 0x0D
+#define CHARGERUSB_CINLIMIT 0x0E
+#define CHARGERUSB_CTRLLIMIT1 0x0F
+#define CHARGERUSB_CTRLLIMIT2 0x10
+#define ANTICOLLAPSE_CTRL1 0x11
+#define ANTICOLLAPSE_CTRL2 0x12
+
+/* TWL6032 registers 0xDA to 0xDE - TWL6032_MODULE_CHARGER */
+#define CONTROLLER_CTRL2 0x00
+#define CONTROLLER_VSEL_COMP 0x01
+#define CHARGERUSB_VSYSREG 0x02
+#define CHARGERUSB_VICHRG_PC 0x03
+#define LINEAR_CHRG_STS 0x04
+
+#define LINEAR_CHRG_STS_CRYSTL_OSC_OK 0x40
+#define LINEAR_CHRG_STS_END_OF_CHARGE 0x20
+#define LINEAR_CHRG_STS_VBATOV 0x10
+#define LINEAR_CHRG_STS_VSYSOV 0x08
+#define LINEAR_CHRG_STS_DPPM_STS 0x04
+#define LINEAR_CHRG_STS_CV_STS 0x02
+#define LINEAR_CHRG_STS_CC_STS 0x01
+
+#define FG_REG_00 0x00
+#define FG_REG_01 0x01
+#define FG_REG_02 0x02
+#define FG_REG_03 0x03
+#define FG_REG_04 0x04
+#define FG_REG_05 0x05
+#define FG_REG_06 0x06
+#define FG_REG_07 0x07
+#define FG_REG_08 0x08
+#define FG_REG_09 0x09
+#define FG_REG_10 0x0A
+#define FG_REG_11 0x0B
+
+/* CONTROLLER_INT_MASK */
+#define MVAC_FAULT BIT(7)
+#define MAC_EOC BIT(6)
+#define LINCH_GATED BIT(5)
+#define MBAT_REMOVED BIT(4)
+#define MFAULT_WDG BIT(3)
+#define MBAT_TEMP BIT(2)
+#define MVBUS_DET BIT(1)
+#define MVAC_DET BIT(0)
+
+/* CONTROLLER_CTRL1 */
+#define CONTROLLER_CTRL1_EN_LINCH BIT(5)
+#define CONTROLLER_CTRL1_EN_CHARGER BIT(4)
+#define CONTROLLER_CTRL1_SEL_CHARGER BIT(3)
+
+/* CONTROLLER_STAT1 */
+#define CONTROLLER_STAT1_EXTCHRG_STATZ BIT(7)
+#define CONTROLLER_STAT1_LINCH_GATED BIT(6)
+#define CONTROLLER_STAT1_CHRG_DET_N BIT(5)
+#define CONTROLLER_STAT1_FAULT_WDG BIT(4)
+#define CONTROLLER_STAT1_VAC_DET BIT(3)
+#define VAC_DET BIT(3)
+#define CONTROLLER_STAT1_VBUS_DET BIT(2)
+#define VBUS_DET BIT(2)
+#define CONTROLLER_STAT1_BAT_REMOVED BIT(1)
+#define CONTROLLER_STAT1_BAT_TEMP_OVRANGE BIT(0)
+
+/* CHARGERUSB_INT_STATUS */
+#define EN_LINCH BIT(4)
+#define CURRENT_TERM_INT BIT(3)
+#define CHARGERUSB_STAT BIT(2)
+#define CHARGERUSB_THMREG BIT(1)
+#define CHARGERUSB_FAULT BIT(0)
+
+/* CHARGERUSB_INT_MASK */
+#define MASK_MCURRENT_TERM BIT(3)
+#define MASK_MCHARGERUSB_STAT BIT(2)
+#define MASK_MCHARGERUSB_THMREG BIT(1)
+#define MASK_MCHARGERUSB_FAULT BIT(0)
+
+/* CHARGERUSB_STATUS_INT1 */
+#define CHARGERUSB_STATUS_INT1_TMREG BIT(7)
+#define CHARGERUSB_STATUS_INT1_NO_BAT BIT(6)
+#define CHARGERUSB_STATUS_INT1_BST_OCP BIT(5)
+#define CHARGERUSB_STATUS_INT1_TH_SHUTD BIT(4)
+#define CHARGERUSB_STATUS_INT1_BAT_OVP BIT(3)
+#define CHARGERUSB_STATUS_INT1_POOR_SRC BIT(2)
+#define CHARGERUSB_STATUS_INT1_SLP_MODE BIT(1)
+#define CHARGERUSB_STATUS_INT1_VBUS_OVP BIT(0)
+
+/* CHARGERUSB_STATUS_INT2 */
+#define ICCLOOP BIT(3)
+#define CURRENT_TERM BIT(2)
+#define CHARGE_DONE BIT(1)
+#define ANTICOLLAPSE BIT(0)
+
+/* CHARGERUSB_CTRL1 */
+#define SUSPEND_BOOT BIT(7)
+#define OPA_MODE BIT(6)
+#define HZ_MODE BIT(5)
+#define TERM BIT(4)
+
+/* CHARGERUSB_CTRL2 */
+#define UA_TO_VITERM(x) (((x) / 50000 - 1) << 5)
+
+/* CHARGERUSB_CTRL3 */
+#define VBUSCHRG_LDO_OVRD BIT(7)
+#define CHARGE_ONCE BIT(6)
+#define BST_HW_PR_DIS BIT(5)
+#define AUTOSUPPLY BIT(3)
+#define BUCK_HSILIM BIT(0)
+
+/* CHARGERUSB_VOREG */
+#define UV_TO_VOREG(x) (((x) - 3500000) / 20000)
+#define VOREG_TO_UV(x) (((x) & 0x3F) * 20000 + 3500000)
+#define CHARGERUSB_VOREG_3P52 0x01
+#define CHARGERUSB_VOREG_4P0 0x19
+#define CHARGERUSB_VOREG_4P2 0x23
+#define CHARGERUSB_VOREG_4P76 0x3F
+
+/* CHARGERUSB_VICHRG */
+/*
+ * might be inaccurate for < 500 mA, diffent scale might apply,
+ * either starting from 100 mA or 300 mA
+ */
+#define UA_TO_VICHRG(x) (((x) / 100000) - 1)
+#define VICHRG_TO_UA(x) (((x) & 0xf) * 100000 + 100000)
+
+/* CHARGERUSB_CINLIMIT */
+#define CHARGERUSB_CIN_LIMIT_100 0x1
+#define CHARGERUSB_CIN_LIMIT_300 0x5
+#define CHARGERUSB_CIN_LIMIT_500 0x9
+#define CHARGERUSB_CIN_LIMIT_NONE 0xF
+
+/* CHARGERUSB_CTRLLIMIT2 */
+#define CHARGERUSB_CTRLLIMIT2_1500 0x0E
+#define LOCK_LIMIT BIT(4)
+
+/* ANTICOLLAPSE_CTRL2 */
+#define BUCK_VTH_SHIFT 5
+
+/* FG_REG_00 */
+#define CC_ACTIVE_MODE_SHIFT 6
+#define CC_AUTOCLEAR BIT(2)
+#define CC_CAL_EN BIT(1)
+#define CC_PAUSE BIT(0)
+
+#define REG_TOGGLE1 0x90
+#define REG_PWDNSTATUS1 0x93
+#define FGDITHS BIT(7)
+#define FGDITHR BIT(6)
+#define FGS BIT(5)
+#define FGR BIT(4)
+#define BBSPOR_CFG 0xE6
+#define BB_CHG_EN BIT(3)
+
+struct twl6030_charger_info {
+ struct device *dev;
+ struct power_supply *usb;
+ struct power_supply_battery_info *binfo;
+ struct work_struct work;
+ int irq_chg;
+ int input_current_limit;
+ struct iio_channel *channel_vusb;
+ struct delayed_work charger_monitor;
+ bool extended_current_range;
+};
+
+struct twl6030_charger_chip_data {
+ bool extended_current_range;
+};
+
+static int twl6030_charger_read(u8 reg, u8 *val)
+{
+ return twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, val, reg);
+}
+
+static int twl6030_charger_write(u8 reg, u8 val)
+{
+ return twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, val, reg);
+}
+
+static int twl6030_config_cinlimit_reg(struct twl6030_charger_info *charger,
+ unsigned int ua)
+{
+ if (ua >= 50000 && ua <= 750000) {
+ ua = (ua - 50000) / 50000;
+ } else if ((ua > 750000) && (ua <= 1500000) && charger->extended_current_range) {
+ ua = ((ua % 100000) ? 0x30 : 0x20) + ((ua - 100000) / 100000);
+ } else {
+ if (ua < 50000) {
+ dev_err(charger->dev, "invalid input current limit\n");
+ return -EINVAL;
+ }
+ /* This is no current limit */
+ ua = 0x0F;
+ }
+
+ return twl6030_charger_write(CHARGERUSB_CINLIMIT, ua);
+}
+
+/*
+ * rewriting all stuff here, resets to extremely conservative defaults were
+ * seen under some circumstances, like charge voltage to 3.5V
+ */
+static int twl6030_enable_usb(struct twl6030_charger_info *charger)
+{
+ int ret;
+
+ ret = twl6030_charger_write(CHARGERUSB_VICHRG,
+ UA_TO_VICHRG(charger->binfo->constant_charge_current_max_ua));
+ if (ret < 0)
+ return ret;
+
+ ret = twl6030_charger_write(CONTROLLER_WDG, 0xff);
+ if (ret < 0)
+ return ret;
+
+ charger->input_current_limit = 500000;
+ ret = twl6030_config_cinlimit_reg(charger, charger->input_current_limit);
+ if (ret < 0)
+ return ret;
+
+ ret = twl6030_charger_write(CHARGERUSB_CINLIMIT, CHARGERUSB_CIN_LIMIT_500);
+ if (ret < 0)
+ return ret;
+
+ ret = twl6030_charger_write(CHARGERUSB_VOREG,
+ UV_TO_VOREG(charger->binfo->constant_charge_voltage_max_uv));
+ if (ret < 0)
+ return ret;
+
+ ret = twl6030_charger_write(CHARGERUSB_CTRL1, TERM);
+ if (ret < 0)
+ return ret;
+
+ if (charger->binfo->charge_term_current_ua != -EINVAL) {
+ ret = twl6030_charger_write(CHARGERUSB_CTRL2,
+ UA_TO_VITERM(charger->binfo->charge_term_current_ua));
+ if (ret < 0)
+ return ret;
+ }
+
+ return twl6030_charger_write(CONTROLLER_CTRL1, CONTROLLER_CTRL1_EN_CHARGER);
+}
+
+static void twl6030_charger_wdg(struct work_struct *data)
+{
+ struct twl6030_charger_info *charger =
+ container_of(data, struct twl6030_charger_info,
+ charger_monitor.work);
+
+ u8 val;
+ u8 int_stat;
+ u8 stat_int1;
+ u8 stat_int2;
+
+ twl6030_charger_read(CONTROLLER_STAT1, &val);
+ twl6030_charger_read(CHARGERUSB_INT_STATUS, &int_stat);
+ twl6030_charger_read(CHARGERUSB_STATUS_INT1, &stat_int1);
+ twl6030_charger_read(CHARGERUSB_STATUS_INT2, &stat_int2);
+ dev_dbg(charger->dev,
+ "wdg: stat1: %02x %s INT_STATUS %02x STATUS_INT1 %02x STATUS_INT2 %02x\n",
+ val, (val & VBUS_DET) ? "usb online" : "usb offline",
+ int_stat, stat_int1, stat_int2);
+
+ twl6030_charger_write(CONTROLLER_WDG, 0xff);
+ schedule_delayed_work(&charger->charger_monitor,
+ msecs_to_jiffies(10000));
+}
+
+static irqreturn_t twl6030_charger_interrupt(int irq, void *arg)
+{
+ struct twl6030_charger_info *charger = arg;
+ u8 val;
+ u8 int_stat;
+ u8 stat_int1;
+ u8 stat_int2;
+
+ if (twl6030_charger_read(CONTROLLER_STAT1, &val) < 0)
+ return IRQ_HANDLED;
+
+ if (twl6030_charger_read(CHARGERUSB_INT_STATUS, &int_stat) < 0)
+ return IRQ_HANDLED;
+
+ if (twl6030_charger_read(CHARGERUSB_STATUS_INT1, &stat_int1) < 0)
+ return IRQ_HANDLED;
+
+ if (twl6030_charger_read(CHARGERUSB_STATUS_INT2, &stat_int2) < 0)
+ return IRQ_HANDLED;
+
+ dev_dbg(charger->dev,
+ "charger irq: stat1: %02x %s INT_STATUS %02x STATUS_INT1 %02x STATUS_INT2 %02x\n",
+ val, (val & VBUS_DET) ? "usb online" : "usb offline",
+ int_stat, stat_int1, stat_int2);
+ power_supply_changed(charger->usb);
+
+ if (val & VBUS_DET) {
+ if (twl6030_charger_read(CONTROLLER_CTRL1, &val) < 0)
+ return IRQ_HANDLED;
+
+ if (!(val & CONTROLLER_CTRL1_EN_CHARGER)) {
+ if (twl6030_enable_usb(charger) < 0)
+ return IRQ_HANDLED;
+
+ schedule_delayed_work(&charger->charger_monitor,
+ msecs_to_jiffies(10000));
+ }
+ } else {
+ cancel_delayed_work(&charger->charger_monitor);
+ }
+ return IRQ_HANDLED;
+}
+
+static int twl6030_charger_usb_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct twl6030_charger_info *charger = power_supply_get_drvdata(psy);
+ int ret;
+ u8 stat1;
+ u8 intstat;
+
+ ret = twl6030_charger_read(CONTROLLER_STAT1, &stat1);
+ if (ret)
+ return ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (!(stat1 & VBUS_DET)) {
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ break;
+ }
+ ret = twl6030_charger_read(CHARGERUSB_STATUS_INT2, &intstat);
+ if (ret)
+ return ret;
+
+ if (intstat & CHARGE_DONE)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else if (intstat & CURRENT_TERM)
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ if (!charger->channel_vusb)
+ return -ENODATA;
+
+ ret = iio_read_channel_processed_scale(charger->channel_vusb, &val->intval, 1000);
+ if (ret < 0)
+ return ret;
+
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = !!(stat1 & VBUS_DET);
+ break;
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ val->intval = charger->input_current_limit;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int twl6030_charger_usb_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct twl6030_charger_info *charger = power_supply_get_drvdata(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ charger->input_current_limit = val->intval;
+ return twl6030_config_cinlimit_reg(charger, charger->input_current_limit);
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int twl6030_charger_usb_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ dev_info(&psy->dev, "is %d writeable?\n", (int)psp);
+ switch (psp) {
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static enum power_supply_property twl6030_charger_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+};
+
+static const struct power_supply_desc twl6030_charger_usb_desc = {
+ .name = "twl6030_usb",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .properties = twl6030_charger_props,
+ .num_properties = ARRAY_SIZE(twl6030_charger_props),
+ .get_property = twl6030_charger_usb_get_property,
+ .set_property = twl6030_charger_usb_set_property,
+ .property_is_writeable = twl6030_charger_usb_property_is_writeable,
+};
+
+static int twl6030_charger_probe(struct platform_device *pdev)
+{
+ struct twl6030_charger_info *charger;
+ const struct twl6030_charger_chip_data *chip_data;
+ struct power_supply_config psy_cfg = {};
+ int ret;
+ u8 val;
+
+ charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
+ if (!charger)
+ return -ENOMEM;
+
+ charger->dev = &pdev->dev;
+ charger->irq_chg = platform_get_irq(pdev, 0);
+
+ chip_data = device_get_match_data(&pdev->dev);
+ if (!chip_data)
+ return dev_err_probe(&pdev->dev, -EINVAL, "missing chip data\n");
+
+ charger->extended_current_range = chip_data->extended_current_range;
+ platform_set_drvdata(pdev, charger);
+ psy_cfg.drv_data = charger;
+ psy_cfg.fwnode = dev_fwnode(&pdev->dev);
+
+ charger->channel_vusb = devm_iio_channel_get(&pdev->dev, "vusb");
+ if (IS_ERR(charger->channel_vusb)) {
+ ret = PTR_ERR(charger->channel_vusb);
+ if (ret == -EPROBE_DEFER)
+ return ret; /* iio not ready */
+ dev_warn(&pdev->dev, "could not request vusb iio channel (%d)",
+ ret);
+ charger->channel_vusb = NULL;
+ }
+
+ charger->usb = devm_power_supply_register(&pdev->dev,
+ &twl6030_charger_usb_desc,
+ &psy_cfg);
+ if (IS_ERR(charger->usb))
+ return dev_err_probe(&pdev->dev, PTR_ERR(charger->usb),
+ "Failed to register usb\n");
+
+ ret = power_supply_get_battery_info(charger->usb, &charger->binfo);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to get battery info\n");
+
+ dev_info(&pdev->dev, "battery with vmax %d imax: %d\n",
+ charger->binfo->constant_charge_voltage_max_uv,
+ charger->binfo->constant_charge_current_max_ua);
+
+ if (charger->binfo->constant_charge_voltage_max_uv == -EINVAL) {
+ ret = twl6030_charger_read(CHARGERUSB_CTRLLIMIT1, &val);
+ if (ret < 0)
+ return ret;
+
+ charger->binfo->constant_charge_voltage_max_uv =
+ VOREG_TO_UV(val);
+ }
+
+ if (charger->binfo->constant_charge_voltage_max_uv > 4760000 ||
+ charger->binfo->constant_charge_voltage_max_uv < 350000)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "Invalid charge voltage\n");
+
+ if (charger->binfo->constant_charge_current_max_ua == -EINVAL) {
+ ret = twl6030_charger_read(CHARGERUSB_CTRLLIMIT2, &val);
+ if (ret < 0)
+ return ret;
+
+ charger->binfo->constant_charge_current_max_ua = VICHRG_TO_UA(val);
+ }
+
+ if (charger->binfo->constant_charge_current_max_ua < 100000 ||
+ charger->binfo->constant_charge_current_max_ua > 1500000) {
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "Invalid charge current\n");
+ }
+
+ if ((charger->binfo->charge_term_current_ua != -EINVAL) &&
+ (charger->binfo->charge_term_current_ua > 400000 ||
+ charger->binfo->charge_term_current_ua < 50000)) {
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "Invalid charge termination current\n");
+ }
+
+ ret = devm_delayed_work_autocancel(&pdev->dev,
+ &charger->charger_monitor,
+ twl6030_charger_wdg);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to register delayed work\n");
+
+ ret = devm_request_threaded_irq(&pdev->dev, charger->irq_chg, NULL,
+ twl6030_charger_interrupt,
+ IRQF_ONESHOT, pdev->name,
+ charger);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "could not request irq %d\n",
+ charger->irq_chg);
+
+ /* turing to charging to configure things */
+ twl6030_charger_write(CONTROLLER_CTRL1, 0);
+ twl6030_charger_interrupt(0, charger);
+
+ return 0;
+}
+
+static const struct twl6030_charger_chip_data twl6030_data = {
+ .extended_current_range = false,
+};
+
+static const struct twl6030_charger_chip_data twl6032_data = {
+ .extended_current_range = true,
+};
+
+static const struct of_device_id twl_charger_of_match[] = {
+ {.compatible = "ti,twl6030-charger", .data = &twl6030_data},
+ {.compatible = "ti,twl6032-charger", .data = &twl6032_data},
+ { }
+};
+MODULE_DEVICE_TABLE(of, twl_charger_of_match);
+
+static struct platform_driver twl6030_charger_driver = {
+ .probe = twl6030_charger_probe,
+ .driver = {
+ .name = "twl6030_charger",
+ .of_match_table = twl_charger_of_match,
+ },
+};
+module_platform_driver(twl6030_charger_driver);
+
+MODULE_DESCRIPTION("TWL6030 Battery Charger Interface driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/supply/wm831x_power.c b/drivers/power/supply/wm831x_power.c
index d56e499ac59f..538055b29dec 100644
--- a/drivers/power/supply/wm831x_power.c
+++ b/drivers/power/supply/wm831x_power.c
@@ -720,7 +720,7 @@ static void wm831x_power_remove(struct platform_device *pdev)
static struct platform_driver wm831x_power_driver = {
.probe = wm831x_power_probe,
- .remove_new = wm831x_power_remove,
+ .remove = wm831x_power_remove,
.driver = {
.name = "wm831x-power",
},
diff --git a/drivers/power/supply/wm8350_power.c b/drivers/power/supply/wm8350_power.c
index 3f79ab6f6abf..b0eb6e0ce8bc 100644
--- a/drivers/power/supply/wm8350_power.c
+++ b/drivers/power/supply/wm8350_power.c
@@ -577,7 +577,7 @@ static void wm8350_power_remove(struct platform_device *pdev)
static struct platform_driver wm8350_power_driver = {
.probe = wm8350_power_probe,
- .remove_new = wm8350_power_remove,
+ .remove = wm8350_power_remove,
.driver = {
.name = "wm8350-power",
},
diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
index 1cc38d1437d9..b3b0c37a9dd2 100644
--- a/drivers/power/supply/wm97xx_battery.c
+++ b/drivers/power/supply/wm97xx_battery.c
@@ -265,7 +265,7 @@ static struct platform_driver wm97xx_bat_driver = {
#endif
},
.probe = wm97xx_bat_probe,
- .remove_new = wm97xx_bat_remove,
+ .remove = wm97xx_bat_remove,
};
module_platform_driver(wm97xx_bat_driver);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 84d48e310aa8..8cb948a91e60 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -497,7 +497,8 @@ static int regulator_check_current_limit(struct regulator_dev *rdev,
return -EPERM;
}
- if (*max_uA > rdev->constraints->max_uA)
+ if (*max_uA > rdev->constraints->max_uA &&
+ rdev->constraints->max_uA)
*max_uA = rdev->constraints->max_uA;
if (*min_uA < rdev->constraints->min_uA)
*min_uA = rdev->constraints->min_uA;
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c
index 6c343b4b9d15..7870722b6ee2 100644
--- a/drivers/regulator/qcom-rpmh-regulator.c
+++ b/drivers/regulator/qcom-rpmh-regulator.c
@@ -843,26 +843,15 @@ static const struct rpmh_vreg_hw_data pmic5_ftsmps520 = {
.of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
};
-static const struct rpmh_vreg_hw_data pmic5_ftsmps525_lv = {
+static const struct rpmh_vreg_hw_data pmic5_ftsmps525 = {
.regulator_type = VRM,
.ops = &rpmh_regulator_vrm_ops,
.voltage_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(300000, 0, 267, 4000),
+ REGULATOR_LINEAR_RANGE(1376000, 268, 438, 8000),
},
- .n_linear_ranges = 1,
- .n_voltages = 268,
- .pmic_mode_map = pmic_mode_map_pmic5_smps,
- .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
-};
-
-static const struct rpmh_vreg_hw_data pmic5_ftsmps525_mv = {
- .regulator_type = VRM,
- .ops = &rpmh_regulator_vrm_ops,
- .voltage_ranges = (struct linear_range[]) {
- REGULATOR_LINEAR_RANGE(600000, 0, 267, 8000),
- },
- .n_linear_ranges = 1,
- .n_voltages = 268,
+ .n_linear_ranges = 2,
+ .n_voltages = 439,
.pmic_mode_map = pmic_mode_map_pmic5_smps,
.of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
};
@@ -1190,12 +1179,12 @@ static const struct rpmh_vreg_init_data pm8550_vreg_data[] = {
};
static const struct rpmh_vreg_init_data pm8550vs_vreg_data[] = {
- RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"),
- RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"),
- RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"),
- RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_lv, "vdd-s4"),
- RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"),
- RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_mv, "vdd-s6"),
+ RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525, "vdd-s1"),
+ RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525, "vdd-s2"),
+ RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525, "vdd-s3"),
+ RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525, "vdd-s4"),
+ RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525, "vdd-s5"),
+ RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525, "vdd-s6"),
RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-l1"),
RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo515, "vdd-l2"),
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l3"),
@@ -1203,14 +1192,14 @@ static const struct rpmh_vreg_init_data pm8550vs_vreg_data[] = {
};
static const struct rpmh_vreg_init_data pm8550ve_vreg_data[] = {
- RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"),
- RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"),
- RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"),
- RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_mv, "vdd-s4"),
- RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"),
- RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_lv, "vdd-s6"),
- RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525_lv, "vdd-s7"),
- RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps525_lv, "vdd-s8"),
+ RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525, "vdd-s1"),
+ RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525, "vdd-s2"),
+ RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525, "vdd-s3"),
+ RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525, "vdd-s4"),
+ RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525, "vdd-s5"),
+ RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525, "vdd-s6"),
+ RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525, "vdd-s7"),
+ RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps525, "vdd-s8"),
RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-l1"),
RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo515, "vdd-l2"),
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l3"),
@@ -1218,14 +1207,14 @@ static const struct rpmh_vreg_init_data pm8550ve_vreg_data[] = {
};
static const struct rpmh_vreg_init_data pmc8380_vreg_data[] = {
- RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"),
- RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"),
- RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"),
- RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_mv, "vdd-s4"),
- RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"),
- RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_lv, "vdd-s6"),
- RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525_lv, "vdd-s7"),
- RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps525_lv, "vdd-s8"),
+ RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525, "vdd-s1"),
+ RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525, "vdd-s2"),
+ RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525, "vdd-s3"),
+ RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525, "vdd-s4"),
+ RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525, "vdd-s5"),
+ RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525, "vdd-s6"),
+ RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525, "vdd-s7"),
+ RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps525, "vdd-s8"),
RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-l1"),
RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo515, "vdd-l2"),
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l3"),
@@ -1409,16 +1398,16 @@ static const struct rpmh_vreg_init_data pmx65_vreg_data[] = {
};
static const struct rpmh_vreg_init_data pmx75_vreg_data[] = {
- RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"),
- RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"),
- RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"),
- RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_mv, "vdd-s4"),
- RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"),
- RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_lv, "vdd-s6"),
- RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525_lv, "vdd-s7"),
- RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps525_lv, "vdd-s8"),
- RPMH_VREG("smps9", "smp%s9", &pmic5_ftsmps525_lv, "vdd-s9"),
- RPMH_VREG("smps10", "smp%s10", &pmic5_ftsmps525_lv, "vdd-s10"),
+ RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525, "vdd-s1"),
+ RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525, "vdd-s2"),
+ RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525, "vdd-s3"),
+ RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525, "vdd-s4"),
+ RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525, "vdd-s5"),
+ RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525, "vdd-s6"),
+ RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525, "vdd-s7"),
+ RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps525, "vdd-s8"),
+ RPMH_VREG("smps9", "smp%s9", &pmic5_ftsmps525, "vdd-s9"),
+ RPMH_VREG("smps10", "smp%s10", &pmic5_ftsmps525, "vdd-s10"),
RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-l1"),
RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo515, "vdd-l2-18"),
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l3"),
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 66eb1122248b..a60bcc791a48 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -182,6 +182,16 @@ config RTC_DRV_88PM80X
This driver can also be built as a module. If so, the module
will be called rtc-88pm80x.
+config RTC_DRV_88PM886
+ tristate "Marvell 88PM886 RTC driver"
+ depends on MFD_88PM886_PMIC
+ help
+ If you say yes here you will get support for the RTC function in the
+ Marvell 88PM886 chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-88pm886.
+
config RTC_DRV_ABB5ZES3
select REGMAP_I2C
tristate "Abracon AB-RTCMC-32.768kHz-B5ZE-S3"
@@ -496,6 +506,7 @@ config RTC_DRV_PCF85363
config RTC_DRV_PCF8563
tristate "Philips PCF8563/Epson RTC8564"
+ select REGMAP_I2C
help
If you say yes here you get support for the
Philips PCF8563 RTC chip. The Epson RTC8564
@@ -2005,6 +2016,16 @@ config RTC_DRV_MA35D1
This driver can also be built as a module, if so, the module
will be called "rtc-ma35d1".
+config RTC_DRV_RENESAS_RTCA3
+ tristate "Renesas RTCA-3 RTC"
+ depends on ARCH_RENESAS
+ help
+ If you say yes here you get support for the Renesas RTCA-3 RTC
+ available on the Renesas RZ/G3S SoC.
+
+ This driver can also be built as a module, if so, the module
+ will be called "rtc-rtca3".
+
comment "HID Sensor RTC drivers"
config RTC_DRV_HID_SENSOR_TIME
@@ -2070,4 +2091,16 @@ config RTC_DRV_SSD202D
This driver can also be built as a module, if so, the module
will be called "rtc-ssd20xd".
+config RTC_DRV_AMLOGIC_A4
+ tristate "Amlogic RTC"
+ depends on ARCH_MESON || COMPILE_TEST
+ select REGMAP_MMIO
+ default y
+ help
+ If you say yes here you get support for the RTC block on the
+ Amlogic A113L2(A4) and A113X2(A5) SoCs.
+
+ This driver can also be built as a module. If so, the module
+ will be called "rtc-amlogic-a4".
+
endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index f62340ecc534..489b4ab07068 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -21,11 +21,13 @@ obj-$(CONFIG_RTC_LIB_KUNIT_TEST) += lib_test.o
obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88pm80x.o
obj-$(CONFIG_RTC_DRV_88PM860X) += rtc-88pm860x.o
+obj-$(CONFIG_RTC_DRV_88PM886) += rtc-88pm886.o
obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o
obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o
obj-$(CONFIG_RTC_DRV_ABEOZ9) += rtc-ab-eoz9.o
obj-$(CONFIG_RTC_DRV_ABX80X) += rtc-abx80x.o
obj-$(CONFIG_RTC_DRV_AC100) += rtc-ac100.o
+obj-$(CONFIG_RTC_DRV_AMLOGIC_A4) += rtc-amlogic-a4.o
obj-$(CONFIG_RTC_DRV_ARMADA38X) += rtc-armada38x.o
obj-$(CONFIG_RTC_DRV_AS3722) += rtc-as3722.o
obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o
@@ -158,13 +160,14 @@ obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o
obj-$(CONFIG_RTC_DRV_RX8111) += rtc-rx8111.o
obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
obj-$(CONFIG_RTC_DRV_RZN1) += rtc-rzn1.o
+obj-$(CONFIG_RTC_DRV_RENESAS_RTCA3) += rtc-renesas-rtca3.o
obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o
obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
obj-$(CONFIG_RTC_DRV_S5M) += rtc-s5m.o
obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
obj-$(CONFIG_RTC_DRV_SC27XX) += rtc-sc27xx.o
obj-$(CONFIG_RTC_DRV_SD2405AL) += rtc-sd2405al.o
-obj-$(CONFIG_RTC_DRV_SD3078) += rtc-sd3078.o
+obj-$(CONFIG_RTC_DRV_SD3078) += rtc-sd3078.o
obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o
obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index cca650b2e0b9..aaf76406cd7d 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -904,13 +904,18 @@ void rtc_timer_do_work(struct work_struct *work)
struct timerqueue_node *next;
ktime_t now;
struct rtc_time tm;
+ int err;
struct rtc_device *rtc =
container_of(work, struct rtc_device, irqwork);
mutex_lock(&rtc->ops_lock);
again:
- __rtc_read_time(rtc, &tm);
+ err = __rtc_read_time(rtc, &tm);
+ if (err) {
+ mutex_unlock(&rtc->ops_lock);
+ return;
+ }
now = rtc_tm_to_ktime(tm);
while ((next = timerqueue_getnext(&rtc->timerqueue))) {
if (next->expires > now)
diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c
index f40cc06b0979..5c39cf252392 100644
--- a/drivers/rtc/rtc-88pm80x.c
+++ b/drivers/rtc/rtc-88pm80x.c
@@ -329,7 +329,7 @@ static struct platform_driver pm80x_rtc_driver = {
.pm = &pm80x_rtc_pm_ops,
},
.probe = pm80x_rtc_probe,
- .remove_new = pm80x_rtc_remove,
+ .remove = pm80x_rtc_remove,
};
module_platform_driver(pm80x_rtc_driver);
diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c
index 0f124ed5b3e5..814230d61842 100644
--- a/drivers/rtc/rtc-88pm860x.c
+++ b/drivers/rtc/rtc-88pm860x.c
@@ -371,7 +371,7 @@ static struct platform_driver pm860x_rtc_driver = {
.pm = &pm860x_rtc_pm_ops,
},
.probe = pm860x_rtc_probe,
- .remove_new = pm860x_rtc_remove,
+ .remove = pm860x_rtc_remove,
};
module_platform_driver(pm860x_rtc_driver);
diff --git a/drivers/rtc/rtc-88pm886.c b/drivers/rtc/rtc-88pm886.c
new file mode 100644
index 000000000000..57e9b0a66eed
--- /dev/null
+++ b/drivers/rtc/rtc-88pm886.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/limits.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+#include <linux/mfd/88pm886.h>
+
+/*
+ * Time is calculated as the sum of a 32-bit read-only advancing counter and a
+ * writeable constant offset stored in the chip's spare registers.
+ */
+
+static int pm886_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct regmap *regmap = dev_get_drvdata(dev);
+ u32 time;
+ u32 buf;
+ int ret;
+
+ ret = regmap_bulk_read(regmap, PM886_REG_RTC_SPARE1, &buf, 4);
+ if (ret)
+ return ret;
+ time = buf;
+
+ ret = regmap_bulk_read(regmap, PM886_REG_RTC_CNT1, &buf, 4);
+ if (ret)
+ return ret;
+ time += buf;
+
+ rtc_time64_to_tm(time, tm);
+
+ return 0;
+}
+
+static int pm886_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct regmap *regmap = dev_get_drvdata(dev);
+ u32 buf;
+ int ret;
+
+ ret = regmap_bulk_read(regmap, PM886_REG_RTC_CNT1, &buf, 4);
+ if (ret)
+ return ret;
+
+ buf = rtc_tm_to_time64(tm) - buf;
+
+ return regmap_bulk_write(regmap, PM886_REG_RTC_SPARE1, &buf, 4);
+}
+
+static const struct rtc_class_ops pm886_rtc_ops = {
+ .read_time = pm886_rtc_read_time,
+ .set_time = pm886_rtc_set_time,
+};
+
+static int pm886_rtc_probe(struct platform_device *pdev)
+{
+ struct pm886_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct device *dev = &pdev->dev;
+ struct rtc_device *rtc;
+ int ret;
+
+ platform_set_drvdata(pdev, chip->regmap);
+
+ rtc = devm_rtc_allocate_device(dev);
+ if (IS_ERR(rtc))
+ return dev_err_probe(dev, PTR_ERR(rtc),
+ "Failed to allocate RTC device\n");
+
+ rtc->ops = &pm886_rtc_ops;
+ rtc->range_max = U32_MAX;
+
+ ret = devm_rtc_register_device(rtc);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register RTC device\n");
+
+ return 0;
+}
+
+static const struct platform_device_id pm886_rtc_id_table[] = {
+ { "88pm886-rtc", },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, pm886_rtc_id_table);
+
+static struct platform_driver pm886_rtc_driver = {
+ .driver = {
+ .name = "88pm886-rtc",
+ },
+ .probe = pm886_rtc_probe,
+ .id_table = pm886_rtc_id_table,
+};
+module_platform_driver(pm886_rtc_driver);
+
+MODULE_DESCRIPTION("Marvell 88PM886 RTC driver");
+MODULE_AUTHOR("Karel Balej <balejk@matfyz.cz>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c
index 02f7d0711287..d2b60487d462 100644
--- a/drivers/rtc/rtc-ab-eoz9.c
+++ b/drivers/rtc/rtc-ab-eoz9.c
@@ -64,7 +64,7 @@
#define ABEOZ9_BIT_ALARM_MIN GENMASK(6, 0)
#define ABEOZ9_REG_ALARM_HOURS 0x12
#define ABEOZ9_BIT_ALARM_HOURS_PM BIT(5)
-#define ABEOZ9_BIT_ALARM_HOURS GENMASK(4, 0)
+#define ABEOZ9_BIT_ALARM_HOURS GENMASK(5, 0)
#define ABEOZ9_REG_ALARM_DAYS 0x13
#define ABEOZ9_BIT_ALARM_DAYS GENMASK(5, 0)
#define ABEOZ9_REG_ALARM_WEEKDAYS 0x14
@@ -231,8 +231,6 @@ static int abeoz9_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
alarm->time.tm_sec = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_SEC, regs[0]));
alarm->time.tm_min = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_MIN, regs[1]));
alarm->time.tm_hour = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_HOURS, regs[2]));
- if (FIELD_GET(ABEOZ9_BIT_ALARM_HOURS_PM, regs[2]))
- alarm->time.tm_hour += 12;
alarm->time.tm_mday = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_DAYS, regs[3]));
@@ -396,13 +394,6 @@ static int abeoz9z3_temp_read(struct device *dev,
if (ret < 0)
return ret;
- if ((val & ABEOZ9_REG_CTRL_STATUS_V1F) ||
- (val & ABEOZ9_REG_CTRL_STATUS_V2F)) {
- dev_err(dev,
- "thermometer might be disabled due to low voltage\n");
- return -EINVAL;
- }
-
switch (attr) {
case hwmon_temp_input:
ret = regmap_read(regmap, ABEOZ9_REG_REG_TEMP, &val);
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c
index 75bb2ac9005c..2dcda96f4a8e 100644
--- a/drivers/rtc/rtc-ab8500.c
+++ b/drivers/rtc/rtc-ab8500.c
@@ -403,7 +403,7 @@ static struct platform_driver ab8500_rtc_driver = {
.name = "ab8500-rtc",
},
.probe = ab8500_rtc_probe,
- .remove_new = ab8500_rtc_remove,
+ .remove = ab8500_rtc_remove,
.id_table = ab85xx_rtc_ids,
};
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index 1298962402ff..3fee27914ba8 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -39,7 +39,7 @@
#define ABX8XX_REG_STATUS 0x0f
#define ABX8XX_STATUS_AF BIT(2)
#define ABX8XX_STATUS_BLF BIT(4)
-#define ABX8XX_STATUS_WDT BIT(6)
+#define ABX8XX_STATUS_WDT BIT(5)
#define ABX8XX_REG_CTRL1 0x10
#define ABX8XX_CTRL_WRITE BIT(0)
diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c
index fa642bba3cee..33626311fa78 100644
--- a/drivers/rtc/rtc-ac100.c
+++ b/drivers/rtc/rtc-ac100.c
@@ -628,7 +628,7 @@ MODULE_DEVICE_TABLE(of, ac100_rtc_match);
static struct platform_driver ac100_rtc_driver = {
.probe = ac100_rtc_probe,
- .remove_new = ac100_rtc_remove,
+ .remove = ac100_rtc_remove,
.driver = {
.name = "ac100-rtc",
.of_match_table = of_match_ptr(ac100_rtc_match),
diff --git a/drivers/rtc/rtc-amlogic-a4.c b/drivers/rtc/rtc-amlogic-a4.c
new file mode 100644
index 000000000000..2278b4c98a71
--- /dev/null
+++ b/drivers/rtc/rtc-amlogic-a4.c
@@ -0,0 +1,465 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Copyright (C) 2024 Amlogic, Inc. All rights reserved
+ * Author: Yiting Deng <yiting.deng@amlogic.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/time64.h>
+
+/* rtc oscillator rate */
+#define OSC_32K 32768
+#define OSC_24M 24000000
+
+#define RTC_CTRL (0x0 << 2) /* Control RTC */
+#define RTC_ALRM0_EN BIT(0)
+#define RTC_OSC_SEL BIT(8)
+#define RTC_ENABLE BIT(12)
+
+#define RTC_COUNTER_REG (0x1 << 2) /* Program RTC counter initial value */
+
+#define RTC_ALARM0_REG (0x2 << 2) /* Program RTC alarm0 value */
+
+#define RTC_SEC_ADJUST_REG (0x6 << 2) /* Control second-based timing adjustment */
+#define RTC_MATCH_COUNTER GENMASK(18, 0)
+#define RTC_SEC_ADJUST_CTRL GENMASK(20, 19)
+#define RTC_ADJ_VALID BIT(23)
+
+#define RTC_INT_MASK (0x8 << 2) /* RTC interrupt mask */
+#define RTC_ALRM0_IRQ_MSK BIT(0)
+
+#define RTC_INT_CLR (0x9 << 2) /* Clear RTC interrupt */
+#define RTC_ALRM0_IRQ_CLR BIT(0)
+
+#define RTC_OSCIN_CTRL0 (0xa << 2) /* Control RTC clk from 24M */
+#define RTC_OSCIN_CTRL1 (0xb << 2) /* Control RTC clk from 24M */
+#define RTC_OSCIN_IN_EN BIT(31)
+#define RTC_OSCIN_OUT_CFG GENMASK(29, 28)
+#define RTC_OSCIN_OUT_N0M0 GENMASK(11, 0)
+#define RTC_OSCIN_OUT_N1M1 GENMASK(23, 12)
+
+#define RTC_INT_STATUS (0xc << 2) /* RTC interrupt status */
+#define RTC_ALRM0_IRQ_STATUS BIT(0)
+
+#define RTC_REAL_TIME (0xd << 2) /* RTC time value */
+
+#define RTC_OSCIN_OUT_32K_N0 0x2dc
+#define RTC_OSCIN_OUT_32K_N1 0x2db
+#define RTC_OSCIN_OUT_32K_M0 0x1
+#define RTC_OSCIN_OUT_32K_M1 0x2
+
+#define RTC_SWALLOW_SECOND 0x2
+#define RTC_INSERT_SECOND 0x3
+
+struct aml_rtc_config {
+ bool gray_stored;
+};
+
+struct aml_rtc_data {
+ struct regmap *map;
+ struct rtc_device *rtc_dev;
+ int irq;
+ struct clk *rtc_clk;
+ struct clk *sys_clk;
+ int rtc_enabled;
+ const struct aml_rtc_config *config;
+};
+
+static const struct regmap_config aml_rtc_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = RTC_REAL_TIME,
+};
+
+static inline u32 gray_to_binary(u32 gray)
+{
+ u32 bcd = gray;
+ int size = sizeof(bcd) * 8;
+ int i;
+
+ for (i = 0; (1 << i) < size; i++)
+ bcd ^= bcd >> (1 << i);
+
+ return bcd;
+}
+
+static inline u32 binary_to_gray(u32 bcd)
+{
+ return bcd ^ (bcd >> 1);
+}
+
+static int aml_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+ u32 time_sec;
+
+ /* if RTC disabled, read time failed */
+ if (!rtc->rtc_enabled)
+ return -EINVAL;
+
+ regmap_read(rtc->map, RTC_REAL_TIME, &time_sec);
+ if (rtc->config->gray_stored)
+ time_sec = gray_to_binary(time_sec);
+ rtc_time64_to_tm(time_sec, tm);
+ dev_dbg(dev, "%s: read time = %us\n", __func__, time_sec);
+
+ return 0;
+}
+
+static int aml_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+ u32 time_sec;
+
+ /* if RTC disabled, first enable it */
+ if (!rtc->rtc_enabled) {
+ regmap_write_bits(rtc->map, RTC_CTRL, RTC_ENABLE, RTC_ENABLE);
+ usleep_range(100, 200);
+ rtc->rtc_enabled = regmap_test_bits(rtc->map, RTC_CTRL, RTC_ENABLE);
+ if (!rtc->rtc_enabled)
+ return -EINVAL;
+ }
+
+ time_sec = rtc_tm_to_time64(tm);
+ if (rtc->config->gray_stored)
+ time_sec = binary_to_gray(time_sec);
+ regmap_write(rtc->map, RTC_COUNTER_REG, time_sec);
+ dev_dbg(dev, "%s: set time = %us\n", __func__, time_sec);
+
+ return 0;
+}
+
+static int aml_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+ time64_t alarm_sec;
+
+ /* if RTC disabled, set alarm failed */
+ if (!rtc->rtc_enabled)
+ return -EINVAL;
+
+ regmap_update_bits(rtc->map, RTC_CTRL,
+ RTC_ALRM0_EN, RTC_ALRM0_EN);
+ regmap_update_bits(rtc->map, RTC_INT_MASK,
+ RTC_ALRM0_IRQ_MSK, 0);
+
+ alarm_sec = rtc_tm_to_time64(&alarm->time);
+ if (rtc->config->gray_stored)
+ alarm_sec = binary_to_gray(alarm_sec);
+ regmap_write(rtc->map, RTC_ALARM0_REG, alarm_sec);
+
+ dev_dbg(dev, "%s: alarm->enabled=%d alarm_set=%llds\n", __func__,
+ alarm->enabled, alarm_sec);
+
+ return 0;
+}
+
+static int aml_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+ u32 alarm_sec;
+ int alarm_enable;
+ int alarm_mask;
+
+ /* if RTC disabled, read alarm failed */
+ if (!rtc->rtc_enabled)
+ return -EINVAL;
+
+ regmap_read(rtc->map, RTC_ALARM0_REG, &alarm_sec);
+ if (rtc->config->gray_stored)
+ alarm_sec = gray_to_binary(alarm_sec);
+ rtc_time64_to_tm(alarm_sec, &alarm->time);
+
+ alarm_enable = regmap_test_bits(rtc->map, RTC_CTRL, RTC_ALRM0_EN);
+ alarm_mask = regmap_test_bits(rtc->map, RTC_INT_MASK, RTC_ALRM0_IRQ_MSK);
+ alarm->enabled = (alarm_enable && !alarm_mask) ? 1 : 0;
+ dev_dbg(dev, "%s: alarm->enabled=%d alarm=%us\n", __func__,
+ alarm->enabled, alarm_sec);
+
+ return 0;
+}
+
+static int aml_rtc_read_offset(struct device *dev, long *offset)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+ u32 reg_val;
+ long val;
+ int sign, match_counter, enable;
+
+ /* if RTC disabled, read offset failed */
+ if (!rtc->rtc_enabled)
+ return -EINVAL;
+
+ regmap_read(rtc->map, RTC_SEC_ADJUST_REG, &reg_val);
+ enable = FIELD_GET(RTC_ADJ_VALID, reg_val);
+ if (!enable) {
+ val = 0;
+ } else {
+ sign = FIELD_GET(RTC_SEC_ADJUST_CTRL, reg_val);
+ match_counter = FIELD_GET(RTC_MATCH_COUNTER, reg_val);
+ val = 1000000000 / (match_counter + 1);
+ if (sign == RTC_SWALLOW_SECOND)
+ val = -val;
+ }
+ *offset = val;
+
+ return 0;
+}
+
+static int aml_rtc_set_offset(struct device *dev, long offset)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+ int sign = 0;
+ int match_counter = 0;
+ int enable = 0;
+ u32 reg_val;
+
+ /* if RTC disabled, set offset failed */
+ if (!rtc->rtc_enabled)
+ return -EINVAL;
+
+ if (offset) {
+ enable = 1;
+ sign = offset < 0 ? RTC_SWALLOW_SECOND : RTC_INSERT_SECOND;
+ match_counter = 1000000000 / abs(offset) - 1;
+ if (match_counter < 0 || match_counter > RTC_MATCH_COUNTER)
+ return -EINVAL;
+ }
+
+ reg_val = FIELD_PREP(RTC_ADJ_VALID, enable) |
+ FIELD_PREP(RTC_SEC_ADJUST_CTRL, sign) |
+ FIELD_PREP(RTC_MATCH_COUNTER, match_counter);
+ regmap_write(rtc->map, RTC_SEC_ADJUST_REG, reg_val);
+
+ return 0;
+}
+
+static int aml_rtc_alarm_enable(struct device *dev, unsigned int enabled)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+
+ if (enabled) {
+ regmap_update_bits(rtc->map, RTC_CTRL,
+ RTC_ALRM0_EN, RTC_ALRM0_EN);
+ regmap_update_bits(rtc->map, RTC_INT_MASK,
+ RTC_ALRM0_IRQ_MSK, 0);
+ } else {
+ regmap_update_bits(rtc->map, RTC_INT_MASK,
+ RTC_ALRM0_IRQ_MSK, RTC_ALRM0_IRQ_MSK);
+ regmap_update_bits(rtc->map, RTC_CTRL,
+ RTC_ALRM0_EN, 0);
+ }
+
+ return 0;
+}
+
+static const struct rtc_class_ops aml_rtc_ops = {
+ .read_time = aml_rtc_read_time,
+ .set_time = aml_rtc_set_time,
+ .read_alarm = aml_rtc_read_alarm,
+ .set_alarm = aml_rtc_set_alarm,
+ .alarm_irq_enable = aml_rtc_alarm_enable,
+ .read_offset = aml_rtc_read_offset,
+ .set_offset = aml_rtc_set_offset,
+};
+
+static irqreturn_t aml_rtc_handler(int irq, void *data)
+{
+ struct aml_rtc_data *rtc = (struct aml_rtc_data *)data;
+
+ regmap_write(rtc->map, RTC_ALARM0_REG, 0);
+ regmap_write(rtc->map, RTC_INT_CLR, RTC_ALRM0_IRQ_STATUS);
+
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+
+ return IRQ_HANDLED;
+}
+
+static void aml_rtc_init(struct aml_rtc_data *rtc)
+{
+ u32 reg_val = 0;
+
+ rtc->rtc_enabled = regmap_test_bits(rtc->map, RTC_CTRL, RTC_ENABLE);
+ if (!rtc->rtc_enabled) {
+ if (clk_get_rate(rtc->rtc_clk) == OSC_24M) {
+ /* select 24M oscillator */
+ regmap_write_bits(rtc->map, RTC_CTRL, RTC_OSC_SEL, RTC_OSC_SEL);
+
+ /*
+ * Set RTC oscillator to freq_out to freq_in/((N0*M0+N1*M1)/(M0+M1))
+ * Enable clock_in gate of oscillator 24MHz
+ * Set N0 to 733, N1 to 732
+ */
+ reg_val = FIELD_PREP(RTC_OSCIN_IN_EN, 1)
+ | FIELD_PREP(RTC_OSCIN_OUT_CFG, 1)
+ | FIELD_PREP(RTC_OSCIN_OUT_N0M0, RTC_OSCIN_OUT_32K_N0)
+ | FIELD_PREP(RTC_OSCIN_OUT_N1M1, RTC_OSCIN_OUT_32K_N1);
+ regmap_write_bits(rtc->map, RTC_OSCIN_CTRL0, RTC_OSCIN_IN_EN
+ | RTC_OSCIN_OUT_CFG | RTC_OSCIN_OUT_N0M0
+ | RTC_OSCIN_OUT_N1M1, reg_val);
+
+ /* Set M0 to 2, M1 to 3, so freq_out = 32768 Hz*/
+ reg_val = FIELD_PREP(RTC_OSCIN_OUT_N0M0, RTC_OSCIN_OUT_32K_M0)
+ | FIELD_PREP(RTC_OSCIN_OUT_N1M1, RTC_OSCIN_OUT_32K_M1);
+ regmap_write_bits(rtc->map, RTC_OSCIN_CTRL1, RTC_OSCIN_OUT_N0M0
+ | RTC_OSCIN_OUT_N1M1, reg_val);
+ } else {
+ /* select 32K oscillator */
+ regmap_write_bits(rtc->map, RTC_CTRL, RTC_OSC_SEL, 0);
+ }
+ }
+ regmap_write_bits(rtc->map, RTC_INT_MASK,
+ RTC_ALRM0_IRQ_MSK, RTC_ALRM0_IRQ_MSK);
+ regmap_write_bits(rtc->map, RTC_CTRL, RTC_ALRM0_EN, 0);
+}
+
+static int aml_rtc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct aml_rtc_data *rtc;
+ void __iomem *base;
+ int ret = 0;
+
+ rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ rtc->config = of_device_get_match_data(dev);
+ if (!rtc->config)
+ return -ENODEV;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return dev_err_probe(dev, PTR_ERR(base), "resource ioremap failed\n");
+
+ rtc->map = devm_regmap_init_mmio(dev, base, &aml_rtc_regmap_config);
+ if (IS_ERR(rtc->map))
+ return dev_err_probe(dev, PTR_ERR(rtc->map), "regmap init failed\n");
+
+ rtc->irq = platform_get_irq(pdev, 0);
+ if (rtc->irq < 0)
+ return rtc->irq;
+
+ rtc->rtc_clk = devm_clk_get(dev, "osc");
+ if (IS_ERR(rtc->rtc_clk))
+ return dev_err_probe(dev, PTR_ERR(rtc->rtc_clk),
+ "failed to find rtc clock\n");
+ if (clk_get_rate(rtc->rtc_clk) != OSC_32K && clk_get_rate(rtc->rtc_clk) != OSC_24M)
+ return dev_err_probe(dev, -EINVAL, "Invalid clock configuration\n");
+
+ rtc->sys_clk = devm_clk_get_enabled(dev, "sys");
+ if (IS_ERR(rtc->sys_clk))
+ return dev_err_probe(dev, PTR_ERR(rtc->sys_clk),
+ "failed to get_enable rtc sys clk\n");
+ aml_rtc_init(rtc);
+
+ device_init_wakeup(dev, 1);
+ platform_set_drvdata(pdev, rtc);
+
+ rtc->rtc_dev = devm_rtc_allocate_device(dev);
+ if (IS_ERR(rtc->rtc_dev)) {
+ ret = PTR_ERR(rtc->rtc_dev);
+ goto err_clk;
+ }
+
+ ret = devm_request_irq(dev, rtc->irq, aml_rtc_handler,
+ IRQF_ONESHOT, "aml-rtc alarm", rtc);
+ if (ret) {
+ dev_err_probe(dev, ret, "IRQ%d request failed, ret = %d\n",
+ rtc->irq, ret);
+ goto err_clk;
+ }
+
+ rtc->rtc_dev->ops = &aml_rtc_ops;
+ rtc->rtc_dev->range_min = 0;
+ rtc->rtc_dev->range_max = U32_MAX;
+
+ ret = devm_rtc_register_device(rtc->rtc_dev);
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "Failed to register RTC device: %d\n", ret);
+ goto err_clk;
+ }
+
+ return 0;
+err_clk:
+ clk_disable_unprepare(rtc->sys_clk);
+ device_init_wakeup(dev, 0);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int aml_rtc_suspend(struct device *dev)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(rtc->irq);
+
+ return 0;
+}
+
+static int aml_rtc_resume(struct device *dev)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(rtc->irq);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(aml_rtc_pm_ops,
+ aml_rtc_suspend, aml_rtc_resume);
+
+static void aml_rtc_remove(struct platform_device *pdev)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(&pdev->dev);
+
+ clk_disable_unprepare(rtc->sys_clk);
+ device_init_wakeup(&pdev->dev, 0);
+}
+
+static const struct aml_rtc_config a5_rtc_config = {
+};
+
+static const struct aml_rtc_config a4_rtc_config = {
+ .gray_stored = true,
+};
+
+static const struct of_device_id aml_rtc_device_id[] = {
+ {
+ .compatible = "amlogic,a4-rtc",
+ .data = &a4_rtc_config,
+ },
+ {
+ .compatible = "amlogic,a5-rtc",
+ .data = &a5_rtc_config,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, aml_rtc_device_id);
+
+static struct platform_driver aml_rtc_driver = {
+ .probe = aml_rtc_probe,
+ .remove = aml_rtc_remove,
+ .driver = {
+ .name = "aml-rtc",
+ .pm = &aml_rtc_pm_ops,
+ .of_match_table = aml_rtc_device_id,
+ },
+};
+
+module_platform_driver(aml_rtc_driver);
+MODULE_DESCRIPTION("Amlogic RTC driver");
+MODULE_AUTHOR("Yiting Deng <yiting.deng@amlogic.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-asm9260.c b/drivers/rtc/rtc-asm9260.c
index a83b47e0d8f5..705470ae8428 100644
--- a/drivers/rtc/rtc-asm9260.c
+++ b/drivers/rtc/rtc-asm9260.c
@@ -325,7 +325,7 @@ MODULE_DEVICE_TABLE(of, asm9260_dt_ids);
static struct platform_driver asm9260_rtc_driver = {
.probe = asm9260_rtc_probe,
- .remove_new = asm9260_rtc_remove,
+ .remove = asm9260_rtc_remove,
.driver = {
.name = "asm9260-rtc",
.of_match_table = asm9260_dt_ids,
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index c16fe711a0d9..9b3898b8de7c 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -640,7 +640,7 @@ static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume);
* triggering a section mismatch warning.
*/
static struct platform_driver at91_rtc_driver __refdata = {
- .remove_new = __exit_p(at91_rtc_remove),
+ .remove = __exit_p(at91_rtc_remove),
.shutdown = at91_rtc_shutdown,
.driver = {
.name = "at91_rtc",
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 993c0878fb66..15b21da2788f 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -530,7 +530,7 @@ MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids);
static struct platform_driver at91_rtc_driver = {
.probe = at91_rtc_probe,
- .remove_new = at91_rtc_remove,
+ .remove = at91_rtc_remove,
.shutdown = at91_rtc_shutdown,
.driver = {
.name = "rtc-at91sam9",
diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c
index 1a65a4e0dc00..fb47c32ab5ff 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -17,7 +17,6 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
-#include <linux/pm_wakeup.h>
#include <linux/reboot.h>
#include <linux/rtc.h>
#include <linux/stat.h>
@@ -417,7 +416,7 @@ static const __maybe_unused struct of_device_id brcmstb_waketmr_of_match[] = {
static struct platform_driver brcmstb_waketmr_driver = {
.probe = brcmstb_waketmr_probe,
- .remove_new = brcmstb_waketmr_remove,
+ .remove = brcmstb_waketmr_remove,
.driver = {
.name = "brcmstb-waketimer",
.pm = &brcmstb_waketmr_pm_ops,
diff --git a/drivers/rtc/rtc-cadence.c b/drivers/rtc/rtc-cadence.c
index 4ca60b519836..bf2a9a1fdea7 100644
--- a/drivers/rtc/rtc-cadence.c
+++ b/drivers/rtc/rtc-cadence.c
@@ -402,7 +402,7 @@ static struct platform_driver cdns_rtc_driver = {
.pm = &cdns_rtc_pm_ops,
},
.probe = cdns_rtc_probe,
- .remove_new = cdns_rtc_remove,
+ .remove = cdns_rtc_remove,
};
module_platform_driver(cdns_rtc_driver);
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 35dca2accbb8..78f2ce12c75a 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -645,18 +645,17 @@ static int cmos_nvram_read(void *priv, unsigned int off, void *val,
unsigned char *buf = val;
off += NVRAM_OFFSET;
- spin_lock_irq(&rtc_lock);
- for (; count; count--, off++) {
+ for (; count; count--, off++, buf++) {
+ guard(spinlock_irq)(&rtc_lock);
if (off < 128)
- *buf++ = CMOS_READ(off);
+ *buf = CMOS_READ(off);
else if (can_bank2)
- *buf++ = cmos_read_bank2(off);
+ *buf = cmos_read_bank2(off);
else
- break;
+ return -EIO;
}
- spin_unlock_irq(&rtc_lock);
- return count ? -EIO : 0;
+ return 0;
}
static int cmos_nvram_write(void *priv, unsigned int off, void *val,
@@ -671,23 +670,23 @@ static int cmos_nvram_write(void *priv, unsigned int off, void *val,
* NVRAM to update, updating checksums is also part of its job.
*/
off += NVRAM_OFFSET;
- spin_lock_irq(&rtc_lock);
- for (; count; count--, off++) {
+ for (; count; count--, off++, buf++) {
/* don't trash RTC registers */
if (off == cmos->day_alrm
|| off == cmos->mon_alrm
|| off == cmos->century)
- buf++;
- else if (off < 128)
- CMOS_WRITE(*buf++, off);
+ continue;
+
+ guard(spinlock_irq)(&rtc_lock);
+ if (off < 128)
+ CMOS_WRITE(*buf, off);
else if (can_bank2)
- cmos_write_bank2(*buf++, off);
+ cmos_write_bank2(*buf, off);
else
- break;
+ return -EIO;
}
- spin_unlock_irq(&rtc_lock);
- return count ? -EIO : 0;
+ return 0;
}
/*----------------------------------------------------------------*/
@@ -1528,7 +1527,7 @@ static void cmos_platform_shutdown(struct platform_device *pdev)
MODULE_ALIAS("platform:rtc_cmos");
static struct platform_driver cmos_platform_driver = {
- .remove_new = cmos_platform_remove,
+ .remove = cmos_platform_remove,
.shutdown = cmos_platform_shutdown,
.driver = {
.name = driver_name,
diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c
index f57462c7b2c6..60a48c3ba3ca 100644
--- a/drivers/rtc/rtc-cros-ec.c
+++ b/drivers/rtc/rtc-cros-ec.c
@@ -401,7 +401,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_rtc_id);
static struct platform_driver cros_ec_rtc_driver = {
.probe = cros_ec_rtc_probe,
- .remove_new = cros_ec_rtc_remove,
+ .remove = cros_ec_rtc_remove,
.driver = {
.name = DRV_NAME,
.pm = &cros_ec_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c
index 04dbf35cf3b7..38e25f63597a 100644
--- a/drivers/rtc/rtc-ds1685.c
+++ b/drivers/rtc/rtc-ds1685.c
@@ -1354,7 +1354,7 @@ static struct platform_driver ds1685_rtc_driver = {
.name = "rtc-ds1685",
},
.probe = ds1685_rtc_probe,
- .remove_new = ds1685_rtc_remove,
+ .remove = ds1685_rtc_remove,
};
module_platform_driver(ds1685_rtc_driver);
/* ----------------------------------------------------------------------- */
diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c
index 8bfe7378f653..cb4a5d101f53 100644
--- a/drivers/rtc/rtc-ftrtc010.c
+++ b/drivers/rtc/rtc-ftrtc010.c
@@ -214,7 +214,7 @@ static struct platform_driver ftrtc010_rtc_driver = {
.of_match_table = ftrtc010_rtc_dt_match,
},
.probe = ftrtc010_rtc_probe,
- .remove_new = ftrtc010_rtc_remove,
+ .remove = ftrtc010_rtc_remove,
};
module_platform_driver_probe(ftrtc010_rtc_driver, ftrtc010_rtc_probe);
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
index b81cea505ee9..e30f80dc9319 100644
--- a/drivers/rtc/rtc-hid-sensor-time.c
+++ b/drivers/rtc/rtc-hid-sensor-time.c
@@ -319,7 +319,7 @@ static struct platform_driver hid_time_platform_driver = {
.name = KBUILD_MODNAME,
},
.probe = hid_time_probe,
- .remove_new = hid_time_remove,
+ .remove = hid_time_remove,
};
module_platform_driver(hid_time_platform_driver);
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c
index 284011c419db..ca4a0af95e8c 100644
--- a/drivers/rtc/rtc-imxdi.c
+++ b/drivers/rtc/rtc-imxdi.c
@@ -860,7 +860,7 @@ static struct platform_driver dryice_rtc_driver __refdata = {
.name = "imxdi_rtc",
.of_match_table = dryice_dt_ids,
},
- .remove_new = __exit_p(dryice_rtc_remove),
+ .remove = __exit_p(dryice_rtc_remove),
};
module_platform_driver_probe(dryice_rtc_driver, dryice_rtc_probe);
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c
index 6fa9a68af9d9..9b44839a7402 100644
--- a/drivers/rtc/rtc-isl12022.c
+++ b/drivers/rtc/rtc-isl12022.c
@@ -21,7 +21,7 @@
#include <asm/byteorder.h>
-/* ISL register offsets */
+/* RTC - Real time clock registers */
#define ISL12022_REG_SC 0x00
#define ISL12022_REG_MN 0x01
#define ISL12022_REG_HR 0x02
@@ -30,21 +30,36 @@
#define ISL12022_REG_YR 0x05
#define ISL12022_REG_DW 0x06
+/* CSR - Control and status registers */
#define ISL12022_REG_SR 0x07
#define ISL12022_REG_INT 0x08
-
#define ISL12022_REG_PWR_VBAT 0x0a
-
#define ISL12022_REG_BETA 0x0d
+
+/* ALARM - Alarm registers */
+#define ISL12022_REG_SCA0 0x10
+#define ISL12022_REG_MNA0 0x11
+#define ISL12022_REG_HRA0 0x12
+#define ISL12022_REG_DTA0 0x13
+#define ISL12022_REG_MOA0 0x14
+#define ISL12022_REG_DWA0 0x15
+#define ISL12022_ALARM ISL12022_REG_SCA0
+#define ISL12022_ALARM_LEN (ISL12022_REG_DWA0 - ISL12022_REG_SCA0 + 1)
+
+/* TEMP - Temperature sensor registers */
#define ISL12022_REG_TEMP_L 0x28
/* ISL register bits */
#define ISL12022_HR_MIL (1 << 7) /* military or 24 hour time */
+#define ISL12022_SR_ALM (1 << 4)
#define ISL12022_SR_LBAT85 (1 << 2)
#define ISL12022_SR_LBAT75 (1 << 1)
+#define ISL12022_INT_ARST (1 << 7)
#define ISL12022_INT_WRTC (1 << 6)
+#define ISL12022_INT_IM (1 << 5)
+#define ISL12022_INT_FOBATB (1 << 4)
#define ISL12022_INT_FO_MASK GENMASK(3, 0)
#define ISL12022_INT_FO_OFF 0x0
#define ISL12022_INT_FO_32K 0x1
@@ -52,8 +67,19 @@
#define ISL12022_REG_VB85_MASK GENMASK(5, 3)
#define ISL12022_REG_VB75_MASK GENMASK(2, 0)
+#define ISL12022_ALARM_ENABLE (1 << 7) /* for all ALARM registers */
+
#define ISL12022_BETA_TSE (1 << 7)
+static struct i2c_driver isl12022_driver;
+
+struct isl12022 {
+ struct rtc_device *rtc;
+ struct regmap *regmap;
+ int irq;
+ bool irq_enabled;
+};
+
static umode_t isl12022_hwmon_is_visible(const void *data,
enum hwmon_sensor_types type,
u32 attr, int channel)
@@ -116,7 +142,8 @@ static const struct hwmon_chip_info isl12022_hwmon_chip_info = {
static void isl12022_hwmon_register(struct device *dev)
{
- struct regmap *regmap = dev_get_drvdata(dev);
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
struct device *hwmon;
int ret;
@@ -143,8 +170,9 @@ static void isl12022_hwmon_register(struct device *dev)
*/
static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct regmap *regmap = dev_get_drvdata(dev);
- uint8_t buf[ISL12022_REG_INT + 1];
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
+ u8 buf[ISL12022_REG_INT + 1];
int ret;
ret = regmap_bulk_read(regmap, ISL12022_REG_SC, buf, sizeof(buf));
@@ -178,9 +206,10 @@ static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct regmap *regmap = dev_get_drvdata(dev);
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
int ret;
- uint8_t buf[ISL12022_REG_DW + 1];
+ u8 buf[ISL12022_REG_DW + 1];
dev_dbg(dev, "%s: %ptR\n", __func__, tm);
@@ -208,9 +237,198 @@ static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
return regmap_bulk_write(regmap, ISL12022_REG_SC, buf, sizeof(buf));
}
+static int isl12022_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct rtc_time *tm = &alarm->time;
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
+ u8 buf[ISL12022_ALARM_LEN];
+ unsigned int i, yr;
+ int ret;
+
+ ret = regmap_bulk_read(regmap, ISL12022_ALARM, buf, sizeof(buf));
+ if (ret) {
+ dev_dbg(dev, "%s: reading ALARM registers failed\n",
+ __func__);
+ return ret;
+ }
+
+ /* The alarm doesn't store the year so get it from the rtc section */
+ ret = regmap_read(regmap, ISL12022_REG_YR, &yr);
+ if (ret) {
+ dev_dbg(dev, "%s: reading YR register failed\n", __func__);
+ return ret;
+ }
+
+ dev_dbg(dev,
+ "%s: sc=%02x, mn=%02x, hr=%02x, dt=%02x, mo=%02x, dw=%02x yr=%u\n",
+ __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], yr);
+
+ tm->tm_sec = bcd2bin(buf[ISL12022_REG_SCA0 - ISL12022_ALARM] & 0x7F);
+ tm->tm_min = bcd2bin(buf[ISL12022_REG_MNA0 - ISL12022_ALARM] & 0x7F);
+ tm->tm_hour = bcd2bin(buf[ISL12022_REG_HRA0 - ISL12022_ALARM] & 0x3F);
+ tm->tm_mday = bcd2bin(buf[ISL12022_REG_DTA0 - ISL12022_ALARM] & 0x3F);
+ tm->tm_mon = bcd2bin(buf[ISL12022_REG_MOA0 - ISL12022_ALARM] & 0x1F) - 1;
+ tm->tm_wday = buf[ISL12022_REG_DWA0 - ISL12022_ALARM] & 0x07;
+ tm->tm_year = bcd2bin(yr) + 100;
+
+ for (i = 0; i < ISL12022_ALARM_LEN; i++) {
+ if (buf[i] & ISL12022_ALARM_ENABLE) {
+ alarm->enabled = 1;
+ break;
+ }
+ }
+
+ dev_dbg(dev, "%s: %ptR\n", __func__, tm);
+
+ return 0;
+}
+
+static int isl12022_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct rtc_time *alarm_tm = &alarm->time;
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
+ u8 regs[ISL12022_ALARM_LEN] = { 0, };
+ struct rtc_time rtc_tm;
+ int ret, enable, dw;
+
+ ret = isl12022_rtc_read_time(dev, &rtc_tm);
+ if (ret)
+ return ret;
+
+ /* If the alarm time is before the current time disable the alarm */
+ if (!alarm->enabled || rtc_tm_sub(alarm_tm, &rtc_tm) <= 0)
+ enable = 0;
+ else
+ enable = ISL12022_ALARM_ENABLE;
+
+ /*
+ * Set non-matching day of the week to safeguard against early false
+ * matching while setting all the alarm registers (this rtc lacks a
+ * general alarm/irq enable/disable bit).
+ */
+ ret = regmap_read(regmap, ISL12022_REG_DW, &dw);
+ if (ret) {
+ dev_dbg(dev, "%s: reading DW failed\n", __func__);
+ return ret;
+ }
+ /* ~4 days into the future should be enough to avoid match */
+ dw = ((dw + 4) % 7) | ISL12022_ALARM_ENABLE;
+ ret = regmap_write(regmap, ISL12022_REG_DWA0, dw);
+ if (ret) {
+ dev_dbg(dev, "%s: writing DWA0 failed\n", __func__);
+ return ret;
+ }
+
+ /* Program the alarm and enable it for each setting */
+ regs[ISL12022_REG_SCA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_sec) | enable;
+ regs[ISL12022_REG_MNA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_min) | enable;
+ regs[ISL12022_REG_HRA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_hour) | enable;
+ regs[ISL12022_REG_DTA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_mday) | enable;
+ regs[ISL12022_REG_MOA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_mon + 1) | enable;
+ regs[ISL12022_REG_DWA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_wday & 7) | enable;
+
+ /* write ALARM registers */
+ ret = regmap_bulk_write(regmap, ISL12022_ALARM, &regs, sizeof(regs));
+ if (ret) {
+ dev_dbg(dev, "%s: writing ALARM registers failed\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static irqreturn_t isl12022_rtc_interrupt(int irq, void *data)
+{
+ struct isl12022 *isl12022 = data;
+ struct rtc_device *rtc = isl12022->rtc;
+ struct device *dev = &rtc->dev;
+ struct regmap *regmap = isl12022->regmap;
+ u32 val = 0;
+ unsigned long events = 0;
+ int ret;
+
+ ret = regmap_read(regmap, ISL12022_REG_SR, &val);
+ if (ret) {
+ dev_dbg(dev, "%s: reading SR failed\n", __func__);
+ return IRQ_HANDLED;
+ }
+
+ if (val & ISL12022_SR_ALM)
+ events |= RTC_IRQF | RTC_AF;
+
+ if (events & RTC_AF)
+ dev_dbg(dev, "alarm!\n");
+
+ if (!events)
+ return IRQ_NONE;
+
+ rtc_update_irq(rtc, 1, events);
+ return IRQ_HANDLED;
+}
+
+static int isl12022_rtc_alarm_irq_enable(struct device *dev,
+ unsigned int enabled)
+{
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+
+ /* Make sure enabled is 0 or 1 */
+ enabled = !!enabled;
+
+ if (isl12022->irq_enabled == enabled)
+ return 0;
+
+ if (enabled)
+ enable_irq(isl12022->irq);
+ else
+ disable_irq(isl12022->irq);
+
+ isl12022->irq_enabled = enabled;
+
+ return 0;
+}
+
+static int isl12022_setup_irq(struct device *dev, int irq)
+{
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
+ unsigned int reg_mask, reg_val;
+ u8 buf[ISL12022_ALARM_LEN] = { 0, };
+ int ret;
+
+ /* Clear and disable all alarm registers */
+ ret = regmap_bulk_write(regmap, ISL12022_ALARM, buf, sizeof(buf));
+ if (ret)
+ return ret;
+
+ /*
+ * Enable automatic reset of ALM bit and enable single event interrupt
+ * mode.
+ */
+ reg_mask = ISL12022_INT_ARST | ISL12022_INT_IM | ISL12022_INT_FO_MASK;
+ reg_val = ISL12022_INT_ARST | ISL12022_INT_FO_OFF;
+ ret = regmap_write_bits(regmap, ISL12022_REG_INT,
+ reg_mask, reg_val);
+ if (ret)
+ return ret;
+
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ isl12022_rtc_interrupt,
+ IRQF_SHARED | IRQF_ONESHOT,
+ isl12022_driver.driver.name,
+ isl12022);
+ if (ret)
+ return dev_err_probe(dev, ret, "Unable to request irq %d\n", irq);
+
+ isl12022->irq = irq;
+ return 0;
+}
+
static int isl12022_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
- struct regmap *regmap = dev_get_drvdata(dev);
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
u32 user, val;
int ret;
@@ -238,6 +456,9 @@ static const struct rtc_class_ops isl12022_rtc_ops = {
.ioctl = isl12022_rtc_ioctl,
.read_time = isl12022_rtc_read_time,
.set_time = isl12022_rtc_set_time,
+ .read_alarm = isl12022_rtc_read_alarm,
+ .set_alarm = isl12022_rtc_set_alarm,
+ .alarm_irq_enable = isl12022_rtc_alarm_irq_enable,
};
static const struct regmap_config regmap_config = {
@@ -248,7 +469,8 @@ static const struct regmap_config regmap_config = {
static int isl12022_register_clock(struct device *dev)
{
- struct regmap *regmap = dev_get_drvdata(dev);
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
struct clk_hw *hw;
int ret;
@@ -288,7 +510,8 @@ static const u32 trip_levels[2][7] = {
static void isl12022_set_trip_levels(struct device *dev)
{
- struct regmap *regmap = dev_get_drvdata(dev);
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
u32 levels[2] = {0, 0};
int ret, i, j, x[2];
u8 val, mask;
@@ -325,6 +548,7 @@ static void isl12022_set_trip_levels(struct device *dev)
static int isl12022_probe(struct i2c_client *client)
{
+ struct isl12022 *isl12022;
struct rtc_device *rtc;
struct regmap *regmap;
int ret;
@@ -332,13 +556,17 @@ static int isl12022_probe(struct i2c_client *client)
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
+ /* Allocate driver state */
+ isl12022 = devm_kzalloc(&client->dev, sizeof(*isl12022), GFP_KERNEL);
+ if (!isl12022)
+ return -ENOMEM;
+
regmap = devm_regmap_init_i2c(client, &regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(&client->dev, "regmap allocation failed\n");
- return PTR_ERR(regmap);
- }
+ if (IS_ERR(regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(regmap), "regmap allocation failed\n");
+ isl12022->regmap = regmap;
- dev_set_drvdata(&client->dev, regmap);
+ dev_set_drvdata(&client->dev, isl12022);
ret = isl12022_register_clock(&client->dev);
if (ret)
@@ -350,11 +578,20 @@ static int isl12022_probe(struct i2c_client *client)
rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
+ isl12022->rtc = rtc;
rtc->ops = &isl12022_rtc_ops;
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc->range_max = RTC_TIMESTAMP_END_2099;
+ if (client->irq > 0) {
+ ret = isl12022_setup_irq(&client->dev, client->irq);
+ if (ret)
+ return ret;
+ } else {
+ clear_bit(RTC_FEATURE_ALARM, rtc->features);
+ }
+
return devm_rtc_register_device(rtc);
}
diff --git a/drivers/rtc/rtc-loongson.c b/drivers/rtc/rtc-loongson.c
index e8ffc1ab90b0..8d713e563d7c 100644
--- a/drivers/rtc/rtc-loongson.c
+++ b/drivers/rtc/rtc-loongson.c
@@ -381,7 +381,7 @@ MODULE_DEVICE_TABLE(acpi, loongson_rtc_acpi_match);
static struct platform_driver loongson_rtc_driver = {
.probe = loongson_rtc_probe,
- .remove_new = loongson_rtc_remove,
+ .remove = loongson_rtc_remove,
.driver = {
.name = "loongson-rtc",
.of_match_table = loongson_rtc_of_match,
diff --git a/drivers/rtc/rtc-lpc24xx.c b/drivers/rtc/rtc-lpc24xx.c
index df17c48ff086..2dcdc77ff646 100644
--- a/drivers/rtc/rtc-lpc24xx.c
+++ b/drivers/rtc/rtc-lpc24xx.c
@@ -285,7 +285,7 @@ MODULE_DEVICE_TABLE(of, lpc24xx_rtc_match);
static struct platform_driver lpc24xx_rtc_driver = {
.probe = lpc24xx_rtc_probe,
- .remove_new = lpc24xx_rtc_remove,
+ .remove = lpc24xx_rtc_remove,
.driver = {
.name = "lpc24xx-rtc",
.of_match_table = lpc24xx_rtc_match,
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 5d30ce8e13ca..4e608bc8bbd3 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -71,7 +71,7 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* Issue the READ command */
M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
- tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR));
+ tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)) + pdata->yy_offset;
/* tm_mon is 0-11 */
tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
tm->tm_mday = bcd2bin(M48T59_READ(M48T59_MDAY));
@@ -82,10 +82,6 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
dev_dbg(dev, "Century bit is enabled\n");
tm->tm_year += 100; /* one century */
}
-#ifdef CONFIG_SPARC
- /* Sun SPARC machines count years since 1968 */
- tm->tm_year += 68;
-#endif
tm->tm_wday = bcd2bin(val & 0x07);
tm->tm_hour = bcd2bin(M48T59_READ(M48T59_HOUR) & 0x3F);
@@ -106,12 +102,7 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
struct m48t59_private *m48t59 = dev_get_drvdata(dev);
unsigned long flags;
u8 val = 0;
- int year = tm->tm_year;
-
-#ifdef CONFIG_SPARC
- /* Sun SPARC machines count years since 1968 */
- year -= 68;
-#endif
+ int year = tm->tm_year - pdata->yy_offset;
dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n",
year + 1900, tm->tm_mon, tm->tm_mday,
@@ -162,11 +153,7 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
/* Issue the READ command */
M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
- tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR));
-#ifdef CONFIG_SPARC
- /* Sun SPARC machines count years since 1968 */
- tm->tm_year += 68;
-#endif
+ tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)) + pdata->yy_offset;
/* tm_mon is 0-11 */
tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
@@ -197,12 +184,7 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
struct rtc_time *tm = &alrm->time;
u8 mday, hour, min, sec;
unsigned long flags;
- int year = tm->tm_year;
-
-#ifdef CONFIG_SPARC
- /* Sun SPARC machines count years since 1968 */
- year -= 68;
-#endif
+ int year = tm->tm_year - pdata->yy_offset;
/* If no irq, we don't support ALARM */
if (m48t59->irq == NO_IRQ)
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 35a6021d9ba4..a8f4b645c09d 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -875,7 +875,7 @@ static struct platform_driver max77686_rtc_driver = {
.pm = &max77686_rtc_pm_ops,
},
.probe = max77686_rtc_probe,
- .remove_new = max77686_rtc_remove,
+ .remove = max77686_rtc_remove,
.id_table = rtc_id,
};
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
index 763a42f422eb..e7b87130e624 100644
--- a/drivers/rtc/rtc-mc13xxx.c
+++ b/drivers/rtc/rtc-mc13xxx.c
@@ -350,7 +350,7 @@ MODULE_DEVICE_TABLE(platform, mc13xxx_rtc_idtable);
static struct platform_driver mc13xxx_rtc_driver = {
.id_table = mc13xxx_rtc_idtable,
- .remove_new = mc13xxx_rtc_remove,
+ .remove = mc13xxx_rtc_remove,
.driver = {
.name = DRIVER_NAME,
},
diff --git a/drivers/rtc/rtc-mc146818-lib.c b/drivers/rtc/rtc-mc146818-lib.c
index 651bf3c279c7..dbd2d5835f00 100644
--- a/drivers/rtc/rtc-mc146818-lib.c
+++ b/drivers/rtc/rtc-mc146818-lib.c
@@ -216,7 +216,7 @@ int mc146818_set_time(struct rtc_time *time)
unsigned char save_control, save_freq_select;
unsigned int yrs;
#ifdef CONFIG_MACH_DECSTATION
- unsigned int real_yrs, leap_yr;
+ unsigned int real_yrs;
#endif
unsigned char century = 0;
@@ -232,8 +232,6 @@ int mc146818_set_time(struct rtc_time *time)
#ifdef CONFIG_MACH_DECSTATION
real_yrs = yrs;
- leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) ||
- !((yrs + 1900) % 400));
yrs = 72;
/*
@@ -241,7 +239,7 @@ int mc146818_set_time(struct rtc_time *time)
* for non-leap years, so that Feb, 29th is handled
* correctly.
*/
- if (!leap_yr && mon < 3) {
+ if (!is_leap_year(real_yrs + 1900) && mon < 3) {
real_yrs--;
yrs = 73;
}
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index 71eafe4fbc72..600328131603 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -398,7 +398,7 @@ static struct platform_driver mpc5121_rtc_driver = {
.of_match_table = of_match_ptr(mpc5121_rtc_match),
},
.probe = mpc5121_rtc_probe,
- .remove_new = mpc5121_rtc_remove,
+ .remove = mpc5121_rtc_remove,
};
module_platform_driver(mpc5121_rtc_driver);
diff --git a/drivers/rtc/rtc-mpfs.c b/drivers/rtc/rtc-mpfs.c
index 5b96a6d39210..3892b0f9917f 100644
--- a/drivers/rtc/rtc-mpfs.c
+++ b/drivers/rtc/rtc-mpfs.c
@@ -288,7 +288,7 @@ MODULE_DEVICE_TABLE(of, mpfs_rtc_of_match);
static struct platform_driver mpfs_rtc_driver = {
.probe = mpfs_rtc_probe,
- .remove_new = mpfs_rtc_remove,
+ .remove = mpfs_rtc_remove,
.driver = {
.name = "mpfs_rtc",
.of_match_table = mpfs_rtc_of_match,
diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c
index 1617063669cc..152699219a2b 100644
--- a/drivers/rtc/rtc-mt6397.c
+++ b/drivers/rtc/rtc-mt6397.c
@@ -75,6 +75,7 @@ static int __mtk_rtc_read_time(struct mt6397_rtc *rtc,
tm->tm_min = data[RTC_OFFSET_MIN];
tm->tm_hour = data[RTC_OFFSET_HOUR];
tm->tm_mday = data[RTC_OFFSET_DOM];
+ tm->tm_wday = data[RTC_OFFSET_DOW];
tm->tm_mon = data[RTC_OFFSET_MTH] & RTC_TC_MTH_MASK;
tm->tm_year = data[RTC_OFFSET_YEAR];
@@ -86,9 +87,8 @@ exit:
static int mtk_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- time64_t time;
struct mt6397_rtc *rtc = dev_get_drvdata(dev);
- int days, sec, ret;
+ int sec, ret;
do {
ret = __mtk_rtc_read_time(rtc, tm, &sec);
@@ -96,21 +96,9 @@ static int mtk_rtc_read_time(struct device *dev, struct rtc_time *tm)
goto exit;
} while (sec < tm->tm_sec);
- /* HW register use 7 bits to store year data, minus
- * RTC_MIN_YEAR_OFFSET before write year data to register, and plus
- * RTC_MIN_YEAR_OFFSET back after read year from register
- */
- tm->tm_year += RTC_MIN_YEAR_OFFSET;
-
- /* HW register start mon from one, but tm_mon start from zero. */
+ /* HW register start mon/wday from one, but tm_mon/tm_wday start from zero. */
tm->tm_mon--;
- time = rtc_tm_to_time64(tm);
-
- /* rtc_tm_to_time64 covert Gregorian date to seconds since
- * 01-01-1970 00:00:00, and this date is Thursday.
- */
- days = div_s64(time, 86400);
- tm->tm_wday = (days + 4) % 7;
+ tm->tm_wday--;
exit:
return ret;
@@ -122,13 +110,14 @@ static int mtk_rtc_set_time(struct device *dev, struct rtc_time *tm)
int ret;
u16 data[RTC_OFFSET_COUNT];
- tm->tm_year -= RTC_MIN_YEAR_OFFSET;
tm->tm_mon++;
+ tm->tm_wday++;
data[RTC_OFFSET_SEC] = tm->tm_sec;
data[RTC_OFFSET_MIN] = tm->tm_min;
data[RTC_OFFSET_HOUR] = tm->tm_hour;
data[RTC_OFFSET_DOM] = tm->tm_mday;
+ data[RTC_OFFSET_DOW] = tm->tm_wday;
data[RTC_OFFSET_MTH] = tm->tm_mon;
data[RTC_OFFSET_YEAR] = tm->tm_year;
@@ -178,7 +167,6 @@ static int mtk_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
tm->tm_mon = data[RTC_OFFSET_MTH] & RTC_AL_MTH_MASK;
tm->tm_year = data[RTC_OFFSET_YEAR] & RTC_AL_YEA_MASK;
- tm->tm_year += RTC_MIN_YEAR_OFFSET;
tm->tm_mon--;
return 0;
@@ -194,7 +182,6 @@ static int mtk_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
int ret;
u16 data[RTC_OFFSET_COUNT];
- tm->tm_year -= RTC_MIN_YEAR_OFFSET;
tm->tm_mon++;
mutex_lock(&rtc->lock);
@@ -302,6 +289,10 @@ static int mtk_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 1);
rtc->rtc_dev->ops = &mtk_rtc_ops;
+ rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900;
+ rtc->rtc_dev->range_max = mktime64(2027, 12, 31, 23, 59, 59);
+ rtc->rtc_dev->start_secs = mktime64(1968, 1, 2, 0, 0, 0);
+ rtc->rtc_dev->set_start_time = true;
return devm_rtc_register_device(rtc->rtc_dev);
}
diff --git a/drivers/rtc/rtc-mt7622.c b/drivers/rtc/rtc-mt7622.c
index 094c649fc137..4cf0cbb31a31 100644
--- a/drivers/rtc/rtc-mt7622.c
+++ b/drivers/rtc/rtc-mt7622.c
@@ -394,7 +394,7 @@ static SIMPLE_DEV_PM_OPS(mtk_rtc_pm_ops, mtk_rtc_suspend, mtk_rtc_resume);
static struct platform_driver mtk_rtc_driver = {
.probe = mtk_rtc_probe,
- .remove_new = mtk_rtc_remove,
+ .remove = mtk_rtc_remove,
.driver = {
.name = MTK_RTC_DEV,
.of_match_table = mtk_rtc_match,
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index db31da56bfa7..51029c536244 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -308,7 +308,7 @@ MODULE_DEVICE_TABLE(of, rtc_mv_of_match_table);
* triggering a section mismatch warning.
*/
static struct platform_driver mv_rtc_driver __refdata = {
- .remove_new = __exit_p(mv_rtc_remove),
+ .remove = __exit_p(mv_rtc_remove),
.driver = {
.name = "rtc-mv",
.of_match_table = of_match_ptr(rtc_mv_of_match_table),
diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c
index 6934bce4b29f..13c041bb79f1 100644
--- a/drivers/rtc/rtc-mxc_v2.c
+++ b/drivers/rtc/rtc-mxc_v2.c
@@ -381,7 +381,7 @@ static struct platform_driver mxc_rtc_driver = {
.of_match_table = mxc_ids,
},
.probe = mxc_rtc_probe,
- .remove_new = mxc_rtc_remove,
+ .remove = mxc_rtc_remove,
};
module_platform_driver(mxc_rtc_driver);
diff --git a/drivers/rtc/rtc-nxp-bbnsm.c b/drivers/rtc/rtc-nxp-bbnsm.c
index acbfbeb8b070..fa3b0328c7a2 100644
--- a/drivers/rtc/rtc-nxp-bbnsm.c
+++ b/drivers/rtc/rtc-nxp-bbnsm.c
@@ -197,13 +197,28 @@ static int bbnsm_rtc_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "failed to request irq %d: %d\n",
bbnsm->irq, ret);
- return ret;
+ goto err;
}
bbnsm->rtc->ops = &bbnsm_rtc_ops;
bbnsm->rtc->range_max = U32_MAX;
- return devm_rtc_register_device(bbnsm->rtc);
+ ret = devm_rtc_register_device(bbnsm->rtc);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ dev_pm_clear_wake_irq(&pdev->dev);
+ device_init_wakeup(&pdev->dev, false);
+ return ret;
+}
+
+static void bbnsm_rtc_remove(struct platform_device *pdev)
+{
+ dev_pm_clear_wake_irq(&pdev->dev);
+ device_init_wakeup(&pdev->dev, false);
}
static const struct of_device_id bbnsm_dt_ids[] = {
@@ -218,6 +233,7 @@ static struct platform_driver bbnsm_rtc_driver = {
.of_match_table = bbnsm_dt_ids,
},
.probe = bbnsm_rtc_probe,
+ .remove = bbnsm_rtc_remove,
};
module_platform_driver(bbnsm_rtc_driver);
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index e6b2a9c15b54..c123778e2d9b 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -1014,7 +1014,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev)
static struct platform_driver omap_rtc_driver = {
.probe = omap_rtc_probe,
- .remove_new = omap_rtc_remove,
+ .remove = omap_rtc_remove,
.shutdown = omap_rtc_shutdown,
.driver = {
.name = "omap_rtc",
diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c
index 6971e47c6021..7256a88b490c 100644
--- a/drivers/rtc/rtc-palmas.c
+++ b/drivers/rtc/rtc-palmas.c
@@ -346,7 +346,7 @@ MODULE_DEVICE_TABLE(of, of_palmas_rtc_match);
static struct platform_driver palmas_rtc_driver = {
.probe = palmas_rtc_probe,
- .remove_new = palmas_rtc_remove,
+ .remove = palmas_rtc_remove,
.driver = {
.name = "palmas-rtc",
.pm = &palmas_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c
index 23edd11aa40c..c019c4d91c7d 100644
--- a/drivers/rtc/rtc-pcf50633.c
+++ b/drivers/rtc/rtc-pcf50633.c
@@ -273,7 +273,7 @@ static struct platform_driver pcf50633_rtc_driver = {
.name = "pcf50633-rtc",
},
.probe = pcf50633_rtc_probe,
- .remove_new = pcf50633_rtc_remove,
+ .remove = pcf50633_rtc_remove,
};
module_platform_driver(pcf50633_rtc_driver);
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index 647d52f1f5c5..5a084d426e58 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -11,14 +11,15 @@
* https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf
*/
+#include <linux/bcd.h>
#include <linux/clk-provider.h>
+#include <linux/err.h>
#include <linux/i2c.h>
-#include <linux/bcd.h>
-#include <linux/rtc.h>
-#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/err.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
#define PCF8563_REG_ST1 0x00 /* status */
#define PCF8563_REG_ST2 0x01
@@ -77,64 +78,18 @@ struct pcf8563 {
*/
int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
- struct i2c_client *client;
+ struct regmap *regmap;
#ifdef CONFIG_COMMON_CLK
struct clk_hw clkout_hw;
#endif
};
-static int pcf8563_read_block_data(struct i2c_client *client, unsigned char reg,
- unsigned char length, unsigned char *buf)
-{
- struct i2c_msg msgs[] = {
- {/* setup read ptr */
- .addr = client->addr,
- .len = 1,
- .buf = &reg,
- },
- {
- .addr = client->addr,
- .flags = I2C_M_RD,
- .len = length,
- .buf = buf
- },
- };
-
- if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
- dev_err(&client->dev, "%s: read error\n", __func__);
- return -EIO;
- }
-
- return 0;
-}
-
-static int pcf8563_write_block_data(struct i2c_client *client,
- unsigned char reg, unsigned char length,
- unsigned char *buf)
-{
- int i, err;
-
- for (i = 0; i < length; i++) {
- unsigned char data[2] = { reg + i, buf[i] };
-
- err = i2c_master_send(client, data, sizeof(data));
- if (err != sizeof(data)) {
- dev_err(&client->dev,
- "%s: err=%d addr=%02x, data=%02x\n",
- __func__, err, data[0], data[1]);
- return -EIO;
- }
- }
-
- return 0;
-}
-
-static int pcf8563_set_alarm_mode(struct i2c_client *client, bool on)
+static int pcf8563_set_alarm_mode(struct pcf8563 *pcf8563, bool on)
{
- unsigned char buf;
+ u32 buf;
int err;
- err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf);
+ err = regmap_read(pcf8563->regmap, PCF8563_REG_ST2, &buf);
if (err < 0)
return err;
@@ -145,23 +100,17 @@ static int pcf8563_set_alarm_mode(struct i2c_client *client, bool on)
buf &= ~(PCF8563_BIT_AF | PCF8563_BITS_ST2_N);
- err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf);
- if (err < 0) {
- dev_err(&client->dev, "%s: write error\n", __func__);
- return -EIO;
- }
-
- return 0;
+ return regmap_write(pcf8563->regmap, PCF8563_REG_ST2, buf);
}
-static int pcf8563_get_alarm_mode(struct i2c_client *client, unsigned char *en,
+static int pcf8563_get_alarm_mode(struct pcf8563 *pcf8563, unsigned char *en,
unsigned char *pen)
{
- unsigned char buf;
+ u32 buf;
int err;
- err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf);
- if (err)
+ err = regmap_read(pcf8563->regmap, PCF8563_REG_ST2, &buf);
+ if (err < 0)
return err;
if (en)
@@ -174,17 +123,17 @@ static int pcf8563_get_alarm_mode(struct i2c_client *client, unsigned char *en,
static irqreturn_t pcf8563_irq(int irq, void *dev_id)
{
- struct pcf8563 *pcf8563 = i2c_get_clientdata(dev_id);
- int err;
+ struct pcf8563 *pcf8563 = dev_id;
char pending;
+ int err;
- err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending);
+ err = pcf8563_get_alarm_mode(pcf8563, NULL, &pending);
if (err)
return IRQ_NONE;
if (pending) {
rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF);
- pcf8563_set_alarm_mode(pcf8563->client, 1);
+ pcf8563_set_alarm_mode(pcf8563, 1);
return IRQ_HANDLED;
}
@@ -197,22 +146,22 @@ static irqreturn_t pcf8563_irq(int irq, void *dev_id)
*/
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
+ struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
unsigned char buf[9];
int err;
- err = pcf8563_read_block_data(client, PCF8563_REG_ST1, 9, buf);
- if (err)
+ err = regmap_bulk_read(pcf8563->regmap, PCF8563_REG_ST1, buf,
+ sizeof(buf));
+ if (err < 0)
return err;
if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) {
- dev_err(&client->dev,
+ dev_err(dev,
"low voltage detected, date/time is not reliable.\n");
return -EINVAL;
}
- dev_dbg(&client->dev,
+ dev_dbg(dev,
"%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
"mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
__func__,
@@ -220,7 +169,6 @@ static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
buf[4], buf[5], buf[6], buf[7],
buf[8]);
-
tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
@@ -232,7 +180,7 @@ static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?
(tm->tm_year >= 100) : (tm->tm_year < 100);
- dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
__func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
@@ -243,11 +191,10 @@ static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
+ struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
unsigned char buf[9];
- dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+ dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
__func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
@@ -270,22 +217,24 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
- return pcf8563_write_block_data(client, PCF8563_REG_SC,
- 9 - PCF8563_REG_SC, buf + PCF8563_REG_SC);
+ return regmap_bulk_write(pcf8563->regmap, PCF8563_REG_SC,
+ buf + PCF8563_REG_SC,
+ sizeof(buf) - PCF8563_REG_SC);
}
static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
int ret;
switch (cmd) {
case RTC_VL_READ:
- ret = i2c_smbus_read_byte_data(client, PCF8563_REG_SC);
+ ret = regmap_test_bits(pcf8563->regmap, PCF8563_REG_SC,
+ PCF8563_SC_LV);
if (ret < 0)
return ret;
- return put_user(ret & PCF8563_SC_LV ? RTC_VL_DATA_INVALID : 0,
+ return put_user(ret ? RTC_VL_DATA_INVALID : 0,
(unsigned int __user *)arg);
default:
return -ENOIOCTLCMD;
@@ -294,15 +243,16 @@ static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
unsigned char buf[4];
int err;
- err = pcf8563_read_block_data(client, PCF8563_REG_AMN, 4, buf);
- if (err)
+ err = regmap_bulk_read(pcf8563->regmap, PCF8563_REG_AMN, buf,
+ sizeof(buf));
+ if (err < 0)
return err;
- dev_dbg(&client->dev,
+ dev_dbg(dev,
"%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n",
__func__, buf[0], buf[1], buf[2], buf[3]);
@@ -312,11 +262,11 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
tm->time.tm_mday = bcd2bin(buf[2] & 0x3F);
tm->time.tm_wday = bcd2bin(buf[3] & 0x7);
- err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending);
+ err = pcf8563_get_alarm_mode(pcf8563, &tm->enabled, &tm->pending);
if (err < 0)
return err;
- dev_dbg(&client->dev, "%s: tm is mins=%d, hours=%d, mday=%d, wday=%d,"
+ dev_dbg(dev, "%s: tm is mins=%d, hours=%d, mday=%d, wday=%d,"
" enabled=%d, pending=%d\n", __func__, tm->time.tm_min,
tm->time.tm_hour, tm->time.tm_mday, tm->time.tm_wday,
tm->enabled, tm->pending);
@@ -326,7 +276,7 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
unsigned char buf[4];
int err;
@@ -335,17 +285,20 @@ static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
buf[2] = bin2bcd(tm->time.tm_mday);
buf[3] = tm->time.tm_wday & 0x07;
- err = pcf8563_write_block_data(client, PCF8563_REG_AMN, 4, buf);
+ err = regmap_bulk_write(pcf8563->regmap, PCF8563_REG_SC, buf,
+ sizeof(buf));
if (err)
return err;
- return pcf8563_set_alarm_mode(client, !!tm->enabled);
+ return pcf8563_set_alarm_mode(pcf8563, !!tm->enabled);
}
static int pcf8563_irq_enable(struct device *dev, unsigned int enabled)
{
+ struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
+
dev_dbg(dev, "%s: en=%d\n", __func__, enabled);
- return pcf8563_set_alarm_mode(to_i2c_client(dev), !!enabled);
+ return pcf8563_set_alarm_mode(pcf8563, !!enabled);
}
#ifdef CONFIG_COMMON_CLK
@@ -366,10 +319,10 @@ static unsigned long pcf8563_clkout_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
- struct i2c_client *client = pcf8563->client;
- unsigned char buf;
- int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+ u32 buf;
+ int ret;
+ ret = regmap_read(pcf8563->regmap, PCF8563_REG_CLKO, &buf);
if (ret < 0)
return 0;
@@ -393,11 +346,10 @@ static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
- struct i2c_client *client = pcf8563->client;
- unsigned char buf;
- int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
- int i;
+ int i, ret;
+ u32 buf;
+ ret = regmap_read(pcf8563->regmap, PCF8563_REG_CLKO, &buf);
if (ret < 0)
return ret;
@@ -405,10 +357,10 @@ static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
if (clkout_rates[i] == rate) {
buf &= ~PCF8563_REG_CLKO_F_MASK;
buf |= i;
- ret = pcf8563_write_block_data(client,
- PCF8563_REG_CLKO, 1,
- &buf);
- return ret;
+ return regmap_update_bits(pcf8563->regmap,
+ PCF8563_REG_CLKO,
+ PCF8563_REG_CLKO_F_MASK,
+ buf);
}
return -EINVAL;
@@ -417,10 +369,10 @@ static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
static int pcf8563_clkout_control(struct clk_hw *hw, bool enable)
{
struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
- struct i2c_client *client = pcf8563->client;
- unsigned char buf;
- int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+ u32 buf;
+ int ret;
+ ret = regmap_read(pcf8563->regmap, PCF8563_REG_CLKO, &buf);
if (ret < 0)
return ret;
@@ -429,8 +381,8 @@ static int pcf8563_clkout_control(struct clk_hw *hw, bool enable)
else
buf &= ~PCF8563_REG_CLKO_FE;
- ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
- return ret;
+ return regmap_update_bits(pcf8563->regmap, PCF8563_REG_CLKO,
+ PCF8563_REG_CLKO_FE, buf);
}
static int pcf8563_clkout_prepare(struct clk_hw *hw)
@@ -446,10 +398,10 @@ static void pcf8563_clkout_unprepare(struct clk_hw *hw)
static int pcf8563_clkout_is_prepared(struct clk_hw *hw)
{
struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
- struct i2c_client *client = pcf8563->client;
- unsigned char buf;
- int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+ u32 buf;
+ int ret;
+ ret = regmap_read(pcf8563->regmap, PCF8563_REG_CLKO, &buf);
if (ret < 0)
return ret;
@@ -467,16 +419,14 @@ static const struct clk_ops pcf8563_clkout_ops = {
static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563)
{
- struct i2c_client *client = pcf8563->client;
- struct device_node *node = client->dev.of_node;
- struct clk *clk;
+ struct device_node *node = pcf8563->rtc->dev.of_node;
struct clk_init_data init;
+ struct clk *clk;
int ret;
- unsigned char buf;
/* disable the clkout output */
- buf = 0;
- ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+ ret = regmap_clear_bits(pcf8563->regmap, PCF8563_REG_CLKO,
+ PCF8563_REG_CLKO_FE);
if (ret < 0)
return ERR_PTR(ret);
@@ -491,7 +441,7 @@ static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563)
of_property_read_string(node, "clock-output-names", &init.name);
/* register the clock */
- clk = devm_clk_register(&client->dev, &pcf8563->clkout_hw);
+ clk = devm_clk_register(&pcf8563->rtc->dev, &pcf8563->clkout_hw);
if (!IS_ERR(clk))
of_clk_add_provider(node, of_clk_src_simple_get, clk);
@@ -509,11 +459,16 @@ static const struct rtc_class_ops pcf8563_rtc_ops = {
.alarm_irq_enable = pcf8563_irq_enable,
};
+static const struct regmap_config regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xF,
+};
+
static int pcf8563_probe(struct i2c_client *client)
{
struct pcf8563 *pcf8563;
int err;
- unsigned char buf;
dev_dbg(&client->dev, "%s\n", __func__);
@@ -525,20 +480,23 @@ static int pcf8563_probe(struct i2c_client *client)
if (!pcf8563)
return -ENOMEM;
+ pcf8563->regmap = devm_regmap_init_i2c(client, &regmap_config);
+ if (IS_ERR(pcf8563->regmap))
+ return PTR_ERR(pcf8563->regmap);
+
i2c_set_clientdata(client, pcf8563);
- pcf8563->client = client;
+ device_set_wakeup_capable(&client->dev, 1);
/* Set timer to lowest frequency to save power (ref Haoyu datasheet) */
- buf = PCF8563_TMRC_1_60;
- err = pcf8563_write_block_data(client, PCF8563_REG_TMRC, 1, &buf);
+ err = regmap_set_bits(pcf8563->regmap, PCF8563_REG_TMRC,
+ PCF8563_TMRC_1_60);
if (err < 0) {
dev_err(&client->dev, "%s: write error\n", __func__);
return err;
}
/* Clear flags and disable interrupts */
- buf = 0;
- err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf);
+ err = regmap_write(pcf8563->regmap, PCF8563_REG_ST2, 0);
if (err < 0) {
dev_err(&client->dev, "%s: write error\n", __func__);
return err;
diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c
index 4f85e0c3d757..bed3c27e665f 100644
--- a/drivers/rtc/rtc-pic32.c
+++ b/drivers/rtc/rtc-pic32.c
@@ -371,7 +371,7 @@ MODULE_DEVICE_TABLE(of, pic32_rtc_dt_ids);
static struct platform_driver pic32_rtc_driver = {
.probe = pic32_rtc_probe,
- .remove_new = pic32_rtc_remove,
+ .remove = pic32_rtc_remove,
.driver = {
.name = "pic32-rtc",
.of_match_table = of_match_ptr(pic32_rtc_dt_ids),
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c
index c32fba550c8e..2f32187ecc8d 100644
--- a/drivers/rtc/rtc-pm8xxx.c
+++ b/drivers/rtc/rtc-pm8xxx.c
@@ -537,7 +537,7 @@ static void pm8xxx_remove(struct platform_device *pdev)
static struct platform_driver pm8xxx_rtc_driver = {
.probe = pm8xxx_rtc_probe,
- .remove_new = pm8xxx_remove,
+ .remove = pm8xxx_remove,
.driver = {
.name = "rtc-pm8xxx",
.of_match_table = pm8xxx_id_table,
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c
index cdb39fc4cab5..34d8545c8e15 100644
--- a/drivers/rtc/rtc-pxa.c
+++ b/drivers/rtc/rtc-pxa.c
@@ -409,7 +409,7 @@ static SIMPLE_DEV_PM_OPS(pxa_rtc_pm_ops, pxa_rtc_suspend, pxa_rtc_resume);
* triggering a section mismatch warning.
*/
static struct platform_driver pxa_rtc_driver __refdata = {
- .remove_new = __exit_p(pxa_rtc_remove),
+ .remove = __exit_p(pxa_rtc_remove),
.driver = {
.name = "pxa-rtc",
.of_match_table = of_match_ptr(pxa_rtc_dt_ids),
diff --git a/drivers/rtc/rtc-rc5t583.c b/drivers/rtc/rtc-rc5t583.c
index 115c46f862f9..eecb49bab56a 100644
--- a/drivers/rtc/rtc-rc5t583.c
+++ b/drivers/rtc/rtc-rc5t583.c
@@ -298,7 +298,7 @@ static SIMPLE_DEV_PM_OPS(rc5t583_rtc_pm_ops, rc5t583_rtc_suspend,
static struct platform_driver rc5t583_rtc_driver = {
.probe = rc5t583_rtc_probe,
- .remove_new = rc5t583_rtc_remove,
+ .remove = rc5t583_rtc_remove,
.driver = {
.name = "rtc-rc5t583",
.pm = &rc5t583_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-renesas-rtca3.c b/drivers/rtc/rtc-renesas-rtca3.c
new file mode 100644
index 000000000000..d127933bfc8a
--- /dev/null
+++ b/drivers/rtc/rtc-renesas-rtca3.c
@@ -0,0 +1,900 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * On-Chip RTC Support available on RZ/G3S SoC
+ *
+ * Copyright (C) 2024 Renesas Electronics Corp.
+ */
+#include <linux/bcd.h>
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/rtc.h>
+
+/* Counter registers. */
+#define RTCA3_RSECCNT 0x2
+#define RTCA3_RSECCNT_SEC GENMASK(6, 0)
+#define RTCA3_RMINCNT 0x4
+#define RTCA3_RMINCNT_MIN GENMASK(6, 0)
+#define RTCA3_RHRCNT 0x6
+#define RTCA3_RHRCNT_HR GENMASK(5, 0)
+#define RTCA3_RHRCNT_PM BIT(6)
+#define RTCA3_RWKCNT 0x8
+#define RTCA3_RWKCNT_WK GENMASK(2, 0)
+#define RTCA3_RDAYCNT 0xa
+#define RTCA3_RDAYCNT_DAY GENMASK(5, 0)
+#define RTCA3_RMONCNT 0xc
+#define RTCA3_RMONCNT_MONTH GENMASK(4, 0)
+#define RTCA3_RYRCNT 0xe
+#define RTCA3_RYRCNT_YEAR GENMASK(7, 0)
+
+/* Alarm registers. */
+#define RTCA3_RSECAR 0x10
+#define RTCA3_RSECAR_SEC GENMASK(6, 0)
+#define RTCA3_RMINAR 0x12
+#define RTCA3_RMINAR_MIN GENMASK(6, 0)
+#define RTCA3_RHRAR 0x14
+#define RTCA3_RHRAR_HR GENMASK(5, 0)
+#define RTCA3_RHRAR_PM BIT(6)
+#define RTCA3_RWKAR 0x16
+#define RTCA3_RWKAR_DAYW GENMASK(2, 0)
+#define RTCA3_RDAYAR 0x18
+#define RTCA3_RDAYAR_DATE GENMASK(5, 0)
+#define RTCA3_RMONAR 0x1a
+#define RTCA3_RMONAR_MON GENMASK(4, 0)
+#define RTCA3_RYRAR 0x1c
+#define RTCA3_RYRAR_YR GENMASK(7, 0)
+#define RTCA3_RYRAREN 0x1e
+
+/* Alarm enable bit (for all alarm registers). */
+#define RTCA3_AR_ENB BIT(7)
+
+/* Control registers. */
+#define RTCA3_RCR1 0x22
+#define RTCA3_RCR1_AIE BIT(0)
+#define RTCA3_RCR1_CIE BIT(1)
+#define RTCA3_RCR1_PIE BIT(2)
+#define RTCA3_RCR1_PES GENMASK(7, 4)
+#define RTCA3_RCR1_PES_1_64_SEC 0x8
+#define RTCA3_RCR2 0x24
+#define RTCA3_RCR2_START BIT(0)
+#define RTCA3_RCR2_RESET BIT(1)
+#define RTCA3_RCR2_AADJE BIT(4)
+#define RTCA3_RCR2_ADJP BIT(5)
+#define RTCA3_RCR2_HR24 BIT(6)
+#define RTCA3_RCR2_CNTMD BIT(7)
+#define RTCA3_RSR 0x20
+#define RTCA3_RSR_AF BIT(0)
+#define RTCA3_RSR_CF BIT(1)
+#define RTCA3_RSR_PF BIT(2)
+#define RTCA3_RADJ 0x2e
+#define RTCA3_RADJ_ADJ GENMASK(5, 0)
+#define RTCA3_RADJ_ADJ_MAX 0x3f
+#define RTCA3_RADJ_PMADJ GENMASK(7, 6)
+#define RTCA3_RADJ_PMADJ_NONE 0
+#define RTCA3_RADJ_PMADJ_ADD 1
+#define RTCA3_RADJ_PMADJ_SUB 2
+
+/* Polling operation timeouts. */
+#define RTCA3_DEFAULT_TIMEOUT_US 150
+#define RTCA3_IRQSET_TIMEOUT_US 5000
+#define RTCA3_START_TIMEOUT_US 150000
+#define RTCA3_RESET_TIMEOUT_US 200000
+
+/**
+ * enum rtca3_alrm_set_step - RTCA3 alarm set steps
+ * @RTCA3_ALRM_SSTEP_DONE: alarm setup done step
+ * @RTCA3_ALRM_SSTEP_IRQ: two 1/64 periodic IRQs were generated step
+ * @RTCA3_ALRM_SSTEP_INIT: alarm setup initialization step
+ */
+enum rtca3_alrm_set_step {
+ RTCA3_ALRM_SSTEP_DONE = 0,
+ RTCA3_ALRM_SSTEP_IRQ = 1,
+ RTCA3_ALRM_SSTEP_INIT = 3,
+};
+
+/**
+ * struct rtca3_ppb_per_cycle - PPB per cycle
+ * @ten_sec: PPB per cycle in 10 seconds adjutment mode
+ * @sixty_sec: PPB per cycle in 60 seconds adjustment mode
+ */
+struct rtca3_ppb_per_cycle {
+ int ten_sec;
+ int sixty_sec;
+};
+
+/**
+ * struct rtca3_priv - RTCA3 private data structure
+ * @base: base address
+ * @rtc_dev: RTC device
+ * @rstc: reset control
+ * @set_alarm_completion: alarm setup completion
+ * @alrm_sstep: alarm setup step (see enum rtca3_alrm_set_step)
+ * @lock: device lock
+ * @ppb: ppb per cycle for each the available adjustment modes
+ * @wakeup_irq: wakeup IRQ
+ */
+struct rtca3_priv {
+ void __iomem *base;
+ struct rtc_device *rtc_dev;
+ struct reset_control *rstc;
+ struct completion set_alarm_completion;
+ atomic_t alrm_sstep;
+ spinlock_t lock;
+ struct rtca3_ppb_per_cycle ppb;
+ int wakeup_irq;
+};
+
+static void rtca3_byte_update_bits(struct rtca3_priv *priv, u8 off, u8 mask, u8 val)
+{
+ u8 tmp;
+
+ tmp = readb(priv->base + off);
+ tmp &= ~mask;
+ tmp |= (val & mask);
+ writeb(tmp, priv->base + off);
+}
+
+static u8 rtca3_alarm_handler_helper(struct rtca3_priv *priv)
+{
+ u8 val, pending;
+
+ val = readb(priv->base + RTCA3_RSR);
+ pending = val & RTCA3_RSR_AF;
+ writeb(val & ~pending, priv->base + RTCA3_RSR);
+
+ if (pending)
+ rtc_update_irq(priv->rtc_dev, 1, RTC_AF | RTC_IRQF);
+
+ return pending;
+}
+
+static irqreturn_t rtca3_alarm_handler(int irq, void *dev_id)
+{
+ struct rtca3_priv *priv = dev_id;
+ u8 pending;
+
+ guard(spinlock)(&priv->lock);
+
+ pending = rtca3_alarm_handler_helper(priv);
+
+ return IRQ_RETVAL(pending);
+}
+
+static irqreturn_t rtca3_periodic_handler(int irq, void *dev_id)
+{
+ struct rtca3_priv *priv = dev_id;
+ u8 val, pending;
+
+ guard(spinlock)(&priv->lock);
+
+ val = readb(priv->base + RTCA3_RSR);
+ pending = val & RTCA3_RSR_PF;
+
+ if (pending) {
+ writeb(val & ~pending, priv->base + RTCA3_RSR);
+
+ if (atomic_read(&priv->alrm_sstep) > RTCA3_ALRM_SSTEP_IRQ) {
+ /* Alarm setup in progress. */
+ atomic_dec(&priv->alrm_sstep);
+
+ if (atomic_read(&priv->alrm_sstep) == RTCA3_ALRM_SSTEP_IRQ) {
+ /*
+ * We got 2 * 1/64 periodic interrupts. Disable
+ * interrupt and let alarm setup continue.
+ */
+ rtca3_byte_update_bits(priv, RTCA3_RCR1,
+ RTCA3_RCR1_PIE, 0);
+ readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, val,
+ !(val & RTCA3_RCR1_PIE),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ complete(&priv->set_alarm_completion);
+ }
+ }
+ }
+
+ return IRQ_RETVAL(pending);
+}
+
+static void rtca3_prepare_cntalrm_regs_for_read(struct rtca3_priv *priv, bool cnt)
+{
+ /* Offset b/w time and alarm registers. */
+ u8 offset = cnt ? 0 : 0xe;
+
+ /*
+ * According to HW manual (section 22.6.4. Notes on writing to and
+ * reading from registers) after writing to count registers, alarm
+ * registers, year alarm enable register, bits RCR2.AADJE, AADJP,
+ * and HR24 register, we need to do 3 empty reads before being
+ * able to fetch the registers content.
+ */
+ for (u8 i = 0; i < 3; i++) {
+ readb(priv->base + RTCA3_RSECCNT + offset);
+ readb(priv->base + RTCA3_RMINCNT + offset);
+ readb(priv->base + RTCA3_RHRCNT + offset);
+ readb(priv->base + RTCA3_RWKCNT + offset);
+ readb(priv->base + RTCA3_RDAYCNT + offset);
+ readw(priv->base + RTCA3_RYRCNT + offset);
+ if (!cnt)
+ readb(priv->base + RTCA3_RYRAREN);
+ }
+}
+
+static int rtca3_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ u8 sec, min, hour, wday, mday, month, tmp;
+ u8 trials = 0;
+ u32 year100;
+ u16 year;
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ tmp = readb(priv->base + RTCA3_RCR2);
+ if (!(tmp & RTCA3_RCR2_START))
+ return -EINVAL;
+
+ do {
+ /* Clear carry interrupt. */
+ rtca3_byte_update_bits(priv, RTCA3_RSR, RTCA3_RSR_CF, 0);
+
+ /* Read counters. */
+ sec = readb(priv->base + RTCA3_RSECCNT);
+ min = readb(priv->base + RTCA3_RMINCNT);
+ hour = readb(priv->base + RTCA3_RHRCNT);
+ wday = readb(priv->base + RTCA3_RWKCNT);
+ mday = readb(priv->base + RTCA3_RDAYCNT);
+ month = readb(priv->base + RTCA3_RMONCNT);
+ year = readw(priv->base + RTCA3_RYRCNT);
+
+ tmp = readb(priv->base + RTCA3_RSR);
+
+ /*
+ * We cannot generate carries due to reading 64Hz counter as
+ * the driver doesn't implement carry, thus, carries will be
+ * generated once per seconds. Add a timeout of 5 trials here
+ * to avoid infinite loop, if any.
+ */
+ } while ((tmp & RTCA3_RSR_CF) && ++trials < 5);
+
+ if (trials >= 5)
+ return -ETIMEDOUT;
+
+ tm->tm_sec = bcd2bin(FIELD_GET(RTCA3_RSECCNT_SEC, sec));
+ tm->tm_min = bcd2bin(FIELD_GET(RTCA3_RMINCNT_MIN, min));
+ tm->tm_hour = bcd2bin(FIELD_GET(RTCA3_RHRCNT_HR, hour));
+ tm->tm_wday = bcd2bin(FIELD_GET(RTCA3_RWKCNT_WK, wday));
+ tm->tm_mday = bcd2bin(FIELD_GET(RTCA3_RDAYCNT_DAY, mday));
+ tm->tm_mon = bcd2bin(FIELD_GET(RTCA3_RMONCNT_MONTH, month)) - 1;
+ year = FIELD_GET(RTCA3_RYRCNT_YEAR, year);
+ year100 = bcd2bin((year == 0x99) ? 0x19 : 0x20);
+ tm->tm_year = (year100 * 100 + bcd2bin(year)) - 1900;
+
+ return 0;
+}
+
+static int rtca3_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ u8 rcr2, tmp;
+ int ret;
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ /* Stop the RTC. */
+ rcr2 = readb(priv->base + RTCA3_RCR2);
+ writeb(rcr2 & ~RTCA3_RCR2_START, priv->base + RTCA3_RCR2);
+ ret = readb_poll_timeout_atomic(priv->base + RTCA3_RCR2, tmp,
+ !(tmp & RTCA3_RCR2_START),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /* Update time. */
+ writeb(bin2bcd(tm->tm_sec), priv->base + RTCA3_RSECCNT);
+ writeb(bin2bcd(tm->tm_min), priv->base + RTCA3_RMINCNT);
+ writeb(bin2bcd(tm->tm_hour), priv->base + RTCA3_RHRCNT);
+ writeb(bin2bcd(tm->tm_wday), priv->base + RTCA3_RWKCNT);
+ writeb(bin2bcd(tm->tm_mday), priv->base + RTCA3_RDAYCNT);
+ writeb(bin2bcd(tm->tm_mon + 1), priv->base + RTCA3_RMONCNT);
+ writew(bin2bcd(tm->tm_year % 100), priv->base + RTCA3_RYRCNT);
+
+ /* Make sure we can read back the counters. */
+ rtca3_prepare_cntalrm_regs_for_read(priv, true);
+
+ /* Start RTC. */
+ writeb(rcr2 | RTCA3_RCR2_START, priv->base + RTCA3_RCR2);
+ return readb_poll_timeout_atomic(priv->base + RTCA3_RCR2, tmp,
+ (tmp & RTCA3_RCR2_START),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+}
+
+static int rtca3_alarm_irq_set_helper(struct rtca3_priv *priv,
+ u8 interrupts,
+ unsigned int enabled)
+{
+ u8 tmp, val;
+
+ if (enabled) {
+ /*
+ * AIE, CIE, PIE bit indexes in RSR corresponds with
+ * those on RCR1. Same interrupts mask can be used.
+ */
+ rtca3_byte_update_bits(priv, RTCA3_RSR, interrupts, 0);
+ val = interrupts;
+ } else {
+ val = 0;
+ }
+
+ rtca3_byte_update_bits(priv, RTCA3_RCR1, interrupts, val);
+ return readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp,
+ ((tmp & interrupts) == val),
+ 10, RTCA3_IRQSET_TIMEOUT_US);
+}
+
+static int rtca3_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ return rtca3_alarm_irq_set_helper(priv, RTCA3_RCR1_AIE, enabled);
+}
+
+static int rtca3_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ u8 sec, min, hour, wday, mday, month;
+ struct rtc_time *tm = &wkalrm->time;
+ u32 year100;
+ u16 year;
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ sec = readb(priv->base + RTCA3_RSECAR);
+ min = readb(priv->base + RTCA3_RMINAR);
+ hour = readb(priv->base + RTCA3_RHRAR);
+ wday = readb(priv->base + RTCA3_RWKAR);
+ mday = readb(priv->base + RTCA3_RDAYAR);
+ month = readb(priv->base + RTCA3_RMONAR);
+ year = readw(priv->base + RTCA3_RYRAR);
+
+ tm->tm_sec = bcd2bin(FIELD_GET(RTCA3_RSECAR_SEC, sec));
+ tm->tm_min = bcd2bin(FIELD_GET(RTCA3_RMINAR_MIN, min));
+ tm->tm_hour = bcd2bin(FIELD_GET(RTCA3_RHRAR_HR, hour));
+ tm->tm_wday = bcd2bin(FIELD_GET(RTCA3_RWKAR_DAYW, wday));
+ tm->tm_mday = bcd2bin(FIELD_GET(RTCA3_RDAYAR_DATE, mday));
+ tm->tm_mon = bcd2bin(FIELD_GET(RTCA3_RMONAR_MON, month)) - 1;
+ year = FIELD_GET(RTCA3_RYRAR_YR, year);
+ year100 = bcd2bin((year == 0x99) ? 0x19 : 0x20);
+ tm->tm_year = (year100 * 100 + bcd2bin(year)) - 1900;
+
+ wkalrm->enabled = !!(readb(priv->base + RTCA3_RCR1) & RTCA3_RCR1_AIE);
+
+ return 0;
+}
+
+static int rtca3_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ struct rtc_time *tm = &wkalrm->time;
+ u8 rcr1, tmp;
+ int ret;
+
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ tmp = readb(priv->base + RTCA3_RCR2);
+ if (!(tmp & RTCA3_RCR2_START))
+ return -EPERM;
+
+ /* Disable AIE to prevent false interrupts. */
+ rcr1 = readb(priv->base + RTCA3_RCR1);
+ rcr1 &= ~RTCA3_RCR1_AIE;
+ writeb(rcr1, priv->base + RTCA3_RCR1);
+ ret = readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp,
+ !(tmp & RTCA3_RCR1_AIE),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /* Set the time and enable the alarm. */
+ writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_sec), priv->base + RTCA3_RSECAR);
+ writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_min), priv->base + RTCA3_RMINAR);
+ writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_hour), priv->base + RTCA3_RHRAR);
+ writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_wday), priv->base + RTCA3_RWKAR);
+ writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_mday), priv->base + RTCA3_RDAYAR);
+ writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_mon + 1), priv->base + RTCA3_RMONAR);
+
+ writew(bin2bcd(tm->tm_year % 100), priv->base + RTCA3_RYRAR);
+ writeb(RTCA3_AR_ENB, priv->base + RTCA3_RYRAREN);
+
+ /* Make sure we can read back the counters. */
+ rtca3_prepare_cntalrm_regs_for_read(priv, false);
+
+ /* Need to wait for 2 * 1/64 periodic interrupts to be generated. */
+ atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_INIT);
+ reinit_completion(&priv->set_alarm_completion);
+
+ /* Enable periodic interrupt. */
+ rcr1 |= RTCA3_RCR1_PIE;
+ writeb(rcr1, priv->base + RTCA3_RCR1);
+ ret = readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp,
+ (tmp & RTCA3_RCR1_PIE),
+ 10, RTCA3_IRQSET_TIMEOUT_US);
+ }
+
+ if (ret)
+ goto setup_failed;
+
+ /* Wait for the 2 * 1/64 periodic interrupts. */
+ ret = wait_for_completion_interruptible_timeout(&priv->set_alarm_completion,
+ msecs_to_jiffies(500));
+ if (ret <= 0) {
+ ret = -ETIMEDOUT;
+ goto setup_failed;
+ }
+
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ ret = rtca3_alarm_irq_set_helper(priv, RTCA3_RCR1_AIE, wkalrm->enabled);
+ atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_DONE);
+ }
+
+ return ret;
+
+setup_failed:
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ /*
+ * Disable PIE to avoid interrupt storm in case HW needed more than
+ * specified timeout for setup.
+ */
+ writeb(rcr1 & ~RTCA3_RCR1_PIE, priv->base + RTCA3_RCR1);
+ readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp, !(tmp & ~RTCA3_RCR1_PIE),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_DONE);
+ }
+
+ return ret;
+}
+
+static int rtca3_read_offset(struct device *dev, long *offset)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ u8 val, radj, cycles;
+ u32 ppb_per_cycle;
+
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ radj = readb(priv->base + RTCA3_RADJ);
+ val = readb(priv->base + RTCA3_RCR2);
+ }
+
+ cycles = FIELD_GET(RTCA3_RADJ_ADJ, radj);
+
+ if (!cycles) {
+ *offset = 0;
+ return 0;
+ }
+
+ if (val & RTCA3_RCR2_ADJP)
+ ppb_per_cycle = priv->ppb.ten_sec;
+ else
+ ppb_per_cycle = priv->ppb.sixty_sec;
+
+ *offset = cycles * ppb_per_cycle;
+ val = FIELD_GET(RTCA3_RADJ_PMADJ, radj);
+ if (val == RTCA3_RADJ_PMADJ_SUB)
+ *offset = -(*offset);
+
+ return 0;
+}
+
+static int rtca3_set_offset(struct device *dev, long offset)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ int cycles, cycles10, cycles60;
+ u8 radj, adjp, tmp;
+ int ret;
+
+ /*
+ * Automatic time error adjustment could be set at intervals of 10
+ * or 60 seconds.
+ */
+ cycles10 = DIV_ROUND_CLOSEST(offset, priv->ppb.ten_sec);
+ cycles60 = DIV_ROUND_CLOSEST(offset, priv->ppb.sixty_sec);
+
+ /* We can set b/w 1 and 63 clock cycles. */
+ if (cycles60 >= -RTCA3_RADJ_ADJ_MAX &&
+ cycles60 <= RTCA3_RADJ_ADJ_MAX) {
+ cycles = cycles60;
+ adjp = 0;
+ } else if (cycles10 >= -RTCA3_RADJ_ADJ_MAX &&
+ cycles10 <= RTCA3_RADJ_ADJ_MAX) {
+ cycles = cycles10;
+ adjp = RTCA3_RCR2_ADJP;
+ } else {
+ return -ERANGE;
+ }
+
+ radj = FIELD_PREP(RTCA3_RADJ_ADJ, abs(cycles));
+ if (!cycles)
+ radj |= FIELD_PREP(RTCA3_RADJ_PMADJ, RTCA3_RADJ_PMADJ_NONE);
+ else if (cycles > 0)
+ radj |= FIELD_PREP(RTCA3_RADJ_PMADJ, RTCA3_RADJ_PMADJ_ADD);
+ else
+ radj |= FIELD_PREP(RTCA3_RADJ_PMADJ, RTCA3_RADJ_PMADJ_SUB);
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ tmp = readb(priv->base + RTCA3_RCR2);
+
+ if ((tmp & RTCA3_RCR2_ADJP) != adjp) {
+ /* RADJ.PMADJ need to be set to zero before setting RCR2.ADJP. */
+ writeb(0, priv->base + RTCA3_RADJ);
+ ret = readb_poll_timeout_atomic(priv->base + RTCA3_RADJ, tmp, !tmp,
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ rtca3_byte_update_bits(priv, RTCA3_RCR2, RTCA3_RCR2_ADJP, adjp);
+ ret = readb_poll_timeout_atomic(priv->base + RTCA3_RCR2, tmp,
+ ((tmp & RTCA3_RCR2_ADJP) == adjp),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
+ }
+
+ writeb(radj, priv->base + RTCA3_RADJ);
+ return readb_poll_timeout_atomic(priv->base + RTCA3_RADJ, tmp, (tmp == radj),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+}
+
+static const struct rtc_class_ops rtca3_ops = {
+ .read_time = rtca3_read_time,
+ .set_time = rtca3_set_time,
+ .read_alarm = rtca3_read_alarm,
+ .set_alarm = rtca3_set_alarm,
+ .alarm_irq_enable = rtca3_alarm_irq_enable,
+ .set_offset = rtca3_set_offset,
+ .read_offset = rtca3_read_offset,
+};
+
+static int rtca3_initial_setup(struct clk *clk, struct rtca3_priv *priv)
+{
+ unsigned long osc32k_rate;
+ u8 val, tmp, mask;
+ u32 sleep_us;
+ int ret;
+
+ osc32k_rate = clk_get_rate(clk);
+ if (!osc32k_rate)
+ return -EINVAL;
+
+ sleep_us = DIV_ROUND_UP_ULL(1000000ULL, osc32k_rate) * 6;
+
+ priv->ppb.ten_sec = DIV_ROUND_CLOSEST_ULL(1000000000ULL, (osc32k_rate * 10));
+ priv->ppb.sixty_sec = DIV_ROUND_CLOSEST_ULL(1000000000ULL, (osc32k_rate * 60));
+
+ /*
+ * According to HW manual (section 22.4.2. Clock and count mode setting procedure)
+ * we need to wait at least 6 cycles of the 32KHz clock after clock was enabled.
+ */
+ usleep_range(sleep_us, sleep_us + 10);
+
+ /* Disable all interrupts. */
+ mask = RTCA3_RCR1_AIE | RTCA3_RCR1_CIE | RTCA3_RCR1_PIE;
+ ret = rtca3_alarm_irq_set_helper(priv, mask, 0);
+ if (ret)
+ return ret;
+
+ mask = RTCA3_RCR2_START | RTCA3_RCR2_HR24;
+ val = readb(priv->base + RTCA3_RCR2);
+ /* Nothing to do if already started in 24 hours and calendar count mode. */
+ if ((val & mask) == mask)
+ return 0;
+
+ /* Reconfigure the RTC in 24 hours and calendar count mode. */
+ mask = RTCA3_RCR2_START | RTCA3_RCR2_CNTMD;
+ writeb(0, priv->base + RTCA3_RCR2);
+ ret = readb_poll_timeout(priv->base + RTCA3_RCR2, tmp, !(tmp & mask),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /*
+ * Set 24 hours mode. According to HW manual (section 22.3.19. RTC Control
+ * Register 2) this needs to be done separate from stop operation.
+ */
+ mask = RTCA3_RCR2_HR24;
+ val = RTCA3_RCR2_HR24;
+ writeb(val, priv->base + RTCA3_RCR2);
+ ret = readb_poll_timeout(priv->base + RTCA3_RCR2, tmp, (tmp & mask),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /* Execute reset. */
+ mask = RTCA3_RCR2_RESET;
+ writeb(val | RTCA3_RCR2_RESET, priv->base + RTCA3_RCR2);
+ ret = readb_poll_timeout(priv->base + RTCA3_RCR2, tmp, !(tmp & mask),
+ 10, RTCA3_RESET_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /*
+ * According to HW manual (section 22.6.3. Notes on writing to and reading
+ * from registers) after reset we need to wait 6 clock cycles before
+ * writing to RTC registers.
+ */
+ usleep_range(sleep_us, sleep_us + 10);
+
+ /* Set no adjustment. */
+ writeb(0, priv->base + RTCA3_RADJ);
+ ret = readb_poll_timeout(priv->base + RTCA3_RADJ, tmp, !tmp, 10,
+ RTCA3_DEFAULT_TIMEOUT_US);
+
+ /* Start the RTC and enable automatic time error adjustment. */
+ mask = RTCA3_RCR2_START | RTCA3_RCR2_AADJE;
+ val |= RTCA3_RCR2_START | RTCA3_RCR2_AADJE;
+ writeb(val, priv->base + RTCA3_RCR2);
+ ret = readb_poll_timeout(priv->base + RTCA3_RCR2, tmp, ((tmp & mask) == mask),
+ 10, RTCA3_START_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /*
+ * According to HW manual (section 22.6.4. Notes on writing to and reading
+ * from registers) we need to wait 1/128 seconds while the clock is operating
+ * (RCR2.START bit = 1) to be able to read the counters after a return from
+ * reset.
+ */
+ usleep_range(8000, 9000);
+
+ /* Set period interrupt to 1/64 seconds. It is necessary for alarm setup. */
+ val = FIELD_PREP(RTCA3_RCR1_PES, RTCA3_RCR1_PES_1_64_SEC);
+ rtca3_byte_update_bits(priv, RTCA3_RCR1, RTCA3_RCR1_PES, val);
+ return readb_poll_timeout(priv->base + RTCA3_RCR1, tmp, ((tmp & RTCA3_RCR1_PES) == val),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+}
+
+static int rtca3_request_irqs(struct platform_device *pdev, struct rtca3_priv *priv)
+{
+ struct device *dev = &pdev->dev;
+ int ret, irq;
+
+ irq = platform_get_irq_byname(pdev, "alarm");
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "Failed to get alarm IRQ!\n");
+
+ ret = devm_request_irq(dev, irq, rtca3_alarm_handler, 0, "rtca3-alarm", priv);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to request alarm IRQ!\n");
+ priv->wakeup_irq = irq;
+
+ irq = platform_get_irq_byname(pdev, "period");
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "Failed to get period IRQ!\n");
+
+ ret = devm_request_irq(dev, irq, rtca3_periodic_handler, 0, "rtca3-period", priv);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to request period IRQ!\n");
+
+ /*
+ * Driver doesn't implement carry handler. Just get the IRQ here
+ * for backward compatibility, in case carry support will be added later.
+ */
+ irq = platform_get_irq_byname(pdev, "carry");
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "Failed to get carry IRQ!\n");
+
+ return 0;
+}
+
+static void rtca3_action(void *data)
+{
+ struct device *dev = data;
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ int ret;
+
+ ret = reset_control_assert(priv->rstc);
+ if (ret)
+ dev_err(dev, "Failed to de-assert reset!");
+
+ ret = pm_runtime_put_sync(dev);
+ if (ret < 0)
+ dev_err(dev, "Failed to runtime suspend!");
+}
+
+static int rtca3_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rtca3_priv *priv;
+ struct clk *clk;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ priv->rstc = devm_reset_control_get_shared(dev, NULL);
+ if (IS_ERR(priv->rstc))
+ return PTR_ERR(priv->rstc);
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(priv->rstc);
+ if (ret) {
+ pm_runtime_put_sync(dev);
+ return ret;
+ }
+
+ dev_set_drvdata(dev, priv);
+ ret = devm_add_action_or_reset(dev, rtca3_action, dev);
+ if (ret)
+ return ret;
+
+ /*
+ * This must be an always-on clock to keep the RTC running even after
+ * driver is unbinded.
+ */
+ clk = devm_clk_get_enabled(dev, "counter");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ spin_lock_init(&priv->lock);
+ atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_DONE);
+ init_completion(&priv->set_alarm_completion);
+
+ ret = rtca3_initial_setup(clk, priv);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to setup the RTC!\n");
+
+ ret = rtca3_request_irqs(pdev, priv);
+ if (ret)
+ return ret;
+
+ device_init_wakeup(&pdev->dev, 1);
+
+ priv->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(priv->rtc_dev))
+ return PTR_ERR(priv->rtc_dev);
+
+ priv->rtc_dev->ops = &rtca3_ops;
+ priv->rtc_dev->max_user_freq = 256;
+ priv->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ priv->rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
+
+ return devm_rtc_register_device(priv->rtc_dev);
+}
+
+static void rtca3_remove(struct platform_device *pdev)
+{
+ struct rtca3_priv *priv = platform_get_drvdata(pdev);
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ /*
+ * Disable alarm, periodic interrupts. The RTC device cannot
+ * power up the system.
+ */
+ rtca3_alarm_irq_set_helper(priv, RTCA3_RCR1_AIE | RTCA3_RCR1_PIE, 0);
+}
+
+static int rtca3_suspend(struct device *dev)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+
+ if (!device_may_wakeup(dev))
+ return 0;
+
+ /* Alarm setup in progress. */
+ if (atomic_read(&priv->alrm_sstep) != RTCA3_ALRM_SSTEP_DONE)
+ return -EBUSY;
+
+ enable_irq_wake(priv->wakeup_irq);
+
+ return 0;
+}
+
+static int rtca3_clean_alarm(struct rtca3_priv *priv)
+{
+ struct rtc_device *rtc_dev = priv->rtc_dev;
+ time64_t alarm_time, now;
+ struct rtc_wkalrm alarm;
+ struct rtc_time tm;
+ u8 pending;
+ int ret;
+
+ ret = rtc_read_alarm(rtc_dev, &alarm);
+ if (ret)
+ return ret;
+
+ if (!alarm.enabled)
+ return 0;
+
+ ret = rtc_read_time(rtc_dev, &tm);
+ if (ret)
+ return ret;
+
+ alarm_time = rtc_tm_to_time64(&alarm.time);
+ now = rtc_tm_to_time64(&tm);
+ if (alarm_time >= now)
+ return 0;
+
+ /*
+ * Heuristically, it has been determined that when returning from deep
+ * sleep state the RTCA3_RSR.AF is zero even though the alarm expired.
+ * Call again the rtc_update_irq() if alarm helper detects this.
+ */
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ pending = rtca3_alarm_handler_helper(priv);
+ if (!pending)
+ rtc_update_irq(priv->rtc_dev, 1, RTC_AF | RTC_IRQF);
+
+ return 0;
+}
+
+static int rtca3_resume(struct device *dev)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+
+ if (!device_may_wakeup(dev))
+ return 0;
+
+ disable_irq_wake(priv->wakeup_irq);
+
+ /*
+ * According to the HW manual (section 22.6.4 Notes on writing to
+ * and reading from registers) we need to wait 1/128 seconds while
+ * RCR2.START = 1 to be able to read the counters after a return from low
+ * power consumption state.
+ */
+ mdelay(8);
+
+ /*
+ * The alarm cannot wake the system from deep sleep states. In case
+ * we return from deep sleep states and the alarm expired we need
+ * to disable it to avoid failures when setting another alarm.
+ */
+ return rtca3_clean_alarm(priv);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(rtca3_pm_ops, rtca3_suspend, rtca3_resume);
+
+static const struct of_device_id rtca3_of_match[] = {
+ { .compatible = "renesas,rz-rtca3", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rtca3_of_match);
+
+static struct platform_driver rtca3_platform_driver = {
+ .driver = {
+ .name = "rtc-rtca3",
+ .pm = pm_ptr(&rtca3_pm_ops),
+ .of_match_table = rtca3_of_match,
+ },
+ .probe = rtca3_probe,
+ .remove = rtca3_remove,
+};
+module_platform_driver(rtca3_platform_driver);
+
+MODULE_DESCRIPTION("Renesas RTCA-3 RTC driver");
+MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rtd119x.c b/drivers/rtc/rtc-rtd119x.c
index 29662dfd56fe..85a138db81d7 100644
--- a/drivers/rtc/rtc-rtd119x.c
+++ b/drivers/rtc/rtc-rtd119x.c
@@ -228,7 +228,7 @@ static void rtd119x_rtc_remove(struct platform_device *pdev)
static struct platform_driver rtd119x_rtc_driver = {
.probe = rtd119x_rtc_probe,
- .remove_new = rtd119x_rtc_remove,
+ .remove = rtd119x_rtc_remove,
.driver = {
.name = "rtd1295-rtc",
.of_match_table = rtd119x_rtc_dt_ids,
diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c
index 2f001c59c61d..868d1b1eb0f4 100644
--- a/drivers/rtc/rtc-rv3028.c
+++ b/drivers/rtc/rtc-rv3028.c
@@ -120,8 +120,9 @@ static ssize_t timestamp0_show(struct device *dev,
{
struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
struct rtc_time tm;
- int ret, count;
+ unsigned int count;
u8 date[6];
+ int ret;
ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
if (ret)
@@ -156,7 +157,8 @@ static ssize_t timestamp0_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
- int ret, count;
+ unsigned int count;
+ int ret;
ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
if (ret)
diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c
index 56ebbd4d0481..cb220807d925 100644
--- a/drivers/rtc/rtc-rzn1.c
+++ b/drivers/rtc/rtc-rzn1.c
@@ -7,7 +7,7 @@
* - 2022 Schneider Electric
*
* Authors:
- * - Michel Pollet <michel.pollet@bp.renesas.com>, <buserror@gmail.com>
+ * - Michel Pollet <buserror@gmail.com>
* - Miquel Raynal <miquel.raynal@bootlin.com>
*/
@@ -35,13 +35,13 @@
#define RZN1_RTC_CTL2_WUST BIT(5)
#define RZN1_RTC_CTL2_STOPPED (RZN1_RTC_CTL2_WAIT | RZN1_RTC_CTL2_WST)
-#define RZN1_RTC_SEC 0x14
-#define RZN1_RTC_MIN 0x18
-#define RZN1_RTC_HOUR 0x1c
-#define RZN1_RTC_WEEK 0x20
-#define RZN1_RTC_DAY 0x24
-#define RZN1_RTC_MONTH 0x28
-#define RZN1_RTC_YEAR 0x2c
+#define RZN1_RTC_TIME 0x30
+#define RZN1_RTC_TIME_MIN_SHIFT 8
+#define RZN1_RTC_TIME_HOUR_SHIFT 16
+#define RZN1_RTC_CAL 0x34
+#define RZN1_RTC_CAL_DAY_SHIFT 8
+#define RZN1_RTC_CAL_MON_SHIFT 16
+#define RZN1_RTC_CAL_YEAR_SHIFT 24
#define RZN1_RTC_SUBU 0x38
#define RZN1_RTC_SUBU_DEV BIT(7)
@@ -52,12 +52,8 @@
#define RZN1_RTC_ALW 0x48
#define RZN1_RTC_SECC 0x4c
-#define RZN1_RTC_MINC 0x50
-#define RZN1_RTC_HOURC 0x54
-#define RZN1_RTC_WEEKC 0x58
-#define RZN1_RTC_DAYC 0x5c
-#define RZN1_RTC_MONTHC 0x60
-#define RZN1_RTC_YEARC 0x64
+#define RZN1_RTC_TIMEC 0x68
+#define RZN1_RTC_CALC 0x6c
struct rzn1_rtc {
struct rtc_device *rtcdev;
@@ -66,26 +62,18 @@ struct rzn1_rtc {
static void rzn1_rtc_get_time_snapshot(struct rzn1_rtc *rtc, struct rtc_time *tm)
{
- tm->tm_sec = readl(rtc->base + RZN1_RTC_SECC);
- tm->tm_min = readl(rtc->base + RZN1_RTC_MINC);
- tm->tm_hour = readl(rtc->base + RZN1_RTC_HOURC);
- tm->tm_wday = readl(rtc->base + RZN1_RTC_WEEKC);
- tm->tm_mday = readl(rtc->base + RZN1_RTC_DAYC);
- tm->tm_mon = readl(rtc->base + RZN1_RTC_MONTHC);
- tm->tm_year = readl(rtc->base + RZN1_RTC_YEARC);
-}
-
-static unsigned int rzn1_rtc_tm_to_wday(struct rtc_time *tm)
-{
- time64_t time;
- unsigned int days;
- u32 secs;
+ u32 val;
- time = rtc_tm_to_time64(tm);
- days = div_s64_rem(time, 86400, &secs);
+ val = readl(rtc->base + RZN1_RTC_TIMEC);
+ tm->tm_sec = bcd2bin(val);
+ tm->tm_min = bcd2bin(val >> RZN1_RTC_TIME_MIN_SHIFT);
+ tm->tm_hour = bcd2bin(val >> RZN1_RTC_TIME_HOUR_SHIFT);
- /* day of the week, 1970-01-01 was a Thursday */
- return (days + 4) % 7;
+ val = readl(rtc->base + RZN1_RTC_CALC);
+ tm->tm_wday = val & 0x0f;
+ tm->tm_mday = bcd2bin(val >> RZN1_RTC_CAL_DAY_SHIFT);
+ tm->tm_mon = bcd2bin(val >> RZN1_RTC_CAL_MON_SHIFT) - 1;
+ tm->tm_year = bcd2bin(val >> RZN1_RTC_CAL_YEAR_SHIFT) + 100;
}
static int rzn1_rtc_read_time(struct device *dev, struct rtc_time *tm)
@@ -103,17 +91,9 @@ static int rzn1_rtc_read_time(struct device *dev, struct rtc_time *tm)
rzn1_rtc_get_time_snapshot(rtc, tm);
secs = readl(rtc->base + RZN1_RTC_SECC);
- if (tm->tm_sec != secs)
+ if (tm->tm_sec != bcd2bin(secs))
rzn1_rtc_get_time_snapshot(rtc, tm);
- tm->tm_sec = bcd2bin(tm->tm_sec);
- tm->tm_min = bcd2bin(tm->tm_min);
- tm->tm_hour = bcd2bin(tm->tm_hour);
- tm->tm_wday = bcd2bin(tm->tm_wday);
- tm->tm_mday = bcd2bin(tm->tm_mday);
- tm->tm_mon = bcd2bin(tm->tm_mon);
- tm->tm_year = bcd2bin(tm->tm_year);
-
return 0;
}
@@ -123,14 +103,6 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm)
u32 val;
int ret;
- tm->tm_sec = bin2bcd(tm->tm_sec);
- tm->tm_min = bin2bcd(tm->tm_min);
- tm->tm_hour = bin2bcd(tm->tm_hour);
- tm->tm_wday = bin2bcd(rzn1_rtc_tm_to_wday(tm));
- tm->tm_mday = bin2bcd(tm->tm_mday);
- tm->tm_mon = bin2bcd(tm->tm_mon);
- tm->tm_year = bin2bcd(tm->tm_year);
-
val = readl(rtc->base + RZN1_RTC_CTL2);
if (!(val & RZN1_RTC_CTL2_STOPPED)) {
/* Hold the counter if it was counting up */
@@ -144,13 +116,17 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm)
return ret;
}
- writel(tm->tm_sec, rtc->base + RZN1_RTC_SEC);
- writel(tm->tm_min, rtc->base + RZN1_RTC_MIN);
- writel(tm->tm_hour, rtc->base + RZN1_RTC_HOUR);
- writel(tm->tm_wday, rtc->base + RZN1_RTC_WEEK);
- writel(tm->tm_mday, rtc->base + RZN1_RTC_DAY);
- writel(tm->tm_mon, rtc->base + RZN1_RTC_MONTH);
- writel(tm->tm_year, rtc->base + RZN1_RTC_YEAR);
+ val = bin2bcd(tm->tm_sec);
+ val |= bin2bcd(tm->tm_min) << RZN1_RTC_TIME_MIN_SHIFT;
+ val |= bin2bcd(tm->tm_hour) << RZN1_RTC_TIME_HOUR_SHIFT;
+ writel(val, rtc->base + RZN1_RTC_TIME);
+
+ val = tm->tm_wday;
+ val |= bin2bcd(tm->tm_mday) << RZN1_RTC_CAL_DAY_SHIFT;
+ val |= bin2bcd(tm->tm_mon + 1) << RZN1_RTC_CAL_MON_SHIFT;
+ val |= bin2bcd(tm->tm_year - 100) << RZN1_RTC_CAL_YEAR_SHIFT;
+ writel(val, rtc->base + RZN1_RTC_CAL);
+
writel(0, rtc->base + RZN1_RTC_CTL2);
return 0;
@@ -405,7 +381,7 @@ MODULE_DEVICE_TABLE(of, rzn1_rtc_of_match);
static struct platform_driver rzn1_rtc_driver = {
.probe = rzn1_rtc_probe,
- .remove_new = rzn1_rtc_remove,
+ .remove = rzn1_rtc_remove,
.driver = {
.name = "rzn1-rtc",
.of_match_table = rzn1_rtc_of_match,
@@ -413,7 +389,7 @@ static struct platform_driver rzn1_rtc_driver = {
};
module_platform_driver(rzn1_rtc_driver);
-MODULE_AUTHOR("Michel Pollet <Michel.Pollet@bp.renesas.com");
+MODULE_AUTHOR("Michel Pollet <buserror@gmail.com>");
MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com");
MODULE_DESCRIPTION("RZ/N1 RTC driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 282238818f63..c0ac3bdb2f42 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -597,7 +597,7 @@ MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
static struct platform_driver s3c_rtc_driver = {
.probe = s3c_rtc_probe,
- .remove_new = s3c_rtc_remove,
+ .remove = s3c_rtc_remove,
.driver = {
.name = "s3c-rtc",
.pm = &s3c_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 0b2cfa8ca05b..13799b1abca1 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -341,7 +341,7 @@ MODULE_DEVICE_TABLE(of, sa1100_rtc_dt_ids);
static struct platform_driver sa1100_rtc_driver = {
.probe = sa1100_rtc_probe,
- .remove_new = sa1100_rtc_remove,
+ .remove = sa1100_rtc_remove,
.driver = {
.name = "sa1100-rtc",
.pm = &sa1100_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 27a191fa3704..a5df521876ba 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -678,7 +678,7 @@ static struct platform_driver sh_rtc_platform_driver __refdata = {
.pm = &sh_rtc_pm_ops,
.of_match_table = sh_rtc_of_match,
},
- .remove_new = __exit_p(sh_rtc_remove),
+ .remove = __exit_p(sh_rtc_remove),
};
module_platform_driver_probe(sh_rtc_platform_driver, sh_rtc_probe);
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c
index 1df5c7e94198..26eed927f8b3 100644
--- a/drivers/rtc/rtc-spear.c
+++ b/drivers/rtc/rtc-spear.c
@@ -475,7 +475,7 @@ MODULE_DEVICE_TABLE(of, spear_rtc_id_table);
static struct platform_driver spear_rtc_driver = {
.probe = spear_rtc_probe,
- .remove_new = spear_rtc_remove,
+ .remove = spear_rtc_remove,
.shutdown = spear_rtc_shutdown,
.driver = {
.name = "rtc-spear",
diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c
index d492a2d26600..c6d4522411b3 100644
--- a/drivers/rtc/rtc-st-lpc.c
+++ b/drivers/rtc/rtc-st-lpc.c
@@ -218,15 +218,14 @@ static int st_rtc_probe(struct platform_device *pdev)
return -EINVAL;
}
- ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler, 0,
- pdev->name, rtc);
+ ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler,
+ IRQF_NO_AUTOEN, pdev->name, rtc);
if (ret) {
dev_err(&pdev->dev, "Failed to request irq %i\n", rtc->irq);
return ret;
}
enable_irq_wake(rtc->irq);
- disable_irq(rtc->irq);
rtc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(rtc->clk))
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index 3e4f2ee22b0b..9f1a019ec8af 100644
--- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c
@@ -1287,7 +1287,7 @@ static const struct dev_pm_ops stm32_rtc_pm_ops = {
static struct platform_driver stm32_rtc_driver = {
.probe = stm32_rtc_probe,
- .remove_new = stm32_rtc_remove,
+ .remove = stm32_rtc_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &stm32_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index 7566d0a44af8..7afcd14aeee5 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -403,7 +403,7 @@ MODULE_DEVICE_TABLE(of, rtc_dt_ids);
static struct platform_driver stmp3xxx_rtcdrv = {
.probe = stmp3xxx_rtc_probe,
- .remove_new = stmp3xxx_rtc_remove,
+ .remove = stmp3xxx_rtc_remove,
.driver = {
.name = "stmp3xxx-rtc",
.pm = &stmp3xxx_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-sunplus.c b/drivers/rtc/rtc-sunplus.c
index 20c7e97c2fc8..9b1ce0e8ba27 100644
--- a/drivers/rtc/rtc-sunplus.c
+++ b/drivers/rtc/rtc-sunplus.c
@@ -344,7 +344,7 @@ static SIMPLE_DEV_PM_OPS(sp_rtc_pm_ops, sp_rtc_suspend, sp_rtc_resume);
static struct platform_driver sp_rtc_driver = {
.probe = sp_rtc_probe,
- .remove_new = sp_rtc_remove,
+ .remove = sp_rtc_remove,
.driver = {
.name = "sp7021-rtc",
.of_match_table = sp_rtc_of_match,
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c
index 441e0a66b215..79a3102c8354 100644
--- a/drivers/rtc/rtc-tegra.c
+++ b/drivers/rtc/rtc-tegra.c
@@ -399,7 +399,7 @@ static void tegra_rtc_shutdown(struct platform_device *pdev)
static struct platform_driver tegra_rtc_driver = {
.probe = tegra_rtc_probe,
- .remove_new = tegra_rtc_remove,
+ .remove = tegra_rtc_remove,
.shutdown = tegra_rtc_shutdown,
.driver = {
.name = "tegra_rtc",
diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c
index 20faf08c254c..e796729fc817 100644
--- a/drivers/rtc/rtc-tps6586x.c
+++ b/drivers/rtc/rtc-tps6586x.c
@@ -317,7 +317,7 @@ static struct platform_driver tps6586x_rtc_driver = {
.pm = &tps6586x_pm_ops,
},
.probe = tps6586x_rtc_probe,
- .remove_new = tps6586x_rtc_remove,
+ .remove = tps6586x_rtc_remove,
};
module_platform_driver(tps6586x_rtc_driver);
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index 4e24c12004f1..794429182b34 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -673,7 +673,7 @@ MODULE_DEVICE_TABLE(of, twl_rtc_of_match);
static struct platform_driver twl4030rtc_driver = {
.probe = twl_rtc_probe,
- .remove_new = twl_rtc_remove,
+ .remove = twl_rtc_remove,
.shutdown = twl_rtc_shutdown,
.driver = {
.name = "twl_rtc",
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c
index ccfa76513a2c..c8b568498016 100644
--- a/drivers/rtc/rtc-vt8500.c
+++ b/drivers/rtc/rtc-vt8500.c
@@ -251,7 +251,7 @@ MODULE_DEVICE_TABLE(of, wmt_dt_ids);
static struct platform_driver vt8500_rtc_driver = {
.probe = vt8500_rtc_probe,
- .remove_new = vt8500_rtc_remove,
+ .remove = vt8500_rtc_remove,
.driver = {
.name = "vt8500-rtc",
.of_match_table = wmt_dt_ids,
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
index 3c773cff2b39..6797eb4d2e49 100644
--- a/drivers/rtc/rtc-wm8350.c
+++ b/drivers/rtc/rtc-wm8350.c
@@ -459,7 +459,7 @@ static SIMPLE_DEV_PM_OPS(wm8350_rtc_pm_ops, wm8350_rtc_suspend,
static struct platform_driver wm8350_rtc_driver = {
.probe = wm8350_rtc_probe,
- .remove_new = wm8350_rtc_remove,
+ .remove = wm8350_rtc_remove,
.driver = {
.name = "wm8350-rtc",
.pm = &wm8350_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-xgene.c b/drivers/rtc/rtc-xgene.c
index f78efc9760c0..0813ea1a03c2 100644
--- a/drivers/rtc/rtc-xgene.c
+++ b/drivers/rtc/rtc-xgene.c
@@ -263,7 +263,7 @@ MODULE_DEVICE_TABLE(of, xgene_rtc_of_match);
static struct platform_driver xgene_rtc_driver = {
.probe = xgene_rtc_probe,
- .remove_new = xgene_rtc_remove,
+ .remove = xgene_rtc_remove,
.driver = {
.name = "xgene-rtc",
.pm = &xgene_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c
index 08ed171bdab4..af1abb69d1e3 100644
--- a/drivers/rtc/rtc-zynqmp.c
+++ b/drivers/rtc/rtc-zynqmp.c
@@ -382,7 +382,7 @@ MODULE_DEVICE_TABLE(of, xlnx_rtc_of_match);
static struct platform_driver xlnx_rtc_driver = {
.probe = xlnx_rtc_probe,
- .remove_new = xlnx_rtc_remove,
+ .remove = xlnx_rtc_remove,
.driver = {
.name = KBUILD_MODNAME,
.pm = &xlnx_rtc_pm_ops,
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index dcb3c32f027a..c763c50d1454 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -803,7 +803,6 @@ static struct attribute *con3215_drv_attrs[] = {
static struct attribute_group con3215_drv_attr_group = {
.attrs = con3215_drv_attrs,
- NULL,
};
static const struct attribute_group *con3215_drv_attr_groups[] = {
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index e14638936de6..26e1ea1940ec 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -453,7 +453,7 @@ static void ap_tasklet_fn(unsigned long dummy)
* important that no requests on any AP get lost.
*/
if (ap_irq_flag)
- xchg(ap_airq.lsi_ptr, 0);
+ WRITE_ONCE(*ap_airq.lsi_ptr, 0);
spin_lock_bh(&ap_queues_lock);
hash_for_each(ap_queues, bkt, aq, hnode) {
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 8c0b40d8eb39..a52c2690933f 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -360,10 +360,26 @@ static int vfio_ap_validate_nib(struct kvm_vcpu *vcpu, dma_addr_t *nib)
return 0;
}
-static int ensure_nib_shared(unsigned long addr, struct gmap *gmap)
+/**
+ * ensure_nib_shared() - Ensure the address of the NIB is secure and shared
+ * @addr: the physical (absolute) address of the NIB
+ *
+ * This function checks whether the NIB page, which has been pinned with
+ * vfio_pin_pages(), is a shared page belonging to a secure guest.
+ *
+ * It will call uv_pin_shared() on it; if the page was already pinned shared
+ * (i.e. if the NIB belongs to a secure guest and is shared), then 0
+ * (success) is returned. If the NIB was not shared, vfio_pin_pages() had
+ * exported it and now it does not belong to the secure guest anymore. In
+ * that case, an error is returned.
+ *
+ * Context: the NIB (at physical address @addr) has to be pinned with
+ * vfio_pin_pages() before calling this function.
+ *
+ * Return: 0 in case of success, otherwise an error < 0.
+ */
+static int ensure_nib_shared(unsigned long addr)
{
- int ret;
-
/*
* The nib has to be located in shared storage since guest and
* host access it. vfio_pin_pages() will do a pin shared and
@@ -374,12 +390,7 @@ static int ensure_nib_shared(unsigned long addr, struct gmap *gmap)
*
* If the page is already pinned shared the UV will return a success.
*/
- ret = uv_pin_shared(addr);
- if (ret) {
- /* vfio_pin_pages() likely exported the page so let's re-import */
- gmap_convert_to_secure(gmap, addr);
- }
- return ret;
+ return uv_pin_shared(addr);
}
/**
@@ -425,6 +436,7 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q,
return status;
}
+ /* The pin will probably be successful even if the NIB was not shared */
ret = vfio_pin_pages(&q->matrix_mdev->vdev, nib, 1,
IOMMU_READ | IOMMU_WRITE, &h_page);
switch (ret) {
@@ -447,7 +459,7 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q,
/* NIB in non-shared storage is a rc 6 for PV guests */
if (kvm_s390_pv_cpu_is_protected(vcpu) &&
- ensure_nib_shared(h_nib & PAGE_MASK, kvm->arch.gmap)) {
+ ensure_nib_shared(h_nib & PAGE_MASK)) {
vfio_unpin_pages(&q->matrix_mdev->vdev, nib, 1);
status.response_code = AP_RESPONSE_INVALID_ADDRESS;
return status;
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 32f94db6d6bf..f3a1ecb42128 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1274,7 +1274,7 @@ static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj,
}
static umode_t scsi_sdev_bin_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *attr, int i)
+ const struct bin_attribute *attr, int i)
{
struct device *dev = kobj_to_dev(kobj);
struct scsi_device *sdev = to_scsi_device(dev);
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
index 74350b5871dc..ea571eeb3078 100644
--- a/drivers/sh/intc/core.c
+++ b/drivers/sh/intc/core.c
@@ -209,7 +209,6 @@ int __init register_intc_controller(struct intc_desc *desc)
goto err0;
INIT_LIST_HEAD(&d->list);
- list_add_tail(&d->list, &intc_list);
raw_spin_lock_init(&d->lock);
INIT_RADIX_TREE(&d->tree, GFP_ATOMIC);
@@ -369,6 +368,7 @@ int __init register_intc_controller(struct intc_desc *desc)
d->skip_suspend = desc->skip_syscore_suspend;
+ list_add_tail(&d->list, &intc_list);
nr_intc_controllers++;
return 0;
diff --git a/drivers/soundwire/amd_init.c b/drivers/soundwire/amd_init.c
index 53d1d707ca1a..d11b60efda33 100644
--- a/drivers/soundwire/amd_init.c
+++ b/drivers/soundwire/amd_init.c
@@ -121,6 +121,7 @@ static struct sdw_amd_ctx *sdw_amd_probe_controller(struct sdw_amd_res *res)
sdw_pdata[index].instance = index;
sdw_pdata[index].acp_sdw_lock = res->acp_lock;
+ sdw_pdata[index].acp_rev = res->acp_rev;
pdevinfo[index].name = "amd_sdw_manager";
pdevinfo[index].id = index;
pdevinfo[index].parent = res->parent;
diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c
index 0d01849c3586..5a4bfaef65fb 100644
--- a/drivers/soundwire/amd_manager.c
+++ b/drivers/soundwire/amd_manager.c
@@ -433,12 +433,18 @@ static int amd_sdw_port_params(struct sdw_bus *bus, struct sdw_port_params *p_pa
u32 frame_fmt_reg, dpn_frame_fmt;
dev_dbg(amd_manager->dev, "p_params->num:0x%x\n", p_params->num);
- switch (amd_manager->instance) {
- case ACP_SDW0:
- frame_fmt_reg = sdw0_manager_dp_reg[p_params->num].frame_fmt_reg;
- break;
- case ACP_SDW1:
- frame_fmt_reg = sdw1_manager_dp_reg[p_params->num].frame_fmt_reg;
+ switch (amd_manager->acp_rev) {
+ case ACP63_PCI_REV_ID:
+ switch (amd_manager->instance) {
+ case ACP_SDW0:
+ frame_fmt_reg = acp63_sdw0_dp_reg[p_params->num].frame_fmt_reg;
+ break;
+ case ACP_SDW1:
+ frame_fmt_reg = acp63_sdw1_dp_reg[p_params->num].frame_fmt_reg;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
default:
return -EINVAL;
@@ -465,20 +471,28 @@ static int amd_sdw_transport_params(struct sdw_bus *bus,
u32 frame_fmt_reg, sample_int_reg, hctrl_dp0_reg;
u32 offset_reg, lane_ctrl_ch_en_reg;
- switch (amd_manager->instance) {
- case ACP_SDW0:
- frame_fmt_reg = sdw0_manager_dp_reg[params->port_num].frame_fmt_reg;
- sample_int_reg = sdw0_manager_dp_reg[params->port_num].sample_int_reg;
- hctrl_dp0_reg = sdw0_manager_dp_reg[params->port_num].hctrl_dp0_reg;
- offset_reg = sdw0_manager_dp_reg[params->port_num].offset_reg;
- lane_ctrl_ch_en_reg = sdw0_manager_dp_reg[params->port_num].lane_ctrl_ch_en_reg;
- break;
- case ACP_SDW1:
- frame_fmt_reg = sdw1_manager_dp_reg[params->port_num].frame_fmt_reg;
- sample_int_reg = sdw1_manager_dp_reg[params->port_num].sample_int_reg;
- hctrl_dp0_reg = sdw1_manager_dp_reg[params->port_num].hctrl_dp0_reg;
- offset_reg = sdw1_manager_dp_reg[params->port_num].offset_reg;
- lane_ctrl_ch_en_reg = sdw1_manager_dp_reg[params->port_num].lane_ctrl_ch_en_reg;
+ switch (amd_manager->acp_rev) {
+ case ACP63_PCI_REV_ID:
+ switch (amd_manager->instance) {
+ case ACP_SDW0:
+ frame_fmt_reg = acp63_sdw0_dp_reg[params->port_num].frame_fmt_reg;
+ sample_int_reg = acp63_sdw0_dp_reg[params->port_num].sample_int_reg;
+ hctrl_dp0_reg = acp63_sdw0_dp_reg[params->port_num].hctrl_dp0_reg;
+ offset_reg = acp63_sdw0_dp_reg[params->port_num].offset_reg;
+ lane_ctrl_ch_en_reg =
+ acp63_sdw0_dp_reg[params->port_num].lane_ctrl_ch_en_reg;
+ break;
+ case ACP_SDW1:
+ frame_fmt_reg = acp63_sdw1_dp_reg[params->port_num].frame_fmt_reg;
+ sample_int_reg = acp63_sdw1_dp_reg[params->port_num].sample_int_reg;
+ hctrl_dp0_reg = acp63_sdw1_dp_reg[params->port_num].hctrl_dp0_reg;
+ offset_reg = acp63_sdw1_dp_reg[params->port_num].offset_reg;
+ lane_ctrl_ch_en_reg =
+ acp63_sdw1_dp_reg[params->port_num].lane_ctrl_ch_en_reg;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
default:
return -EINVAL;
@@ -520,12 +534,20 @@ static int amd_sdw_port_enable(struct sdw_bus *bus,
u32 dpn_ch_enable;
u32 lane_ctrl_ch_en_reg;
- switch (amd_manager->instance) {
- case ACP_SDW0:
- lane_ctrl_ch_en_reg = sdw0_manager_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg;
- break;
- case ACP_SDW1:
- lane_ctrl_ch_en_reg = sdw1_manager_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg;
+ switch (amd_manager->acp_rev) {
+ case ACP63_PCI_REV_ID:
+ switch (amd_manager->instance) {
+ case ACP_SDW0:
+ lane_ctrl_ch_en_reg =
+ acp63_sdw0_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg;
+ break;
+ case ACP_SDW1:
+ lane_ctrl_ch_en_reg =
+ acp63_sdw1_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
default:
return -EINVAL;
@@ -910,6 +932,7 @@ static int amd_sdw_manager_probe(struct platform_device *pdev)
amd_manager->mmio = amd_manager->acp_mmio +
(amd_manager->instance * SDW_MANAGER_REG_OFFSET);
amd_manager->acp_sdw_lock = pdata->acp_sdw_lock;
+ amd_manager->acp_rev = pdata->acp_rev;
amd_manager->cols_index = sdw_find_col_index(AMD_SDW_DEFAULT_COLUMNS);
amd_manager->rows_index = sdw_find_row_index(AMD_SDW_DEFAULT_ROWS);
amd_manager->dev = dev;
@@ -926,15 +949,21 @@ static int amd_sdw_manager_probe(struct platform_device *pdev)
* information.
*/
amd_manager->bus.controller_id = 0;
-
- switch (amd_manager->instance) {
- case ACP_SDW0:
- amd_manager->num_dout_ports = AMD_SDW0_MAX_TX_PORTS;
- amd_manager->num_din_ports = AMD_SDW0_MAX_RX_PORTS;
- break;
- case ACP_SDW1:
- amd_manager->num_dout_ports = AMD_SDW1_MAX_TX_PORTS;
- amd_manager->num_din_ports = AMD_SDW1_MAX_RX_PORTS;
+ dev_dbg(dev, "acp_rev:0x%x\n", amd_manager->acp_rev);
+ switch (amd_manager->acp_rev) {
+ case ACP63_PCI_REV_ID:
+ switch (amd_manager->instance) {
+ case ACP_SDW0:
+ amd_manager->num_dout_ports = AMD_ACP63_SDW0_MAX_TX_PORTS;
+ amd_manager->num_din_ports = AMD_ACP63_SDW0_MAX_RX_PORTS;
+ break;
+ case ACP_SDW1:
+ amd_manager->num_dout_ports = AMD_ACP63_SDW1_MAX_TX_PORTS;
+ amd_manager->num_din_ports = AMD_ACP63_SDW1_MAX_RX_PORTS;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
default:
return -EINVAL;
diff --git a/drivers/soundwire/amd_manager.h b/drivers/soundwire/amd_manager.h
index 707065468e05..cc2170e4521e 100644
--- a/drivers/soundwire/amd_manager.h
+++ b/drivers/soundwire/amd_manager.h
@@ -155,12 +155,12 @@
#define AMD_SDW_IRQ_MASK_8TO11 0x000c7777
#define AMD_SDW_IRQ_ERROR_MASK 0xff
#define AMD_SDW_MAX_FREQ_NUM 1
-#define AMD_SDW0_MAX_TX_PORTS 3
-#define AMD_SDW0_MAX_RX_PORTS 3
-#define AMD_SDW1_MAX_TX_PORTS 1
-#define AMD_SDW1_MAX_RX_PORTS 1
-#define AMD_SDW0_MAX_DAI 6
-#define AMD_SDW1_MAX_DAI 2
+#define AMD_ACP63_SDW0_MAX_TX_PORTS 3
+#define AMD_ACP63_SDW0_MAX_RX_PORTS 3
+#define AMD_ACP63_SDW1_MAX_TX_PORTS 1
+#define AMD_ACP63_SDW1_MAX_RX_PORTS 1
+#define AMD_ACP63_SDW0_MAX_DAI 6
+#define AMD_ACP63_SDW1_MAX_DAI 2
#define AMD_SDW_SLAVE_0_ATTACHED 5
#define AMD_SDW_SSP_COUNTER_VAL 3
@@ -222,7 +222,7 @@ struct sdw_manager_dp_reg {
* in SoundWire DMA driver.
*/
-static struct sdw_manager_dp_reg sdw0_manager_dp_reg[AMD_SDW0_MAX_DAI] = {
+static struct sdw_manager_dp_reg acp63_sdw0_dp_reg[AMD_ACP63_SDW0_MAX_DAI] = {
{ACP_SW_AUDIO0_TX_FRAME_FORMAT, ACP_SW_AUDIO0_TX_SAMPLEINTERVAL, ACP_SW_AUDIO0_TX_HCTRL_DP0,
ACP_SW_AUDIO0_TX_OFFSET_DP0, ACP_SW_AUDIO0_TX_CHANNEL_ENABLE_DP0},
{ACP_SW_AUDIO1_TX_FRAME_FORMAT, ACP_SW_AUDIO1_TX_SAMPLEINTERVAL, ACP_SW_AUDIO1_TX_HCTRL,
@@ -237,7 +237,7 @@ static struct sdw_manager_dp_reg sdw0_manager_dp_reg[AMD_SDW0_MAX_DAI] = {
ACP_SW_AUDIO2_RX_OFFSET, ACP_SW_AUDIO2_RX_CHANNEL_ENABLE_DP0},
};
-static struct sdw_manager_dp_reg sdw1_manager_dp_reg[AMD_SDW1_MAX_DAI] = {
+static struct sdw_manager_dp_reg acp63_sdw1_dp_reg[AMD_ACP63_SDW1_MAX_DAI] = {
{ACP_SW_AUDIO1_TX_FRAME_FORMAT, ACP_SW_AUDIO1_TX_SAMPLEINTERVAL, ACP_SW_AUDIO1_TX_HCTRL,
ACP_SW_AUDIO1_TX_OFFSET, ACP_SW_AUDIO1_TX_CHANNEL_ENABLE_DP0},
{ACP_SW_AUDIO1_RX_FRAME_FORMAT, ACP_SW_AUDIO1_RX_SAMPLEINTERVAL, ACP_SW_AUDIO1_RX_HCTRL,
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index 263ca32f0c5c..d1dc62c34f1c 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -112,7 +112,7 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
/* Set higher order bits */
*bus->assigned = ~GENMASK(SDW_BROADCAST_DEV_NUM, SDW_ENUM_DEV_NUM);
- /* Set enumuration device number and broadcast device number */
+ /* Set enumeration device number and broadcast device number */
set_bit(SDW_ENUM_DEV_NUM, bus->assigned);
set_bit(SDW_BROADCAST_DEV_NUM, bus->assigned);
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c
index 05652e983539..f367670ea991 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -1378,6 +1378,31 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns)
}
/**
+ * sdw_cdns_soft_reset() - Cadence soft-reset
+ * @cdns: Cadence instance
+ */
+int sdw_cdns_soft_reset(struct sdw_cdns *cdns)
+{
+ int ret;
+
+ cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_SOFT_RST,
+ CDNS_MCP_CONTROL_SOFT_RST);
+
+ ret = cdns_config_update(cdns);
+ if (ret < 0) {
+ dev_err(cdns->dev, "%s: config update failed\n", __func__);
+ return ret;
+ }
+
+ ret = cdns_set_wait(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_SOFT_RST, 0);
+ if (ret < 0)
+ dev_err(cdns->dev, "%s: Soft Reset timed out\n", __func__);
+
+ return ret;
+}
+EXPORT_SYMBOL(sdw_cdns_soft_reset);
+
+/**
* sdw_cdns_init() - Cadence initialization
* @cdns: Cadence instance
*/
@@ -1400,6 +1425,11 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
cdns_ip_updatel(cdns, CDNS_IP_MCP_CONTROL, CDNS_IP_MCP_CONTROL_CMD_ACCEPT,
CDNS_IP_MCP_CONTROL_CMD_ACCEPT);
+ /* disable wakeup */
+ cdns_ip_updatel(cdns, CDNS_IP_MCP_CONTROL,
+ CDNS_IP_MCP_CONTROL_BLOCK_WAKEUP,
+ 0);
+
/* Configure mcp config */
val = cdns_readl(cdns, CDNS_MCP_CONFIG);
diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h
index e1d7969ba48a..c34fb050fe4f 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -168,6 +168,7 @@ int sdw_cdns_probe(struct sdw_cdns *cdns);
irqreturn_t sdw_cdns_irq(int irq, void *dev_id);
irqreturn_t sdw_cdns_thread(int irq, void *dev_id);
+int sdw_cdns_soft_reset(struct sdw_cdns *cdns);
int sdw_cdns_init(struct sdw_cdns *cdns);
int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
struct sdw_cdns_stream_config config);
diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c
index ae689d5d1ab9..599954d92752 100644
--- a/drivers/soundwire/intel_auxdevice.c
+++ b/drivers/soundwire/intel_auxdevice.c
@@ -41,6 +41,10 @@ static int md_flags;
module_param_named(sdw_md_flags, md_flags, int, 0444);
MODULE_PARM_DESC(sdw_md_flags, "SoundWire Intel Master device flags (0x0 all off)");
+static int mclk_divider;
+module_param_named(sdw_mclk_divider, mclk_divider, int, 0444);
+MODULE_PARM_DESC(sdw_mclk_divider, "SoundWire Intel mclk divider");
+
struct wake_capable_part {
const u16 mfg_id;
const u16 part_id;
@@ -142,8 +146,12 @@ static int sdw_master_read_intel_prop(struct sdw_bus *bus)
"intel-sdw-ip-clock",
&prop->mclk_freq);
- /* the values reported by BIOS are the 2x clock, not the bus clock */
- prop->mclk_freq /= 2;
+ if (mclk_divider)
+ /* use kernel parameter for BIOS or board work-arounds */
+ prop->mclk_freq /= mclk_divider;
+ else
+ /* the values reported by BIOS are the 2x clock, not the bus clock */
+ prop->mclk_freq /= 2;
fwnode_property_read_u32(link,
"intel-quirk-mask",
diff --git a/drivers/soundwire/intel_bus_common.c b/drivers/soundwire/intel_bus_common.c
index d3ff6c65b64c..ad1f8ebdbfc9 100644
--- a/drivers/soundwire/intel_bus_common.c
+++ b/drivers/soundwire/intel_bus_common.c
@@ -16,6 +16,12 @@ int intel_start_bus(struct sdw_intel *sdw)
struct sdw_bus *bus = &cdns->bus;
int ret;
+ ret = sdw_cdns_soft_reset(cdns);
+ if (ret < 0) {
+ dev_err(dev, "%s: unable to soft-reset Cadence IP: %d\n", __func__, ret);
+ return ret;
+ }
+
/*
* follow recommended programming flows to avoid timeouts when
* gsync is enabled
diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c
index e5d9df26d4dc..9d59f486edbe 100644
--- a/drivers/soundwire/mipi_disco.c
+++ b/drivers/soundwire/mipi_disco.c
@@ -23,6 +23,26 @@
#include <linux/soundwire/sdw.h>
#include "bus.h"
+static bool mipi_fwnode_property_read_bool(const struct fwnode_handle *fwnode,
+ const char *propname)
+{
+ int ret;
+ u8 val;
+
+ if (!fwnode_property_present(fwnode, propname))
+ return false;
+ ret = fwnode_property_read_u8_array(fwnode, propname, &val, 1);
+ if (ret < 0)
+ return false;
+ return !!val;
+}
+
+static bool mipi_device_property_read_bool(const struct device *dev,
+ const char *propname)
+{
+ return mipi_fwnode_property_read_bool(dev_fwnode(dev), propname);
+}
+
/**
* sdw_master_read_prop() - Read Master properties
* @bus: SDW bus instance
@@ -31,8 +51,11 @@ int sdw_master_read_prop(struct sdw_bus *bus)
{
struct sdw_master_prop *prop = &bus->prop;
struct fwnode_handle *link;
+ const char *scales_prop;
char name[32];
- int nval, i;
+ int nval;
+ int ret;
+ int i;
device_property_read_u32(bus->dev,
"mipi-sdw-sw-interface-revision",
@@ -48,11 +71,11 @@ int sdw_master_read_prop(struct sdw_bus *bus)
return -EIO;
}
- if (fwnode_property_read_bool(link,
+ if (mipi_fwnode_property_read_bool(link,
"mipi-sdw-clock-stop-mode0-supported"))
prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE0);
- if (fwnode_property_read_bool(link,
+ if (mipi_fwnode_property_read_bool(link,
"mipi-sdw-clock-stop-mode1-supported"))
prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1);
@@ -71,9 +94,11 @@ int sdw_master_read_prop(struct sdw_bus *bus)
return -ENOMEM;
}
- fwnode_property_read_u32_array(link,
+ ret = fwnode_property_read_u32_array(link,
"mipi-sdw-clock-frequencies-supported",
prop->clk_freq, prop->num_clk_freq);
+ if (ret < 0)
+ return ret;
}
/*
@@ -88,7 +113,12 @@ int sdw_master_read_prop(struct sdw_bus *bus)
}
}
- nval = fwnode_property_count_u32(link, "mipi-sdw-supported-clock-gears");
+ scales_prop = "mipi-sdw-supported-clock-scales";
+ nval = fwnode_property_count_u32(link, scales_prop);
+ if (nval == 0) {
+ scales_prop = "mipi-sdw-supported-clock-gears";
+ nval = fwnode_property_count_u32(link, scales_prop);
+ }
if (nval > 0) {
prop->num_clk_gears = nval;
prop->clk_gears = devm_kcalloc(bus->dev, prop->num_clk_gears,
@@ -99,10 +129,12 @@ int sdw_master_read_prop(struct sdw_bus *bus)
return -ENOMEM;
}
- fwnode_property_read_u32_array(link,
- "mipi-sdw-supported-clock-gears",
+ ret = fwnode_property_read_u32_array(link,
+ scales_prop,
prop->clk_gears,
prop->num_clk_gears);
+ if (ret < 0)
+ return ret;
}
fwnode_property_read_u32(link, "mipi-sdw-default-frame-rate",
@@ -114,7 +146,7 @@ int sdw_master_read_prop(struct sdw_bus *bus)
fwnode_property_read_u32(link, "mipi-sdw-default-frame-col-size",
&prop->default_col);
- prop->dynamic_frame = fwnode_property_read_bool(link,
+ prop->dynamic_frame = mipi_fwnode_property_read_bool(link,
"mipi-sdw-dynamic-frame-shape");
fwnode_property_read_u32(link, "mipi-sdw-command-error-threshold",
@@ -131,6 +163,7 @@ static int sdw_slave_read_dp0(struct sdw_slave *slave,
struct sdw_dp0_prop *dp0)
{
int nval;
+ int ret;
fwnode_property_read_u32(port, "mipi-sdw-port-max-wordlength",
&dp0->max_word);
@@ -148,20 +181,38 @@ static int sdw_slave_read_dp0(struct sdw_slave *slave,
if (!dp0->words)
return -ENOMEM;
- fwnode_property_read_u32_array(port,
+ ret = fwnode_property_read_u32_array(port,
"mipi-sdw-port-wordlength-configs",
dp0->words, dp0->num_words);
+ if (ret < 0)
+ return ret;
}
- dp0->BRA_flow_controlled = fwnode_property_read_bool(port,
+ dp0->BRA_flow_controlled = mipi_fwnode_property_read_bool(port,
"mipi-sdw-bra-flow-controlled");
- dp0->simple_ch_prep_sm = fwnode_property_read_bool(port,
+ dp0->simple_ch_prep_sm = mipi_fwnode_property_read_bool(port,
"mipi-sdw-simplified-channel-prepare-sm");
- dp0->imp_def_interrupts = fwnode_property_read_bool(port,
+ dp0->imp_def_interrupts = mipi_fwnode_property_read_bool(port,
"mipi-sdw-imp-def-dp0-interrupts-supported");
+ nval = fwnode_property_count_u32(port, "mipi-sdw-lane-list");
+ if (nval > 0) {
+ dp0->num_lanes = nval;
+ dp0->lane_list = devm_kcalloc(&slave->dev,
+ dp0->num_lanes, sizeof(*dp0->lane_list),
+ GFP_KERNEL);
+ if (!dp0->lane_list)
+ return -ENOMEM;
+
+ ret = fwnode_property_read_u32_array(port,
+ "mipi-sdw-lane-list",
+ dp0->lane_list, dp0->num_lanes);
+ if (ret < 0)
+ return ret;
+ }
+
return 0;
}
@@ -171,9 +222,10 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
{
struct fwnode_handle *node;
u32 bit, i = 0;
- int nval;
unsigned long addr;
char name[40];
+ int nval;
+ int ret;
addr = ports;
/* valid ports are 1 to 14 so apply mask */
@@ -208,9 +260,11 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
return -ENOMEM;
}
- fwnode_property_read_u32_array(node,
+ ret = fwnode_property_read_u32_array(node,
"mipi-sdw-port-wordlength-configs",
dpn[i].words, dpn[i].num_words);
+ if (ret < 0)
+ return ret;
}
fwnode_property_read_u32(node, "mipi-sdw-data-port-type",
@@ -220,7 +274,7 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
"mipi-sdw-max-grouping-supported",
&dpn[i].max_grouping);
- dpn[i].simple_ch_prep_sm = fwnode_property_read_bool(node,
+ dpn[i].simple_ch_prep_sm = mipi_fwnode_property_read_bool(node,
"mipi-sdw-simplified-channelprepare-sm");
fwnode_property_read_u32(node,
@@ -249,9 +303,11 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
return -ENOMEM;
}
- fwnode_property_read_u32_array(node,
+ ret = fwnode_property_read_u32_array(node,
"mipi-sdw-channel-number-list",
dpn[i].channels, dpn[i].num_channels);
+ if (ret < 0)
+ return ret;
}
nval = fwnode_property_count_u32(node, "mipi-sdw-channel-combination-list");
@@ -266,10 +322,12 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
return -ENOMEM;
}
- fwnode_property_read_u32_array(node,
+ ret = fwnode_property_read_u32_array(node,
"mipi-sdw-channel-combination-list",
dpn[i].ch_combinations,
dpn[i].num_ch_combinations);
+ if (ret < 0)
+ return ret;
}
fwnode_property_read_u32(node,
@@ -278,13 +336,27 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
fwnode_property_read_u32(node, "mipi-sdw-max-async-buffer",
&dpn[i].max_async_buffer);
- dpn[i].block_pack_mode = fwnode_property_read_bool(node,
+ dpn[i].block_pack_mode = mipi_fwnode_property_read_bool(node,
"mipi-sdw-block-packing-mode");
fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type",
&dpn[i].port_encoding);
- /* TODO: Read audio mode */
+ nval = fwnode_property_count_u32(node, "mipi-sdw-lane-list");
+ if (nval > 0) {
+ dpn[i].num_lanes = nval;
+ dpn[i].lane_list = devm_kcalloc(&slave->dev,
+ dpn[i].num_lanes, sizeof(*dpn[i].lane_list),
+ GFP_KERNEL);
+ if (!dpn[i].lane_list)
+ return -ENOMEM;
+
+ ret = fwnode_property_read_u32_array(node,
+ "mipi-sdw-lane-list",
+ dpn[i].lane_list, dpn[i].num_lanes);
+ if (ret < 0)
+ return ret;
+ }
fwnode_handle_put(node);
@@ -304,42 +376,46 @@ int sdw_slave_read_prop(struct sdw_slave *slave)
struct device *dev = &slave->dev;
struct fwnode_handle *port;
int nval;
+ int ret;
device_property_read_u32(dev, "mipi-sdw-sw-interface-revision",
&prop->mipi_revision);
- prop->wake_capable = device_property_read_bool(dev,
+ prop->wake_capable = mipi_device_property_read_bool(dev,
"mipi-sdw-wake-up-unavailable");
prop->wake_capable = !prop->wake_capable;
- prop->test_mode_capable = device_property_read_bool(dev,
+ prop->test_mode_capable = mipi_device_property_read_bool(dev,
"mipi-sdw-test-mode-supported");
prop->clk_stop_mode1 = false;
- if (device_property_read_bool(dev,
+ if (mipi_device_property_read_bool(dev,
"mipi-sdw-clock-stop-mode1-supported"))
prop->clk_stop_mode1 = true;
- prop->simple_clk_stop_capable = device_property_read_bool(dev,
+ prop->simple_clk_stop_capable = mipi_device_property_read_bool(dev,
"mipi-sdw-simplified-clockstopprepare-sm-supported");
device_property_read_u32(dev, "mipi-sdw-clockstopprepare-timeout",
&prop->clk_stop_timeout);
- device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout",
- &prop->ch_prep_timeout);
+ ret = device_property_read_u32(dev, "mipi-sdw-peripheral-channelprepare-timeout",
+ &prop->ch_prep_timeout);
+ if (ret < 0)
+ device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout",
+ &prop->ch_prep_timeout);
device_property_read_u32(dev,
"mipi-sdw-clockstopprepare-hard-reset-behavior",
&prop->reset_behave);
- prop->high_PHY_capable = device_property_read_bool(dev,
+ prop->high_PHY_capable = mipi_device_property_read_bool(dev,
"mipi-sdw-highPHY-capable");
- prop->paging_support = device_property_read_bool(dev,
+ prop->paging_support = mipi_device_property_read_bool(dev,
"mipi-sdw-paging-support");
- prop->bank_delay_support = device_property_read_bool(dev,
+ prop->bank_delay_support = mipi_device_property_read_bool(dev,
"mipi-sdw-bank-delay-support");
device_property_read_u32(dev,
@@ -354,7 +430,17 @@ int sdw_slave_read_prop(struct sdw_slave *slave)
device_property_read_u32(dev, "mipi-sdw-sink-port-list",
&prop->sink_ports);
- /* Read dp0 properties */
+ device_property_read_u32(dev, "mipi-sdw-sdca-interrupt-register-list",
+ &prop->sdca_interrupt_register_list);
+
+ prop->commit_register_supported = mipi_device_property_read_bool(dev,
+ "mipi-sdw-commit-register-supported");
+
+ /*
+ * Read dp0 properties - we don't rely on the 'mipi-sdw-dp-0-supported'
+ * property since the 'mipi-sdw-dp0-subproperties' property is logically
+ * equivalent.
+ */
port = device_get_named_child_node(dev, "mipi-sdw-dp-0-subproperties");
if (!port) {
dev_dbg(dev, "DP0 node not found!!\n");
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index aed57002fd0e..2b403b14066c 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -1173,7 +1173,7 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl,
else
sconfig.direction = SDW_DATA_DIR_RX;
- /* hw parameters wil be ignored as we only support PDM */
+ /* hw parameters will be ignored as we only support PDM */
sconfig.ch_count = 1;
sconfig.frame_rate = params_rate(params);
sconfig.type = stream->type;
diff --git a/drivers/soundwire/sysfs_slave.c b/drivers/soundwire/sysfs_slave.c
index f4259710dd0f..c5c22d1708ec 100644
--- a/drivers/soundwire/sysfs_slave.c
+++ b/drivers/soundwire/sysfs_slave.c
@@ -215,7 +215,7 @@ const struct attribute_group *sdw_attr_groups[] = {
/*
* the status is shown in capital letters for UNATTACHED and RESERVED
- * on purpose, to highligh users to the fact that these status values
+ * on purpose, to highlight users to the fact that these status values
* are not expected.
*/
static const char *const slave_status[] = {
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index 91108ddfaef2..316bce577081 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -183,7 +183,7 @@ static const char *atmel_qspi_reg_name(u32 offset, char *tmp, size_t sz)
case QSPI_MR:
return "MR";
case QSPI_RD:
- return "MR";
+ return "RD";
case QSPI_TD:
return "TD";
case QSPI_SR:
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 0b6b0151b3a3..eeb7d082c247 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1685,7 +1685,7 @@ static unsigned int spi_imx_transfer_estimate_time_us(struct spi_transfer *trans
words = DIV_ROUND_UP(transfer->len * BITS_PER_BYTE, transfer->bits_per_word);
word_delay_us = DIV_ROUND_CLOSEST(spi_delay_to_ns(&transfer->word_delay, transfer),
NSEC_PER_USEC);
- result += words * word_delay_us;
+ result += (u64)words * word_delay_us;
}
return min(result, U32_MAX);
diff --git a/drivers/spi/spi-rockchip-sfc.c b/drivers/spi/spi-rockchip-sfc.c
index 316e3db88492..69d0f2175568 100644
--- a/drivers/spi/spi-rockchip-sfc.c
+++ b/drivers/spi/spi-rockchip-sfc.c
@@ -503,7 +503,7 @@ static int rockchip_sfc_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op
rockchip_sfc_adjust_op_work((struct spi_mem_op *)op);
rockchip_sfc_xfer_setup(sfc, mem, op, len);
if (len) {
- if (likely(sfc->use_dma) && len >= SFC_DMA_TRANS_THRETHOLD) {
+ if (likely(sfc->use_dma) && len >= SFC_DMA_TRANS_THRETHOLD && !(len & 0x3)) {
init_completion(&sfc->cp);
rockchip_sfc_irq_unmask(sfc, SFC_IMR_DMA);
ret = rockchip_sfc_xfer_data_dma(sfc, op, len);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 460a49d9a0de..ff1add2ecb91 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -424,6 +424,16 @@ static int spi_probe(struct device *dev)
spi->irq = 0;
}
+ if (has_acpi_companion(dev) && spi->irq < 0) {
+ struct acpi_device *adev = to_acpi_device_node(dev->fwnode);
+
+ spi->irq = acpi_dev_gpio_irq_get(adev, 0);
+ if (spi->irq == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ if (spi->irq < 0)
+ spi->irq = 0;
+ }
+
ret = dev_pm_domain_attach(dev, true);
if (ret)
return ret;
@@ -2866,9 +2876,6 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,
acpi_set_modalias(adev, acpi_device_hid(adev), spi->modalias,
sizeof(spi->modalias));
- if (spi->irq < 0)
- spi->irq = acpi_dev_gpio_irq_get(adev, 0);
-
acpi_device_set_enumerated(adev);
adev->power.flags.ignore_parent = true;
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 9ba9495fcc4b..ea843159b745 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -1763,14 +1763,13 @@ static int spmi_pmic_arb_register_buses(struct spmi_pmic_arb *pmic_arb,
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
- struct device_node *child;
int ret;
/* legacy mode doesn't provide child node for the bus */
if (of_device_is_compatible(node, "qcom,spmi-pmic-arb"))
return spmi_pmic_arb_bus_init(pdev, node, pmic_arb);
- for_each_available_child_of_node(node, child) {
+ for_each_available_child_of_node_scoped(node, child) {
if (of_node_name_eq(child, "spmi")) {
ret = spmi_pmic_arb_bus_init(pdev, child, pmic_arb);
if (ret)
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index fcdd559a8acf..075e775d3868 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -24,20 +24,10 @@ menuconfig STAGING
if STAGING
-source "drivers/staging/olpc_dcon/Kconfig"
-
source "drivers/staging/rtl8723bs/Kconfig"
-source "drivers/staging/rtl8712/Kconfig"
-
-source "drivers/staging/rts5208/Kconfig"
-
source "drivers/staging/octeon/Kconfig"
-source "drivers/staging/vt6655/Kconfig"
-
-source "drivers/staging/vt6656/Kconfig"
-
source "drivers/staging/iio/Kconfig"
source "drivers/staging/sm750fb/Kconfig"
@@ -46,8 +36,6 @@ source "drivers/staging/nvec/Kconfig"
source "drivers/staging/media/Kconfig"
-source "drivers/staging/gdm724x/Kconfig"
-
source "drivers/staging/fbtft/Kconfig"
source "drivers/staging/most/Kconfig"
@@ -58,8 +46,8 @@ source "drivers/staging/vc04_services/Kconfig"
source "drivers/staging/axis-fifo/Kconfig"
-source "drivers/staging/fieldbus/Kconfig"
-
source "drivers/staging/vme_user/Kconfig"
+source "drivers/staging/gpib/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 4a84c4848664..e681e403509c 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -2,21 +2,15 @@
# Makefile for staging directory
obj-y += media/
-obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/
obj-$(CONFIG_RTL8723BS) += rtl8723bs/
-obj-$(CONFIG_R8712U) += rtl8712/
-obj-$(CONFIG_RTS5208) += rts5208/
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
-obj-$(CONFIG_VT6655) += vt6655/
-obj-$(CONFIG_VT6656) += vt6656/
obj-$(CONFIG_VME_BUS) += vme_user/
obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_FB_SM750) += sm750fb/
obj-$(CONFIG_MFD_NVEC) += nvec/
-obj-$(CONFIG_LTE_GDM724X) += gdm724x/
obj-$(CONFIG_FB_TFT) += fbtft/
obj-$(CONFIG_MOST) += most/
obj-$(CONFIG_GREYBUS) += greybus/
obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/
obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/
-obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/
+obj-$(CONFIG_GPIB) += gpib/
diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c
index 1bbb9a6db597..7540c20090c7 100644
--- a/drivers/staging/axis-fifo/axis-fifo.c
+++ b/drivers/staging/axis-fifo/axis-fifo.c
@@ -919,7 +919,7 @@ static struct platform_driver axis_fifo_driver = {
.of_match_table = axis_fifo_of_match,
},
.probe = axis_fifo_probe,
- .remove_new = axis_fifo_remove,
+ .remove = axis_fifo_remove,
};
static int __init axis_fifo_init(void)
diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h
index 3e00a26a29d5..317be17b95c1 100644
--- a/drivers/staging/fbtft/fbtft.h
+++ b/drivers/staging/fbtft/fbtft.h
@@ -330,7 +330,7 @@ static struct platform_driver fbtft_driver_platform_driver = { \
.of_match_table = dt_ids, \
}, \
.probe = fbtft_driver_probe_pdev, \
- .remove_new = fbtft_driver_remove_pdev, \
+ .remove = fbtft_driver_remove_pdev, \
}; \
\
static int __init fbtft_driver_module_init(void) \
diff --git a/drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev b/drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev
deleted file mode 100644
index 45f631ea32a6..000000000000
--- a/drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev
+++ /dev/null
@@ -1,31 +0,0 @@
-What: /dev/fieldbus_devX
-Date: December 2018
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- The cdev interface to drivers for Fieldbus Device Memory
- (aka. Process Memory).
-
- The following file operations are supported:
-
- open(2)
- Create an I/O context associated with the file descriptor.
-
- read(2)
- Read from Process Memory's "read area".
- Clears POLLERR | POLLPRI from the file descriptor.
-
- write(2)
- Write to Process Memory's "write area".
-
- poll(2), select(2), epoll_wait(2) etc.
- When a "Process Memory Read Area Changed" event occurs,
- POLLERR | POLLPRI will be set on the file descriptor.
- Note that POLLIN | POLLOUT events are always set, because the
- process memory area is always readable and writable.
-
- close(2)
- Free up the I/O context that was associated
- with the file descriptor.
-
-Users: TBD
diff --git a/drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev b/drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev
deleted file mode 100644
index 439f14d33c3b..000000000000
--- a/drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev
+++ /dev/null
@@ -1,62 +0,0 @@
-What: /sys/class/fieldbus_dev/fieldbus_devX/card_name
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- Human-readable name of the Fieldbus Device.
-
-What: /sys/class/fieldbus_dev/fieldbus_devX/fieldbus_type
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- The type of fieldbus implemented by this device.
- Possible values:
- 'unknown'
- 'profinet'
-
-What: /sys/class/fieldbus_dev/fieldbus_devX/fieldbus_id
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- The unique fieldbus id associated with this device.
- The exact format of this id is fieldbus type dependent, e.g.
- a mac address for profinet.
-
-What: /sys/class/fieldbus_dev/fieldbus_devX/read_area_size
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- The size, in bytes, of the Process Memory read area.
- Note: this area is accessible by reading from the associated
- character device (/dev/fieldbus_devX).
-
-What: /sys/class/fieldbus_dev/fieldbus_devX/write_area_size
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- The size, in bytes, of the Process Memory write area.
- Note: this area is accessible by writing to the associated
- character device (/dev/fieldbus_devX)
-
-What: /sys/class/fieldbus_dev/fieldbus_devX/online
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- Whether the fieldbus is online or offline.
- Possible values:
- '1' meaning 'online'
- '0' meaning 'offline'
- Note: an uevent is generated when this property changes.
-
-What: /sys/class/fieldbus_dev/fieldbus_devX/enabled
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- Whether the device is enabled (power on) or
- disabled (power off).
- Possible values:
- '1' meaning enabled
- '0' meaning disabled
- Normally a r/o property, but optionally r/w:
- Writing '1' enables the device (power on) with default
- settings.
- Writing '0' disables the card (power off).
diff --git a/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt b/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt
deleted file mode 100644
index f34a95611645..000000000000
--- a/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-* Arcx Anybus-S controller
-
-This chip communicates with the SoC over a parallel bus. It is
-expected that its Device Tree node is specified as the child of a node
-corresponding to the parallel bus used for communication.
-
-Required properties:
---------------------
-
- - compatible : The following chip-specific string:
- "arcx,anybus-controller"
-
- - reg : three areas:
- index 0: bus memory area where the cpld registers are located.
- index 1: bus memory area of the first host's dual-port ram.
- index 2: bus memory area of the second host's dual-port ram.
-
- - reset-gpios : the GPIO pin connected to the reset line of the controller.
-
- - interrupts : two interrupts:
- index 0: interrupt connected to the first host
- index 1: interrupt connected to the second host
- Generic interrupt client node bindings are described in
- interrupt-controller/interrupts.txt
-
-Optional: use of subnodes
--------------------------
-
-The card connected to a host may need additional properties. These can be
-specified in subnodes to the controller node.
-
-The subnodes are identified by the standard 'reg' property. Which information
-exactly can be specified depends on the bindings for the function driver
-for the subnode.
-
-Required controller node properties when using subnodes:
-- #address-cells: should be one.
-- #size-cells: should be zero.
-
-Required subnode properties:
-- reg: Must contain the host index of the card this subnode describes:
- <0> for the first host on the controller
- <1> for the second host on the controller
- Note that only a single card can be plugged into a host, so the host
- index uniquely describes the card location.
-
-Example of usage:
------------------
-
-This example places the bridge on top of the i.MX WEIM parallel bus, see:
-Documentation/devicetree/bindings/memory-controllers/fsl/fsl,imx-weim.yaml
-
-&weim {
- controller@0,0 {
- compatible = "arcx,anybus-controller";
- reg = <0 0 0x100>, <0 0x400000 0x800>, <1 0x400000 0x800>;
- reset-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
- interrupt-parent = <&gpio1>;
- interrupts = <1 IRQ_TYPE_LEVEL_LOW>, <5 IRQ_TYPE_LEVEL_LOW>;
- /* fsl,weim-cs-timing is a i.MX WEIM bus specific property */
- fsl,weim-cs-timing = <0x024400b1 0x00001010 0x20081100
- 0x00000000 0xa0000240 0x00000000>;
- /* optional subnode for a card plugged into the first host */
- #address-cells = <1>;
- #size-cells = <0>;
- card@0 {
- reg = <0>;
- /* card specific properties go here */
- };
- };
-};
diff --git a/drivers/staging/fieldbus/Documentation/fieldbus_dev.txt b/drivers/staging/fieldbus/Documentation/fieldbus_dev.txt
deleted file mode 100644
index 89fb8e14676f..000000000000
--- a/drivers/staging/fieldbus/Documentation/fieldbus_dev.txt
+++ /dev/null
@@ -1,66 +0,0 @@
- Fieldbus-Device Subsystem
- ============================================
-
-Part 0 - What is a Fieldbus Device ?
-------------------------------------
-
-Fieldbus is the name of a family of industrial computer network protocols used
-for real-time distributed control, standardized as IEC 61158.
-
-A complex automated industrial system -- such as manufacturing assembly line --
-usually needs a distributed control system -- an organized hierarchy of
-controller systems -- to function. In this hierarchy, there is usually a
-Human Machine Interface (HMI) at the top, where an operator can monitor or
-operate the system. This is typically linked to a middle layer of programmable
-logic controllers (PLC) via a non-time-critical communications system
-(e.g. Ethernet). At the bottom of the control chain is the fieldbus that links
-the PLCs to the components that actually do the work, such as sensors,
-actuators, electric motors, console lights, switches, valves and contactors.
-
-(Source: Wikipedia)
-
-A "Fieldbus Device" is such an actuator, motor, console light, switch, ...
-controlled via the Fieldbus by a PLC aka "Fieldbus Controller".
-
-Communication between PLC and device typically happens via process data memory,
-separated into input and output areas. The Fieldbus then cyclically transfers
-the PLC's output area to the device's input area, and vice versa.
-
-Part I - Why do we need this subsystem?
----------------------------------------
-
-Fieldbus device (client) adapters are commercially available. They allow data
-exchange with a PLC aka "Fieldbus Controller" via process data memory.
-
-They are typically used when a Linux device wants to expose itself as an
-actuator, motor, console light, switch, etc. over the fieldbus.
-
-The purpose of this subsystem is:
-a) present a general, standardized, extensible API/ABI to userspace; and
-b) present a convenient interface to drivers.
-
-Part II - How can drivers use the subsystem?
---------------------------------------------
-
-Any driver that wants to register as a Fieldbus Device should allocate and
-populate a 'struct fieldbus_dev' (from include/linux/fieldbus_dev.h).
-Registration then happens by calling fieldbus_dev_register().
-
-Part III - How can userspace use the subsystem?
------------------------------------------------
-
-Fieldbus protocols and adapters are diverse and varied. However, they share
-a limited few common behaviours and properties. This allows us to define
-a simple interface consisting of a character device and a set of sysfs files:
-
-See:
-drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev
-drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev
-
-Note that this simple interface does not provide a way to modify adapter
-configuration settings. It is therefore useful only for adapters that get their
-configuration settings some other way, e.g. non-volatile memory on the adapter,
-through the network, ...
-
-At a later phase, this simple interface can easily co-exist with a future
-(netlink-based ?) configuration settings interface.
diff --git a/drivers/staging/fieldbus/Kconfig b/drivers/staging/fieldbus/Kconfig
deleted file mode 100644
index b0b865acccfb..000000000000
--- a/drivers/staging/fieldbus/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-menuconfig FIELDBUS_DEV
- tristate "Fieldbus Device Support"
- help
- Support for Fieldbus Device Adapters.
-
- Fieldbus device (client) adapters allow data exchange with a PLC aka.
- "Fieldbus Controller" over a fieldbus (Profinet, FLNet, etc.)
-
- They are typically used when a Linux device wants to expose itself
- as an actuator, motor, console light, switch, etc. over the fieldbus.
-
- This framework is designed to provide a generic interface to Fieldbus
- Devices from both the Linux Kernel and the userspace.
-
- If unsure, say no.
-
-source "drivers/staging/fieldbus/anybuss/Kconfig"
-
diff --git a/drivers/staging/fieldbus/Makefile b/drivers/staging/fieldbus/Makefile
deleted file mode 100644
index bdf645d41344..000000000000
--- a/drivers/staging/fieldbus/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for fieldbus_dev drivers.
-#
-
-obj-$(CONFIG_FIELDBUS_DEV) += fieldbus_dev.o anybuss/
-fieldbus_dev-y := dev_core.o
diff --git a/drivers/staging/fieldbus/TODO b/drivers/staging/fieldbus/TODO
deleted file mode 100644
index 6d6626af4ec7..000000000000
--- a/drivers/staging/fieldbus/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-TODO:
--Get more people/drivers to use the Fieldbus userspace ABI. It requires
- verification/sign-off by multiple users.
-
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
diff --git a/drivers/staging/fieldbus/anybuss/Kconfig b/drivers/staging/fieldbus/anybuss/Kconfig
deleted file mode 100644
index 635a0a7b7dd2..000000000000
--- a/drivers/staging/fieldbus/anybuss/Kconfig
+++ /dev/null
@@ -1,41 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config HMS_ANYBUSS_BUS
- tristate "HMS Anybus-S Bus Support"
- select REGMAP
- depends on OF && FIELDBUS_DEV
- help
- Driver for the HMS Industrial Networks Anybus-S bus.
- You can attach a single Anybus-S compatible card to it, which
- typically provides fieldbus and industrial ethernet
- functionality.
-
-if HMS_ANYBUSS_BUS
-
-config ARCX_ANYBUS_CONTROLLER
- tristate "Arcx Anybus-S Controller"
- depends on OF && GPIOLIB && HAS_IOMEM && REGULATOR
- select REGMAP_MMIO
- help
- Select this to get support for the Arcx Anybus controller.
- It connects to the SoC via a parallel memory bus, and
- embeds up to two Anybus-S buses (slots).
- There is also a CAN power readout, unrelated to the Anybus,
- modelled as a regulator.
-
-config HMS_PROFINET
- tristate "HMS Profinet IRT Controller (Anybus-S)"
- depends on FIELDBUS_DEV && HMS_ANYBUSS_BUS
- help
- If you say yes here you get support for the HMS Industrial
- Networks Profinet IRT Controller.
-
- It will be registered with the kernel as a fieldbus_dev,
- so userspace can interact with it via the fieldbus_dev userspace
- interface(s).
-
- This driver can also be built as a module. If so, the module
- will be called hms-profinet.
-
- If unsure, say N.
-
-endif
diff --git a/drivers/staging/fieldbus/anybuss/Makefile b/drivers/staging/fieldbus/anybuss/Makefile
deleted file mode 100644
index 3ad3dcc6be56..000000000000
--- a/drivers/staging/fieldbus/anybuss/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for anybuss drivers.
-#
-
-obj-$(CONFIG_HMS_ANYBUSS_BUS) += anybuss_core.o
-anybuss_core-y += host.o
-
-obj-$(CONFIG_ARCX_ANYBUS_CONTROLLER) += arcx-anybus.o
-obj-$(CONFIG_HMS_PROFINET) += hms-profinet.o
diff --git a/drivers/staging/fieldbus/anybuss/anybuss-client.h b/drivers/staging/fieldbus/anybuss/anybuss-client.h
deleted file mode 100644
index c21c4bebfb84..000000000000
--- a/drivers/staging/fieldbus/anybuss/anybuss-client.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Anybus-S client adapter definitions
- *
- * Copyright 2018 Arcx Inc
- */
-
-#ifndef __LINUX_ANYBUSS_CLIENT_H__
-#define __LINUX_ANYBUSS_CLIENT_H__
-
-#include <linux/device.h>
-#include <linux/types.h>
-#include <linux/poll.h>
-
-/* move to <linux/fieldbus_dev.h> when taking this out of staging */
-#include "../fieldbus_dev.h"
-
-struct anybuss_host;
-
-struct anybuss_client {
- struct device dev;
- struct anybuss_host *host;
- __be16 anybus_id;
- /*
- * these can be optionally set by the client to receive event
- * notifications from the host.
- */
- void (*on_area_updated)(struct anybuss_client *client);
- void (*on_online_changed)(struct anybuss_client *client, bool online);
-};
-
-struct anybuss_client_driver {
- struct device_driver driver;
- int (*probe)(struct anybuss_client *adev);
- void (*remove)(struct anybuss_client *adev);
- u16 anybus_id;
-};
-
-int anybuss_client_driver_register(struct anybuss_client_driver *drv);
-void anybuss_client_driver_unregister(struct anybuss_client_driver *drv);
-
-static inline struct anybuss_client *to_anybuss_client(struct device *dev)
-{
- return container_of(dev, struct anybuss_client, dev);
-}
-
-#define to_anybuss_client_driver(__drv) container_of_const(__drv, struct anybuss_client_driver, driver)
-
-static inline void *
-anybuss_get_drvdata(const struct anybuss_client *client)
-{
- return dev_get_drvdata(&client->dev);
-}
-
-static inline void
-anybuss_set_drvdata(struct anybuss_client *client, void *data)
-{
- dev_set_drvdata(&client->dev, data);
-}
-
-int anybuss_set_power(struct anybuss_client *client, bool power_on);
-
-struct anybuss_memcfg {
- u16 input_io;
- u16 input_dpram;
- u16 input_total;
-
- u16 output_io;
- u16 output_dpram;
- u16 output_total;
-
- enum fieldbus_dev_offl_mode offl_mode;
-};
-
-int anybuss_start_init(struct anybuss_client *client,
- const struct anybuss_memcfg *cfg);
-int anybuss_finish_init(struct anybuss_client *client);
-int anybuss_read_fbctrl(struct anybuss_client *client, u16 addr,
- void *buf, size_t count);
-int anybuss_send_msg(struct anybuss_client *client, u16 cmd_num,
- const void *buf, size_t count);
-int anybuss_send_ext(struct anybuss_client *client, u16 cmd_num,
- const void *buf, size_t count);
-int anybuss_recv_msg(struct anybuss_client *client, u16 cmd_num,
- void *buf, size_t count);
-
-/* these help clients make a struct file_operations */
-int anybuss_write_input(struct anybuss_client *client,
- const char __user *buf, size_t size,
- loff_t *offset);
-int anybuss_read_output(struct anybuss_client *client,
- char __user *buf, size_t size,
- loff_t *offset);
-
-#endif /* __LINUX_ANYBUSS_CLIENT_H__ */
diff --git a/drivers/staging/fieldbus/anybuss/anybuss-controller.h b/drivers/staging/fieldbus/anybuss/anybuss-controller.h
deleted file mode 100644
index 02fa0749043b..000000000000
--- a/drivers/staging/fieldbus/anybuss/anybuss-controller.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Anybus-S controller definitions
- *
- * Copyright 2018 Arcx Inc
- */
-
-#ifndef __LINUX_ANYBUSS_CONTROLLER_H__
-#define __LINUX_ANYBUSS_CONTROLLER_H__
-
-#include <linux/device.h>
-#include <linux/regmap.h>
-
-/*
- * To instantiate an Anybus-S host, a controller should provide the following:
- * - a reset function which resets the attached card;
- * - a regmap which provides access to the attached card's dpram;
- * - the irq of the attached card
- */
-/**
- * struct anybuss_ops - Controller resources to instantiate an Anybus-S host
- *
- * @reset: asserts/deasserts the anybus card's reset line.
- * @regmap: provides access to the card's dual-port RAM area.
- * @irq: number of the interrupt connected to the card's interrupt line.
- * @host_idx: for multi-host controllers, the host index:
- * 0 for the first host on the controller, 1 for the second, etc.
- */
-struct anybuss_ops {
- void (*reset)(struct device *dev, bool assert);
- struct regmap *regmap;
- int irq;
- int host_idx;
-};
-
-struct anybuss_host;
-
-struct anybuss_host * __must_check
-anybuss_host_common_probe(struct device *dev,
- const struct anybuss_ops *ops);
-void anybuss_host_common_remove(struct anybuss_host *host);
-
-struct anybuss_host * __must_check
-devm_anybuss_host_common_probe(struct device *dev,
- const struct anybuss_ops *ops);
-
-#endif /* __LINUX_ANYBUSS_CONTROLLER_H__ */
diff --git a/drivers/staging/fieldbus/anybuss/arcx-anybus.c b/drivers/staging/fieldbus/anybuss/arcx-anybus.c
deleted file mode 100644
index fcd3e3722ae0..000000000000
--- a/drivers/staging/fieldbus/anybuss/arcx-anybus.c
+++ /dev/null
@@ -1,379 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Arcx Anybus-S Controller driver
- *
- * Copyright (C) 2018 Arcx Inc
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/gpio/consumer.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/delay.h>
-#include <linux/idr.h>
-#include <linux/mutex.h>
-#include <linux/regulator/driver.h>
-#include <linux/regulator/machine.h>
-#include <linux/regmap.h>
-
-/* move to <linux/anybuss-controller.h> when taking this out of staging */
-#include "anybuss-controller.h"
-
-#define CPLD_STATUS1 0x80
-#define CPLD_CONTROL 0x80
-#define CPLD_CONTROL_CRST 0x40
-#define CPLD_CONTROL_RST1 0x04
-#define CPLD_CONTROL_RST2 0x80
-#define CPLD_STATUS1_AB 0x02
-#define CPLD_STATUS1_CAN_POWER 0x01
-#define CPLD_DESIGN_LO 0x81
-#define CPLD_DESIGN_HI 0x82
-#define CPLD_CAP 0x83
-#define CPLD_CAP_COMPAT 0x01
-#define CPLD_CAP_SEP_RESETS 0x02
-
-struct controller_priv {
- struct device *class_dev;
- bool common_reset;
- struct gpio_desc *reset_gpiod;
- void __iomem *cpld_base;
- struct mutex ctrl_lock; /* protects CONTROL register */
- u8 control_reg;
- char version[3];
- u16 design_no;
-};
-
-static void do_reset(struct controller_priv *cd, u8 rst_bit, bool reset)
-{
- mutex_lock(&cd->ctrl_lock);
- /*
- * CPLD_CONTROL is write-only, so cache its value in
- * cd->control_reg
- */
- if (reset)
- cd->control_reg &= ~rst_bit;
- else
- cd->control_reg |= rst_bit;
- writeb(cd->control_reg, cd->cpld_base + CPLD_CONTROL);
- /*
- * h/w work-around:
- * the hardware is 'too fast', so a reset followed by an immediate
- * not-reset will _not_ change the anybus reset line in any way,
- * losing the reset. to prevent this from happening, introduce
- * a minimum reset duration.
- * Verified minimum safe duration required using a scope
- * on 14-June-2018: 100 us.
- */
- if (reset)
- usleep_range(100, 200);
- mutex_unlock(&cd->ctrl_lock);
-}
-
-static int anybuss_reset(struct controller_priv *cd,
- unsigned long id, bool reset)
-{
- if (id >= 2)
- return -EINVAL;
- if (cd->common_reset)
- do_reset(cd, CPLD_CONTROL_CRST, reset);
- else
- do_reset(cd, id ? CPLD_CONTROL_RST2 : CPLD_CONTROL_RST1, reset);
- return 0;
-}
-
-static void export_reset_0(struct device *dev, bool assert)
-{
- struct controller_priv *cd = dev_get_drvdata(dev);
-
- anybuss_reset(cd, 0, assert);
-}
-
-static void export_reset_1(struct device *dev, bool assert)
-{
- struct controller_priv *cd = dev_get_drvdata(dev);
-
- anybuss_reset(cd, 1, assert);
-}
-
-/*
- * parallel bus limitation:
- *
- * the anybus is 8-bit wide. we can't assume that the hardware will translate
- * word accesses on the parallel bus to multiple byte-accesses on the anybus.
- *
- * the imx WEIM bus does not provide this type of translation.
- *
- * to be safe, we will limit parallel bus accesses to a single byte
- * at a time for now.
- */
-
-static const struct regmap_config arcx_regmap_cfg = {
- .reg_bits = 16,
- .val_bits = 8,
- .max_register = 0x7ff,
- .use_single_read = true,
- .use_single_write = true,
- /*
- * single-byte parallel bus accesses are atomic, so don't
- * require any synchronization.
- */
- .disable_locking = true,
-};
-
-static struct regmap *create_parallel_regmap(struct platform_device *pdev,
- int idx)
-{
- void __iomem *base;
- struct device *dev = &pdev->dev;
-
- base = devm_platform_ioremap_resource(pdev, idx + 1);
- if (IS_ERR(base))
- return ERR_CAST(base);
- return devm_regmap_init_mmio(dev, base, &arcx_regmap_cfg);
-}
-
-static struct anybuss_host *
-create_anybus_host(struct platform_device *pdev, int idx)
-{
- struct anybuss_ops ops = {};
-
- switch (idx) {
- case 0:
- ops.reset = export_reset_0;
- break;
- case 1:
- ops.reset = export_reset_1;
- break;
- default:
- return ERR_PTR(-EINVAL);
- }
- ops.host_idx = idx;
- ops.regmap = create_parallel_regmap(pdev, idx);
- if (IS_ERR(ops.regmap))
- return ERR_CAST(ops.regmap);
- ops.irq = platform_get_irq(pdev, idx);
- if (ops.irq < 0)
- return ERR_PTR(ops.irq);
- return devm_anybuss_host_common_probe(&pdev->dev, &ops);
-}
-
-static ssize_t version_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct controller_priv *cd = dev_get_drvdata(dev);
-
- return sprintf(buf, "%s\n", cd->version);
-}
-static DEVICE_ATTR_RO(version);
-
-static ssize_t design_number_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct controller_priv *cd = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", cd->design_no);
-}
-static DEVICE_ATTR_RO(design_number);
-
-static struct attribute *controller_attributes[] = {
- &dev_attr_version.attr,
- &dev_attr_design_number.attr,
- NULL,
-};
-
-static const struct attribute_group controller_attribute_group = {
- .attrs = controller_attributes,
-};
-
-static const struct attribute_group *controller_attribute_groups[] = {
- &controller_attribute_group,
- NULL,
-};
-
-static void controller_device_release(struct device *dev)
-{
- kfree(dev);
-}
-
-static int can_power_is_enabled(struct regulator_dev *rdev)
-{
- struct controller_priv *cd = rdev_get_drvdata(rdev);
-
- return !(readb(cd->cpld_base + CPLD_STATUS1) & CPLD_STATUS1_CAN_POWER);
-}
-
-static const struct regulator_ops can_power_ops = {
- .is_enabled = can_power_is_enabled,
-};
-
-static const struct regulator_desc can_power_desc = {
- .name = "regulator-can-power",
- .id = -1,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- .ops = &can_power_ops,
-};
-
-static const struct class controller_class = {
- .name = "arcx_anybus_controller",
-};
-
-static DEFINE_IDA(controller_index_ida);
-
-static int controller_probe(struct platform_device *pdev)
-{
- struct controller_priv *cd;
- struct device *dev = &pdev->dev;
- struct regulator_config config = { };
- struct regulator_dev *regulator;
- int err, id;
- struct anybuss_host *host;
- u8 status1, cap;
-
- cd = devm_kzalloc(dev, sizeof(*cd), GFP_KERNEL);
- if (!cd)
- return -ENOMEM;
- dev_set_drvdata(dev, cd);
- mutex_init(&cd->ctrl_lock);
- cd->reset_gpiod = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR(cd->reset_gpiod))
- return PTR_ERR(cd->reset_gpiod);
-
- /* CPLD control memory, sits at index 0 */
- cd->cpld_base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(cd->cpld_base)) {
- dev_err(dev,
- "failed to map cpld base address\n");
- err = PTR_ERR(cd->cpld_base);
- goto out_reset;
- }
-
- /* identify cpld */
- status1 = readb(cd->cpld_base + CPLD_STATUS1);
- cd->design_no = (readb(cd->cpld_base + CPLD_DESIGN_HI) << 8) |
- readb(cd->cpld_base + CPLD_DESIGN_LO);
- snprintf(cd->version, sizeof(cd->version), "%c%d",
- 'A' + ((status1 >> 5) & 0x7),
- (status1 >> 2) & 0x7);
- dev_info(dev, "design number %d, revision %s\n",
- cd->design_no,
- cd->version);
- cap = readb(cd->cpld_base + CPLD_CAP);
- if (!(cap & CPLD_CAP_COMPAT)) {
- dev_err(dev, "unsupported controller [cap=0x%02X]", cap);
- err = -ENODEV;
- goto out_reset;
- }
-
- if (status1 & CPLD_STATUS1_AB) {
- dev_info(dev, "has anybus-S slot(s)");
- cd->common_reset = !(cap & CPLD_CAP_SEP_RESETS);
- dev_info(dev, "supports %s", cd->common_reset ?
- "a common reset" : "separate resets");
- for (id = 0; id < 2; id++) {
- host = create_anybus_host(pdev, id);
- if (!IS_ERR(host))
- continue;
- err = PTR_ERR(host);
- /* -ENODEV is fine, it just means no card detected */
- if (err != -ENODEV)
- goto out_reset;
- }
- }
-
- id = ida_alloc(&controller_index_ida, GFP_KERNEL);
- if (id < 0) {
- err = id;
- goto out_reset;
- }
- /* export can power readout as a regulator */
- config.dev = dev;
- config.driver_data = cd;
- regulator = devm_regulator_register(dev, &can_power_desc, &config);
- if (IS_ERR(regulator)) {
- err = PTR_ERR(regulator);
- goto out_ida;
- }
- /* make controller info visible to userspace */
- cd->class_dev = kzalloc(sizeof(*cd->class_dev), GFP_KERNEL);
- if (!cd->class_dev) {
- err = -ENOMEM;
- goto out_ida;
- }
- cd->class_dev->class = &controller_class;
- cd->class_dev->groups = controller_attribute_groups;
- cd->class_dev->parent = dev;
- cd->class_dev->id = id;
- cd->class_dev->release = controller_device_release;
- dev_set_name(cd->class_dev, "%d", cd->class_dev->id);
- dev_set_drvdata(cd->class_dev, cd);
- err = device_register(cd->class_dev);
- if (err)
- goto out_dev;
- return 0;
-out_dev:
- put_device(cd->class_dev);
-out_ida:
- ida_free(&controller_index_ida, id);
-out_reset:
- gpiod_set_value_cansleep(cd->reset_gpiod, 1);
- return err;
-}
-
-static void controller_remove(struct platform_device *pdev)
-{
- struct controller_priv *cd = platform_get_drvdata(pdev);
- int id = cd->class_dev->id;
-
- device_unregister(cd->class_dev);
- ida_free(&controller_index_ida, id);
- gpiod_set_value_cansleep(cd->reset_gpiod, 1);
-}
-
-static const struct of_device_id controller_of_match[] = {
- { .compatible = "arcx,anybus-controller" },
- { }
-};
-
-MODULE_DEVICE_TABLE(of, controller_of_match);
-
-static struct platform_driver controller_driver = {
- .probe = controller_probe,
- .remove_new = controller_remove,
- .driver = {
- .name = "arcx-anybus-controller",
- .of_match_table = controller_of_match,
- },
-};
-
-static int __init controller_init(void)
-{
- int err;
-
- err = class_register(&controller_class);
- if (err)
- return err;
- err = platform_driver_register(&controller_driver);
- if (err)
- class_unregister(&controller_class);
-
- return err;
-}
-
-static void __exit controller_exit(void)
-{
- platform_driver_unregister(&controller_driver);
- class_unregister(&controller_class);
- ida_destroy(&controller_index_ida);
-}
-
-module_init(controller_init);
-module_exit(controller_exit);
-
-MODULE_DESCRIPTION("Arcx Anybus-S Controller driver");
-MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/fieldbus/anybuss/hms-profinet.c b/drivers/staging/fieldbus/anybuss/hms-profinet.c
deleted file mode 100644
index e691736a53f1..000000000000
--- a/drivers/staging/fieldbus/anybuss/hms-profinet.c
+++ /dev/null
@@ -1,224 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * HMS Profinet Client Driver
- *
- * Copyright (C) 2018 Arcx Inc
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-/* move to <linux/fieldbus_dev.h> when taking this out of staging */
-#include "../fieldbus_dev.h"
-
-/* move to <linux/anybuss-client.h> when taking this out of staging */
-#include "anybuss-client.h"
-
-#define PROFI_DPRAM_SIZE 512
-
-/*
- * ---------------------------------------------------------------
- * Anybus Profinet mailbox messages - definitions
- * ---------------------------------------------------------------
- * note that we're depending on the layout of these structures being
- * exactly as advertised.
- */
-
-struct msg_mac_addr {
- u8 addr[6];
-};
-
-struct profi_priv {
- struct fieldbus_dev fbdev;
- struct anybuss_client *client;
- struct mutex enable_lock; /* serializes card enable */
- bool power_on;
-};
-
-static ssize_t
-profi_read_area(struct fieldbus_dev *fbdev, char __user *buf, size_t size,
- loff_t *offset)
-{
- struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
-
- return anybuss_read_output(priv->client, buf, size, offset);
-}
-
-static ssize_t
-profi_write_area(struct fieldbus_dev *fbdev, const char __user *buf,
- size_t size, loff_t *offset)
-{
- struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
-
- return anybuss_write_input(priv->client, buf, size, offset);
-}
-
-static int profi_id_get(struct fieldbus_dev *fbdev, char *buf,
- size_t max_size)
-{
- struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
- struct msg_mac_addr response;
- int ret;
-
- ret = anybuss_recv_msg(priv->client, 0x0010, &response,
- sizeof(response));
- if (ret < 0)
- return ret;
- return snprintf(buf, max_size, "%pM\n", response.addr);
-}
-
-static bool profi_enable_get(struct fieldbus_dev *fbdev)
-{
- struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
- bool power_on;
-
- mutex_lock(&priv->enable_lock);
- power_on = priv->power_on;
- mutex_unlock(&priv->enable_lock);
-
- return power_on;
-}
-
-static int __profi_enable(struct profi_priv *priv)
-{
- int ret;
- struct anybuss_client *client = priv->client;
- /* Initialization Sequence, Generic Anybus Mode */
- const struct anybuss_memcfg mem_cfg = {
- .input_io = 220,
- .input_dpram = PROFI_DPRAM_SIZE,
- .input_total = PROFI_DPRAM_SIZE,
- .output_io = 220,
- .output_dpram = PROFI_DPRAM_SIZE,
- .output_total = PROFI_DPRAM_SIZE,
- .offl_mode = FIELDBUS_DEV_OFFL_MODE_CLEAR,
- };
-
- /*
- * switch anybus off then on, this ensures we can do a complete
- * configuration cycle in case anybus was already on.
- */
- anybuss_set_power(client, false);
- ret = anybuss_set_power(client, true);
- if (ret)
- goto err;
- ret = anybuss_start_init(client, &mem_cfg);
- if (ret)
- goto err;
- ret = anybuss_finish_init(client);
- if (ret)
- goto err;
- priv->power_on = true;
- return 0;
-
-err:
- anybuss_set_power(client, false);
- priv->power_on = false;
- return ret;
-}
-
-static int __profi_disable(struct profi_priv *priv)
-{
- struct anybuss_client *client = priv->client;
-
- anybuss_set_power(client, false);
- priv->power_on = false;
- return 0;
-}
-
-static int profi_simple_enable(struct fieldbus_dev *fbdev, bool enable)
-{
- int ret;
- struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
-
- mutex_lock(&priv->enable_lock);
- if (enable)
- ret = __profi_enable(priv);
- else
- ret = __profi_disable(priv);
- mutex_unlock(&priv->enable_lock);
-
- return ret;
-}
-
-static void profi_on_area_updated(struct anybuss_client *client)
-{
- struct profi_priv *priv = anybuss_get_drvdata(client);
-
- fieldbus_dev_area_updated(&priv->fbdev);
-}
-
-static void profi_on_online_changed(struct anybuss_client *client, bool online)
-{
- struct profi_priv *priv = anybuss_get_drvdata(client);
-
- fieldbus_dev_online_changed(&priv->fbdev, online);
-}
-
-static int profinet_probe(struct anybuss_client *client)
-{
- struct profi_priv *priv;
- struct device *dev = &client->dev;
- int err;
-
- client->on_area_updated = profi_on_area_updated;
- client->on_online_changed = profi_on_online_changed;
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
- mutex_init(&priv->enable_lock);
- priv->client = client;
- priv->fbdev.read_area_sz = PROFI_DPRAM_SIZE;
- priv->fbdev.write_area_sz = PROFI_DPRAM_SIZE;
- priv->fbdev.card_name = "HMS Profinet IRT (Anybus-S)";
- priv->fbdev.fieldbus_type = FIELDBUS_DEV_TYPE_PROFINET;
- priv->fbdev.read_area = profi_read_area;
- priv->fbdev.write_area = profi_write_area;
- priv->fbdev.fieldbus_id_get = profi_id_get;
- priv->fbdev.enable_get = profi_enable_get;
- priv->fbdev.simple_enable_set = profi_simple_enable;
- priv->fbdev.parent = dev;
- err = fieldbus_dev_register(&priv->fbdev);
- if (err < 0)
- return err;
- dev_info(dev, "card detected, registered as %s",
- dev_name(priv->fbdev.dev));
- anybuss_set_drvdata(client, priv);
-
- return 0;
-}
-
-static void profinet_remove(struct anybuss_client *client)
-{
- struct profi_priv *priv = anybuss_get_drvdata(client);
-
- fieldbus_dev_unregister(&priv->fbdev);
-}
-
-static struct anybuss_client_driver profinet_driver = {
- .probe = profinet_probe,
- .remove = profinet_remove,
- .driver = {
- .name = "hms-profinet",
- .owner = THIS_MODULE,
- },
- .anybus_id = 0x0089,
-};
-
-static int __init profinet_init(void)
-{
- return anybuss_client_driver_register(&profinet_driver);
-}
-module_init(profinet_init);
-
-static void __exit profinet_exit(void)
-{
- return anybuss_client_driver_unregister(&profinet_driver);
-}
-module_exit(profinet_exit);
-
-MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>");
-MODULE_DESCRIPTION("HMS Profinet IRT Driver (Anybus-S)");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/fieldbus/anybuss/host.c b/drivers/staging/fieldbus/anybuss/host.c
deleted file mode 100644
index 4f2b2fce92ee..000000000000
--- a/drivers/staging/fieldbus/anybuss/host.c
+++ /dev/null
@@ -1,1452 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * HMS Anybus-S Host Driver
- *
- * Copyright (C) 2018 Arcx Inc
- */
-
-/*
- * Architecture Overview
- * =====================
- * This driver (running on the CPU/SoC) and the Anybus-S card communicate
- * by reading and writing data to/from the Anybus-S Dual-Port RAM (dpram).
- * This is memory connected to both the SoC and Anybus-S card, which both sides
- * can access freely and concurrently.
- *
- * Synchronization happens by means of two registers located in the dpram:
- * IND_AB: written exclusively by the Anybus card; and
- * IND_AP: written exclusively by this driver.
- *
- * Communication happens using one of the following mechanisms:
- * 1. reserve, read/write, release dpram memory areas:
- * using an IND_AB/IND_AP protocol, the driver is able to reserve certain
- * memory areas. no dpram memory can be read or written except if reserved.
- * (with a few limited exceptions)
- * 2. send and receive data structures via a shared mailbox:
- * using an IND_AB/IND_AP protocol, the driver and Anybus card are able to
- * exchange commands and responses using a shared mailbox.
- * 3. receive software interrupts:
- * using an IND_AB/IND_AP protocol, the Anybus card is able to notify the
- * driver of certain events such as: bus online/offline, data available.
- * note that software interrupt event bits are located in a memory area
- * which must be reserved before it can be accessed.
- *
- * The manual[1] is silent on whether these mechanisms can happen concurrently,
- * or how they should be synchronized. However, section 13 (Driver Example)
- * provides the following suggestion for developing a driver:
- * a) an interrupt handler which updates global variables;
- * b) a continuously-running task handling area requests (1 above)
- * c) a continuously-running task handling mailbox requests (2 above)
- * The example conspicuously leaves out software interrupts (3 above), which
- * is the thorniest issue to get right (see below).
- *
- * The naive, straightforward way to implement this would be:
- * - create an isr which updates shared variables;
- * - create a work_struct which handles software interrupts on a queue;
- * - create a function which does reserve/update/unlock in a loop;
- * - create a function which does mailbox send/receive in a loop;
- * - call the above functions from the driver's read/write/ioctl;
- * - synchronize using mutexes/spinlocks:
- * + only one area request at a time
- * + only one mailbox request at a time
- * + protect AB_IND, AB_IND against data hazards (e.g. read-after-write)
- *
- * Unfortunately, the presence of the software interrupt causes subtle yet
- * considerable synchronization issues; especially problematic is the
- * requirement to reserve/release the area which contains the status bits.
- *
- * The driver architecture presented here sidesteps these synchronization issues
- * by accessing the dpram from a single kernel thread only. User-space throws
- * "tasks" (i.e. 1, 2 above) into a task queue, waits for their completion,
- * and the kernel thread runs them to completion.
- *
- * Each task has a task_function, which is called/run by the queue thread.
- * That function communicates with the Anybus card, and returns either
- * 0 (OK), a negative error code (error), or -EINPROGRESS (waiting).
- * On OK or error, the queue thread completes and dequeues the task,
- * which also releases the user space thread which may still be waiting for it.
- * On -EINPROGRESS (waiting), the queue thread will leave the task on the queue,
- * and revisit (call again) whenever an interrupt event comes in.
- *
- * Each task has a state machine, which is run by calling its task_function.
- * It ensures that the task will go through its various stages over time,
- * returning -EINPROGRESS if it wants to wait for an event to happen.
- *
- * Note that according to the manual's driver example, the following operations
- * may run independent of each other:
- * - area reserve/read/write/release (point 1 above)
- * - mailbox operations (point 2 above)
- * - switching power on/off
- *
- * To allow them to run independently, each operation class gets its own queue.
- *
- * Userspace processes A, B, C, D post tasks to the appropriate queue,
- * and wait for task completion:
- *
- * process A B C D
- * | | | |
- * v v v v
- * |<----- ========================================
- * | | | |
- * | v v v-------<-------+
- * | +--------------------------------------+ |
- * | | power q | mbox q | area q | |
- * | |------------|------------|------------| |
- * | | task | task | task | |
- * | | task | task | task | |
- * | | task wait | task wait | task wait | |
- * | +--------------------------------------+ |
- * | ^ ^ ^ |
- * | | | | ^
- * | +--------------------------------------+ |
- * | | queue thread | |
- * | |--------------------------------------| |
- * | | single-threaded: | |
- * | | loop: | |
- * v | for each queue: | |
- * | | run task state machine | |
- * | | if task waiting: | |
- * | | leave on queue | |
- * | | if task done: | |
- * | | complete task, remove from q | |
- * | | if software irq event bits set: | |
- * | | notify userspace | |
- * | | post clear event bits task------>|>-------+
- * | | wait for IND_AB changed event OR |
- * | | task added event OR |
- * | | timeout |
- * | | end loop |
- * | +--------------------------------------+
- * | + wake up +
- * | +--------------------------------------+
- * | ^ ^
- * | | |
- * +-------->------- |
- * |
- * +--------------------------------------+
- * | interrupt service routine |
- * |--------------------------------------|
- * | wake up queue thread on IND_AB change|
- * +--------------------------------------+
- *
- * Note that the Anybus interrupt is dual-purpose:
- * - after a reset, triggered when the card becomes ready;
- * - during normal operation, triggered when AB_IND changes.
- * This is why the interrupt service routine doesn't just wake up the
- * queue thread, but also completes the card_boot completion.
- *
- * [1] https://www.anybus.com/docs/librariesprovider7/default-document-library/
- * manuals-design-guides/hms-hmsi-27-275.pdf
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/atomic.h>
-#include <linux/kthread.h>
-#include <linux/kfifo.h>
-#include <linux/spinlock.h>
-#include <linux/uaccess.h>
-#include <linux/regmap.h>
-#include <linux/of.h>
-#include <linux/random.h>
-#include <linux/kref.h>
-#include <linux/of_address.h>
-
-/* move to <linux/anybuss-*.h> when taking this out of staging */
-#include "anybuss-client.h"
-#include "anybuss-controller.h"
-
-#define DPRAM_SIZE 0x800
-#define MAX_MBOX_MSG_SZ 0x0FF
-#define TIMEOUT (HZ * 2)
-#define MAX_DATA_AREA_SZ 0x200
-#define MAX_FBCTRL_AREA_SZ 0x1BE
-
-#define REG_BOOTLOADER_V 0x7C0
-#define REG_API_V 0x7C2
-#define REG_FIELDBUS_V 0x7C4
-#define REG_SERIAL_NO 0x7C6
-#define REG_FIELDBUS_TYPE 0x7CC
-#define REG_MODULE_SW_V 0x7CE
-#define REG_IND_AB 0x7FF
-#define REG_IND_AP 0x7FE
-#define REG_EVENT_CAUSE 0x7ED
-#define MBOX_IN_AREA 0x400
-#define MBOX_OUT_AREA 0x520
-#define DATA_IN_AREA 0x000
-#define DATA_OUT_AREA 0x200
-#define FBCTRL_AREA 0x640
-
-#define EVENT_CAUSE_DC 0x01
-#define EVENT_CAUSE_FBOF 0x02
-#define EVENT_CAUSE_FBON 0x04
-
-#define IND_AB_UPDATED 0x08
-#define IND_AX_MIN 0x80
-#define IND_AX_MOUT 0x40
-#define IND_AX_IN 0x04
-#define IND_AX_OUT 0x02
-#define IND_AX_FBCTRL 0x01
-#define IND_AP_LOCK 0x08
-#define IND_AP_ACTION 0x10
-#define IND_AX_EVNT 0x20
-#define IND_AP_ABITS (IND_AX_IN | IND_AX_OUT | \
- IND_AX_FBCTRL | \
- IND_AP_ACTION | IND_AP_LOCK)
-
-#define INFO_TYPE_FB 0x0002
-#define INFO_TYPE_APP 0x0001
-#define INFO_COMMAND 0x4000
-
-#define OP_MODE_FBFC 0x0002
-#define OP_MODE_FBS 0x0004
-#define OP_MODE_CD 0x0200
-
-#define CMD_START_INIT 0x0001
-#define CMD_ANYBUS_INIT 0x0002
-#define CMD_END_INIT 0x0003
-
-/*
- * ---------------------------------------------------------------
- * Anybus mailbox messages - definitions
- * ---------------------------------------------------------------
- * note that we're depending on the layout of these structures being
- * exactly as advertised.
- */
-
-struct anybus_mbox_hdr {
- __be16 id;
- __be16 info;
- __be16 cmd_num;
- __be16 data_size;
- __be16 frame_count;
- __be16 frame_num;
- __be16 offset_high;
- __be16 offset_low;
- __be16 extended[8];
-};
-
-struct msg_anybus_init {
- __be16 input_io_len;
- __be16 input_dpram_len;
- __be16 input_total_len;
- __be16 output_io_len;
- __be16 output_dpram_len;
- __be16 output_total_len;
- __be16 op_mode;
- __be16 notif_config;
- __be16 wd_val;
-};
-
-/* ------------- ref counted tasks ------------- */
-
-struct ab_task;
-typedef int (*ab_task_fn_t)(struct anybuss_host *cd,
- struct ab_task *t);
-typedef void (*ab_done_fn_t)(struct anybuss_host *cd);
-
-struct area_priv {
- bool is_write;
- u16 flags;
- u16 addr;
- size_t count;
- u8 buf[MAX_DATA_AREA_SZ];
-};
-
-struct mbox_priv {
- struct anybus_mbox_hdr hdr;
- size_t msg_out_sz;
- size_t msg_in_sz;
- u8 msg[MAX_MBOX_MSG_SZ];
-};
-
-struct ab_task {
- struct kmem_cache *cache;
- struct kref refcount;
- ab_task_fn_t task_fn;
- ab_done_fn_t done_fn;
- int result;
- struct completion done;
- unsigned long start_jiffies;
- union {
- struct area_priv area_pd;
- struct mbox_priv mbox_pd;
- };
-};
-
-static struct ab_task *ab_task_create_get(struct kmem_cache *cache,
- ab_task_fn_t task_fn)
-{
- struct ab_task *t;
-
- t = kmem_cache_alloc(cache, GFP_KERNEL);
- if (!t)
- return NULL;
- t->cache = cache;
- kref_init(&t->refcount);
- t->task_fn = task_fn;
- t->done_fn = NULL;
- t->result = 0;
- init_completion(&t->done);
- return t;
-}
-
-static void __ab_task_destroy(struct kref *refcount)
-{
- struct ab_task *t = container_of(refcount, struct ab_task, refcount);
- struct kmem_cache *cache = t->cache;
-
- kmem_cache_free(cache, t);
-}
-
-static void ab_task_put(struct ab_task *t)
-{
- kref_put(&t->refcount, __ab_task_destroy);
-}
-
-static struct ab_task *__ab_task_get(struct ab_task *t)
-{
- kref_get(&t->refcount);
- return t;
-}
-
-static void __ab_task_finish(struct ab_task *t, struct anybuss_host *cd)
-{
- if (t->done_fn)
- t->done_fn(cd);
- complete(&t->done);
-}
-
-static void
-ab_task_dequeue_finish_put(struct kfifo *q, struct anybuss_host *cd)
-{
- int ret;
- struct ab_task *t;
-
- ret = kfifo_out(q, &t, sizeof(t));
- WARN_ON(!ret);
- __ab_task_finish(t, cd);
- ab_task_put(t);
-}
-
-static int
-ab_task_enqueue(struct ab_task *t, struct kfifo *q, spinlock_t *slock,
- wait_queue_head_t *wq)
-{
- int ret;
-
- t->start_jiffies = jiffies;
- __ab_task_get(t);
- ret = kfifo_in_spinlocked(q, &t, sizeof(t), slock);
- if (!ret) {
- ab_task_put(t);
- return -ENOMEM;
- }
- wake_up(wq);
- return 0;
-}
-
-static int
-ab_task_enqueue_wait(struct ab_task *t, struct kfifo *q, spinlock_t *slock,
- wait_queue_head_t *wq)
-{
- int ret;
-
- ret = ab_task_enqueue(t, q, slock, wq);
- if (ret)
- return ret;
- ret = wait_for_completion_interruptible(&t->done);
- if (ret)
- return ret;
- return t->result;
-}
-
-/* ------------------------ anybus hardware ------------------------ */
-
-struct anybuss_host {
- struct device *dev;
- struct anybuss_client *client;
- void (*reset)(struct device *dev, bool assert);
- struct regmap *regmap;
- int irq;
- int host_idx;
- struct task_struct *qthread;
- wait_queue_head_t wq;
- struct completion card_boot;
- atomic_t ind_ab;
- spinlock_t qlock; /* protects IN side of powerq, mboxq, areaq */
- struct kmem_cache *qcache;
- struct kfifo qs[3];
- struct kfifo *powerq;
- struct kfifo *mboxq;
- struct kfifo *areaq;
- bool power_on;
- bool softint_pending;
-};
-
-static void reset_assert(struct anybuss_host *cd)
-{
- cd->reset(cd->dev, true);
-}
-
-static void reset_deassert(struct anybuss_host *cd)
-{
- cd->reset(cd->dev, false);
-}
-
-static int test_dpram(struct regmap *regmap)
-{
- int i;
- unsigned int val;
-
- for (i = 0; i < DPRAM_SIZE; i++)
- regmap_write(regmap, i, (u8)i);
- for (i = 0; i < DPRAM_SIZE; i++) {
- regmap_read(regmap, i, &val);
- if ((u8)val != (u8)i)
- return -EIO;
- }
- return 0;
-}
-
-static int read_ind_ab(struct regmap *regmap)
-{
- unsigned long timeout = jiffies + HZ / 2;
- unsigned int a, b, i = 0;
-
- while (time_before_eq(jiffies, timeout)) {
- regmap_read(regmap, REG_IND_AB, &a);
- regmap_read(regmap, REG_IND_AB, &b);
- if (likely(a == b))
- return (int)a;
- if (i < 10) {
- cpu_relax();
- i++;
- } else {
- usleep_range(500, 1000);
- }
- }
- WARN(1, "IND_AB register not stable");
- return -ETIMEDOUT;
-}
-
-static int write_ind_ap(struct regmap *regmap, unsigned int ind_ap)
-{
- unsigned long timeout = jiffies + HZ / 2;
- unsigned int v, i = 0;
-
- while (time_before_eq(jiffies, timeout)) {
- regmap_write(regmap, REG_IND_AP, ind_ap);
- regmap_read(regmap, REG_IND_AP, &v);
- if (likely(ind_ap == v))
- return 0;
- if (i < 10) {
- cpu_relax();
- i++;
- } else {
- usleep_range(500, 1000);
- }
- }
- WARN(1, "IND_AP register not stable");
- return -ETIMEDOUT;
-}
-
-static irqreturn_t irq_handler(int irq, void *data)
-{
- struct anybuss_host *cd = data;
- int ind_ab;
-
- /*
- * irq handler needs exclusive access to the IND_AB register,
- * because the act of reading the register acks the interrupt.
- *
- * store the register value in cd->ind_ab (an atomic_t), so that the
- * queue thread is able to read it without causing an interrupt ack
- * side-effect (and without spuriously acking an interrupt).
- */
- ind_ab = read_ind_ab(cd->regmap);
- if (ind_ab < 0)
- return IRQ_NONE;
- atomic_set(&cd->ind_ab, ind_ab);
- complete(&cd->card_boot);
- wake_up(&cd->wq);
- return IRQ_HANDLED;
-}
-
-/* ------------------------ power on/off tasks --------------------- */
-
-static int task_fn_power_off(struct anybuss_host *cd,
- struct ab_task *t)
-{
- struct anybuss_client *client = cd->client;
-
- if (!cd->power_on)
- return 0;
- disable_irq(cd->irq);
- reset_assert(cd);
- atomic_set(&cd->ind_ab, IND_AB_UPDATED);
- if (client->on_online_changed)
- client->on_online_changed(client, false);
- cd->power_on = false;
- return 0;
-}
-
-static int task_fn_power_on_2(struct anybuss_host *cd,
- struct ab_task *t)
-{
- if (completion_done(&cd->card_boot)) {
- cd->power_on = true;
- return 0;
- }
- if (time_after(jiffies, t->start_jiffies + TIMEOUT)) {
- disable_irq(cd->irq);
- reset_assert(cd);
- dev_err(cd->dev, "power on timed out");
- return -ETIMEDOUT;
- }
- return -EINPROGRESS;
-}
-
-static int task_fn_power_on(struct anybuss_host *cd,
- struct ab_task *t)
-{
- unsigned int dummy;
-
- if (cd->power_on)
- return 0;
- /*
- * anybus docs: prevent false 'init done' interrupt by
- * doing a dummy read of IND_AB register while in reset.
- */
- regmap_read(cd->regmap, REG_IND_AB, &dummy);
- reinit_completion(&cd->card_boot);
- enable_irq(cd->irq);
- reset_deassert(cd);
- t->task_fn = task_fn_power_on_2;
- return -EINPROGRESS;
-}
-
-int anybuss_set_power(struct anybuss_client *client, bool power_on)
-{
- struct anybuss_host *cd = client->host;
- struct ab_task *t;
- int err;
-
- t = ab_task_create_get(cd->qcache, power_on ?
- task_fn_power_on : task_fn_power_off);
- if (!t)
- return -ENOMEM;
- err = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq);
- ab_task_put(t);
- return err;
-}
-EXPORT_SYMBOL_GPL(anybuss_set_power);
-
-/* ---------------------------- area tasks ------------------------ */
-
-static int task_fn_area_3(struct anybuss_host *cd, struct ab_task *t)
-{
- struct area_priv *pd = &t->area_pd;
-
- if (!cd->power_on)
- return -EIO;
- if (atomic_read(&cd->ind_ab) & pd->flags) {
- /* area not released yet */
- if (time_after(jiffies, t->start_jiffies + TIMEOUT))
- return -ETIMEDOUT;
- return -EINPROGRESS;
- }
- return 0;
-}
-
-static int task_fn_area_2(struct anybuss_host *cd, struct ab_task *t)
-{
- struct area_priv *pd = &t->area_pd;
- unsigned int ind_ap;
- int ret;
-
- if (!cd->power_on)
- return -EIO;
- regmap_read(cd->regmap, REG_IND_AP, &ind_ap);
- if (!(atomic_read(&cd->ind_ab) & pd->flags)) {
- /* we don't own the area yet */
- if (time_after(jiffies, t->start_jiffies + TIMEOUT)) {
- dev_warn(cd->dev, "timeout waiting for area");
- dump_stack();
- return -ETIMEDOUT;
- }
- return -EINPROGRESS;
- }
- /* we own the area, do what we're here to do */
- if (pd->is_write)
- regmap_bulk_write(cd->regmap, pd->addr, pd->buf,
- pd->count);
- else
- regmap_bulk_read(cd->regmap, pd->addr, pd->buf,
- pd->count);
- /* ask to release the area, must use unlocked release */
- ind_ap &= ~IND_AP_ABITS;
- ind_ap |= pd->flags;
- ret = write_ind_ap(cd->regmap, ind_ap);
- if (ret)
- return ret;
- t->task_fn = task_fn_area_3;
- return -EINPROGRESS;
-}
-
-static int task_fn_area(struct anybuss_host *cd, struct ab_task *t)
-{
- struct area_priv *pd = &t->area_pd;
- unsigned int ind_ap;
- int ret;
-
- if (!cd->power_on)
- return -EIO;
- regmap_read(cd->regmap, REG_IND_AP, &ind_ap);
- /* ask to take the area */
- ind_ap &= ~IND_AP_ABITS;
- ind_ap |= pd->flags | IND_AP_ACTION | IND_AP_LOCK;
- ret = write_ind_ap(cd->regmap, ind_ap);
- if (ret)
- return ret;
- t->task_fn = task_fn_area_2;
- return -EINPROGRESS;
-}
-
-static struct ab_task *
-create_area_reader(struct kmem_cache *qcache, u16 flags, u16 addr,
- size_t count)
-{
- struct ab_task *t;
- struct area_priv *ap;
-
- t = ab_task_create_get(qcache, task_fn_area);
- if (!t)
- return NULL;
- ap = &t->area_pd;
- ap->flags = flags;
- ap->addr = addr;
- ap->is_write = false;
- ap->count = count;
- return t;
-}
-
-static struct ab_task *
-create_area_writer(struct kmem_cache *qcache, u16 flags, u16 addr,
- const void *buf, size_t count)
-{
- struct ab_task *t;
- struct area_priv *ap;
-
- t = ab_task_create_get(qcache, task_fn_area);
- if (!t)
- return NULL;
- ap = &t->area_pd;
- ap->flags = flags;
- ap->addr = addr;
- ap->is_write = true;
- ap->count = count;
- memcpy(ap->buf, buf, count);
- return t;
-}
-
-static struct ab_task *
-create_area_user_writer(struct kmem_cache *qcache, u16 flags, u16 addr,
- const void __user *buf, size_t count)
-{
- struct ab_task *t;
- struct area_priv *ap;
-
- t = ab_task_create_get(qcache, task_fn_area);
- if (!t)
- return ERR_PTR(-ENOMEM);
- ap = &t->area_pd;
- ap->flags = flags;
- ap->addr = addr;
- ap->is_write = true;
- ap->count = count;
- if (copy_from_user(ap->buf, buf, count)) {
- ab_task_put(t);
- return ERR_PTR(-EFAULT);
- }
- return t;
-}
-
-static bool area_range_ok(u16 addr, size_t count, u16 area_start,
- size_t area_sz)
-{
- u16 area_end_ex = area_start + area_sz;
- u16 addr_end_ex;
-
- if (addr < area_start)
- return false;
- if (addr >= area_end_ex)
- return false;
- addr_end_ex = addr + count;
- if (addr_end_ex > area_end_ex)
- return false;
- return true;
-}
-
-/* -------------------------- mailbox tasks ----------------------- */
-
-static int task_fn_mbox_2(struct anybuss_host *cd, struct ab_task *t)
-{
- struct mbox_priv *pd = &t->mbox_pd;
- unsigned int ind_ap;
-
- if (!cd->power_on)
- return -EIO;
- regmap_read(cd->regmap, REG_IND_AP, &ind_ap);
- if (((atomic_read(&cd->ind_ab) ^ ind_ap) & IND_AX_MOUT) == 0) {
- /* output message not here */
- if (time_after(jiffies, t->start_jiffies + TIMEOUT))
- return -ETIMEDOUT;
- return -EINPROGRESS;
- }
- /* grab the returned header and msg */
- regmap_bulk_read(cd->regmap, MBOX_OUT_AREA, &pd->hdr,
- sizeof(pd->hdr));
- regmap_bulk_read(cd->regmap, MBOX_OUT_AREA + sizeof(pd->hdr),
- pd->msg, pd->msg_in_sz);
- /* tell anybus we've consumed the message */
- ind_ap ^= IND_AX_MOUT;
- return write_ind_ap(cd->regmap, ind_ap);
-}
-
-static int task_fn_mbox(struct anybuss_host *cd, struct ab_task *t)
-{
- struct mbox_priv *pd = &t->mbox_pd;
- unsigned int ind_ap;
- int ret;
-
- if (!cd->power_on)
- return -EIO;
- regmap_read(cd->regmap, REG_IND_AP, &ind_ap);
- if ((atomic_read(&cd->ind_ab) ^ ind_ap) & IND_AX_MIN) {
- /* mbox input area busy */
- if (time_after(jiffies, t->start_jiffies + TIMEOUT))
- return -ETIMEDOUT;
- return -EINPROGRESS;
- }
- /* write the header and msg to input area */
- regmap_bulk_write(cd->regmap, MBOX_IN_AREA, &pd->hdr,
- sizeof(pd->hdr));
- regmap_bulk_write(cd->regmap, MBOX_IN_AREA + sizeof(pd->hdr),
- pd->msg, pd->msg_out_sz);
- /* tell anybus we gave it a message */
- ind_ap ^= IND_AX_MIN;
- ret = write_ind_ap(cd->regmap, ind_ap);
- if (ret)
- return ret;
- t->start_jiffies = jiffies;
- t->task_fn = task_fn_mbox_2;
- return -EINPROGRESS;
-}
-
-static void log_invalid_other(struct device *dev,
- struct anybus_mbox_hdr *hdr)
-{
- size_t ext_offs = ARRAY_SIZE(hdr->extended) - 1;
- u16 code = be16_to_cpu(hdr->extended[ext_offs]);
-
- dev_err(dev, " Invalid other: [0x%02X]", code);
-}
-
-static const char * const EMSGS[] = {
- "Invalid Message ID",
- "Invalid Message Type",
- "Invalid Command",
- "Invalid Data Size",
- "Message Header Malformed (offset 008h)",
- "Message Header Malformed (offset 00Ah)",
- "Message Header Malformed (offset 00Ch - 00Dh)",
- "Invalid Address",
- "Invalid Response",
- "Flash Config Error",
-};
-
-static int mbox_cmd_err(struct device *dev, struct mbox_priv *mpriv)
-{
- int i;
- u8 ecode;
- struct anybus_mbox_hdr *hdr = &mpriv->hdr;
- u16 info = be16_to_cpu(hdr->info);
- u8 *phdr = (u8 *)hdr;
- u8 *pmsg = mpriv->msg;
-
- if (!(info & 0x8000))
- return 0;
- ecode = (info >> 8) & 0x0F;
- dev_err(dev, "mailbox command failed:");
- if (ecode == 0x0F)
- log_invalid_other(dev, hdr);
- else if (ecode < ARRAY_SIZE(EMSGS))
- dev_err(dev, " Error code: %s (0x%02X)",
- EMSGS[ecode], ecode);
- else
- dev_err(dev, " Error code: 0x%02X\n", ecode);
- dev_err(dev, "Failed command:");
- dev_err(dev, "Message Header:");
- for (i = 0; i < sizeof(mpriv->hdr); i += 2)
- dev_err(dev, "%02X%02X", phdr[i], phdr[i + 1]);
- dev_err(dev, "Message Data:");
- for (i = 0; i < mpriv->msg_in_sz; i += 2)
- dev_err(dev, "%02X%02X", pmsg[i], pmsg[i + 1]);
- dev_err(dev, "Stack dump:");
- dump_stack();
- return -EIO;
-}
-
-static int _anybus_mbox_cmd(struct anybuss_host *cd,
- u16 cmd_num, bool is_fb_cmd,
- const void *msg_out, size_t msg_out_sz,
- void *msg_in, size_t msg_in_sz,
- const void *ext, size_t ext_sz)
-{
- struct ab_task *t;
- struct mbox_priv *pd;
- struct anybus_mbox_hdr *h;
- size_t msg_sz = max(msg_in_sz, msg_out_sz);
- u16 info;
- int err;
-
- if (msg_sz > MAX_MBOX_MSG_SZ)
- return -EINVAL;
- if (ext && ext_sz > sizeof(h->extended))
- return -EINVAL;
- t = ab_task_create_get(cd->qcache, task_fn_mbox);
- if (!t)
- return -ENOMEM;
- pd = &t->mbox_pd;
- h = &pd->hdr;
- info = is_fb_cmd ? INFO_TYPE_FB : INFO_TYPE_APP;
- /*
- * prevent uninitialized memory in the header from being sent
- * across the anybus
- */
- memset(h, 0, sizeof(*h));
- h->info = cpu_to_be16(info | INFO_COMMAND);
- h->cmd_num = cpu_to_be16(cmd_num);
- h->data_size = cpu_to_be16(msg_out_sz);
- h->frame_count = cpu_to_be16(1);
- h->frame_num = cpu_to_be16(1);
- h->offset_high = cpu_to_be16(0);
- h->offset_low = cpu_to_be16(0);
- if (ext)
- memcpy(h->extended, ext, ext_sz);
- memcpy(pd->msg, msg_out, msg_out_sz);
- pd->msg_out_sz = msg_out_sz;
- pd->msg_in_sz = msg_in_sz;
- err = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq);
- if (err)
- goto out;
- /*
- * mailbox mechanism worked ok, but maybe the mbox response
- * contains an error ?
- */
- err = mbox_cmd_err(cd->dev, pd);
- if (err)
- goto out;
- memcpy(msg_in, pd->msg, msg_in_sz);
-out:
- ab_task_put(t);
- return err;
-}
-
-/* ------------------------ anybus queues ------------------------ */
-
-static void process_q(struct anybuss_host *cd, struct kfifo *q)
-{
- struct ab_task *t;
- int ret;
-
- ret = kfifo_out_peek(q, &t, sizeof(t));
- if (!ret)
- return;
- t->result = t->task_fn(cd, t);
- if (t->result != -EINPROGRESS)
- ab_task_dequeue_finish_put(q, cd);
-}
-
-static bool qs_have_work(struct kfifo *qs, size_t num)
-{
- size_t i;
- struct ab_task *t;
- int ret;
-
- for (i = 0; i < num; i++, qs++) {
- ret = kfifo_out_peek(qs, &t, sizeof(t));
- if (ret && (t->result != -EINPROGRESS))
- return true;
- }
- return false;
-}
-
-static void process_qs(struct anybuss_host *cd)
-{
- size_t i;
- struct kfifo *qs = cd->qs;
- size_t nqs = ARRAY_SIZE(cd->qs);
-
- for (i = 0; i < nqs; i++, qs++)
- process_q(cd, qs);
-}
-
-static void softint_ack(struct anybuss_host *cd)
-{
- unsigned int ind_ap;
-
- cd->softint_pending = false;
- if (!cd->power_on)
- return;
- regmap_read(cd->regmap, REG_IND_AP, &ind_ap);
- ind_ap &= ~IND_AX_EVNT;
- ind_ap |= atomic_read(&cd->ind_ab) & IND_AX_EVNT;
- write_ind_ap(cd->regmap, ind_ap);
-}
-
-static void process_softint(struct anybuss_host *cd)
-{
- struct anybuss_client *client = cd->client;
- static const u8 zero;
- int ret;
- unsigned int ind_ap, ev;
- struct ab_task *t;
-
- if (!cd->power_on)
- return;
- if (cd->softint_pending)
- return;
- regmap_read(cd->regmap, REG_IND_AP, &ind_ap);
- if (!((atomic_read(&cd->ind_ab) ^ ind_ap) & IND_AX_EVNT))
- return;
- /* process software interrupt */
- regmap_read(cd->regmap, REG_EVENT_CAUSE, &ev);
- if (ev & EVENT_CAUSE_FBON) {
- if (client->on_online_changed)
- client->on_online_changed(client, true);
- dev_dbg(cd->dev, "Fieldbus ON");
- }
- if (ev & EVENT_CAUSE_FBOF) {
- if (client->on_online_changed)
- client->on_online_changed(client, false);
- dev_dbg(cd->dev, "Fieldbus OFF");
- }
- if (ev & EVENT_CAUSE_DC) {
- if (client->on_area_updated)
- client->on_area_updated(client);
- dev_dbg(cd->dev, "Fieldbus data changed");
- }
- /*
- * reset the event cause bits.
- * this must be done while owning the fbctrl area, so we'll
- * enqueue a task to do that.
- */
- t = create_area_writer(cd->qcache, IND_AX_FBCTRL,
- REG_EVENT_CAUSE, &zero, sizeof(zero));
- if (!t) {
- ret = -ENOMEM;
- goto out;
- }
- t->done_fn = softint_ack;
- ret = ab_task_enqueue(t, cd->powerq, &cd->qlock, &cd->wq);
- ab_task_put(t);
- cd->softint_pending = true;
-out:
- WARN_ON(ret);
- if (ret)
- softint_ack(cd);
-}
-
-static int qthread_fn(void *data)
-{
- struct anybuss_host *cd = data;
- struct kfifo *qs = cd->qs;
- size_t nqs = ARRAY_SIZE(cd->qs);
- unsigned int ind_ab;
-
- /*
- * this kernel thread has exclusive access to the anybus's memory.
- * only exception: the IND_AB register, which is accessed exclusively
- * by the interrupt service routine (ISR). This thread must not touch
- * the IND_AB register, but it does require access to its value.
- *
- * the interrupt service routine stores the register's value in
- * cd->ind_ab (an atomic_t), where we may safely access it, with the
- * understanding that it can be modified by the ISR at any time.
- */
-
- while (!kthread_should_stop()) {
- /*
- * make a local copy of IND_AB, so we can go around the loop
- * again in case it changed while processing queues and softint.
- */
- ind_ab = atomic_read(&cd->ind_ab);
- process_qs(cd);
- process_softint(cd);
- wait_event_timeout(cd->wq,
- (atomic_read(&cd->ind_ab) != ind_ab) ||
- qs_have_work(qs, nqs) ||
- kthread_should_stop(),
- HZ);
- /*
- * time out so even 'stuck' tasks will run eventually,
- * and can time out.
- */
- }
-
- return 0;
-}
-
-/* ------------------------ anybus exports ------------------------ */
-
-int anybuss_start_init(struct anybuss_client *client,
- const struct anybuss_memcfg *cfg)
-{
- int ret;
- u16 op_mode;
- struct anybuss_host *cd = client->host;
- struct msg_anybus_init msg = {
- .input_io_len = cpu_to_be16(cfg->input_io),
- .input_dpram_len = cpu_to_be16(cfg->input_dpram),
- .input_total_len = cpu_to_be16(cfg->input_total),
- .output_io_len = cpu_to_be16(cfg->output_io),
- .output_dpram_len = cpu_to_be16(cfg->output_dpram),
- .output_total_len = cpu_to_be16(cfg->output_total),
- .notif_config = cpu_to_be16(0x000F),
- .wd_val = cpu_to_be16(0),
- };
-
- switch (cfg->offl_mode) {
- case FIELDBUS_DEV_OFFL_MODE_CLEAR:
- op_mode = 0;
- break;
- case FIELDBUS_DEV_OFFL_MODE_FREEZE:
- op_mode = OP_MODE_FBFC;
- break;
- case FIELDBUS_DEV_OFFL_MODE_SET:
- op_mode = OP_MODE_FBS;
- break;
- default:
- return -EINVAL;
- }
- msg.op_mode = cpu_to_be16(op_mode | OP_MODE_CD);
- ret = _anybus_mbox_cmd(cd, CMD_START_INIT, false, NULL, 0,
- NULL, 0, NULL, 0);
- if (ret)
- return ret;
- return _anybus_mbox_cmd(cd, CMD_ANYBUS_INIT, false,
- &msg, sizeof(msg), NULL, 0, NULL, 0);
-}
-EXPORT_SYMBOL_GPL(anybuss_start_init);
-
-int anybuss_finish_init(struct anybuss_client *client)
-{
- struct anybuss_host *cd = client->host;
-
- return _anybus_mbox_cmd(cd, CMD_END_INIT, false, NULL, 0,
- NULL, 0, NULL, 0);
-}
-EXPORT_SYMBOL_GPL(anybuss_finish_init);
-
-int anybuss_read_fbctrl(struct anybuss_client *client, u16 addr,
- void *buf, size_t count)
-{
- struct anybuss_host *cd = client->host;
- struct ab_task *t;
- int ret;
-
- if (count == 0)
- return 0;
- if (!area_range_ok(addr, count, FBCTRL_AREA,
- MAX_FBCTRL_AREA_SZ))
- return -EFAULT;
- t = create_area_reader(cd->qcache, IND_AX_FBCTRL, addr, count);
- if (!t)
- return -ENOMEM;
- ret = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq);
- if (ret)
- goto out;
- memcpy(buf, t->area_pd.buf, count);
-out:
- ab_task_put(t);
- return ret;
-}
-EXPORT_SYMBOL_GPL(anybuss_read_fbctrl);
-
-int anybuss_write_input(struct anybuss_client *client,
- const char __user *buf, size_t size,
- loff_t *offset)
-{
- ssize_t len = min_t(loff_t, MAX_DATA_AREA_SZ - *offset, size);
- struct anybuss_host *cd = client->host;
- struct ab_task *t;
- int ret;
-
- if (len <= 0)
- return 0;
- t = create_area_user_writer(cd->qcache, IND_AX_IN,
- DATA_IN_AREA + *offset, buf, len);
- if (IS_ERR(t))
- return PTR_ERR(t);
- ret = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq);
- ab_task_put(t);
- if (ret)
- return ret;
- /* success */
- *offset += len;
- return len;
-}
-EXPORT_SYMBOL_GPL(anybuss_write_input);
-
-int anybuss_read_output(struct anybuss_client *client,
- char __user *buf, size_t size,
- loff_t *offset)
-{
- ssize_t len = min_t(loff_t, MAX_DATA_AREA_SZ - *offset, size);
- struct anybuss_host *cd = client->host;
- struct ab_task *t;
- int ret;
-
- if (len <= 0)
- return 0;
- t = create_area_reader(cd->qcache, IND_AX_OUT,
- DATA_OUT_AREA + *offset, len);
- if (!t)
- return -ENOMEM;
- ret = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq);
- if (ret)
- goto out;
- if (copy_to_user(buf, t->area_pd.buf, len))
- ret = -EFAULT;
-out:
- ab_task_put(t);
- if (ret)
- return ret;
- /* success */
- *offset += len;
- return len;
-}
-EXPORT_SYMBOL_GPL(anybuss_read_output);
-
-int anybuss_send_msg(struct anybuss_client *client, u16 cmd_num,
- const void *buf, size_t count)
-{
- struct anybuss_host *cd = client->host;
-
- return _anybus_mbox_cmd(cd, cmd_num, true, buf, count, NULL, 0,
- NULL, 0);
-}
-EXPORT_SYMBOL_GPL(anybuss_send_msg);
-
-int anybuss_send_ext(struct anybuss_client *client, u16 cmd_num,
- const void *buf, size_t count)
-{
- struct anybuss_host *cd = client->host;
-
- return _anybus_mbox_cmd(cd, cmd_num, true, NULL, 0, NULL, 0,
- buf, count);
-}
-EXPORT_SYMBOL_GPL(anybuss_send_ext);
-
-int anybuss_recv_msg(struct anybuss_client *client, u16 cmd_num,
- void *buf, size_t count)
-{
- struct anybuss_host *cd = client->host;
-
- return _anybus_mbox_cmd(cd, cmd_num, true, NULL, 0, buf, count,
- NULL, 0);
-}
-EXPORT_SYMBOL_GPL(anybuss_recv_msg);
-
-/* ------------------------ bus functions ------------------------ */
-
-static int anybus_bus_match(struct device *dev,
- const struct device_driver *drv)
-{
- const struct anybuss_client_driver *adrv =
- to_anybuss_client_driver(drv);
- struct anybuss_client *adev =
- to_anybuss_client(dev);
-
- return adrv->anybus_id == be16_to_cpu(adev->anybus_id);
-}
-
-static int anybus_bus_probe(struct device *dev)
-{
- struct anybuss_client_driver *adrv =
- to_anybuss_client_driver(dev->driver);
- struct anybuss_client *adev =
- to_anybuss_client(dev);
-
- return adrv->probe(adev);
-}
-
-static void anybus_bus_remove(struct device *dev)
-{
- struct anybuss_client_driver *adrv =
- to_anybuss_client_driver(dev->driver);
-
- if (adrv->remove)
- adrv->remove(to_anybuss_client(dev));
-}
-
-static const struct bus_type anybus_bus = {
- .name = "anybuss",
- .match = anybus_bus_match,
- .probe = anybus_bus_probe,
- .remove = anybus_bus_remove,
-};
-
-int anybuss_client_driver_register(struct anybuss_client_driver *drv)
-{
- if (!drv->probe)
- return -ENODEV;
-
- drv->driver.bus = &anybus_bus;
- return driver_register(&drv->driver);
-}
-EXPORT_SYMBOL_GPL(anybuss_client_driver_register);
-
-void anybuss_client_driver_unregister(struct anybuss_client_driver *drv)
-{
- return driver_unregister(&drv->driver);
-}
-EXPORT_SYMBOL_GPL(anybuss_client_driver_unregister);
-
-static void client_device_release(struct device *dev)
-{
- kfree(to_anybuss_client(dev));
-}
-
-static int taskq_alloc(struct device *dev, struct kfifo *q)
-{
- void *buf;
- size_t size = 64 * sizeof(struct ab_task *);
-
- buf = devm_kzalloc(dev, size, GFP_KERNEL);
- if (!buf)
- return -EIO;
- return kfifo_init(q, buf, size);
-}
-
-static int anybus_of_get_host_idx(struct device_node *np)
-{
- const __be32 *host_idx;
-
- host_idx = of_get_address(np, 0, NULL, NULL);
- if (!host_idx)
- return -ENOENT;
- return __be32_to_cpu(*host_idx);
-}
-
-static struct device_node *
-anybus_of_find_child_device(struct device *dev, int host_idx)
-{
- struct device_node *node;
-
- if (!dev || !dev->of_node)
- return NULL;
- for_each_child_of_node(dev->of_node, node) {
- if (anybus_of_get_host_idx(node) == host_idx)
- return node;
- }
- return NULL;
-}
-
-struct anybuss_host * __must_check
-anybuss_host_common_probe(struct device *dev,
- const struct anybuss_ops *ops)
-{
- int ret, i;
- u8 val[4];
- __be16 fieldbus_type;
- struct anybuss_host *cd;
-
- cd = devm_kzalloc(dev, sizeof(*cd), GFP_KERNEL);
- if (!cd)
- return ERR_PTR(-ENOMEM);
- cd->dev = dev;
- cd->host_idx = ops->host_idx;
- init_completion(&cd->card_boot);
- init_waitqueue_head(&cd->wq);
- for (i = 0; i < ARRAY_SIZE(cd->qs); i++) {
- ret = taskq_alloc(dev, &cd->qs[i]);
- if (ret)
- return ERR_PTR(ret);
- }
- if (WARN_ON(ARRAY_SIZE(cd->qs) < 3))
- return ERR_PTR(-EINVAL);
- cd->powerq = &cd->qs[0];
- cd->mboxq = &cd->qs[1];
- cd->areaq = &cd->qs[2];
- cd->reset = ops->reset;
- if (!cd->reset)
- return ERR_PTR(-EINVAL);
- cd->regmap = ops->regmap;
- if (!cd->regmap)
- return ERR_PTR(-EINVAL);
- spin_lock_init(&cd->qlock);
- cd->qcache = kmem_cache_create(dev_name(dev),
- sizeof(struct ab_task), 0, 0, NULL);
- if (!cd->qcache)
- return ERR_PTR(-ENOMEM);
- cd->irq = ops->irq;
- if (cd->irq <= 0) {
- ret = -EINVAL;
- goto err_qcache;
- }
- /*
- * use a dpram test to check if a card is present, this is only
- * possible while in reset.
- */
- reset_assert(cd);
- if (test_dpram(cd->regmap)) {
- dev_err(dev, "no Anybus-S card in slot");
- ret = -ENODEV;
- goto err_qcache;
- }
- ret = devm_request_threaded_irq(dev, cd->irq, NULL, irq_handler,
- IRQF_ONESHOT, dev_name(dev), cd);
- if (ret) {
- dev_err(dev, "could not request irq");
- goto err_qcache;
- }
- /*
- * startup sequence:
- * a) perform dummy IND_AB read to prevent false 'init done' irq
- * (already done by test_dpram() above)
- * b) release reset
- * c) wait for first interrupt
- * d) interrupt came in: ready to go !
- */
- reset_deassert(cd);
- if (!wait_for_completion_timeout(&cd->card_boot, TIMEOUT)) {
- ret = -ETIMEDOUT;
- goto err_reset;
- }
- /*
- * according to the anybus docs, we're allowed to read these
- * without handshaking / reserving the area
- */
- dev_info(dev, "Anybus-S card detected");
- regmap_bulk_read(cd->regmap, REG_BOOTLOADER_V, val, 2);
- dev_info(dev, "Bootloader version: %02X%02X",
- val[0], val[1]);
- regmap_bulk_read(cd->regmap, REG_API_V, val, 2);
- dev_info(dev, "API version: %02X%02X", val[0], val[1]);
- regmap_bulk_read(cd->regmap, REG_FIELDBUS_V, val, 2);
- dev_info(dev, "Fieldbus version: %02X%02X", val[0], val[1]);
- regmap_bulk_read(cd->regmap, REG_SERIAL_NO, val, 4);
- dev_info(dev, "Serial number: %02X%02X%02X%02X",
- val[0], val[1], val[2], val[3]);
- add_device_randomness(&val, 4);
- regmap_bulk_read(cd->regmap, REG_FIELDBUS_TYPE, &fieldbus_type,
- sizeof(fieldbus_type));
- dev_info(dev, "Fieldbus type: %04X", be16_to_cpu(fieldbus_type));
- regmap_bulk_read(cd->regmap, REG_MODULE_SW_V, val, 2);
- dev_info(dev, "Module SW version: %02X%02X",
- val[0], val[1]);
- /* put card back reset until a client driver releases it */
- disable_irq(cd->irq);
- reset_assert(cd);
- atomic_set(&cd->ind_ab, IND_AB_UPDATED);
- /* fire up the queue thread */
- cd->qthread = kthread_run(qthread_fn, cd, dev_name(dev));
- if (IS_ERR(cd->qthread)) {
- dev_err(dev, "could not create kthread");
- ret = PTR_ERR(cd->qthread);
- goto err_reset;
- }
- /*
- * now advertise that we've detected a client device (card).
- * the bus infrastructure will match it to a client driver.
- */
- cd->client = kzalloc(sizeof(*cd->client), GFP_KERNEL);
- if (!cd->client) {
- ret = -ENOMEM;
- goto err_kthread;
- }
- cd->client->anybus_id = fieldbus_type;
- cd->client->host = cd;
- cd->client->dev.bus = &anybus_bus;
- cd->client->dev.parent = dev;
- cd->client->dev.release = client_device_release;
- cd->client->dev.of_node =
- anybus_of_find_child_device(dev, cd->host_idx);
- dev_set_name(&cd->client->dev, "anybuss.card%d", cd->host_idx);
- ret = device_register(&cd->client->dev);
- if (ret)
- goto err_device;
- return cd;
-err_device:
- put_device(&cd->client->dev);
-err_kthread:
- kthread_stop(cd->qthread);
-err_reset:
- reset_assert(cd);
-err_qcache:
- kmem_cache_destroy(cd->qcache);
- return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(anybuss_host_common_probe);
-
-void anybuss_host_common_remove(struct anybuss_host *host)
-{
- struct anybuss_host *cd = host;
-
- device_unregister(&cd->client->dev);
- kthread_stop(cd->qthread);
- reset_assert(cd);
- kmem_cache_destroy(cd->qcache);
-}
-EXPORT_SYMBOL_GPL(anybuss_host_common_remove);
-
-static void host_release(void *res)
-{
- anybuss_host_common_remove(res);
-}
-
-struct anybuss_host * __must_check
-devm_anybuss_host_common_probe(struct device *dev,
- const struct anybuss_ops *ops)
-{
- struct anybuss_host *host;
- int ret;
-
- host = anybuss_host_common_probe(dev, ops);
- if (IS_ERR(host))
- return host;
-
- ret = devm_add_action_or_reset(dev, host_release, host);
- if (ret)
- return ERR_PTR(ret);
-
- return host;
-}
-EXPORT_SYMBOL_GPL(devm_anybuss_host_common_probe);
-
-static int __init anybus_init(void)
-{
- int ret;
-
- ret = bus_register(&anybus_bus);
- if (ret)
- pr_err("could not register Anybus-S bus: %d\n", ret);
- return ret;
-}
-module_init(anybus_init);
-
-static void __exit anybus_exit(void)
-{
- bus_unregister(&anybus_bus);
-}
-module_exit(anybus_exit);
-
-MODULE_DESCRIPTION("HMS Anybus-S Host Driver");
-MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/fieldbus/dev_core.c b/drivers/staging/fieldbus/dev_core.c
deleted file mode 100644
index 0053ebd91442..000000000000
--- a/drivers/staging/fieldbus/dev_core.c
+++ /dev/null
@@ -1,344 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Fieldbus Device Driver Core
- *
- */
-
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/idr.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-
-/* move to <linux/fieldbus_dev.h> when taking this out of staging */
-#include "fieldbus_dev.h"
-
-/* Maximum number of fieldbus devices */
-#define MAX_FIELDBUSES 32
-
-/* the dev_t structure to store the dynamically allocated fieldbus devices */
-static dev_t fieldbus_devt;
-static DEFINE_IDA(fieldbus_ida);
-static DEFINE_MUTEX(fieldbus_mtx);
-
-static ssize_t online_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%d\n", !!fb->online);
-}
-static DEVICE_ATTR_RO(online);
-
-static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
-
- if (!fb->enable_get)
- return -EINVAL;
- return sysfs_emit(buf, "%d\n", !!fb->enable_get(fb));
-}
-
-static ssize_t enabled_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t n)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
- bool value;
- int ret;
-
- if (!fb->simple_enable_set)
- return -ENOTSUPP;
- ret = kstrtobool(buf, &value);
- if (ret)
- return ret;
- ret = fb->simple_enable_set(fb, value);
- if (ret < 0)
- return ret;
- return n;
-}
-static DEVICE_ATTR_RW(enabled);
-
-static ssize_t card_name_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
-
- /* card_name was provided by child driver. */
- return sysfs_emit(buf, "%s\n", fb->card_name);
-}
-static DEVICE_ATTR_RO(card_name);
-
-static ssize_t read_area_size_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%zu\n", fb->read_area_sz);
-}
-static DEVICE_ATTR_RO(read_area_size);
-
-static ssize_t write_area_size_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%zu\n", fb->write_area_sz);
-}
-static DEVICE_ATTR_RO(write_area_size);
-
-static ssize_t fieldbus_id_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
-
- return fb->fieldbus_id_get(fb, buf, PAGE_SIZE);
-}
-static DEVICE_ATTR_RO(fieldbus_id);
-
-static ssize_t fieldbus_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
- const char *t;
-
- switch (fb->fieldbus_type) {
- case FIELDBUS_DEV_TYPE_PROFINET:
- t = "profinet";
- break;
- default:
- t = "unknown";
- break;
- }
-
- return sysfs_emit(buf, "%s\n", t);
-}
-static DEVICE_ATTR_RO(fieldbus_type);
-
-static struct attribute *fieldbus_attrs[] = {
- &dev_attr_enabled.attr,
- &dev_attr_card_name.attr,
- &dev_attr_fieldbus_id.attr,
- &dev_attr_read_area_size.attr,
- &dev_attr_write_area_size.attr,
- &dev_attr_online.attr,
- &dev_attr_fieldbus_type.attr,
- NULL,
-};
-
-static umode_t fieldbus_is_visible(struct kobject *kobj, struct attribute *attr,
- int n)
-{
- struct device *dev = kobj_to_dev(kobj);
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
- umode_t mode = attr->mode;
-
- if (attr == &dev_attr_enabled.attr) {
- mode = 0;
- if (fb->enable_get)
- mode |= 0444;
- if (fb->simple_enable_set)
- mode |= 0200;
- }
-
- return mode;
-}
-
-static const struct attribute_group fieldbus_group = {
- .attrs = fieldbus_attrs,
- .is_visible = fieldbus_is_visible,
-};
-__ATTRIBUTE_GROUPS(fieldbus);
-
-static const struct class fieldbus_class = {
- .name = "fieldbus_dev",
- .dev_groups = fieldbus_groups,
-};
-
-struct fb_open_file {
- struct fieldbus_dev *fbdev;
- int dc_event;
-};
-
-static int fieldbus_open(struct inode *inode, struct file *filp)
-{
- struct fb_open_file *of;
- struct fieldbus_dev *fbdev = container_of(inode->i_cdev,
- struct fieldbus_dev,
- cdev);
-
- of = kzalloc(sizeof(*of), GFP_KERNEL);
- if (!of)
- return -ENOMEM;
- of->fbdev = fbdev;
- filp->private_data = of;
- return 0;
-}
-
-static int fieldbus_release(struct inode *node, struct file *filp)
-{
- struct fb_open_file *of = filp->private_data;
-
- kfree(of);
- return 0;
-}
-
-static ssize_t fieldbus_read(struct file *filp, char __user *buf, size_t size,
- loff_t *offset)
-{
- struct fb_open_file *of = filp->private_data;
- struct fieldbus_dev *fbdev = of->fbdev;
-
- of->dc_event = fbdev->dc_event;
- return fbdev->read_area(fbdev, buf, size, offset);
-}
-
-static ssize_t fieldbus_write(struct file *filp, const char __user *buf,
- size_t size, loff_t *offset)
-{
- struct fb_open_file *of = filp->private_data;
- struct fieldbus_dev *fbdev = of->fbdev;
-
- return fbdev->write_area(fbdev, buf, size, offset);
-}
-
-static __poll_t fieldbus_poll(struct file *filp, poll_table *wait)
-{
- struct fb_open_file *of = filp->private_data;
- struct fieldbus_dev *fbdev = of->fbdev;
- __poll_t mask = EPOLLIN | EPOLLRDNORM | EPOLLOUT | EPOLLWRNORM;
-
- poll_wait(filp, &fbdev->dc_wq, wait);
- /* data changed ? */
- if (fbdev->dc_event != of->dc_event)
- mask |= EPOLLPRI | EPOLLERR;
- return mask;
-}
-
-static const struct file_operations fieldbus_fops = {
- .open = fieldbus_open,
- .release = fieldbus_release,
- .read = fieldbus_read,
- .write = fieldbus_write,
- .poll = fieldbus_poll,
- .llseek = generic_file_llseek,
- .owner = THIS_MODULE,
-};
-
-void fieldbus_dev_area_updated(struct fieldbus_dev *fb)
-{
- fb->dc_event++;
- wake_up_all(&fb->dc_wq);
-}
-EXPORT_SYMBOL_GPL(fieldbus_dev_area_updated);
-
-void fieldbus_dev_online_changed(struct fieldbus_dev *fb, bool online)
-{
- fb->online = online;
- kobject_uevent(&fb->dev->kobj, KOBJ_CHANGE);
-}
-EXPORT_SYMBOL_GPL(fieldbus_dev_online_changed);
-
-static void __fieldbus_dev_unregister(struct fieldbus_dev *fb)
-{
- if (!fb)
- return;
- device_destroy(&fieldbus_class, fb->cdev.dev);
- cdev_del(&fb->cdev);
- ida_free(&fieldbus_ida, fb->id);
-}
-
-void fieldbus_dev_unregister(struct fieldbus_dev *fb)
-{
- mutex_lock(&fieldbus_mtx);
- __fieldbus_dev_unregister(fb);
- mutex_unlock(&fieldbus_mtx);
-}
-EXPORT_SYMBOL_GPL(fieldbus_dev_unregister);
-
-static int __fieldbus_dev_register(struct fieldbus_dev *fb)
-{
- dev_t devno;
- int err;
-
- if (!fb)
- return -EINVAL;
- if (!fb->read_area || !fb->write_area || !fb->fieldbus_id_get)
- return -EINVAL;
- fb->id = ida_alloc_max(&fieldbus_ida, MAX_FIELDBUSES - 1, GFP_KERNEL);
- if (fb->id < 0)
- return fb->id;
- devno = MKDEV(MAJOR(fieldbus_devt), fb->id);
- init_waitqueue_head(&fb->dc_wq);
- cdev_init(&fb->cdev, &fieldbus_fops);
- err = cdev_add(&fb->cdev, devno, 1);
- if (err) {
- pr_err("fieldbus_dev%d unable to add device %d:%d\n",
- fb->id, MAJOR(fieldbus_devt), fb->id);
- goto err_cdev;
- }
- fb->dev = device_create(&fieldbus_class, fb->parent, devno, fb,
- "fieldbus_dev%d", fb->id);
- if (IS_ERR(fb->dev)) {
- err = PTR_ERR(fb->dev);
- goto err_dev_create;
- }
- return 0;
-
-err_dev_create:
- cdev_del(&fb->cdev);
-err_cdev:
- ida_free(&fieldbus_ida, fb->id);
- return err;
-}
-
-int fieldbus_dev_register(struct fieldbus_dev *fb)
-{
- int err;
-
- mutex_lock(&fieldbus_mtx);
- err = __fieldbus_dev_register(fb);
- mutex_unlock(&fieldbus_mtx);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(fieldbus_dev_register);
-
-static int __init fieldbus_init(void)
-{
- int err;
-
- err = class_register(&fieldbus_class);
- if (err < 0) {
- pr_err("fieldbus_dev: could not register class\n");
- return err;
- }
- err = alloc_chrdev_region(&fieldbus_devt, 0,
- MAX_FIELDBUSES, "fieldbus_dev");
- if (err < 0) {
- pr_err("fieldbus_dev: unable to allocate char dev region\n");
- goto err_alloc;
- }
- return 0;
-
-err_alloc:
- class_unregister(&fieldbus_class);
- return err;
-}
-
-static void __exit fieldbus_exit(void)
-{
- unregister_chrdev_region(fieldbus_devt, MAX_FIELDBUSES);
- class_unregister(&fieldbus_class);
- ida_destroy(&fieldbus_ida);
-}
-
-subsys_initcall(fieldbus_init);
-module_exit(fieldbus_exit);
-
-MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>");
-MODULE_AUTHOR("Jonathan Stiles <jonathans@arcx.com>");
-MODULE_DESCRIPTION("Fieldbus Device Driver Core");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/fieldbus/fieldbus_dev.h b/drivers/staging/fieldbus/fieldbus_dev.h
deleted file mode 100644
index 301dca3b8d71..000000000000
--- a/drivers/staging/fieldbus/fieldbus_dev.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Fieldbus Device Driver Core
- *
- */
-
-#ifndef __FIELDBUS_DEV_H
-#define __FIELDBUS_DEV_H
-
-#include <linux/cdev.h>
-#include <linux/wait.h>
-
-enum fieldbus_dev_type {
- FIELDBUS_DEV_TYPE_UNKNOWN = 0,
- FIELDBUS_DEV_TYPE_PROFINET,
-};
-
-enum fieldbus_dev_offl_mode {
- FIELDBUS_DEV_OFFL_MODE_CLEAR = 0,
- FIELDBUS_DEV_OFFL_MODE_FREEZE,
- FIELDBUS_DEV_OFFL_MODE_SET
-};
-
-/**
- * struct fieldbus_dev - Fieldbus device
- * @read_area: [DRIVER] function to read the process data area of the
- * device. same parameters/return values as
- * the read function in struct file_operations
- * @write_area: [DRIVER] function to write to the process data area of
- * the device. same parameters/return values as
- * the write function in struct file_operations
- * @write_area_sz [DRIVER] size of the writable process data area
- * @read_area_sz [DRIVER] size of the readable process data area
- * @card_name [DRIVER] name of the card, e.g. "ACME Inc. profinet"
- * @fieldbus_type [DRIVER] fieldbus type of this device, e.g.
- * FIELDBUS_DEV_TYPE_PROFINET
- * @enable_get [DRIVER] function which returns true if the card
- * is enabled, false otherwise
- * @fieldbus_id_get [DRIVER] function to retrieve the unique fieldbus id
- * by which this device can be identified;
- * return value follows the snprintf convention
- * @simple_enable_set [DRIVER] (optional) function to enable the device
- * according to its default settings
- * @parent [DRIVER] (optional) the device's parent device
- */
-struct fieldbus_dev {
- ssize_t (*read_area)(struct fieldbus_dev *fbdev, char __user *buf,
- size_t size, loff_t *offset);
- ssize_t (*write_area)(struct fieldbus_dev *fbdev,
- const char __user *buf, size_t size,
- loff_t *offset);
- size_t write_area_sz, read_area_sz;
- const char *card_name;
- enum fieldbus_dev_type fieldbus_type;
- bool (*enable_get)(struct fieldbus_dev *fbdev);
- int (*fieldbus_id_get)(struct fieldbus_dev *fbdev, char *buf,
- size_t max_size);
- int (*simple_enable_set)(struct fieldbus_dev *fbdev, bool enable);
- struct device *parent;
-
- /* private data */
- int id;
- struct cdev cdev;
- struct device *dev;
- int dc_event;
- wait_queue_head_t dc_wq;
- bool online;
-};
-
-#if IS_ENABLED(CONFIG_FIELDBUS_DEV)
-
-/**
- * fieldbus_dev_unregister()
- * - unregister a previously registered fieldbus device
- * @fb: Device structure previously registered
- **/
-void fieldbus_dev_unregister(struct fieldbus_dev *fb);
-
-/**
- * fieldbus_dev_register()
- * - register a device with the fieldbus device subsystem
- * @fb: Device structure filled by the device driver
- **/
-int __must_check fieldbus_dev_register(struct fieldbus_dev *fb);
-
-/**
- * fieldbus_dev_area_updated()
- * - notify the subsystem that an external fieldbus controller updated
- * the process data area
- * @fb: Device structure
- **/
-void fieldbus_dev_area_updated(struct fieldbus_dev *fb);
-
-/**
- * fieldbus_dev_online_changed()
- * - notify the subsystem that the fieldbus online status changed
- * @fb: Device structure
- **/
-void fieldbus_dev_online_changed(struct fieldbus_dev *fb, bool online);
-
-#else /* IS_ENABLED(CONFIG_FIELDBUS_DEV) */
-
-static inline void fieldbus_dev_unregister(struct fieldbus_dev *fb) {}
-static inline int __must_check fieldbus_dev_register(struct fieldbus_dev *fb)
-{
- return -ENOTSUPP;
-}
-
-static inline void fieldbus_dev_area_updated(struct fieldbus_dev *fb) {}
-static inline void fieldbus_dev_online_changed(struct fieldbus_dev *fb,
- bool online) {}
-
-#endif /* IS_ENABLED(CONFIG_FIELDBUS_DEV) */
-#endif /* __FIELDBUS_DEV_H */
diff --git a/drivers/staging/gdm724x/Kconfig b/drivers/staging/gdm724x/Kconfig
deleted file mode 100644
index 1f403ecd9608..000000000000
--- a/drivers/staging/gdm724x/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# GCT GDM724x LTE driver configuration
-#
-
-config LTE_GDM724X
- tristate "GCT GDM724x LTE support"
- depends on NET && USB && TTY && m
- help
- This driver supports GCT GDM724x LTE chip based USB modem devices.
- It exposes 4 network devices to be used per PDN and 2 tty devices to be
- used for AT commands and DM monitoring applications.
- The modules will be called gdmulte.ko and gdmtty.ko
-
- GCT-ATCx can be used for AT Commands
- GCT-DMx can be used for LTE protocol monitoring
diff --git a/drivers/staging/gdm724x/Makefile b/drivers/staging/gdm724x/Makefile
deleted file mode 100644
index e61b95788c9f..000000000000
--- a/drivers/staging/gdm724x/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_LTE_GDM724X) := gdmulte.o
-gdmulte-y += gdm_lte.o netlink_k.o
-gdmulte-y += gdm_usb.o gdm_endian.o
-
-obj-$(CONFIG_LTE_GDM724X) += gdmtty.o
-gdmtty-y := gdm_tty.o gdm_mux.o
-
diff --git a/drivers/staging/gdm724x/TODO b/drivers/staging/gdm724x/TODO
deleted file mode 100644
index b2b571ecb063..000000000000
--- a/drivers/staging/gdm724x/TODO
+++ /dev/null
@@ -1,16 +0,0 @@
-TODO:
-- Clean up coding style to meet kernel standard. (80 line limit, netdev_err)
-- Remove test for host endian
-- Remove confusing macros (endian, hci_send, sdu_send, rcv_with_cb)
-- Fixes for every instances of function returning -1
-- Check for skb->len in gdm_lte_emulate_arp()
-- Use ALIGN() macro for dummy_cnt in up_to_host()
-- Error handling in init_usb()
-- Explain reason for multiples of 512 bytes in alloc_tx_struct()
-- Review use of atomic allocation for tx structs
-- No error checking for alloc_tx_struct in do_tx()
-- fix up static tty port allocation to be dynamic
-
-Patches to:
- Jonathan Kim <jonathankim@gctsemi.com>
- Dean ahn <deanahn@gctsemi.com>
diff --git a/drivers/staging/gdm724x/gdm_endian.c b/drivers/staging/gdm724x/gdm_endian.c
deleted file mode 100644
index ae39e59daf70..000000000000
--- a/drivers/staging/gdm724x/gdm_endian.c
+++ /dev/null
@@ -1,37 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#include <linux/kernel.h>
-#include "gdm_endian.h"
-
-__dev16 gdm_cpu_to_dev16(u8 dev_ed, u16 x)
-{
- if (dev_ed == ENDIANNESS_LITTLE)
- return (__force __dev16)cpu_to_le16(x);
- else
- return (__force __dev16)cpu_to_be16(x);
-}
-
-u16 gdm_dev16_to_cpu(u8 dev_ed, __dev16 x)
-{
- if (dev_ed == ENDIANNESS_LITTLE)
- return le16_to_cpu((__force __le16)x);
- else
- return be16_to_cpu((__force __be16)x);
-}
-
-__dev32 gdm_cpu_to_dev32(u8 dev_ed, u32 x)
-{
- if (dev_ed == ENDIANNESS_LITTLE)
- return (__force __dev32)cpu_to_le32(x);
- else
- return (__force __dev32)cpu_to_be32(x);
-}
-
-u32 gdm_dev32_to_cpu(u8 dev_ed, __dev32 x)
-{
- if (dev_ed == ENDIANNESS_LITTLE)
- return le32_to_cpu((__force __le32)x);
- else
- return be32_to_cpu((__force __be32)x);
-}
diff --git a/drivers/staging/gdm724x/gdm_endian.h b/drivers/staging/gdm724x/gdm_endian.h
deleted file mode 100644
index f373dc3a19bf..000000000000
--- a/drivers/staging/gdm724x/gdm_endian.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef __GDM_ENDIAN_H__
-#define __GDM_ENDIAN_H__
-
-#include <linux/types.h>
-
-/*
- * For data in "device-endian" byte order (device endianness is model
- * dependent). Analogous to __leXX or __beXX.
- */
-typedef __u32 __bitwise __dev32;
-typedef __u16 __bitwise __dev16;
-
-enum {
- ENDIANNESS_MIN = 0,
- ENDIANNESS_UNKNOWN,
- ENDIANNESS_LITTLE,
- ENDIANNESS_BIG,
- ENDIANNESS_MIDDLE,
- ENDIANNESS_MAX
-};
-
-__dev16 gdm_cpu_to_dev16(u8 dev_ed, u16 x);
-u16 gdm_dev16_to_cpu(u8 dev_ed, __dev16 x);
-__dev32 gdm_cpu_to_dev32(u8 dev_ed, u32 x);
-u32 gdm_dev32_to_cpu(u8 dev_ed, __dev32 x);
-
-#endif /*__GDM_ENDIAN_H__*/
diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c
deleted file mode 100644
index eb754b231429..000000000000
--- a/drivers/staging/gdm724x/gdm_lte.c
+++ /dev/null
@@ -1,937 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/etherdevice.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/udp.h>
-#include <linux/in.h>
-#include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-#include <linux/in6.h>
-#include <linux/tcp.h>
-#include <linux/icmp.h>
-#include <linux/icmpv6.h>
-#include <linux/uaccess.h>
-#include <linux/errno.h>
-#include <net/ndisc.h>
-
-#include "gdm_lte.h"
-#include "netlink_k.h"
-#include "hci.h"
-#include "hci_packet.h"
-#include "gdm_endian.h"
-
-/*
- * Netlink protocol number
- */
-#define NETLINK_LTE 30
-
-/*
- * Default MTU Size
- */
-#define DEFAULT_MTU_SIZE 1500
-
-#define IP_VERSION_4 4
-#define IP_VERSION_6 6
-
-static struct {
- int ref_cnt;
- struct sock *sock;
-} lte_event;
-
-static const struct device_type wwan_type = {
- .name = "wwan",
-};
-
-static int gdm_lte_open(struct net_device *dev)
-{
- netif_start_queue(dev);
- return 0;
-}
-
-static int gdm_lte_close(struct net_device *dev)
-{
- netif_stop_queue(dev);
- return 0;
-}
-
-static int gdm_lte_set_config(struct net_device *dev, struct ifmap *map)
-{
- if (dev->flags & IFF_UP)
- return -EBUSY;
- return 0;
-}
-
-static void tx_complete(void *arg)
-{
- struct nic *nic = arg;
-
- if (netif_queue_stopped(nic->netdev))
- netif_wake_queue(nic->netdev);
-}
-
-static int gdm_lte_rx(struct sk_buff *skb, struct nic *nic, int nic_type)
-{
- int ret, len;
-
- len = skb->len + ETH_HLEN;
- ret = netif_rx(skb);
- if (ret == NET_RX_DROP) {
- nic->stats.rx_dropped++;
- } else {
- nic->stats.rx_packets++;
- nic->stats.rx_bytes += len;
- }
-
- return 0;
-}
-
-static int gdm_lte_emulate_arp(struct sk_buff *skb_in, u32 nic_type)
-{
- struct nic *nic = netdev_priv(skb_in->dev);
- struct sk_buff *skb_out;
- struct ethhdr eth;
- struct vlan_ethhdr vlan_eth;
- struct arphdr *arp_in;
- struct arphdr *arp_out;
- struct arpdata {
- u8 ar_sha[ETH_ALEN];
- u8 ar_sip[4];
- u8 ar_tha[ETH_ALEN];
- u8 ar_tip[4];
- };
- struct arpdata *arp_data_in;
- struct arpdata *arp_data_out;
- u8 arp_temp[60];
- void *mac_header_data;
- u32 mac_header_len;
-
- /* Check for skb->len, discard if empty */
- if (skb_in->len == 0)
- return -ENODATA;
-
- /* Format the mac header so that it can be put to skb */
- if (ntohs(((struct ethhdr *)skb_in->data)->h_proto) == ETH_P_8021Q) {
- memcpy(&vlan_eth, skb_in->data, sizeof(struct vlan_ethhdr));
- mac_header_data = &vlan_eth;
- mac_header_len = VLAN_ETH_HLEN;
- } else {
- memcpy(&eth, skb_in->data, sizeof(struct ethhdr));
- mac_header_data = &eth;
- mac_header_len = ETH_HLEN;
- }
-
- /* Get the pointer of the original request */
- arp_in = (struct arphdr *)(skb_in->data + mac_header_len);
- arp_data_in = (struct arpdata *)(skb_in->data + mac_header_len +
- sizeof(struct arphdr));
-
- /* Get the pointer of the outgoing response */
- arp_out = (struct arphdr *)arp_temp;
- arp_data_out = (struct arpdata *)(arp_temp + sizeof(struct arphdr));
-
- /* Copy the arp header */
- memcpy(arp_out, arp_in, sizeof(struct arphdr));
- arp_out->ar_op = htons(ARPOP_REPLY);
-
- /* Copy the arp payload: based on 2 bytes of mac and fill the IP */
- arp_data_out->ar_sha[0] = arp_data_in->ar_sha[0];
- arp_data_out->ar_sha[1] = arp_data_in->ar_sha[1];
- memcpy(&arp_data_out->ar_sha[2], &arp_data_in->ar_tip[0], 4);
- memcpy(&arp_data_out->ar_sip[0], &arp_data_in->ar_tip[0], 4);
- memcpy(&arp_data_out->ar_tha[0], &arp_data_in->ar_sha[0], 6);
- memcpy(&arp_data_out->ar_tip[0], &arp_data_in->ar_sip[0], 4);
-
- /* Fill the destination mac with source mac of the received packet */
- memcpy(mac_header_data, mac_header_data + ETH_ALEN, ETH_ALEN);
- /* Fill the source mac with nic's source mac */
- memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN);
-
- /* Alloc skb and reserve align */
- skb_out = dev_alloc_skb(skb_in->len);
- if (!skb_out)
- return -ENOMEM;
- skb_reserve(skb_out, NET_IP_ALIGN);
-
- skb_put_data(skb_out, mac_header_data, mac_header_len);
- skb_put_data(skb_out, arp_out, sizeof(struct arphdr));
- skb_put_data(skb_out, arp_data_out, sizeof(struct arpdata));
-
- skb_out->protocol = ((struct ethhdr *)mac_header_data)->h_proto;
- skb_out->dev = skb_in->dev;
- skb_reset_mac_header(skb_out);
- skb_pull(skb_out, ETH_HLEN);
-
- gdm_lte_rx(skb_out, nic, nic_type);
-
- return 0;
-}
-
-static __sum16 icmp6_checksum(struct ipv6hdr *ipv6, u16 *ptr, int len)
-{
- unsigned short *w;
- __wsum sum = 0;
- int i;
- u16 pa;
-
- union {
- struct {
- u8 ph_src[16];
- u8 ph_dst[16];
- u32 ph_len;
- u8 ph_zero[3];
- u8 ph_nxt;
- } ph __packed;
- u16 pa[20];
- } pseudo_header;
-
- memset(&pseudo_header, 0, sizeof(pseudo_header));
- memcpy(&pseudo_header.ph.ph_src, &ipv6->saddr.in6_u.u6_addr8, 16);
- memcpy(&pseudo_header.ph.ph_dst, &ipv6->daddr.in6_u.u6_addr8, 16);
- pseudo_header.ph.ph_len = be16_to_cpu(ipv6->payload_len);
- pseudo_header.ph.ph_nxt = ipv6->nexthdr;
-
- for (i = 0; i < ARRAY_SIZE(pseudo_header.pa); i++) {
- pa = pseudo_header.pa[i];
- sum = csum_add(sum, csum_unfold((__force __sum16)pa));
- }
-
- w = ptr;
- while (len > 1) {
- sum = csum_add(sum, csum_unfold((__force __sum16)*w++));
- len -= 2;
- }
-
- return csum_fold(sum);
-}
-
-static int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type)
-{
- struct nic *nic = netdev_priv(skb_in->dev);
- struct sk_buff *skb_out;
- struct ethhdr eth;
- struct vlan_ethhdr vlan_eth;
- struct neighbour_advertisement {
- u8 target_address[16];
- u8 type;
- u8 length;
- u8 link_layer_address[6];
- };
- struct neighbour_advertisement na;
- struct neighbour_solicitation {
- u8 target_address[16];
- };
- struct neighbour_solicitation *ns;
- struct ipv6hdr *ipv6_in;
- struct ipv6hdr ipv6_out;
- struct icmp6hdr *icmp6_in;
- struct icmp6hdr icmp6_out;
-
- void *mac_header_data;
- u32 mac_header_len;
-
- /* Format the mac header so that it can be put to skb */
- if (ntohs(((struct ethhdr *)skb_in->data)->h_proto) == ETH_P_8021Q) {
- memcpy(&vlan_eth, skb_in->data, sizeof(struct vlan_ethhdr));
- if (ntohs(vlan_eth.h_vlan_encapsulated_proto) != ETH_P_IPV6)
- return -EPROTONOSUPPORT;
- mac_header_data = &vlan_eth;
- mac_header_len = VLAN_ETH_HLEN;
- } else {
- memcpy(&eth, skb_in->data, sizeof(struct ethhdr));
- if (ntohs(eth.h_proto) != ETH_P_IPV6)
- return -EPROTONOSUPPORT;
- mac_header_data = &eth;
- mac_header_len = ETH_HLEN;
- }
-
- /* Check if this is IPv6 ICMP packet */
- ipv6_in = (struct ipv6hdr *)(skb_in->data + mac_header_len);
- if (ipv6_in->version != 6 || ipv6_in->nexthdr != IPPROTO_ICMPV6)
- return -EPROTONOSUPPORT;
-
- /* Check if this is NDP packet */
- icmp6_in = (struct icmp6hdr *)(skb_in->data + mac_header_len +
- sizeof(struct ipv6hdr));
- if (icmp6_in->icmp6_type == NDISC_ROUTER_SOLICITATION) { /* Check RS */
- return -EPROTONOSUPPORT;
- } else if (icmp6_in->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
- /* Check NS */
- u8 icmp_na[sizeof(struct icmp6hdr) +
- sizeof(struct neighbour_advertisement)];
- u8 zero_addr8[16] = {0,};
-
- if (memcmp(ipv6_in->saddr.in6_u.u6_addr8, zero_addr8, 16) == 0)
- /* Duplicate Address Detection: Source IP is all zero */
- return 0;
-
- icmp6_out.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
- icmp6_out.icmp6_code = 0;
- icmp6_out.icmp6_cksum = 0;
- /* R=0, S=1, O=1 */
- icmp6_out.icmp6_dataun.un_data32[0] = htonl(0x60000000);
-
- ns = (struct neighbour_solicitation *)
- (skb_in->data + mac_header_len +
- sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr));
- memcpy(&na.target_address, ns->target_address, 16);
- na.type = 0x02;
- na.length = 1;
- na.link_layer_address[0] = 0x00;
- na.link_layer_address[1] = 0x0a;
- na.link_layer_address[2] = 0x3b;
- na.link_layer_address[3] = 0xaf;
- na.link_layer_address[4] = 0x63;
- na.link_layer_address[5] = 0xc7;
-
- memcpy(&ipv6_out, ipv6_in, sizeof(struct ipv6hdr));
- memcpy(ipv6_out.saddr.in6_u.u6_addr8, &na.target_address, 16);
- memcpy(ipv6_out.daddr.in6_u.u6_addr8,
- ipv6_in->saddr.in6_u.u6_addr8, 16);
- ipv6_out.payload_len = htons(sizeof(struct icmp6hdr) +
- sizeof(struct neighbour_advertisement));
-
- memcpy(icmp_na, &icmp6_out, sizeof(struct icmp6hdr));
- memcpy(icmp_na + sizeof(struct icmp6hdr), &na,
- sizeof(struct neighbour_advertisement));
-
- icmp6_out.icmp6_cksum = icmp6_checksum(&ipv6_out,
- (u16 *)icmp_na,
- sizeof(icmp_na));
- } else {
- return -EINVAL;
- }
-
- /* Fill the destination mac with source mac of the received packet */
- memcpy(mac_header_data, mac_header_data + ETH_ALEN, ETH_ALEN);
- /* Fill the source mac with nic's source mac */
- memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN);
-
- /* Alloc skb and reserve align */
- skb_out = dev_alloc_skb(skb_in->len);
- if (!skb_out)
- return -ENOMEM;
- skb_reserve(skb_out, NET_IP_ALIGN);
-
- skb_put_data(skb_out, mac_header_data, mac_header_len);
- skb_put_data(skb_out, &ipv6_out, sizeof(struct ipv6hdr));
- skb_put_data(skb_out, &icmp6_out, sizeof(struct icmp6hdr));
- skb_put_data(skb_out, &na, sizeof(struct neighbour_advertisement));
-
- skb_out->protocol = ((struct ethhdr *)mac_header_data)->h_proto;
- skb_out->dev = skb_in->dev;
- skb_reset_mac_header(skb_out);
- skb_pull(skb_out, ETH_HLEN);
-
- gdm_lte_rx(skb_out, nic, nic_type);
-
- return 0;
-}
-
-static s32 gdm_lte_tx_nic_type(struct net_device *dev, struct sk_buff *skb)
-{
- struct nic *nic = netdev_priv(dev);
- struct ethhdr *eth;
- struct vlan_ethhdr *vlan_eth;
- struct iphdr *ip;
- struct ipv6hdr *ipv6;
- int mac_proto;
- void *network_data;
- u32 nic_type;
-
- /* NIC TYPE is based on the nic_id of this net_device */
- nic_type = 0x00000010 | nic->nic_id;
-
- /* Get ethernet protocol */
- eth = (struct ethhdr *)skb->data;
- if (ntohs(eth->h_proto) == ETH_P_8021Q) {
- vlan_eth = skb_vlan_eth_hdr(skb);
- mac_proto = ntohs(vlan_eth->h_vlan_encapsulated_proto);
- network_data = skb->data + VLAN_ETH_HLEN;
- nic_type |= NIC_TYPE_F_VLAN;
- } else {
- mac_proto = ntohs(eth->h_proto);
- network_data = skb->data + ETH_HLEN;
- }
-
- /* Process packet for nic type */
- switch (mac_proto) {
- case ETH_P_ARP:
- nic_type |= NIC_TYPE_ARP;
- break;
- case ETH_P_IP:
- nic_type |= NIC_TYPE_F_IPV4;
- ip = network_data;
-
- /* Check DHCPv4 */
- if (ip->protocol == IPPROTO_UDP) {
- struct udphdr *udp =
- network_data + sizeof(struct iphdr);
- if (ntohs(udp->dest) == 67 || ntohs(udp->dest) == 68)
- nic_type |= NIC_TYPE_F_DHCP;
- }
- break;
- case ETH_P_IPV6:
- nic_type |= NIC_TYPE_F_IPV6;
- ipv6 = network_data;
-
- if (ipv6->nexthdr == IPPROTO_ICMPV6) /* Check NDP request */ {
- struct icmp6hdr *icmp6 =
- network_data + sizeof(struct ipv6hdr);
- if (icmp6->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION)
- nic_type |= NIC_TYPE_ICMPV6;
- } else if (ipv6->nexthdr == IPPROTO_UDP) /* Check DHCPv6 */ {
- struct udphdr *udp =
- network_data + sizeof(struct ipv6hdr);
- if (ntohs(udp->dest) == 546 || ntohs(udp->dest) == 547)
- nic_type |= NIC_TYPE_F_DHCP;
- }
- break;
- default:
- break;
- }
-
- return nic_type;
-}
-
-static netdev_tx_t gdm_lte_tx(struct sk_buff *skb, struct net_device *dev)
-{
- struct nic *nic = netdev_priv(dev);
- u32 nic_type;
- void *data_buf;
- int data_len;
- int idx;
- int ret = 0;
-
- nic_type = gdm_lte_tx_nic_type(dev, skb);
- if (nic_type == 0) {
- netdev_err(dev, "tx - invalid nic_type\n");
- return -EMEDIUMTYPE;
- }
-
- if (nic_type & NIC_TYPE_ARP) {
- if (gdm_lte_emulate_arp(skb, nic_type) == 0) {
- dev_kfree_skb(skb);
- return 0;
- }
- }
-
- if (nic_type & NIC_TYPE_ICMPV6) {
- if (gdm_lte_emulate_ndp(skb, nic_type) == 0) {
- dev_kfree_skb(skb);
- return 0;
- }
- }
-
- /*
- * Need byte shift (that is, remove VLAN tag) if there is one
- * For the case of ARP, this breaks the offset as vlan_ethhdr+4
- * is treated as ethhdr However, it shouldn't be a problem as
- * the response starts from arp_hdr and ethhdr is created by this
- * driver based on the NIC mac
- */
- if (nic_type & NIC_TYPE_F_VLAN) {
- struct vlan_ethhdr *vlan_eth = skb_vlan_eth_hdr(skb);
-
- nic->vlan_id = ntohs(vlan_eth->h_vlan_TCI) & VLAN_VID_MASK;
- data_buf = skb->data + (VLAN_ETH_HLEN - ETH_HLEN);
- data_len = skb->len - (VLAN_ETH_HLEN - ETH_HLEN);
- } else {
- nic->vlan_id = 0;
- data_buf = skb->data;
- data_len = skb->len;
- }
-
- /* If it is a ICMPV6 packet, clear all the other bits :
- * for backward compatibility with the firmware
- */
- if (nic_type & NIC_TYPE_ICMPV6)
- nic_type = NIC_TYPE_ICMPV6;
-
- /* If it is not a dhcp packet, clear all the flag bits :
- * original NIC, otherwise the special flag (IPVX | DHCP)
- */
- if (!(nic_type & NIC_TYPE_F_DHCP))
- nic_type &= NIC_TYPE_MASK;
-
- ret = sscanf(dev->name, "lte%d", &idx);
- if (ret != 1) {
- dev_kfree_skb(skb);
- return -EINVAL;
- }
-
- ret = nic->phy_dev->send_sdu_func(nic->phy_dev->priv_dev,
- data_buf, data_len,
- nic->pdn_table.dft_eps_id, 0,
- tx_complete, nic, idx,
- nic_type);
-
- if (ret == TX_NO_BUFFER || ret == TX_NO_SPC) {
- netif_stop_queue(dev);
- if (ret == TX_NO_BUFFER)
- ret = 0;
- else
- ret = -ENOSPC;
- } else if (ret == TX_NO_DEV) {
- ret = -ENODEV;
- }
-
- /* Updates tx stats */
- if (ret) {
- nic->stats.tx_dropped++;
- } else {
- nic->stats.tx_packets++;
- nic->stats.tx_bytes += data_len;
- }
- dev_kfree_skb(skb);
-
- return 0;
-}
-
-static struct net_device_stats *gdm_lte_stats(struct net_device *dev)
-{
- struct nic *nic = netdev_priv(dev);
-
- return &nic->stats;
-}
-
-static int gdm_lte_event_send(struct net_device *dev, char *buf, int len)
-{
- struct phy_dev *phy_dev = ((struct nic *)netdev_priv(dev))->phy_dev;
- struct hci_packet *hci = (struct hci_packet *)buf;
- int length;
- int idx;
- int ret;
-
- ret = sscanf(dev->name, "lte%d", &idx);
- if (ret != 1)
- return -EINVAL;
-
- length = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev),
- hci->len) + HCI_HEADER_SIZE;
- return netlink_send(lte_event.sock, idx, 0, buf, length, dev);
-}
-
-static void gdm_lte_event_rcv(struct net_device *dev, u16 type,
- void *msg, int len)
-{
- struct nic *nic = netdev_priv(dev);
-
- nic->phy_dev->send_hci_func(nic->phy_dev->priv_dev, msg, len, NULL,
- NULL);
-}
-
-int gdm_lte_event_init(void)
-{
- if (lte_event.ref_cnt == 0)
- lte_event.sock = netlink_init(NETLINK_LTE, gdm_lte_event_rcv);
-
- if (lte_event.sock) {
- lte_event.ref_cnt++;
- return 0;
- }
-
- pr_err("event init failed\n");
- return -ENODATA;
-}
-
-void gdm_lte_event_exit(void)
-{
- if (lte_event.sock && --lte_event.ref_cnt == 0) {
- sock_release(lte_event.sock->sk_socket);
- lte_event.sock = NULL;
- }
-}
-
-static int find_dev_index(u32 nic_type)
-{
- u8 index;
-
- index = (u8)(nic_type & 0x0000000f);
- if (index >= MAX_NIC_TYPE)
- return -EINVAL;
-
- return index;
-}
-
-static void gdm_lte_netif_rx(struct net_device *dev, char *buf,
- int len, int flagged_nic_type)
-{
- u32 nic_type;
- struct nic *nic;
- struct sk_buff *skb;
- struct ethhdr eth;
- struct vlan_ethhdr vlan_eth;
- void *mac_header_data;
- u32 mac_header_len;
- char ip_version = 0;
-
- nic_type = flagged_nic_type & NIC_TYPE_MASK;
- nic = netdev_priv(dev);
-
- if (flagged_nic_type & NIC_TYPE_F_DHCP) {
- /* Change the destination mac address
- * with the one requested the IP
- */
- if (flagged_nic_type & NIC_TYPE_F_IPV4) {
- struct dhcp_packet {
- u8 op; /* BOOTREQUEST or BOOTREPLY */
- u8 htype; /* hardware address type.
- * 1 = 10mb ethernet
- */
- u8 hlen; /* hardware address length */
- u8 hops; /* used by relay agents only */
- u32 xid; /* unique id */
- u16 secs; /* elapsed since client began
- * acquisition/renewal
- */
- u16 flags; /* only one flag so far: */
- #define BROADCAST_FLAG 0x8000
- /* "I need broadcast replies" */
- u32 ciaddr; /* client IP (if client is in
- * BOUND, RENEW or REBINDING state)
- */
- u32 yiaddr; /* 'your' (client) IP address */
- /* IP address of next server to use in
- * bootstrap, returned in DHCPOFFER,
- * DHCPACK by server
- */
- u32 siaddr_nip;
- u32 gateway_nip; /* relay agent IP address */
- u8 chaddr[16]; /* link-layer client hardware
- * address (MAC)
- */
- u8 sname[64]; /* server host name (ASCIZ) */
- u8 file[128]; /* boot file name (ASCIZ) */
- u32 cookie; /* fixed first four option
- * bytes (99,130,83,99 dec)
- */
- } __packed;
- int offset = sizeof(struct iphdr) +
- sizeof(struct udphdr) +
- offsetof(struct dhcp_packet, chaddr);
- if (offset + ETH_ALEN > len)
- return;
- ether_addr_copy(nic->dest_mac_addr, buf + offset);
- }
- }
-
- if (nic->vlan_id > 0) {
- mac_header_data = (void *)&vlan_eth;
- mac_header_len = VLAN_ETH_HLEN;
- } else {
- mac_header_data = (void *)&eth;
- mac_header_len = ETH_HLEN;
- }
-
- /* Format the data so that it can be put to skb */
- ether_addr_copy(mac_header_data, nic->dest_mac_addr);
- memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN);
-
- vlan_eth.h_vlan_TCI = htons(nic->vlan_id);
- vlan_eth.h_vlan_proto = htons(ETH_P_8021Q);
-
- if (nic_type == NIC_TYPE_ARP) {
- /* Should be response: Only happens because
- * there was a request from the host
- */
- eth.h_proto = htons(ETH_P_ARP);
- vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_ARP);
- } else {
- ip_version = buf[0] >> 4;
- if (ip_version == IP_VERSION_4) {
- eth.h_proto = htons(ETH_P_IP);
- vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_IP);
- } else if (ip_version == IP_VERSION_6) {
- eth.h_proto = htons(ETH_P_IPV6);
- vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_IPV6);
- } else {
- netdev_err(dev, "Unknown IP version %d\n", ip_version);
- return;
- }
- }
-
- /* Alloc skb and reserve align */
- skb = dev_alloc_skb(len + mac_header_len + NET_IP_ALIGN);
- if (!skb)
- return;
- skb_reserve(skb, NET_IP_ALIGN);
-
- skb_put_data(skb, mac_header_data, mac_header_len);
- skb_put_data(skb, buf, len);
-
- skb->protocol = ((struct ethhdr *)mac_header_data)->h_proto;
- skb->dev = dev;
- skb_reset_mac_header(skb);
- skb_pull(skb, ETH_HLEN);
-
- gdm_lte_rx(skb, nic, nic_type);
-}
-
-static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len)
-{
- struct net_device *dev;
- struct multi_sdu *multi_sdu = (struct multi_sdu *)buf;
- struct sdu *sdu = NULL;
- u8 endian = phy_dev->get_endian(phy_dev->priv_dev);
- u8 *data = (u8 *)multi_sdu->data;
- int copied;
- u16 i = 0;
- u16 num_packet;
- u16 hci_len;
- u16 cmd_evt;
- u32 nic_type;
- int index;
-
- num_packet = gdm_dev16_to_cpu(endian, multi_sdu->num_packet);
-
- for (i = 0; i < num_packet; i++) {
- copied = data - multi_sdu->data;
- if (len < copied + sizeof(*sdu)) {
- pr_err("rx prevent buffer overflow");
- return;
- }
-
- sdu = (struct sdu *)data;
-
- cmd_evt = gdm_dev16_to_cpu(endian, sdu->cmd_evt);
- hci_len = gdm_dev16_to_cpu(endian, sdu->len);
- nic_type = gdm_dev32_to_cpu(endian, sdu->nic_type);
-
- if (cmd_evt != LTE_RX_SDU) {
- pr_err("rx sdu wrong hci %04x\n", cmd_evt);
- return;
- }
- if (hci_len < 12 ||
- len < copied + sizeof(*sdu) + (hci_len - 12)) {
- pr_err("rx sdu invalid len %d\n", hci_len);
- return;
- }
-
- index = find_dev_index(nic_type);
- if (index < 0) {
- pr_err("rx sdu invalid nic_type :%x\n", nic_type);
- return;
- }
- dev = phy_dev->dev[index];
- gdm_lte_netif_rx(dev, (char *)sdu->data,
- (int)(hci_len - 12), nic_type);
-
- data += ((hci_len + 3) & 0xfffc) + HCI_HEADER_SIZE;
- }
-}
-
-static void gdm_lte_pdn_table(struct net_device *dev, char *buf, int len)
-{
- struct nic *nic = netdev_priv(dev);
- struct hci_pdn_table_ind *pdn_table = (struct hci_pdn_table_ind *)buf;
- u8 ed = nic->phy_dev->get_endian(nic->phy_dev->priv_dev);
-
- if (!pdn_table->activate) {
- memset(&nic->pdn_table, 0x00, sizeof(struct pdn_table));
- netdev_info(dev, "pdn deactivated\n");
-
- return;
- }
-
- nic->pdn_table.activate = pdn_table->activate;
- nic->pdn_table.dft_eps_id = gdm_dev32_to_cpu(ed, pdn_table->dft_eps_id);
- nic->pdn_table.nic_type = gdm_dev32_to_cpu(ed, pdn_table->nic_type);
-
- netdev_info(dev, "pdn activated, nic_type=0x%x\n",
- nic->pdn_table.nic_type);
-}
-
-static int gdm_lte_receive_pkt(struct phy_dev *phy_dev, char *buf, int len)
-{
- struct hci_packet *hci = (struct hci_packet *)buf;
- struct hci_pdn_table_ind *pdn_table = (struct hci_pdn_table_ind *)buf;
- struct sdu *sdu;
- struct net_device *dev;
- u8 endian = phy_dev->get_endian(phy_dev->priv_dev);
- int ret = 0;
- u16 cmd_evt;
- u32 nic_type;
- int index;
-
- if (!len)
- return ret;
-
- cmd_evt = gdm_dev16_to_cpu(endian, hci->cmd_evt);
-
- dev = phy_dev->dev[0];
- if (!dev)
- return 0;
-
- switch (cmd_evt) {
- case LTE_RX_SDU:
- sdu = (struct sdu *)hci->data;
- nic_type = gdm_dev32_to_cpu(endian, sdu->nic_type);
- index = find_dev_index(nic_type);
- if (index < 0)
- return index;
- dev = phy_dev->dev[index];
- gdm_lte_netif_rx(dev, hci->data, len, nic_type);
- break;
- case LTE_RX_MULTI_SDU:
- gdm_lte_multi_sdu_pkt(phy_dev, buf, len);
- break;
- case LTE_LINK_ON_OFF_INDICATION:
- netdev_info(dev, "link %s\n",
- ((struct hci_connect_ind *)buf)->connect
- ? "on" : "off");
- break;
- case LTE_PDN_TABLE_IND:
- pdn_table = (struct hci_pdn_table_ind *)buf;
- nic_type = gdm_dev32_to_cpu(endian, pdn_table->nic_type);
- index = find_dev_index(nic_type);
- if (index < 0)
- return index;
- dev = phy_dev->dev[index];
- gdm_lte_pdn_table(dev, buf, len);
- fallthrough;
- default:
- ret = gdm_lte_event_send(dev, buf, len);
- break;
- }
-
- return ret;
-}
-
-static int rx_complete(void *arg, void *data, int len, int context)
-{
- struct phy_dev *phy_dev = arg;
-
- return gdm_lte_receive_pkt(phy_dev, data, len);
-}
-
-void start_rx_proc(struct phy_dev *phy_dev)
-{
- int i;
-
- for (i = 0; i < MAX_RX_SUBMIT_COUNT; i++)
- phy_dev->rcv_func(phy_dev->priv_dev,
- rx_complete, phy_dev, USB_COMPLETE);
-}
-
-static const struct net_device_ops gdm_netdev_ops = {
- .ndo_open = gdm_lte_open,
- .ndo_stop = gdm_lte_close,
- .ndo_set_config = gdm_lte_set_config,
- .ndo_start_xmit = gdm_lte_tx,
- .ndo_get_stats = gdm_lte_stats,
-};
-
-static u8 gdm_lte_macaddr[ETH_ALEN] = {0x00, 0x0a, 0x3b, 0x00, 0x00, 0x00};
-
-static void form_mac_address(u8 *dev_addr, u8 *nic_src, u8 *nic_dest,
- u8 *mac_address, u8 index)
-{
- /* Form the dev_addr */
- if (!mac_address)
- ether_addr_copy(dev_addr, gdm_lte_macaddr);
- else
- ether_addr_copy(dev_addr, mac_address);
-
- /* The last byte of the mac address
- * should be less than or equal to 0xFC
- */
- dev_addr[ETH_ALEN - 1] += index;
-
- /* Create random nic src and copy the first
- * 3 bytes to be the same as dev_addr
- */
- eth_random_addr(nic_src);
- memcpy(nic_src, dev_addr, 3);
-
- /* Copy the nic_dest from dev_addr*/
- ether_addr_copy(nic_dest, dev_addr);
-}
-
-static void validate_mac_address(u8 *mac_address)
-{
- /* if zero address or multicast bit set, restore the default value */
- if (is_zero_ether_addr(mac_address) || (mac_address[0] & 0x01)) {
- pr_err("MAC invalid, restoring default\n");
- memcpy(mac_address, gdm_lte_macaddr, 6);
- }
-}
-
-int register_lte_device(struct phy_dev *phy_dev,
- struct device *dev, u8 *mac_address)
-{
- struct nic *nic;
- struct net_device *net;
- char pdn_dev_name[16];
- u8 addr[ETH_ALEN];
- int ret = 0;
- u8 index;
-
- validate_mac_address(mac_address);
-
- for (index = 0; index < MAX_NIC_TYPE; index++) {
- /* Create device name lteXpdnX */
- sprintf(pdn_dev_name, "lte%%dpdn%d", index);
-
- /* Allocate netdev */
- net = alloc_netdev(sizeof(struct nic), pdn_dev_name,
- NET_NAME_UNKNOWN, ether_setup);
- if (!net) {
- ret = -ENOMEM;
- goto err;
- }
- net->netdev_ops = &gdm_netdev_ops;
- net->flags &= ~IFF_MULTICAST;
- net->mtu = DEFAULT_MTU_SIZE;
-
- nic = netdev_priv(net);
- memset(nic, 0, sizeof(struct nic));
- nic->netdev = net;
- nic->phy_dev = phy_dev;
- nic->nic_id = index;
-
- form_mac_address(addr,
- nic->src_mac_addr,
- nic->dest_mac_addr,
- mac_address,
- index);
- eth_hw_addr_set(net, addr);
-
- SET_NETDEV_DEV(net, dev);
- SET_NETDEV_DEVTYPE(net, &wwan_type);
-
- ret = register_netdev(net);
- if (ret)
- goto err;
-
- netif_carrier_on(net);
-
- phy_dev->dev[index] = net;
- }
-
- return 0;
-
-err:
- unregister_lte_device(phy_dev);
-
- return ret;
-}
-
-void unregister_lte_device(struct phy_dev *phy_dev)
-{
- struct net_device *net;
- int index;
-
- for (index = 0; index < MAX_NIC_TYPE; index++) {
- net = phy_dev->dev[index];
- if (!net)
- continue;
-
- unregister_netdev(net);
- free_netdev(net);
- }
-}
diff --git a/drivers/staging/gdm724x/gdm_lte.h b/drivers/staging/gdm724x/gdm_lte.h
deleted file mode 100644
index f2143a6e0e99..000000000000
--- a/drivers/staging/gdm724x/gdm_lte.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _GDM_LTE_H_
-#define _GDM_LTE_H_
-
-#include <linux/netdevice.h>
-#include <linux/types.h>
-
-#include "gdm_endian.h"
-
-#define MAX_NIC_TYPE 4
-#define MAX_RX_SUBMIT_COUNT 3
-#define DRIVER_VERSION "3.7.17.0"
-
-enum TX_ERROR_CODE {
- TX_NO_ERROR = 0,
- TX_NO_DEV,
- TX_NO_SPC,
- TX_NO_BUFFER,
-};
-
-enum CALLBACK_CONTEXT {
- KERNEL_THREAD = 0,
- USB_COMPLETE,
-};
-
-struct pdn_table {
- u8 activate;
- u32 dft_eps_id;
- u32 nic_type;
-} __packed;
-
-struct nic;
-
-struct phy_dev {
- void *priv_dev;
- struct net_device *dev[MAX_NIC_TYPE];
- int (*send_hci_func)(void *priv_dev, void *data, int len,
- void (*cb)(void *cb_data), void *cb_data);
- int (*send_sdu_func)(void *priv_dev, void *data, int len,
- unsigned int dft_eps_id, unsigned int eps_id,
- void (*cb)(void *cb_data), void *cb_data,
- int dev_idx, int nic_type);
- int (*rcv_func)(void *priv_dev,
- int (*cb)(void *cb_data, void *data, int len,
- int context),
- void *cb_data, int context);
- u8 (*get_endian)(void *priv_dev);
-};
-
-struct nic {
- struct net_device *netdev;
- struct phy_dev *phy_dev;
- struct net_device_stats stats;
- struct pdn_table pdn_table;
- u8 dest_mac_addr[ETH_ALEN];
- u8 src_mac_addr[ETH_ALEN];
- u32 nic_id;
- u16 vlan_id;
-};
-
-int gdm_lte_event_init(void);
-void gdm_lte_event_exit(void);
-
-void start_rx_proc(struct phy_dev *phy_dev);
-int register_lte_device(struct phy_dev *phy_dev, struct device *dev,
- u8 *mac_address);
-void unregister_lte_device(struct phy_dev *phy_dev);
-
-#endif /* _GDM_LTE_H_ */
diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c
deleted file mode 100644
index 9b12619671a1..000000000000
--- a/drivers/staging/gdm724x/gdm_mux.c
+++ /dev/null
@@ -1,668 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/slab.h>
-#include <linux/usb/cdc.h>
-
-#include "gdm_mux.h"
-
-static u16 packet_type_for_tty_index[TTY_MAX_COUNT] = {0xF011, 0xF010};
-
-#define USB_DEVICE_CDC_DATA(vid, pid) \
- .match_flags = \
- USB_DEVICE_ID_MATCH_DEVICE |\
- USB_DEVICE_ID_MATCH_INT_CLASS |\
- USB_DEVICE_ID_MATCH_INT_SUBCLASS,\
- .idVendor = vid,\
- .idProduct = pid,\
- .bInterfaceClass = USB_CLASS_COMM,\
- .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM
-
-static const struct usb_device_id id_table[] = {
- { USB_DEVICE_CDC_DATA(0x1076, 0x8000) }, /* GCT GDM7240 */
- { USB_DEVICE_CDC_DATA(0x1076, 0x8f00) }, /* GCT GDM7243 */
- { USB_DEVICE_CDC_DATA(0x1076, 0x9000) }, /* GCT GDM7243 */
- { USB_DEVICE_CDC_DATA(0x1d74, 0x2300) }, /* LGIT Phoenix */
- {}
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static int packet_type_to_tty_index(u16 packet_type)
-{
- int i;
-
- for (i = 0; i < TTY_MAX_COUNT; i++) {
- if (packet_type_for_tty_index[i] == packet_type)
- return i;
- }
-
- return -1;
-}
-
-static struct mux_tx *alloc_mux_tx(int len)
-{
- struct mux_tx *t;
-
- t = kzalloc(sizeof(*t), GFP_ATOMIC);
- if (!t)
- return NULL;
-
- t->urb = usb_alloc_urb(0, GFP_ATOMIC);
- t->buf = kmalloc(MUX_TX_MAX_SIZE, GFP_ATOMIC);
- if (!t->urb || !t->buf) {
- usb_free_urb(t->urb);
- kfree(t->buf);
- kfree(t);
- return NULL;
- }
-
- return t;
-}
-
-static void free_mux_tx(struct mux_tx *t)
-{
- if (t) {
- usb_free_urb(t->urb);
- kfree(t->buf);
- kfree(t);
- }
-}
-
-static struct mux_rx *alloc_mux_rx(void)
-{
- struct mux_rx *r;
-
- r = kzalloc(sizeof(*r), GFP_KERNEL);
- if (!r)
- return NULL;
-
- r->urb = usb_alloc_urb(0, GFP_KERNEL);
- r->buf = kmalloc(MUX_RX_MAX_SIZE, GFP_KERNEL);
- if (!r->urb || !r->buf) {
- usb_free_urb(r->urb);
- kfree(r->buf);
- kfree(r);
- return NULL;
- }
-
- return r;
-}
-
-static void free_mux_rx(struct mux_rx *r)
-{
- if (r) {
- usb_free_urb(r->urb);
- kfree(r->buf);
- kfree(r);
- }
-}
-
-static struct mux_rx *get_rx_struct(struct rx_cxt *rx)
-{
- struct mux_rx *r;
- unsigned long flags;
-
- spin_lock_irqsave(&rx->free_list_lock, flags);
-
- if (list_empty(&rx->rx_free_list)) {
- spin_unlock_irqrestore(&rx->free_list_lock, flags);
- return NULL;
- }
-
- r = list_entry(rx->rx_free_list.prev, struct mux_rx, free_list);
- list_del(&r->free_list);
-
- spin_unlock_irqrestore(&rx->free_list_lock, flags);
-
- return r;
-}
-
-static void put_rx_struct(struct rx_cxt *rx, struct mux_rx *r)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&rx->free_list_lock, flags);
- list_add_tail(&r->free_list, &rx->rx_free_list);
- spin_unlock_irqrestore(&rx->free_list_lock, flags);
-}
-
-static int up_to_host(struct mux_rx *r)
-{
- struct mux_dev *mux_dev = r->mux_dev;
- struct mux_pkt_header *mux_header;
- unsigned int start_flag;
- unsigned int payload_size;
- unsigned short packet_type;
- int total_len;
- u32 packet_size_sum = r->offset;
- int index;
- int ret = TO_HOST_INVALID_PACKET;
- int len = r->len;
-
- while (1) {
- mux_header = (struct mux_pkt_header *)(r->buf +
- packet_size_sum);
- start_flag = __le32_to_cpu(mux_header->start_flag);
- payload_size = __le32_to_cpu(mux_header->payload_size);
- packet_type = __le16_to_cpu(mux_header->packet_type);
-
- if (start_flag != START_FLAG) {
- pr_err("invalid START_FLAG %x\n", start_flag);
- break;
- }
-
- total_len = ALIGN(MUX_HEADER_SIZE + payload_size, 4);
-
- if (len - packet_size_sum < total_len) {
- pr_err("invalid payload : %d %d %04x\n",
- payload_size, len, packet_type);
- break;
- }
-
- index = packet_type_to_tty_index(packet_type);
- if (index < 0) {
- pr_err("invalid index %d\n", index);
- break;
- }
-
- ret = r->callback(mux_header->data,
- payload_size,
- index,
- mux_dev->tty_dev,
- RECV_PACKET_PROCESS_CONTINUE
- );
- if (ret == TO_HOST_BUFFER_REQUEST_FAIL) {
- r->offset += packet_size_sum;
- break;
- }
-
- packet_size_sum += total_len;
- if (len - packet_size_sum <= MUX_HEADER_SIZE + 2) {
- ret = r->callback(NULL,
- 0,
- index,
- mux_dev->tty_dev,
- RECV_PACKET_PROCESS_COMPLETE
- );
- break;
- }
- }
-
- return ret;
-}
-
-static void do_rx(struct work_struct *work)
-{
- struct mux_dev *mux_dev =
- container_of(work, struct mux_dev, work_rx.work);
- struct mux_rx *r;
- struct rx_cxt *rx = &mux_dev->rx;
- unsigned long flags;
- int ret = 0;
-
- while (1) {
- spin_lock_irqsave(&rx->to_host_lock, flags);
- if (list_empty(&rx->to_host_list)) {
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
- break;
- }
- r = list_entry(rx->to_host_list.next, struct mux_rx,
- to_host_list);
- list_del(&r->to_host_list);
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
-
- ret = up_to_host(r);
- if (ret == TO_HOST_BUFFER_REQUEST_FAIL)
- pr_err("failed to send mux data to host\n");
- else
- put_rx_struct(rx, r);
- }
-}
-
-static void remove_rx_submit_list(struct mux_rx *r, struct rx_cxt *rx)
-{
- unsigned long flags;
- struct mux_rx *r_remove, *r_remove_next;
-
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- list_for_each_entry_safe(r_remove, r_remove_next, &rx->rx_submit_list,
- rx_submit_list) {
- if (r == r_remove)
- list_del(&r->rx_submit_list);
- }
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
-}
-
-static void gdm_mux_rcv_complete(struct urb *urb)
-{
- struct mux_rx *r = urb->context;
- struct mux_dev *mux_dev = r->mux_dev;
- struct rx_cxt *rx = &mux_dev->rx;
- unsigned long flags;
-
- remove_rx_submit_list(r, rx);
-
- if (urb->status) {
- if (mux_dev->usb_state == PM_NORMAL)
- dev_err(&urb->dev->dev, "%s: urb status error %d\n",
- __func__, urb->status);
- put_rx_struct(rx, r);
- } else {
- r->len = r->urb->actual_length;
- spin_lock_irqsave(&rx->to_host_lock, flags);
- list_add_tail(&r->to_host_list, &rx->to_host_list);
- schedule_work(&mux_dev->work_rx.work);
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
- }
-}
-
-static int gdm_mux_recv(void *priv_dev,
- int (*cb)(void *data, int len, int tty_index,
- struct tty_dev *tty_dev, int complete))
-{
- struct mux_dev *mux_dev = priv_dev;
- struct usb_device *usbdev = mux_dev->usbdev;
- struct mux_rx *r;
- struct rx_cxt *rx = &mux_dev->rx;
- unsigned long flags;
- int ret;
-
- if (!usbdev) {
- pr_err("device is disconnected\n");
- return -ENODEV;
- }
-
- r = get_rx_struct(rx);
- if (!r) {
- pr_err("get_rx_struct fail\n");
- return -ENOMEM;
- }
-
- r->offset = 0;
- r->mux_dev = (void *)mux_dev;
- r->callback = cb;
- mux_dev->rx_cb = cb;
-
- usb_fill_bulk_urb(r->urb,
- usbdev,
- usb_rcvbulkpipe(usbdev, 0x86),
- r->buf,
- MUX_RX_MAX_SIZE,
- gdm_mux_rcv_complete,
- r);
-
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- list_add_tail(&r->rx_submit_list, &rx->rx_submit_list);
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
-
- ret = usb_submit_urb(r->urb, GFP_KERNEL);
-
- if (ret) {
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- list_del(&r->rx_submit_list);
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
-
- put_rx_struct(rx, r);
-
- pr_err("usb_submit_urb ret=%d\n", ret);
- }
-
- usb_mark_last_busy(usbdev);
-
- return ret;
-}
-
-static void gdm_mux_send_complete(struct urb *urb)
-{
- struct mux_tx *t = urb->context;
-
- if (urb->status == -ECONNRESET) {
- dev_info(&urb->dev->dev, "CONNRESET\n");
- free_mux_tx(t);
- return;
- }
-
- if (t->callback)
- t->callback(t->cb_data);
-
- free_mux_tx(t);
-}
-
-static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index,
- void (*cb)(void *data), void *cb_data)
-{
- struct mux_dev *mux_dev = priv_dev;
- struct usb_device *usbdev = mux_dev->usbdev;
- struct mux_pkt_header *mux_header;
- struct mux_tx *t = NULL;
- static u32 seq_num = 1;
- int total_len;
- int ret;
- unsigned long flags;
-
- if (mux_dev->usb_state == PM_SUSPEND) {
- ret = usb_autopm_get_interface(mux_dev->intf);
- if (!ret)
- usb_autopm_put_interface(mux_dev->intf);
- }
-
- spin_lock_irqsave(&mux_dev->write_lock, flags);
-
- total_len = ALIGN(MUX_HEADER_SIZE + len, 4);
-
- t = alloc_mux_tx(total_len);
- if (!t) {
- pr_err("alloc_mux_tx fail\n");
- spin_unlock_irqrestore(&mux_dev->write_lock, flags);
- return -ENOMEM;
- }
-
- mux_header = (struct mux_pkt_header *)t->buf;
- mux_header->start_flag = __cpu_to_le32(START_FLAG);
- mux_header->seq_num = __cpu_to_le32(seq_num++);
- mux_header->payload_size = __cpu_to_le32((u32)len);
- mux_header->packet_type = __cpu_to_le16(packet_type_for_tty_index[tty_index]);
-
- memcpy(t->buf + MUX_HEADER_SIZE, data, len);
- memset(t->buf + MUX_HEADER_SIZE + len, 0,
- total_len - MUX_HEADER_SIZE - len);
-
- t->len = total_len;
- t->callback = cb;
- t->cb_data = cb_data;
-
- usb_fill_bulk_urb(t->urb,
- usbdev,
- usb_sndbulkpipe(usbdev, 5),
- t->buf,
- total_len,
- gdm_mux_send_complete,
- t);
-
- ret = usb_submit_urb(t->urb, GFP_ATOMIC);
-
- spin_unlock_irqrestore(&mux_dev->write_lock, flags);
-
- if (ret)
- pr_err("usb_submit_urb Error: %d\n", ret);
-
- usb_mark_last_busy(usbdev);
-
- return ret;
-}
-
-static int gdm_mux_send_control(void *priv_dev, int request, int value,
- void *buf, int len)
-{
- struct mux_dev *mux_dev = priv_dev;
- struct usb_device *usbdev = mux_dev->usbdev;
- int ret;
-
- ret = usb_control_msg(usbdev,
- usb_sndctrlpipe(usbdev, 0),
- request,
- USB_RT_ACM,
- value,
- 2,
- buf,
- len,
- 5000
- );
-
- if (ret < 0)
- pr_err("usb_control_msg error: %d\n", ret);
-
- return min(ret, 0);
-}
-
-static void release_usb(struct mux_dev *mux_dev)
-{
- struct rx_cxt *rx = &mux_dev->rx;
- struct mux_rx *r, *r_next;
- unsigned long flags;
-
- cancel_delayed_work(&mux_dev->work_rx);
-
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
- rx_submit_list) {
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
- usb_kill_urb(r->urb);
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- }
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
-
- spin_lock_irqsave(&rx->free_list_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->rx_free_list, free_list) {
- list_del(&r->free_list);
- free_mux_rx(r);
- }
- spin_unlock_irqrestore(&rx->free_list_lock, flags);
-
- spin_lock_irqsave(&rx->to_host_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list) {
- if (r->mux_dev == (void *)mux_dev) {
- list_del(&r->to_host_list);
- free_mux_rx(r);
- }
- }
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
-}
-
-static int init_usb(struct mux_dev *mux_dev)
-{
- struct mux_rx *r;
- struct rx_cxt *rx = &mux_dev->rx;
- int ret = 0;
- int i;
-
- spin_lock_init(&mux_dev->write_lock);
- INIT_LIST_HEAD(&rx->to_host_list);
- INIT_LIST_HEAD(&rx->rx_submit_list);
- INIT_LIST_HEAD(&rx->rx_free_list);
- spin_lock_init(&rx->to_host_lock);
- spin_lock_init(&rx->submit_list_lock);
- spin_lock_init(&rx->free_list_lock);
-
- for (i = 0; i < MAX_ISSUE_NUM * 2; i++) {
- r = alloc_mux_rx();
- if (!r) {
- ret = -ENOMEM;
- break;
- }
-
- list_add(&r->free_list, &rx->rx_free_list);
- }
-
- INIT_DELAYED_WORK(&mux_dev->work_rx, do_rx);
-
- return ret;
-}
-
-static int gdm_mux_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct mux_dev *mux_dev;
- struct tty_dev *tty_dev;
- u16 idVendor, idProduct;
- int bInterfaceNumber;
- int ret;
- int i;
- struct usb_device *usbdev = interface_to_usbdev(intf);
-
- bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber;
-
- idVendor = __le16_to_cpu(usbdev->descriptor.idVendor);
- idProduct = __le16_to_cpu(usbdev->descriptor.idProduct);
-
- pr_info("mux vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct);
-
- if (bInterfaceNumber != 2)
- return -ENODEV;
-
- mux_dev = kzalloc(sizeof(*mux_dev), GFP_KERNEL);
- if (!mux_dev)
- return -ENOMEM;
-
- tty_dev = kzalloc(sizeof(*tty_dev), GFP_KERNEL);
- if (!tty_dev) {
- ret = -ENOMEM;
- goto err_free_mux;
- }
-
- mux_dev->usbdev = usbdev;
- mux_dev->control_intf = intf;
-
- ret = init_usb(mux_dev);
- if (ret)
- goto err_free_usb;
-
- tty_dev->priv_dev = (void *)mux_dev;
- tty_dev->send_func = gdm_mux_send;
- tty_dev->recv_func = gdm_mux_recv;
- tty_dev->send_control = gdm_mux_send_control;
-
- ret = register_lte_tty_device(tty_dev, &intf->dev);
- if (ret)
- goto err_unregister_tty;
-
- for (i = 0; i < TTY_MAX_COUNT; i++)
- mux_dev->tty_dev = tty_dev;
-
- mux_dev->intf = intf;
- mux_dev->usb_state = PM_NORMAL;
-
- usb_get_dev(usbdev);
- usb_set_intfdata(intf, tty_dev);
-
- return 0;
-
-err_unregister_tty:
- unregister_lte_tty_device(tty_dev);
-err_free_usb:
- release_usb(mux_dev);
- kfree(tty_dev);
-err_free_mux:
- kfree(mux_dev);
-
- return ret;
-}
-
-static void gdm_mux_disconnect(struct usb_interface *intf)
-{
- struct tty_dev *tty_dev;
- struct mux_dev *mux_dev;
- struct usb_device *usbdev = interface_to_usbdev(intf);
-
- tty_dev = usb_get_intfdata(intf);
-
- mux_dev = tty_dev->priv_dev;
-
- release_usb(mux_dev);
- unregister_lte_tty_device(tty_dev);
-
- kfree(mux_dev);
- kfree(tty_dev);
-
- usb_put_dev(usbdev);
-}
-
-static int gdm_mux_suspend(struct usb_interface *intf, pm_message_t pm_msg)
-{
- struct tty_dev *tty_dev;
- struct mux_dev *mux_dev;
- struct rx_cxt *rx;
- struct mux_rx *r, *r_next;
- unsigned long flags;
-
- tty_dev = usb_get_intfdata(intf);
- mux_dev = tty_dev->priv_dev;
- rx = &mux_dev->rx;
-
- cancel_work_sync(&mux_dev->work_rx.work);
-
- if (mux_dev->usb_state != PM_NORMAL) {
- dev_err(intf->usb_dev, "usb suspend - invalid state\n");
- return -1;
- }
-
- mux_dev->usb_state = PM_SUSPEND;
-
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
- rx_submit_list) {
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
- usb_kill_urb(r->urb);
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- }
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
-
- return 0;
-}
-
-static int gdm_mux_resume(struct usb_interface *intf)
-{
- struct tty_dev *tty_dev;
- struct mux_dev *mux_dev;
- u8 i;
-
- tty_dev = usb_get_intfdata(intf);
- mux_dev = tty_dev->priv_dev;
-
- if (mux_dev->usb_state != PM_SUSPEND) {
- dev_err(intf->usb_dev, "usb resume - invalid state\n");
- return -1;
- }
-
- mux_dev->usb_state = PM_NORMAL;
-
- for (i = 0; i < MAX_ISSUE_NUM; i++)
- gdm_mux_recv(mux_dev, mux_dev->rx_cb);
-
- return 0;
-}
-
-static struct usb_driver gdm_mux_driver = {
- .name = "gdm_mux",
- .probe = gdm_mux_probe,
- .disconnect = gdm_mux_disconnect,
- .id_table = id_table,
- .supports_autosuspend = 1,
- .suspend = gdm_mux_suspend,
- .resume = gdm_mux_resume,
- .reset_resume = gdm_mux_resume,
-};
-
-static int __init gdm_usb_mux_init(void)
-{
- int ret;
-
- ret = register_lte_tty_driver();
- if (ret)
- return ret;
-
- return usb_register(&gdm_mux_driver);
-}
-
-static void __exit gdm_usb_mux_exit(void)
-{
- usb_deregister(&gdm_mux_driver);
- unregister_lte_tty_driver();
-}
-
-module_init(gdm_usb_mux_init);
-module_exit(gdm_usb_mux_exit);
-
-MODULE_DESCRIPTION("GCT LTE TTY Device Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gdm724x/gdm_mux.h b/drivers/staging/gdm724x/gdm_mux.h
deleted file mode 100644
index 87b8d921fdc8..000000000000
--- a/drivers/staging/gdm724x/gdm_mux.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _GDM_MUX_H_
-#define _GDM_MUX_H_
-
-#include <linux/types.h>
-#include <linux/usb.h>
-#include <linux/list.h>
-
-#include "gdm_tty.h"
-
-#define PM_NORMAL 0
-#define PM_SUSPEND 1
-
-#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
-
-#define START_FLAG 0xA512485A
-#define MUX_HEADER_SIZE 14
-#define MUX_TX_MAX_SIZE (1024 * 10)
-#define MUX_RX_MAX_SIZE (1024 * 30)
-#define AT_PKT_TYPE 0xF011
-#define DM_PKT_TYPE 0xF010
-
-#define RETRY_TIMER 30 /* msec */
-
-struct mux_pkt_header {
- __le32 start_flag;
- __le32 seq_num;
- __le32 payload_size;
- __le16 packet_type;
- unsigned char data[];
-};
-
-struct mux_tx {
- struct urb *urb;
- u8 *buf;
- int len;
- void (*callback)(void *cb_data);
- void *cb_data;
-};
-
-struct mux_rx {
- struct list_head free_list;
- struct list_head rx_submit_list;
- struct list_head to_host_list;
- struct urb *urb;
- u8 *buf;
- void *mux_dev;
- u32 offset;
- u32 len;
- int (*callback)(void *data,
- int len,
- int tty_index,
- struct tty_dev *tty_dev,
- int complete);
-};
-
-struct rx_cxt {
- struct list_head to_host_list;
- struct list_head rx_submit_list;
- struct list_head rx_free_list;
- spinlock_t to_host_lock;
- spinlock_t submit_list_lock;
- spinlock_t free_list_lock;
-};
-
-struct mux_dev {
- struct usb_device *usbdev;
- struct usb_interface *control_intf;
- struct usb_interface *data_intf;
- struct rx_cxt rx;
- struct delayed_work work_rx;
- struct usb_interface *intf;
- int usb_state;
- int (*rx_cb)(void *data,
- int len,
- int tty_index,
- struct tty_dev *tty_dev,
- int complete);
- spinlock_t write_lock;
- struct tty_dev *tty_dev;
-};
-
-#endif /* _GDM_MUX_H_ */
diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c
deleted file mode 100644
index 15c246d3b1a3..000000000000
--- a/drivers/staging/gdm724x/gdm_tty.c
+++ /dev/null
@@ -1,316 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb/cdc.h>
-#include <linux/serial.h>
-#include "gdm_tty.h"
-
-#define GDM_TTY_MAJOR 0
-#define GDM_TTY_MINOR 32
-
-#define WRITE_SIZE 2048
-
-#define MUX_TX_MAX_SIZE 2048
-
-static inline bool gdm_tty_ready(struct gdm *gdm)
-{
- return gdm && gdm->tty_dev && gdm->port.count;
-}
-
-static struct tty_driver *gdm_driver[TTY_MAX_COUNT];
-static struct gdm *gdm_table[TTY_MAX_COUNT][GDM_TTY_MINOR];
-static DEFINE_MUTEX(gdm_table_lock);
-
-static const char *DRIVER_STRING[TTY_MAX_COUNT] = {"GCTATC", "GCTDM"};
-static char *DEVICE_STRING[TTY_MAX_COUNT] = {"GCT-ATC", "GCT-DM"};
-
-static void gdm_port_destruct(struct tty_port *port)
-{
- struct gdm *gdm = container_of(port, struct gdm, port);
-
- mutex_lock(&gdm_table_lock);
- gdm_table[gdm->index][gdm->minor] = NULL;
- mutex_unlock(&gdm_table_lock);
-
- kfree(gdm);
-}
-
-static const struct tty_port_operations gdm_port_ops = {
- .destruct = gdm_port_destruct,
-};
-
-static int gdm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
-{
- struct gdm *gdm = NULL;
- int ret;
-
- ret = match_string(DRIVER_STRING, TTY_MAX_COUNT,
- tty->driver->driver_name);
- if (ret < 0)
- return -ENODEV;
-
- mutex_lock(&gdm_table_lock);
- gdm = gdm_table[ret][tty->index];
- if (!gdm) {
- mutex_unlock(&gdm_table_lock);
- return -ENODEV;
- }
-
- tty_port_get(&gdm->port);
-
- ret = tty_standard_install(driver, tty);
- if (ret) {
- tty_port_put(&gdm->port);
- mutex_unlock(&gdm_table_lock);
- return ret;
- }
-
- tty->driver_data = gdm;
- mutex_unlock(&gdm_table_lock);
-
- return 0;
-}
-
-static int gdm_tty_open(struct tty_struct *tty, struct file *filp)
-{
- struct gdm *gdm = tty->driver_data;
-
- return tty_port_open(&gdm->port, tty, filp);
-}
-
-static void gdm_tty_cleanup(struct tty_struct *tty)
-{
- struct gdm *gdm = tty->driver_data;
-
- tty_port_put(&gdm->port);
-}
-
-static void gdm_tty_hangup(struct tty_struct *tty)
-{
- struct gdm *gdm = tty->driver_data;
-
- tty_port_hangup(&gdm->port);
-}
-
-static void gdm_tty_close(struct tty_struct *tty, struct file *filp)
-{
- struct gdm *gdm = tty->driver_data;
-
- tty_port_close(&gdm->port, tty, filp);
-}
-
-static int gdm_tty_recv_complete(void *data,
- int len,
- int index,
- struct tty_dev *tty_dev,
- int complete)
-{
- struct gdm *gdm = tty_dev->gdm[index];
-
- if (!gdm_tty_ready(gdm)) {
- if (complete == RECV_PACKET_PROCESS_COMPLETE)
- gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev,
- gdm_tty_recv_complete);
- return TO_HOST_PORT_CLOSE;
- }
-
- if (data && len) {
- if (tty_buffer_request_room(&gdm->port, len) == len) {
- tty_insert_flip_string(&gdm->port, data, len);
- tty_flip_buffer_push(&gdm->port);
- } else {
- return TO_HOST_BUFFER_REQUEST_FAIL;
- }
- }
-
- if (complete == RECV_PACKET_PROCESS_COMPLETE)
- gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev,
- gdm_tty_recv_complete);
-
- return 0;
-}
-
-static void gdm_tty_send_complete(void *arg)
-{
- struct gdm *gdm = arg;
-
- if (!gdm_tty_ready(gdm))
- return;
-
- tty_port_tty_wakeup(&gdm->port);
-}
-
-static ssize_t gdm_tty_write(struct tty_struct *tty, const u8 *buf, size_t len)
-{
- struct gdm *gdm = tty->driver_data;
- size_t remain = len;
- size_t sent_len = 0;
-
- if (!gdm_tty_ready(gdm))
- return -ENODEV;
-
- while (remain) {
- size_t sending_len = min_t(size_t, MUX_TX_MAX_SIZE, remain);
-
- gdm->tty_dev->send_func(gdm->tty_dev->priv_dev,
- (void *)(buf + sent_len),
- sending_len,
- gdm->index,
- gdm_tty_send_complete,
- gdm);
- sent_len += sending_len;
- remain -= sending_len;
- }
-
- return len;
-}
-
-static unsigned int gdm_tty_write_room(struct tty_struct *tty)
-{
- struct gdm *gdm = tty->driver_data;
-
- if (!gdm_tty_ready(gdm))
- return 0;
-
- return WRITE_SIZE;
-}
-
-int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device)
-{
- struct gdm *gdm;
- int i;
- int j;
-
- for (i = 0; i < TTY_MAX_COUNT; i++) {
- gdm = kmalloc(sizeof(*gdm), GFP_KERNEL);
- if (!gdm)
- return -ENOMEM;
-
- mutex_lock(&gdm_table_lock);
- for (j = 0; j < GDM_TTY_MINOR; j++) {
- if (!gdm_table[i][j])
- break;
- }
-
- if (j == GDM_TTY_MINOR) {
- kfree(gdm);
- mutex_unlock(&gdm_table_lock);
- return -EINVAL;
- }
-
- gdm_table[i][j] = gdm;
- mutex_unlock(&gdm_table_lock);
-
- tty_dev->gdm[i] = gdm;
- tty_port_init(&gdm->port);
-
- gdm->port.ops = &gdm_port_ops;
- gdm->index = i;
- gdm->minor = j;
- gdm->tty_dev = tty_dev;
-
- tty_port_register_device(&gdm->port, gdm_driver[i],
- gdm->minor, device);
- }
-
- for (i = 0; i < MAX_ISSUE_NUM; i++)
- gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev,
- gdm_tty_recv_complete);
-
- return 0;
-}
-
-void unregister_lte_tty_device(struct tty_dev *tty_dev)
-{
- struct gdm *gdm;
- struct tty_struct *tty;
- int i;
-
- for (i = 0; i < TTY_MAX_COUNT; i++) {
- gdm = tty_dev->gdm[i];
- if (!gdm)
- continue;
-
- mutex_lock(&gdm_table_lock);
- gdm_table[gdm->index][gdm->minor] = NULL;
- mutex_unlock(&gdm_table_lock);
-
- tty = tty_port_tty_get(&gdm->port);
- if (tty) {
- tty_vhangup(tty);
- tty_kref_put(tty);
- }
-
- tty_unregister_device(gdm_driver[i], gdm->minor);
- tty_port_put(&gdm->port);
- }
-}
-
-static const struct tty_operations gdm_tty_ops = {
- .install = gdm_tty_install,
- .open = gdm_tty_open,
- .close = gdm_tty_close,
- .cleanup = gdm_tty_cleanup,
- .hangup = gdm_tty_hangup,
- .write = gdm_tty_write,
- .write_room = gdm_tty_write_room,
-};
-
-int register_lte_tty_driver(void)
-{
- struct tty_driver *tty_driver;
- int i;
- int ret;
-
- for (i = 0; i < TTY_MAX_COUNT; i++) {
- tty_driver = tty_alloc_driver(GDM_TTY_MINOR,
- TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
- if (IS_ERR(tty_driver))
- return PTR_ERR(tty_driver);
-
- tty_driver->owner = THIS_MODULE;
- tty_driver->driver_name = DRIVER_STRING[i];
- tty_driver->name = DEVICE_STRING[i];
- tty_driver->major = GDM_TTY_MAJOR;
- tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
- tty_driver->subtype = SERIAL_TYPE_NORMAL;
- tty_driver->init_termios = tty_std_termios;
- tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL;
- tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN;
- tty_set_operations(tty_driver, &gdm_tty_ops);
-
- ret = tty_register_driver(tty_driver);
- if (ret) {
- tty_driver_kref_put(tty_driver);
- return ret;
- }
-
- gdm_driver[i] = tty_driver;
- }
-
- return ret;
-}
-
-void unregister_lte_tty_driver(void)
-{
- struct tty_driver *tty_driver;
- int i;
-
- for (i = 0; i < TTY_MAX_COUNT; i++) {
- tty_driver = gdm_driver[i];
- if (tty_driver) {
- tty_unregister_driver(tty_driver);
- tty_driver_kref_put(tty_driver);
- }
- }
-}
-
diff --git a/drivers/staging/gdm724x/gdm_tty.h b/drivers/staging/gdm724x/gdm_tty.h
deleted file mode 100644
index afec97ced476..000000000000
--- a/drivers/staging/gdm724x/gdm_tty.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _GDM_TTY_H_
-#define _GDM_TTY_H_
-
-#include <linux/types.h>
-#include <linux/tty.h>
-
-#define TTY_MAX_COUNT 2
-
-#define MAX_ISSUE_NUM 3
-
-enum TO_HOST_RESULT {
- TO_HOST_BUFFER_REQUEST_FAIL = 1,
- TO_HOST_PORT_CLOSE = 2,
- TO_HOST_INVALID_PACKET = 3,
-};
-
-enum RECV_PACKET_PROCESS {
- RECV_PACKET_PROCESS_COMPLETE = 0,
- RECV_PACKET_PROCESS_CONTINUE = 1,
-};
-
-struct gdm {
- struct tty_dev *tty_dev;
- struct tty_port port;
- unsigned int index;
- unsigned int minor;
-};
-
-struct tty_dev {
- void *priv_dev;
- int (*send_func)(void *priv_dev,
- void *data,
- int len,
- int tty_index,
- void (*cb)(void *cb_data),
- void *cb_data);
- int (*recv_func)(void *priv_dev,
- int (*cb)(void *data,
- int len,
- int tty_index,
- struct tty_dev *tty_dev,
- int complete));
- int (*send_control)(void *priv_dev,
- int request,
- int value,
- void *data,
- int len);
- struct gdm *gdm[2];
-};
-
-int register_lte_tty_driver(void);
-void unregister_lte_tty_driver(void);
-int register_lte_tty_device(struct tty_dev *tty_dev, struct device *dev);
-void unregister_lte_tty_device(struct tty_dev *tty_dev);
-
-#endif /* _GDM_USB_H_ */
-
diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c
deleted file mode 100644
index 54bdb64f52e8..000000000000
--- a/drivers/staging/gdm724x/gdm_usb.c
+++ /dev/null
@@ -1,1012 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-#include <linux/usb/cdc.h>
-#include <linux/wait.h>
-#include <linux/if_ether.h>
-#include <linux/pm_runtime.h>
-
-#include "gdm_usb.h"
-#include "gdm_lte.h"
-#include "hci.h"
-#include "hci_packet.h"
-#include "gdm_endian.h"
-
-#define USB_DEVICE_CDC_DATA(vid, pid) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
- USB_DEVICE_ID_MATCH_INT_CLASS | \
- USB_DEVICE_ID_MATCH_INT_SUBCLASS,\
- .idVendor = vid,\
- .idProduct = pid,\
- .bInterfaceClass = USB_CLASS_COMM,\
- .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET
-
-#define USB_DEVICE_MASS_DATA(vid, pid) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
- USB_DEVICE_ID_MATCH_INT_INFO,\
- .idVendor = vid,\
- .idProduct = pid,\
- .bInterfaceSubClass = USB_SC_SCSI, \
- .bInterfaceClass = USB_CLASS_MASS_STORAGE,\
- .bInterfaceProtocol = USB_PR_BULK
-
-static const struct usb_device_id id_table[] = {
- { USB_DEVICE_CDC_DATA(VID_GCT, PID_GDM7240) }, /* GCT GDM7240 */
- { USB_DEVICE_CDC_DATA(VID_GCT, PID_GDM7243) }, /* GCT GDM7243 */
- { }
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static void do_tx(struct work_struct *work);
-static void do_rx(struct work_struct *work);
-
-static int gdm_usb_recv(void *priv_dev,
- int (*cb)(void *cb_data,
- void *data, int len, int context),
- void *cb_data,
- int context);
-
-static int request_mac_address(struct lte_udev *udev)
-{
- struct hci_packet *hci;
- struct usb_device *usbdev = udev->usbdev;
- int actual;
- int ret = -1;
-
- hci = kmalloc(struct_size(hci, data, 1), GFP_KERNEL);
- if (!hci)
- return -ENOMEM;
-
- hci->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_GET_INFORMATION);
- hci->len = gdm_cpu_to_dev16(udev->gdm_ed, 1);
- hci->data[0] = MAC_ADDRESS;
-
- ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), hci, 5,
- &actual, 1000);
-
- udev->request_mac_addr = 1;
- kfree(hci);
-
- return ret;
-}
-
-static struct usb_tx *alloc_tx_struct(int len)
-{
- struct usb_tx *t = NULL;
- int ret = 0;
-
- t = kzalloc(sizeof(*t), GFP_ATOMIC);
- if (!t) {
- ret = -ENOMEM;
- goto out;
- }
-
- t->urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!(len % 512))
- len++;
-
- t->buf = kmalloc(len, GFP_ATOMIC);
- if (!t->urb || !t->buf) {
- ret = -ENOMEM;
- goto out;
- }
-
-out:
- if (ret < 0) {
- if (t) {
- usb_free_urb(t->urb);
- kfree(t->buf);
- kfree(t);
- }
- return NULL;
- }
-
- return t;
-}
-
-static struct usb_tx_sdu *alloc_tx_sdu_struct(void)
-{
- struct usb_tx_sdu *t_sdu;
-
- t_sdu = kzalloc(sizeof(*t_sdu), GFP_KERNEL);
- if (!t_sdu)
- return NULL;
-
- t_sdu->buf = kmalloc(SDU_BUF_SIZE, GFP_KERNEL);
- if (!t_sdu->buf) {
- kfree(t_sdu);
- return NULL;
- }
-
- return t_sdu;
-}
-
-static void free_tx_struct(struct usb_tx *t)
-{
- if (t) {
- usb_free_urb(t->urb);
- kfree(t->buf);
- kfree(t);
- }
-}
-
-static void free_tx_sdu_struct(struct usb_tx_sdu *t_sdu)
-{
- if (t_sdu) {
- kfree(t_sdu->buf);
- kfree(t_sdu);
- }
-}
-
-static struct usb_tx_sdu *get_tx_sdu_struct(struct tx_cxt *tx, int *no_spc)
-{
- struct usb_tx_sdu *t_sdu;
-
- if (list_empty(&tx->free_list))
- return NULL;
-
- t_sdu = list_entry(tx->free_list.next, struct usb_tx_sdu, list);
- list_del(&t_sdu->list);
-
- tx->avail_count--;
-
- *no_spc = list_empty(&tx->free_list) ? 1 : 0;
-
- return t_sdu;
-}
-
-static void put_tx_struct(struct tx_cxt *tx, struct usb_tx_sdu *t_sdu)
-{
- list_add_tail(&t_sdu->list, &tx->free_list);
- tx->avail_count++;
-}
-
-static struct usb_rx *alloc_rx_struct(void)
-{
- struct usb_rx *r = NULL;
- int ret = 0;
-
- r = kmalloc(sizeof(*r), GFP_KERNEL);
- if (!r) {
- ret = -ENOMEM;
- goto out;
- }
-
- r->urb = usb_alloc_urb(0, GFP_KERNEL);
- r->buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
- if (!r->urb || !r->buf) {
- ret = -ENOMEM;
- goto out;
- }
-out:
-
- if (ret < 0) {
- if (r) {
- usb_free_urb(r->urb);
- kfree(r->buf);
- kfree(r);
- }
- return NULL;
- }
-
- return r;
-}
-
-static void free_rx_struct(struct usb_rx *r)
-{
- if (r) {
- usb_free_urb(r->urb);
- kfree(r->buf);
- kfree(r);
- }
-}
-
-static struct usb_rx *get_rx_struct(struct rx_cxt *rx, int *no_spc)
-{
- struct usb_rx *r;
- unsigned long flags;
-
- spin_lock_irqsave(&rx->rx_lock, flags);
-
- if (list_empty(&rx->free_list)) {
- spin_unlock_irqrestore(&rx->rx_lock, flags);
- return NULL;
- }
-
- r = list_entry(rx->free_list.next, struct usb_rx, free_list);
- list_del(&r->free_list);
-
- rx->avail_count--;
-
- *no_spc = list_empty(&rx->free_list) ? 1 : 0;
-
- spin_unlock_irqrestore(&rx->rx_lock, flags);
-
- return r;
-}
-
-static void put_rx_struct(struct rx_cxt *rx, struct usb_rx *r)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&rx->rx_lock, flags);
-
- list_add_tail(&r->free_list, &rx->free_list);
- rx->avail_count++;
-
- spin_unlock_irqrestore(&rx->rx_lock, flags);
-}
-
-static void release_usb(struct lte_udev *udev)
-{
- struct rx_cxt *rx = &udev->rx;
- struct tx_cxt *tx = &udev->tx;
- struct usb_tx *t, *t_next;
- struct usb_rx *r, *r_next;
- struct usb_tx_sdu *t_sdu, *t_sdu_next;
- unsigned long flags;
-
- spin_lock_irqsave(&tx->lock, flags);
- list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->sdu_list, list) {
- list_del(&t_sdu->list);
- free_tx_sdu_struct(t_sdu);
- }
-
- list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
- list_del(&t->list);
- free_tx_struct(t);
- }
-
- list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->free_list, list) {
- list_del(&t_sdu->list);
- free_tx_sdu_struct(t_sdu);
- }
- spin_unlock_irqrestore(&tx->lock, flags);
-
- spin_lock_irqsave(&rx->submit_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
- rx_submit_list) {
- spin_unlock_irqrestore(&rx->submit_lock, flags);
- usb_kill_urb(r->urb);
- spin_lock_irqsave(&rx->submit_lock, flags);
- }
- spin_unlock_irqrestore(&rx->submit_lock, flags);
-
- spin_lock_irqsave(&rx->rx_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->free_list, free_list) {
- list_del(&r->free_list);
- free_rx_struct(r);
- }
- spin_unlock_irqrestore(&rx->rx_lock, flags);
-
- spin_lock_irqsave(&rx->to_host_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list) {
- if (r->index == (void *)udev) {
- list_del(&r->to_host_list);
- free_rx_struct(r);
- }
- }
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
-}
-
-static int init_usb(struct lte_udev *udev)
-{
- int ret = 0;
- int i;
- struct tx_cxt *tx = &udev->tx;
- struct rx_cxt *rx = &udev->rx;
- struct usb_tx_sdu *t_sdu = NULL;
- struct usb_rx *r = NULL;
-
- udev->send_complete = 1;
- udev->tx_stop = 0;
- udev->request_mac_addr = 0;
- udev->usb_state = PM_NORMAL;
-
- INIT_LIST_HEAD(&tx->sdu_list);
- INIT_LIST_HEAD(&tx->hci_list);
- INIT_LIST_HEAD(&tx->free_list);
- INIT_LIST_HEAD(&rx->rx_submit_list);
- INIT_LIST_HEAD(&rx->free_list);
- INIT_LIST_HEAD(&rx->to_host_list);
- spin_lock_init(&tx->lock);
- spin_lock_init(&rx->rx_lock);
- spin_lock_init(&rx->submit_lock);
- spin_lock_init(&rx->to_host_lock);
-
- tx->avail_count = 0;
- rx->avail_count = 0;
-
- udev->rx_cb = NULL;
-
- for (i = 0; i < MAX_NUM_SDU_BUF; i++) {
- t_sdu = alloc_tx_sdu_struct();
- if (!t_sdu) {
- ret = -ENOMEM;
- goto fail;
- }
-
- list_add(&t_sdu->list, &tx->free_list);
- tx->avail_count++;
- }
-
- for (i = 0; i < MAX_RX_SUBMIT_COUNT * 2; i++) {
- r = alloc_rx_struct();
- if (!r) {
- ret = -ENOMEM;
- goto fail;
- }
-
- list_add(&r->free_list, &rx->free_list);
- rx->avail_count++;
- }
- INIT_DELAYED_WORK(&udev->work_tx, do_tx);
- INIT_DELAYED_WORK(&udev->work_rx, do_rx);
- return 0;
-fail:
- release_usb(udev);
- return ret;
-}
-
-static int set_mac_address(u8 *data, void *arg)
-{
- struct phy_dev *phy_dev = arg;
- struct lte_udev *udev = phy_dev->priv_dev;
- struct tlv *tlv = (struct tlv *)data;
- u8 mac_address[ETH_ALEN] = {0, };
-
- if (tlv->type == MAC_ADDRESS && udev->request_mac_addr) {
- memcpy(mac_address, tlv->data, tlv->len);
-
- if (register_lte_device(phy_dev,
- &udev->intf->dev, mac_address) < 0)
- pr_err("register lte device failed\n");
-
- udev->request_mac_addr = 0;
-
- return 1;
- }
-
- return 0;
-}
-
-static void do_rx(struct work_struct *work)
-{
- struct lte_udev *udev =
- container_of(work, struct lte_udev, work_rx.work);
- struct rx_cxt *rx = &udev->rx;
- struct usb_rx *r;
- struct hci_packet *hci;
- struct phy_dev *phy_dev;
- u16 cmd_evt;
- int ret;
- unsigned long flags;
-
- while (1) {
- spin_lock_irqsave(&rx->to_host_lock, flags);
- if (list_empty(&rx->to_host_list)) {
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
- break;
- }
- r = list_entry(rx->to_host_list.next,
- struct usb_rx, to_host_list);
- list_del(&r->to_host_list);
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
-
- phy_dev = r->cb_data;
- udev = phy_dev->priv_dev;
- hci = (struct hci_packet *)r->buf;
- cmd_evt = gdm_dev16_to_cpu(udev->gdm_ed, hci->cmd_evt);
-
- switch (cmd_evt) {
- case LTE_GET_INFORMATION_RESULT:
- if (set_mac_address(hci->data, r->cb_data) == 0) {
- r->callback(r->cb_data,
- r->buf,
- r->urb->actual_length,
- KERNEL_THREAD);
- }
- break;
-
- default:
- if (r->callback) {
- ret = r->callback(r->cb_data,
- r->buf,
- r->urb->actual_length,
- KERNEL_THREAD);
-
- if (ret == -EAGAIN)
- pr_err("failed to send received data\n");
- }
- break;
- }
-
- put_rx_struct(rx, r);
-
- gdm_usb_recv(udev,
- r->callback,
- r->cb_data,
- USB_COMPLETE);
- }
-}
-
-static void remove_rx_submit_list(struct usb_rx *r, struct rx_cxt *rx)
-{
- unsigned long flags;
- struct usb_rx *r_remove, *r_remove_next;
-
- spin_lock_irqsave(&rx->submit_lock, flags);
- list_for_each_entry_safe(r_remove, r_remove_next,
- &rx->rx_submit_list, rx_submit_list) {
- if (r == r_remove) {
- list_del(&r->rx_submit_list);
- break;
- }
- }
- spin_unlock_irqrestore(&rx->submit_lock, flags);
-}
-
-static void gdm_usb_rcv_complete(struct urb *urb)
-{
- struct usb_rx *r = urb->context;
- struct rx_cxt *rx = r->rx;
- unsigned long flags;
- struct lte_udev *udev = container_of(r->rx, struct lte_udev, rx);
- struct usb_device *usbdev = udev->usbdev;
-
- remove_rx_submit_list(r, rx);
-
- if (!urb->status && r->callback) {
- spin_lock_irqsave(&rx->to_host_lock, flags);
- list_add_tail(&r->to_host_list, &rx->to_host_list);
- schedule_work(&udev->work_rx.work);
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
- } else {
- if (urb->status && udev->usb_state == PM_NORMAL)
- dev_err(&urb->dev->dev, "%s: urb status error %d\n",
- __func__, urb->status);
-
- put_rx_struct(rx, r);
- }
-
- usb_mark_last_busy(usbdev);
-}
-
-static int gdm_usb_recv(void *priv_dev,
- int (*cb)(void *cb_data,
- void *data, int len, int context),
- void *cb_data,
- int context)
-{
- struct lte_udev *udev = priv_dev;
- struct usb_device *usbdev = udev->usbdev;
- struct rx_cxt *rx = &udev->rx;
- struct usb_rx *r;
- int no_spc;
- int ret;
- unsigned long flags;
-
- if (!udev->usbdev) {
- pr_err("invalid device\n");
- return -ENODEV;
- }
-
- r = get_rx_struct(rx, &no_spc);
- if (!r) {
- pr_err("Out of Memory\n");
- return -ENOMEM;
- }
-
- udev->rx_cb = cb;
- r->callback = cb;
- r->cb_data = cb_data;
- r->index = (void *)udev;
- r->rx = rx;
-
- usb_fill_bulk_urb(r->urb,
- usbdev,
- usb_rcvbulkpipe(usbdev, 0x83),
- r->buf,
- RX_BUF_SIZE,
- gdm_usb_rcv_complete,
- r);
-
- spin_lock_irqsave(&rx->submit_lock, flags);
- list_add_tail(&r->rx_submit_list, &rx->rx_submit_list);
- spin_unlock_irqrestore(&rx->submit_lock, flags);
-
- if (context == KERNEL_THREAD)
- ret = usb_submit_urb(r->urb, GFP_KERNEL);
- else
- ret = usb_submit_urb(r->urb, GFP_ATOMIC);
-
- if (ret) {
- spin_lock_irqsave(&rx->submit_lock, flags);
- list_del(&r->rx_submit_list);
- spin_unlock_irqrestore(&rx->submit_lock, flags);
-
- pr_err("usb_submit_urb failed (%p)\n", r);
- put_rx_struct(rx, r);
- }
-
- return ret;
-}
-
-static void gdm_usb_send_complete(struct urb *urb)
-{
- struct usb_tx *t = urb->context;
- struct tx_cxt *tx = t->tx;
- struct lte_udev *udev = container_of(tx, struct lte_udev, tx);
- unsigned long flags;
-
- if (urb->status == -ECONNRESET) {
- dev_info(&urb->dev->dev, "CONNRESET\n");
- return;
- }
-
- if (t->callback)
- t->callback(t->cb_data);
-
- free_tx_struct(t);
-
- spin_lock_irqsave(&tx->lock, flags);
- udev->send_complete = 1;
- schedule_work(&udev->work_tx.work);
- spin_unlock_irqrestore(&tx->lock, flags);
-}
-
-static int send_tx_packet(struct usb_device *usbdev, struct usb_tx *t, u32 len)
-{
- int ret = 0;
-
- if (!(len % 512))
- len++;
-
- usb_fill_bulk_urb(t->urb,
- usbdev,
- usb_sndbulkpipe(usbdev, 2),
- t->buf,
- len,
- gdm_usb_send_complete,
- t);
-
- ret = usb_submit_urb(t->urb, GFP_ATOMIC);
-
- if (ret)
- dev_err(&usbdev->dev, "usb_submit_urb failed: %d\n",
- ret);
-
- usb_mark_last_busy(usbdev);
-
- return ret;
-}
-
-static u32 packet_aggregation(struct lte_udev *udev, u8 *send_buf)
-{
- struct tx_cxt *tx = &udev->tx;
- struct usb_tx_sdu *t_sdu = NULL;
- struct multi_sdu *multi_sdu = (struct multi_sdu *)send_buf;
- u16 send_len = 0;
- u16 num_packet = 0;
- unsigned long flags;
-
- multi_sdu->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_TX_MULTI_SDU);
-
- while (num_packet < MAX_PACKET_IN_MULTI_SDU) {
- spin_lock_irqsave(&tx->lock, flags);
- if (list_empty(&tx->sdu_list)) {
- spin_unlock_irqrestore(&tx->lock, flags);
- break;
- }
-
- t_sdu = list_entry(tx->sdu_list.next, struct usb_tx_sdu, list);
- if (send_len + t_sdu->len > MAX_SDU_SIZE) {
- spin_unlock_irqrestore(&tx->lock, flags);
- break;
- }
-
- list_del(&t_sdu->list);
- spin_unlock_irqrestore(&tx->lock, flags);
-
- memcpy(multi_sdu->data + send_len, t_sdu->buf, t_sdu->len);
-
- send_len += (t_sdu->len + 3) & 0xfffc;
- num_packet++;
-
- if (tx->avail_count > 10)
- t_sdu->callback(t_sdu->cb_data);
-
- spin_lock_irqsave(&tx->lock, flags);
- put_tx_struct(tx, t_sdu);
- spin_unlock_irqrestore(&tx->lock, flags);
- }
-
- multi_sdu->len = gdm_cpu_to_dev16(udev->gdm_ed, send_len);
- multi_sdu->num_packet = gdm_cpu_to_dev16(udev->gdm_ed, num_packet);
-
- return send_len + offsetof(struct multi_sdu, data);
-}
-
-static void do_tx(struct work_struct *work)
-{
- struct lte_udev *udev =
- container_of(work, struct lte_udev, work_tx.work);
- struct usb_device *usbdev = udev->usbdev;
- struct tx_cxt *tx = &udev->tx;
- struct usb_tx *t = NULL;
- int is_send = 0;
- u32 len = 0;
- unsigned long flags;
-
- if (!usb_autopm_get_interface(udev->intf))
- usb_autopm_put_interface(udev->intf);
-
- if (udev->usb_state == PM_SUSPEND)
- return;
-
- spin_lock_irqsave(&tx->lock, flags);
- if (!udev->send_complete) {
- spin_unlock_irqrestore(&tx->lock, flags);
- return;
- }
- udev->send_complete = 0;
-
- if (!list_empty(&tx->hci_list)) {
- t = list_entry(tx->hci_list.next, struct usb_tx, list);
- list_del(&t->list);
- len = t->len;
- t->is_sdu = 0;
- is_send = 1;
- } else if (!list_empty(&tx->sdu_list)) {
- if (udev->tx_stop) {
- udev->send_complete = 1;
- spin_unlock_irqrestore(&tx->lock, flags);
- return;
- }
-
- t = alloc_tx_struct(TX_BUF_SIZE);
- if (!t) {
- spin_unlock_irqrestore(&tx->lock, flags);
- return;
- }
- t->callback = NULL;
- t->tx = tx;
- t->is_sdu = 1;
- is_send = 1;
- }
-
- if (!is_send) {
- udev->send_complete = 1;
- spin_unlock_irqrestore(&tx->lock, flags);
- return;
- }
- spin_unlock_irqrestore(&tx->lock, flags);
-
- if (t->is_sdu)
- len = packet_aggregation(udev, t->buf);
-
- if (send_tx_packet(usbdev, t, len)) {
- pr_err("send_tx_packet failed\n");
- t->callback = NULL;
- gdm_usb_send_complete(t->urb);
- }
-}
-
-#define SDU_PARAM_LEN 12
-static int gdm_usb_sdu_send(void *priv_dev, void *data, int len,
- unsigned int dft_eps_ID, unsigned int eps_ID,
- void (*cb)(void *data), void *cb_data,
- int dev_idx, int nic_type)
-{
- struct lte_udev *udev = priv_dev;
- struct tx_cxt *tx = &udev->tx;
- struct usb_tx_sdu *t_sdu;
- struct sdu *sdu = NULL;
- unsigned long flags;
- int no_spc = 0;
- u16 send_len;
-
- if (!udev->usbdev) {
- pr_err("sdu send - invalid device\n");
- return TX_NO_DEV;
- }
-
- spin_lock_irqsave(&tx->lock, flags);
- t_sdu = get_tx_sdu_struct(tx, &no_spc);
- spin_unlock_irqrestore(&tx->lock, flags);
-
- if (!t_sdu) {
- pr_err("sdu send - free list empty\n");
- return TX_NO_SPC;
- }
-
- sdu = (struct sdu *)t_sdu->buf;
- sdu->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_TX_SDU);
- if (nic_type == NIC_TYPE_ARP) {
- send_len = len + SDU_PARAM_LEN;
- memcpy(sdu->data, data, len);
- } else {
- send_len = len - ETH_HLEN;
- send_len += SDU_PARAM_LEN;
- memcpy(sdu->data, data + ETH_HLEN, len - ETH_HLEN);
- }
-
- sdu->len = gdm_cpu_to_dev16(udev->gdm_ed, send_len);
- sdu->dft_eps_ID = gdm_cpu_to_dev32(udev->gdm_ed, dft_eps_ID);
- sdu->bearer_ID = gdm_cpu_to_dev32(udev->gdm_ed, eps_ID);
- sdu->nic_type = gdm_cpu_to_dev32(udev->gdm_ed, nic_type);
-
- t_sdu->len = send_len + HCI_HEADER_SIZE;
- t_sdu->callback = cb;
- t_sdu->cb_data = cb_data;
-
- spin_lock_irqsave(&tx->lock, flags);
- list_add_tail(&t_sdu->list, &tx->sdu_list);
- schedule_work(&udev->work_tx.work);
- spin_unlock_irqrestore(&tx->lock, flags);
-
- if (no_spc)
- return TX_NO_BUFFER;
-
- return 0;
-}
-
-static int gdm_usb_hci_send(void *priv_dev, void *data, int len,
- void (*cb)(void *data), void *cb_data)
-{
- struct lte_udev *udev = priv_dev;
- struct tx_cxt *tx = &udev->tx;
- struct usb_tx *t;
- unsigned long flags;
-
- if (!udev->usbdev) {
- pr_err("hci send - invalid device\n");
- return -ENODEV;
- }
-
- t = alloc_tx_struct(len);
- if (!t) {
- pr_err("hci_send - out of memory\n");
- return -ENOMEM;
- }
-
- memcpy(t->buf, data, len);
- t->callback = cb;
- t->cb_data = cb_data;
- t->len = len;
- t->tx = tx;
- t->is_sdu = 0;
-
- spin_lock_irqsave(&tx->lock, flags);
- list_add_tail(&t->list, &tx->hci_list);
- schedule_work(&udev->work_tx.work);
- spin_unlock_irqrestore(&tx->lock, flags);
-
- return 0;
-}
-
-static u8 gdm_usb_get_endian(void *priv_dev)
-{
- struct lte_udev *udev = priv_dev;
-
- return udev->gdm_ed;
-}
-
-static int gdm_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- int ret = 0;
- struct phy_dev *phy_dev = NULL;
- struct lte_udev *udev = NULL;
- u16 idVendor, idProduct;
- int bInterfaceNumber;
- struct usb_device *usbdev = interface_to_usbdev(intf);
-
- bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber;
- idVendor = __le16_to_cpu(usbdev->descriptor.idVendor);
- idProduct = __le16_to_cpu(usbdev->descriptor.idProduct);
-
- pr_info("net vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct);
-
- if (bInterfaceNumber > NETWORK_INTERFACE) {
- pr_info("not a network device\n");
- return -ENODEV;
- }
-
- phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL);
- if (!phy_dev)
- return -ENOMEM;
-
- udev = kzalloc(sizeof(*udev), GFP_KERNEL);
- if (!udev) {
- ret = -ENOMEM;
- goto err_udev;
- }
-
- phy_dev->priv_dev = (void *)udev;
- phy_dev->send_hci_func = gdm_usb_hci_send;
- phy_dev->send_sdu_func = gdm_usb_sdu_send;
- phy_dev->rcv_func = gdm_usb_recv;
- phy_dev->get_endian = gdm_usb_get_endian;
-
- udev->usbdev = usbdev;
- ret = init_usb(udev);
- if (ret < 0) {
- dev_err(intf->usb_dev, "init_usb func failed\n");
- goto err_init_usb;
- }
- udev->intf = intf;
-
- intf->needs_remote_wakeup = 1;
- usb_enable_autosuspend(usbdev);
- pm_runtime_set_autosuspend_delay(&usbdev->dev, AUTO_SUSPEND_TIMER);
-
- /* List up hosts with big endians, otherwise,
- * defaults to little endian
- */
- if (idProduct == PID_GDM7243)
- udev->gdm_ed = ENDIANNESS_BIG;
- else
- udev->gdm_ed = ENDIANNESS_LITTLE;
-
- ret = request_mac_address(udev);
- if (ret < 0) {
- dev_err(intf->usb_dev, "request Mac address failed\n");
- goto err_mac_address;
- }
-
- start_rx_proc(phy_dev);
- usb_get_dev(usbdev);
- usb_set_intfdata(intf, phy_dev);
-
- return 0;
-
-err_mac_address:
- release_usb(udev);
-err_init_usb:
- kfree(udev);
-err_udev:
- kfree(phy_dev);
-
- return ret;
-}
-
-static void gdm_usb_disconnect(struct usb_interface *intf)
-{
- struct phy_dev *phy_dev;
- struct lte_udev *udev;
- struct usb_device *usbdev;
-
- usbdev = interface_to_usbdev(intf);
- phy_dev = usb_get_intfdata(intf);
-
- udev = phy_dev->priv_dev;
- unregister_lte_device(phy_dev);
-
- release_usb(udev);
-
- kfree(udev);
- udev = NULL;
-
- kfree(phy_dev);
- phy_dev = NULL;
-
- usb_put_dev(usbdev);
-}
-
-static int gdm_usb_suspend(struct usb_interface *intf, pm_message_t pm_msg)
-{
- struct phy_dev *phy_dev;
- struct lte_udev *udev;
- struct rx_cxt *rx;
- struct usb_rx *r;
- struct usb_rx *r_next;
- unsigned long flags;
-
- phy_dev = usb_get_intfdata(intf);
- udev = phy_dev->priv_dev;
- rx = &udev->rx;
- if (udev->usb_state != PM_NORMAL) {
- dev_err(intf->usb_dev, "usb suspend - invalid state\n");
- return -1;
- }
-
- udev->usb_state = PM_SUSPEND;
-
- spin_lock_irqsave(&rx->submit_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
- rx_submit_list) {
- spin_unlock_irqrestore(&rx->submit_lock, flags);
- usb_kill_urb(r->urb);
- spin_lock_irqsave(&rx->submit_lock, flags);
- }
- spin_unlock_irqrestore(&rx->submit_lock, flags);
-
- cancel_work_sync(&udev->work_tx.work);
- cancel_work_sync(&udev->work_rx.work);
-
- return 0;
-}
-
-static int gdm_usb_resume(struct usb_interface *intf)
-{
- struct phy_dev *phy_dev;
- struct lte_udev *udev;
- struct tx_cxt *tx;
- struct rx_cxt *rx;
- unsigned long flags;
- int issue_count;
- int i;
-
- phy_dev = usb_get_intfdata(intf);
- udev = phy_dev->priv_dev;
- rx = &udev->rx;
-
- if (udev->usb_state != PM_SUSPEND) {
- dev_err(intf->usb_dev, "usb resume - invalid state\n");
- return -1;
- }
- udev->usb_state = PM_NORMAL;
-
- spin_lock_irqsave(&rx->rx_lock, flags);
- issue_count = rx->avail_count - MAX_RX_SUBMIT_COUNT;
- spin_unlock_irqrestore(&rx->rx_lock, flags);
-
- if (issue_count >= 0) {
- for (i = 0; i < issue_count; i++)
- gdm_usb_recv(phy_dev->priv_dev,
- udev->rx_cb,
- phy_dev,
- USB_COMPLETE);
- }
-
- tx = &udev->tx;
- spin_lock_irqsave(&tx->lock, flags);
- schedule_work(&udev->work_tx.work);
- spin_unlock_irqrestore(&tx->lock, flags);
-
- return 0;
-}
-
-static struct usb_driver gdm_usb_lte_driver = {
- .name = "gdm_lte",
- .probe = gdm_usb_probe,
- .disconnect = gdm_usb_disconnect,
- .id_table = id_table,
- .supports_autosuspend = 1,
- .suspend = gdm_usb_suspend,
- .resume = gdm_usb_resume,
- .reset_resume = gdm_usb_resume,
-};
-
-static int __init gdm_usb_lte_init(void)
-{
- if (gdm_lte_event_init() < 0) {
- pr_err("error creating event\n");
- return -1;
- }
-
- return usb_register(&gdm_usb_lte_driver);
-}
-
-static void __exit gdm_usb_lte_exit(void)
-{
- gdm_lte_event_exit();
-
- usb_deregister(&gdm_usb_lte_driver);
-}
-
-module_init(gdm_usb_lte_init);
-module_exit(gdm_usb_lte_exit);
-
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_DESCRIPTION("GCT LTE USB Device Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gdm724x/gdm_usb.h b/drivers/staging/gdm724x/gdm_usb.h
deleted file mode 100644
index db689b091c4f..000000000000
--- a/drivers/staging/gdm724x/gdm_usb.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _GDM_USB_H_
-#define _GDM_USB_H_
-
-#include <linux/types.h>
-#include <linux/usb.h>
-#include <linux/list.h>
-#include <linux/time.h>
-
-#include "gdm_endian.h"
-#include "hci_packet.h"
-
-#define PM_NORMAL 0
-#define PM_SUSPEND 1
-#define AUTO_SUSPEND_TIMER 5000 /* ms */
-
-#define RX_BUF_SIZE (1024 * 32)
-#define TX_BUF_SIZE (1024 * 32)
-#define SDU_BUF_SIZE 2048
-#define MAX_SDU_SIZE (1024 * 30)
-#define MAX_PACKET_IN_MULTI_SDU 256
-
-#define VID_GCT 0x1076
-#define PID_GDM7240 0x8000
-#define PID_GDM7243 0x9000
-
-#define NETWORK_INTERFACE 1
-#define USB_SC_SCSI 0x06
-#define USB_PR_BULK 0x50
-
-#define MAX_NUM_SDU_BUF 64
-
-struct usb_tx {
- struct list_head list;
- struct urb *urb;
- u8 *buf;
- u32 len;
- void (*callback)(void *cb_data);
- void *cb_data;
- struct tx_cxt *tx;
- u8 is_sdu;
-};
-
-struct usb_tx_sdu {
- struct list_head list;
- u8 *buf;
- u32 len;
- void (*callback)(void *cb_data);
- void *cb_data;
-};
-
-struct usb_rx {
- struct list_head to_host_list;
- struct list_head free_list;
- struct list_head rx_submit_list;
- struct rx_cxt *rx;
- struct urb *urb;
- u8 *buf;
- int (*callback)(void *cb_data, void *data, int len, int context);
- void *cb_data;
- void *index;
-};
-
-struct tx_cxt {
- struct list_head sdu_list;
- struct list_head hci_list;
- struct list_head free_list;
- u32 avail_count;
- spinlock_t lock;
-};
-
-struct rx_cxt {
- struct list_head to_host_list;
- struct list_head rx_submit_list;
- struct list_head free_list;
- u32 avail_count;
- spinlock_t to_host_lock;
- spinlock_t rx_lock;
- spinlock_t submit_lock;
-};
-
-struct lte_udev {
- struct usb_device *usbdev;
- struct tx_cxt tx;
- struct rx_cxt rx;
- struct delayed_work work_tx;
- struct delayed_work work_rx;
- u8 gdm_ed;
- u8 send_complete;
- u8 tx_stop;
- struct usb_interface *intf;
- int (*rx_cb)(void *cb_data, void *data, int len, int context);
- int usb_state;
- u8 request_mac_addr;
-};
-
-#endif /* _GDM_USB_H_ */
diff --git a/drivers/staging/gdm724x/hci.h b/drivers/staging/gdm724x/hci.h
deleted file mode 100644
index b30945daf3a5..000000000000
--- a/drivers/staging/gdm724x/hci.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _HCI_H_
-#define _HCI_H_
-
-#define LTE_GET_INFORMATION 0x3002
-#define LTE_GET_INFORMATION_RESULT 0xB003
- #define MAC_ADDRESS 0xA2
-
-#define LTE_LINK_ON_OFF_INDICATION 0xB133
-#define LTE_PDN_TABLE_IND 0xB143
-
-#define LTE_TX_SDU 0x3200
-#define LTE_RX_SDU 0xB201
-#define LTE_TX_MULTI_SDU 0x3202
-#define LTE_RX_MULTI_SDU 0xB203
-
-#define LTE_DL_SDU_FLOW_CONTROL 0x3305
-#define LTE_UL_SDU_FLOW_CONTROL 0xB306
-
-#define LTE_AT_CMD_TO_DEVICE 0x3307
-#define LTE_AT_CMD_FROM_DEVICE 0xB308
-
-#define LTE_SDIO_DM_SEND_PKT 0x3312
-#define LTE_SDIO_DM_RECV_PKT 0xB313
-
-#define LTE_NV_RESTORE_REQUEST 0xB30C
-#define LTE_NV_RESTORE_RESPONSE 0x330D
-#define LTE_NV_SAVE_REQUEST 0xB30E
- #define NV_TYPE_LTE_INFO 0x00
- #define NV_TYPE_BOARD_CONFIG 0x01
- #define NV_TYPE_RF_CAL 0x02
- #define NV_TYPE_TEMP 0x03
- #define NV_TYPE_NET_INFO 0x04
- #define NV_TYPE_SAFETY_INFO 0x05
- #define NV_TYPE_CDMA_CAL 0x06
- #define NV_TYPE_VENDOR 0x07
- #define NV_TYPE_ALL 0xff
-#define LTE_NV_SAVE_RESPONSE 0x330F
-
-#define LTE_AT_CMD_TO_DEVICE_EXT 0x3323
-#define LTE_AT_CMD_FROM_DEVICE_EXT 0xB324
-
-#endif /* _HCI_H_ */
diff --git a/drivers/staging/gdm724x/hci_packet.h b/drivers/staging/gdm724x/hci_packet.h
deleted file mode 100644
index 3bb01e94f3b5..000000000000
--- a/drivers/staging/gdm724x/hci_packet.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _HCI_PACKET_H_
-#define _HCI_PACKET_H_
-
-#define HCI_HEADER_SIZE 4
-
-/*
- * The NIC type definition:
- * For backward compatibility, lower 16 bits used as they were.
- * Lower 16 bit: NIC_TYPE values
- * Uppoer 16 bit: NIC_TYPE Flags
- */
-#define NIC_TYPE_NIC0 0x00000010
-#define NIC_TYPE_NIC1 0x00000011
-#define NIC_TYPE_NIC2 0x00000012
-#define NIC_TYPE_NIC3 0x00000013
-#define NIC_TYPE_ARP 0x00000100
-#define NIC_TYPE_ICMPV6 0x00000200
-#define NIC_TYPE_MASK 0x0000FFFF
-#define NIC_TYPE_F_IPV4 0x00010000
-#define NIC_TYPE_F_IPV6 0x00020000
-#define NIC_TYPE_F_DHCP 0x00040000
-#define NIC_TYPE_F_NDP 0x00080000
-#define NIC_TYPE_F_VLAN 0x00100000
-
-struct hci_packet {
- __dev16 cmd_evt;
- __dev16 len;
- u8 data[];
-} __packed;
-
-struct tlv {
- u8 type;
- u8 len;
- u8 *data[];
-} __packed;
-
-struct sdu_header {
- __dev16 cmd_evt;
- __dev16 len;
- __dev32 dft_eps_id;
- __dev32 bearer_ID;
- __dev32 nic_type;
-} __packed;
-
-struct sdu {
- __dev16 cmd_evt;
- __dev16 len;
- __dev32 dft_eps_ID;
- __dev32 bearer_ID;
- __dev32 nic_type;
- u8 data[];
-} __packed;
-
-struct multi_sdu {
- __dev16 cmd_evt;
- __dev16 len;
- __dev16 num_packet;
- __dev16 reserved;
- u8 data[];
-} __packed;
-
-struct hci_pdn_table_ind {
- __dev16 cmd_evt;
- __dev16 len;
- u8 activate;
- __dev32 dft_eps_id;
- __dev32 nic_type;
- u8 pdn_type;
- u8 ipv4_addr[4];
- u8 ipv6_intf_id[8];
-} __packed;
-
-struct hci_connect_ind {
- __dev16 cmd_evt;
- __dev16 len;
- __dev32 connect;
-} __packed;
-
-#endif /* _HCI_PACKET_H_ */
diff --git a/drivers/staging/gdm724x/netlink_k.c b/drivers/staging/gdm724x/netlink_k.c
deleted file mode 100644
index 8f39cc5617aa..000000000000
--- a/drivers/staging/gdm724x/netlink_k.c
+++ /dev/null
@@ -1,128 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/export.h>
-#include <linux/mutex.h>
-#include <linux/etherdevice.h>
-#include <linux/netlink.h>
-#include <asm/byteorder.h>
-#include <net/sock.h>
-
-#include "netlink_k.h"
-
-static DEFINE_MUTEX(netlink_mutex);
-
-#define ND_MAX_GROUP 30
-#define ND_IFINDEX_LEN sizeof(int)
-#define ND_NLMSG_SPACE(len) (NLMSG_SPACE(len) + ND_IFINDEX_LEN)
-#define ND_NLMSG_DATA(nlh) ((void *)((char *)NLMSG_DATA(nlh) + \
- ND_IFINDEX_LEN))
-#define ND_NLMSG_S_LEN(len) ((len) + ND_IFINDEX_LEN)
-#define ND_NLMSG_R_LEN(nlh) ((nlh)->nlmsg_len - ND_IFINDEX_LEN)
-#define ND_NLMSG_IFIDX(nlh) NLMSG_DATA(nlh)
-#define ND_MAX_MSG_LEN (1024 * 32)
-
-static void (*rcv_cb)(struct net_device *dev, u16 type, void *msg, int len);
-
-static void netlink_rcv_cb(struct sk_buff *skb)
-{
- struct nlmsghdr *nlh;
- struct net_device *dev;
- u32 mlen;
- void *msg;
- int ifindex;
-
- if (!rcv_cb) {
- pr_err("nl cb - unregistered\n");
- return;
- }
-
- if (skb->len < NLMSG_HDRLEN) {
- pr_err("nl cb - invalid skb length\n");
- return;
- }
-
- nlh = (struct nlmsghdr *)skb->data;
-
- if (skb->len < nlh->nlmsg_len || nlh->nlmsg_len > ND_MAX_MSG_LEN) {
- pr_err("nl cb - invalid length (%d,%d)\n",
- skb->len, nlh->nlmsg_len);
- return;
- }
-
- memcpy(&ifindex, ND_NLMSG_IFIDX(nlh), ND_IFINDEX_LEN);
- msg = ND_NLMSG_DATA(nlh);
- mlen = ND_NLMSG_R_LEN(nlh);
-
- dev = dev_get_by_index(&init_net, ifindex);
- if (dev) {
- rcv_cb(dev, nlh->nlmsg_type, msg, mlen);
- dev_put(dev);
- } else {
- pr_err("nl cb - dev (%d) not found\n", ifindex);
- }
-}
-
-static void netlink_rcv(struct sk_buff *skb)
-{
- mutex_lock(&netlink_mutex);
- netlink_rcv_cb(skb);
- mutex_unlock(&netlink_mutex);
-}
-
-struct sock *netlink_init(int unit,
- void (*cb)(struct net_device *dev, u16 type,
- void *msg, int len))
-{
- struct sock *sock;
- struct netlink_kernel_cfg cfg = {
- .input = netlink_rcv,
- };
-
- sock = netlink_kernel_create(&init_net, unit, &cfg);
-
- if (sock)
- rcv_cb = cb;
-
- return sock;
-}
-
-int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len,
- struct net_device *dev)
-{
- static u32 seq;
- struct sk_buff *skb = NULL;
- struct nlmsghdr *nlh;
- int ret = 0;
-
- if (group > ND_MAX_GROUP)
- return -EINVAL;
-
- if (!netlink_has_listeners(sock, group + 1))
- return -ESRCH;
-
- skb = alloc_skb(NLMSG_SPACE(len), GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
-
- seq++;
-
- nlh = nlmsg_put(skb, 0, seq, type, len, 0);
- memcpy(NLMSG_DATA(nlh), msg, len);
- NETLINK_CB(skb).portid = 0;
- NETLINK_CB(skb).dst_group = 0;
-
- ret = netlink_broadcast(sock, skb, 0, group + 1, GFP_ATOMIC);
- if (!ret)
- return len;
-
- if (ret != -ESRCH)
- netdev_err(dev, "nl broadcast g=%d, t=%d, l=%d, r=%d\n",
- group, type, len, ret);
- else if (netlink_has_listeners(sock, group + 1))
- return -EAGAIN;
-
- return ret;
-}
diff --git a/drivers/staging/gdm724x/netlink_k.h b/drivers/staging/gdm724x/netlink_k.h
deleted file mode 100644
index d42eea9bea3e..000000000000
--- a/drivers/staging/gdm724x/netlink_k.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _NETLINK_K_H
-#define _NETLINK_K_H
-
-#include <linux/netdevice.h>
-#include <net/sock.h>
-
-struct sock *netlink_init(int unit,
- void (*cb)(struct net_device *dev,
- u16 type, void *msg, int len));
-int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len,
- struct net_device *dev);
-
-#endif /* _NETLINK_K_H_ */
diff --git a/drivers/staging/gpib/Kconfig b/drivers/staging/gpib/Kconfig
new file mode 100644
index 000000000000..95308d15a555
--- /dev/null
+++ b/drivers/staging/gpib/Kconfig
@@ -0,0 +1,251 @@
+# SPDX-License-Identifier: GPL-2.0
+menuconfig GPIB
+ tristate "Linux GPIB drivers"
+ help
+ Enable support for GPIB cards and dongles for Linux. GPIB
+ is the General Purpose Interface Bus which conforms to the
+ IEEE488 standard.
+
+ This set of drivers can be used with the corresponding user
+ space library that can be found on Sourceforge under linux-gpib.
+ Select the drivers for your hardware from the list.
+
+if GPIB
+
+config GPIB_COMMON
+ tristate "GPIB core"
+ help
+
+ Core common driver for all GPIB drivers. It provides the
+ interface for the userland library
+
+ To compile this driver as a module, choose M here: the module will be
+ called gpib_common
+
+config GPIB_AGILENT_82350B
+ tristate "Agilent 8235xx PCI(e) adapters"
+ depends on PCI
+ select GPIB_COMMON
+ select GPIB_TMS9914
+ help
+ Enable support for HP/Agilent/Keysight boards
+ 82350A
+ 82350B
+ 82351A
+
+ To compile this driver as a module, choose M here: the module will be
+ called agilent_82350b.
+
+config GPIB_AGILENT_82357A
+ tristate "Agilent 82357a/b USB dongles"
+ select GPIB_COMMON
+ depends on USB
+ help
+ Enable support for Agilent/Keysight 82357x USB dongles.
+
+ To compile this driver as a module, choose M here: the module will be
+ called agilent_82357a.
+
+config GPIB_CEC_PCI
+ tristate "CEC PCI board"
+ depends on PCI
+ depends on HAS_IOPORT
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ help
+ Enable support for Capital Equipment Corporation PCI-488
+ and Keithly KPCI-488 boards.
+
+ To compile this driver as a module, choose M here: the module will be
+ called cec_gpib.
+
+config GPIB_NI_PCI_ISA
+ tristate "NI PCI/ISA compatible boards"
+ depends on ISA_BUS || PCI || PCMCIA
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ help
+ Enable support for National Instruments boards based
+ on TNT4882 chips:
+ AT-GPIB (with NAT4882 chip)
+ AT-GPIB (with NEC7210 chip)
+ AT-GPIB/TNT
+ PCI-GPIB
+ PCIe-GPIB
+ PCI-GPIB+
+ PCM-GPIB
+ PXI-GPIB
+ PCMCIA-GPIB
+ and Capital Equipment Corporation CEC-488 board.
+
+ To compile this driver as a module, choose M here: the module will be
+ called tnt4882.
+
+config GPIB_CB7210
+ tristate "Measurement Computing compatible boards"
+ depends on HAS_IOPORT
+ depends on ISA_BUS || PCI || PCMCIA
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ help
+ Enable support for Measurement Computing (Computer Boards):
+ CPCI_GPIB, ISA-GPIB, ISA-GPIB/LC, PCI-GPIB/1M, PCI-GPIB/300K and
+ PCMCIA-GPIB
+ Quancom PCIGPIB-1 with MC cb7210 chip
+
+ To compile this driver as a module, choose M here: the module will be
+
+config GPIB_NI_USB
+ tristate "NI USB dongles"
+ select GPIB_COMMON
+ depends on USB
+ help
+ Enable support for National Instruments
+ GPIB-USB-B
+ GPIB-USB-HS
+ GPIB-USB-HS+
+ Keithly
+ KUSB-488
+ KUSB-488A
+ Measurement Computing (Computer Boards)
+ USB-488
+
+ To compile this driver as a module, choose M here: the module will be
+ called ni_usb.
+
+config GPIB_FLUKE
+ tristate "Fluke"
+ depends on OF
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ help
+ GPIB driver for Fluke based cda devices.
+
+ To compile this driver as a module, choose M here: the module will be
+ called fluke_gpib
+
+config GPIB_FMH
+ tristate "FMH FPGA based devices"
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ depends on BROKEN
+ depends on OF && PCI
+ help
+ GPIB driver for fmhess FPGA based devices
+
+ To compile this driver as a module, choose M here: the module will be
+ called fmh_gpib
+
+config GPIB_GPIO
+ tristate "RPi GPIO bitbang"
+ depends on ARCH_BCM2835 || COMPILE_TEST
+ select GPIB_COMMON
+ help
+ GPIB bitbang driver Raspberry Pi GPIO adapters
+
+ To compile this driver as a module, choose M here: the module will be
+ called gpib_bitbang
+
+config GPIB_HP82335
+ tristate "HP82335/HP27209"
+ depends on ISA_BUS
+ select GPIB_COMMON
+ select GPIB_TMS9914
+ help
+ GPIB driver for HP82335 and HP27209 boards
+
+ To compile this driver as a module, choose M here: the module will be
+ called hp82335
+
+
+config GPIB_HP82341
+ tristate "HP82341x"
+ select GPIB_COMMON
+ select GPIB_TMS9914
+ depends on BROKEN
+ depends on ISA_BUS || EISA
+ help
+ GPIB driver for HP82341 A/B/C/D boards
+
+ To compile this driver as a module, choose M here: the module will be
+ called hp82341
+
+config GPIB_INES
+ tristate "INES"
+ depends on PCI || ISA_BUS || PCMCIA
+ depends on HAS_IOPORT
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ help
+ GPIB driver for Ines compatible boards
+ Ines
+ GPIB-HS-NT
+ GPIB for Compact PCI
+ GPIB for PCI
+ GPIB for PCMCIA
+ GPIB PC/104
+ Hameg
+ HO80-2
+ Quancom
+ PCIGPIB-1 based on Ines iGPIB 72010 chip
+
+ To compile this driver as a module, choose M here: the module will be
+ called ines_gpib
+ called cb7210.
+
+config GPIB_PCMCIA
+ bool "PCMCIA/Cardbus support for NI MC and Ines boards"
+ depends on PCCARD && (GPIB_NI_PCI_ISA || GPIB_CB7210 || GPIB_INES)
+ help
+ Enable PCMCIA/CArdbus support for National Instruments,
+ measurement computing boards and Ines boards.
+
+config GPIB_LPVO
+ tristate "LPVO DIY USB GPIB"
+ select GPIB_COMMON
+ depends on USB
+ help
+ Enable support for LPVO Self-made usb-gpib adapter
+
+ To compile this driver as a module, choose M here: the module will be
+ called lpvo_usb_gpib
+
+config GPIB_PC2
+ tristate "PC2 PC2a"
+ depends on ISA_BUS
+ depends on HAS_IOPORT
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ help
+ Enable support for pc2 and pc2a compatible adapters
+ Capital Equipment Corporation PC-488
+ CONTEC GP-IB(PC)
+ Hameg HO80
+ Iotech GP488B
+ Keithly MBC-488
+ Measurement Computing ISA-GPIB-PCA2
+ National Instruments PCII, PCIIa and PCII/IIa
+
+ To compile this driver as a module, choose M here: the module will be
+ called pc2_gpib
+
+
+config GPIB_TMS9914
+ tristate
+ select GPIB_COMMON
+ help
+ Enable support for TMS 9914 chip.
+
+ To compile this driver as a module, choose M here: the module will be
+ called tms9914
+
+config GPIB_NEC7210
+ tristate
+ select GPIB_COMMON
+ help
+ Enable support for NEC 7210 compatible chips.
+
+ To compile this driver as a module, choose M here: the module will be
+ called nec7210
+
+endif # GPIB
diff --git a/drivers/staging/gpib/Makefile b/drivers/staging/gpib/Makefile
new file mode 100644
index 000000000000..d0e88f5c0844
--- /dev/null
+++ b/drivers/staging/gpib/Makefile
@@ -0,0 +1,20 @@
+
+subdir-ccflags-y += -I$(src)/include -I$(src)/uapi
+
+obj-$(CONFIG_GPIB_AGILENT_82350B) += agilent_82350b/
+obj-$(CONFIG_GPIB_AGILENT_82357A) += agilent_82357a/
+obj-$(CONFIG_GPIB_CB7210) += cb7210/
+obj-$(CONFIG_GPIB_CEC_PCI) += cec/
+obj-$(CONFIG_GPIB_COMMON) += common/
+obj-$(CONFIG_GPIB_FLUKE) += eastwood/
+obj-$(CONFIG_GPIB_FMH) += fmh_gpib/
+obj-$(CONFIG_GPIB_GPIO) += gpio/
+obj-$(CONFIG_GPIB_HP82335) += hp_82335/
+obj-$(CONFIG_GPIB_HP82341) += hp_82341/
+obj-$(CONFIG_GPIB_INES) += ines/
+obj-$(CONFIG_GPIB_LPVO) += lpvo_usb_gpib/
+obj-$(CONFIG_GPIB_NEC7210) += nec7210/
+obj-$(CONFIG_GPIB_NI_USB) += ni_usb/
+obj-$(CONFIG_GPIB_PC2) += pc2/
+obj-$(CONFIG_GPIB_TMS9914) += tms9914/
+obj-$(CONFIG_GPIB_NI_PCI_ISA) += tnt4882/
diff --git a/drivers/staging/gpib/TODO b/drivers/staging/gpib/TODO
new file mode 100644
index 000000000000..bf2c39742548
--- /dev/null
+++ b/drivers/staging/gpib/TODO
@@ -0,0 +1,21 @@
+TODO:
+- checkpatch.pl fixes
+- fix device drivers that are broken ("depends on BROKEN" in Kconfig)
+- tidy-up comments:
+ - there are some "//comments" and "// comments" scattered around
+ - sometimes they are misaligned
+ - sometimes "// comments" are interleaved with "/* comments */"
+ - multiline comments should start with initial almost-blank line:
+ /*
+ * Good
+ * multiline
+ * comment
+ */
+ /* Bad
+ * multiline
+ * comment
+ */
+- resolve XXX notes where possible
+- fix FIXME notes
+- clean-up commented-out code
+- fix typos
diff --git a/drivers/staging/gpib/agilent_82350b/Makefile b/drivers/staging/gpib/agilent_82350b/Makefile
new file mode 100644
index 000000000000..d9236c92e04b
--- /dev/null
+++ b/drivers/staging/gpib/agilent_82350b/Makefile
@@ -0,0 +1,2 @@
+
+obj-m += agilent_82350b.o
diff --git a/drivers/staging/gpib/agilent_82350b/agilent_82350b.c b/drivers/staging/gpib/agilent_82350b/agilent_82350b.c
new file mode 100644
index 000000000000..53006d0cc79c
--- /dev/null
+++ b/drivers/staging/gpib/agilent_82350b/agilent_82350b.c
@@ -0,0 +1,932 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2002, 2004 by Frank Mori Hess *
+ ***************************************************************************/
+
+#include "agilent_82350b.h"
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/dma.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for Agilent 82350b");
+
+int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ struct tms9914_priv *tms_priv = &a_priv->tms9914_priv;
+ int retval = 0;
+ unsigned short event_status;
+ int i, num_fifo_bytes;
+ //hardware doesn't support checking for end-of-string character when using fifo
+ if (tms_priv->eos_flags & REOS) {
+ //pr_info("ag-rd: using tms9914 read for REOS %x EOS %x\n",tms_priv->eos_flags,
+ // tms_priv->eos);
+ return tms9914_read(board, tms_priv, buffer, length, end, bytes_read);
+ }
+
+ clear_bit(DEV_CLEAR_BN, &tms_priv->state);
+
+ read_and_clear_event_status(board);
+ *end = 0;
+ *bytes_read = 0;
+ if (length == 0)
+ return 0;
+ //disable fifo for the moment
+ writeb(DIRECTION_GPIB_TO_HOST, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+ // handle corner case of board not in holdoff and one byte might slip in early
+ if (tms_priv->holdoff_active == 0 && length > 1) {
+ size_t num_bytes;
+
+ retval = tms9914_read(board, tms_priv, buffer, 1, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ dev_err(board->gpib_dev, "%s: tms9914_read failed retval=%i\n",
+ driver_name, retval);
+ if (retval < 0 || *end)
+ return retval;
+ ++buffer;
+ --length;
+ }
+ tms9914_set_holdoff_mode(tms_priv, TMS9914_HOLDOFF_EOI);
+ tms9914_release_holdoff(tms_priv);
+ i = 0;
+ num_fifo_bytes = length - 1;
+ write_byte(tms_priv, tms_priv->imr0_bits & ~HR_BIIE, IMR0); // disable BI interrupts
+ while (i < num_fifo_bytes && *end == 0) {
+ int block_size;
+ int j;
+ int count;
+
+ if (num_fifo_bytes - i < agilent_82350b_fifo_size)
+ block_size = num_fifo_bytes - i;
+ else
+ block_size = agilent_82350b_fifo_size;
+ set_transfer_counter(a_priv, block_size);
+ writeb(ENABLE_TI_TO_SRAM | DIRECTION_GPIB_TO_HOST,
+ a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+ if (agilent_82350b_fifo_is_halted(a_priv))
+ writeb(RESTART_STREAM_BIT, a_priv->gpib_base + STREAM_STATUS_REG);
+
+ clear_bit(READ_READY_BN, &tms_priv->state);
+
+ retval = wait_event_interruptible(board->wait,
+ ((event_status =
+ read_and_clear_event_status(board)) &
+ (TERM_COUNT_STATUS_BIT |
+ BUFFER_END_STATUS_BIT)) ||
+ test_bit(DEV_CLEAR_BN, &tms_priv->state) ||
+ test_bit(TIMO_NUM, &board->status));
+ if (retval) {
+ dev_dbg(board->gpib_dev, "%s: read wait interrupted\n", driver_name);
+ retval = -ERESTARTSYS;
+ break;
+ }
+ count = block_size - read_transfer_counter(a_priv);
+ for (j = 0; j < count && i < num_fifo_bytes; ++j)
+ buffer[i++] = readb(a_priv->sram_base + j);
+ if (event_status & BUFFER_END_STATUS_BIT) {
+ clear_bit(RECEIVED_END_BN, &tms_priv->state);
+
+ tms_priv->holdoff_active = 1;
+ *end = 1;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ dev_err(board->gpib_dev, "%s: read timed out\n", driver_name);
+ retval = -ETIMEDOUT;
+ break;
+ }
+ if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) {
+ dev_err(board->gpib_dev, "%s: device clear interrupted read\n",
+ driver_name);
+ retval = -EINTR;
+ break;
+ }
+ }
+ write_byte(tms_priv, tms_priv->imr0_bits, IMR0); // re-enable BI interrupts
+ *bytes_read += i;
+ buffer += i;
+ length -= i;
+ writeb(DIRECTION_GPIB_TO_HOST, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+ if (retval < 0)
+ return retval;
+ // read last bytes if we havn't received an END yet
+ if (*end == 0) {
+ size_t num_bytes;
+ // try to make sure we holdoff after last byte read
+ retval = tms9914_read(board, tms_priv, buffer, length, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+
+static int translate_wait_return_value(gpib_board_t *board, int retval)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ struct tms9914_priv *tms_priv = &a_priv->tms9914_priv;
+
+ if (retval) {
+ dev_err(board->gpib_dev, "%s: write wait interrupted\n", driver_name);
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ dev_err(board->gpib_dev, "%s: write timed out\n", driver_name);
+ return -ETIMEDOUT;
+ }
+ if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) {
+ dev_err(board->gpib_dev, "%s: device clear interrupted write\n", driver_name);
+ return -EINTR;
+ }
+ return 0;
+}
+
+int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ struct tms9914_priv *tms_priv = &a_priv->tms9914_priv;
+ int i, j;
+ unsigned short event_status;
+ int retval = 0;
+ int fifotransferlength = length;
+ int block_size = 0;
+ size_t num_bytes;
+
+ *bytes_written = 0;
+ if (send_eoi)
+ --fifotransferlength;
+
+ clear_bit(DEV_CLEAR_BN, &tms_priv->state);
+
+ writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+
+ event_status = read_and_clear_event_status(board);
+
+ //pr_info("ag_ac_wr: event status 0x%x tms state 0x%lx\n", event_status, tms_priv->state);
+
+#ifdef EXPERIMENTAL
+ pr_info("ag_ac_wr: wait for previous BO to complete if any\n");
+ retval = wait_event_interruptible(board->wait,
+ test_bit(DEV_CLEAR_BN, &tms_priv->state) ||
+ test_bit(WRITE_READY_BN, &tms_priv->state) ||
+ test_bit(TIMO_NUM, &board->status));
+ retval = translate_wait_return_value(board, retval);
+
+ if (retval)
+ return retval;
+#endif
+
+ //pr_info("ag_ac_wr: sending first byte\n");
+ retval = agilent_82350b_write(board, buffer, 1, 0, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+
+ //pr_info("ag_ac_wr: %ld bytes eoi %d tms state 0x%lx\n",length, send_eoi, tms_priv->state);
+
+ write_byte(tms_priv, tms_priv->imr0_bits & ~HR_BOIE, IMR0);
+ for (i = 1; i < fifotransferlength;) {
+ clear_bit(WRITE_READY_BN, &tms_priv->state);
+
+ if (fifotransferlength - i < agilent_82350b_fifo_size)
+ block_size = fifotransferlength - i;
+ else
+ block_size = agilent_82350b_fifo_size;
+ set_transfer_counter(a_priv, block_size);
+ for (j = 0; j < block_size; ++j, ++i) {
+ // load data into board's sram
+ writeb(buffer[i], a_priv->sram_base + j);
+ }
+ writeb(ENABLE_TI_TO_SRAM, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+
+ //pr_info("ag_ac_wr: send block: %d bytes tms 0x%lx\n", block_size,
+ // tms_priv->state);
+
+ if (agilent_82350b_fifo_is_halted(a_priv)) {
+ writeb(RESTART_STREAM_BIT, a_priv->gpib_base + STREAM_STATUS_REG);
+ // pr_info("ag_ac_wr: needed restart\n");
+ }
+
+ retval = wait_event_interruptible(board->wait,
+ ((event_status =
+ read_and_clear_event_status(board)) &
+ TERM_COUNT_STATUS_BIT) ||
+ test_bit(DEV_CLEAR_BN, &tms_priv->state) ||
+ test_bit(TIMO_NUM, &board->status));
+ writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+ num_bytes = block_size - read_transfer_counter(a_priv);
+ //pr_info("ag_ac_wr: sent %ld bytes tms 0x%lx\n", num_bytes, tms_priv->state);
+
+ *bytes_written += num_bytes;
+ retval = translate_wait_return_value(board, retval);
+ if (retval)
+ break;
+ }
+ write_byte(tms_priv, tms_priv->imr0_bits, IMR0);
+ if (retval)
+ return retval;
+
+ if (send_eoi) {
+ //pr_info("ag_ac_wr: sending last byte with eoi byte no: %d\n",
+ // fifotransferlength+1);
+
+ retval = agilent_82350b_write(board, buffer + fifotransferlength, 1, send_eoi,
+ &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+
+unsigned short read_and_clear_event_status(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ unsigned long flags;
+ unsigned short status;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ status = a_priv->event_status_bits;
+ a_priv->event_status_bits = 0;
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return status;
+}
+
+irqreturn_t agilent_82350b_interrupt(int irq, void *arg)
+
+{
+ int tms9914_status1 = 0, tms9914_status2 = 0;
+ int event_status;
+ gpib_board_t *board = arg;
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ unsigned long flags;
+ irqreturn_t retval = IRQ_NONE;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ event_status = readb(a_priv->gpib_base + EVENT_STATUS_REG);
+ if (event_status & IRQ_STATUS_BIT)
+ retval = IRQ_HANDLED;
+
+ if (event_status & TMS9914_IRQ_STATUS_BIT) {
+ tms9914_status1 = read_byte(&a_priv->tms9914_priv, ISR0);
+ tms9914_status2 = read_byte(&a_priv->tms9914_priv, ISR1);
+ tms9914_interrupt_have_status(board, &a_priv->tms9914_priv, tms9914_status1,
+ tms9914_status2);
+ }
+//pr_info("event_status=0x%x s1 %x s2 %x\n", event_status,tms9914_status1,tms9914_status2);
+//write-clear status bits
+ if (event_status & (BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT)) {
+ writeb(event_status & (BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT),
+ a_priv->gpib_base + EVENT_STATUS_REG);
+ a_priv->event_status_bits |= event_status;
+ wake_up_interruptible(&board->wait);
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+void agilent_82350b_detach(gpib_board_t *board);
+
+const char *driver_name = "agilent_82350b";
+
+int read_transfer_counter(struct agilent_82350b_priv *a_priv)
+
+{
+ int lo, mid, value;
+
+ lo = readb(a_priv->gpib_base + XFER_COUNT_LO_REG);
+ mid = readb(a_priv->gpib_base + XFER_COUNT_MID_REG);
+ value = (lo & 0xff) | ((mid << 8) & 0x7f00);
+ value = ~(value - 1) & 0x7fff;
+ return value;
+}
+
+void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count)
+
+{
+ int complement = -count;
+
+ writeb(complement & 0xff, a_priv->gpib_base + XFER_COUNT_LO_REG);
+ writeb((complement >> 8) & 0xff, a_priv->gpib_base + XFER_COUNT_MID_REG);
+ //I don't think the hi count reg is even used, but oh well
+ writeb((complement >> 16) & 0xf, a_priv->gpib_base + XFER_COUNT_HI_REG);
+}
+
+// wrappers for interface functions
+int agilent_82350b_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read);
+}
+
+int agilent_82350b_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int agilent_82350b_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written);
+}
+
+int agilent_82350b_take_control(gpib_board_t *board, int synchronous)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_take_control_workaround(board, &priv->tms9914_priv, synchronous);
+}
+
+int agilent_82350b_go_to_standby(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_go_to_standby(board, &priv->tms9914_priv);
+}
+
+void agilent_82350b_request_system_control(gpib_board_t *board, int request_control)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+
+ if (request_control) {
+ a_priv->card_mode_bits |= CM_SYSTEM_CONTROLLER_BIT;
+ if (a_priv->model != MODEL_82350A)
+ writeb(IC_SYSTEM_CONTROLLER_BIT, a_priv->gpib_base + INTERNAL_CONFIG_REG);
+ } else {
+ a_priv->card_mode_bits &= ~CM_SYSTEM_CONTROLLER_BIT;
+ if (a_priv->model != MODEL_82350A)
+ writeb(0, a_priv->gpib_base + INTERNAL_CONFIG_REG);
+ }
+ writeb(a_priv->card_mode_bits, a_priv->gpib_base + CARD_MODE_REG);
+ tms9914_request_system_control(board, &a_priv->tms9914_priv, request_control);
+}
+
+void agilent_82350b_interface_clear(gpib_board_t *board, int assert)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_interface_clear(board, &priv->tms9914_priv, assert);
+}
+
+void agilent_82350b_remote_enable(gpib_board_t *board, int enable)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_remote_enable(board, &priv->tms9914_priv, enable);
+}
+
+int agilent_82350b_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits);
+}
+
+void agilent_82350b_disable_eos(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_disable_eos(board, &priv->tms9914_priv);
+}
+
+unsigned int agilent_82350b_update_status(gpib_board_t *board, unsigned int clear_mask)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_update_status(board, &priv->tms9914_priv, clear_mask);
+}
+
+int agilent_82350b_primary_address(gpib_board_t *board, unsigned int address)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_primary_address(board, &priv->tms9914_priv, address);
+}
+
+int agilent_82350b_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable);
+}
+
+int agilent_82350b_parallel_poll(gpib_board_t *board, uint8_t *result)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_parallel_poll(board, &priv->tms9914_priv, result);
+}
+
+void agilent_82350b_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config);
+}
+
+void agilent_82350b_parallel_poll_response(gpib_board_t *board, int ist)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist);
+}
+
+void agilent_82350b_serial_poll_response(gpib_board_t *board, uint8_t status)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_serial_poll_response(board, &priv->tms9914_priv, status);
+}
+
+uint8_t agilent_82350b_serial_poll_status(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_serial_poll_status(board, &priv->tms9914_priv);
+}
+
+int agilent_82350b_line_status(const gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_line_status(board, &priv->tms9914_priv);
+}
+
+unsigned int agilent_82350b_t1_delay(gpib_board_t *board, unsigned int nanosec)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ static const int nanosec_per_clock = 30;
+ unsigned int value;
+
+ tms9914_t1_delay(board, &a_priv->tms9914_priv, nanosec);
+
+ value = (nanosec + nanosec_per_clock - 1) / nanosec_per_clock;
+ if (value > 0xff)
+ value = 0xff;
+ writeb(value, a_priv->gpib_base + T1_DELAY_REG);
+ return value * nanosec_per_clock;
+}
+
+void agilent_82350b_return_to_local(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_return_to_local(board, &priv->tms9914_priv);
+}
+
+int agilent_82350b_allocate_private(gpib_board_t *board)
+
+{
+ board->private_data = kzalloc(sizeof(struct agilent_82350b_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+ return 0;
+}
+
+void agilent_82350b_free_private(gpib_board_t *board)
+
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+static int init_82350a_hardware(gpib_board_t *board, const gpib_board_config_t *config)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ static const unsigned int firmware_length = 5302;
+ unsigned int borg_status;
+ static const unsigned int timeout = 1000;
+ int i, j;
+ const char *firmware_data = config->init_data;
+ const unsigned int plx_cntrl_static_bits = PLX9050_WAITO_NOT_USER0_SELECT_BIT |
+ PLX9050_USER0_OUTPUT_BIT |
+ PLX9050_LLOCK_NOT_USER1_SELECT_BIT |
+ PLX9050_USER1_OUTPUT_BIT |
+ PLX9050_USER2_OUTPUT_BIT |
+ PLX9050_USER3_OUTPUT_BIT |
+ PLX9050_PCI_READ_MODE_BIT |
+ PLX9050_PCI_WRITE_MODE_BIT |
+ PLX9050_PCI_RETRY_DELAY_BITS(64) |
+ PLX9050_DIRECT_SLAVE_LOCK_ENABLE_BIT;
+
+// load borg data
+ borg_status = readb(a_priv->borg_base);
+ if ((borg_status & BORG_DONE_BIT))
+ return 0;
+ // need to programme borg
+ if (!config->init_data || config->init_data_length != firmware_length) {
+ dev_err(board->gpib_dev, "%s: the 82350A board requires firmware after powering on.\n",
+ driver_name);
+ return -EIO;
+ }
+ dev_info(board->gpib_dev, "%s: Loading firmware...\n", driver_name);
+
+ // tickle the borg
+ writel(plx_cntrl_static_bits | PLX9050_USER3_DATA_BIT,
+ a_priv->plx_base + PLX9050_CNTRL_REG);
+ usleep_range(1000, 2000);
+ writel(plx_cntrl_static_bits, a_priv->plx_base + PLX9050_CNTRL_REG);
+ usleep_range(1000, 2000);
+ writel(plx_cntrl_static_bits | PLX9050_USER3_DATA_BIT,
+ a_priv->plx_base + PLX9050_CNTRL_REG);
+ usleep_range(1000, 2000);
+
+ for (i = 0; i < config->init_data_length; ++i) {
+ for (j = 0; j < timeout && (readb(a_priv->borg_base) & BORG_READY_BIT) == 0; ++j) {
+ if (need_resched())
+ schedule();
+ usleep_range(10, 20);
+ }
+ if (j == timeout) {
+ dev_err(board->gpib_dev, "%s: timed out loading firmware.\n", driver_name);
+ return -ETIMEDOUT;
+ }
+ writeb(firmware_data[i], a_priv->gpib_base + CONFIG_DATA_REG);
+ }
+ for (j = 0; j < timeout && (readb(a_priv->borg_base) & BORG_DONE_BIT) == 0; ++j) {
+ if (need_resched())
+ schedule();
+ usleep_range(10, 20);
+ }
+ if (j == timeout) {
+ dev_err(board->gpib_dev, "%s: timed out waiting for firmware load to complete.\n",
+ driver_name);
+ return -ETIMEDOUT;
+ }
+ dev_info(board->gpib_dev, "%s: ...done.\n", driver_name);
+ return 0;
+}
+
+static int test_sram(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ unsigned int i;
+ const unsigned int sram_length = pci_resource_len(a_priv->pci_device, SRAM_82350A_REGION);
+ // test SRAM
+ const unsigned int byte_mask = 0xff;
+
+ for (i = 0; i < sram_length; ++i) {
+ writeb(i & byte_mask, a_priv->sram_base + i);
+ if (need_resched())
+ schedule();
+ }
+ for (i = 0; i < sram_length; ++i) {
+ unsigned int read_value = readb(a_priv->sram_base + i);
+
+ if ((i & byte_mask) != read_value) {
+ dev_err(board->gpib_dev, "%s: SRAM test failed at %d wanted %d got %d\n",
+ driver_name, i, (i & byte_mask), read_value);
+ return -EIO;
+ }
+ if (need_resched())
+ schedule();
+ }
+ dev_info(board->gpib_dev, "%s: SRAM test passed 0x%x bytes checked\n",
+ driver_name, sram_length);
+ return 0;
+}
+
+static int agilent_82350b_generic_attach(gpib_board_t *board, const gpib_board_config_t *config,
+ int use_fifos)
+
+{
+ struct agilent_82350b_priv *a_priv;
+ struct tms9914_priv *tms_priv;
+ int retval;
+
+ board->status = 0;
+
+ if (agilent_82350b_allocate_private(board))
+ return -ENOMEM;
+ a_priv = board->private_data;
+ a_priv->using_fifos = use_fifos;
+ tms_priv = &a_priv->tms9914_priv;
+ tms_priv->read_byte = tms9914_iomem_read_byte;
+ tms_priv->write_byte = tms9914_iomem_write_byte;
+ tms_priv->offset = 1;
+
+ // find board
+ a_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_AGILENT,
+ PCI_DEVICE_ID_82350B, NULL);
+ if (a_priv->pci_device) {
+ a_priv->model = MODEL_82350B;
+ dev_info(board->gpib_dev, "%s: Agilent 82350B board found\n", driver_name);
+
+ } else {
+ a_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_AGILENT,
+ PCI_DEVICE_ID_82351A, NULL);
+ if (a_priv->pci_device) {
+ a_priv->model = MODEL_82351A;
+ dev_info(board->gpib_dev, "%s: Agilent 82351B board found\n", driver_name);
+
+ } else {
+ a_priv->pci_device = gpib_pci_get_subsys(config, PCI_VENDOR_ID_PLX,
+ PCI_DEVICE_ID_PLX_9050,
+ PCI_VENDOR_ID_HP,
+ PCI_SUBDEVICE_ID_82350A,
+ a_priv->pci_device);
+ if (a_priv->pci_device) {
+ a_priv->model = MODEL_82350A;
+ dev_info(board->gpib_dev, "%s: HP/Agilent 82350A board found\n",
+ driver_name);
+ } else {
+ dev_err(board->gpib_dev, "%s: no 82350/82351 board found\n",
+ driver_name);
+ return -ENODEV;
+ }
+ }
+ }
+ if (pci_enable_device(a_priv->pci_device)) {
+ dev_err(board->gpib_dev, "%s: error enabling pci device\n", driver_name);
+ return -EIO;
+ }
+ if (pci_request_regions(a_priv->pci_device, driver_name))
+ return -EIO;
+ switch (a_priv->model) {
+ case MODEL_82350A:
+ a_priv->plx_base = ioremap(pci_resource_start(a_priv->pci_device, PLX_MEM_REGION),
+ pci_resource_len(a_priv->pci_device, PLX_MEM_REGION));
+ dev_dbg(board->gpib_dev, "%s: plx base address remapped to 0x%p\n",
+ driver_name, a_priv->plx_base);
+ a_priv->gpib_base = ioremap(pci_resource_start(a_priv->pci_device,
+ GPIB_82350A_REGION),
+ pci_resource_len(a_priv->pci_device,
+ GPIB_82350A_REGION));
+ dev_dbg(board->gpib_dev, "%s: gpib base address remapped to 0x%p\n",
+ driver_name, a_priv->gpib_base);
+ tms_priv->iobase = a_priv->gpib_base + TMS9914_BASE_REG;
+ a_priv->sram_base = ioremap(pci_resource_start(a_priv->pci_device,
+ SRAM_82350A_REGION),
+ pci_resource_len(a_priv->pci_device,
+ SRAM_82350A_REGION));
+ dev_dbg(board->gpib_dev, "%s: sram base address remapped to 0x%p\n",
+ driver_name, a_priv->sram_base);
+ a_priv->borg_base = ioremap(pci_resource_start(a_priv->pci_device,
+ BORG_82350A_REGION),
+ pci_resource_len(a_priv->pci_device,
+ BORG_82350A_REGION));
+ dev_dbg(board->gpib_dev, "%s: borg base address remapped to 0x%p\n",
+ driver_name, a_priv->borg_base);
+
+ retval = init_82350a_hardware(board, config);
+ if (retval < 0)
+ return retval;
+ break;
+ case MODEL_82350B:
+ case MODEL_82351A:
+ a_priv->gpib_base = ioremap(pci_resource_start(a_priv->pci_device, GPIB_REGION),
+ pci_resource_len(a_priv->pci_device, GPIB_REGION));
+ dev_dbg(board->gpib_dev, "%s: gpib base address remapped to 0x%p\n",
+ driver_name, a_priv->gpib_base);
+ tms_priv->iobase = a_priv->gpib_base + TMS9914_BASE_REG;
+ a_priv->sram_base = ioremap(pci_resource_start(a_priv->pci_device, SRAM_REGION),
+ pci_resource_len(a_priv->pci_device, SRAM_REGION));
+ dev_dbg(board->gpib_dev, "%s: sram base address remapped to 0x%p\n",
+ driver_name, a_priv->sram_base);
+ a_priv->misc_base = ioremap(pci_resource_start(a_priv->pci_device, MISC_REGION),
+ pci_resource_len(a_priv->pci_device, MISC_REGION));
+ dev_dbg(board->gpib_dev, "%s: misc base address remapped to 0x%p\n",
+ driver_name, a_priv->misc_base);
+ break;
+ default:
+ pr_err("%s: invalid board\n", driver_name);
+ return -1;
+ }
+
+ retval = test_sram(board);
+ if (retval < 0)
+ return retval;
+
+ if (request_irq(a_priv->pci_device->irq, agilent_82350b_interrupt,
+ IRQF_SHARED, driver_name, board)) {
+ pr_err("%s: can't request IRQ %d\n", driver_name, a_priv->pci_device->irq);
+ return -EIO;
+ }
+ a_priv->irq = a_priv->pci_device->irq;
+ dev_dbg(board->gpib_dev, "%s: IRQ %d\n", driver_name, a_priv->irq);
+
+ writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+ a_priv->card_mode_bits = ENABLE_PCI_IRQ_BIT;
+ writeb(a_priv->card_mode_bits, a_priv->gpib_base + CARD_MODE_REG);
+
+ if (a_priv->model == MODEL_82350A) {
+ // enable PCI interrupts for 82350a
+ writel(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR2_POLARITY_BIT |
+ PLX9050_PCI_INTR_EN_BIT,
+ a_priv->plx_base + PLX9050_INTCSR_REG);
+ }
+
+ if (use_fifos) {
+ writeb(ENABLE_BUFFER_END_EVENTS_BIT | ENABLE_TERM_COUNT_EVENTS_BIT,
+ a_priv->gpib_base + EVENT_ENABLE_REG);
+ writeb(ENABLE_TERM_COUNT_INTERRUPT_BIT | ENABLE_BUFFER_END_INTERRUPT_BIT |
+ ENABLE_TMS9914_INTERRUPTS_BIT, a_priv->gpib_base + INTERRUPT_ENABLE_REG);
+ //write-clear event status bits
+ writeb(BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT,
+ a_priv->gpib_base + EVENT_STATUS_REG);
+ } else {
+ writeb(0, a_priv->gpib_base + EVENT_ENABLE_REG);
+ writeb(ENABLE_TMS9914_INTERRUPTS_BIT,
+ a_priv->gpib_base + INTERRUPT_ENABLE_REG);
+ }
+ board->t1_nano_sec = agilent_82350b_t1_delay(board, 2000);
+ tms9914_board_reset(tms_priv);
+
+ tms9914_online(board, tms_priv);
+
+ return 0;
+}
+
+int agilent_82350b_unaccel_attach(gpib_board_t *board, const gpib_board_config_t *config)
+
+{
+ return agilent_82350b_generic_attach(board, config, 0);
+}
+
+int agilent_82350b_accel_attach(gpib_board_t *board, const gpib_board_config_t *config)
+
+{
+ return agilent_82350b_generic_attach(board, config, 1);
+}
+
+void agilent_82350b_detach(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ struct tms9914_priv *tms_priv;
+
+ if (a_priv) {
+ if (a_priv->plx_base) // disable interrupts
+ writel(0, a_priv->plx_base + PLX9050_INTCSR_REG);
+
+ tms_priv = &a_priv->tms9914_priv;
+ if (a_priv->irq)
+ free_irq(a_priv->irq, board);
+ if (a_priv->gpib_base) {
+ tms9914_board_reset(tms_priv);
+ if (a_priv->misc_base)
+ iounmap((void *)a_priv->misc_base);
+ if (a_priv->borg_base)
+ iounmap((void *)a_priv->borg_base);
+ if (a_priv->sram_base)
+ iounmap((void *)a_priv->sram_base);
+ if (a_priv->gpib_base)
+ iounmap((void *)a_priv->gpib_base);
+ if (a_priv->plx_base)
+ iounmap((void *)a_priv->plx_base);
+ pci_release_regions(a_priv->pci_device);
+ }
+ if (a_priv->pci_device)
+ pci_dev_put(a_priv->pci_device);
+ }
+ agilent_82350b_free_private(board);
+}
+
+gpib_interface_t agilent_82350b_unaccel_interface = {
+name: "agilent_82350b_unaccel",
+attach : agilent_82350b_unaccel_attach,
+detach : agilent_82350b_detach,
+read : agilent_82350b_read,
+write : agilent_82350b_write,
+command : agilent_82350b_command,
+request_system_control : agilent_82350b_request_system_control,
+take_control : agilent_82350b_take_control,
+go_to_standby : agilent_82350b_go_to_standby,
+interface_clear : agilent_82350b_interface_clear,
+remote_enable : agilent_82350b_remote_enable,
+enable_eos : agilent_82350b_enable_eos,
+disable_eos : agilent_82350b_disable_eos,
+parallel_poll : agilent_82350b_parallel_poll,
+parallel_poll_configure : agilent_82350b_parallel_poll_configure,
+parallel_poll_response : agilent_82350b_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : agilent_82350b_line_status,
+update_status : agilent_82350b_update_status,
+primary_address : agilent_82350b_primary_address,
+secondary_address : agilent_82350b_secondary_address,
+serial_poll_response : agilent_82350b_serial_poll_response,
+t1_delay : agilent_82350b_t1_delay,
+return_to_local : agilent_82350b_return_to_local,
+};
+
+gpib_interface_t agilent_82350b_interface = {
+name: "agilent_82350b",
+attach : agilent_82350b_accel_attach,
+detach : agilent_82350b_detach,
+read : agilent_82350b_accel_read,
+write : agilent_82350b_accel_write,
+command : agilent_82350b_command,
+request_system_control : agilent_82350b_request_system_control,
+take_control : agilent_82350b_take_control,
+go_to_standby : agilent_82350b_go_to_standby,
+interface_clear : agilent_82350b_interface_clear,
+remote_enable : agilent_82350b_remote_enable,
+enable_eos : agilent_82350b_enable_eos,
+disable_eos : agilent_82350b_disable_eos,
+parallel_poll : agilent_82350b_parallel_poll,
+parallel_poll_configure : agilent_82350b_parallel_poll_configure,
+parallel_poll_response : agilent_82350b_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : agilent_82350b_line_status,
+update_status : agilent_82350b_update_status,
+primary_address : agilent_82350b_primary_address,
+secondary_address : agilent_82350b_secondary_address,
+serial_poll_response : agilent_82350b_serial_poll_response,
+t1_delay : agilent_82350b_t1_delay,
+return_to_local : agilent_82350b_return_to_local,
+};
+
+static int agilent_82350b_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+
+{
+ return 0;
+}
+
+static const struct pci_device_id agilent_82350b_pci_table[] = {
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_HP,
+ PCI_SUBDEVICE_ID_82350A, 0, 0, 0 },
+ { PCI_VENDOR_ID_AGILENT, PCI_DEVICE_ID_82350B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_AGILENT, PCI_DEVICE_ID_82351A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, agilent_82350b_pci_table);
+
+static struct pci_driver agilent_82350b_pci_driver = {
+ .name = "agilent_82350b",
+ .id_table = agilent_82350b_pci_table,
+ .probe = &agilent_82350b_pci_probe
+};
+
+static int __init agilent_82350b_init_module(void)
+
+{
+ int result;
+
+ result = pci_register_driver(&agilent_82350b_pci_driver);
+ if (result) {
+ pr_err("agilent_82350b: pci_driver_register failed!\n");
+ return result;
+ }
+
+ gpib_register_driver(&agilent_82350b_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&agilent_82350b_interface, THIS_MODULE);
+ return 0;
+}
+
+static void __exit agilent_82350b_exit_module(void)
+
+{
+ gpib_unregister_driver(&agilent_82350b_interface);
+ gpib_unregister_driver(&agilent_82350b_unaccel_interface);
+
+ pci_unregister_driver(&agilent_82350b_pci_driver);
+}
+
+module_init(agilent_82350b_init_module);
+module_exit(agilent_82350b_exit_module);
diff --git a/drivers/staging/gpib/agilent_82350b/agilent_82350b.h b/drivers/staging/gpib/agilent_82350b/agilent_82350b.h
new file mode 100644
index 000000000000..30683d67d170
--- /dev/null
+++ b/drivers/staging/gpib/agilent_82350b/agilent_82350b.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002, 2004 by Frank Mori Hess *
+ ***************************************************************************/
+
+#include "gpibP.h"
+#include "plx9050.h"
+#include "tms9914.h"
+
+enum pci_vendor_ids {
+ PCI_VENDOR_ID_AGILENT = 0x15bc,
+};
+
+enum pci_device_ids {
+ PCI_DEVICE_ID_82350B = 0x0b01,
+ PCI_DEVICE_ID_82351A = 0x1218
+};
+
+enum pci_subdevice_ids {
+ PCI_SUBDEVICE_ID_82350A = 0x10b0,
+};
+
+enum pci_regions_82350a {
+ PLX_MEM_REGION = 0,
+ PLX_IO_REGION = 1,
+ GPIB_82350A_REGION = 2,
+ SRAM_82350A_REGION = 3,
+ BORG_82350A_REGION = 4
+};
+
+enum pci_regions_82350b {
+ GPIB_REGION = 0,
+ SRAM_REGION = 1,
+ MISC_REGION = 2,
+};
+
+enum board_model {
+ MODEL_82350A,
+ MODEL_82350B,
+ MODEL_82351A
+};
+
+// struct which defines private_data for board
+struct agilent_82350b_priv {
+ struct tms9914_priv tms9914_priv;
+ struct pci_dev *pci_device;
+ void *plx_base; //82350a only
+ void *gpib_base;
+ void *sram_base;
+ void *misc_base;
+ void *borg_base;
+ int irq;
+ unsigned short card_mode_bits;
+ unsigned short event_status_bits;
+ enum board_model model;
+ bool using_fifos;
+};
+
+// driver name
+extern const char *driver_name;
+
+// interfaces
+extern gpib_interface_t agilent_82350b_interface;
+// init functions
+
+int agilent_82350b_unaccel_attach(gpib_board_t *board, const gpib_board_config_t *config);
+int agilent_82350b_accel_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+// interface functions
+int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read);
+int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written);
+int agilent_82350b_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read);
+int agilent_82350b_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written);
+int agilent_82350b_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written);
+int agilent_82350b_take_control(gpib_board_t *board, int synchronous);
+int agilent_82350b_go_to_standby(gpib_board_t *board);
+void agilent_82350b_request_system_control(gpib_board_t *board, int request_control);
+void agilent_82350b_interface_clear(gpib_board_t *board, int assert);
+void agilent_82350b_remote_enable(gpib_board_t *board, int enable);
+int agilent_82350b_enable_eos(gpib_board_t *board, uint8_t eos_byte, int
+ compare_8_bits);
+void agilent_82350b_disable_eos(gpib_board_t *board);
+unsigned int agilent_82350b_update_status(gpib_board_t *board, unsigned int clear_mask);
+int agilent_82350b_primary_address(gpib_board_t *board, unsigned int address);
+int agilent_82350b_secondary_address(gpib_board_t *board, unsigned int address, int
+ enable);
+int agilent_82350b_parallel_poll(gpib_board_t *board, uint8_t *result);
+void agilent_82350b_parallel_poll_configure(gpib_board_t *board, uint8_t config);
+void agilent_82350b_parallel_poll_response(gpib_board_t *board, int ist);
+void agilent_82350b_serial_poll_response(gpib_board_t *board, uint8_t status);
+void agilent_82350b_return_to_local(gpib_board_t *board);
+uint8_t agilent_82350b_serial_poll_status(gpib_board_t *board);
+int agilent_82350b_line_status(const gpib_board_t *board);
+unsigned int agilent_82350b_t1_delay(gpib_board_t *board, unsigned int nanosec);
+
+// interrupt service routines
+irqreturn_t agilent_82350b_interrupt(int irq, void *arg);
+
+// utility functions
+int agilent_82350b_allocate_private(gpib_board_t *board);
+void agilent_82350b_free_private(gpib_board_t *board);
+unsigned short read_and_clear_event_status(gpib_board_t *board);
+int read_transfer_counter(struct agilent_82350b_priv *a_priv);
+void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count);
+
+//registers
+enum agilent_82350b_gpib_registers
+
+{
+ CARD_MODE_REG = 0x1,
+ CONFIG_DATA_REG = 0x2, // 82350A specific
+ INTERRUPT_ENABLE_REG = 0x3,
+ EVENT_STATUS_REG = 0x4,
+ EVENT_ENABLE_REG = 0x5,
+ STREAM_STATUS_REG = 0x7,
+ DEBUG_RAM0_REG = 0x8,
+ DEBUG_RAM1_REG = 0x9,
+ DEBUG_RAM2_REG = 0xa,
+ DEBUG_RAM3_REG = 0xb,
+ XFER_COUNT_LO_REG = 0xc,
+ XFER_COUNT_MID_REG = 0xd,
+ XFER_COUNT_HI_REG = 0xe,
+ TMS9914_BASE_REG = 0x10,
+ INTERNAL_CONFIG_REG = 0x18,
+ IMR0_READ_REG = 0x19, //read
+ T1_DELAY_REG = 0x19, // write
+ IMR1_READ_REG = 0x1a,
+ ADR_READ_REG = 0x1b,
+ SPMR_READ_REG = 0x1c,
+ PPR_READ_REG = 0x1d,
+ CDOR_READ_REG = 0x1e,
+ SRAM_ACCESS_CONTROL_REG = 0x1f,
+};
+
+enum card_mode_bits
+
+{
+ ACTIVE_CONTROLLER_BIT = 0x2, // read-only
+ CM_SYSTEM_CONTROLLER_BIT = 0x8,
+ ENABLE_BUS_MONITOR_BIT = 0x10,
+ ENABLE_PCI_IRQ_BIT = 0x20,
+};
+
+enum interrupt_enable_bits
+
+{
+ ENABLE_TMS9914_INTERRUPTS_BIT = 0x1,
+ ENABLE_BUFFER_END_INTERRUPT_BIT = 0x10,
+ ENABLE_TERM_COUNT_INTERRUPT_BIT = 0x20,
+};
+
+enum event_enable_bits
+
+{
+ ENABLE_BUFFER_END_EVENTS_BIT = 0x10,
+ ENABLE_TERM_COUNT_EVENTS_BIT = 0x20,
+};
+
+enum event_status_bits
+
+{
+ TMS9914_IRQ_STATUS_BIT = 0x1,
+ IRQ_STATUS_BIT = 0x2,
+ BUFFER_END_STATUS_BIT = 0x10, // write-clear
+ TERM_COUNT_STATUS_BIT = 0x20, // write-clear
+};
+
+enum stream_status_bits
+
+{
+ HALTED_STATUS_BIT = 0x1, //read
+ RESTART_STREAM_BIT = 0x1, //write
+};
+
+enum internal_config_bits
+
+{
+ IC_SYSTEM_CONTROLLER_BIT = 0x80,
+};
+
+enum sram_access_control_bits
+
+{
+ DIRECTION_GPIB_TO_HOST = 0x20, // transfer direction
+ ENABLE_TI_TO_SRAM = 0x40, // enable fifo
+ ENABLE_FAST_TALKER = 0x80 // added for 82350A (not used)
+};
+
+enum borg_bits
+
+{
+ BORG_READY_BIT = 0x40,
+ BORG_DONE_BIT = 0x80
+};
+
+static const int agilent_82350b_fifo_size = 0x8000;
+
+static inline int agilent_82350b_fifo_is_halted(struct agilent_82350b_priv *a_priv)
+
+{
+ return readb(a_priv->gpib_base + STREAM_STATUS_REG) & HALTED_STATUS_BIT;
+}
+
diff --git a/drivers/staging/gpib/agilent_82357a/Makefile b/drivers/staging/gpib/agilent_82357a/Makefile
new file mode 100644
index 000000000000..4a1d940fce2b
--- /dev/null
+++ b/drivers/staging/gpib/agilent_82357a/Makefile
@@ -0,0 +1,4 @@
+
+obj-m += agilent_82357a.o
+
+
diff --git a/drivers/staging/gpib/agilent_82357a/agilent_82357a.c b/drivers/staging/gpib/agilent_82357a/agilent_82357a.c
new file mode 100644
index 000000000000..bf05fb4a736b
--- /dev/null
+++ b/drivers/staging/gpib/agilent_82357a/agilent_82357a.c
@@ -0,0 +1,1712 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * driver for Agilent 82357A/B usb to gpib adapters *
+ * copyright : (C) 2004 by Frank Mori Hess *
+ ***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "agilent_82357a.h"
+#include "gpibP.h"
+#include "tms9914.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for Agilent 82357A/B usb adapters");
+
+#define MAX_NUM_82357A_INTERFACES 128
+static struct usb_interface *agilent_82357a_driver_interfaces[MAX_NUM_82357A_INTERFACES];
+DEFINE_MUTEX(agilent_82357a_hotplug_lock); // protect board insertion and removal
+
+static unsigned int agilent_82357a_update_status(gpib_board_t *board, unsigned int clear_mask);
+
+static int agilent_82357a_take_control_internal(gpib_board_t *board, int synchronous);
+
+static void agilent_82357a_bulk_complete(struct urb *urb)
+{
+ struct agilent_82357a_urb_ctx *context = urb->context;
+
+ up(&context->complete);
+}
+
+static void agilent_82357a_timeout_handler(struct timer_list *t)
+{
+ struct agilent_82357a_priv *a_priv = from_timer(a_priv, t, bulk_timer);
+ struct agilent_82357a_urb_ctx *context = &a_priv->context;
+
+ context->timed_out = 1;
+ up(&context->complete);
+}
+
+static int agilent_82357a_send_bulk_msg(struct agilent_82357a_priv *a_priv, void *data,
+ int data_length, int *actual_data_length,
+ int timeout_msecs)
+{
+ struct usb_device *usb_dev;
+ int retval;
+ unsigned int out_pipe;
+ struct agilent_82357a_urb_ctx *context = &a_priv->context;
+
+ *actual_data_length = 0;
+ retval = mutex_lock_interruptible(&a_priv->bulk_alloc_lock);
+ if (retval)
+ return retval;
+ if (!a_priv->bus_interface) {
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return -ENODEV;
+ }
+ if (a_priv->bulk_urb) {
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return -EAGAIN;
+ }
+ a_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!a_priv->bulk_urb) {
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return -ENOMEM;
+ }
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ out_pipe = usb_sndbulkpipe(usb_dev, a_priv->bulk_out_endpoint);
+ sema_init(&context->complete, 0);
+ context->timed_out = 0;
+ usb_fill_bulk_urb(a_priv->bulk_urb, usb_dev, out_pipe, data, data_length,
+ &agilent_82357a_bulk_complete, context);
+
+ if (timeout_msecs)
+ mod_timer(&a_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs));
+
+ retval = usb_submit_urb(a_priv->bulk_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ goto cleanup;
+ }
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ if (down_interruptible(&context->complete)) {
+ dev_err(&usb_dev->dev, "%s: interrupted\n", __func__);
+ retval = -ERESTARTSYS;
+ goto cleanup;
+ }
+ if (context->timed_out) {
+ retval = -ETIMEDOUT;
+ } else {
+ retval = a_priv->bulk_urb->status;
+ *actual_data_length = a_priv->bulk_urb->actual_length;
+ }
+cleanup:
+ if (timeout_msecs) {
+ if (timer_pending(&a_priv->bulk_timer))
+ del_timer_sync(&a_priv->bulk_timer);
+ }
+ mutex_lock(&a_priv->bulk_alloc_lock);
+ if (a_priv->bulk_urb) {
+ usb_kill_urb(a_priv->bulk_urb);
+ usb_free_urb(a_priv->bulk_urb);
+ a_priv->bulk_urb = NULL;
+ }
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return retval;
+}
+
+static int agilent_82357a_receive_bulk_msg(struct agilent_82357a_priv *a_priv, void *data,
+ int data_length, int *actual_data_length,
+ int timeout_msecs)
+{
+ struct usb_device *usb_dev;
+ int retval;
+ unsigned int in_pipe;
+ struct agilent_82357a_urb_ctx *context = &a_priv->context;
+
+ *actual_data_length = 0;
+ retval = mutex_lock_interruptible(&a_priv->bulk_alloc_lock);
+ if (retval)
+ return retval;
+ if (!a_priv->bus_interface) {
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return -ENODEV;
+ }
+ if (a_priv->bulk_urb) {
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return -EAGAIN;
+ }
+ a_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!a_priv->bulk_urb) {
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return -ENOMEM;
+ }
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ in_pipe = usb_rcvbulkpipe(usb_dev, AGILENT_82357_BULK_IN_ENDPOINT);
+ sema_init(&context->complete, 0);
+ context->timed_out = 0;
+ usb_fill_bulk_urb(a_priv->bulk_urb, usb_dev, in_pipe, data, data_length,
+ &agilent_82357a_bulk_complete, context);
+
+ if (timeout_msecs)
+ mod_timer(&a_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs));
+
+ retval = usb_submit_urb(a_priv->bulk_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ goto cleanup;
+ }
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ if (down_interruptible(&context->complete)) {
+ dev_err(&usb_dev->dev, "%s: interrupted\n", __func__);
+ retval = -ERESTARTSYS;
+ goto cleanup;
+ }
+ if (context->timed_out) {
+ retval = -ETIMEDOUT;
+ goto cleanup;
+ }
+ retval = a_priv->bulk_urb->status;
+ *actual_data_length = a_priv->bulk_urb->actual_length;
+cleanup:
+ if (timeout_msecs)
+ del_timer_sync(&a_priv->bulk_timer);
+
+ mutex_lock(&a_priv->bulk_alloc_lock);
+ if (a_priv->bulk_urb) {
+ usb_kill_urb(a_priv->bulk_urb);
+ usb_free_urb(a_priv->bulk_urb);
+ a_priv->bulk_urb = NULL;
+ }
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return retval;
+}
+
+static int agilent_82357a_receive_control_msg(struct agilent_82357a_priv *a_priv, __u8 request,
+ __u8 requesttype, __u16 value, __u16 index,
+ void *data, __u16 size, int timeout_msecs)
+{
+ struct usb_device *usb_dev;
+ int retval;
+ unsigned int in_pipe;
+
+ retval = mutex_lock_interruptible(&a_priv->control_alloc_lock);
+ if (retval)
+ return retval;
+ if (!a_priv->bus_interface) {
+ mutex_unlock(&a_priv->control_alloc_lock);
+ return -ENODEV;
+ }
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ in_pipe = usb_rcvctrlpipe(usb_dev, AGILENT_82357_CONTROL_ENDPOINT);
+ retval = usb_control_msg(usb_dev, in_pipe, request, requesttype, value, index, data,
+ size, timeout_msecs);
+ mutex_unlock(&a_priv->control_alloc_lock);
+ return retval;
+}
+
+static void agilent_82357a_dump_raw_block(const u8 *raw_data, int length)
+{
+ pr_info("hex block dump\n");
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 8, 1, raw_data, length, true);
+}
+
+static int agilent_82357a_write_registers(struct agilent_82357a_priv *a_priv,
+ const struct agilent_82357a_register_pairlet *writes,
+ int num_writes)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ int retval;
+ u8 *out_data, *in_data;
+ int out_data_length, in_data_length;
+ int bytes_written, bytes_read;
+ int i = 0;
+ int j;
+ static const int bytes_per_write = 2;
+ static const int header_length = 2;
+ static const int max_writes = 31;
+
+ if (num_writes > max_writes) {
+ dev_err(&usb_dev->dev, "%s: bug! num_writes=%i too large\n", __func__, num_writes);
+ return -EIO;
+ }
+ out_data_length = num_writes * bytes_per_write + header_length;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+
+ out_data[i++] = DATA_PIPE_CMD_WR_REGS;
+ out_data[i++] = num_writes;
+ for (j = 0; j < num_writes; j++) {
+ out_data[i++] = writes[j].address;
+ out_data[i++] = writes[j].value;
+ }
+ if (i > out_data_length)
+ dev_err(&usb_dev->dev, "%s: bug! buffer overrun\n", __func__);
+ retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock);
+ if (retval) {
+ kfree(out_data);
+ return retval;
+ }
+ retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return retval;
+ }
+ in_data_length = 0x20;
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return -ENOMEM;
+ }
+ retval = agilent_82357a_receive_bulk_msg(a_priv, in_data, in_data_length,
+ &bytes_read, 1000);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ agilent_82357a_dump_raw_block(in_data, bytes_read);
+ kfree(in_data);
+ return -EIO;
+ }
+ if (in_data[0] != (0xff & ~DATA_PIPE_CMD_WR_REGS)) {
+ dev_err(&usb_dev->dev, "%s: error, bulk command=0x%x != ~DATA_PIPE_CMD_WR_REGS\n",
+ __func__, in_data[0]);
+ return -EIO;
+ }
+ if (in_data[1]) {
+ dev_err(&usb_dev->dev, "%s: nonzero error code 0x%x in DATA_PIPE_CMD_WR_REGS response\n",
+ __func__, in_data[1]);
+ return -EIO;
+ }
+ kfree(in_data);
+ return 0;
+}
+
+static int agilent_82357a_read_registers(struct agilent_82357a_priv *a_priv,
+ struct agilent_82357a_register_pairlet *reads,
+ int num_reads, int blocking)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ int retval;
+ u8 *out_data, *in_data;
+ int out_data_length, in_data_length;
+ int bytes_written, bytes_read;
+ int i = 0;
+ int j;
+ static const int header_length = 2;
+ static const int max_reads = 62;
+
+ if (num_reads > max_reads)
+ dev_err(&usb_dev->dev, "%s: bug! num_reads=%i too large\n", __func__, num_reads);
+
+ out_data_length = num_reads + header_length;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+
+ out_data[i++] = DATA_PIPE_CMD_RD_REGS;
+ out_data[i++] = num_reads;
+ for (j = 0; j < num_reads; j++)
+ out_data[i++] = reads[j].address;
+ if (i > out_data_length)
+ dev_err(&usb_dev->dev, "%s: bug! buffer overrun\n", __func__);
+ if (blocking) {
+ retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock);
+ if (retval) {
+ kfree(out_data);
+ return retval;
+ }
+ } else {
+ retval = mutex_trylock(&a_priv->bulk_transfer_lock);
+ if (retval == 0) {
+ kfree(out_data);
+ return -EAGAIN;
+ }
+ }
+ retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return retval;
+ }
+ in_data_length = 0x20;
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return -ENOMEM;
+ }
+ retval = agilent_82357a_receive_bulk_msg(a_priv, in_data, in_data_length,
+ &bytes_read, 10000);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ agilent_82357a_dump_raw_block(in_data, bytes_read);
+ kfree(in_data);
+ return -EIO;
+ }
+ i = 0;
+ if (in_data[i++] != (0xff & ~DATA_PIPE_CMD_RD_REGS)) {
+ dev_err(&usb_dev->dev, "%s: error, bulk command=0x%x != ~DATA_PIPE_CMD_RD_REGS\n",
+ __func__, in_data[0]);
+ return -EIO;
+ }
+ if (in_data[i++]) {
+ dev_err(&usb_dev->dev, "%s: nonzero error code 0x%x in DATA_PIPE_CMD_RD_REGS response\n",
+ __func__, in_data[1]);
+ return -EIO;
+ }
+ for (j = 0; j < num_reads; j++)
+ reads[j].value = in_data[i++];
+ kfree(in_data);
+ return 0;
+}
+
+static int agilent_82357a_abort(struct agilent_82357a_priv *a_priv, int flush)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ int retval = 0;
+ int receive_control_retval;
+ u16 wIndex = 0;
+ u8 *status_data;
+ static const unsigned int status_data_len = 2;
+
+ status_data = kmalloc(status_data_len, GFP_KERNEL);
+ if (!status_data)
+ return -ENOMEM;
+
+ if (flush)
+ wIndex |= XA_FLUSH;
+ receive_control_retval = agilent_82357a_receive_control_msg(a_priv,
+ agilent_82357a_control_request,
+ USB_DIR_IN | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE, XFER_ABORT,
+ wIndex, status_data,
+ status_data_len, 100);
+ if (receive_control_retval < 0) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_control_msg() returned %i\n",
+ __func__, receive_control_retval);
+ retval = -EIO;
+ goto cleanup;
+ }
+ if (status_data[0] != (~XFER_ABORT & 0xff)) {
+ dev_err(&usb_dev->dev, "%s: error, major code=0x%x != ~XFER_ABORT\n",
+ __func__, status_data[0]);
+ retval = -EIO;
+ goto cleanup;
+ }
+ switch (status_data[1]) {
+ case UGP_SUCCESS:
+ retval = 0;
+ break;
+ case UGP_ERR_FLUSHING:
+ if (flush) {
+ retval = 0;
+ break;
+ }
+ fallthrough;
+ case UGP_ERR_FLUSHING_ALREADY:
+ default:
+ dev_err(&usb_dev->dev, "%s: abort returned error code=0x%x\n",
+ __func__, status_data[1]);
+ retval = -EIO;
+ break;
+ }
+
+cleanup:
+ kfree(status_data);
+ return retval;
+}
+
+// interface functions
+int agilent_82357a_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written);
+
+static int agilent_82357a_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *nbytes)
+{
+ int retval;
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ u8 *out_data, *in_data;
+ int out_data_length, in_data_length;
+ int bytes_written, bytes_read;
+ int i = 0;
+ u8 trailing_flags;
+ unsigned long start_jiffies = jiffies;
+ int msec_timeout;
+
+ *nbytes = 0;
+ *end = 0;
+ out_data_length = 0x9;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+ out_data[i++] = DATA_PIPE_CMD_READ;
+ out_data[i++] = 0; //primary address when ARF_NO_ADDR is not set
+ out_data[i++] = 0; //secondary address when ARF_NO_ADDR is not set
+ out_data[i] = ARF_NO_ADDRESS | ARF_END_ON_EOI;
+ if (a_priv->eos_mode & REOS)
+ out_data[i] |= ARF_END_ON_EOS_CHAR;
+ ++i;
+ out_data[i++] = length & 0xff;
+ out_data[i++] = (length >> 8) & 0xff;
+ out_data[i++] = (length >> 16) & 0xff;
+ out_data[i++] = (length >> 24) & 0xff;
+ out_data[i++] = a_priv->eos_char;
+ msec_timeout = (board->usec_timeout + 999) / 1000;
+ retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock);
+ if (retval) {
+ kfree(out_data);
+ return retval;
+ }
+ retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, msec_timeout);
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ if (retval < 0)
+ return retval;
+ return -EIO;
+ }
+ in_data_length = length + 1;
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return -ENOMEM;
+ }
+ if (board->usec_timeout != 0)
+ msec_timeout -= jiffies_to_msecs(jiffies - start_jiffies) - 1;
+ if (msec_timeout >= 0) {
+ retval = agilent_82357a_receive_bulk_msg(a_priv, in_data, in_data_length,
+ &bytes_read, msec_timeout);
+ } else {
+ retval = -ETIMEDOUT;
+ bytes_read = 0;
+ }
+ if (retval == -ETIMEDOUT) {
+ int extra_bytes_read;
+ int extra_bytes_retval;
+
+ agilent_82357a_abort(a_priv, 1);
+ extra_bytes_retval = agilent_82357a_receive_bulk_msg(a_priv, in_data + bytes_read,
+ in_data_length - bytes_read,
+ &extra_bytes_read, 100);
+ bytes_read += extra_bytes_read;
+ if (extra_bytes_retval) {
+ dev_err(&usb_dev->dev, "%s: extra_bytes_retval=%i, bytes_read=%i\n",
+ __func__, extra_bytes_retval, bytes_read);
+ agilent_82357a_abort(a_priv, 0);
+ }
+ } else if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ agilent_82357a_abort(a_priv, 0);
+ }
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ if (bytes_read > length + 1) {
+ bytes_read = length + 1;
+ pr_warn("%s: bytes_read > length? truncating", __func__);
+ }
+
+ if (bytes_read >= 1) {
+ memcpy(buffer, in_data, bytes_read - 1);
+ trailing_flags = in_data[bytes_read - 1];
+ *nbytes = bytes_read - 1;
+ if (trailing_flags & (ATRF_EOI | ATRF_EOS))
+ *end = 1;
+ }
+ kfree(in_data);
+
+ /* Fix for a bug in 9914A that does not return the contents of ADSR
+ * when the board is in listener active state and ATN is not asserted.
+ * Set ATN here to obtain a valid board level ibsta
+ */
+ agilent_82357a_take_control_internal(board, 0);
+
+ //FIXME check trailing flags for error
+ return retval;
+}
+
+static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_commands, int send_eoi, size_t *bytes_written)
+{
+ int retval;
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ u8 *out_data = NULL;
+ u8 *status_data = NULL;
+ int out_data_length;
+ int raw_bytes_written;
+ int i = 0, j;
+ int msec_timeout;
+ unsigned short bsr, adsr;
+ struct agilent_82357a_register_pairlet read_reg;
+
+ *bytes_written = 0;
+ out_data_length = length + 0x8;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+ out_data[i++] = DATA_PIPE_CMD_WRITE;
+ out_data[i++] = 0; // primary address when AWF_NO_ADDRESS is not set
+ out_data[i++] = 0; // secondary address when AWF_NO_ADDRESS is not set
+ out_data[i] = AWF_NO_ADDRESS | AWF_NO_FAST_TALKER_FIRST_BYTE;
+ if (send_commands)
+ out_data[i] |= AWF_ATN | AWF_NO_FAST_TALKER;
+ if (send_eoi)
+ out_data[i] |= AWF_SEND_EOI;
+ ++i;
+ out_data[i++] = length & 0xff;
+ out_data[i++] = (length >> 8) & 0xff;
+ out_data[i++] = (length >> 16) & 0xff;
+ out_data[i++] = (length >> 24) & 0xff;
+ for (j = 0; j < length; j++)
+ out_data[i++] = buffer[j];
+
+ clear_bit(AIF_WRITE_COMPLETE_BN, &a_priv->interrupt_flags);
+
+ msec_timeout = (board->usec_timeout + 999) / 1000;
+ retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock);
+ if (retval) {
+ kfree(out_data);
+ return retval;
+ }
+ retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &raw_bytes_written,
+ msec_timeout);
+ kfree(out_data);
+ if (retval || raw_bytes_written != i) {
+ agilent_82357a_abort(a_priv, 0);
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, raw_bytes_written=%i, i=%i\n",
+ __func__, retval, raw_bytes_written, i);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ if (retval < 0)
+ return retval;
+ return -EIO;
+ }
+
+ retval = wait_event_interruptible(board->wait,
+ test_bit(AIF_WRITE_COMPLETE_BN,
+ &a_priv->interrupt_flags) ||
+ test_bit(TIMO_NUM, &board->status));
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: wait write complete interrupted\n", __func__);
+ agilent_82357a_abort(a_priv, 0);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return -ERESTARTSYS;
+ }
+
+ if (test_bit(AIF_WRITE_COMPLETE_BN, &a_priv->interrupt_flags) == 0) {
+ dev_dbg(&usb_dev->dev, "write timed out ibs %i, tmo %i\n",
+ test_bit(TIMO_NUM, &board->status), msec_timeout);
+
+ agilent_82357a_abort(a_priv, 0);
+
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+
+ read_reg.address = BSR;
+ retval = agilent_82357a_read_registers(a_priv, &read_reg, 1, 1);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+
+ bsr = read_reg.value;
+ dev_dbg(&usb_dev->dev, "write aborted bsr 0x%x\n", bsr);
+
+ if (send_commands) {/* check for no listeners */
+ if ((bsr & BSR_ATN_BIT) && !(bsr & (BSR_NDAC_BIT | BSR_NRFD_BIT))) {
+ dev_dbg(&usb_dev->dev, "No listener on command\n");
+ clear_bit(TIMO_NUM, &board->status);
+ return -ENOTCONN; // no listener on bus
+ }
+ } else {
+ read_reg.address = ADSR;
+ retval = agilent_82357a_read_registers(a_priv, &read_reg, 1, 1);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+ adsr = read_reg.value;
+ if ((adsr & HR_TA) && !(bsr & (BSR_NDAC_BIT | BSR_NRFD_BIT))) {
+ dev_dbg(&usb_dev->dev, "No listener on write\n");
+ clear_bit(TIMO_NUM, &board->status);
+ return -ECOMM;
+ }
+ }
+
+ return -ETIMEDOUT;
+ }
+
+ status_data = kmalloc(STATUS_DATA_LEN, GFP_KERNEL);
+ if (!status_data) {
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return -ENOMEM;
+ }
+
+ retval = agilent_82357a_receive_control_msg(a_priv, agilent_82357a_control_request,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ XFER_STATUS, 0, status_data, STATUS_DATA_LEN,
+ 100);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_control_msg() returned %i\n",
+ __func__, retval);
+ kfree(status_data);
+ return -EIO;
+ }
+ *bytes_written = (u32)status_data[2];
+ *bytes_written |= (u32)status_data[3] << 8;
+ *bytes_written |= (u32)status_data[4] << 16;
+ *bytes_written |= (u32)status_data[5] << 24;
+
+ kfree(status_data);
+ return 0;
+}
+
+static int agilent_82357a_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ return agilent_82357a_generic_write(board, buffer, length, 0, send_eoi, bytes_written);
+}
+
+int agilent_82357a_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written)
+{
+ return agilent_82357a_generic_write(board, buffer, length, 1, 0, bytes_written);
+}
+
+int agilent_82357a_take_control_internal(gpib_board_t *board, int synchronous)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet write;
+ int retval;
+
+ write.address = AUXCR;
+ if (synchronous)
+ write.value = AUX_TCS;
+ else
+ write.value = AUX_TCA;
+ retval = agilent_82357a_write_registers(a_priv, &write, 1);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+
+ return retval;
+}
+
+static int agilent_82357a_take_control(gpib_board_t *board, int synchronous)
+{
+ const int timeout = 10;
+ int i;
+
+/* It looks like the 9914 does not handle tcs properly.
+ * See comment above tms9914_take_control_workaround() in
+ * drivers/gpib/tms9914/tms9914_aux.c
+ */
+ if (synchronous)
+ return -ETIMEDOUT;
+
+ agilent_82357a_take_control_internal(board, synchronous);
+ // busy wait until ATN is asserted
+ for (i = 0; i < timeout; ++i) {
+ agilent_82357a_update_status(board, 0);
+ if (test_bit(ATN_NUM, &board->status))
+ break;
+ udelay(1);
+ }
+ if (i == timeout)
+ return -ETIMEDOUT;
+ return 0;
+}
+
+static int agilent_82357a_go_to_standby(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet write;
+ int retval;
+
+ write.address = AUXCR;
+ write.value = AUX_GTS;
+ retval = agilent_82357a_write_registers(a_priv, &write, 1);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return 0;
+}
+
+//FIXME should change prototype to return int
+static void agilent_82357a_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet writes[2];
+ int retval;
+ int i = 0;
+
+ /* 82357B needs bit to be set in 9914 AUXCR register */
+ writes[i].address = AUXCR;
+ if (request_control) {
+ writes[i].value = AUX_RQC;
+ a_priv->hw_control_bits |= SYSTEM_CONTROLLER;
+ } else {
+ writes[i].value = AUX_RLC;
+ a_priv->is_cic = 0;
+ a_priv->hw_control_bits &= ~SYSTEM_CONTROLLER;
+ }
+ ++i;
+ writes[i].address = HW_CONTROL;
+ writes[i].value = a_priv->hw_control_bits;
+ ++i;
+ retval = agilent_82357a_write_registers(a_priv, writes, i);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return;// retval;
+}
+
+static void agilent_82357a_interface_clear(gpib_board_t *board, int assert)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet write;
+ int retval;
+
+ write.address = AUXCR;
+ write.value = AUX_SIC;
+ if (assert) {
+ write.value |= AUX_CS;
+ a_priv->is_cic = 1;
+ }
+ retval = agilent_82357a_write_registers(a_priv, &write, 1);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+}
+
+static void agilent_82357a_remote_enable(gpib_board_t *board, int enable)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet write;
+ int retval;
+
+ write.address = AUXCR;
+ write.value = AUX_SRE;
+ if (enable)
+ write.value |= AUX_CS;
+ retval = agilent_82357a_write_registers(a_priv, &write, 1);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ a_priv->ren_state = enable;
+ return;// 0;
+}
+
+static int agilent_82357a_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+
+ if (compare_8_bits == 0) {
+ pr_warn("%s: hardware only supports 8-bit EOS compare", __func__);
+ return -EOPNOTSUPP;
+ }
+ a_priv->eos_char = eos_byte;
+ a_priv->eos_mode = REOS | BIN;
+ return 0;
+}
+
+static void agilent_82357a_disable_eos(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+
+ a_priv->eos_mode &= ~REOS;
+}
+
+static unsigned int agilent_82357a_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet address_status, bus_status;
+ int retval;
+
+ board->status &= ~clear_mask;
+ if (a_priv->is_cic)
+ set_bit(CIC_NUM, &board->status);
+ else
+ clear_bit(CIC_NUM, &board->status);
+ address_status.address = ADSR;
+ retval = agilent_82357a_read_registers(a_priv, &address_status, 1, 0);
+ if (retval) {
+ if (retval != -EAGAIN)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return board->status;
+ }
+ // check for remote/local
+ if (address_status.value & HR_REM)
+ set_bit(REM_NUM, &board->status);
+ else
+ clear_bit(REM_NUM, &board->status);
+ // check for lockout
+ if (address_status.value & HR_LLO)
+ set_bit(LOK_NUM, &board->status);
+ else
+ clear_bit(LOK_NUM, &board->status);
+ // check for ATN
+ if (address_status.value & HR_ATN)
+ set_bit(ATN_NUM, &board->status);
+ else
+ clear_bit(ATN_NUM, &board->status);
+ // check for talker/listener addressed
+ if (address_status.value & HR_TA)
+ set_bit(TACS_NUM, &board->status);
+ else
+ clear_bit(TACS_NUM, &board->status);
+ if (address_status.value & HR_LA)
+ set_bit(LACS_NUM, &board->status);
+ else
+ clear_bit(LACS_NUM, &board->status);
+
+ bus_status.address = BSR;
+ retval = agilent_82357a_read_registers(a_priv, &bus_status, 1, 0);
+ if (retval) {
+ if (retval != -EAGAIN)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return board->status;
+ }
+ if (bus_status.value & BSR_SRQ_BIT)
+ set_bit(SRQI_NUM, &board->status);
+ else
+ clear_bit(SRQI_NUM, &board->status);
+
+ return board->status;
+}
+
+static int agilent_82357a_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet write;
+ int retval;
+
+ // put primary address in address0
+ write.address = ADR;
+ write.value = address & ADDRESS_MASK;
+ retval = agilent_82357a_write_registers(a_priv, &write, 1);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return retval;
+ }
+ return retval;
+}
+
+static int agilent_82357a_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ if (enable)
+ pr_warn("%s: warning: assigning a secondary address not supported\n", __func__);
+ return -EOPNOTSUPP;
+}
+
+static int agilent_82357a_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet writes[2];
+ struct agilent_82357a_register_pairlet read;
+ int retval;
+
+ // execute parallel poll
+ writes[0].address = AUXCR;
+ writes[0].value = AUX_CS | AUX_RPP;
+ writes[1].address = HW_CONTROL;
+ writes[1].value = a_priv->hw_control_bits & ~NOT_PARALLEL_POLL;
+ retval = agilent_82357a_write_registers(a_priv, writes, 2);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return retval;
+ }
+ udelay(2); //silly, since usb write will take way longer
+ read.address = CPTR;
+ retval = agilent_82357a_read_registers(a_priv, &read, 1, 1);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return retval;
+ }
+ *result = read.value;
+ // clear parallel poll state
+ writes[0].address = HW_CONTROL;
+ writes[0].value = a_priv->hw_control_bits | NOT_PARALLEL_POLL;
+ writes[1].address = AUXCR;
+ writes[1].value = AUX_RPP;
+ retval = agilent_82357a_write_registers(a_priv, writes, 2);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return retval;
+ }
+ return 0;
+}
+
+static void agilent_82357a_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ //board can only be system controller
+ return;// 0;
+}
+
+static void agilent_82357a_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ //board can only be system controller
+ return;// 0;
+}
+
+static void agilent_82357a_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ //board can only be system controller
+ return;// 0;
+}
+
+static uint8_t agilent_82357a_serial_poll_status(gpib_board_t *board)
+{
+ //board can only be system controller
+ return 0;
+}
+
+static void agilent_82357a_return_to_local(gpib_board_t *board)
+{
+ //board can only be system controller
+ return;// 0;
+}
+
+static int agilent_82357a_line_status(const gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet bus_status;
+ int retval;
+ int status = ValidALL;
+
+ bus_status.address = BSR;
+ retval = agilent_82357a_read_registers(a_priv, &bus_status, 1, 0);
+ if (retval) {
+ if (retval != -EAGAIN)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return retval;
+ }
+ if (bus_status.value & BSR_REN_BIT)
+ status |= BusREN;
+ if (bus_status.value & BSR_IFC_BIT)
+ status |= BusIFC;
+ if (bus_status.value & BSR_SRQ_BIT)
+ status |= BusSRQ;
+ if (bus_status.value & BSR_EOI_BIT)
+ status |= BusEOI;
+ if (bus_status.value & BSR_NRFD_BIT)
+ status |= BusNRFD;
+ if (bus_status.value & BSR_NDAC_BIT)
+ status |= BusNDAC;
+ if (bus_status.value & BSR_DAV_BIT)
+ status |= BusDAV;
+ if (bus_status.value & BSR_ATN_BIT)
+ status |= BusATN;
+ return status;
+}
+
+static unsigned short nanosec_to_fast_talker_bits(unsigned int *nanosec)
+{
+ static const int nanosec_per_bit = 21;
+ static const int max_value = 0x72;
+ static const int min_value = 0x11;
+ unsigned short bits;
+
+ bits = (*nanosec + nanosec_per_bit / 2) / nanosec_per_bit;
+ if (bits < min_value)
+ bits = min_value;
+ if (bits > max_value)
+ bits = max_value;
+ *nanosec = bits * nanosec_per_bit;
+ return bits;
+}
+
+static unsigned int agilent_82357a_t1_delay(gpib_board_t *board, unsigned int nanosec)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet write;
+ int retval;
+
+ write.address = FAST_TALKER_T1;
+ write.value = nanosec_to_fast_talker_bits(&nanosec);
+ retval = agilent_82357a_write_registers(a_priv, &write, 1);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return nanosec;
+}
+
+static void agilent_82357a_interrupt_complete(struct urb *urb)
+{
+ gpib_board_t *board = urb->context;
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ int retval;
+ u8 *transfer_buffer = urb->transfer_buffer;
+ unsigned long interrupt_flags;
+
+ switch (urb->status) {
+ /* success */
+ case 0:
+ break;
+ /* unlinked, don't resubmit */
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ default: /* other error, resubmit */
+ retval = usb_submit_urb(a_priv->interrupt_urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__);
+ return;
+ }
+
+ interrupt_flags = transfer_buffer[0];
+ if (test_bit(AIF_READ_COMPLETE_BN, &interrupt_flags))
+ set_bit(AIF_READ_COMPLETE_BN, &a_priv->interrupt_flags);
+ if (test_bit(AIF_WRITE_COMPLETE_BN, &interrupt_flags))
+ set_bit(AIF_WRITE_COMPLETE_BN, &a_priv->interrupt_flags);
+ if (test_bit(AIF_SRQ_BN, &interrupt_flags))
+ set_bit(SRQI_NUM, &board->status);
+
+ wake_up_interruptible(&board->wait);
+
+ retval = usb_submit_urb(a_priv->interrupt_urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__);
+}
+
+static int agilent_82357a_setup_urbs(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev;
+ int int_pipe;
+ int retval;
+
+ retval = mutex_lock_interruptible(&a_priv->interrupt_alloc_lock);
+ if (retval)
+ return retval;
+ if (!a_priv->bus_interface) {
+ retval = -ENODEV;
+ goto setup_exit;
+ }
+
+ a_priv->interrupt_buffer = kmalloc(INTERRUPT_BUF_LEN, GFP_KERNEL);
+ if (!a_priv->interrupt_buffer) {
+ retval = -ENOMEM;
+ goto setup_exit;
+ }
+ a_priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!a_priv->interrupt_urb) {
+ retval = -ENOMEM;
+ goto setup_exit;
+ }
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ int_pipe = usb_rcvintpipe(usb_dev, a_priv->interrupt_in_endpoint);
+ usb_fill_int_urb(a_priv->interrupt_urb, usb_dev, int_pipe, a_priv->interrupt_buffer,
+ INTERRUPT_BUF_LEN, &agilent_82357a_interrupt_complete, board, 1);
+ retval = usb_submit_urb(a_priv->interrupt_urb, GFP_KERNEL);
+ if (retval) {
+ usb_free_urb(a_priv->interrupt_urb);
+ a_priv->interrupt_urb = NULL;
+ dev_err(&usb_dev->dev, "%s: failed to submit first interrupt urb, retval=%i\n",
+ __func__, retval);
+ goto setup_exit;
+ }
+ mutex_unlock(&a_priv->interrupt_alloc_lock);
+ return 0;
+
+setup_exit:
+ kfree(a_priv->interrupt_buffer);
+ mutex_unlock(&a_priv->interrupt_alloc_lock);
+ return retval;
+}
+
+#ifdef RESET_USB_CONFIG
+static int agilent_82357a_reset_usb_configuration(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct usb_device *usb_dev;
+ int retval;
+
+ if (!a_priv->bus_interface)
+ return -ENODEV;
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ retval = usb_reset_configuration(usb_dev);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: usb_reset_configuration() returned %i\n",
+ __func__, retval);
+ return retval;
+}
+#endif
+
+static void agilent_82357a_cleanup_urbs(struct agilent_82357a_priv *a_priv)
+{
+ if (a_priv && a_priv->bus_interface) {
+ if (a_priv->interrupt_urb)
+ usb_kill_urb(a_priv->interrupt_urb);
+ if (a_priv->bulk_urb)
+ usb_kill_urb(a_priv->bulk_urb);
+ }
+};
+
+static int agilent_82357a_allocate_private(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv;
+
+ board->private_data = kmalloc(sizeof(struct agilent_82357a_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+ a_priv = board->private_data;
+ memset(a_priv, 0, sizeof(struct agilent_82357a_priv));
+ mutex_init(&a_priv->bulk_transfer_lock);
+ mutex_init(&a_priv->bulk_alloc_lock);
+ mutex_init(&a_priv->control_alloc_lock);
+ mutex_init(&a_priv->interrupt_alloc_lock);
+ return 0;
+}
+
+static void agilent_82357a_free_private(struct agilent_82357a_priv *a_priv)
+{
+ usb_free_urb(a_priv->interrupt_urb);
+ kfree(a_priv->interrupt_buffer);
+ kfree(a_priv);
+}
+
+static int agilent_82357a_init(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet hw_control;
+ struct agilent_82357a_register_pairlet writes[0x20];
+ int retval;
+ int i;
+ unsigned int nanosec;
+
+ i = 0;
+ writes[i].address = LED_CONTROL;
+ writes[i].value = FAIL_LED_ON;
+ ++i;
+ writes[i].address = RESET_TO_POWERUP;
+ writes[i].value = RESET_SPACEBALL;
+ ++i;
+ retval = agilent_82357a_write_registers(a_priv, writes, i);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return -EIO;
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (schedule_timeout(usec_to_jiffies(2000)))
+ return -ERESTARTSYS;
+ i = 0;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_NBAF;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_HLDE;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_TON;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_LON;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_RSV2;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_INVAL;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_RPP;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_STDL;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_VSTDL;
+ ++i;
+ writes[i].address = FAST_TALKER_T1;
+ nanosec = board->t1_nano_sec;
+ writes[i].value = nanosec_to_fast_talker_bits(&nanosec);
+ board->t1_nano_sec = nanosec;
+ ++i;
+ writes[i].address = ADR;
+ writes[i].value = board->pad & ADDRESS_MASK;
+ ++i;
+ writes[i].address = PPR;
+ writes[i].value = 0;
+ ++i;
+ writes[i].address = SPMR;
+ writes[i].value = 0;
+ ++i;
+ writes[i].address = PROTOCOL_CONTROL;
+ writes[i].value = WRITE_COMPLETE_INTERRUPT_EN;
+ ++i;
+ writes[i].address = IMR0;
+ writes[i].value = HR_BOIE | HR_BIIE;
+ ++i;
+ writes[i].address = IMR1;
+ writes[i].value = HR_SRQIE;
+ ++i;
+ // turn off reset state
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_CHIP_RESET;
+ ++i;
+ writes[i].address = LED_CONTROL;
+ writes[i].value = FIRMWARE_LED_CONTROL;
+ ++i;
+ if (i > ARRAY_SIZE(writes)) {
+ dev_err(&usb_dev->dev, "%s: bug! writes[] overflow\n", __func__);
+ return -EFAULT;
+ }
+ retval = agilent_82357a_write_registers(a_priv, writes, i);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return -EIO;
+ }
+ hw_control.address = HW_CONTROL;
+ retval = agilent_82357a_read_registers(a_priv, &hw_control, 1, 1);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return -EIO;
+ }
+ a_priv->hw_control_bits = (hw_control.value & ~0x7) | NOT_TI_RESET | NOT_PARALLEL_POLL;
+
+ return 0;
+}
+
+static inline int agilent_82357a_device_match(struct usb_interface *interface,
+ const gpib_board_config_t *config)
+{
+ struct usb_device * const usbdev = interface_to_usbdev(interface);
+
+ if (gpib_match_device_path(&interface->dev, config->device_path) == 0)
+ return 0;
+ if (config->serial_number &&
+ strcmp(usbdev->serial, config->serial_number) != 0)
+ return 0;
+
+ return 1;
+}
+
+static int agilent_82357a_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ int retval;
+ int i;
+ unsigned int product_id;
+ struct agilent_82357a_priv *a_priv;
+ struct usb_device *usb_dev;
+
+ if (mutex_lock_interruptible(&agilent_82357a_hotplug_lock))
+ return -ERESTARTSYS;
+
+ retval = agilent_82357a_allocate_private(board);
+ if (retval < 0) {
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+ a_priv = board->private_data;
+ for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) {
+ if (agilent_82357a_driver_interfaces[i] &&
+ !usb_get_intfdata(agilent_82357a_driver_interfaces[i]) &&
+ agilent_82357a_device_match(agilent_82357a_driver_interfaces[i], config)) {
+ a_priv->bus_interface = agilent_82357a_driver_interfaces[i];
+ usb_set_intfdata(agilent_82357a_driver_interfaces[i], board);
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d attached to gpib minor %d, agilent usb interface %i\n",
+ usb_dev->bus->busnum, usb_dev->devnum, board->minor, i);
+ break;
+ }
+ }
+ if (i == MAX_NUM_82357A_INTERFACES) {
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ pr_err("No Agilent 82357 gpib adapters found, have you loaded its firmware?\n");
+ return -ENODEV;
+ }
+ product_id = le16_to_cpu(interface_to_usbdev(a_priv->bus_interface)->descriptor.idProduct);
+ switch (product_id) {
+ case USB_DEVICE_ID_AGILENT_82357A:
+ a_priv->bulk_out_endpoint = AGILENT_82357A_BULK_OUT_ENDPOINT;
+ a_priv->interrupt_in_endpoint = AGILENT_82357A_INTERRUPT_IN_ENDPOINT;
+ break;
+ case USB_DEVICE_ID_AGILENT_82357B:
+ a_priv->bulk_out_endpoint = AGILENT_82357B_BULK_OUT_ENDPOINT;
+ a_priv->interrupt_in_endpoint = AGILENT_82357B_INTERRUPT_IN_ENDPOINT;
+ break;
+ default:
+ dev_err(&usb_dev->dev, "bug, unhandled product_id in switch?\n");
+ return -EIO;
+ }
+#ifdef RESET_USB_CONFIG
+ retval = agilent_82357a_reset_usb_configuration(board);
+ if (retval < 0) {
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+#endif
+ retval = agilent_82357a_setup_urbs(board);
+ if (retval < 0) {
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+
+ timer_setup(&a_priv->bulk_timer, agilent_82357a_timeout_handler, 0);
+
+ board->t1_nano_sec = 800;
+
+ retval = agilent_82357a_init(board);
+
+ if (retval < 0) {
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+
+ dev_info(&usb_dev->dev, "%s: attached\n", __func__);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+}
+
+static int agilent_82357a_go_idle(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet writes[0x20];
+ int retval;
+ int i;
+
+ i = 0;
+ // turn on tms9914 reset state
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_CS | AUX_CHIP_RESET;
+ ++i;
+ a_priv->hw_control_bits &= ~NOT_TI_RESET;
+ writes[i].address = HW_CONTROL;
+ writes[i].value = a_priv->hw_control_bits;
+ ++i;
+ writes[i].address = PROTOCOL_CONTROL;
+ writes[i].value = 0;
+ ++i;
+ writes[i].address = IMR0;
+ writes[i].value = 0;
+ ++i;
+ writes[i].address = IMR1;
+ writes[i].value = 0;
+ ++i;
+ writes[i].address = LED_CONTROL;
+ writes[i].value = 0;
+ ++i;
+ if (i > ARRAY_SIZE(writes)) {
+ dev_err(&usb_dev->dev, "%s: bug! writes[] overflow\n", __func__);
+ return -EFAULT;
+ }
+ retval = agilent_82357a_write_registers(a_priv, writes, i);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return -EIO;
+ }
+ return 0;
+}
+
+static void agilent_82357a_detach(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv;
+ struct usb_device *usb_dev;
+
+ mutex_lock(&agilent_82357a_hotplug_lock);
+
+ a_priv = board->private_data;
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ if (a_priv) {
+ if (a_priv->bus_interface) {
+ agilent_82357a_go_idle(board);
+ usb_set_intfdata(a_priv->bus_interface, NULL);
+ }
+ mutex_lock(&a_priv->control_alloc_lock);
+ mutex_lock(&a_priv->bulk_alloc_lock);
+ mutex_lock(&a_priv->interrupt_alloc_lock);
+ agilent_82357a_cleanup_urbs(a_priv);
+ agilent_82357a_free_private(a_priv);
+ }
+ dev_info(&usb_dev->dev, "%s: detached\n", __func__);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+}
+
+gpib_interface_t agilent_82357a_gpib_interface = {
+name: "agilent_82357a",
+attach : agilent_82357a_attach,
+detach : agilent_82357a_detach,
+read : agilent_82357a_read,
+write : agilent_82357a_write,
+command : agilent_82357a_command,
+take_control : agilent_82357a_take_control,
+go_to_standby : agilent_82357a_go_to_standby,
+request_system_control : agilent_82357a_request_system_control,
+interface_clear : agilent_82357a_interface_clear,
+remote_enable : agilent_82357a_remote_enable,
+enable_eos : agilent_82357a_enable_eos,
+disable_eos : agilent_82357a_disable_eos,
+parallel_poll : agilent_82357a_parallel_poll,
+parallel_poll_configure : agilent_82357a_parallel_poll_configure,
+parallel_poll_response : agilent_82357a_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : agilent_82357a_line_status,
+update_status : agilent_82357a_update_status,
+primary_address : agilent_82357a_primary_address,
+secondary_address : agilent_82357a_secondary_address,
+serial_poll_response : agilent_82357a_serial_poll_response,
+serial_poll_status : agilent_82357a_serial_poll_status,
+t1_delay : agilent_82357a_t1_delay,
+return_to_local : agilent_82357a_return_to_local,
+no_7_bit_eos : 1,
+skip_check_for_command_acceptors : 1
+};
+
+// Table with the USB-devices: just now only testing IDs
+static struct usb_device_id agilent_82357a_driver_device_table[] = {
+ {USB_DEVICE(USB_VENDOR_ID_AGILENT, USB_DEVICE_ID_AGILENT_82357A)},
+ {USB_DEVICE(USB_VENDOR_ID_AGILENT, USB_DEVICE_ID_AGILENT_82357B)},
+ {} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, agilent_82357a_driver_device_table);
+
+static int agilent_82357a_driver_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ int i;
+ char *path;
+ static const int path_length = 1024;
+ struct usb_device *usb_dev;
+
+ if (mutex_lock_interruptible(&agilent_82357a_hotplug_lock))
+ return -ERESTARTSYS;
+ usb_dev = usb_get_dev(interface_to_usbdev(interface));
+ for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) {
+ if (!agilent_82357a_driver_interfaces[i]) {
+ agilent_82357a_driver_interfaces[i] = interface;
+ usb_set_intfdata(interface, NULL);
+ dev_dbg(&usb_dev->dev, "set bus interface %i to address 0x%p\n",
+ i, interface);
+ break;
+ }
+ }
+ if (i == MAX_NUM_82357A_INTERFACES) {
+ usb_put_dev(usb_dev);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ dev_err(&usb_dev->dev, "%s: out of space in agilent_82357a_driver_interfaces[]\n",
+ __func__);
+ return -1;
+ }
+ path = kmalloc(path_length, GFP_KERNEL);
+ if (!path) {
+ usb_put_dev(usb_dev);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return -ENOMEM;
+ }
+ usb_make_path(usb_dev, path, path_length);
+ dev_info(&usb_dev->dev, "probe succeeded for path: %s\n", path);
+ kfree(path);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return 0;
+}
+
+static void agilent_82357a_driver_disconnect(struct usb_interface *interface)
+{
+ int i;
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+
+ mutex_lock(&agilent_82357a_hotplug_lock);
+
+ for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) {
+ if (agilent_82357a_driver_interfaces[i] == interface) {
+ gpib_board_t *board = usb_get_intfdata(interface);
+
+ if (board) {
+ struct agilent_82357a_priv *a_priv = board->private_data;
+
+ if (a_priv) {
+ mutex_lock(&a_priv->control_alloc_lock);
+ mutex_lock(&a_priv->bulk_alloc_lock);
+ mutex_lock(&a_priv->interrupt_alloc_lock);
+ agilent_82357a_cleanup_urbs(a_priv);
+ a_priv->bus_interface = NULL;
+ mutex_unlock(&a_priv->interrupt_alloc_lock);
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ mutex_unlock(&a_priv->control_alloc_lock);
+ }
+ }
+ dev_dbg(&usb_dev->dev, "nulled agilent_82357a_driver_interfaces[%i]\n", i);
+ agilent_82357a_driver_interfaces[i] = NULL;
+ break;
+ }
+ }
+ if (i == MAX_NUM_82357A_INTERFACES)
+ dev_err(&usb_dev->dev, "unable to find interface in agilent_82357a_driver_interfaces[]? bug?\n");
+ usb_put_dev(usb_dev);
+
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+}
+
+static int agilent_82357a_driver_suspend(struct usb_interface *interface, pm_message_t message)
+{
+ int i, retval;
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+
+ mutex_lock(&agilent_82357a_hotplug_lock);
+
+ for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) {
+ if (agilent_82357a_driver_interfaces[i] == interface) {
+ gpib_board_t *board = usb_get_intfdata(interface);
+
+ if (board) {
+ struct agilent_82357a_priv *a_priv = board->private_data;
+
+ if (a_priv) {
+ agilent_82357a_abort(a_priv, 0);
+ agilent_82357a_abort(a_priv, 0);
+ retval = agilent_82357a_go_idle(board);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: failed to go idle, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+ mutex_lock(&a_priv->interrupt_alloc_lock);
+ agilent_82357a_cleanup_urbs(a_priv);
+ mutex_unlock(&a_priv->interrupt_alloc_lock);
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d gpib minor %d, agilent usb interface %i suspended\n",
+ usb_dev->bus->busnum, usb_dev->devnum,
+ board->minor, i);
+ }
+ }
+ break;
+ }
+ }
+
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+
+ return 0;
+}
+
+static int agilent_82357a_driver_resume(struct usb_interface *interface)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+ gpib_board_t *board;
+ int i, retval;
+
+ mutex_lock(&agilent_82357a_hotplug_lock);
+
+ for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) {
+ if (agilent_82357a_driver_interfaces[i] == interface) {
+ board = usb_get_intfdata(interface);
+ if (board)
+ break;
+ }
+ }
+ if (i == MAX_NUM_82357A_INTERFACES)
+ goto resume_exit;
+
+ struct agilent_82357a_priv *a_priv = board->private_data;
+
+ if (a_priv) {
+ if (a_priv->interrupt_urb) {
+ mutex_lock(&a_priv->interrupt_alloc_lock);
+ retval = usb_submit_urb(a_priv->interrupt_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&a_priv->interrupt_alloc_lock);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+ mutex_unlock(&a_priv->interrupt_alloc_lock);
+ }
+ retval = agilent_82357a_init(board);
+ if (retval < 0) {
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+ // set/unset system controller
+ agilent_82357a_request_system_control(board, board->master);
+ // toggle ifc if master
+ if (board->master) {
+ agilent_82357a_interface_clear(board, 1);
+ usleep_range(200, 250);
+ agilent_82357a_interface_clear(board, 0);
+ }
+ // assert/unassert REN
+ agilent_82357a_remote_enable(board, a_priv->ren_state);
+
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d gpib minor %d, agilent usb interface %i resumed\n",
+ usb_dev->bus->busnum, usb_dev->devnum, board->minor, i);
+ }
+
+resume_exit:
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+
+ return 0;
+}
+
+static struct usb_driver agilent_82357a_bus_driver = {
+ .name = "agilent_82357a_gpib",
+ .probe = agilent_82357a_driver_probe,
+ .disconnect = agilent_82357a_driver_disconnect,
+ .suspend = agilent_82357a_driver_suspend,
+ .resume = agilent_82357a_driver_resume,
+ .id_table = agilent_82357a_driver_device_table,
+};
+
+static int __init agilent_82357a_init_module(void)
+{
+ int i;
+
+ pr_info("agilent_82357a_gpib driver loading");
+ for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i)
+ agilent_82357a_driver_interfaces[i] = NULL;
+ usb_register(&agilent_82357a_bus_driver);
+ gpib_register_driver(&agilent_82357a_gpib_interface, THIS_MODULE);
+
+ return 0;
+}
+
+static void __exit agilent_82357a_exit_module(void)
+{
+ pr_info("agilent_82357a_gpib driver unloading");
+ gpib_unregister_driver(&agilent_82357a_gpib_interface);
+ usb_deregister(&agilent_82357a_bus_driver);
+}
+
+module_init(agilent_82357a_init_module);
+module_exit(agilent_82357a_exit_module);
diff --git a/drivers/staging/gpib/agilent_82357a/agilent_82357a.h b/drivers/staging/gpib/agilent_82357a/agilent_82357a.h
new file mode 100644
index 000000000000..cdbc3ec5d8bd
--- /dev/null
+++ b/drivers/staging/gpib/agilent_82357a/agilent_82357a.h
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2004 by Frank Mori Hess *
+ ***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/semaphore.h>
+#include <linux/usb.h>
+#include <linux/timer.h>
+#include <linux/compiler_attributes.h>
+#include "gpibP.h"
+#include "tms9914.h"
+
+enum usb_vendor_ids {
+ USB_VENDOR_ID_AGILENT = 0x0957
+};
+
+enum usb_device_ids {
+ USB_DEVICE_ID_AGILENT_82357A = 0x0107,
+ USB_DEVICE_ID_AGILENT_82357A_PREINIT = 0x0007, // device id before firmware is loaded
+ USB_DEVICE_ID_AGILENT_82357B = 0x0718, // device id before firmware is loaded
+ USB_DEVICE_ID_AGILENT_82357B_PREINIT = 0x0518, // device id before firmware is loaded
+};
+
+enum endpoint_addresses {
+ AGILENT_82357_CONTROL_ENDPOINT = 0x0,
+ AGILENT_82357_BULK_IN_ENDPOINT = 0x2,
+ AGILENT_82357A_BULK_OUT_ENDPOINT = 0x4,
+ AGILENT_82357A_INTERRUPT_IN_ENDPOINT = 0x6,
+ AGILENT_82357B_BULK_OUT_ENDPOINT = 0x6,
+ AGILENT_82357B_INTERRUPT_IN_ENDPOINT = 0x8,
+};
+
+enum bulk_commands {
+ DATA_PIPE_CMD_WRITE = 0x1,
+ DATA_PIPE_CMD_READ = 0x3,
+ DATA_PIPE_CMD_WR_REGS = 0x4,
+ DATA_PIPE_CMD_RD_REGS = 0x5
+};
+
+enum agilent_82357a_read_flags {
+ ARF_END_ON_EOI = 0x1,
+ ARF_NO_ADDRESS = 0x2,
+ ARF_END_ON_EOS_CHAR = 0x4,
+ ARF_SPOLL = 0x8
+};
+
+enum agilent_82357a_trailing_read_flags {
+ ATRF_EOI = 0x1,
+ ATRF_ATN = 0x2,
+ ATRF_IFC = 0x4,
+ ATRF_EOS = 0x8,
+ ATRF_ABORT = 0x10,
+ ATRF_COUNT = 0x20,
+ ATRF_DEAD_BUS = 0x40,
+ ATRF_UNADDRESSED = 0x80
+};
+
+enum agilent_82357a_write_flags {
+ AWF_SEND_EOI = 0x1,
+ AWF_NO_FAST_TALKER_FIRST_BYTE = 0x2,
+ AWF_NO_FAST_TALKER = 0x4,
+ AWF_NO_ADDRESS = 0x8,
+ AWF_ATN = 0x10,
+ AWF_SEPARATE_HEADER = 0x80
+};
+
+enum agilent_82357a_interrupt_flag_bit_numbers {
+ AIF_SRQ_BN = 0,
+ AIF_WRITE_COMPLETE_BN = 1,
+ AIF_READ_COMPLETE_BN = 2,
+};
+
+enum agilent_82357_error_codes {
+ UGP_SUCCESS = 0,
+ UGP_ERR_INVALID_CMD = 1,
+ UGP_ERR_INVALID_PARAM = 2,
+ UGP_ERR_INVALID_REG = 3,
+ UGP_ERR_GPIB_READ = 4,
+ UGP_ERR_GPIB_WRITE = 5,
+ UGP_ERR_FLUSHING = 6,
+ UGP_ERR_FLUSHING_ALREADY = 7,
+ UGP_ERR_UNSUPPORTED = 8,
+ UGP_ERR_OTHER = 9
+};
+
+enum agilent_82357_control_values {
+ XFER_ABORT = 0xa0,
+ XFER_STATUS = 0xb0,
+};
+
+enum xfer_status_bits {
+ XS_COMPLETED = 0x1,
+ XS_READ = 0x2,
+};
+
+enum xfer_status_completion_bits {
+ XSC_EOI = 0x1,
+ XSC_ATN = 0x2,
+ XSC_IFC = 0x4,
+ XSC_EOS = 0x8,
+ XSC_ABORT = 0x10,
+ XSC_COUNT = 0x20,
+ XSC_DEAD_BUS = 0x40,
+ XSC_BUS_NOT_ADDRESSED = 0x80
+};
+
+enum xfer_abort_type {
+ XA_FLUSH = 0x1
+};
+
+#define STATUS_DATA_LEN 8
+#define INTERRUPT_BUF_LEN 8
+
+struct agilent_82357a_urb_ctx {
+ struct semaphore complete;
+ unsigned timed_out : 1;
+};
+
+// struct which defines local data for each 82357 device
+struct agilent_82357a_priv {
+ struct usb_interface *bus_interface;
+ unsigned short eos_char;
+ unsigned short eos_mode;
+ unsigned short hw_control_bits;
+ unsigned long interrupt_flags;
+ struct urb *bulk_urb;
+ struct urb *interrupt_urb;
+ u8 *interrupt_buffer;
+ struct mutex bulk_transfer_lock; // bulk transfer lock
+ struct mutex bulk_alloc_lock; // bulk transfer allocation lock
+ struct mutex interrupt_alloc_lock; // interrupt allocation lock
+ struct mutex control_alloc_lock; // control message allocation lock
+ struct timer_list bulk_timer;
+ struct agilent_82357a_urb_ctx context;
+ unsigned int bulk_out_endpoint;
+ unsigned int interrupt_in_endpoint;
+ unsigned is_cic : 1;
+ unsigned ren_state : 1;
+};
+
+struct agilent_82357a_register_pairlet {
+ short address;
+ unsigned short value;
+};
+
+enum firmware_registers {
+ HW_CONTROL = 0xa,
+ LED_CONTROL = 0xb,
+ RESET_TO_POWERUP = 0xc,
+ PROTOCOL_CONTROL = 0xd,
+ FAST_TALKER_T1 = 0xe
+};
+
+enum hardware_control_bits {
+ NOT_TI_RESET = 0x1,
+ SYSTEM_CONTROLLER = 0x2,
+ NOT_PARALLEL_POLL = 0x4,
+ OSCILLATOR_5V_ON = 0x8,
+ OUTPUT_5V_ON = 0x20,
+ CPLD_3V_ON = 0x80,
+};
+
+enum led_control_bits {
+ FIRMWARE_LED_CONTROL = 0x1,
+ FAIL_LED_ON = 0x20,
+ READY_LED_ON = 0x40,
+ ACCESS_LED_ON = 0x80
+};
+
+enum reset_to_powerup_bits {
+ RESET_SPACEBALL = 0x1, // wait 2 millisec after sending
+};
+
+enum protocol_control_bits {
+ WRITE_COMPLETE_INTERRUPT_EN = 0x1,
+};
+
+static const int agilent_82357a_control_request = 0x4;
+
diff --git a/drivers/staging/gpib/cb7210/Makefile b/drivers/staging/gpib/cb7210/Makefile
new file mode 100644
index 000000000000..22e0214fc17d
--- /dev/null
+++ b/drivers/staging/gpib/cb7210/Makefile
@@ -0,0 +1,4 @@
+ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA
+obj-m += cb7210.o
+
+
diff --git a/drivers/staging/gpib/cb7210/cb7210.c b/drivers/staging/gpib/cb7210/cb7210.c
new file mode 100644
index 000000000000..63df7f3eb3f3
--- /dev/null
+++ b/drivers/staging/gpib/cb7210/cb7210.c
@@ -0,0 +1,1556 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * Measurement Computing boards using cb7210.2 and cbi488.2 chips
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "cb7210.h"
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/dma.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include "gpib_pci_ids.h"
+#include "quancom_pci.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver Measurement Computing boards using cb7210.2 and cbi488.2");
+
+static inline int have_fifo_word(const struct cb7210_priv *cb_priv)
+{
+ if (((cb7210_read_byte(cb_priv, HS_STATUS)) &
+ (HS_RX_MSB_NOT_EMPTY | HS_RX_LSB_NOT_EMPTY)) ==
+ (HS_RX_MSB_NOT_EMPTY | HS_RX_LSB_NOT_EMPTY))
+ return 1;
+ else
+ return 0;
+}
+
+static inline void input_fifo_enable(gpib_board_t *board, int enable)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ if (enable) {
+ cb_priv->in_fifo_half_full = 0;
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+
+ cb7210_write_byte(cb_priv, HS_RX_ENABLE | HS_TX_ENABLE | HS_CLR_SRQ_INT |
+ HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT | cb_priv->hs_mode_bits,
+ HS_MODE);
+
+ cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE);
+
+ cb7210_write_byte(cb_priv, irq_bits(cb_priv->irq), HS_INT_LEVEL);
+
+ cb_priv->hs_mode_bits |= HS_RX_ENABLE;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE);
+ } else {
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+
+ cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, nec7210_iobase(cb_priv) +
+ HS_MODE);
+
+ clear_bit(READ_READY_BN, &nec_priv->state);
+ }
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+static int fifo_read(gpib_board_t *board, struct cb7210_priv *cb_priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval = 0;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ int hs_status;
+ u16 word;
+ unsigned long flags;
+
+ *bytes_read = 0;
+ if (cb_priv->fifo_iobase == 0) {
+ pr_err("cb7210: fifo iobase is zero!\n");
+ return -EIO;
+ }
+ *end = 0;
+ if (length <= cb7210_fifo_size) {
+ pr_err("cb7210: bug! %s with length < fifo size\n", __func__);
+ return -EINVAL;
+ }
+
+ input_fifo_enable(board, 1);
+
+ while (*bytes_read + cb7210_fifo_size < length) {
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI);
+
+ if (wait_event_interruptible(board->wait,
+ (cb_priv->in_fifo_half_full &&
+ have_fifo_word(cb_priv)) ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_warn("cb7210: fifo half full wait interrupted\n");
+ retval = -ERESTARTSYS;
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+ break;
+ }
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+
+ while (have_fifo_word(cb_priv)) {
+ word = inw(cb_priv->fifo_iobase + DIR);
+ buffer[(*bytes_read)++] = word & 0xff;
+ buffer[(*bytes_read)++] = (word >> 8) & 0xff;
+ }
+
+ cb_priv->in_fifo_half_full = 0;
+
+ hs_status = cb7210_read_byte(cb_priv, HS_STATUS);
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state)) {
+ *end = 1;
+ break;
+ }
+ if (hs_status & HS_FIFO_FULL)
+ break;
+ if (test_bit(TIMO_NUM, &board->status)) {
+ retval = -ETIMEDOUT;
+ break;
+ }
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) {
+ retval = -EINTR;
+ break;
+ }
+ }
+ hs_status = cb7210_read_byte(cb_priv, HS_STATUS);
+ if (hs_status & HS_RX_LSB_NOT_EMPTY) {
+ word = inw(cb_priv->fifo_iobase + DIR);
+ buffer[(*bytes_read)++] = word & 0xff;
+ }
+
+ input_fifo_enable(board, 0);
+
+ if (wait_event_interruptible(board->wait,
+ test_bit(READ_READY_BN, &nec_priv->state) ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_warn("cb7210: fifo half full wait interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ if (test_bit(READ_READY_BN, &nec_priv->state)) {
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDA);
+ buffer[(*bytes_read)++] = nec7210_read_data_in(board, nec_priv, end);
+ }
+
+ return retval;
+}
+
+int cb7210_accel_read(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval;
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ size_t num_bytes;
+
+ *bytes_read = 0;
+ // deal with limitations of fifo
+ if (length < cb7210_fifo_size + 3 || (nec_priv->auxa_bits & HR_REOS))
+ return cb7210_read(board, buffer, length, end, bytes_read);
+ *end = 0;
+
+ nec7210_release_rfd_holdoff(board, nec_priv);
+
+ if (wait_event_interruptible(board->wait,
+ test_bit(READ_READY_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_warn("cb7210: read ready wait interrupted\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ return -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ return -EINTR;
+
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDE);
+ buffer[(*bytes_read)++] = nec7210_read_data_in(board, nec_priv, end);
+ if (*end)
+ return 0;
+
+ nec7210_release_rfd_holdoff(board, nec_priv);
+
+ retval = fifo_read(board, cb_priv, &buffer[*bytes_read], length - *bytes_read - 1,
+ end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ return retval;
+ if (*end)
+ return 0;
+
+ retval = cb7210_read(board, &buffer[*bytes_read], 1, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ return retval;
+
+ return 0;
+}
+
+static int output_fifo_empty(const struct cb7210_priv *cb_priv)
+{
+ if ((cb7210_read_byte(cb_priv, HS_STATUS) & (HS_TX_MSB_NOT_EMPTY | HS_TX_LSB_NOT_EMPTY))
+ == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static inline void output_fifo_enable(gpib_board_t *board, int enable)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ if (enable) {
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO);
+
+ cb7210_write_byte(cb_priv, HS_RX_ENABLE | HS_TX_ENABLE | HS_CLR_SRQ_INT |
+ HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT | cb_priv->hs_mode_bits,
+ HS_MODE);
+
+ cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK;
+ cb_priv->hs_mode_bits |= HS_TX_ENABLE;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE);
+
+ cb7210_write_byte(cb_priv, irq_bits(cb_priv->irq), HS_INT_LEVEL);
+
+ clear_bit(WRITE_READY_BN, &nec_priv->state);
+
+ } else {
+ cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE);
+
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0);
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, HR_DOIE);
+ }
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+static int fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ size_t count = 0;
+ ssize_t retval = 0;
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ unsigned int num_bytes, i;
+ unsigned long flags;
+
+ *bytes_written = 0;
+ if (cb_priv->fifo_iobase == 0) {
+ pr_err("cb7210: fifo iobase is zero!\n");
+ return -EINVAL;
+ }
+ if (length == 0)
+ return 0;
+
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state);
+ clear_bit(BUS_ERROR_BN, &nec_priv->state);
+
+ output_fifo_enable(board, 1);
+
+ while (count < length) {
+ // wait until byte is ready to be sent
+ if (wait_event_interruptible(board->wait,
+ cb_priv->out_fifo_half_empty ||
+ output_fifo_empty(cb_priv) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_warn("cb7210: fifo wait interrupted\n");
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (test_bit(TIMO_NUM, &board->status) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state))
+ break;
+
+ if (output_fifo_empty(cb_priv))
+ num_bytes = cb7210_fifo_size - cb7210_fifo_width;
+ else
+ num_bytes = cb7210_fifo_size / 2;
+ if (num_bytes + count > length)
+ num_bytes = length - count;
+ if (num_bytes % cb7210_fifo_width) {
+ pr_err("cb7210: bug! %s with odd number of bytes\n", __func__);
+ retval = -EINVAL;
+ break;
+ }
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ for (i = 0; i < num_bytes / cb7210_fifo_width; i++) {
+ u16 word;
+
+ word = buffer[count++] & 0xff;
+ word |= (buffer[count++] << 8) & 0xff00;
+ outw(word, cb_priv->fifo_iobase + CDOR);
+ }
+ cb_priv->out_fifo_half_empty = 0;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits |
+ HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT, HS_MODE);
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ }
+ // wait last byte has been sent
+ if (wait_event_interruptible(board->wait,
+ output_fifo_empty(cb_priv) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_err("cb7210: wait for last byte interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_bit(BUS_ERROR_BN, &nec_priv->state))
+ retval = -EIO;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+
+ output_fifo_enable(board, 0);
+
+ *bytes_written = count;
+ return retval;
+}
+
+int cb7210_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ unsigned long fast_chunk_size, leftover;
+ int retval;
+ size_t num_bytes;
+
+ *bytes_written = 0;
+ if (length > cb7210_fifo_width)
+ fast_chunk_size = length - 1;
+ else
+ fast_chunk_size = 0;
+ fast_chunk_size -= fast_chunk_size % cb7210_fifo_width;
+ leftover = length - fast_chunk_size;
+
+ retval = fifo_write(board, buffer, fast_chunk_size, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+
+ retval = nec7210_write(board, nec_priv, buffer + fast_chunk_size, leftover,
+ send_eoi, &num_bytes);
+ *bytes_written += num_bytes;
+ return retval;
+}
+
+int cb7210_line_status(const gpib_board_t *board)
+{
+ int status = ValidALL;
+ int bsr_bits;
+ struct cb7210_priv *cb_priv;
+ struct nec7210_priv *nec_priv;
+
+ cb_priv = board->private_data;
+ nec_priv = &cb_priv->nec7210_priv;
+
+ bsr_bits = cb7210_paged_read_byte(cb_priv, BUS_STATUS, BUS_STATUS_PAGE);
+
+ if ((bsr_bits & BSR_REN_BIT) == 0)
+ status |= BusREN;
+ if ((bsr_bits & BSR_IFC_BIT) == 0)
+ status |= BusIFC;
+ if ((bsr_bits & BSR_SRQ_BIT) == 0)
+ status |= BusSRQ;
+ if ((bsr_bits & BSR_EOI_BIT) == 0)
+ status |= BusEOI;
+ if ((bsr_bits & BSR_NRFD_BIT) == 0)
+ status |= BusNRFD;
+ if ((bsr_bits & BSR_NDAC_BIT) == 0)
+ status |= BusNDAC;
+ if ((bsr_bits & BSR_DAV_BIT) == 0)
+ status |= BusDAV;
+ if ((bsr_bits & BSR_ATN_BIT) == 0)
+ status |= BusATN;
+
+ return status;
+}
+
+unsigned int cb7210_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ unsigned int retval;
+
+ retval = nec7210_t1_delay(board, nec_priv, nano_sec);
+
+ if (nano_sec <= 350) {
+ write_byte(nec_priv, AUX_HI_SPEED, AUXMR);
+ retval = 350;
+ } else {
+ write_byte(nec_priv, AUX_LO_SPEED, AUXMR);
+ }
+ return retval;
+}
+
+irqreturn_t cb7210_locked_internal_interrupt(gpib_board_t *board);
+
+/*
+ * GPIB interrupt service routines
+ */
+
+irqreturn_t cb_pci_interrupt(int irq, void *arg)
+{
+ int bits;
+ gpib_board_t *board = arg;
+ struct cb7210_priv *priv = board->private_data;
+
+ // first task check if this is really our interrupt in a shared irq environment
+ switch (priv->pci_chip) {
+ case PCI_CHIP_AMCC_S5933:
+ if ((inl(priv->amcc_iobase + INTCSR_REG) &
+ (INBOX_INTR_CS_BIT | INTR_ASSERTED_BIT)) == 0)
+ return IRQ_NONE;
+
+ // read incoming mailbox to clear mailbox full flag
+ inl(priv->amcc_iobase + INCOMING_MAILBOX_REG(3));
+ // clear amccs5933 interrupt
+ bits = INBOX_FULL_INTR_BIT | INBOX_BYTE_BITS(3) |
+ INBOX_SELECT_BITS(3) | INBOX_INTR_CS_BIT;
+ outl(bits, priv->amcc_iobase + INTCSR_REG);
+ break;
+ case PCI_CHIP_QUANCOM:
+ if ((inb(nec7210_iobase(priv) + QUANCOM_IRQ_CONTROL_STATUS_REG) &
+ QUANCOM_IRQ_ASSERTED_BIT))
+ outb(QUANCOM_IRQ_ENABLE_BIT, nec7210_iobase(priv) +
+ QUANCOM_IRQ_CONTROL_STATUS_REG);
+ break;
+ default:
+ break;
+ }
+ return cb7210_locked_internal_interrupt(arg);
+}
+
+irqreturn_t cb7210_internal_interrupt(gpib_board_t *board)
+{
+ int hs_status, status1, status2;
+ struct cb7210_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+ int clear_bits;
+
+ if ((priv->hs_mode_bits & HS_ENABLE_MASK)) {
+ status1 = 0;
+ hs_status = cb7210_read_byte(priv, HS_STATUS);
+ } else {
+ hs_status = 0;
+ status1 = read_byte(nec_priv, ISR1);
+ }
+ status2 = read_byte(nec_priv, ISR2);
+ nec7210_interrupt_have_status(board, nec_priv, status1, status2);
+
+ dev_dbg(board->gpib_dev, "cb7210: status 0x%x, mode 0x%x\n", hs_status, priv->hs_mode_bits);
+
+ clear_bits = 0;
+
+ if (hs_status & HS_HALF_FULL) {
+ if (priv->hs_mode_bits & HS_TX_ENABLE)
+ priv->out_fifo_half_empty = 1;
+ else if (priv->hs_mode_bits & HS_RX_ENABLE)
+ priv->in_fifo_half_full = 1;
+ clear_bits |= HS_CLR_HF_INT;
+ }
+
+ if (hs_status & HS_SRQ_INT) {
+ set_bit(SRQI_NUM, &board->status);
+ clear_bits |= HS_CLR_SRQ_INT;
+ }
+
+ if ((hs_status & HS_EOI_INT)) {
+ clear_bits |= HS_CLR_EOI_EMPTY_INT;
+ set_bit(RECEIVED_END_BN, &nec_priv->state);
+ if ((nec_priv->auxa_bits & HR_HANDSHAKE_MASK) == HR_HLDE)
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ }
+
+ if ((priv->hs_mode_bits & HS_TX_ENABLE) &&
+ (hs_status & (HS_TX_MSB_NOT_EMPTY | HS_TX_LSB_NOT_EMPTY)) == 0)
+ clear_bits |= HS_CLR_EOI_EMPTY_INT;
+
+ if (clear_bits) {
+ cb7210_write_byte(priv, priv->hs_mode_bits | clear_bits, HS_MODE);
+ cb7210_write_byte(priv, priv->hs_mode_bits, HS_MODE);
+ wake_up_interruptible(&board->wait);
+ }
+
+ return IRQ_HANDLED;
+}
+
+irqreturn_t cb7210_locked_internal_interrupt(gpib_board_t *board)
+{
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = cb7210_internal_interrupt(board);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+irqreturn_t cb7210_interrupt(int irq, void *arg)
+{
+ return cb7210_internal_interrupt(arg);
+}
+
+static int cb_pci_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int cb_isa_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void cb_pci_detach(gpib_board_t *board);
+static void cb_isa_detach(gpib_board_t *board);
+
+// wrappers for interface functions
+int cb7210_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+}
+
+int cb7210_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int cb7210_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+int cb7210_take_control(gpib_board_t *board, int synchronous)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+int cb7210_go_to_standby(gpib_board_t *board)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+void cb7210_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct cb7210_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ if (request_control)
+ priv->hs_mode_bits |= HS_SYS_CONTROL;
+ else
+ priv->hs_mode_bits &= ~HS_SYS_CONTROL;
+
+ cb7210_write_byte(priv, priv->hs_mode_bits, HS_MODE);
+ nec7210_request_system_control(board, nec_priv, request_control);
+}
+
+void cb7210_interface_clear(gpib_board_t *board, int assert)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+void cb7210_remote_enable(gpib_board_t *board, int enable)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+int cb7210_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+void cb7210_disable_eos(gpib_board_t *board)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+unsigned int cb7210_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
+}
+
+int cb7210_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+int cb7210_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+int cb7210_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
+}
+
+void cb7210_parallel_poll_configure(gpib_board_t *board, uint8_t configuration)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration);
+}
+
+void cb7210_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+void cb7210_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
+}
+
+uint8_t cb7210_serial_poll_status(gpib_board_t *board)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+void cb7210_return_to_local(gpib_board_t *board)
+{
+ struct cb7210_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ write_byte(nec_priv, AUX_RTL2, AUXMR);
+ udelay(1);
+ write_byte(nec_priv, AUX_RTL, AUXMR);
+}
+
+gpib_interface_t cb_pci_unaccel_interface = {
+name: "cbi_pci_unaccel",
+attach : cb_pci_attach,
+detach : cb_pci_detach,
+read : cb7210_read,
+write : cb7210_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_pci_accel_interface = {
+name: "cbi_pci_accel",
+attach : cb_pci_attach,
+detach : cb_pci_detach,
+read : cb7210_accel_read,
+write : cb7210_accel_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_pci_interface = {
+name: "cbi_pci",
+attach : cb_pci_attach,
+detach : cb_pci_detach,
+read : cb7210_accel_read,
+write : cb7210_accel_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_isa_unaccel_interface = {
+name: "cbi_isa_unaccel",
+attach : cb_isa_attach,
+detach : cb_isa_detach,
+read : cb7210_read,
+write : cb7210_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_isa_interface = {
+name: "cbi_isa",
+attach : cb_isa_attach,
+detach : cb_isa_detach,
+read : cb7210_accel_read,
+write : cb7210_accel_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_isa_accel_interface = {
+name: "cbi_isa_accel",
+attach : cb_isa_attach,
+detach : cb_isa_detach,
+read : cb7210_accel_read,
+write : cb7210_accel_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+static int cb7210_allocate_private(gpib_board_t *board)
+{
+ struct cb7210_priv *priv;
+
+ board->private_data = kmalloc(sizeof(struct cb7210_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ priv = board->private_data;
+ memset(priv, 0, sizeof(struct cb7210_priv));
+ init_nec7210_private(&priv->nec7210_priv);
+ return 0;
+}
+
+void cb7210_generic_detach(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+// generic part of attach functions shared by all cb7210 boards
+int cb7210_generic_attach(gpib_board_t *board)
+{
+ struct cb7210_priv *cb_priv;
+ struct nec7210_priv *nec_priv;
+
+ board->status = 0;
+
+ if (cb7210_allocate_private(board))
+ return -ENOMEM;
+ cb_priv = board->private_data;
+ nec_priv = &cb_priv->nec7210_priv;
+ nec_priv->read_byte = nec7210_locking_ioport_read_byte;
+ nec_priv->write_byte = nec7210_locking_ioport_write_byte;
+ nec_priv->offset = cb7210_reg_offset;
+ nec_priv->type = CB7210;
+ return 0;
+}
+
+int cb7210_init(struct cb7210_priv *cb_priv, gpib_board_t *board)
+{
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+
+ cb7210_write_byte(cb_priv, HS_RESET7210, HS_INT_LEVEL);
+ cb7210_write_byte(cb_priv, irq_bits(cb_priv->irq), HS_INT_LEVEL);
+
+ nec7210_board_reset(nec_priv, board);
+ cb7210_write_byte(cb_priv, HS_TX_ENABLE | HS_RX_ENABLE | HS_CLR_SRQ_INT |
+ HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT, HS_MODE);
+
+ cb_priv->hs_mode_bits = HS_HF_INT_EN;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE);
+
+ write_byte(nec_priv, AUX_LO_SPEED, AUXMR);
+ /* set clock register for maximum (20 MHz) driving frequency
+ * ICR should be set to clock in megahertz (1-15) and to zero
+ * for clocks faster than 15 MHz (max 20MHz)
+ */
+ write_byte(nec_priv, ICR | 0, AUXMR);
+
+ if (cb_priv->pci_chip == PCI_CHIP_QUANCOM) {
+ /* change interrupt polarity */
+ nec_priv->auxb_bits |= HR_INV;
+ write_byte(nec_priv, nec_priv->auxb_bits, AUXMR);
+ }
+ nec7210_board_online(nec_priv, board);
+
+ /* poll so we can detect assertion of ATN */
+ if (gpib_request_pseudo_irq(board, cb_pci_interrupt)) {
+ pr_err("pc2_gpib: failed to allocate pseudo_irq\n");
+ return -1;
+ }
+ return 0;
+}
+
+int cb_pci_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct cb7210_priv *cb_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = 0;
+ int bits;
+ int retval;
+
+ retval = cb7210_generic_attach(board);
+ if (retval)
+ return retval;
+
+ cb_priv = board->private_data;
+ nec_priv = &cb_priv->nec7210_priv;
+
+ cb_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_CBOARDS,
+ PCI_DEVICE_ID_CBOARDS_PCI_GPIB, NULL);
+ if (cb_priv->pci_device)
+ cb_priv->pci_chip = PCI_CHIP_AMCC_S5933;
+ if (!cb_priv->pci_device) {
+ cb_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_CBOARDS,
+ PCI_DEVICE_ID_CBOARDS_CPCI_GPIB, NULL);
+ if (cb_priv->pci_device)
+ cb_priv->pci_chip = PCI_CHIP_AMCC_S5933;
+ }
+ if (!cb_priv->pci_device) {
+ cb_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_QUANCOM,
+ PCI_DEVICE_ID_QUANCOM_GPIB, NULL);
+ if (cb_priv->pci_device) {
+ cb_priv->pci_chip = PCI_CHIP_QUANCOM;
+ nec_priv->offset = 4;
+ }
+ }
+ if (!cb_priv->pci_device) {
+ pr_warn("cb7210: no supported boards found.\n");
+ return -1;
+ }
+
+ if (pci_enable_device(cb_priv->pci_device)) {
+ pr_err("cb7210: error enabling pci device\n");
+ return -1;
+ }
+
+ if (pci_request_regions(cb_priv->pci_device, "cb7210"))
+ return -1;
+ switch (cb_priv->pci_chip) {
+ case PCI_CHIP_AMCC_S5933:
+ cb_priv->amcc_iobase = pci_resource_start(cb_priv->pci_device, 0);
+ nec_priv->iobase = (void *)(pci_resource_start(cb_priv->pci_device, 1));
+ cb_priv->fifo_iobase = pci_resource_start(cb_priv->pci_device, 2);
+ break;
+ case PCI_CHIP_QUANCOM:
+ nec_priv->iobase = (void *)(pci_resource_start(cb_priv->pci_device, 0));
+ cb_priv->fifo_iobase = (unsigned long)nec_priv->iobase;
+ break;
+ default:
+ pr_err("cb7210: bug! unhandled pci_chip=%i\n", cb_priv->pci_chip);
+ return -EIO;
+ }
+ isr_flags |= IRQF_SHARED;
+ if (request_irq(cb_priv->pci_device->irq, cb_pci_interrupt, isr_flags, "cb7210", board)) {
+ pr_err("cb7210: can't request IRQ %d\n", cb_priv->pci_device->irq);
+ return -1;
+ }
+ cb_priv->irq = cb_priv->pci_device->irq;
+
+ switch (cb_priv->pci_chip) {
+ case PCI_CHIP_AMCC_S5933:
+ // make sure mailbox flags are clear
+ inl(cb_priv->amcc_iobase + INCOMING_MAILBOX_REG(3));
+ // enable interrupts on amccs5933 chip
+ bits = INBOX_FULL_INTR_BIT | INBOX_BYTE_BITS(3) | INBOX_SELECT_BITS(3) |
+ INBOX_INTR_CS_BIT;
+ outl(bits, cb_priv->amcc_iobase + INTCSR_REG);
+ break;
+ default:
+ break;
+ }
+ return cb7210_init(cb_priv, board);
+}
+
+void cb_pci_detach(gpib_board_t *board)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (cb_priv) {
+ gpib_free_pseudo_irq(board);
+ nec_priv = &cb_priv->nec7210_priv;
+ if (cb_priv->irq) {
+ // disable amcc interrupts
+ outl(0, cb_priv->amcc_iobase + INTCSR_REG);
+ free_irq(cb_priv->irq, board);
+ }
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ pci_release_regions(cb_priv->pci_device);
+ }
+ if (cb_priv->pci_device)
+ pci_dev_put(cb_priv->pci_device);
+ }
+ cb7210_generic_detach(board);
+}
+
+int cb_isa_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ int isr_flags = 0;
+ struct cb7210_priv *cb_priv;
+ struct nec7210_priv *nec_priv;
+ unsigned int bits;
+ int retval;
+
+ retval = cb7210_generic_attach(board);
+ if (retval)
+ return retval;
+ cb_priv = board->private_data;
+ nec_priv = &cb_priv->nec7210_priv;
+ if (request_region((unsigned long)config->ibbase, cb7210_iosize, "cb7210") == 0) {
+ pr_err("gpib: ioports starting at 0x%p are already in use\n", config->ibbase);
+ return -EIO;
+ }
+ nec_priv->iobase = config->ibbase;
+ cb_priv->fifo_iobase = nec7210_iobase(cb_priv);
+
+ bits = irq_bits(config->ibirq);
+ if (bits == 0)
+ pr_err("board incapable of using irq %i, try 2-5, 7, 10, or 11\n", config->ibirq);
+
+ // install interrupt handler
+ if (request_irq(config->ibirq, cb7210_interrupt, isr_flags, "cb7210", board)) {
+ pr_err("gpib: can't request IRQ %d\n", config->ibirq);
+ return -EBUSY;
+ }
+ cb_priv->irq = config->ibirq;
+
+ return cb7210_init(cb_priv, board);
+}
+
+void cb_isa_detach(gpib_board_t *board)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (cb_priv) {
+ gpib_free_pseudo_irq(board);
+ nec_priv = &cb_priv->nec7210_priv;
+ if (cb_priv->irq)
+ free_irq(cb_priv->irq, board);
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ release_region(nec7210_iobase(cb_priv), cb7210_iosize);
+ }
+ }
+ cb7210_generic_detach(board);
+}
+
+static int cb7210_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ return 0;
+}
+
+static const struct pci_device_id cb7210_pci_table[] = {
+ {PCI_VENDOR_ID_CBOARDS, PCI_DEVICE_ID_CBOARDS_PCI_GPIB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ {PCI_VENDOR_ID_CBOARDS, PCI_DEVICE_ID_CBOARDS_CPCI_GPIB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ {PCI_VENDOR_ID_QUANCOM, PCI_DEVICE_ID_QUANCOM_GPIB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, cb7210_pci_table);
+
+static struct pci_driver cb7210_pci_driver = {
+ .name = "cb7210",
+ .id_table = cb7210_pci_table,
+ .probe = &cb7210_pci_probe
+};
+
+/***************************************************************************
+ * Support for computer boards pcmcia-gpib card
+ *
+ * Based on gpib PCMCIA client driver written by Claus Schroeter
+ * (clausi@chemie.fu-berlin.de), which was adapted from the
+ * pcmcia skeleton example (presumably David Hinds)
+ ***************************************************************************/
+
+#ifdef GPIB_PCMCIA
+
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/io.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+/*
+ * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
+ * you do not define PCMCIA_DEBUG at all, all the debug code will be
+ * left out. If you compile with PCMCIA_DEBUG=0, the debug code will
+ * be present but disabled -- but it can then be enabled for specific
+ * modules at load time with a 'pc_debug=#' option to insmod.
+ */
+
+#define PCMCIA_DEBUG 1
+
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+#define DEBUG(n, args...) do {if (pc_debug > (n)) pr_debug(args); } while (0)
+#else
+#define DEBUG(args...)
+#endif
+
+/*
+ * The event() function is this driver's Card Services event handler.
+ * It will be called by Card Services when an appropriate card status
+ * event is received. The config() and release() entry points are
+ * used to configure or release a socket, in response to card insertion
+ * and ejection events. They are invoked from the gpib event
+ * handler.
+ */
+
+static int cb_gpib_config(struct pcmcia_device *link);
+static void cb_gpib_release(struct pcmcia_device *link);
+static int cb_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static void cb_pcmcia_detach(gpib_board_t *board);
+
+/*
+ * A linked list of "instances" of the gpib device. Each actual
+ * PCMCIA card corresponds to one device instance, and is described
+ * by one dev_link_t structure (defined in ds.h).
+ *
+ * You may not want to use a linked list for this -- for example, the
+ * memory card driver uses an array of dev_link_t pointers, where minor
+ * device numbers are used to derive the corresponding array index.
+ */
+
+static struct pcmcia_device *curr_dev;
+
+/*
+ * A dev_link_t structure has fields for most things that are needed
+ * to keep track of a socket, but there will usually be some device
+ * specific information that also needs to be kept track of. The
+ * 'priv' pointer in a dev_link_t structure can be used to point to
+ * a device-specific private data structure, like this.
+ *
+ * A driver needs to provide a dev_node_t structure for each device
+ * on a card. In some cases, there is only one device per card (for
+ * example, ethernet cards, modems). In other cases, there may be
+ * many actual or logical devices (SCSI adapters, memory cards with
+ * multiple partitions). The dev_node_t structures need to be kept
+ * in a linked list starting at the 'dev' field of a dev_link_t
+ * structure. We allocate them in the card's private data structure,
+ * because they generally can't be allocated dynamically.
+ */
+
+struct local_info {
+ struct pcmcia_device *p_dev;
+ gpib_board_t *dev;
+};
+
+/*
+ * gpib_attach() creates an "instance" of the driver, allocating
+ * local data structures for one device. The device is registered
+ * with Card Services.
+ *
+ * The dev_link structure is initialized, but we don't actually
+ * configure the card at this point -- we wait until we receive a
+ * card insertion event.
+ */
+
+static int cb_gpib_probe(struct pcmcia_device *link)
+{
+ struct local_info *info;
+
+// int ret, i;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ /* Allocate space for private device-specific data */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->p_dev = link;
+ link->priv = info;
+
+ /* The io structure describes IO port mapping */
+ link->resource[0]->end = 16;
+ link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+ link->resource[1]->end = 16;
+ link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+ link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
+ link->io_lines = 10;
+
+ /* General socket configuration */
+ link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+ link->config_index = 1;
+ link->config_regs = PRESENT_OPTION;
+
+ /* Register with Card Services */
+ curr_dev = link;
+ return cb_gpib_config(link);
+} /* gpib_attach */
+
+/*
+ * This deletes a driver "instance". The device is de-registered
+ * with Card Services. If it has been released, all local data
+ * structures are freed. Otherwise, the structures will be freed
+ * when the device is released.
+ */
+
+static void cb_gpib_remove(struct pcmcia_device *link)
+{
+ struct local_info *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ if (info->dev)
+ cb_pcmcia_detach(info->dev);
+ cb_gpib_release(link);
+
+ //free_netdev(dev);
+ kfree(info);
+}
+
+static int cb_gpib_config_iteration(struct pcmcia_device *link, void *priv_data)
+{
+ return pcmcia_request_io(link);
+}
+
+/*
+ * gpib_config() is scheduled to run after a CARD_INSERTION event
+ * is received, to configure the PCMCIA socket, and to make the
+ * ethernet device available to the system.
+ */
+
+static int cb_gpib_config(struct pcmcia_device *link)
+{
+ struct pcmcia_device *handle;
+ struct local_info *dev;
+ int retval;
+
+ handle = link;
+ dev = link->priv;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ retval = pcmcia_loop_config(link, &cb_gpib_config_iteration, NULL);
+ if (retval) {
+ dev_warn(&link->dev, "no configuration found\n");
+ cb_gpib_release(link);
+ return -ENODEV;
+ }
+
+ DEBUG(0, "gpib_cs: manufacturer: 0x%x card: 0x%x\n", link->manf_id, link->card_id);
+
+ /*
+ * This actually configures the PCMCIA socket -- setting up
+ * the I/O windows and the interrupt mapping.
+ */
+ retval = pcmcia_enable_device(link);
+ if (retval) {
+ dev_warn(&link->dev, "pcmcia_enable_device failed\n");
+ cb_gpib_release(link);
+ return -ENODEV;
+ }
+
+ pr_info("gpib device loaded\n");
+ return 0;
+} /* gpib_config */
+
+/*
+ * After a card is removed, gpib_release() will unregister the net
+ * device, and release the PCMCIA configuration. If the device is
+ * still open, this will be postponed until it is closed.
+ */
+
+static void cb_gpib_release(struct pcmcia_device *link)
+{
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+ pcmcia_disable_device(link);
+}
+
+static int cb_gpib_suspend(struct pcmcia_device *link)
+{
+ //struct local_info *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ if (link->open)
+ pr_warn("Device still open ???\n");
+ //netif_device_detach(dev);
+
+ return 0;
+}
+
+static int cb_gpib_resume(struct pcmcia_device *link)
+{
+ //struct local_info *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ /*if (link->open) {
+ * ni_gpib_probe(dev); / really?
+ * printk("Gpib resumed ???\n");
+ * //netif_device_attach(dev);
+ *
+ */
+ return cb_gpib_config(link);
+}
+
+/*====================================================================*/
+
+static struct pcmcia_device_id cb_pcmcia_ids[] = {
+ PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0005),
+ PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, cb_pcmcia_ids);
+
+static struct pcmcia_driver cb_gpib_cs_driver = {
+ .owner = THIS_MODULE,
+ .drv = { .name = "cb_gpib_cs", },
+ .id_table = cb_pcmcia_ids,
+ .probe = cb_gpib_probe,
+ .remove = cb_gpib_remove,
+ .suspend = cb_gpib_suspend,
+ .resume = cb_gpib_resume,
+};
+
+int cb_pcmcia_init_module(void)
+{
+ pcmcia_register_driver(&cb_gpib_cs_driver);
+ return 0;
+}
+
+void cb_pcmcia_cleanup_module(void)
+{
+ DEBUG(0, "cb_gpib_cs: unloading\n");
+ pcmcia_unregister_driver(&cb_gpib_cs_driver);
+}
+
+gpib_interface_t cb_pcmcia_unaccel_interface = {
+name: "cbi_pcmcia_unaccel",
+attach : cb_pcmcia_attach,
+detach : cb_pcmcia_detach,
+read : cb7210_read,
+write : cb7210_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_pcmcia_interface = {
+name: "cbi_pcmcia",
+attach : cb_pcmcia_attach,
+detach : cb_pcmcia_detach,
+read : cb7210_accel_read,
+write : cb7210_accel_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_pcmcia_accel_interface = {
+name: "cbi_pcmcia_accel",
+attach : cb_pcmcia_attach,
+detach : cb_pcmcia_detach,
+read : cb7210_accel_read,
+write : cb7210_accel_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+int cb_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct cb7210_priv *cb_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+
+ if (!curr_dev) {
+ pr_err("no cb pcmcia cards found\n");
+ return -1;
+ }
+
+ retval = cb7210_generic_attach(board);
+ if (retval)
+ return retval;
+
+ cb_priv = board->private_data;
+ nec_priv = &cb_priv->nec7210_priv;
+
+ if (request_region(curr_dev->resource[0]->start, resource_size(curr_dev->resource[0]),
+ "cb7210") == 0) {
+ pr_err("gpib: ioports starting at 0x%lx are already in use\n",
+ (unsigned long)curr_dev->resource[0]->start);
+ return -EIO;
+ }
+ nec_priv->iobase = (void *)(unsigned long)curr_dev->resource[0]->start;
+ cb_priv->fifo_iobase = curr_dev->resource[0]->start;
+
+ if (request_irq(curr_dev->irq, cb7210_interrupt, IRQF_SHARED,
+ "cb7210", board)) {
+ pr_err("cb7210: failed to request IRQ %d\n", curr_dev->irq);
+ return -1;
+ }
+ cb_priv->irq = curr_dev->irq;
+
+ return cb7210_init(cb_priv, board);
+}
+
+void cb_pcmcia_detach(gpib_board_t *board)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (cb_priv) {
+ nec_priv = &cb_priv->nec7210_priv;
+ gpib_free_pseudo_irq(board);
+ if (cb_priv->irq)
+ free_irq(cb_priv->irq, board);
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ release_region(nec7210_iobase(cb_priv), cb7210_iosize);
+ }
+ }
+ cb7210_generic_detach(board);
+}
+
+#endif /* GPIB_PCMCIA */
+
+static int __init cb7210_init_module(void)
+{
+ int err = 0;
+ int result;
+
+ result = pci_register_driver(&cb7210_pci_driver);
+ if (result) {
+ pr_err("cb7210: pci_driver_register failed!\n");
+ return result;
+ }
+
+ gpib_register_driver(&cb_pci_interface, THIS_MODULE);
+ gpib_register_driver(&cb_isa_interface, THIS_MODULE);
+ gpib_register_driver(&cb_pci_accel_interface, THIS_MODULE);
+ gpib_register_driver(&cb_pci_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&cb_isa_accel_interface, THIS_MODULE);
+ gpib_register_driver(&cb_isa_unaccel_interface, THIS_MODULE);
+
+#ifdef GPIB__PCMCIA
+ gpib_register_driver(&cb_pcmcia_interface, THIS_MODULE);
+ gpib_register_driver(&cb_pcmcia_accel_interface, THIS_MODULE);
+ gpib_register_driver(&cb_pcmcia_unaccel_interface, THIS_MODULE);
+ err += cb_pcmcia_init_module();
+#endif
+ if (err)
+ return -1;
+
+ return 0;
+}
+
+static void __exit cb7210_exit_module(void)
+{
+ gpib_unregister_driver(&cb_pci_interface);
+ gpib_unregister_driver(&cb_isa_interface);
+ gpib_unregister_driver(&cb_pci_accel_interface);
+ gpib_unregister_driver(&cb_pci_unaccel_interface);
+ gpib_unregister_driver(&cb_isa_accel_interface);
+ gpib_unregister_driver(&cb_isa_unaccel_interface);
+#ifdef GPIB_PCMCIA
+ gpib_unregister_driver(&cb_pcmcia_interface);
+ gpib_unregister_driver(&cb_pcmcia_accel_interface);
+ gpib_unregister_driver(&cb_pcmcia_unaccel_interface);
+ cb_pcmcia_cleanup_module();
+#endif
+
+ pci_unregister_driver(&cb7210_pci_driver);
+}
+
+module_init(cb7210_init_module);
+module_exit(cb7210_exit_module);
diff --git a/drivers/staging/gpib/cb7210/cb7210.h b/drivers/staging/gpib/cb7210/cb7210.h
new file mode 100644
index 000000000000..4ad976de2b68
--- /dev/null
+++ b/drivers/staging/gpib/cb7210/cb7210.h
@@ -0,0 +1,251 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "nec7210.h"
+#include "gpibP.h"
+#include "amccs5933.h"
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+enum {
+ PCI_DEVICE_ID_CBOARDS_PCI_GPIB = 0x6,
+ PCI_DEVICE_ID_CBOARDS_CPCI_GPIB = 0xe,
+};
+
+enum pci_chip {
+ PCI_CHIP_NONE = 0,
+ PCI_CHIP_AMCC_S5933,
+ PCI_CHIP_QUANCOM
+};
+
+// struct which defines private_data for cb7210 boards
+struct cb7210_priv {
+ struct nec7210_priv nec7210_priv;
+ struct pci_dev *pci_device;
+ // base address of amccs5933 pci chip
+ unsigned long amcc_iobase;
+ unsigned long fifo_iobase;
+ unsigned int irq;
+ enum pci_chip pci_chip;
+ u8 hs_mode_bits;
+ unsigned out_fifo_half_empty : 1;
+ unsigned in_fifo_half_full : 1;
+};
+
+// interfaces
+extern gpib_interface_t cb_pcmcia_interface;
+extern gpib_interface_t cb_pcmcia_accel_interface;
+extern gpib_interface_t cb_pcmcia_unaccel_interface;
+
+// interrupt service routines
+irqreturn_t cb_pci_interrupt(int irq, void *arg);
+irqreturn_t cb7210_interrupt(int irq, void *arg);
+irqreturn_t cb7210_internal_interrupt(gpib_board_t *board);
+
+// interface functions
+int cb7210_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read);
+int cb7210_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read);
+int cb7210_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+int cb7210_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+int cb7210_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written);
+int cb7210_take_control(gpib_board_t *board, int synchronous);
+int cb7210_go_to_standby(gpib_board_t *board);
+void cb7210_request_system_control(gpib_board_t *board, int request_control);
+void cb7210_interface_clear(gpib_board_t *board, int assert);
+void cb7210_remote_enable(gpib_board_t *board, int enable);
+int cb7210_enable_eos(gpib_board_t *board, uint8_t eos_byte,
+ int compare_8_bits);
+void cb7210_disable_eos(gpib_board_t *board);
+unsigned int cb7210_update_status(gpib_board_t *board, unsigned int clear_mask);
+int cb7210_primary_address(gpib_board_t *board, unsigned int address);
+int cb7210_secondary_address(gpib_board_t *board, unsigned int address,
+ int enable);
+int cb7210_parallel_poll(gpib_board_t *board, uint8_t *result);
+void cb7210_serial_poll_response(gpib_board_t *board, uint8_t status);
+uint8_t cb7210_serial_poll_status(gpib_board_t *board);
+void cb7210_parallel_poll_configure(gpib_board_t *board, uint8_t configuration);
+void cb7210_parallel_poll_response(gpib_board_t *board, int ist);
+int cb7210_line_status(const gpib_board_t *board);
+unsigned int cb7210_t1_delay(gpib_board_t *board, unsigned int nano_sec);
+void cb7210_return_to_local(gpib_board_t *board);
+
+// utility functions
+void cb7210_generic_detach(gpib_board_t *board);
+int cb7210_generic_attach(gpib_board_t *board);
+int cb7210_init(struct cb7210_priv *priv, gpib_board_t *board);
+
+// pcmcia init/cleanup
+int cb_pcmcia_init_module(void);
+void cb_pcmcia_cleanup_module(void);
+
+// pci-gpib register offset
+static const int cb7210_reg_offset = 1;
+
+// uses 10 ioports
+static const int cb7210_iosize = 10;
+
+// fifo size in bytes
+static const int cb7210_fifo_size = 2048;
+static const int cb7210_fifo_width = 2;
+
+// cb7210 specific registers and bits
+enum cb7210_regs {
+ BUS_STATUS = 0x7,
+};
+
+enum cb7210_page_in {
+ BUS_STATUS_PAGE = 1,
+};
+
+enum hs_regs {
+ //write registers
+ HS_MODE = 0x8, /* HS_MODE register */
+ HS_INT_LEVEL = 0x9, /* HS_INT_LEVEL register */
+ //read registers
+ HS_STATUS = 0x8, /* HS_STATUS register */
+};
+
+static inline unsigned long nec7210_iobase(const struct cb7210_priv *cb_priv)
+{
+ return (unsigned long)(cb_priv->nec7210_priv.iobase);
+}
+
+static inline int cb7210_page_in_bits(unsigned int page)
+{
+ return 0x50 | (page & 0xf);
+}
+
+static inline uint8_t cb7210_paged_read_byte(struct cb7210_priv *cb_priv,
+ unsigned int register_num, unsigned int page)
+{
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ u8 retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nec_priv->register_page_lock, flags);
+ outb(cb7210_page_in_bits(page), nec7210_iobase(cb_priv) + AUXMR * nec_priv->offset);
+ udelay(1);
+ retval = inb(nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
+ spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
+ return retval;
+}
+
+// don't use for register_num < 8, since it doesn't lock
+static inline uint8_t cb7210_read_byte(const struct cb7210_priv *cb_priv,
+ enum hs_regs register_num)
+{
+ const struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ u8 retval;
+
+ retval = inb(nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
+ return retval;
+}
+
+static inline void cb7210_paged_write_byte(struct cb7210_priv *cb_priv, uint8_t data,
+ unsigned int register_num, unsigned int page)
+{
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nec_priv->register_page_lock, flags);
+ outb(cb7210_page_in_bits(page), nec7210_iobase(cb_priv) + AUXMR * nec_priv->offset);
+ udelay(1);
+ outb(data, nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
+ spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
+}
+
+// don't use for register_num < 8, since it doesn't lock
+static inline void cb7210_write_byte(const struct cb7210_priv *cb_priv, uint8_t data,
+ enum hs_regs register_num)
+{
+ const struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+
+ outb(data, nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
+}
+
+enum bus_status_bits {
+ BSR_ATN_BIT = 0x1,
+ BSR_EOI_BIT = 0x2,
+ BSR_SRQ_BIT = 0x4,
+ BSR_IFC_BIT = 0x8,
+ BSR_REN_BIT = 0x10,
+ BSR_DAV_BIT = 0x20,
+ BSR_NRFD_BIT = 0x40,
+ BSR_NDAC_BIT = 0x80,
+};
+
+/* CBI 488.2 HS control */
+
+/* when both bit 0 and 1 are set, it
+ * 1 clears the transmit state machine to an initial condition
+ * 2 clears any residual interrupts left latched on cbi488.2
+ * 3 resets all control bits in HS_MODE to zero
+ * 4 enables TX empty interrupts
+ * when both bit 0 and 1 are zero, then the high speed mode is disabled
+ */
+enum hs_mode_bits {
+ HS_ENABLE_MASK = 0x3,
+ HS_TX_ENABLE = (1 << 0),
+ HS_RX_ENABLE = (1 << 1),
+ HS_HF_INT_EN = (1 << 3),
+ HS_CLR_SRQ_INT = (1 << 4),
+ HS_CLR_EOI_EMPTY_INT = (1 << 5),
+ HS_CLR_HF_INT = (1 << 6),
+ HS_SYS_CONTROL = (1 << 7),
+};
+
+/* CBI 488.2 status */
+enum hs_status_bits {
+ HS_FIFO_FULL = (1 << 0),
+ HS_HALF_FULL = (1 << 1),
+ HS_SRQ_INT = (1 << 2),
+ HS_EOI_INT = (1 << 3),
+ HS_TX_MSB_NOT_EMPTY = (1 << 4),
+ HS_RX_MSB_NOT_EMPTY = (1 << 5),
+ HS_TX_LSB_NOT_EMPTY = (1 << 6),
+ HS_RX_LSB_NOT_EMPTY = (1 << 7),
+};
+
+/* CBI488.2 hs_int_level register */
+enum hs_int_level_bits {
+ HS_RESET7210 = (1 << 7),
+};
+
+static inline unsigned int irq_bits(unsigned int irq)
+{
+ switch (irq) {
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ return irq - 1;
+ case 7:
+ return 0x5;
+ case 10:
+ return 0x6;
+ case 11:
+ return 0x7;
+ default:
+ return 0;
+ }
+}
+
+enum cb7210_aux_cmds {
+/* AUX_RTL2 is an undocumented aux command which causes cb7210 to assert
+ * (and keep asserted) local rtl message. This is used in conjunction
+ * with the (stupid) cb7210 implementation
+ * of the normal nec7210 AUX_RTL aux command, which
+ * causes the rtl message to toggle between on and off.
+ */
+ AUX_RTL2 = 0xd,
+ AUX_LO_SPEED = 0x40,
+ AUX_HI_SPEED = 0x41,
+};
diff --git a/drivers/staging/gpib/cec/Makefile b/drivers/staging/gpib/cec/Makefile
new file mode 100644
index 000000000000..f4638628ff29
--- /dev/null
+++ b/drivers/staging/gpib/cec/Makefile
@@ -0,0 +1,3 @@
+
+obj-m += cec_gpib.o
+
diff --git a/drivers/staging/gpib/cec/cec.h b/drivers/staging/gpib/cec/cec.h
new file mode 100644
index 000000000000..352cf83d8328
--- /dev/null
+++ b/drivers/staging/gpib/cec/cec.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "nec7210.h"
+#include "gpibP.h"
+#include "plx9050.h"
+
+struct cec_priv {
+ struct nec7210_priv nec7210_priv;
+ struct pci_dev *pci_device;
+ // base address for plx9052 pci chip
+ unsigned long plx_iobase;
+ unsigned int irq;
+};
+
+// interfaces
+extern gpib_interface_t cec_pci_interface;
+extern gpib_interface_t cec_pcmcia_interface;
+
+// interface functions
+int cec_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read);
+int cec_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written);
+int cec_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written);
+int cec_take_control(gpib_board_t *board, int synchronous);
+int cec_go_to_standby(gpib_board_t *board);
+void cec_request_system_control(gpib_board_t *board, int request_control);
+void cec_interface_clear(gpib_board_t *board, int assert);
+void cec_remote_enable(gpib_board_t *board, int enable);
+int cec_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits);
+void cec_disable_eos(gpib_board_t *board);
+unsigned int cec_update_status(gpib_board_t *board, unsigned int clear_mask);
+int cec_primary_address(gpib_board_t *board, unsigned int address);
+int cec_secondary_address(gpib_board_t *board, unsigned int address, int enable);
+int cec_parallel_poll(gpib_board_t *board, uint8_t *result);
+void cec_parallel_poll_configure(gpib_board_t *board, uint8_t configuration);
+void cec_parallel_poll_response(gpib_board_t *board, int ist);
+void cec_serial_poll_response(gpib_board_t *board, uint8_t status);
+void cec_return_to_local(gpib_board_t *board);
+
+// interrupt service routines
+irqreturn_t cec_interrupt(int irq, void *arg);
+
+// utility functions
+void cec_free_private(gpib_board_t *board);
+int cec_generic_attach(gpib_board_t *board);
+void cec_init(struct cec_priv *priv, const gpib_board_t *board);
+
+// offset between consecutive nec7210 registers
+static const int cec_reg_offset = 1;
diff --git a/drivers/staging/gpib/cec/cec_gpib.c b/drivers/staging/gpib/cec/cec_gpib.c
new file mode 100644
index 000000000000..3dc933deb401
--- /dev/null
+++ b/drivers/staging/gpib/cec/cec_gpib.c
@@ -0,0 +1,385 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "cec.h"
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <asm/dma.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for CEC PCI and PCMCIA boards");
+
+/*
+ * GPIB interrupt service routines
+ */
+
+irqreturn_t cec_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct cec_priv *priv = board->private_data;
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = nec7210_interrupt(board, &priv->nec7210_priv);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+#define CEC_VENDOR_ID 0x12fc
+#define CEC_DEV_ID 0x5cec
+#define CEC_SUBID 0x9050
+
+static int cec_pci_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void cec_pci_detach(gpib_board_t *board);
+
+// wrappers for interface functions
+int cec_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+}
+
+int cec_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int cec_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+int cec_take_control(gpib_board_t *board, int synchronous)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+int cec_go_to_standby(gpib_board_t *board)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+void cec_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_request_system_control(board, &priv->nec7210_priv, request_control);
+}
+
+void cec_interface_clear(gpib_board_t *board, int assert)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+void cec_remote_enable(gpib_board_t *board, int enable)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+int cec_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+void cec_disable_eos(gpib_board_t *board)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+unsigned int cec_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
+}
+
+int cec_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+int cec_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+int cec_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
+}
+
+void cec_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config);
+}
+
+void cec_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+void cec_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
+}
+
+static uint8_t cec_serial_poll_status(gpib_board_t *board)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+static unsigned int cec_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_t1_delay(board, &priv->nec7210_priv, nano_sec);
+}
+
+void cec_return_to_local(gpib_board_t *board)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_return_to_local(board, &priv->nec7210_priv);
+}
+
+gpib_interface_t cec_pci_interface = {
+name: "cec_pci",
+attach : cec_pci_attach,
+detach : cec_pci_detach,
+read : cec_read,
+write : cec_write,
+command : cec_command,
+take_control : cec_take_control,
+go_to_standby : cec_go_to_standby,
+request_system_control : cec_request_system_control,
+interface_clear : cec_interface_clear,
+remote_enable : cec_remote_enable,
+enable_eos : cec_enable_eos,
+disable_eos : cec_disable_eos,
+parallel_poll : cec_parallel_poll,
+parallel_poll_configure : cec_parallel_poll_configure,
+parallel_poll_response : cec_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL, //XXX
+update_status : cec_update_status,
+primary_address : cec_primary_address,
+secondary_address : cec_secondary_address,
+serial_poll_response : cec_serial_poll_response,
+serial_poll_status : cec_serial_poll_status,
+t1_delay : cec_t1_delay,
+return_to_local : cec_return_to_local,
+};
+
+static int cec_allocate_private(gpib_board_t *board)
+{
+ struct cec_priv *priv;
+
+ board->private_data = kmalloc(sizeof(struct cec_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ priv = board->private_data;
+ memset(priv, 0, sizeof(struct cec_priv));
+ init_nec7210_private(&priv->nec7210_priv);
+ return 0;
+}
+
+void cec_free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+int cec_generic_attach(gpib_board_t *board)
+{
+ struct cec_priv *cec_priv;
+ struct nec7210_priv *nec_priv;
+
+ board->status = 0;
+
+ if (cec_allocate_private(board))
+ return -ENOMEM;
+ cec_priv = board->private_data;
+ nec_priv = &cec_priv->nec7210_priv;
+ nec_priv->read_byte = nec7210_ioport_read_byte;
+ nec_priv->write_byte = nec7210_ioport_write_byte;
+ nec_priv->offset = cec_reg_offset;
+ nec_priv->type = NEC7210; // guess
+ return 0;
+}
+
+void cec_init(struct cec_priv *cec_priv, const gpib_board_t *board)
+{
+ struct nec7210_priv *nec_priv = &cec_priv->nec7210_priv;
+
+ nec7210_board_reset(nec_priv, board);
+
+ /* set internal counter register for 8 MHz input clock */
+ write_byte(nec_priv, ICR | 8, AUXMR);
+
+ nec7210_board_online(nec_priv, board);
+}
+
+int cec_pci_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct cec_priv *cec_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = 0;
+ int retval;
+
+ retval = cec_generic_attach(board);
+ if (retval)
+ return retval;
+
+ cec_priv = board->private_data;
+ nec_priv = &cec_priv->nec7210_priv;
+
+ // find board
+ cec_priv->pci_device = NULL;
+ while ((cec_priv->pci_device =
+ gpib_pci_get_device(config, CEC_VENDOR_ID,
+ CEC_DEV_ID, cec_priv->pci_device))) {
+ // check for board with plx9050 controller
+ if (cec_priv->pci_device->subsystem_device == CEC_SUBID)
+ break;
+ }
+ if (!cec_priv->pci_device) {
+ pr_err("gpib: no cec PCI board found\n");
+ return -1;
+ }
+
+ if (pci_enable_device(cec_priv->pci_device)) {
+ pr_err("error enabling pci device\n");
+ return -1;
+ }
+
+ if (pci_request_regions(cec_priv->pci_device, "cec-gpib"))
+ return -1;
+
+ cec_priv->plx_iobase = pci_resource_start(cec_priv->pci_device, 1);
+ pr_info(" plx9050 base address 0x%lx\n", cec_priv->plx_iobase);
+ nec_priv->iobase = (void *)(pci_resource_start(cec_priv->pci_device, 3));
+ pr_info(" nec7210 base address 0x%p\n", nec_priv->iobase);
+
+ isr_flags |= IRQF_SHARED;
+ if (request_irq(cec_priv->pci_device->irq, cec_interrupt, isr_flags, "pci-gpib", board)) {
+ pr_err("gpib: can't request IRQ %d\n", cec_priv->pci_device->irq);
+ return -1;
+ }
+ cec_priv->irq = cec_priv->pci_device->irq;
+ if (gpib_request_pseudo_irq(board, cec_interrupt)) {
+ pr_err("cec: failed to allocate pseudo irq\n");
+ return -1;
+ }
+ cec_init(cec_priv, board);
+
+ // enable interrupts on plx chip
+ outl(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR1_POLARITY_BIT | PLX9050_PCI_INTR_EN_BIT,
+ cec_priv->plx_iobase + PLX9050_INTCSR_REG);
+
+ return 0;
+}
+
+void cec_pci_detach(gpib_board_t *board)
+{
+ struct cec_priv *cec_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (cec_priv) {
+ nec_priv = &cec_priv->nec7210_priv;
+ gpib_free_pseudo_irq(board);
+ if (cec_priv->irq) {
+ // disable plx9050 interrupts
+ outl(0, cec_priv->plx_iobase + PLX9050_INTCSR_REG);
+ free_irq(cec_priv->irq, board);
+ }
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ pci_release_regions(cec_priv->pci_device);
+ }
+ if (cec_priv->pci_device)
+ pci_dev_put(cec_priv->pci_device);
+ }
+ cec_free_private(board);
+}
+
+static int cec_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ return 0;
+}
+
+static const struct pci_device_id cec_pci_table[] = {
+ {CEC_VENDOR_ID, CEC_DEV_ID, PCI_ANY_ID, CEC_SUBID, 0, 0, 0 },
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, cec_pci_table);
+
+static struct pci_driver cec_pci_driver = {
+ .name = "cec_gpib",
+ .id_table = cec_pci_table,
+ .probe = &cec_pci_probe
+};
+
+static int __init cec_init_module(void)
+{
+ int result;
+
+ result = pci_register_driver(&cec_pci_driver);
+ if (result) {
+ pr_err("cec_gpib: pci_driver_register failed!\n");
+ return result;
+ }
+
+ gpib_register_driver(&cec_pci_interface, THIS_MODULE);
+
+ return 0;
+}
+
+static void cec_exit_module(void)
+{
+ gpib_unregister_driver(&cec_pci_interface);
+
+ pci_unregister_driver(&cec_pci_driver);
+}
+
+module_init(cec_init_module);
+module_exit(cec_exit_module);
diff --git a/drivers/staging/gpib/common/Makefile b/drivers/staging/gpib/common/Makefile
new file mode 100644
index 000000000000..0c4c77bea75b
--- /dev/null
+++ b/drivers/staging/gpib/common/Makefile
@@ -0,0 +1,6 @@
+
+obj-m += gpib_common.o
+
+gpib_common-objs := gpib_os.o iblib.o
+
+
diff --git a/drivers/staging/gpib/common/gpib_os.c b/drivers/staging/gpib/common/gpib_os.c
new file mode 100644
index 000000000000..405237d8cb47
--- /dev/null
+++ b/drivers/staging/gpib/common/gpib_os.c
@@ -0,0 +1,2328 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2001, 2004 by Frank Mori Hess
+ ***************************************************************************
+ */
+
+#include "ibsys.h"
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <linux/fcntl.h>
+#include <linux/kmod.h>
+#include <linux/uaccess.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB base support");
+MODULE_ALIAS_CHARDEV_MAJOR(GPIB_CODE);
+
+static int board_type_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, unsigned long arg);
+static int read_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board,
+ unsigned long arg);
+static int write_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board,
+ unsigned long arg);
+static int command_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board,
+ unsigned long arg);
+static int open_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg);
+static int close_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg);
+static int serial_poll_ioctl(gpib_board_t *board, unsigned long arg);
+static int wait_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, unsigned long arg);
+static int parallel_poll_ioctl(gpib_board_t *board, unsigned long arg);
+static int online_ioctl(gpib_board_t *board, unsigned long arg);
+static int remote_enable_ioctl(gpib_board_t *board, unsigned long arg);
+static int take_control_ioctl(gpib_board_t *board, unsigned long arg);
+static int line_status_ioctl(gpib_board_t *board, unsigned long arg);
+static int pad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg);
+static int sad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg);
+static int eos_ioctl(gpib_board_t *board, unsigned long arg);
+static int request_service_ioctl(gpib_board_t *board, unsigned long arg);
+static int request_service2_ioctl(gpib_board_t *board, unsigned long arg);
+static int iobase_ioctl(gpib_board_config_t *config, unsigned long arg);
+static int irq_ioctl(gpib_board_config_t *config, unsigned long arg);
+static int dma_ioctl(gpib_board_config_t *config, unsigned long arg);
+static int autospoll_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg);
+static int mutex_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg);
+static int timeout_ioctl(gpib_board_t *board, unsigned long arg);
+static int status_bytes_ioctl(gpib_board_t *board, unsigned long arg);
+static int board_info_ioctl(const gpib_board_t *board, unsigned long arg);
+static int ppc_ioctl(gpib_board_t *board, unsigned long arg);
+static int set_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg);
+static int get_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg);
+static int query_board_rsv_ioctl(gpib_board_t *board, unsigned long arg);
+static int interface_clear_ioctl(gpib_board_t *board, unsigned long arg);
+static int select_pci_ioctl(gpib_board_config_t *config, unsigned long arg);
+static int select_device_path_ioctl(gpib_board_config_t *config, unsigned long arg);
+static int event_ioctl(gpib_board_t *board, unsigned long arg);
+static int request_system_control_ioctl(gpib_board_t *board, unsigned long arg);
+static int t1_delay_ioctl(gpib_board_t *board, unsigned long arg);
+
+static int cleanup_open_devices(gpib_file_private_t *file_priv, gpib_board_t *board);
+
+static int pop_gpib_event_nolock(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type);
+
+/*
+ * Timer functions
+ */
+
+/* Watchdog timeout routine */
+
+static void watchdog_timeout(struct timer_list *t)
+{
+ gpib_board_t *board = from_timer(board, t, timer);
+
+ set_bit(TIMO_NUM, &board->status);
+ wake_up_interruptible(&board->wait);
+}
+
+/* install timer interrupt handler */
+void os_start_timer(gpib_board_t *board, unsigned int usec_timeout)
+/* Starts the timeout task */
+{
+ if (timer_pending(&board->timer)) {
+ pr_err("gpib: bug! timer already running?\n");
+ return;
+ }
+ clear_bit(TIMO_NUM, &board->status);
+
+ if (usec_timeout > 0) {
+ board->timer.function = watchdog_timeout;
+ /* set number of ticks */
+ mod_timer(&board->timer, jiffies + usec_to_jiffies(usec_timeout));
+ }
+}
+
+void os_remove_timer(gpib_board_t *board)
+/* Removes the timeout task */
+{
+ if (timer_pending(&board->timer))
+ del_timer_sync(&board->timer);
+}
+
+int io_timed_out(gpib_board_t *board)
+{
+ if (test_bit(TIMO_NUM, &board->status))
+ return 1;
+ return 0;
+}
+
+void writeb_wrapper(unsigned int value, void *address)
+{
+ writeb(value, address);
+};
+EXPORT_SYMBOL(writeb_wrapper);
+
+void writew_wrapper(unsigned int value, void *address)
+{
+ writew(value, address);
+};
+EXPORT_SYMBOL(writew_wrapper);
+
+unsigned int readb_wrapper(void *address)
+{
+ return readb(address);
+};
+EXPORT_SYMBOL(readb_wrapper);
+
+unsigned int readw_wrapper(void *address)
+{
+ return readw(address);
+};
+EXPORT_SYMBOL(readw_wrapper);
+
+#ifdef CONFIG_HAS_IOPORT
+void outb_wrapper(unsigned int value, void *address)
+{
+ outb(value, (unsigned long)(address));
+};
+EXPORT_SYMBOL(outb_wrapper);
+
+void outw_wrapper(unsigned int value, void *address)
+{
+ outw(value, (unsigned long)(address));
+};
+EXPORT_SYMBOL(outw_wrapper);
+
+unsigned int inb_wrapper(void *address)
+{
+ return inb((unsigned long)(address));
+};
+EXPORT_SYMBOL(inb_wrapper);
+
+unsigned int inw_wrapper(void *address)
+{
+ return inw((unsigned long)(address));
+};
+EXPORT_SYMBOL(inw_wrapper);
+#endif
+
+/* this is a function instead of a constant because of Suse
+ * defining HZ to be a function call to get_hz()
+ */
+static inline int pseudo_irq_period(void)
+{
+ return (HZ + 99) / 100;
+}
+
+static void pseudo_irq_handler(struct timer_list *t)
+{
+ struct gpib_pseudo_irq *pseudo_irq = from_timer(pseudo_irq, t, timer);
+
+ if (pseudo_irq->handler)
+ pseudo_irq->handler(0, pseudo_irq->board);
+ else
+ pr_err("gpib: bug! pseudo_irq.handler is NULL\n");
+
+ if (atomic_read(&pseudo_irq->active))
+ mod_timer(&pseudo_irq->timer, jiffies + pseudo_irq_period());
+}
+
+int gpib_request_pseudo_irq(gpib_board_t *board, irqreturn_t (*handler)(int, void *))
+{
+ if (timer_pending(&board->pseudo_irq.timer) || board->pseudo_irq.handler) {
+ pr_err("gpib: only one pseudo interrupt per board allowed\n");
+ return -1;
+ }
+
+ board->pseudo_irq.handler = handler;
+ board->pseudo_irq.timer.function = pseudo_irq_handler;
+ board->pseudo_irq.board = board;
+
+ atomic_set(&board->pseudo_irq.active, 1);
+
+ mod_timer(&board->pseudo_irq.timer, jiffies + pseudo_irq_period());
+
+ return 0;
+}
+EXPORT_SYMBOL(gpib_request_pseudo_irq);
+
+void gpib_free_pseudo_irq(gpib_board_t *board)
+{
+ atomic_set(&board->pseudo_irq.active, 0);
+
+ del_timer_sync(&board->pseudo_irq.timer);
+ board->pseudo_irq.handler = NULL;
+}
+EXPORT_SYMBOL(gpib_free_pseudo_irq);
+
+static const unsigned int serial_timeout = 1000000;
+
+unsigned int num_status_bytes(const gpib_status_queue_t *dev)
+{
+ if (!dev)
+ return 0;
+ return dev->num_status_bytes;
+}
+
+// push status byte onto back of status byte fifo
+int push_status_byte(gpib_board_t *board, gpib_status_queue_t *device, u8 poll_byte)
+{
+ struct list_head *head = &device->status_bytes;
+ status_byte_t *status;
+ static const unsigned int max_num_status_bytes = 1024;
+ int retval;
+
+ if (num_status_bytes(device) >= max_num_status_bytes) {
+ u8 lost_byte;
+
+ device->dropped_byte = 1;
+ retval = pop_status_byte(board, device, &lost_byte);
+ if (retval < 0)
+ return retval;
+ }
+
+ status = kmalloc(sizeof(status_byte_t), GFP_KERNEL);
+ if (!status)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&status->list);
+ status->poll_byte = poll_byte;
+
+ list_add_tail(&status->list, head);
+
+ device->num_status_bytes++;
+
+ dev_dbg(board->gpib_dev, "pushed status byte 0x%x, %i in queue\n",
+ (int)poll_byte, num_status_bytes(device));
+
+ return 0;
+}
+
+// pop status byte from front of status byte fifo
+int pop_status_byte(gpib_board_t *board, gpib_status_queue_t *device, u8 *poll_byte)
+{
+ struct list_head *head = &device->status_bytes;
+ struct list_head *front = head->next;
+ status_byte_t *status;
+
+ if (num_status_bytes(device) == 0)
+ return -EIO;
+
+ if (front == head)
+ return -EIO;
+
+ if (device->dropped_byte) {
+ device->dropped_byte = 0;
+ return -EPIPE;
+ }
+
+ status = list_entry(front, status_byte_t, list);
+ *poll_byte = status->poll_byte;
+
+ list_del(front);
+ kfree(status);
+
+ device->num_status_bytes--;
+
+ dev_dbg(board->gpib_dev, "popped status byte 0x%x, %i in queue\n",
+ (int)*poll_byte, num_status_bytes(device));
+
+ return 0;
+}
+
+gpib_status_queue_t *get_gpib_status_queue(gpib_board_t *board, unsigned int pad, int sad)
+{
+ gpib_status_queue_t *device;
+ struct list_head *list_ptr;
+ const struct list_head *head = &board->device_list;
+
+ for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) {
+ device = list_entry(list_ptr, gpib_status_queue_t, list);
+ if (gpib_address_equal(device->pad, device->sad, pad, sad))
+ return device;
+ }
+
+ return NULL;
+}
+
+int get_serial_poll_byte(gpib_board_t *board, unsigned int pad, int sad, unsigned int usec_timeout,
+ uint8_t *poll_byte)
+{
+ gpib_status_queue_t *device;
+
+ dev_dbg(board->gpib_dev, "%s:()\n", __func__);
+
+ device = get_gpib_status_queue(board, pad, sad);
+ if (num_status_bytes(device))
+ return pop_status_byte(board, device, poll_byte);
+ else
+ return dvrsp(board, pad, sad, usec_timeout, poll_byte);
+}
+
+int autopoll_all_devices(gpib_board_t *board)
+{
+ int retval;
+
+ dev_dbg(board->gpib_dev, "entering %s()\n", __func__);
+ if (mutex_lock_interruptible(&board->user_mutex))
+ return -ERESTARTSYS;
+ if (mutex_lock_interruptible(&board->big_gpib_mutex)) {
+ mutex_unlock(&board->user_mutex);
+ return -ERESTARTSYS;
+ }
+
+ dev_dbg(board->gpib_dev, "autopoll has board lock\n");
+
+ retval = serial_poll_all(board, serial_timeout);
+ if (retval < 0) {
+ mutex_unlock(&board->big_gpib_mutex);
+ mutex_unlock(&board->user_mutex);
+ return retval;
+ }
+
+ dev_dbg(board->gpib_dev, "%s complete\n", __func__);
+ /* need to wake wait queue in case someone is
+ * waiting on RQS
+ */
+ wake_up_interruptible(&board->wait);
+ mutex_unlock(&board->big_gpib_mutex);
+ mutex_unlock(&board->user_mutex);
+
+ return retval;
+}
+
+static int setup_serial_poll(gpib_board_t *board, unsigned int usec_timeout)
+{
+ u8 cmd_string[8];
+ int i;
+ size_t bytes_written;
+ int ret;
+
+ dev_dbg(board->gpib_dev, "entering %s()\n", __func__);
+
+ os_start_timer(board, usec_timeout);
+ ret = ibcac(board, 1, 1);
+ if (ret < 0) {
+ os_remove_timer(board);
+ return ret;
+ }
+
+ i = 0;
+ cmd_string[i++] = UNL;
+ cmd_string[i++] = MLA(board->pad); /* controller's listen address */
+ if (board->sad >= 0)
+ cmd_string[i++] = MSA(board->sad);
+ cmd_string[i++] = SPE; //serial poll enable
+
+ ret = board->interface->command(board, cmd_string, i, &bytes_written);
+ if (ret < 0 || bytes_written < i) {
+ pr_err("gpib: failed to setup serial poll\n");
+ os_remove_timer(board);
+ return -EIO;
+ }
+ os_remove_timer(board);
+
+ return 0;
+}
+
+static int read_serial_poll_byte(gpib_board_t *board, unsigned int pad,
+ int sad, unsigned int usec_timeout, uint8_t *result)
+{
+ u8 cmd_string[8];
+ int end_flag;
+ int ret;
+ int i;
+ size_t nbytes;
+
+ dev_dbg(board->gpib_dev, "entering %s(), pad=%i sad=%i\n", __func__, pad, sad);
+
+ os_start_timer(board, usec_timeout);
+ ret = ibcac(board, 1, 1);
+ if (ret < 0) {
+ os_remove_timer(board);
+ return ret;
+ }
+
+ i = 0;
+ // send talk address
+ cmd_string[i++] = MTA(pad);
+ if (sad >= 0)
+ cmd_string[i++] = MSA(sad);
+
+ ret = board->interface->command(board, cmd_string, i, &nbytes);
+ if (ret < 0 || nbytes < i) {
+ pr_err("gpib: failed to setup serial poll\n");
+ os_remove_timer(board);
+ return -EIO;
+ }
+
+ ibgts(board);
+
+ // read poll result
+ ret = board->interface->read(board, result, 1, &end_flag, &nbytes);
+ if (ret < 0 || nbytes < 1) {
+ pr_err("gpib: serial poll failed\n");
+ os_remove_timer(board);
+ return -EIO;
+ }
+ os_remove_timer(board);
+
+ return 0;
+}
+
+static int cleanup_serial_poll(gpib_board_t *board, unsigned int usec_timeout)
+{
+ u8 cmd_string[8];
+ int ret;
+ size_t bytes_written;
+
+ dev_dbg(board->gpib_dev, "entering %s()\n", __func__);
+
+ os_start_timer(board, usec_timeout);
+ ret = ibcac(board, 1, 1);
+ if (ret < 0) {
+ os_remove_timer(board);
+ return ret;
+ }
+
+ cmd_string[0] = SPD; /* disable serial poll bytes */
+ cmd_string[1] = UNT;
+ ret = board->interface->command(board, cmd_string, 2, &bytes_written);
+ if (ret < 0 || bytes_written < 2) {
+ pr_err("gpib: failed to disable serial poll\n");
+ os_remove_timer(board);
+ return -EIO;
+ }
+ os_remove_timer(board);
+
+ return 0;
+}
+
+static int serial_poll_single(gpib_board_t *board, unsigned int pad, int sad,
+ unsigned int usec_timeout, uint8_t *result)
+{
+ int retval, cleanup_retval;
+
+ retval = setup_serial_poll(board, usec_timeout);
+ if (retval < 0)
+ return retval;
+ retval = read_serial_poll_byte(board, pad, sad, usec_timeout, result);
+ cleanup_retval = cleanup_serial_poll(board, usec_timeout);
+ if (retval < 0)
+ return retval;
+ if (cleanup_retval < 0)
+ return retval;
+
+ return 0;
+}
+
+int serial_poll_all(gpib_board_t *board, unsigned int usec_timeout)
+{
+ int retval = 0;
+ struct list_head *cur;
+ const struct list_head *head = NULL;
+ gpib_status_queue_t *device;
+ u8 result;
+ unsigned int num_bytes = 0;
+
+ dev_dbg(board->gpib_dev, "entering %s()\n", __func__);
+
+ head = &board->device_list;
+ if (head->next == head)
+ return 0;
+
+ retval = setup_serial_poll(board, usec_timeout);
+ if (retval < 0)
+ return retval;
+
+ for (cur = head->next; cur != head; cur = cur->next) {
+ device = list_entry(cur, gpib_status_queue_t, list);
+ retval = read_serial_poll_byte(board,
+ device->pad, device->sad, usec_timeout, &result);
+ if (retval < 0)
+ continue;
+ if (result & request_service_bit) {
+ retval = push_status_byte(board, device, result);
+ if (retval < 0)
+ continue;
+ num_bytes++;
+ }
+ }
+
+ retval = cleanup_serial_poll(board, usec_timeout);
+ if (retval < 0)
+ return retval;
+
+ return num_bytes;
+}
+
+/*
+ * DVRSP
+ * This function performs a serial poll of the device with primary
+ * address pad and secondary address sad. If the device has no
+ * secondary address, pass a negative number in for this argument. At the
+ * end of a successful serial poll the response is returned in result.
+ * SPD and UNT are sent at the completion of the poll.
+ */
+
+int dvrsp(gpib_board_t *board, unsigned int pad, int sad,
+ unsigned int usec_timeout, uint8_t *result)
+{
+ int status = ibstatus(board);
+ int retval;
+
+ if ((status & CIC) == 0) {
+ pr_err("gpib: not CIC during serial poll\n");
+ return -1;
+ }
+
+ if (pad > MAX_GPIB_PRIMARY_ADDRESS || sad > MAX_GPIB_SECONDARY_ADDRESS) {
+ pr_err("gpib: bad address for serial poll");
+ return -1;
+ }
+
+ retval = serial_poll_single(board, pad, sad, usec_timeout, result);
+ if (io_timed_out(board))
+ retval = -ETIMEDOUT;
+
+ return retval;
+}
+
+static gpib_descriptor_t *handle_to_descriptor(const gpib_file_private_t *file_priv,
+ int handle)
+{
+ if (handle < 0 || handle >= GPIB_MAX_NUM_DESCRIPTORS) {
+ pr_err("gpib: invalid handle %i\n", handle);
+ return NULL;
+ }
+
+ return file_priv->descriptors[handle];
+}
+
+static int init_gpib_file_private(gpib_file_private_t *priv)
+{
+ memset(priv, 0, sizeof(*priv));
+ atomic_set(&priv->holding_mutex, 0);
+ priv->descriptors[0] = kmalloc(sizeof(gpib_descriptor_t), GFP_KERNEL);
+ if (!priv->descriptors[0]) {
+ pr_err("gpib: failed to allocate default board descriptor\n");
+ return -ENOMEM;
+ }
+ init_gpib_descriptor(priv->descriptors[0]);
+ priv->descriptors[0]->is_board = 1;
+ mutex_init(&priv->descriptors_mutex);
+ return 0;
+}
+
+int ibopen(struct inode *inode, struct file *filep)
+{
+ unsigned int minor = iminor(inode);
+ gpib_board_t *board;
+ gpib_file_private_t *priv;
+
+ if (minor >= GPIB_MAX_NUM_BOARDS) {
+ pr_err("gpib: invalid minor number of device file\n");
+ return -ENXIO;
+ }
+
+ board = &board_array[minor];
+
+ filep->private_data = kmalloc(sizeof(gpib_file_private_t), GFP_KERNEL);
+ if (!filep->private_data)
+ return -ENOMEM;
+
+ priv = filep->private_data;
+ init_gpib_file_private((gpib_file_private_t *)filep->private_data);
+
+ dev_dbg(board->gpib_dev, "pid %i, gpib: opening minor %d\n", current->pid, minor);
+
+ if (board->use_count == 0) {
+ int retval;
+
+ retval = request_module("gpib%i", minor);
+ if (retval) {
+ dev_dbg(board->gpib_dev, "pid %i, gpib: request module returned %i\n",
+ current->pid, retval);
+ }
+ }
+ if (board->interface) {
+ if (!try_module_get(board->provider_module)) {
+ pr_err("gpib: try_module_get() failed\n");
+ return -EIO;
+ }
+ board->use_count++;
+ priv->got_module = 1;
+ }
+ return 0;
+}
+
+int ibclose(struct inode *inode, struct file *filep)
+{
+ unsigned int minor = iminor(inode);
+ gpib_board_t *board;
+ gpib_file_private_t *priv = filep->private_data;
+ gpib_descriptor_t *desc;
+
+ if (minor >= GPIB_MAX_NUM_BOARDS) {
+ pr_err("gpib: invalid minor number of device file\n");
+ return -ENODEV;
+ }
+
+ board = &board_array[minor];
+
+ dev_dbg(board->gpib_dev, "pid %i, closing minor %d\n", current->pid, minor);
+
+ if (priv) {
+ desc = handle_to_descriptor(priv, 0);
+ if (desc) {
+ if (desc->autopoll_enabled) {
+ dev_dbg(board->gpib_dev, "pid %i, decrementing autospollers\n",
+ current->pid);
+ if (board->autospollers > 0)
+ board->autospollers--;
+ else
+ pr_err("gpib: Attempt to decrement zero autospollers\n");
+ }
+ } else {
+ pr_err("gpib: Unexpected null gpib_descriptor\n");
+ }
+
+ cleanup_open_devices(priv, board);
+
+ if (atomic_read(&priv->holding_mutex))
+ mutex_unlock(&board->user_mutex);
+
+ if (priv->got_module && board->use_count) {
+ module_put(board->provider_module);
+ --board->use_count;
+ }
+
+ kfree(filep->private_data);
+ filep->private_data = NULL;
+ }
+
+ return 0;
+}
+
+long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg)
+{
+ unsigned int minor = iminor(filep->f_path.dentry->d_inode);
+ gpib_board_t *board;
+ gpib_file_private_t *file_priv = filep->private_data;
+ long retval = -ENOTTY;
+
+ if (minor >= GPIB_MAX_NUM_BOARDS) {
+ pr_err("gpib: invalid minor number of device file\n");
+ return -ENODEV;
+ }
+ board = &board_array[minor];
+
+ if (mutex_lock_interruptible(&board->big_gpib_mutex))
+ return -ERESTARTSYS;
+
+ dev_dbg(board->gpib_dev, "pid %i, ioctl %d, interface=%s, use=%d, onl=%d\n",
+ current->pid, cmd & 0xff,
+ board->interface ? board->interface->name : "",
+ board->use_count,
+ board->online);
+
+ switch (cmd) {
+ case CFCBOARDTYPE:
+ retval = board_type_ioctl(file_priv, board, arg);
+ goto done;
+ case IBONL:
+ retval = online_ioctl(board, arg);
+ goto done;
+ default:
+ break;
+ }
+ if (!board->interface) {
+ pr_err("gpib: no gpib board configured on /dev/gpib%i\n", minor);
+ retval = -ENODEV;
+ goto done;
+ }
+ if (file_priv->got_module == 0) {
+ if (!try_module_get(board->provider_module)) {
+ pr_err("gpib: try_module_get() failed\n");
+ retval = -EIO;
+ goto done;
+ }
+ file_priv->got_module = 1;
+ board->use_count++;
+ }
+ switch (cmd) {
+ case CFCBASE:
+ retval = iobase_ioctl(&board->config, arg);
+ goto done;
+ case CFCIRQ:
+ retval = irq_ioctl(&board->config, arg);
+ goto done;
+ case CFCDMA:
+ retval = dma_ioctl(&board->config, arg);
+ goto done;
+ case IBAUTOSPOLL:
+ retval = autospoll_ioctl(board, file_priv, arg);
+ goto done;
+ case IBBOARD_INFO:
+ retval = board_info_ioctl(board, arg);
+ goto done;
+ case IBMUTEX:
+ /* Need to unlock board->big_gpib_mutex before potentially locking board->user_mutex
+ * to maintain consistent locking order
+ */
+ mutex_unlock(&board->big_gpib_mutex);
+ return mutex_ioctl(board, file_priv, arg);
+ case IBPAD:
+ retval = pad_ioctl(board, file_priv, arg);
+ goto done;
+ case IBSAD:
+ retval = sad_ioctl(board, file_priv, arg);
+ goto done;
+ case IBSELECT_PCI:
+ retval = select_pci_ioctl(&board->config, arg);
+ goto done;
+ case IBSELECT_DEVICE_PATH:
+ retval = select_device_path_ioctl(&board->config, arg);
+ goto done;
+ default:
+ break;
+ }
+
+ if (!board->online) {
+ pr_err("gpib: ioctl %i invalid for offline board\n",
+ cmd & 0xff);
+ retval = -EINVAL;
+ goto done;
+ }
+
+ switch (cmd) {
+ case IBEVENT:
+ retval = event_ioctl(board, arg);
+ goto done;
+ case IBCLOSEDEV:
+ retval = close_dev_ioctl(filep, board, arg);
+ goto done;
+ case IBOPENDEV:
+ retval = open_dev_ioctl(filep, board, arg);
+ goto done;
+ case IBSPOLL_BYTES:
+ retval = status_bytes_ioctl(board, arg);
+ goto done;
+ case IBWAIT:
+ retval = wait_ioctl(file_priv, board, arg);
+ if (retval == -ERESTARTSYS)
+ return retval;
+ goto done;
+ case IBLINES:
+ retval = line_status_ioctl(board, arg);
+ goto done;
+ case IBLOC:
+ board->interface->return_to_local(board);
+ retval = 0;
+ goto done;
+ default:
+ break;
+ }
+
+ spin_lock(&board->locking_pid_spinlock);
+ if (current->pid != board->locking_pid) {
+ spin_unlock(&board->locking_pid_spinlock);
+ pr_err("gpib: need to hold board lock to perform ioctl %i\n",
+ cmd & 0xff);
+ retval = -EPERM;
+ goto done;
+ }
+ spin_unlock(&board->locking_pid_spinlock);
+
+ switch (cmd) {
+ case IB_T1_DELAY:
+ retval = t1_delay_ioctl(board, arg);
+ goto done;
+ case IBCAC:
+ retval = take_control_ioctl(board, arg);
+ goto done;
+ case IBCMD:
+ /* IO ioctls can take a long time, we need to unlock board->big_gpib_mutex
+ * before we call them.
+ */
+ mutex_unlock(&board->big_gpib_mutex);
+ return command_ioctl(file_priv, board, arg);
+ case IBEOS:
+ retval = eos_ioctl(board, arg);
+ goto done;
+ case IBGTS:
+ retval = ibgts(board);
+ goto done;
+ case IBPPC:
+ retval = ppc_ioctl(board, arg);
+ goto done;
+ case IBPP2_SET:
+ retval = set_local_ppoll_mode_ioctl(board, arg);
+ goto done;
+ case IBPP2_GET:
+ retval = get_local_ppoll_mode_ioctl(board, arg);
+ goto done;
+ case IBQUERY_BOARD_RSV:
+ retval = query_board_rsv_ioctl(board, arg);
+ goto done;
+ case IBRD:
+ /* IO ioctls can take a long time, we need to unlock board->big_gpib_mutex
+ * before we call them.
+ */
+ mutex_unlock(&board->big_gpib_mutex);
+ return read_ioctl(file_priv, board, arg);
+ case IBRPP:
+ retval = parallel_poll_ioctl(board, arg);
+ goto done;
+ case IBRSC:
+ retval = request_system_control_ioctl(board, arg);
+ goto done;
+ case IBRSP:
+ retval = serial_poll_ioctl(board, arg);
+ goto done;
+ case IBRSV:
+ retval = request_service_ioctl(board, arg);
+ goto done;
+ case IBRSV2:
+ retval = request_service2_ioctl(board, arg);
+ goto done;
+ case IBSIC:
+ retval = interface_clear_ioctl(board, arg);
+ goto done;
+ case IBSRE:
+ retval = remote_enable_ioctl(board, arg);
+ goto done;
+ case IBTMO:
+ retval = timeout_ioctl(board, arg);
+ goto done;
+ case IBWRT:
+ /* IO ioctls can take a long time, we need to unlock board->big_gpib_mutex
+ * before we call them.
+ */
+ mutex_unlock(&board->big_gpib_mutex);
+ return write_ioctl(file_priv, board, arg);
+ default:
+ retval = -ENOTTY;
+ goto done;
+ }
+
+done:
+ mutex_unlock(&board->big_gpib_mutex);
+ dev_dbg(board->gpib_dev, "ioctl done status = 0x%lx\n", board->status);
+ return retval;
+}
+
+static int board_type_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, unsigned long arg)
+{
+ struct list_head *list_ptr;
+ board_type_ioctl_t cmd;
+ int retval;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (board->online) {
+ pr_err("gpib: can't change board type while board is online.\n");
+ return -EBUSY;
+ }
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(board_type_ioctl_t));
+ if (retval)
+ return retval;
+
+ for (list_ptr = registered_drivers.next; list_ptr != &registered_drivers;
+ list_ptr = list_ptr->next) {
+ gpib_interface_list_t *entry;
+
+ entry = list_entry(list_ptr, gpib_interface_list_t, list);
+ if (strcmp(entry->interface->name, cmd.name) == 0) {
+ int i;
+ int had_module = file_priv->got_module;
+
+ if (board->use_count) {
+ for (i = 0; i < board->use_count; ++i)
+ module_put(board->provider_module);
+ board->interface = NULL;
+ file_priv->got_module = 0;
+ }
+ board->interface = entry->interface;
+ board->provider_module = entry->module;
+ for (i = 0; i < board->use_count; ++i) {
+ if (!try_module_get(entry->module)) {
+ board->use_count = i;
+ return -EIO;
+ }
+ }
+ if (had_module == 0) {
+ if (!try_module_get(entry->module))
+ return -EIO;
+ ++board->use_count;
+ }
+ file_priv->got_module = 1;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int read_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board,
+ unsigned long arg)
+{
+ read_write_ioctl_t read_cmd;
+ u8 *userbuf;
+ unsigned long remain;
+ int end_flag = 0;
+ int retval;
+ ssize_t read_ret = 0;
+ gpib_descriptor_t *desc;
+ size_t nbytes;
+
+ retval = copy_from_user(&read_cmd, (void *)arg, sizeof(read_cmd));
+ if (retval)
+ return -EFAULT;
+
+ if (read_cmd.completed_transfer_count > read_cmd.requested_transfer_count)
+ return -EINVAL;
+
+ desc = handle_to_descriptor(file_priv, read_cmd.handle);
+ if (!desc)
+ return -EINVAL;
+
+ if (WARN_ON_ONCE(sizeof(userbuf) > sizeof(read_cmd.buffer_ptr)))
+ return -EFAULT;
+
+ userbuf = (u8 *)(unsigned long)read_cmd.buffer_ptr;
+ userbuf += read_cmd.completed_transfer_count;
+
+ remain = read_cmd.requested_transfer_count - read_cmd.completed_transfer_count;
+
+ /* Check write access to buffer */
+ if (!access_ok(userbuf, remain))
+ return -EFAULT;
+
+ atomic_set(&desc->io_in_progress, 1);
+
+ /* Read buffer loads till we fill the user supplied buffer */
+ while (remain > 0 && end_flag == 0) {
+ nbytes = 0;
+ read_ret = ibrd(board, board->buffer, (board->buffer_length < remain) ?
+ board->buffer_length : remain, &end_flag, &nbytes);
+ if (nbytes == 0)
+ break;
+ retval = copy_to_user(userbuf, board->buffer, nbytes);
+ if (retval) {
+ retval = -EFAULT;
+ break;
+ }
+ remain -= nbytes;
+ userbuf += nbytes;
+ if (read_ret < 0)
+ break;
+ }
+ read_cmd.completed_transfer_count = read_cmd.requested_transfer_count - remain;
+ read_cmd.end = end_flag;
+ /* suppress errors (for example due to timeout or interruption by device clear)
+ * if all bytes got sent. This prevents races that can occur in the various drivers
+ * if a device receives a device clear immediately after a transfer completes and
+ * the driver code wasn't careful enough to handle that case.
+ */
+ if (remain == 0 || end_flag)
+ read_ret = 0;
+ if (retval == 0)
+ retval = copy_to_user((void *)arg, &read_cmd, sizeof(read_cmd));
+
+ atomic_set(&desc->io_in_progress, 0);
+
+ wake_up_interruptible(&board->wait);
+ if (retval)
+ return -EFAULT;
+
+ return read_ret;
+}
+
+static int command_ioctl(gpib_file_private_t *file_priv,
+ gpib_board_t *board, unsigned long arg)
+{
+ read_write_ioctl_t cmd;
+ u8 *userbuf;
+ unsigned long remain;
+ int retval;
+ int fault = 0;
+ gpib_descriptor_t *desc;
+ size_t bytes_written;
+ int no_clear_io_in_prog;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ if (cmd.completed_transfer_count > cmd.requested_transfer_count)
+ return -EINVAL;
+
+ desc = handle_to_descriptor(file_priv, cmd.handle);
+ if (!desc)
+ return -EINVAL;
+
+ userbuf = (u8 *)(unsigned long)cmd.buffer_ptr;
+ userbuf += cmd.completed_transfer_count;
+
+ no_clear_io_in_prog = cmd.end;
+ cmd.end = 0;
+
+ remain = cmd.requested_transfer_count - cmd.completed_transfer_count;
+
+ /* Check read access to buffer */
+ if (!access_ok(userbuf, remain))
+ return -EFAULT;
+
+ /* Write buffer loads till we empty the user supplied buffer.
+ * Call drivers at least once, even if remain is zero, in
+ * order to allow them to insure previous commands were
+ * completely finished, in the case of a restarted ioctl.
+ */
+
+ atomic_set(&desc->io_in_progress, 1);
+
+ do {
+ fault = copy_from_user(board->buffer, userbuf, (board->buffer_length < remain) ?
+ board->buffer_length : remain);
+ if (fault) {
+ retval = -EFAULT;
+ bytes_written = 0;
+ } else {
+ retval = ibcmd(board, board->buffer, (board->buffer_length < remain) ?
+ board->buffer_length : remain, &bytes_written);
+ }
+ remain -= bytes_written;
+ userbuf += bytes_written;
+ if (retval < 0) {
+ atomic_set(&desc->io_in_progress, 0);
+
+ wake_up_interruptible(&board->wait);
+ break;
+ }
+ } while (remain > 0);
+
+ cmd.completed_transfer_count = cmd.requested_transfer_count - remain;
+
+ if (fault == 0)
+ fault = copy_to_user((void *)arg, &cmd, sizeof(cmd));
+
+ /*
+ * no_clear_io_in_prog (cmd.end) is true when io_in_progress should
+ * not be set to zero because the cmd in progress is the address setup
+ * operation for an async read or write. This causes CMPL not to be set
+ * in general_ibstatus until the async read or write completes.
+ */
+ if (!no_clear_io_in_prog || fault)
+ atomic_set(&desc->io_in_progress, 0);
+
+ wake_up_interruptible(&board->wait);
+ if (fault)
+ return -EFAULT;
+
+ return retval;
+}
+
+static int write_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board,
+ unsigned long arg)
+{
+ read_write_ioctl_t write_cmd;
+ u8 *userbuf;
+ unsigned long remain;
+ int retval = 0;
+ int fault;
+ gpib_descriptor_t *desc;
+
+ fault = copy_from_user(&write_cmd, (void *)arg, sizeof(write_cmd));
+ if (fault)
+ return -EFAULT;
+
+ if (write_cmd.completed_transfer_count > write_cmd.requested_transfer_count)
+ return -EINVAL;
+
+ desc = handle_to_descriptor(file_priv, write_cmd.handle);
+ if (!desc)
+ return -EINVAL;
+
+ userbuf = (u8 *)(unsigned long)write_cmd.buffer_ptr;
+ userbuf += write_cmd.completed_transfer_count;
+
+ remain = write_cmd.requested_transfer_count - write_cmd.completed_transfer_count;
+
+ /* Check read access to buffer */
+ if (!access_ok(userbuf, remain))
+ return -EFAULT;
+
+ atomic_set(&desc->io_in_progress, 1);
+
+ /* Write buffer loads till we empty the user supplied buffer */
+ while (remain > 0) {
+ int send_eoi;
+ size_t bytes_written = 0;
+
+ send_eoi = remain <= board->buffer_length && write_cmd.end;
+ fault = copy_from_user(board->buffer, userbuf, (board->buffer_length < remain) ?
+ board->buffer_length : remain);
+ if (fault) {
+ retval = -EFAULT;
+ break;
+ }
+ retval = ibwrt(board, board->buffer, (board->buffer_length < remain) ?
+ board->buffer_length : remain, send_eoi, &bytes_written);
+ remain -= bytes_written;
+ userbuf += bytes_written;
+ if (retval < 0)
+ break;
+ }
+ write_cmd.completed_transfer_count = write_cmd.requested_transfer_count - remain;
+ /* suppress errors (for example due to timeout or interruption by device clear)
+ * if all bytes got sent. This prevents races that can occur in the various drivers
+ * if a device receives a device clear immediately after a transfer completes and
+ * the driver code wasn't careful enough to handle that case.
+ */
+ if (remain == 0)
+ retval = 0;
+ if (fault == 0)
+ fault = copy_to_user((void *)arg, &write_cmd, sizeof(write_cmd));
+
+ atomic_set(&desc->io_in_progress, 0);
+
+ wake_up_interruptible(&board->wait);
+ if (fault)
+ return -EFAULT;
+
+ return retval;
+}
+
+static int status_bytes_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ gpib_status_queue_t *device;
+ spoll_bytes_ioctl_t cmd;
+ int retval;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ device = get_gpib_status_queue(board, cmd.pad, cmd.sad);
+ if (!device)
+ cmd.num_bytes = 0;
+ else
+ cmd.num_bytes = num_status_bytes(device);
+
+ retval = copy_to_user((void *)arg, &cmd, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int increment_open_device_count(gpib_board_t *board, struct list_head *head,
+ unsigned int pad, int sad)
+{
+ struct list_head *list_ptr;
+ gpib_status_queue_t *device;
+
+ /* first see if address has already been opened, then increment
+ * open count
+ */
+ for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) {
+ device = list_entry(list_ptr, gpib_status_queue_t, list);
+ if (gpib_address_equal(device->pad, device->sad, pad, sad)) {
+ dev_dbg(board->gpib_dev, "pid %i, incrementing open count for pad %i, sad %i\n",
+ current->pid, device->pad, device->sad);
+ device->reference_count++;
+ return 0;
+ }
+ }
+
+ /* otherwise we need to allocate a new gpib_status_queue_t */
+ device = kmalloc(sizeof(gpib_status_queue_t), GFP_ATOMIC);
+ if (!device)
+ return -ENOMEM;
+ init_gpib_status_queue(device);
+ device->pad = pad;
+ device->sad = sad;
+ device->reference_count = 1;
+
+ list_add(&device->list, head);
+
+ dev_dbg(board->gpib_dev, "pid %i, opened pad %i, sad %i\n",
+ current->pid, device->pad, device->sad);
+
+ return 0;
+}
+
+static int subtract_open_device_count(gpib_board_t *board, struct list_head *head,
+ unsigned int pad, int sad, unsigned int count)
+{
+ gpib_status_queue_t *device;
+ struct list_head *list_ptr;
+
+ for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) {
+ device = list_entry(list_ptr, gpib_status_queue_t, list);
+ if (gpib_address_equal(device->pad, device->sad, pad, sad)) {
+ dev_dbg(board->gpib_dev, "pid %i, decrementing open count for pad %i, sad %i\n",
+ current->pid, device->pad, device->sad);
+ if (count > device->reference_count) {
+ pr_err("gpib: bug! in %s()\n", __func__);
+ return -EINVAL;
+ }
+ device->reference_count -= count;
+ if (device->reference_count == 0) {
+ dev_dbg(board->gpib_dev, "pid %i, closing pad %i, sad %i\n",
+ current->pid, device->pad, device->sad);
+ list_del(list_ptr);
+ kfree(device);
+ }
+ return 0;
+ }
+ }
+ pr_err("gpib: bug! tried to close address that was never opened!\n");
+ return -EINVAL;
+}
+
+static inline int decrement_open_device_count(gpib_board_t *board, struct list_head *head,
+ unsigned int pad, int sad)
+{
+ return subtract_open_device_count(board, head, pad, sad, 1);
+}
+
+static int cleanup_open_devices(gpib_file_private_t *file_priv, gpib_board_t *board)
+{
+ int retval = 0;
+ int i;
+
+ for (i = 0; i < GPIB_MAX_NUM_DESCRIPTORS; i++) {
+ gpib_descriptor_t *desc;
+
+ desc = file_priv->descriptors[i];
+ if (!desc)
+ continue;
+
+ if (desc->is_board == 0) {
+ retval = decrement_open_device_count(board, &board->device_list, desc->pad,
+ desc->sad);
+ if (retval < 0)
+ return retval;
+ }
+ kfree(desc);
+ file_priv->descriptors[i] = NULL;
+ }
+
+ return 0;
+}
+
+static int open_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg)
+{
+ open_dev_ioctl_t open_dev_cmd;
+ int retval;
+ gpib_file_private_t *file_priv = filep->private_data;
+ int i;
+
+ retval = copy_from_user(&open_dev_cmd, (void *)arg, sizeof(open_dev_cmd));
+ if (retval)
+ return -EFAULT;
+
+ if (mutex_lock_interruptible(&file_priv->descriptors_mutex))
+ return -ERESTARTSYS;
+ for (i = 0; i < GPIB_MAX_NUM_DESCRIPTORS; i++)
+ if (!file_priv->descriptors[i])
+ break;
+ if (i == GPIB_MAX_NUM_DESCRIPTORS) {
+ mutex_unlock(&file_priv->descriptors_mutex);
+ return -ERANGE;
+ }
+ file_priv->descriptors[i] = kmalloc(sizeof(gpib_descriptor_t), GFP_KERNEL);
+ if (!file_priv->descriptors[i]) {
+ mutex_unlock(&file_priv->descriptors_mutex);
+ return -ENOMEM;
+ }
+ init_gpib_descriptor(file_priv->descriptors[i]);
+
+ file_priv->descriptors[i]->pad = open_dev_cmd.pad;
+ file_priv->descriptors[i]->sad = open_dev_cmd.sad;
+ file_priv->descriptors[i]->is_board = open_dev_cmd.is_board;
+ mutex_unlock(&file_priv->descriptors_mutex);
+
+ retval = increment_open_device_count(board, &board->device_list, open_dev_cmd.pad,
+ open_dev_cmd.sad);
+ if (retval < 0)
+ return retval;
+
+ /* clear stuck srq state, since we may be able to find service request on
+ * the new device
+ */
+ atomic_set(&board->stuck_srq, 0);
+
+ open_dev_cmd.handle = i;
+ retval = copy_to_user((void *)arg, &open_dev_cmd, sizeof(open_dev_cmd));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int close_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg)
+{
+ close_dev_ioctl_t cmd;
+ gpib_file_private_t *file_priv = filep->private_data;
+ int retval;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ if (cmd.handle >= GPIB_MAX_NUM_DESCRIPTORS)
+ return -EINVAL;
+ if (!file_priv->descriptors[cmd.handle])
+ return -EINVAL;
+
+ retval = decrement_open_device_count(board, &board->device_list,
+ file_priv->descriptors[cmd.handle]->pad,
+ file_priv->descriptors[cmd.handle]->sad);
+ if (retval < 0)
+ return retval;
+
+ kfree(file_priv->descriptors[cmd.handle]);
+ file_priv->descriptors[cmd.handle] = NULL;
+
+ return 0;
+}
+
+static int serial_poll_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ serial_poll_ioctl_t serial_cmd;
+ int retval;
+
+ dev_dbg(board->gpib_dev, "pid %i, entering %s()\n", current->pid, __func__);
+
+ retval = copy_from_user(&serial_cmd, (void *)arg, sizeof(serial_cmd));
+ if (retval)
+ return -EFAULT;
+
+ retval = get_serial_poll_byte(board, serial_cmd.pad, serial_cmd.sad, board->usec_timeout,
+ &serial_cmd.status_byte);
+ if (retval < 0)
+ return retval;
+
+ retval = copy_to_user((void *)arg, &serial_cmd, sizeof(serial_cmd));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int wait_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board,
+ unsigned long arg)
+{
+ wait_ioctl_t wait_cmd;
+ int retval;
+ gpib_descriptor_t *desc;
+
+ retval = copy_from_user(&wait_cmd, (void *)arg, sizeof(wait_cmd));
+ if (retval)
+ return -EFAULT;
+
+ desc = handle_to_descriptor(file_priv, wait_cmd.handle);
+ if (!desc)
+ return -EINVAL;
+
+ retval = ibwait(board, wait_cmd.wait_mask, wait_cmd.clear_mask,
+ wait_cmd.set_mask, &wait_cmd.ibsta, wait_cmd.usec_timeout, desc);
+ if (retval < 0)
+ return retval;
+
+ retval = copy_to_user((void *)arg, &wait_cmd, sizeof(wait_cmd));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int parallel_poll_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ u8 poll_byte;
+ int retval;
+
+ retval = ibrpp(board, &poll_byte);
+ if (retval < 0)
+ return retval;
+
+ retval = copy_to_user((void *)arg, &poll_byte, sizeof(poll_byte));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int online_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ online_ioctl_t online_cmd;
+ int retval;
+ void *init_data = NULL;
+
+ board->config.init_data = NULL;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ retval = copy_from_user(&online_cmd, (void *)arg, sizeof(online_cmd));
+ if (retval)
+ return -EFAULT;
+ if (online_cmd.init_data_length > 0) {
+ board->config.init_data = vmalloc(online_cmd.init_data_length);
+ if (!board->config.init_data)
+ return -ENOMEM;
+ if (WARN_ON_ONCE(sizeof(init_data) > sizeof(online_cmd.init_data_ptr)))
+ return -EFAULT;
+ init_data = (void *)(unsigned long)(online_cmd.init_data_ptr);
+ retval = copy_from_user(board->config.init_data, init_data,
+ online_cmd.init_data_length);
+ if (retval) {
+ vfree(board->config.init_data);
+ return -EFAULT;
+ }
+ board->config.init_data_length = online_cmd.init_data_length;
+ } else {
+ board->config.init_data = NULL;
+ board->config.init_data_length = 0;
+ }
+ if (online_cmd.online)
+ retval = ibonline(board);
+ else
+ retval = iboffline(board);
+ if (board->config.init_data) {
+ vfree(board->config.init_data);
+ board->config.init_data = NULL;
+ board->config.init_data_length = 0;
+ }
+ return retval;
+}
+
+static int remote_enable_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ int enable;
+ int retval;
+
+ retval = copy_from_user(&enable, (void *)arg, sizeof(enable));
+ if (retval)
+ return -EFAULT;
+
+ return ibsre(board, enable);
+}
+
+static int take_control_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ int synchronous;
+ int retval;
+
+ retval = copy_from_user(&synchronous, (void *)arg, sizeof(synchronous));
+ if (retval)
+ return -EFAULT;
+
+ return ibcac(board, synchronous, 1);
+}
+
+static int line_status_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ short lines;
+ int retval;
+
+ retval = iblines(board, &lines);
+ if (retval < 0)
+ return retval;
+
+ retval = copy_to_user((void *)arg, &lines, sizeof(lines));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int pad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg)
+{
+ pad_ioctl_t cmd;
+ int retval;
+ gpib_descriptor_t *desc;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ desc = handle_to_descriptor(file_priv, cmd.handle);
+ if (!desc)
+ return -EINVAL;
+
+ if (desc->is_board) {
+ retval = ibpad(board, cmd.pad);
+ if (retval < 0)
+ return retval;
+ } else {
+ retval = decrement_open_device_count(board, &board->device_list, desc->pad,
+ desc->sad);
+ if (retval < 0)
+ return retval;
+
+ desc->pad = cmd.pad;
+
+ retval = increment_open_device_count(board, &board->device_list, desc->pad,
+ desc->sad);
+ if (retval < 0)
+ return retval;
+ }
+
+ return 0;
+}
+
+static int sad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg)
+{
+ sad_ioctl_t cmd;
+ int retval;
+ gpib_descriptor_t *desc;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ desc = handle_to_descriptor(file_priv, cmd.handle);
+ if (!desc)
+ return -EINVAL;
+
+ if (desc->is_board) {
+ retval = ibsad(board, cmd.sad);
+ if (retval < 0)
+ return retval;
+ } else {
+ retval = decrement_open_device_count(board, &board->device_list, desc->pad,
+ desc->sad);
+ if (retval < 0)
+ return retval;
+
+ desc->sad = cmd.sad;
+
+ retval = increment_open_device_count(board, &board->device_list, desc->pad,
+ desc->sad);
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+
+static int eos_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ eos_ioctl_t eos_cmd;
+ int retval;
+
+ retval = copy_from_user(&eos_cmd, (void *)arg, sizeof(eos_cmd));
+ if (retval)
+ return -EFAULT;
+
+ return ibeos(board, eos_cmd.eos, eos_cmd.eos_flags);
+}
+
+static int request_service_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ u8 status_byte;
+ int retval;
+
+ retval = copy_from_user(&status_byte, (void *)arg, sizeof(status_byte));
+ if (retval)
+ return -EFAULT;
+
+ return ibrsv2(board, status_byte, status_byte & request_service_bit);
+}
+
+static int request_service2_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ request_service2_t request_service2_cmd;
+ int retval;
+
+ retval = copy_from_user(&request_service2_cmd, (void *)arg, sizeof(request_service2_t));
+ if (retval)
+ return -EFAULT;
+
+ return ibrsv2(board, request_service2_cmd.status_byte,
+ request_service2_cmd.new_reason_for_service);
+}
+
+static int iobase_ioctl(gpib_board_config_t *config, unsigned long arg)
+{
+ u64 base_addr;
+ int retval;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ retval = copy_from_user(&base_addr, (void *)arg, sizeof(base_addr));
+ if (retval)
+ return -EFAULT;
+
+ if (WARN_ON_ONCE(sizeof(void *) > sizeof(base_addr)))
+ return -EFAULT;
+ config->ibbase = (void *)(unsigned long)(base_addr);
+
+ return 0;
+}
+
+static int irq_ioctl(gpib_board_config_t *config, unsigned long arg)
+{
+ unsigned int irq;
+ int retval;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ retval = copy_from_user(&irq, (void *)arg, sizeof(irq));
+ if (retval)
+ return -EFAULT;
+
+ config->ibirq = irq;
+
+ return 0;
+}
+
+static int dma_ioctl(gpib_board_config_t *config, unsigned long arg)
+{
+ unsigned int dma_channel;
+ int retval;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ retval = copy_from_user(&dma_channel, (void *)arg, sizeof(dma_channel));
+ if (retval)
+ return -EFAULT;
+
+ config->ibdma = dma_channel;
+
+ return 0;
+}
+
+static int autospoll_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg)
+{
+ autospoll_ioctl_t enable;
+ int retval;
+ gpib_descriptor_t *desc;
+
+ retval = copy_from_user(&enable, (void *)arg, sizeof(enable));
+ if (retval)
+ return -EFAULT;
+
+ desc = handle_to_descriptor(file_priv, 0); /* board handle is 0 */
+
+ if (enable) {
+ if (!desc->autopoll_enabled) {
+ board->autospollers++;
+ desc->autopoll_enabled = 1;
+ }
+ retval = 0;
+ } else {
+ if (desc->autopoll_enabled) {
+ desc->autopoll_enabled = 0;
+ if (board->autospollers > 0) {
+ board->autospollers--;
+ retval = 0;
+ } else {
+ pr_err("gpib: tried to set number of autospollers negative\n");
+ retval = -EINVAL;
+ }
+ } else {
+ pr_err("gpib: autopoll disable requested before enable\n");
+ retval = -EINVAL;
+ }
+ }
+ return retval;
+}
+
+static int mutex_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg)
+{
+ int retval, lock_mutex;
+
+ retval = copy_from_user(&lock_mutex, (void *)arg, sizeof(lock_mutex));
+ if (retval)
+ return -EFAULT;
+
+ if (lock_mutex) {
+ retval = mutex_lock_interruptible(&board->user_mutex);
+ if (retval) {
+ pr_warn("gpib: ioctl interrupted while waiting on lock\n");
+ return -ERESTARTSYS;
+ }
+
+ spin_lock(&board->locking_pid_spinlock);
+ board->locking_pid = current->pid;
+ spin_unlock(&board->locking_pid_spinlock);
+
+ atomic_set(&file_priv->holding_mutex, 1);
+
+ dev_dbg(board->gpib_dev, "pid %i, locked board %d mutex\n",
+ current->pid, board->minor);
+ } else {
+ spin_lock(&board->locking_pid_spinlock);
+ if (current->pid != board->locking_pid) {
+ pr_err("gpib: bug! pid %i tried to release mutex held by pid %i\n",
+ current->pid, board->locking_pid);
+ spin_unlock(&board->locking_pid_spinlock);
+ return -EPERM;
+ }
+ board->locking_pid = 0;
+ spin_unlock(&board->locking_pid_spinlock);
+
+ atomic_set(&file_priv->holding_mutex, 0);
+
+ mutex_unlock(&board->user_mutex);
+ dev_dbg(board->gpib_dev, "pid %i, unlocked board %i mutex\n",
+ current->pid, board->minor);
+ }
+ return 0;
+}
+
+static int timeout_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ unsigned int timeout;
+ int retval;
+
+ retval = copy_from_user(&timeout, (void *)arg, sizeof(timeout));
+ if (retval)
+ return -EFAULT;
+
+ board->usec_timeout = timeout;
+ dev_dbg(board->gpib_dev, "pid %i, timeout set to %i usec\n", current->pid, timeout);
+
+ return 0;
+}
+
+static int ppc_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ ppoll_config_ioctl_t cmd;
+ int retval;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ if (cmd.set_ist) {
+ board->ist = 1;
+ board->interface->parallel_poll_response(board, board->ist);
+ } else if (cmd.clear_ist) {
+ board->ist = 0;
+ board->interface->parallel_poll_response(board, board->ist);
+ }
+
+ if (cmd.config) {
+ retval = ibppc(board, cmd.config);
+ if (retval < 0)
+ return retval;
+ }
+
+ return 0;
+}
+
+static int set_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ local_ppoll_mode_ioctl_t cmd;
+ int retval;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ if (!board->interface->local_parallel_poll_mode) {
+ pr_warn("gpib: local/remote parallel poll mode not supported by driver.");
+ return -EIO;
+ }
+ board->local_ppoll_mode = cmd != 0;
+ board->interface->local_parallel_poll_mode(board, board->local_ppoll_mode);
+
+ return 0;
+}
+
+static int get_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ local_ppoll_mode_ioctl_t cmd;
+ int retval;
+
+ cmd = board->local_ppoll_mode;
+ retval = copy_to_user((void *)arg, &cmd, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int query_board_rsv_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ int status;
+ int retval;
+
+ status = board->interface->serial_poll_status(board);
+
+ retval = copy_to_user((void *)arg, &status, sizeof(status));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int board_info_ioctl(const gpib_board_t *board, unsigned long arg)
+{
+ board_info_ioctl_t info;
+ int retval;
+
+ info.pad = board->pad;
+ info.sad = board->sad;
+ info.parallel_poll_configuration = board->parallel_poll_configuration;
+ info.is_system_controller = board->master;
+ if (board->autospollers)
+ info.autopolling = 1;
+ else
+ info.autopolling = 0;
+ info.t1_delay = board->t1_nano_sec;
+ info.ist = board->ist;
+ info.no_7_bit_eos = board->interface->no_7_bit_eos;
+ retval = copy_to_user((void *)arg, &info, sizeof(info));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int interface_clear_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ unsigned int usec_duration;
+ int retval;
+
+ retval = copy_from_user(&usec_duration, (void *)arg, sizeof(usec_duration));
+ if (retval)
+ return -EFAULT;
+
+ return ibsic(board, usec_duration);
+}
+
+static int select_pci_ioctl(gpib_board_config_t *config, unsigned long arg)
+{
+ select_pci_ioctl_t selection;
+ int retval;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ retval = copy_from_user(&selection, (void *)arg, sizeof(selection));
+ if (retval)
+ return -EFAULT;
+
+ config->pci_bus = selection.pci_bus;
+ config->pci_slot = selection.pci_slot;
+
+ return 0;
+}
+
+static int select_device_path_ioctl(gpib_board_config_t *config, unsigned long arg)
+{
+ select_device_path_ioctl_t *selection;
+ int retval;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ selection = vmalloc(sizeof(select_device_path_ioctl_t));
+ if (!selection)
+ return -ENOMEM;
+
+ retval = copy_from_user(selection, (void *)arg, sizeof(select_device_path_ioctl_t));
+ if (retval) {
+ vfree(selection);
+ return -EFAULT;
+ }
+
+ selection->device_path[sizeof(selection->device_path) - 1] = '\0';
+ kfree(config->device_path);
+ config->device_path = NULL;
+ if (strlen(selection->device_path) > 0)
+ config->device_path = kstrdup(selection->device_path, GFP_KERNEL);
+
+ vfree(selection);
+ return 0;
+}
+
+unsigned int num_gpib_events(const gpib_event_queue_t *queue)
+{
+ return queue->num_events;
+}
+
+static int push_gpib_event_nolock(gpib_board_t *board, short event_type)
+{
+ gpib_event_queue_t *queue = &board->event_queue;
+ struct list_head *head = &queue->event_head;
+ gpib_event_t *event;
+ static const unsigned int max_num_events = 1024;
+ int retval;
+
+ if (num_gpib_events(queue) >= max_num_events) {
+ short lost_event;
+
+ queue->dropped_event = 1;
+ retval = pop_gpib_event_nolock(board, queue, &lost_event);
+ if (retval < 0)
+ return retval;
+ }
+
+ event = kmalloc(sizeof(gpib_event_t), GFP_ATOMIC);
+ if (!event) {
+ queue->dropped_event = 1;
+ pr_err("gpib: failed to allocate memory for event\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&event->list);
+ event->event_type = event_type;
+
+ list_add_tail(&event->list, head);
+
+ queue->num_events++;
+
+ dev_dbg(board->gpib_dev, "pushed event %i, %i in queue\n",
+ (int)event_type, num_gpib_events(queue));
+
+ return 0;
+}
+
+// push event onto back of event queue
+int push_gpib_event(gpib_board_t *board, short event_type)
+{
+ unsigned long flags;
+ int retval;
+
+ spin_lock_irqsave(&board->event_queue.lock, flags);
+ retval = push_gpib_event_nolock(board, event_type);
+ spin_unlock_irqrestore(&board->event_queue.lock, flags);
+
+ if (event_type == EventDevTrg)
+ board->status |= DTAS;
+ if (event_type == EventDevClr)
+ board->status |= DCAS;
+
+ return retval;
+}
+EXPORT_SYMBOL(push_gpib_event);
+
+static int pop_gpib_event_nolock(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type)
+{
+ struct list_head *head = &queue->event_head;
+ struct list_head *front = head->next;
+ gpib_event_t *event;
+
+ if (num_gpib_events(queue) == 0) {
+ *event_type = EventNone;
+ return 0;
+ }
+
+ if (front == head)
+ return -EIO;
+
+ if (queue->dropped_event) {
+ queue->dropped_event = 0;
+ return -EPIPE;
+ }
+
+ event = list_entry(front, gpib_event_t, list);
+ *event_type = event->event_type;
+
+ list_del(front);
+ kfree(event);
+
+ queue->num_events--;
+
+ dev_dbg(board->gpib_dev, "popped event %i, %i in queue\n",
+ (int)*event_type, num_gpib_events(queue));
+
+ return 0;
+}
+
+// pop event from front of event queue
+int pop_gpib_event(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type)
+{
+ unsigned long flags;
+ int retval;
+
+ spin_lock_irqsave(&queue->lock, flags);
+ retval = pop_gpib_event_nolock(board, queue, event_type);
+ spin_unlock_irqrestore(&queue->lock, flags);
+ return retval;
+}
+
+static int event_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ event_ioctl_t user_event;
+ int retval;
+ short event;
+
+ retval = pop_gpib_event(board, &board->event_queue, &event);
+ if (retval < 0)
+ return retval;
+
+ user_event = event;
+
+ retval = copy_to_user((void *)arg, &user_event, sizeof(user_event));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int request_system_control_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ rsc_ioctl_t request_control;
+ int retval;
+
+ retval = copy_from_user(&request_control, (void *)arg, sizeof(request_control));
+ if (retval)
+ return -EFAULT;
+
+ ibrsc(board, request_control);
+
+ return 0;
+}
+
+static int t1_delay_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ t1_delay_ioctl_t cmd;
+ unsigned int delay;
+ int retval;
+
+ if (!board->interface->t1_delay) {
+ pr_warn("gpib: t1 delay not implemented in driver!\n");
+ return -EIO;
+ }
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ delay = cmd;
+
+ board->t1_nano_sec = board->interface->t1_delay(board, delay);
+
+ return 0;
+}
+
+const struct file_operations ib_fops = {
+owner: THIS_MODULE,
+llseek : NULL,
+unlocked_ioctl : &ibioctl,
+compat_ioctl : &ibioctl,
+open : &ibopen,
+release : &ibclose,
+};
+
+gpib_board_t board_array[GPIB_MAX_NUM_BOARDS];
+
+LIST_HEAD(registered_drivers);
+
+void init_gpib_descriptor(gpib_descriptor_t *desc)
+{
+ desc->pad = 0;
+ desc->sad = -1;
+ desc->is_board = 0;
+ desc->autopoll_enabled = 0;
+ atomic_set(&desc->io_in_progress, 0);
+}
+
+void gpib_register_driver(gpib_interface_t *interface, struct module *provider_module)
+{
+ struct gpib_interface_list_struct *entry;
+
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return;
+
+ entry->interface = interface;
+ entry->module = provider_module;
+ list_add(&entry->list, &registered_drivers);
+ pr_info("gpib: registered %s interface\n", interface->name);
+}
+EXPORT_SYMBOL(gpib_register_driver);
+
+void gpib_unregister_driver(gpib_interface_t *interface)
+{
+ int i;
+ struct list_head *list_ptr;
+
+ for (i = 0; i < GPIB_MAX_NUM_BOARDS; i++) {
+ gpib_board_t *board = &board_array[i];
+
+ if (board->interface == interface) {
+ if (board->use_count > 0)
+ pr_warn("gpib: Warning: deregistered interface %s in use\n",
+ interface->name);
+ iboffline(board);
+ board->interface = NULL;
+ }
+ }
+ for (list_ptr = registered_drivers.next; list_ptr != &registered_drivers;) {
+ gpib_interface_list_t *entry;
+
+ entry = list_entry(list_ptr, gpib_interface_list_t, list);
+ list_ptr = list_ptr->next;
+ if (entry->interface == interface) {
+ list_del(&entry->list);
+ kfree(entry);
+ }
+ }
+ pr_info("gpib: unregistered %s interface\n", interface->name);
+}
+EXPORT_SYMBOL(gpib_unregister_driver);
+
+static void init_gpib_board_config(gpib_board_config_t *config)
+{
+ memset(config, 0, sizeof(gpib_board_config_t));
+ config->pci_bus = -1;
+ config->pci_slot = -1;
+}
+
+void init_gpib_board(gpib_board_t *board)
+{
+ board->interface = NULL;
+ board->provider_module = NULL;
+ board->buffer = NULL;
+ board->buffer_length = 0;
+ board->status = 0;
+ init_waitqueue_head(&board->wait);
+ mutex_init(&board->user_mutex);
+ mutex_init(&board->big_gpib_mutex);
+ board->locking_pid = 0;
+ spin_lock_init(&board->locking_pid_spinlock);
+ spin_lock_init(&board->spinlock);
+ timer_setup(&board->timer, NULL, 0);
+ board->dev = NULL;
+ board->gpib_dev = NULL;
+ init_gpib_board_config(&board->config);
+ board->private_data = NULL;
+ board->use_count = 0;
+ INIT_LIST_HEAD(&board->device_list);
+ board->pad = 0;
+ board->sad = -1;
+ board->usec_timeout = 3000000;
+ board->parallel_poll_configuration = 0;
+ board->online = 0;
+ board->autospollers = 0;
+ board->autospoll_task = NULL;
+ init_event_queue(&board->event_queue);
+ board->minor = -1;
+ init_gpib_pseudo_irq(&board->pseudo_irq);
+ board->master = 1;
+ atomic_set(&board->stuck_srq, 0);
+ board->local_ppoll_mode = 0;
+}
+
+int gpib_allocate_board(gpib_board_t *board)
+{
+ if (!board->buffer) {
+ board->buffer_length = 0x4000;
+ board->buffer = vmalloc(board->buffer_length);
+ if (!board->buffer) {
+ board->buffer_length = 0;
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+void gpib_deallocate_board(gpib_board_t *board)
+{
+ short dummy;
+
+ if (board->buffer) {
+ vfree(board->buffer);
+ board->buffer = NULL;
+ board->buffer_length = 0;
+ }
+ while (num_gpib_events(&board->event_queue))
+ pop_gpib_event(board, &board->event_queue, &dummy);
+}
+
+static void init_board_array(gpib_board_t *board_array, unsigned int length)
+{
+ int i;
+
+ for (i = 0; i < length; i++) {
+ init_gpib_board(&board_array[i]);
+ board_array[i].minor = i;
+ }
+}
+
+void init_gpib_status_queue(gpib_status_queue_t *device)
+{
+ INIT_LIST_HEAD(&device->list);
+ INIT_LIST_HEAD(&device->status_bytes);
+ device->num_status_bytes = 0;
+ device->reference_count = 0;
+ device->dropped_byte = 0;
+}
+
+static struct class *gpib_class;
+
+static int __init gpib_common_init_module(void)
+{
+ int i;
+
+ pr_info("Linux-GPIB core driver\n");
+ init_board_array(board_array, GPIB_MAX_NUM_BOARDS);
+ if (register_chrdev(GPIB_CODE, "gpib", &ib_fops)) {
+ pr_err("gpib: can't get major %d\n", GPIB_CODE);
+ return -EIO;
+ }
+ gpib_class = class_create("gpib_common");
+ if (IS_ERR(gpib_class)) {
+ pr_err("gpib: failed to create gpib class\n");
+ unregister_chrdev(GPIB_CODE, "gpib");
+ return PTR_ERR(gpib_class);
+ }
+ for (i = 0; i < GPIB_MAX_NUM_BOARDS; ++i)
+ board_array[i].gpib_dev = device_create(gpib_class, 0,
+ MKDEV(GPIB_CODE, i), NULL, "gpib%i", i);
+
+ return 0;
+}
+
+static void __exit gpib_common_exit_module(void)
+{
+ int i;
+
+ for (i = 0; i < GPIB_MAX_NUM_BOARDS; ++i)
+ device_destroy(gpib_class, MKDEV(GPIB_CODE, i));
+
+ class_destroy(gpib_class);
+ unregister_chrdev(GPIB_CODE, "gpib");
+}
+
+int gpib_match_device_path(struct device *dev, const char *device_path_in)
+{
+ if (device_path_in) {
+ char *device_path;
+
+ device_path = kobject_get_path(&dev->kobj, GFP_KERNEL);
+ if (!device_path) {
+ dev_err(dev, "kobject_get_path returned NULL.");
+ return 0;
+ }
+ if (strcmp(device_path_in, device_path) != 0) {
+ kfree(device_path);
+ return 0;
+ }
+ kfree(device_path);
+ }
+ return 1;
+}
+EXPORT_SYMBOL(gpib_match_device_path);
+
+struct pci_dev *gpib_pci_get_device(const gpib_board_config_t *config, unsigned int vendor_id,
+ unsigned int device_id, struct pci_dev *from)
+{
+ struct pci_dev *pci_device = from;
+
+ while ((pci_device = pci_get_device(vendor_id, device_id, pci_device))) {
+ if (config->pci_bus >= 0 && config->pci_bus != pci_device->bus->number)
+ continue;
+ if (config->pci_slot >= 0 && config->pci_slot !=
+ PCI_SLOT(pci_device->devfn))
+ continue;
+ if (gpib_match_device_path(&pci_device->dev, config->device_path) == 0)
+ continue;
+ return pci_device;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(gpib_pci_get_device);
+
+struct pci_dev *gpib_pci_get_subsys(const gpib_board_config_t *config, unsigned int vendor_id,
+ unsigned int device_id, unsigned int ss_vendor,
+ unsigned int ss_device,
+ struct pci_dev *from)
+{
+ struct pci_dev *pci_device = from;
+
+ while ((pci_device = pci_get_subsys(vendor_id, device_id,
+ ss_vendor, ss_device, pci_device))) {
+ if (config->pci_bus >= 0 && config->pci_bus != pci_device->bus->number)
+ continue;
+ if (config->pci_slot >= 0 && config->pci_slot !=
+ PCI_SLOT(pci_device->devfn))
+ continue;
+ if (gpib_match_device_path(&pci_device->dev, config->device_path) == 0)
+ continue;
+ return pci_device;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(gpib_pci_get_subsys);
+
+module_init(gpib_common_init_module);
+module_exit(gpib_common_exit_module);
+
diff --git a/drivers/staging/gpib/common/iblib.c b/drivers/staging/gpib/common/iblib.c
new file mode 100644
index 000000000000..db1911cc1b26
--- /dev/null
+++ b/drivers/staging/gpib/common/iblib.c
@@ -0,0 +1,740 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "ibsys.h"
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/vmalloc.h>
+
+/*
+ * IBCAC
+ * Return to the controller active state from the
+ * controller standby state, i.e., turn ATN on. Note
+ * that in order to enter the controller active state
+ * from the controller idle state, ibsic must be called.
+ * If sync is non-zero, attempt to take control synchronously.
+ * If fallback_to_async is non-zero, try to take control asynchronously
+ * if synchronous attempt fails.
+ */
+int ibcac(gpib_board_t *board, int sync, int fallback_to_async)
+{
+ int status = ibstatus(board);
+ int retval;
+
+ if ((status & CIC) == 0) {
+ pr_err("gpib: not CIC during %s()\n", __func__);
+ return -1;
+ }
+
+ if (status & ATN)
+ return 0;
+
+ if (sync && (status & LACS) == 0)
+ /* tcs (take control synchronously) can only possibly work when
+ * controller is listener. Error code also needs to be -ETIMEDOUT
+ * or it will giveout without doing fallback.
+ */
+ retval = -ETIMEDOUT;
+ else
+ retval = board->interface->take_control(board, sync);
+
+ if (retval < 0 && fallback_to_async) {
+ if (sync && retval == -ETIMEDOUT)
+ retval = board->interface->take_control(board, 0);
+ }
+ board->interface->update_status(board, 0);
+
+ return retval;
+}
+
+/* After ATN is asserted, it should cause any connected devices
+ * to start listening for command bytes and leave acceptor idle state.
+ * So if ATN is asserted and neither NDAC or NRFD are asserted,
+ * then there are no devices and ibcmd should error out immediately.
+ * Some gpib hardware sees itself asserting NDAC/NRFD when it
+ * is controller in charge, in which case this check will
+ * do nothing useful (but shouldn't cause any harm either).
+ * Drivers that don't need this check (ni_usb for example) may
+ * set the skip_check_for_command_acceptors flag in their
+ * gpib_interface_struct to avoid useless overhead.
+ */
+static int check_for_command_acceptors(gpib_board_t *board)
+{
+ int lines;
+
+ if (board->interface->skip_check_for_command_acceptors)
+ return 0;
+ if (!board->interface->line_status)
+ return 0;
+
+ udelay(2); // allow time for devices to respond to ATN if it was just asserted
+
+ lines = board->interface->line_status(board);
+ if (lines < 0)
+ return lines;
+
+ if (lines & ValidATN) {
+ if ((lines & BusATN) == 0) {
+ pr_err("gpib: ATN not asserted in %s()?", __func__);
+ return 0;
+ }
+ }
+
+ if ((lines & ValidNRFD) && (lines & ValidNDAC)) {
+ if ((lines & BusNRFD) == 0 && (lines & BusNDAC) == 0)
+ return -ENOTCONN;
+ }
+
+ return 0;
+}
+
+/*
+ * IBCMD
+ * Write cnt command bytes from buf to the GPIB. The
+ * command operation terminates only on I/O complete.
+ *
+ * NOTE:
+ * 1. Prior to beginning the command, the interface is
+ * placed in the controller active state.
+ * 2. Before calling ibcmd for the first time, ibsic
+ * must be called to initialize the GPIB and enable
+ * the interface to leave the controller idle state.
+ */
+int ibcmd(gpib_board_t *board, uint8_t *buf, size_t length, size_t *bytes_written)
+{
+ ssize_t ret = 0;
+ int status;
+
+ *bytes_written = 0;
+
+ status = ibstatus(board);
+
+ if ((status & CIC) == 0) {
+ pr_err("gpib: cannot send command when not controller-in-charge\n");
+ return -EIO;
+ }
+
+ os_start_timer(board, board->usec_timeout);
+
+ ret = ibcac(board, 1, 1);
+ if (ret == 0) {
+ ret = check_for_command_acceptors(board);
+ if (ret == 0)
+ ret = board->interface->command(board, buf, length, bytes_written);
+ }
+
+ os_remove_timer(board);
+
+ if (io_timed_out(board))
+ ret = -ETIMEDOUT;
+
+ return ret;
+}
+
+/*
+ * IBGTS
+ * Go to the controller standby state from the controller
+ * active state, i.e., turn ATN off.
+ */
+
+int ibgts(gpib_board_t *board)
+{
+ int status = ibstatus(board);
+ int retval;
+
+ if ((status & CIC) == 0) {
+ pr_err("gpib: not CIC during %s()\n", __func__);
+ return -1;
+ }
+
+ retval = board->interface->go_to_standby(board); /* go to standby */
+ if (retval < 0)
+ pr_err("gpib: error while going to standby\n");
+
+ board->interface->update_status(board, 0);
+
+ return retval;
+}
+
+static int autospoll_wait_should_wake_up(gpib_board_t *board)
+{
+ int retval;
+
+ mutex_lock(&board->big_gpib_mutex);
+
+ retval = board->master && board->autospollers > 0 &&
+ !atomic_read(&board->stuck_srq) &&
+ test_and_clear_bit(SRQI_NUM, &board->status);
+
+ mutex_unlock(&board->big_gpib_mutex);
+ return retval;
+}
+
+static int autospoll_thread(void *board_void)
+{
+ gpib_board_t *board = board_void;
+ int retval = 0;
+
+ dev_dbg(board->gpib_dev, "entering autospoll thread\n");
+
+ while (1) {
+ wait_event_interruptible(board->wait,
+ kthread_should_stop() ||
+ autospoll_wait_should_wake_up(board));
+ dev_dbg(board->gpib_dev, "autospoll wait satisfied\n");
+ if (kthread_should_stop())
+ break;
+
+ mutex_lock(&board->big_gpib_mutex);
+ /* make sure we are still good after we have lock */
+ if (board->autospollers <= 0 || board->master == 0) {
+ mutex_unlock(&board->big_gpib_mutex);
+ continue;
+ }
+ mutex_unlock(&board->big_gpib_mutex);
+
+ if (try_module_get(board->provider_module)) {
+ retval = autopoll_all_devices(board);
+ module_put(board->provider_module);
+ } else {
+ pr_err("gpib%i: %s: try_module_get() failed!\n", board->minor, __func__);
+ }
+ if (retval <= 0) {
+ pr_err("gpib%i: %s: stuck SRQ\n", board->minor, __func__);
+
+ atomic_set(&board->stuck_srq, 1); // XXX could be better
+ set_bit(SRQI_NUM, &board->status);
+ }
+ }
+ pr_info("gpib%i: exiting autospoll thread\n", board->minor);
+ return retval;
+}
+
+int ibonline(gpib_board_t *board)
+{
+ int retval;
+
+ if (board->online)
+ return -EBUSY;
+ if (!board->interface)
+ return -ENODEV;
+ retval = gpib_allocate_board(board);
+ if (retval < 0)
+ return retval;
+
+ board->dev = NULL;
+ board->local_ppoll_mode = 0;
+ retval = board->interface->attach(board, &board->config);
+ if (retval < 0) {
+ board->interface->detach(board);
+ pr_err("gpib: interface attach failed\n");
+ return retval;
+ }
+ /* nios2nommu on 2.6.11 uclinux kernel has weird problems
+ * with autospoll thread causing huge slowdowns
+ */
+#ifndef CONFIG_NIOS2
+ board->autospoll_task = kthread_run(&autospoll_thread, board,
+ "gpib%d_autospoll_kthread", board->minor);
+ retval = IS_ERR(board->autospoll_task);
+ if (retval) {
+ pr_err("gpib: failed to create autospoll thread\n");
+ board->interface->detach(board);
+ return retval;
+ }
+#endif
+ board->online = 1;
+ dev_dbg(board->gpib_dev, "gpib: board online\n");
+
+ return 0;
+}
+
+/* XXX need to make sure board is generally not in use (grab board lock?) */
+int iboffline(gpib_board_t *board)
+{
+ int retval;
+
+ if (board->online == 0)
+ return 0;
+ if (!board->interface)
+ return -ENODEV;
+
+ if (board->autospoll_task && !IS_ERR(board->autospoll_task)) {
+ retval = kthread_stop(board->autospoll_task);
+ if (retval)
+ pr_err("gpib: kthread_stop returned %i\n", retval);
+ board->autospoll_task = NULL;
+ }
+
+ board->interface->detach(board);
+ gpib_deallocate_board(board);
+ board->online = 0;
+ dev_dbg(board->gpib_dev, "gpib: board offline\n");
+
+ return 0;
+}
+
+/*
+ * IBLINES
+ * Poll the GPIB control lines and return their status in buf.
+ *
+ * LSB (bits 0-7) - VALID lines mask (lines that can be monitored).
+ * Next LSB (bits 8-15) - STATUS lines mask (lines that are currently set).
+ *
+ */
+int iblines(const gpib_board_t *board, short *lines)
+{
+ int retval;
+
+ *lines = 0;
+ if (!board->interface->line_status)
+ return 0;
+ retval = board->interface->line_status(board);
+ if (retval < 0)
+ return retval;
+ *lines = retval;
+ return 0;
+}
+
+/*
+ * IBRD
+ * Read up to 'length' bytes of data from the GPIB into buf. End
+ * on detection of END (EOI and or EOS) and set 'end_flag'.
+ *
+ * NOTE:
+ * 1. The interface is placed in the controller standby
+ * state prior to beginning the read.
+ * 2. Prior to calling ibrd, the intended devices as well
+ * as the interface board itself must be addressed by
+ * calling ibcmd.
+ */
+
+int ibrd(gpib_board_t *board, uint8_t *buf, size_t length, int *end_flag, size_t *nbytes)
+{
+ ssize_t ret = 0;
+ int retval;
+ size_t bytes_read;
+
+ *nbytes = 0;
+ *end_flag = 0;
+ if (length == 0) {
+ pr_warn("gpib: %s() called with zero length?\n", __func__);
+ return 0;
+ }
+
+ if (board->master) {
+ retval = ibgts(board);
+ if (retval < 0)
+ return retval;
+ }
+ /* XXX resetting timer here could cause timeouts take longer than they should,
+ * since read_ioctl calls this
+ * function in a loop, there is probably a similar problem with writes/commands
+ */
+ os_start_timer(board, board->usec_timeout);
+
+ do {
+ ret = board->interface->read(board, buf, length - *nbytes, end_flag, &bytes_read);
+ if (ret < 0) {
+ pr_err("gpib read error\n");
+ goto ibrd_out;
+ }
+ buf += bytes_read;
+ *nbytes += bytes_read;
+ if (need_resched())
+ schedule();
+ } while (ret == 0 && *nbytes > 0 && *nbytes < length && *end_flag == 0);
+ibrd_out:
+ os_remove_timer(board);
+
+ return ret;
+}
+
+/*
+ * IBRPP
+ * Conduct a parallel poll and return the byte in buf.
+ *
+ * NOTE:
+ * 1. Prior to conducting the poll the interface is placed
+ * in the controller active state.
+ */
+int ibrpp(gpib_board_t *board, uint8_t *result)
+{
+ int retval = 0;
+
+ os_start_timer(board, board->usec_timeout);
+ retval = ibcac(board, 1, 1);
+ if (retval)
+ return -1;
+
+ if (board->interface->parallel_poll(board, result)) {
+ pr_err("gpib: parallel poll failed\n");
+ retval = -1;
+ }
+ os_remove_timer(board);
+ return retval;
+}
+
+int ibppc(gpib_board_t *board, uint8_t configuration)
+{
+ configuration &= 0x1f;
+ board->interface->parallel_poll_configure(board, configuration);
+ board->parallel_poll_configuration = configuration;
+
+ return 0;
+}
+
+int ibrsv2(gpib_board_t *board, uint8_t status_byte, int new_reason_for_service)
+{
+ int board_status = ibstatus(board);
+ const unsigned int MSS = status_byte & request_service_bit;
+
+ if ((board_status & CIC)) {
+ pr_err("gpib: interface requested service while CIC\n");
+ return -EINVAL;
+ }
+
+ if (MSS == 0 && new_reason_for_service)
+ return -EINVAL;
+
+ if (board->interface->serial_poll_response2) {
+ board->interface->serial_poll_response2(board, status_byte, new_reason_for_service);
+ // fall back on simpler serial_poll_response if the behavior would be the same
+ } else if (board->interface->serial_poll_response &&
+ (MSS == 0 || (MSS && new_reason_for_service))) {
+ board->interface->serial_poll_response(board, status_byte);
+ } else {
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+/*
+ * IBSIC
+ * Send IFC for at least 100 microseconds.
+ *
+ * NOTE:
+ * 1. Ibsic must be called prior to the first call to
+ * ibcmd in order to initialize the bus and enable the
+ * interface to leave the controller idle state.
+ */
+int ibsic(gpib_board_t *board, unsigned int usec_duration)
+{
+ if (board->master == 0) {
+ pr_err("gpib: tried to assert IFC when not system controller\n");
+ return -1;
+ }
+
+ if (usec_duration < 100)
+ usec_duration = 100;
+ if (usec_duration > 1000) {
+ usec_duration = 1000;
+ pr_warn("gpib: warning, shortening long udelay\n");
+ }
+
+ dev_dbg(board->gpib_dev, "sending interface clear\n");
+ board->interface->interface_clear(board, 1);
+ udelay(usec_duration);
+ board->interface->interface_clear(board, 0);
+
+ return 0;
+}
+
+void ibrsc(gpib_board_t *board, int request_control)
+{
+ board->master = request_control != 0;
+ if (!board->interface->request_system_control) {
+ pr_err("gpib: bug! driver does not implement request_system_control()\n");
+ return;
+ }
+ board->interface->request_system_control(board, request_control);
+}
+
+/*
+ * IBSRE
+ * Send REN true if v is non-zero or false if v is zero.
+ */
+int ibsre(gpib_board_t *board, int enable)
+{
+ if (board->master == 0) {
+ pr_err("gpib: tried to set REN when not system controller\n");
+ return -1;
+ }
+
+ board->interface->remote_enable(board, enable); /* set or clear REN */
+ if (!enable)
+ usleep_range(100, 150);
+
+ return 0;
+}
+
+/*
+ * IBPAD
+ * change the GPIB address of the interface board. The address
+ * must be 0 through 30. ibonl resets the address to PAD.
+ */
+int ibpad(gpib_board_t *board, unsigned int addr)
+{
+ if (addr > MAX_GPIB_PRIMARY_ADDRESS) {
+ pr_err("gpib: invalid primary address %u\n", addr);
+ return -1;
+ }
+ board->pad = addr;
+ if (board->online)
+ board->interface->primary_address(board, board->pad);
+ dev_dbg(board->gpib_dev, "set primary addr to %i\n", board->pad);
+ return 0;
+}
+
+/*
+ * IBSAD
+ * change the secondary GPIB address of the interface board.
+ * The address must be 0 through 30, or negative disables. ibonl resets the
+ * address to SAD.
+ */
+int ibsad(gpib_board_t *board, int addr)
+{
+ if (addr > MAX_GPIB_SECONDARY_ADDRESS) {
+ pr_err("gpib: invalid secondary address %i\n", addr);
+ return -1;
+ }
+ board->sad = addr;
+ if (board->online) {
+ if (board->sad >= 0)
+ board->interface->secondary_address(board, board->sad, 1);
+ else
+ board->interface->secondary_address(board, 0, 0);
+ }
+ dev_dbg(board->gpib_dev, "set secondary addr to %i\n", board->sad);
+
+ return 0;
+}
+
+/*
+ * IBEOS
+ * Set the end-of-string modes for I/O operations to v.
+ *
+ */
+int ibeos(gpib_board_t *board, int eos, int eosflags)
+{
+ int retval;
+
+ if (eosflags & ~EOS_MASK) {
+ pr_err("bad EOS modes\n");
+ return -EINVAL;
+ }
+ if (eosflags & REOS) {
+ retval = board->interface->enable_eos(board, eos, eosflags & BIN);
+ } else {
+ board->interface->disable_eos(board);
+ retval = 0;
+ }
+ return retval;
+}
+
+int ibstatus(gpib_board_t *board)
+{
+ return general_ibstatus(board, NULL, 0, 0, NULL);
+}
+
+int general_ibstatus(gpib_board_t *board, const gpib_status_queue_t *device,
+ int clear_mask, int set_mask, gpib_descriptor_t *desc)
+{
+ int status = 0;
+ short line_status;
+
+ if (board->private_data) {
+ status = board->interface->update_status(board, clear_mask);
+ /* XXX should probably stop having drivers use TIMO bit in
+ * board->status to avoid confusion
+ */
+ status &= ~TIMO;
+ /* get real SRQI status if we can */
+ if (iblines(board, &line_status) == 0) {
+ if ((line_status & ValidSRQ)) {
+ if ((line_status & BusSRQ))
+ status |= SRQI;
+ else
+ status &= ~SRQI;
+ }
+ }
+ }
+ if (device)
+ if (num_status_bytes(device))
+ status |= RQS;
+
+ if (desc) {
+ if (set_mask & CMPL)
+ atomic_set(&desc->io_in_progress, 0);
+ else if (clear_mask & CMPL)
+ atomic_set(&desc->io_in_progress, 1);
+
+ if (atomic_read(&desc->io_in_progress))
+ status &= ~CMPL;
+ else
+ status |= CMPL;
+ }
+ if (num_gpib_events(&board->event_queue))
+ status |= EVENT;
+ else
+ status &= ~EVENT;
+
+ return status;
+}
+
+struct wait_info {
+ gpib_board_t *board;
+ struct timer_list timer;
+ int timed_out;
+ unsigned long usec_timeout;
+};
+
+static void wait_timeout(struct timer_list *t)
+{
+ struct wait_info *winfo = from_timer(winfo, t, timer);
+
+ winfo->timed_out = 1;
+ wake_up_interruptible(&winfo->board->wait);
+}
+
+static void init_wait_info(struct wait_info *winfo)
+{
+ winfo->board = NULL;
+ winfo->timed_out = 0;
+ timer_setup_on_stack(&winfo->timer, wait_timeout, 0);
+}
+
+static int wait_satisfied(struct wait_info *winfo, gpib_status_queue_t *status_queue,
+ int wait_mask, int *status, gpib_descriptor_t *desc)
+{
+ gpib_board_t *board = winfo->board;
+ int temp_status;
+
+ if (mutex_lock_interruptible(&board->big_gpib_mutex))
+ return -ERESTARTSYS;
+
+ temp_status = general_ibstatus(board, status_queue, 0, 0, desc);
+
+ mutex_unlock(&board->big_gpib_mutex);
+
+ if (winfo->timed_out)
+ temp_status |= TIMO;
+ else
+ temp_status &= ~TIMO;
+ if (wait_mask & temp_status) {
+ *status = temp_status;
+ return 1;
+ }
+//XXX does wait for END work?
+ return 0;
+}
+
+/* install timer interrupt handler */
+static void start_wait_timer(struct wait_info *winfo)
+/* Starts the timeout task */
+{
+ winfo->timed_out = 0;
+
+ if (winfo->usec_timeout > 0)
+ mod_timer(&winfo->timer, jiffies + usec_to_jiffies(winfo->usec_timeout));
+}
+
+static void remove_wait_timer(struct wait_info *winfo)
+{
+ del_timer_sync(&winfo->timer);
+ destroy_timer_on_stack(&winfo->timer);
+}
+
+/*
+ * IBWAIT
+ * Check or wait for a GPIB event to occur. The mask argument
+ * is a bit vector corresponding to the status bit vector. It
+ * has a bit set for each condition which can terminate the wait
+ * If the mask is 0 then
+ * no condition is waited for.
+ */
+int ibwait(gpib_board_t *board, int wait_mask, int clear_mask, int set_mask,
+ int *status, unsigned long usec_timeout, gpib_descriptor_t *desc)
+{
+ int retval = 0;
+ gpib_status_queue_t *status_queue;
+ struct wait_info winfo;
+
+ if (desc->is_board)
+ status_queue = NULL;
+ else
+ status_queue = get_gpib_status_queue(board, desc->pad, desc->sad);
+
+ if (wait_mask == 0) {
+ *status = general_ibstatus(board, status_queue, clear_mask, set_mask, desc);
+ return 0;
+ }
+
+ mutex_unlock(&board->big_gpib_mutex);
+
+ init_wait_info(&winfo);
+ winfo.board = board;
+ winfo.usec_timeout = usec_timeout;
+ start_wait_timer(&winfo);
+
+ if (wait_event_interruptible(board->wait, wait_satisfied(&winfo, status_queue,
+ wait_mask, status, desc))) {
+ dev_dbg(board->gpib_dev, "wait interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ remove_wait_timer(&winfo);
+
+ if (retval)
+ return retval;
+ if (mutex_lock_interruptible(&board->big_gpib_mutex))
+ return -ERESTARTSYS;
+
+ /* make sure we only clear status bits that we are reporting */
+ if (*status & clear_mask || set_mask)
+ general_ibstatus(board, status_queue, *status & clear_mask, set_mask, 0);
+
+ return 0;
+}
+
+/*
+ * IBWRT
+ * Write cnt bytes of data from buf to the GPIB. The write
+ * operation terminates only on I/O complete.
+ *
+ * NOTE:
+ * 1. Prior to beginning the write, the interface is
+ * placed in the controller standby state.
+ * 2. Prior to calling ibwrt, the intended devices as
+ * well as the interface board itself must be
+ * addressed by calling ibcmd.
+ */
+int ibwrt(gpib_board_t *board, uint8_t *buf, size_t cnt, int send_eoi, size_t *bytes_written)
+{
+ int ret = 0;
+ int retval;
+
+ if (cnt == 0) {
+ pr_warn("gpib: %s() called with zero length?\n", __func__);
+ return 0;
+ }
+
+ if (board->master) {
+ retval = ibgts(board);
+ if (retval < 0)
+ return retval;
+ }
+ os_start_timer(board, board->usec_timeout);
+ ret = board->interface->write(board, buf, cnt, send_eoi, bytes_written);
+
+ if (io_timed_out(board))
+ ret = -ETIMEDOUT;
+
+ os_remove_timer(board);
+
+ return ret;
+}
+
diff --git a/drivers/staging/gpib/common/ibsys.h b/drivers/staging/gpib/common/ibsys.h
new file mode 100644
index 000000000000..da20971e9c7e
--- /dev/null
+++ b/drivers/staging/gpib/common/ibsys.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include "gpibP.h"
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/timer.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+
+#define MAX_GPIB_PRIMARY_ADDRESS 30
+#define MAX_GPIB_SECONDARY_ADDRESS 31
+
+int gpib_allocate_board(gpib_board_t *board);
+void gpib_deallocate_board(gpib_board_t *board);
+
+unsigned int num_status_bytes(const gpib_status_queue_t *dev);
+int push_status_byte(gpib_board_t *board, gpib_status_queue_t *device, uint8_t poll_byte);
+int pop_status_byte(gpib_board_t *board, gpib_status_queue_t *device, uint8_t *poll_byte);
+gpib_status_queue_t *get_gpib_status_queue(gpib_board_t *board, unsigned int pad, int sad);
+int get_serial_poll_byte(gpib_board_t *board, unsigned int pad, int sad,
+ unsigned int usec_timeout, uint8_t *poll_byte);
+int autopoll_all_devices(gpib_board_t *board);
diff --git a/drivers/staging/gpib/eastwood/Makefile b/drivers/staging/gpib/eastwood/Makefile
new file mode 100644
index 000000000000..c74056f959d0
--- /dev/null
+++ b/drivers/staging/gpib/eastwood/Makefile
@@ -0,0 +1,3 @@
+
+obj-m += fluke_gpib.o
+
diff --git a/drivers/staging/gpib/eastwood/fluke_gpib.c b/drivers/staging/gpib/eastwood/fluke_gpib.c
new file mode 100644
index 000000000000..3f938ab0c84d
--- /dev/null
+++ b/drivers/staging/gpib/eastwood/fluke_gpib.c
@@ -0,0 +1,1179 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * GPIB Driver for Fluke cda devices. Basically, its a driver for a (bugfixed)
+ * cb7210 connected to channel 0 of a pl330 dma controller.
+ * Author: Frank Mori Hess <fmh6jj@gmail.com>
+ * copyright: (C) 2006, 2010, 2015 Fluke Corporation
+ ***************************************************************************/
+
+#include "fluke_gpib.h"
+
+#include "gpibP.h"
+#include <linux/dma-mapping.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB Driver for Fluke cda devices");
+
+static int fluke_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config);
+static int fluke_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config);
+static void fluke_detach(gpib_board_t *board);
+static int fluke_config_dma(gpib_board_t *board, int output);
+static irqreturn_t fluke_gpib_internal_interrupt(gpib_board_t *board);
+
+static struct platform_device *fluke_gpib_pdev;
+
+static uint8_t fluke_locking_read_byte(struct nec7210_priv *nec_priv, unsigned int register_number)
+{
+ u8 retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nec_priv->register_page_lock, flags);
+ retval = fluke_read_byte_nolock(nec_priv, register_number);
+ spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
+ return retval;
+}
+
+static void fluke_locking_write_byte(struct nec7210_priv *nec_priv, uint8_t byte,
+ unsigned int register_number)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&nec_priv->register_page_lock, flags);
+ fluke_write_byte_nolock(nec_priv, byte, register_number);
+ spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
+}
+
+// wrappers for interface functions
+static int fluke_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+}
+
+static int fluke_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+static int fluke_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+static int fluke_take_control(gpib_board_t *board, int synchronous)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+static int fluke_go_to_standby(gpib_board_t *board)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+static void fluke_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct fluke_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ nec7210_request_system_control(board, nec_priv, request_control);
+}
+
+static void fluke_interface_clear(gpib_board_t *board, int assert)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+static void fluke_remote_enable(gpib_board_t *board, int enable)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+static int fluke_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+static void fluke_disable_eos(gpib_board_t *board)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+static unsigned int fluke_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
+}
+
+static int fluke_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+static int fluke_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+static int fluke_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
+}
+
+static void fluke_parallel_poll_configure(gpib_board_t *board, uint8_t configuration)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration);
+}
+
+static void fluke_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+static void fluke_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
+}
+
+static uint8_t fluke_serial_poll_status(gpib_board_t *board)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+static void fluke_return_to_local(gpib_board_t *board)
+{
+ struct fluke_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ write_byte(nec_priv, AUX_RTL2, AUXMR);
+ udelay(1);
+ write_byte(nec_priv, AUX_RTL, AUXMR);
+}
+
+static int fluke_line_status(const gpib_board_t *board)
+{
+ int status = ValidALL;
+ int bsr_bits;
+ struct fluke_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+
+ bsr_bits = fluke_paged_read_byte(e_priv, BUS_STATUS, BUS_STATUS_PAGE);
+
+ if ((bsr_bits & BSR_REN_BIT) == 0)
+ status |= BusREN;
+ if ((bsr_bits & BSR_IFC_BIT) == 0)
+ status |= BusIFC;
+ if ((bsr_bits & BSR_SRQ_BIT) == 0)
+ status |= BusSRQ;
+ if ((bsr_bits & BSR_EOI_BIT) == 0)
+ status |= BusEOI;
+ if ((bsr_bits & BSR_NRFD_BIT) == 0)
+ status |= BusNRFD;
+ if ((bsr_bits & BSR_NDAC_BIT) == 0)
+ status |= BusNDAC;
+ if ((bsr_bits & BSR_DAV_BIT) == 0)
+ status |= BusDAV;
+ if ((bsr_bits & BSR_ATN_BIT) == 0)
+ status |= BusATN;
+
+ return status;
+}
+
+static unsigned int fluke_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned int retval;
+
+ retval = nec7210_t1_delay(board, nec_priv, nano_sec);
+
+ if (nano_sec <= 350) {
+ write_byte(nec_priv, AUX_HI_SPEED, AUXMR);
+ retval = 350;
+ } else {
+ write_byte(nec_priv, AUX_LO_SPEED, AUXMR);
+ }
+ return retval;
+}
+
+static int lacs_or_read_ready(gpib_board_t *board)
+{
+ const struct fluke_priv *e_priv = board->private_data;
+ const struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+ int retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = test_bit(LACS_NUM, &board->status) || test_bit(READ_READY_BN, &nec_priv->state);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+/* Wait until it is possible for a read to do something useful. This
+ * is not essential, it only exists to prevent RFD holdoff from being released pointlessly.
+ */
+static int wait_for_read(gpib_board_t *board)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+
+ if (wait_event_interruptible(board->wait,
+ lacs_or_read_ready(board) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ return retval;
+}
+
+/* Check if the SH state machine is in SGNS. We check twice since there is a very small chance
+ * we could be blowing through SGNS from SIDS to SDYS if there is already a
+ * byte available in the handshake state machine. We are interested
+ * in the case where the handshake is stuck in SGNS due to no byte being
+ * available to the chip (and thus we can be confident a dma transfer will
+ * result in at least one byte making it into the chip). This matters
+ * because we want to be confident before sending a "send eoi" auxilary
+ * command that we will be able to also put the associated data byte
+ * in the chip before any potential timeout.
+ */
+static int source_handshake_is_sgns(struct fluke_priv *e_priv)
+{
+ int i;
+
+ for (i = 0; i < 2; ++i) {
+ if ((fluke_paged_read_byte(e_priv, STATE1_REG, STATE1_PAGE) &
+ SOURCE_HANDSHAKE_MASK) != SOURCE_HANDSHAKE_SGNS_BITS) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int source_handshake_is_sids_or_sgns(struct fluke_priv *e_priv)
+{
+ unsigned int source_handshake_bits;
+
+ source_handshake_bits = fluke_paged_read_byte(e_priv, STATE1_REG, STATE1_PAGE) &
+ SOURCE_HANDSHAKE_MASK;
+
+ return (source_handshake_bits == SOURCE_HANDSHAKE_SGNS_BITS) ||
+ (source_handshake_bits == SOURCE_HANDSHAKE_SIDS_BITS);
+}
+
+/* Wait until the gpib chip is ready to accept a data out byte.
+ * If the chip is SGNS it is probably waiting for a a byte to
+ * be written to it.
+ */
+static int wait_for_data_out_ready(gpib_board_t *board)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+// printk("%s: enter\n", __FUNCTION__);
+
+ if (wait_event_interruptible(board->wait,
+ (test_bit(TACS_NUM, &board->status) &&
+ source_handshake_is_sgns(e_priv)) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+// printk("%s: exit, retval=%i\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static int wait_for_sids_or_sgns(gpib_board_t *board)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+// printk("%s: enter\n", __FUNCTION__);
+
+ if (wait_event_interruptible(board->wait,
+ source_handshake_is_sids_or_sgns(e_priv) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status)))
+ retval = -ERESTARTSYS;
+
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+// printk("%s: exit, retval=%i\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static void fluke_dma_callback(void *arg)
+{
+ gpib_board_t *board = arg;
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+// printk("%s: enter\n", __FUNCTION__);
+
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, HR_DOIE | HR_DIIE);
+ wake_up_interruptible(&board->wait);
+
+ fluke_gpib_internal_interrupt(board);
+ clear_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state);
+ clear_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state);
+// printk("%s: exit\n", __FUNCTION__);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+static int fluke_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+ int retval = 0;
+ dma_addr_t address;
+ struct dma_async_tx_descriptor *tx_desc;
+
+ *bytes_written = 0;
+// printk("%s: enter\n", __FUNCTION__);
+ if (WARN_ON_ONCE(length > e_priv->dma_buffer_size))
+ return -EFAULT;
+ dmaengine_terminate_all(e_priv->dma_channel);
+ // write-clear counter
+ writel(0x0, e_priv->write_transfer_counter);
+
+ memcpy(e_priv->dma_buffer, buffer, length);
+ address = dma_map_single(board->dev, e_priv->dma_buffer,
+ length, DMA_TO_DEVICE);
+ /* program dma controller */
+ retval = fluke_config_dma(board, 1);
+ if (retval)
+ goto cleanup;
+
+ tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, address, length, DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!tx_desc) {
+ pr_err("fluke_gpib: failed to allocate dma transmit descriptor\n");
+ retval = -ENOMEM;
+ goto cleanup;
+ }
+ tx_desc->callback = fluke_dma_callback;
+ tx_desc->callback_param = board;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO);
+ dmaengine_submit(tx_desc);
+ dma_async_issue_pending(e_priv->dma_channel);
+
+ clear_bit(WRITE_READY_BN, &nec_priv->state);
+ set_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state);
+
+ // printk("%s: in spin lock\n", __FUNCTION__);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+// printk("%s: waiting for write.\n", __FUNCTION__);
+ // suspend until message is sent
+ if (wait_event_interruptible(board->wait,
+ ((readl(e_priv->write_transfer_counter) &
+ write_transfer_counter_mask) == length) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted!\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state))
+ retval = -EIO;
+ // disable board's dma
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0);
+
+ dmaengine_terminate_all(e_priv->dma_channel);
+ // make sure fluke_dma_callback got called
+ if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state))
+ fluke_dma_callback(board);
+
+ /* if everything went fine, try to wait until last byte is actually
+ * transmitted across gpib (but don't try _too_ hard)
+ */
+ if (retval == 0)
+ retval = wait_for_sids_or_sgns(board);
+
+ *bytes_written = readl(e_priv->write_transfer_counter) & write_transfer_counter_mask;
+ if (WARN_ON_ONCE(*bytes_written > length))
+ return -EFAULT;
+
+cleanup:
+ dma_unmap_single(board->dev, address, length, DMA_TO_DEVICE);
+// printk("%s: exit, retval=%d\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static int fluke_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ size_t remainder = length;
+ size_t transfer_size;
+ ssize_t retval = 0;
+ size_t dma_remainder = remainder;
+
+ if (!e_priv->dma_channel) {
+ pr_err("fluke_gpib: No dma channel available, cannot do accel write.");
+ return -ENXIO;
+ }
+
+ *bytes_written = 0;
+ if (length < 1)
+ return 0;
+
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME
+
+ if (send_eoi)
+ --dma_remainder;
+// printk("%s: entering while loop\n", __FUNCTION__);
+
+ while (dma_remainder > 0) {
+ size_t num_bytes;
+
+ retval = wait_for_data_out_ready(board);
+ if (retval < 0)
+ break;
+
+ transfer_size = (e_priv->dma_buffer_size < dma_remainder) ?
+ e_priv->dma_buffer_size : dma_remainder;
+ retval = fluke_dma_write(board, buffer, transfer_size, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ break;
+ dma_remainder -= num_bytes;
+ remainder -= num_bytes;
+ buffer += num_bytes;
+ if (need_resched())
+ schedule();
+ }
+ if (retval < 0)
+ return retval;
+ //handle sending of last byte with eoi
+ if (send_eoi) {
+ size_t num_bytes;
+ // printk("%s: handling last byte\n", __FUNCTION__);
+ if (WARN_ON_ONCE(remainder != 1))
+ return -EFAULT;
+
+ /* wait until we are sure we will be able to write the data byte
+ * into the chip before we send AUX_SEOI. This prevents a timeout
+ * scenerio where we send AUX_SEOI but then timeout without getting
+ * any bytes into the gpib chip. This will result in the first byte
+ * of the next write having a spurious EOI set on the first byte.
+ */
+ retval = wait_for_data_out_ready(board);
+ if (retval < 0)
+ return retval;
+
+ write_byte(nec_priv, AUX_SEOI, AUXMR);
+ retval = fluke_dma_write(board, buffer, remainder, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ remainder -= num_bytes;
+ }
+// printk("%s: bytes send=%i\n", __FUNCTION__, (int)(length - remainder));
+ return 0;
+}
+
+static int fluke_get_dma_residue(struct dma_chan *chan, dma_cookie_t cookie)
+{
+ struct dma_tx_state state;
+ int result;
+
+ result = dmaengine_pause(chan);
+ if (result < 0) {
+ pr_err("fluke_gpib: dma pause failed?\n");
+ return result;
+ }
+ dmaengine_tx_status(chan, cookie, &state);
+ // hardware doesn't support resume, so dont call this
+ // method unless the dma transfer is done.
+ return state.residue;
+}
+
+static int fluke_dma_read(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+ unsigned long flags;
+ int residue;
+ dma_addr_t bus_address;
+ struct dma_async_tx_descriptor *tx_desc;
+ dma_cookie_t dma_cookie;
+ int i;
+ static const int timeout = 10;
+
+ // printk("%s: enter, bus_address=0x%x, length=%i\n", __FUNCTION__,
+ // (unsigned)bus_address,
+ // (int)length);
+
+ *bytes_read = 0;
+ *end = 0;
+ if (length == 0)
+ return 0;
+
+ bus_address = dma_map_single(board->dev, e_priv->dma_buffer,
+ length, DMA_FROM_DEVICE);
+
+ /* program dma controller */
+ retval = fluke_config_dma(board, 0);
+ if (retval) {
+ dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE);
+ return retval;
+ }
+ tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel,
+ bus_address, length, DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!tx_desc) {
+ pr_err("fluke_gpib: failed to allocate dma transmit descriptor\n");
+ dma_unmap_single(NULL, bus_address, length, DMA_FROM_DEVICE);
+ return -EIO;
+ }
+ tx_desc->callback = fluke_dma_callback;
+ tx_desc->callback_param = board;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ // enable nec7210 dma
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI);
+
+ dma_cookie = dmaengine_submit(tx_desc);
+ dma_async_issue_pending(e_priv->dma_channel);
+
+ set_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state);
+ clear_bit(READ_READY_BN, &nec_priv->state);
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+// printk("waiting for data transfer.\n");
+ // wait for data to transfer
+ if (wait_event_interruptible(board->wait,
+ test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state) == 0 ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_warn("fluke: dma read wait interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+
+ /* If we woke up because of end, wait until the dma transfer has pulled
+ * the data byte associated with the end before we cancel the dma transfer.
+ */
+ if (test_bit(RECEIVED_END_BN, &nec_priv->state)) {
+ for (i = 0; i < timeout; ++i) {
+ if (test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state) == 0)
+ break;
+ if ((read_byte(nec_priv, ADR0) & DATA_IN_STATUS) == 0)
+ break;
+ usleep_range(10, 15);
+ }
+ if (i == timeout)
+ pr_warn("fluke_gpib: timeout waiting for dma to transfer end data byte.\n");
+ }
+
+ // stop the dma transfer
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+ /* delay a little just to make sure any bytes in dma controller's fifo get
+ * written to memory before we disable it
+ */
+ usleep_range(10, 15);
+ residue = fluke_get_dma_residue(e_priv->dma_channel, dma_cookie);
+ if (WARN_ON_ONCE(residue > length || residue < 0))
+ return -EFAULT;
+ *bytes_read += length - residue;
+ dmaengine_terminate_all(e_priv->dma_channel);
+ // make sure fluke_dma_callback got called
+ if (test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state))
+ fluke_dma_callback(board);
+
+ dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE);
+ memcpy(buffer, e_priv->dma_buffer, *bytes_read);
+
+ /* If we got an end interrupt, figure out if it was
+ * associated with the last byte we dma'd or with a
+ * byte still sitting on the cb7210.
+ */
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (test_bit(READ_READY_BN, &nec_priv->state) == 0) {
+ // There is no byte sitting on the cb7210. If we
+ // saw an end interrupt, we need to deal with it now
+ if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state))
+ *end = 1;
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return retval;
+}
+
+static int fluke_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ size_t remain = length;
+ size_t transfer_size;
+ int retval = 0;
+ size_t dma_nbytes;
+
+/* printk("%s: enter, buffer=0x%p, length=%i\n", __FUNCTION__,
+ * buffer, (int)length);
+ * printk("\t dma_buffer=0x%p\n", e_priv->dma_buffer);
+ */
+ *end = 0;
+ *bytes_read = 0;
+
+ smp_mb__before_atomic();
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME
+ smp_mb__after_atomic();
+
+ retval = wait_for_read(board);
+ if (retval < 0)
+ return retval;
+
+ nec7210_release_rfd_holdoff(board, nec_priv);
+
+// printk("%s: entering while loop\n", __FUNCTION__);
+ while (remain > 0) {
+ transfer_size = (e_priv->dma_buffer_size < remain) ?
+ e_priv->dma_buffer_size : remain;
+ retval = fluke_dma_read(board, buffer, transfer_size, end, &dma_nbytes);
+ remain -= dma_nbytes;
+ buffer += dma_nbytes;
+ *bytes_read += dma_nbytes;
+ if (*end)
+ break;
+ if (retval < 0) {
+// printk("%s: early exit, retval=%i\n", __FUNCTION__, (int)retval);
+ return retval;
+ }
+ if (need_resched())
+ schedule();
+ }
+// printk("%s: exit, retval=%i\n", __FUNCTION__, (int)retval);
+ return retval;
+}
+
+gpib_interface_t fluke_unaccel_interface = {
+name: "fluke_unaccel",
+attach : fluke_attach_holdoff_all,
+detach : fluke_detach,
+read : fluke_read,
+write : fluke_write,
+command : fluke_command,
+take_control : fluke_take_control,
+go_to_standby : fluke_go_to_standby,
+request_system_control : fluke_request_system_control,
+interface_clear : fluke_interface_clear,
+remote_enable : fluke_remote_enable,
+enable_eos : fluke_enable_eos,
+disable_eos : fluke_disable_eos,
+parallel_poll : fluke_parallel_poll,
+parallel_poll_configure : fluke_parallel_poll_configure,
+parallel_poll_response : fluke_parallel_poll_response,
+line_status : fluke_line_status,
+update_status : fluke_update_status,
+primary_address : fluke_primary_address,
+secondary_address : fluke_secondary_address,
+serial_poll_response : fluke_serial_poll_response,
+serial_poll_status : fluke_serial_poll_status,
+t1_delay : fluke_t1_delay,
+return_to_local : fluke_return_to_local,
+};
+
+/* fluke_hybrid uses dma for writes but not for reads. Added
+ * to deal with occasional corruption of bytes seen when doing dma
+ * reads. From looking at the cb7210 vhdl, I believe the corruption
+ * is due to a hardware bug triggered by the cpu reading a cb7210
+ * }
+ * register just as the dma controller is also doing a read.
+ */
+
+gpib_interface_t fluke_hybrid_interface = {
+name: "fluke_hybrid",
+attach : fluke_attach_holdoff_all,
+detach : fluke_detach,
+read : fluke_read,
+write : fluke_accel_write,
+command : fluke_command,
+take_control : fluke_take_control,
+go_to_standby : fluke_go_to_standby,
+request_system_control : fluke_request_system_control,
+interface_clear : fluke_interface_clear,
+remote_enable : fluke_remote_enable,
+enable_eos : fluke_enable_eos,
+disable_eos : fluke_disable_eos,
+parallel_poll : fluke_parallel_poll,
+parallel_poll_configure : fluke_parallel_poll_configure,
+parallel_poll_response : fluke_parallel_poll_response,
+line_status : fluke_line_status,
+update_status : fluke_update_status,
+primary_address : fluke_primary_address,
+secondary_address : fluke_secondary_address,
+serial_poll_response : fluke_serial_poll_response,
+serial_poll_status : fluke_serial_poll_status,
+t1_delay : fluke_t1_delay,
+return_to_local : fluke_return_to_local,
+};
+
+gpib_interface_t fluke_interface = {
+name: "fluke",
+attach : fluke_attach_holdoff_end,
+detach : fluke_detach,
+read : fluke_accel_read,
+write : fluke_accel_write,
+command : fluke_command,
+take_control : fluke_take_control,
+go_to_standby : fluke_go_to_standby,
+request_system_control : fluke_request_system_control,
+interface_clear : fluke_interface_clear,
+remote_enable : fluke_remote_enable,
+enable_eos : fluke_enable_eos,
+disable_eos : fluke_disable_eos,
+parallel_poll : fluke_parallel_poll,
+parallel_poll_configure : fluke_parallel_poll_configure,
+parallel_poll_response : fluke_parallel_poll_response,
+line_status : fluke_line_status,
+update_status : fluke_update_status,
+primary_address : fluke_primary_address,
+secondary_address : fluke_secondary_address,
+serial_poll_response : fluke_serial_poll_response,
+serial_poll_status : fluke_serial_poll_status,
+t1_delay : fluke_t1_delay,
+return_to_local : fluke_return_to_local,
+};
+
+irqreturn_t fluke_gpib_internal_interrupt(gpib_board_t *board)
+{
+ int status0, status1, status2;
+ struct fluke_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+ int retval = IRQ_NONE;
+
+ if (read_byte(nec_priv, ADR0) & DATA_IN_STATUS)
+ set_bit(READ_READY_BN, &nec_priv->state);
+
+ status0 = fluke_paged_read_byte(priv, ISR0_IMR0, ISR0_IMR0_PAGE);
+ status1 = read_byte(nec_priv, ISR1);
+ status2 = read_byte(nec_priv, ISR2);
+
+ if (status0 & FLUKE_IFCI_BIT) {
+ push_gpib_event(board, EventIFC);
+ retval = IRQ_HANDLED;
+ }
+
+ if (nec7210_interrupt_have_status(board, nec_priv, status1, status2) == IRQ_HANDLED)
+ retval = IRQ_HANDLED;
+/*
+ * if((status1 & nec_priv->reg_bits[IMR1]) ||
+ * (status2 & (nec_priv->reg_bits[IMR2] & IMR2_ENABLE_INTR_MASK)))
+ * {
+ * printk("fluke: status1 0x%x, status2 0x%x\n", status1, status2);
+ * }
+ */
+
+ if (read_byte(nec_priv, ADR0) & DATA_IN_STATUS) {
+ if (test_bit(RFD_HOLDOFF_BN, &nec_priv->state))
+ set_bit(READ_READY_BN, &nec_priv->state);
+ else
+ clear_bit(READ_READY_BN, &nec_priv->state);
+ }
+
+ if (retval == IRQ_HANDLED)
+ wake_up_interruptible(&board->wait);
+
+ return retval;
+}
+
+static irqreturn_t fluke_gpib_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = fluke_gpib_internal_interrupt(board);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+static int fluke_allocate_private(gpib_board_t *board)
+{
+ struct fluke_priv *priv;
+
+ board->private_data = kmalloc(sizeof(struct fluke_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+ priv = board->private_data;
+ memset(priv, 0, sizeof(struct fluke_priv));
+ init_nec7210_private(&priv->nec7210_priv);
+ priv->dma_buffer_size = 0x7ff;
+ priv->dma_buffer = kmalloc(priv->dma_buffer_size, GFP_KERNEL);
+ if (!priv->dma_buffer)
+ return -ENOMEM;
+ return 0;
+}
+
+static void fluke_generic_detach(gpib_board_t *board)
+{
+ if (board->private_data) {
+ struct fluke_priv *e_priv = board->private_data;
+
+ kfree(e_priv->dma_buffer);
+ kfree(board->private_data);
+ board->private_data = NULL;
+ }
+}
+
+// generic part of attach functions shared by all cb7210 boards
+static int fluke_generic_attach(gpib_board_t *board)
+{
+ struct fluke_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+
+ board->status = 0;
+
+ retval = fluke_allocate_private(board);
+ if (retval < 0)
+ return retval;
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+ nec_priv->read_byte = fluke_locking_read_byte;
+ nec_priv->write_byte = fluke_locking_write_byte;
+ nec_priv->offset = fluke_reg_offset;
+ nec_priv->type = CB7210;
+ return 0;
+}
+
+static int fluke_config_dma(gpib_board_t *board, int output)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct dma_slave_config config;
+
+ config.src_maxburst = 1;
+ config.dst_maxburst = 1;
+ config.device_fc = true;
+
+ if (output) {
+ config.direction = DMA_MEM_TO_DEV;
+ config.src_addr = 0;
+ config.dst_addr = e_priv->dma_port_res->start;
+ config.src_addr_width = 1;
+ config.dst_addr_width = 1;
+ } else {
+ config.direction = DMA_DEV_TO_MEM;
+ config.src_addr = e_priv->dma_port_res->start;
+ config.dst_addr = 0;
+ config.src_addr_width = 1;
+ config.dst_addr_width = 1;
+ }
+ return dmaengine_slave_config(e_priv->dma_channel, &config);
+}
+
+static int fluke_init(struct fluke_priv *e_priv, gpib_board_t *board, int handshake_mode)
+{
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+
+ nec7210_board_reset(nec_priv, board);
+ write_byte(nec_priv, AUX_LO_SPEED, AUXMR);
+ /* set clock register for driving frequency
+ * ICR should be set to clock in megahertz (1-15) and to zero
+ * for clocks faster than 15 MHz (max 20MHz)
+ */
+ write_byte(nec_priv, ICR | 10, AUXMR);
+ nec7210_set_handshake_mode(board, nec_priv, handshake_mode);
+
+ nec7210_board_online(nec_priv, board);
+
+ /* poll so we can detect ATN changes */
+ if (gpib_request_pseudo_irq(board, fluke_gpib_interrupt)) {
+ pr_err("fluke_gpib: failed to allocate pseudo_irq\n");
+ return -EINVAL;
+ }
+
+ fluke_paged_write_byte(e_priv, FLUKE_IFCIE_BIT, ISR0_IMR0, ISR0_IMR0_PAGE);
+ return 0;
+}
+
+/* This function is passed to dma_request_channel() in order to
+ * select the pl330 dma channel which has been hardwired to
+ * the gpib controller.
+ */
+static bool gpib_dma_channel_filter(struct dma_chan *chan, void *filter_param)
+{
+ // select the channel which is wired to the gpib chip
+ return chan->chan_id == 0;
+}
+
+static int fluke_attach_impl(gpib_board_t *board, const gpib_board_config_t *config,
+ unsigned int handshake_mode)
+{
+ struct fluke_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = 0;
+ int retval;
+ int irq;
+ struct resource *res;
+ dma_cap_mask_t dma_cap;
+
+ if (!fluke_gpib_pdev) {
+ pr_err("No gpib platform device was found, attach failed.\n");
+ return -ENODEV;
+ }
+
+ retval = fluke_generic_attach(board);
+ if (retval)
+ return retval;
+
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+ nec_priv->offset = fluke_reg_offset;
+ board->dev = &fluke_gpib_pdev->dev;
+
+ res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource for cb7210 gpib\n");
+ return -ENODEV;
+ }
+
+ if (request_mem_region(res->start,
+ resource_size(res),
+ fluke_gpib_pdev->name) == NULL) {
+ dev_err(&fluke_gpib_pdev->dev, "cannot claim registers\n");
+ return -ENXIO;
+ }
+ e_priv->gpib_iomem_res = res;
+
+ nec_priv->iobase = ioremap(e_priv->gpib_iomem_res->start,
+ resource_size(e_priv->gpib_iomem_res));
+ pr_info("gpib: iobase %lx remapped to %p, length=%d\n",
+ (unsigned long)e_priv->gpib_iomem_res->start,
+ nec_priv->iobase, (int)resource_size(e_priv->gpib_iomem_res));
+ if (!nec_priv->iobase) {
+ dev_err(&fluke_gpib_pdev->dev, "Could not map I/O memory\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 1);
+ if (!res) {
+ dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource for gpib dma port\n");
+ return -ENODEV;
+ }
+ if (request_mem_region(res->start,
+ resource_size(res),
+ fluke_gpib_pdev->name) == NULL) {
+ dev_err(&fluke_gpib_pdev->dev, "cannot claim registers\n");
+ return -ENXIO;
+ }
+ e_priv->dma_port_res = res;
+
+ res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 2);
+ if (!res) {
+ dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource for write transfer counter\n");
+ return -ENODEV;
+ }
+
+ if (request_mem_region(res->start,
+ resource_size(res),
+ fluke_gpib_pdev->name) == NULL) {
+ dev_err(&fluke_gpib_pdev->dev, "cannot claim registers\n");
+ return -ENXIO;
+ }
+ e_priv->write_transfer_counter_res = res;
+
+ e_priv->write_transfer_counter = ioremap(e_priv->write_transfer_counter_res->start,
+ resource_size(e_priv->write_transfer_counter_res));
+ pr_info("gpib: write transfer counter %lx remapped to %p, length=%d\n",
+ (unsigned long)e_priv->write_transfer_counter_res->start,
+ e_priv->write_transfer_counter,
+ (int)resource_size(e_priv->write_transfer_counter_res));
+ if (!e_priv->write_transfer_counter) {
+ dev_err(&fluke_gpib_pdev->dev, "Could not map I/O memory\n");
+ return -ENOMEM;
+ }
+
+ irq = platform_get_irq(fluke_gpib_pdev, 0);
+ pr_info("gpib: irq %d\n", irq);
+ if (irq < 0) {
+ dev_err(&fluke_gpib_pdev->dev, "fluke_gpib: request for IRQ failed\n");
+ return -EBUSY;
+ }
+ retval = request_irq(irq, fluke_gpib_interrupt, isr_flags, fluke_gpib_pdev->name, board);
+ if (retval) {
+ dev_err(&fluke_gpib_pdev->dev,
+ "cannot register interrupt handler err=%d\n",
+ retval);
+ return retval;
+ }
+ e_priv->irq = irq;
+
+ dma_cap_zero(dma_cap);
+ dma_cap_set(DMA_SLAVE, dma_cap);
+ e_priv->dma_channel = dma_request_channel(dma_cap, gpib_dma_channel_filter, NULL);
+ if (!e_priv->dma_channel) {
+ pr_err("fluke_gpib: failed to allocate a dma channel.\n");
+ // we don't error out here because unaccel interface will still
+ // work without dma
+ }
+
+ return fluke_init(e_priv, board, handshake_mode);
+}
+
+int fluke_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return fluke_attach_impl(board, config, HR_HLDA);
+}
+
+int fluke_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return fluke_attach_impl(board, config, HR_HLDE);
+}
+
+void fluke_detach(gpib_board_t *board)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (e_priv) {
+ if (e_priv->dma_channel)
+ dma_release_channel(e_priv->dma_channel);
+ gpib_free_pseudo_irq(board);
+ nec_priv = &e_priv->nec7210_priv;
+
+ if (nec_priv->iobase) {
+ fluke_paged_write_byte(e_priv, 0, ISR0_IMR0, ISR0_IMR0_PAGE);
+ nec7210_board_reset(nec_priv, board);
+ }
+ if (e_priv->irq)
+ free_irq(e_priv->irq, board);
+ if (e_priv->write_transfer_counter_res) {
+ release_mem_region(e_priv->write_transfer_counter_res->start,
+ resource_size(e_priv->write_transfer_counter_res));
+ }
+ if (e_priv->dma_port_res) {
+ release_mem_region(e_priv->dma_port_res->start,
+ resource_size(e_priv->dma_port_res));
+ }
+ if (e_priv->gpib_iomem_res)
+ release_mem_region(e_priv->gpib_iomem_res->start,
+ resource_size(e_priv->gpib_iomem_res));
+ }
+ fluke_generic_detach(board);
+}
+
+static int fluke_gpib_probe(struct platform_device *pdev)
+{
+ fluke_gpib_pdev = pdev;
+ return 0;
+}
+
+static const struct of_device_id fluke_gpib_of_match[] = {
+ { .compatible = "flk,fgpib-4.0"},
+ { {0} }
+};
+MODULE_DEVICE_TABLE(of, fluke_gpib_of_match);
+
+static struct platform_driver fluke_gpib_platform_driver = {
+ .driver = {
+ .name = "fluke_gpib",
+ .owner = THIS_MODULE,
+ .of_match_table = fluke_gpib_of_match,
+ },
+ .probe = &fluke_gpib_probe
+};
+
+static int __init fluke_init_module(void)
+{
+ int result;
+
+ result = platform_driver_register(&fluke_gpib_platform_driver);
+ if (result) {
+ pr_err("fluke_gpib: platform_driver_register failed!\n");
+ return result;
+ }
+
+ gpib_register_driver(&fluke_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&fluke_hybrid_interface, THIS_MODULE);
+ gpib_register_driver(&fluke_interface, THIS_MODULE);
+
+ pr_info("fluke_gpib\n");
+ return 0;
+}
+
+static void __exit fluke_exit_module(void)
+{
+ gpib_unregister_driver(&fluke_unaccel_interface);
+ gpib_unregister_driver(&fluke_hybrid_interface);
+ gpib_unregister_driver(&fluke_interface);
+ platform_driver_unregister(&fluke_gpib_platform_driver);
+}
+
+module_init(fluke_init_module);
+module_exit(fluke_exit_module);
diff --git a/drivers/staging/gpib/eastwood/fluke_gpib.h b/drivers/staging/gpib/eastwood/fluke_gpib.h
new file mode 100644
index 000000000000..fcbd42f8f9af
--- /dev/null
+++ b/drivers/staging/gpib/eastwood/fluke_gpib.h
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Author: Frank Mori Hess <fmh6jj@gmail.com>
+ * copyright: (C) 2006, 2010, 2015 Fluke Corporation
+ ***************************************************************************/
+
+#include <linux/compiler.h>
+#include <linux/dmaengine.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include "nec7210.h"
+
+struct fluke_priv {
+ struct nec7210_priv nec7210_priv;
+ struct resource *gpib_iomem_res;
+ struct resource *write_transfer_counter_res;
+ struct resource *dma_port_res;
+ int irq;
+ struct dma_chan *dma_channel;
+ u8 *dma_buffer;
+ int dma_buffer_size;
+ void *write_transfer_counter;
+};
+
+// cb7210 specific registers and bits
+enum cb7210_regs {
+ STATE1_REG = 0x4,
+ ISR0_IMR0 = 0x6,
+ BUS_STATUS = 0x7
+};
+
+enum cb7210_page_in {
+ ISR0_IMR0_PAGE = 1,
+ BUS_STATUS_PAGE = 1,
+ STATE1_PAGE = 1
+};
+
+/* IMR0 -- Interrupt Mode Register 0 */
+enum imr0_bits {
+ FLUKE_IFCIE_BIT = 0x8, /* interface clear interrupt */
+};
+
+/* ISR0 -- Interrupt Status Register 0 */
+enum isr0_bits {
+ FLUKE_IFCI_BIT = 0x8, /* interface clear interrupt */
+};
+
+enum state1_bits {
+ SOURCE_HANDSHAKE_SIDS_BITS = 0x0, /* source idle state */
+ SOURCE_HANDSHAKE_SGNS_BITS = 0x1, /* source generate state */
+ SOURCE_HANDSHAKE_SDYS_BITS = 0x2, /* source delay state */
+ SOURCE_HANDSHAKE_STRS_BITS = 0x5, /* source transfer state */
+ SOURCE_HANDSHAKE_MASK = 0x7
+};
+
+// we customized the cb7210 vhdl to give the "data in" status
+// on the unused bit 7 of the address0 register.
+enum cb7210_address0 {
+ DATA_IN_STATUS = 0x80
+};
+
+static inline int cb7210_page_in_bits(unsigned int page)
+{
+ return 0x50 | (page & 0xf);
+}
+
+// don't use without locking nec_priv->register_page_lock
+static inline uint8_t fluke_read_byte_nolock(struct nec7210_priv *nec_priv,
+ int register_num)
+{
+ u8 retval;
+
+ retval = readl(nec_priv->iobase + register_num * nec_priv->offset);
+ return retval;
+}
+
+// don't use without locking nec_priv->register_page_lock
+static inline void fluke_write_byte_nolock(struct nec7210_priv *nec_priv, uint8_t data,
+ int register_num)
+{
+ writel(data, nec_priv->iobase + register_num * nec_priv->offset);
+}
+
+static inline uint8_t fluke_paged_read_byte(struct fluke_priv *e_priv,
+ unsigned int register_num, unsigned int page)
+{
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ u8 retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nec_priv->register_page_lock, flags);
+ fluke_write_byte_nolock(nec_priv, cb7210_page_in_bits(page), AUXMR);
+ udelay(1);
+ /* chip auto clears the page after a read */
+ retval = fluke_read_byte_nolock(nec_priv, register_num);
+ spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
+ return retval;
+}
+
+static inline void fluke_paged_write_byte(struct fluke_priv *e_priv, uint8_t data,
+ unsigned int register_num, unsigned int page)
+{
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nec_priv->register_page_lock, flags);
+ fluke_write_byte_nolock(nec_priv, cb7210_page_in_bits(page), AUXMR);
+ udelay(1);
+ fluke_write_byte_nolock(nec_priv, data, register_num);
+ spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
+}
+
+enum bus_status_bits {
+ BSR_ATN_BIT = 0x1,
+ BSR_EOI_BIT = 0x2,
+ BSR_SRQ_BIT = 0x4,
+ BSR_IFC_BIT = 0x8,
+ BSR_REN_BIT = 0x10,
+ BSR_DAV_BIT = 0x20,
+ BSR_NRFD_BIT = 0x40,
+ BSR_NDAC_BIT = 0x80,
+};
+
+enum cb7210_aux_cmds {
+/* AUX_RTL2 is an undocumented aux command which causes cb7210 to assert
+ * (and keep asserted) local rtl message. This is used in conjunction
+ * with the (stupid) cb7210 implementation
+ * of the normal nec7210 AUX_RTL aux command, which
+ * causes the rtl message to toggle between on and off.
+ */
+ AUX_RTL2 = 0xd,
+ AUX_NBAF = 0xe, // new byte available false (also clears seoi)
+ AUX_LO_SPEED = 0x40,
+ AUX_HI_SPEED = 0x41,
+};
+
+enum {
+ fluke_reg_offset = 4,
+ fluke_num_regs = 8,
+ write_transfer_counter_mask = 0x7ff,
+};
diff --git a/drivers/staging/gpib/fmh_gpib/Makefile b/drivers/staging/gpib/fmh_gpib/Makefile
new file mode 100644
index 000000000000..cc4d9e7cd5cd
--- /dev/null
+++ b/drivers/staging/gpib/fmh_gpib/Makefile
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_GPIB_FMH) += fmh_gpib.o
diff --git a/drivers/staging/gpib/fmh_gpib/fmh_gpib.c b/drivers/staging/gpib/fmh_gpib/fmh_gpib.c
new file mode 100644
index 000000000000..62791db1c34a
--- /dev/null
+++ b/drivers/staging/gpib/fmh_gpib/fmh_gpib.c
@@ -0,0 +1,1725 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * GPIB Driver for fmh_gpib_core, see
+ * https://github.com/fmhess/fmh_gpib_core
+ *
+ * More specifically, it is a driver for the hardware arrangement described by
+ * src/examples/fmh_gpib_top.vhd in the fmh_gpib_core repository.
+ *
+ * Author: Frank Mori Hess <fmh6jj@gmail.com>
+ * Copyright: (C) 2006, 2010, 2015 Fluke Corporation
+ * (C) 2017 Frank Mori Hess
+ ***************************************************************************/
+
+#include "fmh_gpib.h"
+
+#include "gpibP.h"
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+MODULE_LICENSE("GPL");
+
+static irqreturn_t fmh_gpib_interrupt(int irq, void *arg);
+static int fmh_gpib_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config);
+static int fmh_gpib_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config);
+static void fmh_gpib_detach(gpib_board_t *board);
+static int fmh_gpib_pci_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config);
+static int fmh_gpib_pci_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config);
+static void fmh_gpib_pci_detach(gpib_board_t *board);
+static int fmh_gpib_config_dma(gpib_board_t *board, int output);
+static irqreturn_t fmh_gpib_internal_interrupt(gpib_board_t *board);
+static struct platform_driver fmh_gpib_platform_driver;
+static struct pci_driver fmh_gpib_pci_driver;
+
+// wrappers for interface functions
+static int fmh_gpib_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+}
+
+static int fmh_gpib_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+static int fmh_gpib_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+static int fmh_gpib_take_control(gpib_board_t *board, int synchronous)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+static int fmh_gpib_go_to_standby(gpib_board_t *board)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+static void fmh_gpib_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct fmh_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ nec7210_request_system_control(board, nec_priv, request_control);
+}
+
+static void fmh_gpib_interface_clear(gpib_board_t *board, int assert)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+static void fmh_gpib_remote_enable(gpib_board_t *board, int enable)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+static int fmh_gpib_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+static void fmh_gpib_disable_eos(gpib_board_t *board)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+static unsigned int fmh_gpib_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
+}
+
+static int fmh_gpib_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+static int fmh_gpib_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+static int fmh_gpib_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
+}
+
+static void fmh_gpib_parallel_poll_configure(gpib_board_t *board, uint8_t configuration)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration);
+}
+
+static void fmh_gpib_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+static void fmh_gpib_local_parallel_poll_mode(gpib_board_t *board, int local)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ if (local) {
+ write_byte(&priv->nec7210_priv, AUX_I_REG | LOCAL_PPOLL_MODE_BIT, AUXMR);
+ } else {
+ /* For fmh_gpib_core, remote parallel poll config mode is unaffected by the
+ * state of the disable bit of the parallel poll register (unlike the tnt4882).
+ * So, we don't need to worry about that.
+ */
+ write_byte(&priv->nec7210_priv, AUX_I_REG | 0x0, AUXMR);
+ }
+}
+
+static void fmh_gpib_serial_poll_response2(gpib_board_t *board, uint8_t status,
+ int new_reason_for_service)
+{
+ struct fmh_priv *priv = board->private_data;
+ unsigned long flags;
+ const int MSS = status & request_service_bit;
+ const int reqt = MSS && new_reason_for_service;
+ const int reqf = MSS == 0;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (reqt) {
+ priv->nec7210_priv.srq_pending = 1;
+ clear_bit(SPOLL_NUM, &board->status);
+ } else if (reqf) {
+ priv->nec7210_priv.srq_pending = 0;
+ }
+
+ if (reqt) {
+ /* It may seem like a race to issue reqt before updating
+ * the status byte, but it is not. The chip does not
+ * issue the reqt until the SPMR is written to at
+ * a later time.
+ */
+ write_byte(&priv->nec7210_priv, AUX_REQT, AUXMR);
+ } else if (reqf) {
+ write_byte(&priv->nec7210_priv, AUX_REQF, AUXMR);
+ }
+ /* We need to always zero bit 6 of the status byte before writing it to
+ * the SPMR to insure we are using
+ * serial poll mode SP1, and not accidentally triggering mode SP3.
+ */
+ write_byte(&priv->nec7210_priv, status & ~request_service_bit, SPMR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+static uint8_t fmh_gpib_serial_poll_status(gpib_board_t *board)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+static void fmh_gpib_return_to_local(gpib_board_t *board)
+{
+ struct fmh_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ write_byte(nec_priv, AUX_RTL2, AUXMR);
+ udelay(1);
+ write_byte(nec_priv, AUX_RTL, AUXMR);
+}
+
+static int fmh_gpib_line_status(const gpib_board_t *board)
+{
+ int status = ValidALL;
+ int bsr_bits;
+ struct fmh_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+
+ bsr_bits = read_byte(nec_priv, BUS_STATUS_REG);
+
+ if ((bsr_bits & BSR_REN_BIT) == 0)
+ status |= BusREN;
+ if ((bsr_bits & BSR_IFC_BIT) == 0)
+ status |= BusIFC;
+ if ((bsr_bits & BSR_SRQ_BIT) == 0)
+ status |= BusSRQ;
+ if ((bsr_bits & BSR_EOI_BIT) == 0)
+ status |= BusEOI;
+ if ((bsr_bits & BSR_NRFD_BIT) == 0)
+ status |= BusNRFD;
+ if ((bsr_bits & BSR_NDAC_BIT) == 0)
+ status |= BusNDAC;
+ if ((bsr_bits & BSR_DAV_BIT) == 0)
+ status |= BusDAV;
+ if ((bsr_bits & BSR_ATN_BIT) == 0)
+ status |= BusATN;
+
+ return status;
+}
+
+static unsigned int fmh_gpib_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned int retval;
+
+ retval = nec7210_t1_delay(board, nec_priv, nano_sec);
+
+ if (nano_sec <= 350) {
+ write_byte(nec_priv, AUX_HI_SPEED, AUXMR);
+ retval = 350;
+ } else {
+ write_byte(nec_priv, AUX_LO_SPEED, AUXMR);
+ }
+ return retval;
+}
+
+static int lacs_or_read_ready(gpib_board_t *board)
+{
+ const struct fmh_priv *e_priv = board->private_data;
+ const struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = test_bit(LACS_NUM, &board->status) ||
+ test_bit(READ_READY_BN, &nec_priv->state);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return retval;
+}
+
+static int wait_for_read(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+
+ if (wait_event_interruptible(board->wait,
+ lacs_or_read_ready(board) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status)))
+ retval = -ERESTARTSYS;
+
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ return retval;
+}
+
+static int wait_for_rx_fifo_half_full_or_end(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+
+ if (wait_event_interruptible(board->wait,
+ (fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) &
+ RX_FIFO_HALF_FULL) ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status)))
+ retval = -ERESTARTSYS;
+
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ return retval;
+}
+
+/* Wait until the gpib chip is ready to accept a data out byte.
+ */
+static int wait_for_data_out_ready(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+// printk("%s: enter\n", __FUNCTION__);
+
+ if (wait_event_interruptible(board->wait,
+ (test_bit(TACS_NUM, &board->status) &&
+ (read_byte(nec_priv, EXT_STATUS_1_REG) &
+ DATA_OUT_STATUS_BIT)) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status)))
+ retval = -ERESTARTSYS;
+
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+// printk("%s: exit, retval=%i\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static void fmh_gpib_dma_callback(void *arg)
+{
+ gpib_board_t *board = arg;
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+// printk("%s: enter\n", __FUNCTION__);
+
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, HR_DOIE | HR_DIIE);
+ wake_up_interruptible(&board->wait);
+
+ fmh_gpib_internal_interrupt(board);
+
+ clear_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state);
+ clear_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state);
+
+ // printk("%s: exit\n", __FUNCTION__);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+/* returns true when all the bytes of a write have been transferred to
+ * the chip and successfully transferred out over the gpib bus.
+ */
+static int fmh_gpib_all_bytes_are_sent(struct fmh_priv *e_priv)
+{
+ if (fifos_read(e_priv, FIFO_XFER_COUNTER_REG) & fifo_xfer_counter_mask)
+ return 0;
+
+ if ((read_byte(&e_priv->nec7210_priv, EXT_STATUS_1_REG) & DATA_OUT_STATUS_BIT) == 0)
+ return 0;
+
+ return 1;
+}
+
+static int fmh_gpib_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+ int retval = 0;
+ dma_addr_t address;
+ struct dma_async_tx_descriptor *tx_desc;
+
+ *bytes_written = 0;
+// printk("%s: enter\n", __FUNCTION__);
+ if (WARN_ON_ONCE(length > e_priv->dma_buffer_size))
+ return -EFAULT;
+ dmaengine_terminate_all(e_priv->dma_channel);
+ memcpy(e_priv->dma_buffer, buffer, length);
+ address = dma_map_single(board->dev, e_priv->dma_buffer, length, DMA_TO_DEVICE);
+ if (dma_mapping_error(board->dev, address))
+ pr_err("dma mapping error in dma write!\n");
+ /* program dma controller */
+ retval = fmh_gpib_config_dma(board, 1);
+ if (retval)
+ goto cleanup;
+
+ tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, address, length, DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!tx_desc) {
+ pr_err("fmh_gpib_gpib: failed to allocate dma transmit descriptor\n");
+ retval = -ENOMEM;
+ goto cleanup;
+ }
+ tx_desc->callback = fmh_gpib_dma_callback;
+ tx_desc->callback_param = board;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG);
+ fifos_write(e_priv, TX_FIFO_DMA_REQUEST_ENABLE | TX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG);
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO);
+
+ dmaengine_submit(tx_desc);
+ dma_async_issue_pending(e_priv->dma_channel);
+ clear_bit(WRITE_READY_BN, &nec_priv->state);
+ set_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state);
+// printk("%s: in spin lock\n", __FUNCTION__);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+// printk("%s: waiting for write.\n", __FUNCTION__);
+ // suspend until message is sent
+ if (wait_event_interruptible(board->wait,
+ fmh_gpib_all_bytes_are_sent(e_priv) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted!\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state))
+ retval = -EIO;
+ // disable board's dma
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0);
+ fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG);
+
+ dmaengine_terminate_all(e_priv->dma_channel);
+ // make sure fmh_gpib_dma_callback got called
+ if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state))
+ fmh_gpib_dma_callback(board);
+
+ *bytes_written = length - (fifos_read(e_priv, FIFO_XFER_COUNTER_REG) &
+ fifo_xfer_counter_mask);
+ if (WARN_ON_ONCE(*bytes_written > length))
+ return -EFAULT;
+ /* printk("length=%i, *bytes_written=%i, residue=%i, retval=%i\n",
+ * length, *bytes_written, get_dma_residue(e_priv->dma_channel), retval);
+ */
+cleanup:
+ dma_unmap_single(board->dev, address, length, DMA_TO_DEVICE);
+// printk("%s: exit, retval=%d\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static int fmh_gpib_accel_write(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int send_eoi, size_t *bytes_written)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ size_t remainder = length;
+ size_t transfer_size;
+ ssize_t retval = 0;
+ size_t dma_remainder = remainder;
+
+ if (!e_priv->dma_channel) {
+ pr_err("fmh_gpib_gpib: No dma channel available, cannot do accel write.");
+ return -ENXIO;
+ }
+
+ *bytes_written = 0;
+ if (length < 1)
+ return 0;
+
+ smp_mb__before_atomic();
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME
+ smp_mb__after_atomic();
+
+ if (send_eoi)
+ --dma_remainder;
+// printk("%s: entering while loop\n", __FUNCTION__);
+
+ while (dma_remainder > 0) {
+ size_t num_bytes;
+
+ retval = wait_for_data_out_ready(board);
+ if (retval < 0)
+ break;
+
+ transfer_size = (e_priv->dma_buffer_size < dma_remainder) ?
+ e_priv->dma_buffer_size : dma_remainder;
+ retval = fmh_gpib_dma_write(board, buffer, transfer_size, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ break;
+ dma_remainder -= num_bytes;
+ remainder -= num_bytes;
+ buffer += num_bytes;
+ if (need_resched())
+ schedule();
+ }
+ if (retval < 0)
+ return retval;
+ //handle sending of last byte with eoi
+ if (send_eoi) {
+ size_t num_bytes;
+ // printk("%s: handling last byte\n", __FUNCTION__);
+ if (WARN_ON_ONCE(remainder != 1))
+ return -EFAULT;
+
+ /* wait until we are sure we will be able to write the data byte
+ * into the chip before we send AUX_SEOI. This prevents a timeout
+ * scenario where we send AUX_SEOI but then timeout without getting
+ * any bytes into the gpib chip. This will result in the first byte
+ * of the next write having a spurious EOI set on the first byte.
+ */
+ retval = wait_for_data_out_ready(board);
+ if (retval < 0)
+ return retval;
+
+ write_byte(nec_priv, AUX_SEOI, AUXMR);
+ retval = fmh_gpib_dma_write(board, buffer, remainder, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ remainder -= num_bytes;
+ }
+// printk("%s: bytes send=%i\n", __FUNCTION__, (int)(length - remainder));
+ return 0;
+}
+
+static int fmh_gpib_get_dma_residue(struct dma_chan *chan, dma_cookie_t cookie)
+{
+ struct dma_tx_state state;
+ int result;
+
+ result = dmaengine_pause(chan);
+ if (result < 0) {
+ pr_err("fmh_gpib_gpib: dma pause failed?\n");
+ return result;
+ }
+ dmaengine_tx_status(chan, cookie, &state);
+ // dma330 hardware doesn't support resume, so dont call this
+ // method unless the dma transfer is done.
+ return state.residue;
+}
+
+static int wait_for_tx_fifo_half_empty(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+// printk("%s: enter\n", __FUNCTION__);
+
+ if (wait_event_interruptible(board->wait,
+ (test_bit(TACS_NUM, &board->status) &&
+ (fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) &
+ TX_FIFO_HALF_EMPTY)) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status)))
+ retval = -ERESTARTSYS;
+
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+// printk("%s: exit, retval=%i\n", __FUNCTION__, retval);
+ return retval;
+}
+
+/* supports writing a chunk of data whose length must fit into the hardware'd xfer counter,
+ * called in a loop by fmh_gpib_fifo_write()
+ */
+static int fmh_gpib_fifo_write_countable(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int send_eoi, size_t *bytes_written)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+ unsigned int remainder;
+
+ *bytes_written = 0;
+// printk("%s: enter\n", __FUNCTION__);
+ if (WARN_ON_ONCE(length > fifo_xfer_counter_mask))
+ return -EFAULT;
+
+ fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG);
+ fifos_write(e_priv, TX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG);
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO);
+
+ remainder = length;
+ while (remainder > 0) {
+ int i;
+
+ fifos_write(e_priv, TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE, FIFO_CONTROL_STATUS_REG);
+ retval = wait_for_tx_fifo_half_empty(board);
+ if (retval < 0)
+ goto cleanup;
+
+ for (i = 0; i < fmh_gpib_half_fifo_size(e_priv) && remainder > 0; ++i) {
+ unsigned int data_value = *buffer;
+
+ if (send_eoi && remainder == 1)
+ data_value |= FIFO_DATA_EOI_FLAG;
+ fifos_write(e_priv, data_value, FIFO_DATA_REG);
+ ++buffer;
+ --remainder;
+ }
+ }
+
+ // suspend until last byte is sent
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, HR_DOIE);
+ if (wait_event_interruptible(board->wait,
+ fmh_gpib_all_bytes_are_sent(e_priv) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted!\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state))
+ retval = -EIO;
+
+cleanup:
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0);
+ fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG);
+
+ *bytes_written = length - (fifos_read(e_priv, FIFO_XFER_COUNTER_REG) &
+ fifo_xfer_counter_mask);
+ if (WARN_ON_ONCE(*bytes_written > length))
+ return -EFAULT;
+ /* printk("length=%i, *bytes_written=%i, residue=%i, retval=%i\n",
+ * length, *bytes_written, get_dma_residue(e_priv->dma_channel), retval);
+ */
+
+// printk("%s: exit, retval=%d\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static int fmh_gpib_fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ size_t remainder = length;
+ size_t transfer_size;
+ ssize_t retval = 0;
+
+ *bytes_written = 0;
+ if (length < 1)
+ return 0;
+
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME
+
+// printk("%s: entering while loop\n", __FUNCTION__);
+
+ while (remainder > 0) {
+ size_t num_bytes;
+ int last_pass;
+
+ retval = wait_for_data_out_ready(board);
+ if (retval < 0)
+ break;
+
+ if (fifo_xfer_counter_mask < remainder) {
+ // round transfer size to a multiple of half fifo size
+ transfer_size = (fifo_xfer_counter_mask /
+ fmh_gpib_half_fifo_size(e_priv)) *
+ fmh_gpib_half_fifo_size(e_priv);
+ last_pass = 0;
+ } else {
+ transfer_size = remainder;
+ last_pass = 1;
+ }
+ retval = fmh_gpib_fifo_write_countable(board, buffer, transfer_size,
+ last_pass && send_eoi, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ break;
+ remainder -= num_bytes;
+ buffer += num_bytes;
+ if (need_resched())
+ schedule();
+ }
+// printk("%s: bytes send=%i\n", __FUNCTION__, (int)(length - remainder));
+ return retval;
+}
+
+static int fmh_gpib_dma_read(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+ unsigned long flags;
+ int residue;
+ int wait_retval;
+ dma_addr_t bus_address;
+ struct dma_async_tx_descriptor *tx_desc;
+ dma_cookie_t dma_cookie;
+
+ // printk("%s: enter, bus_address=0x%x, length=%i\n", __FUNCTION__,
+ //(unsigned)bus_address,
+// (int)length);
+
+ *bytes_read = 0;
+ *end = 0;
+ if (length == 0)
+ return 0;
+
+ bus_address = dma_map_single(board->dev, e_priv->dma_buffer,
+ length, DMA_FROM_DEVICE);
+ if (dma_mapping_error(board->dev, bus_address))
+ pr_err("dma mapping error in dma read!");
+
+ /* program dma controller */
+ retval = fmh_gpib_config_dma(board, 0);
+ if (retval) {
+ dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE);
+ return retval;
+ }
+ tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, bus_address,
+ length, DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!tx_desc) {
+ pr_err("fmh_gpib_gpib: failed to allocate dma transmit descriptor\n");
+ dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE);
+ return -EIO;
+ }
+ tx_desc->callback = fmh_gpib_dma_callback;
+ tx_desc->callback_param = board;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ // enable nec7210 dma
+ fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG);
+ fifos_write(e_priv, RX_FIFO_DMA_REQUEST_ENABLE | RX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG);
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI);
+
+ dma_cookie = dmaengine_submit(tx_desc);
+ dma_async_issue_pending(e_priv->dma_channel);
+
+ set_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state);
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+// printk("waiting for data transfer.\n");
+ // wait for data to transfer
+ wait_retval = wait_event_interruptible(board->wait,
+ test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state)
+ == 0 ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status));
+ if (wait_retval) {
+ pr_warn("fmh_gpib: dma read wait interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ // stop the dma transfer
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+ fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG);
+ // give time for pl330 to transfer any in-flight data, since
+ // pl330 will throw it away when dmaengine_pause is called.
+ usleep_range(10, 15);
+ residue = fmh_gpib_get_dma_residue(e_priv->dma_channel, dma_cookie);
+ if (WARN_ON_ONCE(residue > length || residue < 0))
+ return -EFAULT;
+ *bytes_read += length - residue;
+ dmaengine_terminate_all(e_priv->dma_channel);
+ // make sure fmh_gpib_dma_callback got called
+ if (test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state))
+ fmh_gpib_dma_callback(board);
+
+ dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE);
+ memcpy(buffer, e_priv->dma_buffer, *bytes_read);
+
+ /* Manually read any dregs out of fifo. */
+ while ((fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) & RX_FIFO_EMPTY) == 0) {
+ if ((*bytes_read) >= length) {
+ dev_err(board->dev, "unexpected extra bytes in rx fifo, discarding! bytes_read=%d length=%d residue=%d\n",
+ (int)(*bytes_read), (int)length, (int)residue);
+ break;
+ }
+ buffer[(*bytes_read)++] = fifos_read(e_priv, FIFO_DATA_REG) & fifo_data_mask;
+ }
+
+ /* If we got an end interrupt, figure out if it was
+ * associated with the last byte we dma'd or with a
+ * byte still sitting on the cb7210.
+ */
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (*bytes_read > 0 && test_bit(READ_READY_BN, &nec_priv->state) == 0) {
+ // If there is no byte sitting on the cb7210 and we
+ // saw an end, we need to deal with it now
+ if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state))
+ *end = 1;
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+// printk("\tbytes_read=%i, residue=%i, end=%i, retval=%i, wait_retval=%i\n",
+// *bytes_read, residue, *end, retval, wait_retval);
+
+ return retval;
+}
+
+static void fmh_gpib_release_rfd_holdoff(gpib_board_t *board, struct fmh_priv *e_priv)
+{
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned int ext_status_1;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ ext_status_1 = read_byte(nec_priv, EXT_STATUS_1_REG);
+
+ /* if there is an end byte sitting on the chip, don't release
+ * holdoff. We want it left set after we read out the end
+ * byte.
+ */
+ if ((ext_status_1 & (DATA_IN_STATUS_BIT | END_STATUS_BIT)) !=
+ (DATA_IN_STATUS_BIT | END_STATUS_BIT)) {
+ if (ext_status_1 & RFD_HOLDOFF_STATUS_BIT)
+ write_byte(nec_priv, AUX_FH, AUXMR);
+
+ /* Check if an end byte raced in before we executed the AUX_FH command.
+ * If it did, we want to make sure the rfd holdoff is in effect. The end
+ * byte can arrive since
+ * AUX_RFD_HOLDOFF_ASAP doesn't immediately force the acceptor handshake
+ * to leave ACRS.
+ */
+ if ((read_byte(nec_priv, EXT_STATUS_1_REG) &
+ (RFD_HOLDOFF_STATUS_BIT | DATA_IN_STATUS_BIT | END_STATUS_BIT)) ==
+ (DATA_IN_STATUS_BIT | END_STATUS_BIT)) {
+ write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR);
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ } else {
+ clear_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ }
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+static int fmh_gpib_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ size_t remain = length;
+ size_t transfer_size;
+ int retval = 0;
+ size_t dma_nbytes;
+ unsigned long flags;
+
+ smp_mb__before_atomic();
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME
+ smp_mb__after_atomic();
+ *end = 0;
+ *bytes_read = 0;
+
+ retval = wait_for_read(board);
+ if (retval < 0)
+ return retval;
+
+ fmh_gpib_release_rfd_holdoff(board, e_priv);
+ while (remain > 0) {
+ transfer_size = (e_priv->dma_buffer_size < remain) ?
+ e_priv->dma_buffer_size : remain;
+ retval = fmh_gpib_dma_read(board, buffer, transfer_size, end, &dma_nbytes);
+ remain -= dma_nbytes;
+ buffer += dma_nbytes;
+ *bytes_read += dma_nbytes;
+ if (*end)
+ break;
+ if (retval < 0)
+ break;
+ if (need_resched())
+ schedule();
+ }
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (test_bit(RFD_HOLDOFF_BN, &nec_priv->state) == 0) {
+ write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR);
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return retval;
+}
+
+/* Read a chunk of data whose length is within the limits of the hardware's
+ * xfer counter. Called in a loop from fmh_gpib_fifo_read().
+ */
+static int fmh_gpib_fifo_read_countable(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+
+ // printk("%s: enter, bus_address=0x%x, length=%i\n", __FUNCTION__,
+ // (unsigned)bus_address,
+// (int)length);
+
+ *bytes_read = 0;
+ *end = 0;
+ if (length == 0)
+ return 0;
+
+ fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG);
+ fifos_write(e_priv, RX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG);
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI);
+
+ while (*bytes_read < length && *end == 0) {
+ int i;
+
+ fifos_write(e_priv, RX_FIFO_HALF_FULL_INTERRUPT_ENABLE, FIFO_CONTROL_STATUS_REG);
+ retval = wait_for_rx_fifo_half_full_or_end(board);
+ if (retval < 0)
+ goto cleanup;
+
+ for (i = 0; i < fmh_gpib_half_fifo_size(e_priv) && *end == 0; ++i) {
+ unsigned int data_value;
+
+ data_value = fifos_read(e_priv, FIFO_DATA_REG);
+ buffer[(*bytes_read)++] = data_value & fifo_data_mask;
+ if (data_value & FIFO_DATA_EOI_FLAG)
+ *end = 1;
+ }
+ }
+
+cleanup:
+ // stop the transfer
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+ fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG);
+
+ /* Manually read any dregs out of fifo. */
+ while ((fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) & RX_FIFO_EMPTY) == 0) {
+ unsigned int data_value;
+
+ if ((*bytes_read) >= length) {
+ dev_err(board->dev, "unexpected extra bytes in rx fifo, discarding! bytes_read=%d length=%d\n",
+ (int)(*bytes_read), (int)length);
+ break;
+ }
+ data_value = fifos_read(e_priv, FIFO_DATA_REG);
+ buffer[(*bytes_read)++] = data_value & fifo_data_mask;
+ if (data_value & FIFO_DATA_EOI_FLAG)
+ *end = 1;
+ }
+
+// printk("\tbytes_read=%i, end=%i, retval=%i, wait_retval=%i\n",
+// *bytes_read, *end, retval, wait_retval);
+
+ return retval;
+}
+
+static int fmh_gpib_fifo_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ size_t remain = length;
+ size_t transfer_size;
+ int retval = 0;
+ size_t nbytes;
+ unsigned long flags;
+
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME
+ *end = 0;
+ *bytes_read = 0;
+
+ /* Do a little prep with data in interrupt so that following wait_for_read()
+ * will wake up if a data byte is received.
+ */
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, HR_DIIE);
+ fmh_gpib_interrupt(0, board);
+
+ retval = wait_for_read(board);
+ if (retval < 0)
+ return retval;
+
+ fmh_gpib_release_rfd_holdoff(board, e_priv);
+ while (remain > 0) {
+ if (fifo_xfer_counter_mask < remain) {
+ // round transfer size to a multiple of half fifo size
+ transfer_size = (fifo_xfer_counter_mask /
+ fmh_gpib_half_fifo_size(e_priv)) *
+ fmh_gpib_half_fifo_size(e_priv);
+ } else {
+ transfer_size = remain;
+ }
+ retval = fmh_gpib_fifo_read_countable(board, buffer, transfer_size, end, &nbytes);
+ remain -= nbytes;
+ buffer += nbytes;
+ *bytes_read += nbytes;
+ if (*end)
+ break;
+ if (retval < 0)
+ break;
+ if (need_resched())
+ schedule();
+ }
+
+ if (*end == 0) {
+ spin_lock_irqsave(&board->spinlock, flags);
+ write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR);
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ }
+
+ return retval;
+}
+
+gpib_interface_t fmh_gpib_unaccel_interface = {
+name: "fmh_gpib_unaccel",
+attach : fmh_gpib_attach_holdoff_all,
+detach : fmh_gpib_detach,
+read : fmh_gpib_read,
+write : fmh_gpib_write,
+command : fmh_gpib_command,
+take_control : fmh_gpib_take_control,
+go_to_standby : fmh_gpib_go_to_standby,
+request_system_control : fmh_gpib_request_system_control,
+interface_clear : fmh_gpib_interface_clear,
+remote_enable : fmh_gpib_remote_enable,
+enable_eos : fmh_gpib_enable_eos,
+disable_eos : fmh_gpib_disable_eos,
+parallel_poll : fmh_gpib_parallel_poll,
+parallel_poll_configure : fmh_gpib_parallel_poll_configure,
+parallel_poll_response : fmh_gpib_parallel_poll_response,
+local_parallel_poll_mode : fmh_gpib_local_parallel_poll_mode,
+line_status : fmh_gpib_line_status,
+update_status : fmh_gpib_update_status,
+primary_address : fmh_gpib_primary_address,
+secondary_address : fmh_gpib_secondary_address,
+serial_poll_response2 : fmh_gpib_serial_poll_response2,
+serial_poll_status : fmh_gpib_serial_poll_status,
+t1_delay : fmh_gpib_t1_delay,
+return_to_local : fmh_gpib_return_to_local,
+};
+
+gpib_interface_t fmh_gpib_interface = {
+name: "fmh_gpib",
+attach : fmh_gpib_attach_holdoff_end,
+detach : fmh_gpib_detach,
+read : fmh_gpib_accel_read,
+write : fmh_gpib_accel_write,
+command : fmh_gpib_command,
+take_control : fmh_gpib_take_control,
+go_to_standby : fmh_gpib_go_to_standby,
+request_system_control : fmh_gpib_request_system_control,
+interface_clear : fmh_gpib_interface_clear,
+remote_enable : fmh_gpib_remote_enable,
+enable_eos : fmh_gpib_enable_eos,
+disable_eos : fmh_gpib_disable_eos,
+parallel_poll : fmh_gpib_parallel_poll,
+parallel_poll_configure : fmh_gpib_parallel_poll_configure,
+parallel_poll_response : fmh_gpib_parallel_poll_response,
+local_parallel_poll_mode : fmh_gpib_local_parallel_poll_mode,
+line_status : fmh_gpib_line_status,
+update_status : fmh_gpib_update_status,
+primary_address : fmh_gpib_primary_address,
+secondary_address : fmh_gpib_secondary_address,
+serial_poll_response2 : fmh_gpib_serial_poll_response2,
+serial_poll_status : fmh_gpib_serial_poll_status,
+t1_delay : fmh_gpib_t1_delay,
+return_to_local : fmh_gpib_return_to_local,
+};
+
+gpib_interface_t fmh_gpib_pci_interface = {
+name: "fmh_gpib_pci",
+attach : fmh_gpib_pci_attach_holdoff_end,
+detach : fmh_gpib_pci_detach,
+read : fmh_gpib_fifo_read,
+write : fmh_gpib_fifo_write,
+command : fmh_gpib_command,
+take_control : fmh_gpib_take_control,
+go_to_standby : fmh_gpib_go_to_standby,
+request_system_control : fmh_gpib_request_system_control,
+interface_clear : fmh_gpib_interface_clear,
+remote_enable : fmh_gpib_remote_enable,
+enable_eos : fmh_gpib_enable_eos,
+disable_eos : fmh_gpib_disable_eos,
+parallel_poll : fmh_gpib_parallel_poll,
+parallel_poll_configure : fmh_gpib_parallel_poll_configure,
+parallel_poll_response : fmh_gpib_parallel_poll_response,
+local_parallel_poll_mode : fmh_gpib_local_parallel_poll_mode,
+line_status : fmh_gpib_line_status,
+update_status : fmh_gpib_update_status,
+primary_address : fmh_gpib_primary_address,
+secondary_address : fmh_gpib_secondary_address,
+serial_poll_response2 : fmh_gpib_serial_poll_response2,
+serial_poll_status : fmh_gpib_serial_poll_status,
+t1_delay : fmh_gpib_t1_delay,
+return_to_local : fmh_gpib_return_to_local,
+};
+
+gpib_interface_t fmh_gpib_pci_unaccel_interface = {
+name: "fmh_gpib_pci_unaccel",
+attach : fmh_gpib_pci_attach_holdoff_all,
+detach : fmh_gpib_pci_detach,
+read : fmh_gpib_read,
+write : fmh_gpib_write,
+command : fmh_gpib_command,
+take_control : fmh_gpib_take_control,
+go_to_standby : fmh_gpib_go_to_standby,
+request_system_control : fmh_gpib_request_system_control,
+interface_clear : fmh_gpib_interface_clear,
+remote_enable : fmh_gpib_remote_enable,
+enable_eos : fmh_gpib_enable_eos,
+disable_eos : fmh_gpib_disable_eos,
+parallel_poll : fmh_gpib_parallel_poll,
+parallel_poll_configure : fmh_gpib_parallel_poll_configure,
+parallel_poll_response : fmh_gpib_parallel_poll_response,
+local_parallel_poll_mode : fmh_gpib_local_parallel_poll_mode,
+line_status : fmh_gpib_line_status,
+update_status : fmh_gpib_update_status,
+primary_address : fmh_gpib_primary_address,
+secondary_address : fmh_gpib_secondary_address,
+serial_poll_response2 : fmh_gpib_serial_poll_response2,
+serial_poll_status : fmh_gpib_serial_poll_status,
+t1_delay : fmh_gpib_t1_delay,
+return_to_local : fmh_gpib_return_to_local,
+};
+
+irqreturn_t fmh_gpib_internal_interrupt(gpib_board_t *board)
+{
+ unsigned int status0, status1, status2, ext_status_1, fifo_status;
+ struct fmh_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+ int retval = IRQ_NONE;
+
+ status0 = read_byte(nec_priv, ISR0_IMR0_REG);
+ status1 = read_byte(nec_priv, ISR1);
+ status2 = read_byte(nec_priv, ISR2);
+ fifo_status = fifos_read(priv, FIFO_CONTROL_STATUS_REG);
+
+ if (status0 & IFC_INTERRUPT_BIT) {
+ push_gpib_event(board, EventIFC);
+ retval = IRQ_HANDLED;
+ }
+
+ if (nec7210_interrupt_have_status(board, nec_priv, status1, status2) == IRQ_HANDLED)
+ retval = IRQ_HANDLED;
+
+ ext_status_1 = read_byte(nec_priv, EXT_STATUS_1_REG);
+
+ if (ext_status_1 & DATA_IN_STATUS_BIT)
+ set_bit(READ_READY_BN, &nec_priv->state);
+ else
+ clear_bit(READ_READY_BN, &nec_priv->state);
+
+ if (ext_status_1 & DATA_OUT_STATUS_BIT)
+ set_bit(WRITE_READY_BN, &nec_priv->state);
+ else
+ clear_bit(WRITE_READY_BN, &nec_priv->state);
+
+ if (ext_status_1 & COMMAND_OUT_STATUS_BIT)
+ set_bit(COMMAND_READY_BN, &nec_priv->state);
+ else
+ clear_bit(COMMAND_READY_BN, &nec_priv->state);
+
+ if (ext_status_1 & RFD_HOLDOFF_STATUS_BIT)
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ else
+ clear_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+
+ if (ext_status_1 & END_STATUS_BIT) {
+ /* only set RECEIVED_END while there is still a data
+ * byte sitting in the chip, to avoid spuriously
+ * setting it multiple times after it has been cleared
+ * during a read.
+ */
+ if (ext_status_1 & DATA_IN_STATUS_BIT)
+ set_bit(RECEIVED_END_BN, &nec_priv->state);
+ } else {
+ clear_bit(RECEIVED_END_BN, &nec_priv->state);
+ }
+
+ if ((fifo_status & TX_FIFO_HALF_EMPTY_INTERRUPT_IS_ENABLED) &&
+ (fifo_status & TX_FIFO_HALF_EMPTY)) {
+ /* We really only want to clear the
+ * TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE bit in the
+ * FIFO_CONTROL_STATUS_REG. Since we are not being
+ * careful, this also has a side effect of disabling
+ * DMA requests and the RX fifo interrupt. That is
+ * fine though, since they should never be in use at
+ * the same time as the TX fifo interrupt.
+ */
+ fifos_write(priv, 0x0, FIFO_CONTROL_STATUS_REG);
+ retval = IRQ_HANDLED;
+ }
+
+ if ((fifo_status & RX_FIFO_HALF_FULL_INTERRUPT_IS_ENABLED) &&
+ (fifo_status & RX_FIFO_HALF_FULL)) {
+ /* We really only want to clear the
+ * RX_FIFO_HALF_FULL_INTERRUPT_ENABLE bit in the
+ * FIFO_CONTROL_STATUS_REG. Since we are not being
+ * careful, this also has a side effect of disabling
+ * DMA requests and the TX fifo interrupt. That is
+ * fine though, since they should never be in use at
+ * the same time as the RX fifo interrupt.
+ */
+ fifos_write(priv, 0x0, FIFO_CONTROL_STATUS_REG);
+ retval = IRQ_HANDLED;
+ }
+
+ if (retval == IRQ_HANDLED)
+ wake_up_interruptible(&board->wait);
+
+ return retval;
+}
+
+irqreturn_t fmh_gpib_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = fmh_gpib_internal_interrupt(board);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+static int fmh_gpib_allocate_private(gpib_board_t *board)
+{
+ struct fmh_priv *priv;
+
+ board->private_data = kmalloc(sizeof(struct fmh_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+ priv = board->private_data;
+ memset(priv, 0, sizeof(struct fmh_priv));
+ init_nec7210_private(&priv->nec7210_priv);
+ priv->dma_buffer_size = 0x800;
+ priv->dma_buffer = kmalloc(priv->dma_buffer_size, GFP_KERNEL);
+ if (!priv->dma_buffer)
+ return -ENOMEM;
+ return 0;
+}
+
+static void fmh_gpib_generic_detach(gpib_board_t *board)
+{
+ if (board->private_data) {
+ struct fmh_priv *e_priv = board->private_data;
+
+ kfree(e_priv->dma_buffer);
+ kfree(board->private_data);
+ board->private_data = NULL;
+ }
+ if (board->dev)
+ dev_set_drvdata(board->dev, NULL);
+}
+
+// generic part of attach functions
+static int fmh_gpib_generic_attach(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+
+ board->status = 0;
+
+ retval = fmh_gpib_allocate_private(board);
+ if (retval < 0)
+ return retval;
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+ nec_priv->read_byte = gpib_cs_read_byte;
+ nec_priv->write_byte = gpib_cs_write_byte;
+ nec_priv->offset = 1;
+ nec_priv->type = CB7210;
+ return 0;
+}
+
+static int fmh_gpib_config_dma(gpib_board_t *board, int output)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct dma_slave_config config;
+
+ config.device_fc = true;
+
+ if (e_priv->dma_burst_length < 1) {
+ config.src_maxburst = 1;
+ config.dst_maxburst = 1;
+ } else {
+ config.src_maxburst = e_priv->dma_burst_length;
+ config.dst_maxburst = e_priv->dma_burst_length;
+ }
+
+ config.src_addr_width = 1;
+ config.dst_addr_width = 1;
+
+ if (output) {
+ config.direction = DMA_MEM_TO_DEV;
+ config.src_addr = 0;
+ config.dst_addr = e_priv->dma_port_res->start + FIFO_DATA_REG * fifo_reg_offset;
+ } else {
+ config.direction = DMA_DEV_TO_MEM;
+ config.src_addr = e_priv->dma_port_res->start + FIFO_DATA_REG * fifo_reg_offset;
+ config.dst_addr = 0;
+ }
+ return dmaengine_slave_config(e_priv->dma_channel, &config);
+}
+
+static int fmh_gpib_init(struct fmh_priv *e_priv, gpib_board_t *board, int handshake_mode)
+{
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+ unsigned int fifo_status_bits;
+
+ fifos_write(e_priv, RX_FIFO_CLEAR | TX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG);
+
+ nec7210_board_reset(nec_priv, board);
+ write_byte(nec_priv, AUX_LO_SPEED, AUXMR);
+ nec7210_set_handshake_mode(board, nec_priv, handshake_mode);
+
+ /* Hueristically check if hardware supports fifo half full/empty interrupts */
+ fifo_status_bits = fifos_read(e_priv, FIFO_CONTROL_STATUS_REG);
+ e_priv->supports_fifo_interrupts = (fifo_status_bits & TX_FIFO_EMPTY) &&
+ (fifo_status_bits & TX_FIFO_HALF_EMPTY);
+
+ nec7210_board_online(nec_priv, board);
+
+ write_byte(nec_priv, IFC_INTERRUPT_ENABLE_BIT | ATN_INTERRUPT_ENABLE_BIT, ISR0_IMR0_REG);
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR);
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return 0;
+}
+
+/* Match callback for driver_find_device */
+static int fmh_gpib_device_match(struct device *dev, const void *data)
+{
+ const gpib_board_config_t *config = data;
+
+ if (dev_get_drvdata(dev))
+ return 0;
+
+ if (gpib_match_device_path(dev, config->device_path) == 0)
+ return 0;
+
+ // driver doesn't support selection by serial number
+ if (config->serial_number)
+ return 0;
+
+ dev_notice(dev, "matched: %s\n", of_node_full_name(dev_of_node((dev))));
+ return 1;
+}
+
+static int fmh_gpib_attach_impl(gpib_board_t *board, const gpib_board_config_t *config,
+ unsigned int handshake_mode, int acquire_dma)
+{
+ struct fmh_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+ int irq;
+ struct resource *res;
+ struct platform_device *pdev;
+
+ board->dev = driver_find_device(&fmh_gpib_platform_driver.driver,
+ NULL, (const void *)config, &fmh_gpib_device_match);
+ if (!board->dev) {
+ pr_err("No matching fmh_gpib_core device was found, attach failed.");
+ return -ENODEV;
+ }
+ // currently only used to mark the device as already attached
+ dev_set_drvdata(board->dev, board);
+ pdev = to_platform_device(board->dev);
+
+ retval = fmh_gpib_generic_attach(board);
+ if (retval)
+ return retval;
+
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpib_control_status");
+ if (!res) {
+ dev_err(board->dev, "Unable to locate mmio resource for cb7210 gpib\n");
+ return -ENODEV;
+ }
+
+ if (request_mem_region(res->start,
+ resource_size(res),
+ pdev->name) == NULL) {
+ dev_err(board->dev, "cannot claim registers\n");
+ return -ENXIO;
+ }
+ e_priv->gpib_iomem_res = res;
+
+ nec_priv->iobase = ioremap(e_priv->gpib_iomem_res->start,
+ resource_size(e_priv->gpib_iomem_res));
+ if (!nec_priv->iobase) {
+ dev_err(board->dev, "Could not map I/O memory for gpib\n");
+ return -ENOMEM;
+ }
+ dev_info(board->dev, "iobase 0x%lx remapped to %p, length=%ld\n",
+ (unsigned long)e_priv->gpib_iomem_res->start,
+ nec_priv->iobase, (unsigned long)resource_size(e_priv->gpib_iomem_res));
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma_fifos");
+ if (!res) {
+ dev_err(board->dev, "Unable to locate mmio resource for gpib dma port\n");
+ return -ENODEV;
+ }
+ if (request_mem_region(res->start,
+ resource_size(res),
+ pdev->name) == NULL) {
+ dev_err(board->dev, "cannot claim registers\n");
+ return -ENXIO;
+ }
+ e_priv->dma_port_res = res;
+ e_priv->fifo_base = ioremap(e_priv->dma_port_res->start,
+ resource_size(e_priv->dma_port_res));
+ if (!e_priv->fifo_base) {
+ dev_err(board->dev, "Could not map I/O memory for fifos\n");
+ return -ENOMEM;
+ }
+ dev_info(board->dev, "dma fifos 0x%lx remapped to %p, length=%ld\n",
+ (unsigned long)e_priv->dma_port_res->start, e_priv->fifo_base,
+ (unsigned long)resource_size(e_priv->dma_port_res));
+
+ irq = platform_get_irq(pdev, 0);
+ pr_info("gpib: irq %d\n", irq);
+ if (irq < 0) {
+ dev_err(board->dev, "fmh_gpib_gpib: request for IRQ failed\n");
+ return -EBUSY;
+ }
+ retval = request_irq(irq, fmh_gpib_interrupt, IRQF_SHARED, pdev->name, board);
+ if (retval) {
+ dev_err(board->dev,
+ "cannot register interrupt handler err=%d\n",
+ retval);
+ return retval;
+ }
+ e_priv->irq = irq;
+
+ if (acquire_dma) {
+ e_priv->dma_channel = dma_request_slave_channel(board->dev, "rxtx");
+ if (!e_priv->dma_channel) {
+ dev_err(board->dev, "failed to acquire dma channel \"rxtx\".\n");
+ return -EIO;
+ }
+ }
+ /* in the future we might want to know the half-fifo size
+ * (dma_burst_length) even when not using dma, so go ahead an
+ * initialize it unconditionally.
+ */
+ e_priv->dma_burst_length = fifos_read(e_priv, FIFO_MAX_BURST_LENGTH_REG) &
+ fifo_max_burst_length_mask;
+
+ return fmh_gpib_init(e_priv, board, handshake_mode);
+}
+
+int fmh_gpib_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return fmh_gpib_attach_impl(board, config, HR_HLDA, 0);
+}
+
+int fmh_gpib_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return fmh_gpib_attach_impl(board, config, HR_HLDE, 1);
+}
+
+void fmh_gpib_detach(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (e_priv) {
+ if (e_priv->dma_channel)
+ dma_release_channel(e_priv->dma_channel);
+ nec_priv = &e_priv->nec7210_priv;
+
+ if (e_priv->irq)
+ free_irq(e_priv->irq, board);
+ if (e_priv->fifo_base)
+ fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG);
+ if (nec_priv->iobase) {
+ write_byte(nec_priv, 0, ISR0_IMR0_REG);
+ nec7210_board_reset(nec_priv, board);
+ }
+ if (e_priv->fifo_base)
+ iounmap(e_priv->fifo_base);
+ if (nec_priv->iobase)
+ iounmap(nec_priv->iobase);
+ if (e_priv->dma_port_res) {
+ release_mem_region(e_priv->dma_port_res->start,
+ resource_size(e_priv->dma_port_res));
+ }
+ if (e_priv->gpib_iomem_res)
+ release_mem_region(e_priv->gpib_iomem_res->start,
+ resource_size(e_priv->gpib_iomem_res));
+ }
+ fmh_gpib_generic_detach(board);
+}
+
+static int fmh_gpib_pci_attach_impl(gpib_board_t *board, const gpib_board_config_t *config,
+ unsigned int handshake_mode)
+{
+ struct fmh_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+ struct pci_dev *pci_device;
+
+ retval = fmh_gpib_generic_attach(board);
+ if (retval)
+ return retval;
+
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+
+ // find board
+ pci_device = gpib_pci_get_device(config, BOGUS_PCI_VENDOR_ID_FLUKE,
+ BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER, NULL);
+ if (!pci_device) {
+ pr_err("No matching fmh_gpib_core pci device was found, attach failed.");
+ return -ENODEV;
+ }
+ board->dev = &pci_device->dev;
+
+ // bladerunner prototype has offset of 4 between gpib control/status registers
+ nec_priv->offset = 4;
+
+ if (pci_enable_device(pci_device)) {
+ dev_err(board->dev, "error enabling pci device\n");
+ return -EIO;
+ }
+ if (pci_request_regions(pci_device, KBUILD_MODNAME)) {
+ dev_err(board->dev, "pci_request_regions failed\n");
+ return -EIO;
+ }
+ e_priv->gpib_iomem_res = &pci_device->resource[gpib_control_status_pci_resource_index];
+ e_priv->dma_port_res = &pci_device->resource[gpib_fifo_pci_resource_index];
+
+ nec_priv->iobase = ioremap(pci_resource_start(pci_device,
+ gpib_control_status_pci_resource_index),
+ pci_resource_len(pci_device,
+ gpib_control_status_pci_resource_index));
+ dev_info(board->dev, "base address for gpib control/status registers remapped to 0x%p\n",
+ nec_priv->iobase);
+
+ if (e_priv->dma_port_res->flags & IORESOURCE_MEM) {
+ e_priv->fifo_base = ioremap(pci_resource_start(pci_device,
+ gpib_fifo_pci_resource_index),
+ pci_resource_len(pci_device,
+ gpib_fifo_pci_resource_index));
+ dev_info(board->dev, "base address for gpib fifo registers remapped to 0x%p\n",
+ e_priv->fifo_base);
+ } else {
+ e_priv->fifo_base = NULL;
+ dev_info(board->dev, "hardware has no gpib fifo registers.\n");
+ }
+
+ if (pci_device->irq) {
+ retval = request_irq(pci_device->irq, fmh_gpib_interrupt, IRQF_SHARED,
+ KBUILD_MODNAME, board);
+ if (retval) {
+ dev_err(board->dev,
+ "cannot register interrupt handler err=%d\n",
+ retval);
+ return retval;
+ }
+ }
+ e_priv->irq = pci_device->irq;
+
+ e_priv->dma_burst_length = fifos_read(e_priv, FIFO_MAX_BURST_LENGTH_REG) &
+ fifo_max_burst_length_mask;
+
+ return fmh_gpib_init(e_priv, board, handshake_mode);
+}
+
+int fmh_gpib_pci_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return fmh_gpib_pci_attach_impl(board, config, HR_HLDA);
+}
+
+int fmh_gpib_pci_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ int retval;
+ struct fmh_priv *e_priv;
+
+ retval = fmh_gpib_pci_attach_impl(board, config, HR_HLDE);
+ e_priv = board->private_data;
+ if (retval == 0 && e_priv && e_priv->supports_fifo_interrupts == 0) {
+ pr_err("fmh_gpib: your fmh_gpib_core does not appear to support fifo interrupts. Try the fmh_gpib_pci_unaccel board type instead.");
+ return -EIO;
+ }
+ return retval;
+}
+
+void fmh_gpib_pci_detach(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (e_priv) {
+ nec_priv = &e_priv->nec7210_priv;
+
+ if (e_priv->irq)
+ free_irq(e_priv->irq, board);
+ if (e_priv->fifo_base)
+ fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG);
+ if (nec_priv->iobase) {
+ write_byte(nec_priv, 0, ISR0_IMR0_REG);
+ nec7210_board_reset(nec_priv, board);
+ }
+ if (e_priv->fifo_base)
+ iounmap(e_priv->fifo_base);
+ if (nec_priv->iobase)
+ iounmap(nec_priv->iobase);
+ if (e_priv->dma_port_res || e_priv->gpib_iomem_res)
+ pci_release_regions(to_pci_dev(board->dev));
+ if (board->dev)
+ pci_dev_put(to_pci_dev(board->dev));
+ }
+ fmh_gpib_generic_detach(board);
+}
+
+static int fmh_gpib_platform_probe(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct of_device_id fmh_gpib_of_match[] = {
+ { .compatible = "fmhess,fmh_gpib_core"},
+ { {0} }
+};
+MODULE_DEVICE_TABLE(of, fmh_gpib_of_match);
+
+static struct platform_driver fmh_gpib_platform_driver = {
+ .driver = {
+ .name = "fmh_gpib",
+ .owner = THIS_MODULE,
+ .of_match_table = fmh_gpib_of_match,
+ },
+ .probe = &fmh_gpib_platform_probe
+};
+
+static int fmh_gpib_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ return 0;
+}
+
+static const struct pci_device_id fmh_gpib_pci_match[] = {
+ { BOGUS_PCI_VENDOR_ID_FLUKE, BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER, 0, 0, 0 },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, fmh_gpib_pci_match);
+
+static struct pci_driver fmh_gpib_pci_driver = {
+ .name = "fmh_gpib",
+ .id_table = fmh_gpib_pci_match,
+ .probe = &fmh_gpib_pci_probe
+};
+
+static int __init fmh_gpib_init_module(void)
+{
+ int result;
+
+ result = platform_driver_register(&fmh_gpib_platform_driver);
+ if (result) {
+ pr_err("fmh_gpib: platform_driver_register failed!\n");
+ return result;
+ }
+
+ result = pci_register_driver(&fmh_gpib_pci_driver);
+ if (result) {
+ pr_err("fmh_gpib: pci_driver_register failed!\n");
+ return result;
+ }
+
+ gpib_register_driver(&fmh_gpib_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&fmh_gpib_interface, THIS_MODULE);
+ gpib_register_driver(&fmh_gpib_pci_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&fmh_gpib_pci_interface, THIS_MODULE);
+
+ pr_info("fmh_gpib\n");
+ return 0;
+}
+
+static void __exit fmh_gpib_exit_module(void)
+{
+ gpib_unregister_driver(&fmh_gpib_pci_interface);
+ gpib_unregister_driver(&fmh_gpib_pci_unaccel_interface);
+ gpib_unregister_driver(&fmh_gpib_unaccel_interface);
+ gpib_unregister_driver(&fmh_gpib_interface);
+
+ pci_unregister_driver(&fmh_gpib_pci_driver);
+ platform_driver_unregister(&fmh_gpib_platform_driver);
+}
+
+module_init(fmh_gpib_init_module);
+module_exit(fmh_gpib_exit_module);
diff --git a/drivers/staging/gpib/fmh_gpib/fmh_gpib.h b/drivers/staging/gpib/fmh_gpib/fmh_gpib.h
new file mode 100644
index 000000000000..43bfc89d2a6f
--- /dev/null
+++ b/drivers/staging/gpib/fmh_gpib/fmh_gpib.h
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Author: Frank Mori Hess <fmh6jj@gmail.com>
+ * Copyright: (C) 2006, 2010, 2015 Fluke Corporation
+ * (C) 2017 Frank Mori Hess
+ ***************************************************************************/
+
+#include <linux/dmaengine.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include "nec7210.h"
+
+static const int fifo_reg_offset = 2;
+
+static const int gpib_control_status_pci_resource_index;
+static const int gpib_fifo_pci_resource_index = 1;
+
+/* We don't have a real pci vendor/device id, the following will need to be
+ * patched to match prototype hardware.
+ */
+#define BOGUS_PCI_VENDOR_ID_FLUKE 0xffff
+#define BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER 0x0
+
+struct fmh_priv {
+ struct nec7210_priv nec7210_priv;
+ struct resource *gpib_iomem_res;
+ struct resource *write_transfer_counter_res;
+ struct resource *dma_port_res;
+ int irq;
+ struct dma_chan *dma_channel;
+ u8 *dma_buffer;
+ int dma_buffer_size;
+ int dma_burst_length;
+ void *fifo_base;
+ unsigned supports_fifo_interrupts : 1;
+};
+
+static inline int fmh_gpib_half_fifo_size(struct fmh_priv *priv)
+{
+ return priv->dma_burst_length;
+}
+
+// registers beyond the nec7210 register set
+enum fmh_gpib_regs {
+ EXT_STATUS_1_REG = 0x9,
+ STATE1_REG = 0xc,
+ ISR0_IMR0_REG = 0xe,
+ BUS_STATUS_REG = 0xf
+};
+
+/* IMR0 -- Interrupt Mode Register 0 */
+enum imr0_bits {
+ ATN_INTERRUPT_ENABLE_BIT = 0x4,
+ IFC_INTERRUPT_ENABLE_BIT = 0x8
+};
+
+/* ISR0 -- Interrupt Status Register 0 */
+enum isr0_bits {
+ ATN_INTERRUPT_BIT = 0x4,
+ IFC_INTERRUPT_BIT = 0x8
+};
+
+enum state1_bits {
+ SOURCE_HANDSHAKE_SIDS_BITS = 0x0, /* source idle state */
+ SOURCE_HANDSHAKE_SGNS_BITS = 0x1, /* source generate state */
+ SOURCE_HANDSHAKE_SDYS_BITS = 0x2, /* source delay state */
+ SOURCE_HANDSHAKE_STRS_BITS = 0x5, /* source transfer state */
+ SOURCE_HANDSHAKE_MASK = 0x7
+};
+
+enum fmh_gpib_auxmr_bits {
+ AUX_I_REG = 0xe0,
+};
+
+enum aux_reg_i_bits {
+ LOCAL_PPOLL_MODE_BIT = 0x4
+};
+
+enum ext_status_1_bits {
+ DATA_IN_STATUS_BIT = 0x01,
+ DATA_OUT_STATUS_BIT = 0x02,
+ COMMAND_OUT_STATUS_BIT = 0x04,
+ RFD_HOLDOFF_STATUS_BIT = 0x08,
+ END_STATUS_BIT = 0x10
+};
+
+/* dma fifo reg and bits */
+enum dma_fifo_regs {
+ FIFO_DATA_REG = 0x0,
+ FIFO_CONTROL_STATUS_REG = 0x1,
+ FIFO_XFER_COUNTER_REG = 0x2,
+ FIFO_MAX_BURST_LENGTH_REG = 0x3
+};
+
+enum fifo_data_bits {
+ FIFO_DATA_EOI_FLAG = 0x100
+};
+
+enum fifo_control_bits {
+ TX_FIFO_DMA_REQUEST_ENABLE = 0x0001,
+ TX_FIFO_CLEAR = 0x0002,
+ TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE = 0x0008,
+ RX_FIFO_DMA_REQUEST_ENABLE = 0x0100,
+ RX_FIFO_CLEAR = 0x0200,
+ RX_FIFO_HALF_FULL_INTERRUPT_ENABLE = 0x0800
+};
+
+enum fifo_status_bits {
+ TX_FIFO_EMPTY = 0x0001,
+ TX_FIFO_FULL = 0x0002,
+ TX_FIFO_HALF_EMPTY = 0x0004,
+ TX_FIFO_HALF_EMPTY_INTERRUPT_IS_ENABLED = 0x0008,
+ TX_FIFO_DMA_REQUEST_IS_ENABLED = 0x0010,
+ RX_FIFO_EMPTY = 0x0100,
+ RX_FIFO_FULL = 0x0200,
+ RX_FIFO_HALF_FULL = 0x0400,
+ RX_FIFO_HALF_FULL_INTERRUPT_IS_ENABLED = 0x0800,
+ RX_FIFO_DMA_REQUEST_IS_ENABLED = 0x1000
+};
+
+static const unsigned int fifo_data_mask = 0x00ff;
+static const unsigned int fifo_xfer_counter_mask = 0x0fff;
+static const unsigned int fifo_max_burst_length_mask = 0x00ff;
+
+static inline uint8_t gpib_cs_read_byte(struct nec7210_priv *nec_priv,
+ unsigned int register_num)
+{
+ return readb(nec_priv->iobase + register_num * nec_priv->offset);
+}
+
+static inline void gpib_cs_write_byte(struct nec7210_priv *nec_priv, uint8_t data,
+ unsigned int register_num)
+{
+ writeb(data, nec_priv->iobase + register_num * nec_priv->offset);
+}
+
+static inline uint16_t fifos_read(struct fmh_priv *fmh_priv, int register_num)
+{
+ if (!fmh_priv->fifo_base)
+ return 0;
+ return readw(fmh_priv->fifo_base + register_num * fifo_reg_offset);
+}
+
+static inline void fifos_write(struct fmh_priv *fmh_priv, uint16_t data, int register_num)
+{
+ if (!fmh_priv->fifo_base)
+ return;
+ writew(data, fmh_priv->fifo_base + register_num * fifo_reg_offset);
+}
+
+enum bus_status_bits {
+ BSR_ATN_BIT = 0x01,
+ BSR_EOI_BIT = 0x02,
+ BSR_SRQ_BIT = 0x04,
+ BSR_IFC_BIT = 0x08,
+ BSR_REN_BIT = 0x10,
+ BSR_DAV_BIT = 0x20,
+ BSR_NRFD_BIT = 0x40,
+ BSR_NDAC_BIT = 0x80,
+};
+
+enum fmh_gpib_aux_cmds {
+ /* AUX_RTL2 is an auxiliary command which causes the cb7210 to assert
+ * (and keep asserted) the local rtl message. This is used in conjunction
+ * with the normal nec7210 AUX_RTL command, which
+ * pulses the rtl message, having the effect of clearing rtl if it was left
+ * asserted by AUX_RTL2.
+ */
+ AUX_RTL2 = 0x0d,
+ AUX_RFD_HOLDOFF_ASAP = 0x15,
+ AUX_REQT = 0x18,
+ AUX_REQF = 0x19,
+ AUX_LO_SPEED = 0x40,
+ AUX_HI_SPEED = 0x41
+};
diff --git a/drivers/staging/gpib/gpio/Makefile b/drivers/staging/gpib/gpio/Makefile
new file mode 100644
index 000000000000..a31ded6e5924
--- /dev/null
+++ b/drivers/staging/gpib/gpio/Makefile
@@ -0,0 +1,4 @@
+
+obj-m += gpib_bitbang.o
+
+
diff --git a/drivers/staging/gpib/gpio/gpib_bitbang.c b/drivers/staging/gpib/gpio/gpib_bitbang.c
new file mode 100644
index 000000000000..a2d562cbd65b
--- /dev/null
+++ b/drivers/staging/gpib/gpio/gpib_bitbang.c
@@ -0,0 +1,1476 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*************************************************************************
+ * This code has been developed at the Institute of Sensor and Actuator *
+ * Systems (Technical University of Vienna, Austria) to enable the GPIO *
+ * lines (e.g. of a raspberry pi) to function as a GPIO master device *
+ * *
+ * authors : Thomas Klima *
+ * Marcello Carla' *
+ * Dave Penkler *
+ * *
+ * copyright : (C) 2016 Thomas Klima *
+ * *
+ *************************************************************************/
+
+/*
+ * limitations:
+ * works only on RPi
+ * cannot function as non-CIC system controller with SN7516x because
+ * SN75161B cannot simultaneously make ATN input with IFC and REN as
+ * outputs.
+ * not implemented:
+ * parallel poll
+ * return2local
+ * device support (non master operation)
+ */
+
+#define NAME KBUILD_MODNAME
+
+#define ENABLE_IRQ(IRQ, TYPE) irq_set_irq_type(IRQ, TYPE)
+#define DISABLE_IRQ(IRQ) irq_set_irq_type(IRQ, IRQ_TYPE_NONE)
+
+/* Debug print levels:
+ * 0 = load/unload info and errors that make the driver fail;
+ * 1 = + warnings for unforeseen events that may break the current
+ * operation and lead to a timeout, but do not affect the
+ * driver integrity (mainly unexpected interrupts);
+ * 2 = + trace of function calls;
+ * 3 = + trace of protocol codes;
+ * 4 = + trace of interrupt operation.
+ */
+#define dbg_printk(level, frm, ...) \
+ do { if (debug >= (level)) \
+ pr_info("%s:%s - " frm, NAME, __func__, ## __VA_ARGS__); } \
+ while (0)
+
+#define LINVAL gpiod_get_value(DAV), \
+ gpiod_get_value(NRFD), \
+ gpiod_get_value(NDAC), \
+ gpiod_get_value(SRQ)
+#define LINFMT "DAV: %d NRFD:%d NDAC: %d SRQ: %d"
+
+#include "gpibP.h"
+#include "gpib_state_machines.h"
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/leds.h>
+
+static int sn7516x_used = 1, sn7516x;
+module_param(sn7516x_used, int, 0660);
+
+#define PINMAP_0 "elektronomikon"
+#define PINMAP_1 "gpib4pi-1.1"
+#define PINMAP_2 "yoga"
+static char *pin_map = PINMAP_0;
+module_param(pin_map, charp, 0660);
+MODULE_PARM_DESC(pin_map, " valid values: " PINMAP_0 " " PINMAP_1 " " PINMAP_2);
+
+/**********************************************
+ * Signal pairing and pin wiring between the *
+ * Raspberry-Pi connector and the GPIB bus *
+ * *
+ * signal pin wiring *
+ * GPIB Pi-gpio GPIB -> RPi *
+ **********************************************
+ */
+enum lines_t {
+ D01_pin_nr = 20, /* 1 -> 38 */
+ D02_pin_nr = 26, /* 2 -> 37 */
+ D03_pin_nr = 16, /* 3 -> 36 */
+ D04_pin_nr = 19, /* 4 -> 35 */
+ D05_pin_nr = 13, /* 13 -> 33 */
+ D06_pin_nr = 12, /* 14 -> 32 */
+ D07_pin_nr = 6, /* 15 -> 31 */
+ D08_pin_nr = 5, /* 16 -> 29 */
+ EOI_pin_nr = 9, /* 5 -> 21 */
+ DAV_pin_nr = 10, /* 6 -> 19 */
+ NRFD_pin_nr = 24, /* 7 -> 18 */
+ NDAC_pin_nr = 23, /* 8 -> 16 */
+ IFC_pin_nr = 22, /* 9 -> 15 */
+ SRQ_pin_nr = 11, /* 10 -> 23 */
+ _ATN_pin_nr = 25, /* 11 -> 22 */
+ REN_pin_nr = 27, /* 17 -> 13 */
+/*
+ * GROUND PINS
+ * 12,18,19,20,21,22,23,24 => 14,20,25,30,34,39
+ */
+
+/*
+ * These lines are used to control the external
+ * SN75160/161 driver chips when used.
+ * When not used there is reduced fan out;
+ * currently tested with up to 4 devices.
+ */
+
+/* Pi GPIO RPI 75161B 75160B Description */
+ PE_pin_nr = 7, /* 26 -> nc 11 Pullup Enable */
+ DC_pin_nr = 8, /* 24 -> 12 nc Direction control */
+ TE_pin_nr = 18, /* 12 -> 2 1 Talk Enable */
+ ACT_LED_pin_nr = 4, /* 7 -> LED */
+
+/* YOGA adapter uses different pinout to ease layout */
+ YOGA_D03_pin_nr = 13,
+ YOGA_D04_pin_nr = 12,
+ YOGA_D05_pin_nr = 21,
+ YOGA_D06_pin_nr = 19,
+};
+
+/*
+ * GPIO descriptors and pins - WARNING: STRICTLY KEEP ITEMS ORDER
+ */
+
+#define GPIB_PINS 16
+#define SN7516X_PINS 4
+#define NUM_PINS (GPIB_PINS + SN7516X_PINS)
+
+DEFINE_LED_TRIGGER(ledtrig_gpib);
+#define ACT_LED_ON do { \
+ if (ACT_LED) \
+ gpiod_direction_output(ACT_LED, 1); \
+ else \
+ led_trigger_event(ledtrig_gpib, LED_FULL); } \
+ while (0)
+#define ACT_LED_OFF do { \
+ if (ACT_LED) \
+ gpiod_direction_output(ACT_LED, 0); \
+ else \
+ led_trigger_event(ledtrig_gpib, LED_OFF); } \
+ while (0)
+
+struct gpio_desc *all_descriptors[GPIB_PINS + SN7516X_PINS];
+
+#define D01 all_descriptors[0]
+#define D02 all_descriptors[1]
+#define D03 all_descriptors[2]
+#define D04 all_descriptors[3]
+#define D05 all_descriptors[4]
+#define D06 all_descriptors[5]
+#define D07 all_descriptors[6]
+#define D08 all_descriptors[7]
+
+#define EOI all_descriptors[8]
+#define NRFD all_descriptors[9]
+#define IFC all_descriptors[10]
+#define _ATN all_descriptors[11]
+#define REN all_descriptors[12]
+#define DAV all_descriptors[13]
+#define NDAC all_descriptors[14]
+#define SRQ all_descriptors[15]
+
+#define PE all_descriptors[16]
+#define DC all_descriptors[17]
+#define TE all_descriptors[18]
+#define ACT_LED all_descriptors[19]
+
+/* YOGA dapter uses a global enable for the buffer chips, re-using the TE pin */
+#define YOGA_ENABLE TE
+
+int gpios_vector[] = {
+ D01_pin_nr,
+ D02_pin_nr,
+ D03_pin_nr,
+ D04_pin_nr,
+ D05_pin_nr,
+ D06_pin_nr,
+ D07_pin_nr,
+ D08_pin_nr,
+
+ EOI_pin_nr,
+ NRFD_pin_nr,
+ IFC_pin_nr,
+ _ATN_pin_nr,
+ REN_pin_nr,
+ DAV_pin_nr,
+ NDAC_pin_nr,
+ SRQ_pin_nr,
+
+ PE_pin_nr,
+ DC_pin_nr,
+ TE_pin_nr,
+ ACT_LED_pin_nr
+};
+
+/* Lookup table for general GPIOs */
+
+static struct gpiod_lookup_table gpib_gpio_table_1 = {
+ // for bcm2835/6
+ .dev_id = "", // device id of board device
+ .table = {
+ GPIO_LOOKUP_IDX("GPIO_GCLK", U16_MAX, NULL, 4, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO5", U16_MAX, NULL, 5, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO6", U16_MAX, NULL, 6, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("SPI_CE1_N", U16_MAX, NULL, 7, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("SPI_CE0_N", U16_MAX, NULL, 8, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("SPI_MISO", U16_MAX, NULL, 9, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("SPI_MOSI", U16_MAX, NULL, 10, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("SPI_SCLK", U16_MAX, NULL, 11, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO12", U16_MAX, NULL, 12, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO13", U16_MAX, NULL, 13, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO16", U16_MAX, NULL, 16, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO17", U16_MAX, NULL, 17, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO18", U16_MAX, NULL, 18, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO19", U16_MAX, NULL, 19, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO20", U16_MAX, NULL, 20, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO21", U16_MAX, NULL, 21, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO22", U16_MAX, NULL, 22, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO23", U16_MAX, NULL, 23, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO24", U16_MAX, NULL, 24, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO25", U16_MAX, NULL, 25, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO26", U16_MAX, NULL, 26, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO27", U16_MAX, NULL, 27, GPIO_ACTIVE_HIGH),
+ { }
+ },
+};
+
+static struct gpiod_lookup_table gpib_gpio_table_0 = {
+ .dev_id = "", // device id of board device
+ .table = {
+ // for bcm27xx based pis (b b+ 2b 3b 3b+ 4 5)
+ GPIO_LOOKUP_IDX("GPIO4", U16_MAX, NULL, 4, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO5", U16_MAX, NULL, 5, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO6", U16_MAX, NULL, 6, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO7", U16_MAX, NULL, 7, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO8", U16_MAX, NULL, 8, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO9", U16_MAX, NULL, 9, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO10", U16_MAX, NULL, 10, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO11", U16_MAX, NULL, 11, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO12", U16_MAX, NULL, 12, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO13", U16_MAX, NULL, 13, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO16", U16_MAX, NULL, 16, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO17", U16_MAX, NULL, 17, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO18", U16_MAX, NULL, 18, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO19", U16_MAX, NULL, 19, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO20", U16_MAX, NULL, 20, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO21", U16_MAX, NULL, 21, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO22", U16_MAX, NULL, 22, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO23", U16_MAX, NULL, 23, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO24", U16_MAX, NULL, 24, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO25", U16_MAX, NULL, 25, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO26", U16_MAX, NULL, 26, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO27", U16_MAX, NULL, 27, GPIO_ACTIVE_HIGH),
+ { }
+ },
+};
+
+static struct gpiod_lookup_table *lookup_tables[] = {
+ &gpib_gpio_table_0,
+ &gpib_gpio_table_1,
+ 0
+};
+
+/* struct which defines private_data for gpio driver */
+
+struct bb_priv {
+ int irq_NRFD;
+ int irq_NDAC;
+ int irq_DAV;
+ int irq_SRQ;
+ int dav_mode; /* dav interrupt mode 0/1 -> edge/levels */
+ int nrfd_mode; /* nrfd interrupt mode 0/1 -> edge/levels */
+ int ndac_mode; /* nrfd interrupt mode 0/1 -> edge/levels */
+ int dav_tx; /* keep trace of DAV status while sending */
+ int dav_rx; /* keep trace of DAV status while receiving */
+ u8 eos; // eos character
+ short eos_flags; // eos mode
+ short eos_check; /* eos check required in current operation ... */
+ short eos_check_8; /* ... with byte comparison */
+ short eos_mask_7; /* ... with 7 bit masked character */
+ short int end;
+ int request;
+ int count;
+ int direction;
+ int t1_delay;
+ u8 *rbuf;
+ u8 *wbuf;
+ int end_flag;
+ int r_busy; /* 0==idle 1==busy */
+ int w_busy;
+ int write_done;
+ int cmd; /* 1 = cmd write in progress */
+ size_t w_cnt;
+ size_t length;
+ u8 *w_buf;
+ spinlock_t rw_lock; // protect mods to rw_lock
+ int phase;
+ int ndac_idle;
+ int ndac_seq;
+ int nrfd_idle;
+ int nrfd_seq;
+ int dav_seq;
+ long all_irqs;
+ int dav_idle;
+ int atn_asserted;
+
+ enum talker_function_state talker_state;
+ enum listener_function_state listener_state;
+};
+
+inline long usec_diff(struct timespec64 *a, struct timespec64 *b);
+static void bb_buffer_print(unsigned char *buffer, size_t length, int cmd, int eoi);
+static void set_data_lines(u8 byte);
+static u8 get_data_lines(void);
+static void set_data_lines_input(void);
+static void set_data_lines_output(void);
+static inline int check_for_eos(struct bb_priv *priv, uint8_t byte);
+static void set_atn(struct bb_priv *priv, int atn_asserted);
+
+static inline void SET_DIR_WRITE(struct bb_priv *priv);
+static inline void SET_DIR_READ(struct bb_priv *priv);
+
+#define DIR_READ 0
+#define DIR_WRITE 1
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB helper functions for bitbanging I/O");
+
+/**** global variables ****/
+#ifdef CONFIG_GPIB_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+module_param(debug, int, 0644);
+
+static char printable(char x)
+{
+ if (x < 32 || x > 126)
+ return ' ';
+ return x;
+}
+
+/***************************************************************************
+ * *
+ * READ *
+ * *
+ ***************************************************************************/
+
+static int bb_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read)
+{
+ struct bb_priv *priv = board->private_data;
+ unsigned long flags;
+ int retval = 0;
+
+ ACT_LED_ON;
+ SET_DIR_READ(priv);
+
+ dbg_printk(2, "board: %p lock %d length: %zu\n",
+ board, mutex_is_locked(&board->user_mutex), length);
+
+ priv->end = 0;
+ priv->count = 0;
+ priv->rbuf = buffer;
+ if (length == 0)
+ goto read_end;
+ priv->request = length;
+ priv->eos_check = (priv->eos_flags & REOS) == 0; /* do eos check */
+ priv->eos_check_8 = priv->eos_flags & BIN; /* over 8 bits */
+ priv->eos_mask_7 = priv->eos & 0x7f; /* with this 7 bit eos */
+
+ dbg_printk(3, ".........." LINFMT "\n", LINVAL);
+
+ spin_lock_irqsave(&priv->rw_lock, flags);
+ priv->dav_mode = 1;
+ priv->dav_rx = 1;
+ ENABLE_IRQ(priv->irq_DAV, IRQ_TYPE_LEVEL_LOW);
+ priv->end_flag = 0;
+ gpiod_set_value(NRFD, 1); // ready for data
+ priv->r_busy = 1;
+ priv->phase = 100;
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+
+ /* wait for the interrupt routines finish their work */
+
+ retval = wait_event_interruptible(board->wait,
+ (priv->end_flag || board->status & TIMO));
+
+ dbg_printk(3, "awake from wait queue: %d\n", retval);
+
+ if (retval == 0 && board->status & TIMO) {
+ retval = -ETIMEDOUT;
+ dbg_printk(1, "timeout\n");
+ } else if (retval) {
+ retval = -ERESTARTSYS;
+ }
+
+ DISABLE_IRQ(priv->irq_DAV);
+ spin_lock_irqsave(&priv->rw_lock, flags);
+ gpiod_set_value(NRFD, 0); // DIR_READ line state
+ priv->r_busy = 0;
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+
+read_end:
+ ACT_LED_OFF;
+ *bytes_read = priv->count;
+ *end = priv->end;
+ priv->r_busy = 0;
+ dbg_printk(2, "return: %d eoi|eos: %d count: %d\n\n", retval, priv->end, priv->count);
+ return retval;
+}
+
+/***************************************************************************
+ * *
+ * READ interrupt routine (DAV line) *
+ * *
+ ***************************************************************************/
+
+static irqreturn_t bb_DAV_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct bb_priv *priv = board->private_data;
+ int val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->rw_lock, flags);
+
+ priv->all_irqs++;
+
+ if (priv->dav_mode) {
+ ENABLE_IRQ(priv->irq_DAV, IRQ_TYPE_EDGE_BOTH);
+ priv->dav_mode = 0;
+ }
+
+ if (priv->r_busy == 0) {
+ dbg_printk(1, "interrupt while idle after %d at %d\n",
+ priv->count, priv->phase);
+ priv->dav_idle++;
+ priv->phase = 200;
+ goto dav_exit; /* idle */
+ }
+
+ val = gpiod_get_value(DAV);
+ if (val == priv->dav_rx) {
+ dbg_printk(1, "out of order DAV interrupt %d/%d after %zu/%zu at %d cmd %d "
+ LINFMT ".\n", val, priv->dav_rx, priv->w_cnt, priv->length,
+ priv->phase, priv->cmd, LINVAL);
+ priv->dav_seq++;
+ }
+ priv->dav_rx = val;
+
+ dbg_printk(3, "> irq: %d DAV: %d st: %4lx dir: %d busy: %d:%d\n",
+ irq, val, board->status, priv->direction, priv->r_busy, priv->w_busy);
+
+ if (val == 0) {
+ gpiod_set_value(NRFD, 0); // not ready for data
+ priv->rbuf[priv->count++] = get_data_lines();
+ priv->end = !gpiod_get_value(EOI);
+ gpiod_set_value(NDAC, 1); // data accepted
+ priv->end |= check_for_eos(priv, priv->rbuf[priv->count - 1]);
+ priv->end_flag = ((priv->count >= priv->request) || priv->end);
+ priv->phase = 210;
+ } else {
+ gpiod_set_value(NDAC, 0); // data not accepted
+ if (priv->end_flag) {
+ priv->r_busy = 0;
+ wake_up_interruptible(&board->wait);
+ priv->phase = 220;
+ } else {
+ gpiod_set_value(NRFD, 1); // ready for data
+ priv->phase = 230;
+ }
+ }
+
+dav_exit:
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+ dbg_printk(3, "< irq: %d count %d\n", irq, priv->count);
+ return IRQ_HANDLED;
+}
+
+/***************************************************************************
+ * *
+ * WRITE *
+ * *
+ ***************************************************************************/
+
+static int bb_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ unsigned long flags;
+ int retval = 0;
+
+ struct bb_priv *priv = board->private_data;
+
+ ACT_LED_ON;
+
+ priv->w_cnt = 0;
+ priv->w_buf = buffer;
+ dbg_printk(2, "board %p lock %d length: %zu\n",
+ board, mutex_is_locked(&board->user_mutex), length);
+
+ if (debug > 1)
+ bb_buffer_print(buffer, length, priv->cmd, send_eoi);
+ priv->count = 0;
+ priv->phase = 300;
+
+ if (length == 0)
+ goto write_end;
+ priv->end = send_eoi;
+ priv->length = length;
+
+ SET_DIR_WRITE(priv);
+
+ dbg_printk(2, "Enabling interrupts - NRFD: %d NDAC: %d\n",
+ gpiod_get_value(NRFD), gpiod_get_value(NDAC));
+
+ if (gpiod_get_value(NRFD) && gpiod_get_value(NDAC)) { /* check for listener */
+ retval = -ENODEV;
+ goto write_end;
+ }
+
+ spin_lock_irqsave(&priv->rw_lock, flags);
+ priv->w_busy = 1; /* make the interrupt routines active */
+ priv->write_done = 0;
+ priv->nrfd_mode = 1;
+ priv->ndac_mode = 1;
+ priv->dav_tx = 1;
+ ENABLE_IRQ(priv->irq_NDAC, IRQ_TYPE_LEVEL_HIGH);
+ ENABLE_IRQ(priv->irq_NRFD, IRQ_TYPE_LEVEL_HIGH);
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+
+ /* wait for the interrupt routines finish their work */
+
+ retval = wait_event_interruptible(board->wait,
+ priv->write_done || (board->status & TIMO));
+
+ dbg_printk(3, "awake from wait queue: %d\n", retval);
+
+ if (retval == 0) {
+ if (board->status & TIMO) {
+ retval = -ETIMEDOUT;
+ dbg_printk(1, "timeout after %zu/%zu at %d " LINFMT " eoi: %d\n",
+ priv->w_cnt, length, priv->phase, LINVAL, send_eoi);
+ } else {
+ // dbg_printk(1,"written %zu\n", priv->w_cnt);
+ retval = priv->w_cnt;
+ }
+ } else {
+ retval = -ERESTARTSYS;
+ }
+
+ DISABLE_IRQ(priv->irq_NRFD);
+ DISABLE_IRQ(priv->irq_NDAC);
+
+ spin_lock_irqsave(&priv->rw_lock, flags);
+ priv->w_busy = 0;
+ gpiod_set_value(DAV, 1); // DIR_WRITE line state
+ gpiod_set_value(EOI, 1); // De-assert EOI (in case)
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+
+write_end:
+ *bytes_written = priv->w_cnt;
+ ACT_LED_OFF;
+ dbg_printk(2, "sent %zu bytes\r\n\r\n", *bytes_written);
+ priv->phase = 310;
+ return retval;
+}
+
+/***************************************************************************
+ * *
+ * WRITE interrupt routine (NRFD line) *
+ * *
+ ***************************************************************************/
+
+static irqreturn_t bb_NRFD_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct bb_priv *priv = board->private_data;
+ unsigned long flags;
+ int nrfd;
+
+ spin_lock_irqsave(&priv->rw_lock, flags);
+
+ nrfd = gpiod_get_value(NRFD);
+ priv->all_irqs++;
+
+ dbg_printk(3, "> irq: %d NRFD: %d NDAC: %d st: %4lx dir: %d busy: %d:%d\n",
+ irq, nrfd, gpiod_get_value(NDAC), board->status, priv->direction,
+ priv->w_busy, priv->r_busy);
+
+ if (priv->nrfd_mode) {
+ ENABLE_IRQ(priv->irq_NRFD, IRQ_TYPE_EDGE_RISING);
+ priv->nrfd_mode = 0;
+ }
+
+ if (priv->w_busy == 0) {
+ dbg_printk(1, "interrupt while idle after %zu/%zu at %d\n",
+ priv->w_cnt, priv->length, priv->phase);
+ priv->nrfd_idle++;
+ goto nrfd_exit; /* idle */
+ }
+ if (nrfd == 0) {
+ dbg_printk(1, "out of order interrupt after %zu/%zu at %d cmd %d " LINFMT ".\n",
+ priv->w_cnt, priv->length, priv->phase, priv->cmd, LINVAL);
+ priv->phase = 400;
+ priv->nrfd_seq++;
+ goto nrfd_exit;
+ }
+ if (!priv->dav_tx) {
+ dbg_printk(1, "DAV low after %zu/%zu cmd %d " LINFMT ". No action.\n",
+ priv->w_cnt, priv->length, priv->cmd, LINVAL);
+ priv->dav_seq++;
+ goto nrfd_exit;
+ }
+
+ if (priv->atn_asserted && priv->w_cnt >= priv->length) { // test for end of transfer
+ priv->write_done = 1;
+ priv->w_busy = 0;
+ wake_up_interruptible(&board->wait);
+ goto nrfd_exit;
+ }
+
+ dbg_printk(3, "sending %zu\n", priv->w_cnt);
+
+ set_data_lines(priv->w_buf[priv->w_cnt++]); // put the data on the lines
+
+ if (priv->w_cnt == priv->length && priv->end) {
+ dbg_printk(3, "Asserting EOI\n");
+ gpiod_set_value(EOI, 0); // Assert EOI
+ }
+
+ gpiod_set_value(DAV, 0); // Data available
+ priv->dav_tx = 0;
+ priv->phase = 410;
+
+nrfd_exit:
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+/***************************************************************************
+ * *
+ * WRITE interrupt routine (NDAC line) *
+ * *
+ ***************************************************************************/
+
+static irqreturn_t bb_NDAC_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct bb_priv *priv = board->private_data;
+ unsigned long flags;
+ int ndac;
+
+ spin_lock_irqsave(&priv->rw_lock, flags);
+
+ ndac = gpiod_get_value(NDAC);
+ priv->all_irqs++;
+ dbg_printk(3, "> irq: %d NRFD: %d NDAC: %d st: %4lx dir: %d busy: %d:%d\n",
+ irq, gpiod_get_value(NRFD), ndac, board->status, priv->direction,
+ priv->w_busy, priv->r_busy);
+
+ if (priv->ndac_mode) {
+ ENABLE_IRQ(priv->irq_NDAC, IRQ_TYPE_EDGE_RISING);
+ priv->ndac_mode = 0;
+ }
+
+ if (priv->w_busy == 0) {
+ dbg_printk(1, "interrupt while idle.\n");
+ priv->ndac_idle++;
+ goto ndac_exit;
+ }
+ if (ndac == 0) {
+ dbg_printk(1, "out of order interrupt at %zu:%d.\n", priv->w_cnt, priv->phase);
+ priv->phase = 500;
+ priv->ndac_seq++;
+ goto ndac_exit;
+ }
+ if (priv->dav_tx) {
+ dbg_printk(1, "DAV high after %zu/%zu cmd %d " LINFMT ". No action.\n",
+ priv->w_cnt, priv->length, priv->cmd, LINVAL);
+ priv->dav_seq++;
+ goto ndac_exit;
+ }
+
+ dbg_printk(3, "accepted %zu\n", priv->w_cnt - 1);
+
+ if (!priv->atn_asserted && priv->w_cnt >= priv->length) { // test for end of transfer
+ priv->write_done = 1;
+ priv->w_busy = 0;
+ wake_up_interruptible(&board->wait);
+ } else {
+ gpiod_set_value(DAV, 1); // Data not available
+ priv->dav_tx = 1;
+ priv->phase = 510;
+ }
+
+ndac_exit:
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+ return IRQ_HANDLED;
+}
+
+/***************************************************************************
+ * *
+ * interrupt routine for SRQ line *
+ * *
+ ***************************************************************************/
+
+static irqreturn_t bb_SRQ_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+
+ int val = gpiod_get_value(SRQ);
+
+ dbg_printk(3, "> %d st: %4lx\n", val, board->status);
+
+ if (!val)
+ set_bit(SRQI_NUM, &board->status); /* set_bit() is atomic */
+
+ wake_up_interruptible(&board->wait);
+
+ return IRQ_HANDLED;
+}
+
+static int bb_command(gpib_board_t *board, uint8_t *buffer,
+ size_t length, size_t *bytes_written)
+{
+ size_t ret;
+ struct bb_priv *priv = board->private_data;
+ int i;
+
+ dbg_printk(2, "%p %p\n", buffer, board->buffer);
+
+ /* the _ATN line has already been asserted by bb_take_control() */
+
+ priv->cmd = 1;
+
+ ret = bb_write(board, buffer, length, 0, bytes_written); // no eoi
+
+ for (i = 0; i < length; i++) {
+ if (buffer[i] == UNT) {
+ priv->talker_state = talker_idle;
+ } else {
+ if (buffer[i] == UNL) {
+ priv->listener_state = listener_idle;
+ } else {
+ if (buffer[i] == (MTA(board->pad))) {
+ priv->talker_state = talker_addressed;
+ priv->listener_state = listener_idle;
+ } else if (buffer[i] == (MLA(board->pad))) {
+ priv->listener_state = listener_addressed;
+ priv->talker_state = talker_idle;
+ }
+ }
+ }
+ }
+
+ /* the _ATN line will be released by bb_go_to_stby */
+
+ priv->cmd = 0;
+
+ return ret;
+}
+
+/***************************************************************************
+ * *
+ * Buffer print with decode for debug/trace *
+ * *
+ ***************************************************************************/
+
+static char *cmd_string[32] = {
+ "", // 0x00
+ "GTL", // 0x01
+ "", // 0x02
+ "", // 0x03
+ "SDC", // 0x04
+ "PPC", // 0x05
+ "", // 0x06
+ "", // 0x07
+ "GET", // 0x08
+ "TCT", // 0x09
+ "", // 0x0a
+ "", // 0x0b
+ "", // 0x0c
+ "", // 0x0d
+ "", // 0x0e
+ "", // 0x0f
+ "", // 0x10
+ "LLO", // 0x11
+ "", // 0x12
+ "", // 0x13
+ "DCL", // 0x14
+ "PPU", // 0x15
+ "", // 0x16
+ "", // 0x17
+ "SPE", // 0x18
+ "SPD", // 0x19
+ "", // 0x1a
+ "", // 0x1b
+ "", // 0x1c
+ "", // 0x1d
+ "", // 0x1e
+ "CFE" // 0x1f
+};
+
+static void bb_buffer_print(unsigned char *buffer, size_t length, int cmd, int eoi)
+{
+ int i;
+
+ if (cmd) {
+ dbg_printk(2, "<cmd len %zu>\n", length);
+ for (i = 0; i < length; i++) {
+ if (buffer[i] < 0x20) {
+ dbg_printk(3, "0x%x=%s\n", buffer[i], cmd_string[buffer[i]]);
+ } else if (buffer[i] == 0x3f) {
+ dbg_printk(3, "0x%x=%s\n", buffer[i], "UNL");
+ } else if (buffer[i] == 0x5f) {
+ dbg_printk(3, "0x%x=%s\n", buffer[i], "UNT");
+ } else if (buffer[i] < 0x60) {
+ dbg_printk(3, "0x%x=%s%d\n", buffer[i],
+ (buffer[i] & 0x40) ? "TLK" : "LSN", buffer[i] & 0x1F);
+ } else {
+ dbg_printk(3, "0x%x\n", buffer[i]);
+ }
+ }
+ } else {
+ dbg_printk(2, "<data len %zu %s>\n", length, (eoi) ? "w.EOI" : " ");
+ for (i = 0; i < length; i++)
+ dbg_printk(2, "%3d 0x%x->%c\n", i, buffer[i], printable(buffer[i]));
+ }
+}
+
+/***************************************************************************
+ * *
+ * STATUS Management *
+ * *
+ ***************************************************************************/
+static void set_atn(struct bb_priv *priv, int atn_asserted)
+{
+ if (priv->listener_state != listener_idle &&
+ priv->talker_state != talker_idle) {
+ dbg_printk(0, "listener/talker state machine conflict\n");
+ }
+ if (atn_asserted) {
+ if (priv->listener_state == listener_active)
+ priv->listener_state = listener_addressed;
+ if (priv->talker_state == talker_active)
+ priv->talker_state = talker_addressed;
+ } else {
+ if (priv->listener_state == listener_addressed) {
+ priv->listener_state = listener_active;
+ SET_DIR_READ(priv); // make sure holdoff is active when we unassert ATN
+ }
+ if (priv->talker_state == talker_addressed)
+ priv->talker_state = talker_active;
+ }
+ gpiod_direction_output(_ATN, !atn_asserted);
+ priv->atn_asserted = atn_asserted;
+}
+
+static int bb_take_control(gpib_board_t *board, int synchronous)
+{
+ dbg_printk(2, "%d\n", synchronous);
+ set_atn(board->private_data, 1);
+ set_bit(CIC_NUM, &board->status);
+ return 0;
+}
+
+static int bb_go_to_standby(gpib_board_t *board)
+{
+ dbg_printk(2, "\n");
+ set_atn(board->private_data, 0);
+ return 0;
+}
+
+static void bb_request_system_control(gpib_board_t *board, int request_control)
+{
+ dbg_printk(2, "%d\n", request_control);
+ if (request_control) {
+ set_bit(CIC_NUM, &board->status);
+ // drive DAV & EOI false, enable NRFD & NDAC irqs
+ SET_DIR_WRITE(board->private_data);
+ } else {
+ clear_bit(CIC_NUM, &board->status);
+ }
+}
+
+static void bb_interface_clear(gpib_board_t *board, int assert)
+{
+ struct bb_priv *priv = board->private_data;
+
+ dbg_printk(2, "%d\n", assert);
+ if (assert) {
+ gpiod_direction_output(IFC, 0);
+ priv->talker_state = talker_idle;
+ priv->listener_state = listener_idle;
+ } else {
+ gpiod_direction_output(IFC, 1);
+ }
+}
+
+static void bb_remote_enable(gpib_board_t *board, int enable)
+{
+ dbg_printk(2, "%d\n", enable);
+ if (enable) {
+ set_bit(REM_NUM, &board->status);
+ gpiod_direction_output(REN, 0);
+ } else {
+ clear_bit(REM_NUM, &board->status);
+ gpiod_direction_output(REN, 1);
+ }
+}
+
+static int bb_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct bb_priv *priv = board->private_data;
+
+ dbg_printk(2, "%s\n", "EOS_en");
+ priv->eos = eos_byte;
+ priv->eos_flags = REOS;
+ if (compare_8_bits)
+ priv->eos_flags |= BIN;
+
+ return 0;
+}
+
+static void bb_disable_eos(gpib_board_t *board)
+{
+ struct bb_priv *priv = board->private_data;
+
+ dbg_printk(2, "\n");
+ priv->eos_flags &= ~REOS;
+}
+
+static unsigned int bb_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct bb_priv *priv = board->private_data;
+
+ board->status &= ~clear_mask;
+
+ if (gpiod_get_value(SRQ)) /* SRQ asserted low */
+ clear_bit(SRQI_NUM, &board->status);
+ else
+ set_bit(SRQI_NUM, &board->status);
+ if (gpiod_get_value(_ATN)) /* ATN asserted low */
+ clear_bit(ATN_NUM, &board->status);
+ else
+ set_bit(ATN_NUM, &board->status);
+ if (priv->talker_state == talker_active ||
+ priv->talker_state == talker_addressed)
+ set_bit(TACS_NUM, &board->status);
+ else
+ clear_bit(TACS_NUM, &board->status);
+
+ if (priv->listener_state == listener_active ||
+ priv->listener_state == listener_addressed)
+ set_bit(LACS_NUM, &board->status);
+ else
+ clear_bit(LACS_NUM, &board->status);
+
+ dbg_printk(2, "0x%lx mask 0x%x\n", board->status, clear_mask);
+
+ return board->status;
+}
+
+static int bb_primary_address(gpib_board_t *board, unsigned int address)
+{
+ dbg_printk(2, "%d\n", address);
+ board->pad = address;
+ return 0;
+}
+
+static int bb_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ dbg_printk(2, "%d %d\n", address, enable);
+ if (enable)
+ board->sad = address;
+ return 0;
+}
+
+static int bb_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ dbg_printk(1, "%s\n", "not implemented");
+ return -EPERM;
+}
+
+static void bb_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ dbg_printk(1, "%s\n", "not implemented");
+}
+
+static void bb_parallel_poll_response(gpib_board_t *board, int ist)
+{
+}
+
+static void bb_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ dbg_printk(1, "%s\n", "not implemented");
+}
+
+static uint8_t bb_serial_poll_status(gpib_board_t *board)
+{
+ dbg_printk(1, "%s\n", "not implemented");
+ return 0; // -ENOSYS;
+}
+
+static unsigned int bb_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct bb_priv *priv = board->private_data;
+
+ if (nano_sec <= 350)
+ priv->t1_delay = 350;
+ else if (nano_sec <= 1100)
+ priv->t1_delay = 1100;
+ else
+ priv->t1_delay = 2000;
+
+ dbg_printk(2, "t1 delay set to %d nanosec\n", priv->t1_delay);
+
+ return priv->t1_delay;
+}
+
+static void bb_return_to_local(gpib_board_t *board)
+{
+ dbg_printk(1, "%s\n", "not implemented");
+}
+
+static int bb_line_status(const gpib_board_t *board)
+{
+ int line_status = ValidALL;
+
+// dbg_printk(1,"\n");
+
+ if (gpiod_get_value(REN) == 0)
+ line_status |= BusREN;
+ if (gpiod_get_value(IFC) == 0)
+ line_status |= BusIFC;
+ if (gpiod_get_value(NDAC) == 0)
+ line_status |= BusNDAC;
+ if (gpiod_get_value(NRFD) == 0)
+ line_status |= BusNRFD;
+ if (gpiod_get_value(DAV) == 0)
+ line_status |= BusDAV;
+ if (gpiod_get_value(EOI) == 0)
+ line_status |= BusEOI;
+ if (gpiod_get_value(_ATN) == 0)
+ line_status |= BusATN;
+ if (gpiod_get_value(SRQ) == 0)
+ line_status |= BusSRQ;
+
+ dbg_printk(2, "status lines: %4x\n", line_status);
+
+ return line_status;
+}
+
+/***************************************************************************
+ * *
+ * Module Management *
+ * *
+ ***************************************************************************/
+
+static int allocate_private(gpib_board_t *board)
+{
+ board->private_data = kzalloc(sizeof(struct bb_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ return 0;
+}
+
+static void free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+static int bb_get_irq(gpib_board_t *board, char *name,
+ struct gpio_desc *gpio, int *irq,
+ irq_handler_t handler, irq_handler_t thread_fn, unsigned long flags)
+{
+ if (!gpio)
+ return -1;
+ gpiod_direction_input(gpio);
+ *irq = gpiod_to_irq(gpio);
+ dbg_printk(2, "IRQ %s: %d\n", name, *irq);
+ if (*irq < 0) {
+ dbg_printk(0, "gpib: can't get IRQ for %s\n", name);
+ return -1;
+ }
+ if (request_threaded_irq(*irq, handler, thread_fn, flags, name, board)) {
+ dbg_printk(0, "gpib: can't request IRQ for %s %d\n", name, *irq);
+ *irq = 0;
+ return -1;
+ }
+ DISABLE_IRQ(*irq);
+ return 0;
+}
+
+static void bb_free_irq(gpib_board_t *board, int *irq, char *name)
+{
+ if (*irq) {
+ free_irq(*irq, board);
+ dbg_printk(2, "IRQ %d(%s) freed\n", *irq, name);
+ *irq = 0;
+ }
+}
+
+static void release_gpios(void)
+{
+ int j;
+
+ for (j = 0 ; j < NUM_PINS ; j++) {
+ if (all_descriptors[j]) {
+ gpiod_put(all_descriptors[j]);
+ all_descriptors[j] = 0;
+ }
+ }
+}
+
+static int allocate_gpios(gpib_board_t *board)
+{
+ int j, retval = 0;
+ bool error = false;
+ int table_index = 0;
+ char name[256];
+ struct gpio_desc *desc;
+ struct gpiod_lookup_table *lookup_table;
+
+ if (!board->gpib_dev) {
+ pr_err("NULL gpib dev for board\n");
+ return -ENOENT;
+ }
+
+ lookup_table = lookup_tables[0];
+ lookup_table->dev_id = dev_name(board->gpib_dev);
+ gpiod_add_lookup_table(lookup_table);
+ dbg_printk(1, "Allocating gpios using table index %d\n", table_index);
+
+ for (j = 0 ; j < NUM_PINS ; j++) {
+ if (gpios_vector[j] < 0)
+ continue;
+ /* name not really used in gpiod_get_index() */
+ sprintf(name, "GPIO%d", gpios_vector[j]);
+try_again:
+ dbg_printk(1, "Allocating gpio %s pin no %d\n", name, gpios_vector[j]);
+ desc = gpiod_get_index(board->gpib_dev, name, gpios_vector[j], GPIOD_IN);
+
+ if (IS_ERR(desc)) {
+ gpiod_remove_lookup_table(lookup_table);
+ table_index++;
+ lookup_table = lookup_tables[table_index];
+ if (lookup_table) {
+ dbg_printk(1, "Allocation failed, now using table_index %d\n",
+ table_index);
+ lookup_table->dev_id = dev_name(board->gpib_dev);
+ gpiod_add_lookup_table(lookup_table);
+ goto try_again;
+ }
+ dbg_printk(0, "Unable to obtain gpio descriptor for pin %d error %ld\n",
+ gpios_vector[j], PTR_ERR(desc));
+ error = true;
+ break;
+ }
+ all_descriptors[j] = desc;
+ }
+
+ if (error) { /* undo what already done */
+ release_gpios();
+ retval = -1;
+ }
+ if (lookup_table)
+ gpiod_remove_lookup_table(lookup_table);
+ // Initialize LED trigger
+ led_trigger_register_simple("gpib", &ledtrig_gpib);
+ return retval;
+}
+
+static void bb_detach(gpib_board_t *board)
+{
+ struct bb_priv *priv = board->private_data;
+
+ dbg_printk(2, "Enter with data %p\n", board->private_data);
+ if (!board->private_data)
+ return;
+
+ led_trigger_unregister_simple(ledtrig_gpib);
+
+ bb_free_irq(board, &priv->irq_DAV, NAME "_DAV");
+ bb_free_irq(board, &priv->irq_NRFD, NAME "_NRFD");
+ bb_free_irq(board, &priv->irq_NDAC, NAME "_NDAC");
+ bb_free_irq(board, &priv->irq_SRQ, NAME "_SRQ");
+
+ if (strcmp(PINMAP_2, pin_map) == 0) { /* YOGA */
+ gpiod_set_value(YOGA_ENABLE, 0);
+ }
+
+ release_gpios();
+
+ dbg_printk(2, "detached board: %d\n", board->minor);
+ dbg_printk(0, "NRFD: idle %d, seq %d, NDAC: idle %d, seq %d DAV: idle %d seq: %d all: %ld",
+ priv->nrfd_idle, priv->nrfd_seq,
+ priv->ndac_idle, priv->ndac_seq,
+ priv->dav_idle, priv->dav_seq, priv->all_irqs);
+
+ free_private(board);
+}
+
+static int bb_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct bb_priv *priv;
+ int retval = 0;
+
+ dbg_printk(2, "%s\n", "Enter ...");
+
+ board->status = 0;
+
+ if (allocate_private(board))
+ return -ENOMEM;
+ priv = board->private_data;
+ priv->direction = -1;
+ priv->t1_delay = 2000;
+ priv->listener_state = listener_idle;
+ priv->talker_state = talker_idle;
+
+ sn7516x = sn7516x_used;
+ if (strcmp(PINMAP_0, pin_map) == 0) {
+ if (!sn7516x) {
+ gpios_vector[&(PE) - &all_descriptors[0]] = -1;
+ gpios_vector[&(DC) - &all_descriptors[0]] = -1;
+ gpios_vector[&(TE) - &all_descriptors[0]] = -1;
+ }
+ } else if (strcmp(PINMAP_1, pin_map) == 0) {
+ if (!sn7516x) {
+ gpios_vector[&(PE) - &all_descriptors[0]] = -1;
+ gpios_vector[&(DC) - &all_descriptors[0]] = -1;
+ gpios_vector[&(TE) - &all_descriptors[0]] = -1;
+ }
+ gpios_vector[&(REN) - &all_descriptors[0]] = 0; /* 27 -> 0 REN on GPIB pin 0 */
+ } else if (strcmp(PINMAP_2, pin_map) == 0) { /* YOGA */
+ sn7516x = 0;
+ gpios_vector[&(D03) - &all_descriptors[0]] = YOGA_D03_pin_nr;
+ gpios_vector[&(D04) - &all_descriptors[0]] = YOGA_D04_pin_nr;
+ gpios_vector[&(D05) - &all_descriptors[0]] = YOGA_D05_pin_nr;
+ gpios_vector[&(D06) - &all_descriptors[0]] = YOGA_D06_pin_nr;
+ gpios_vector[&(PE) - &all_descriptors[0]] = -1;
+ gpios_vector[&(DC) - &all_descriptors[0]] = -1;
+ gpios_vector[&(ACT_LED) - &all_descriptors[0]] = -1;
+ } else {
+ dbg_printk(0, "Unrecognized pin mapping.\n");
+ goto bb_attach_fail;
+ }
+ dbg_printk(0, "Using pin map \"%s\" %s\n", pin_map, (sn7516x) ?
+ " with SN7516x driver support" : "");
+
+ if (allocate_gpios(board))
+ goto bb_attach_fail;
+
+/* Configure SN7516X control lines.
+ * drive ATN, IFC and REN as outputs only when master
+ * i.e. system controller. In this mode can only be the CIC
+ * When not master then enable device mode ATN, IFC & REN as inputs
+ */
+ if (sn7516x) {
+ gpiod_direction_output(DC, 0);
+ gpiod_direction_output(TE, 1);
+ gpiod_direction_output(PE, 1);
+ }
+
+ if (strcmp(PINMAP_2, pin_map) == 0) { /* YOGA: enable level shifters */
+ gpiod_direction_output(YOGA_ENABLE, 1);
+ }
+
+ spin_lock_init(&priv->rw_lock);
+
+ /* request DAV interrupt for read */
+ if (bb_get_irq(board, NAME "_DAV", DAV, &priv->irq_DAV, bb_DAV_interrupt, NULL,
+ IRQF_TRIGGER_NONE))
+ goto bb_attach_fail_r;
+
+ /* request NRFD interrupt for write */
+ if (bb_get_irq(board, NAME "_NRFD", NRFD, &priv->irq_NRFD, bb_NRFD_interrupt, NULL,
+ IRQF_TRIGGER_NONE))
+ goto bb_attach_fail_r;
+
+ /* request NDAC interrupt for write */
+ if (bb_get_irq(board, NAME "_NDAC", NDAC, &priv->irq_NDAC, bb_NDAC_interrupt, NULL,
+ IRQF_TRIGGER_NONE))
+ goto bb_attach_fail_r;
+
+ /* request SRQ interrupt for Service Request */
+ if (bb_get_irq(board, NAME "_SRQ", SRQ, &priv->irq_SRQ, bb_SRQ_interrupt, NULL,
+ IRQF_TRIGGER_NONE))
+ goto bb_attach_fail_r;
+
+ ENABLE_IRQ(priv->irq_SRQ, IRQ_TYPE_EDGE_FALLING);
+
+ dbg_printk(0, "attached board %d\n", board->minor);
+ goto bb_attach_out;
+
+bb_attach_fail_r:
+ release_gpios();
+bb_attach_fail:
+ retval = -1;
+bb_attach_out:
+ return retval;
+}
+
+gpib_interface_t bb_interface = {
+name: NAME,
+attach : bb_attach,
+detach : bb_detach,
+read : bb_read,
+write : bb_write,
+command : bb_command,
+take_control : bb_take_control,
+go_to_standby : bb_go_to_standby,
+request_system_control : bb_request_system_control,
+interface_clear : bb_interface_clear,
+remote_enable : bb_remote_enable,
+enable_eos : bb_enable_eos,
+disable_eos : bb_disable_eos,
+parallel_poll : bb_parallel_poll,
+parallel_poll_configure : bb_parallel_poll_configure,
+parallel_poll_response : bb_parallel_poll_response,
+line_status : bb_line_status,
+update_status : bb_update_status,
+primary_address : bb_primary_address,
+secondary_address : bb_secondary_address,
+serial_poll_response : bb_serial_poll_response,
+serial_poll_status : bb_serial_poll_status,
+t1_delay : bb_t1_delay,
+return_to_local : bb_return_to_local,
+};
+
+static int __init bb_init_module(void)
+{
+ gpib_register_driver(&bb_interface, THIS_MODULE);
+
+ dbg_printk(0, "module loaded with pin map \"%s\"%s\n",
+ pin_map, (sn7516x_used) ? " and SN7516x driver support" : "");
+ return 0;
+}
+
+static void __exit bb_exit_module(void)
+{
+ dbg_printk(0, "module unloaded!");
+
+ gpib_unregister_driver(&bb_interface);
+}
+
+module_init(bb_init_module);
+module_exit(bb_exit_module);
+
+/***************************************************************************
+ * *
+ * UTILITY Functions *
+ * *
+ ***************************************************************************/
+inline long usec_diff(struct timespec64 *a, struct timespec64 *b)
+{
+ return ((a->tv_sec - b->tv_sec) * 1000000 +
+ (a->tv_nsec - b->tv_nsec) / 1000);
+}
+
+static inline int check_for_eos(struct bb_priv *priv, uint8_t byte)
+{
+ if (priv->eos_check)
+ return 0;
+
+ if (priv->eos_check_8) {
+ if (priv->eos == byte)
+ return 1;
+ } else {
+ if (priv->eos_mask_7 == (byte & 0x7f))
+ return 1;
+ }
+ return 0;
+}
+
+static void set_data_lines_output(void)
+{
+ gpiod_direction_output(D01, 1);
+ gpiod_direction_output(D02, 1);
+ gpiod_direction_output(D03, 1);
+ gpiod_direction_output(D04, 1);
+ gpiod_direction_output(D05, 1);
+ gpiod_direction_output(D06, 1);
+ gpiod_direction_output(D07, 1);
+ gpiod_direction_output(D08, 1);
+}
+
+static void set_data_lines(u8 byte)
+{
+ gpiod_set_value(D01, !(byte & 0x01));
+ gpiod_set_value(D02, !(byte & 0x02));
+ gpiod_set_value(D03, !(byte & 0x04));
+ gpiod_set_value(D04, !(byte & 0x08));
+ gpiod_set_value(D05, !(byte & 0x10));
+ gpiod_set_value(D06, !(byte & 0x20));
+ gpiod_set_value(D07, !(byte & 0x40));
+ gpiod_set_value(D08, !(byte & 0x80));
+}
+
+static u8 get_data_lines(void)
+{
+ u8 ret;
+
+ ret = gpiod_get_value(D01);
+ ret |= gpiod_get_value(D02) << 1;
+ ret |= gpiod_get_value(D03) << 2;
+ ret |= gpiod_get_value(D04) << 3;
+ ret |= gpiod_get_value(D05) << 4;
+ ret |= gpiod_get_value(D06) << 5;
+ ret |= gpiod_get_value(D07) << 6;
+ ret |= gpiod_get_value(D08) << 7;
+ return ~ret;
+}
+
+static void set_data_lines_input(void)
+{
+ gpiod_direction_input(D01);
+ gpiod_direction_input(D02);
+ gpiod_direction_input(D03);
+ gpiod_direction_input(D04);
+ gpiod_direction_input(D05);
+ gpiod_direction_input(D06);
+ gpiod_direction_input(D07);
+ gpiod_direction_input(D08);
+}
+
+static inline void SET_DIR_WRITE(struct bb_priv *priv)
+{
+ if (priv->direction == DIR_WRITE)
+ return;
+
+ gpiod_direction_input(NRFD);
+ gpiod_direction_input(NDAC);
+ set_data_lines_output();
+ gpiod_direction_output(DAV, 1);
+ gpiod_direction_output(EOI, 1);
+
+ if (sn7516x) {
+ gpiod_set_value(PE, 1); /* set data lines to transmit on sn75160b */
+ gpiod_set_value(TE, 1); /* set NDAC and NRFD to receive and DAV to transmit */
+ }
+
+ priv->direction = DIR_WRITE;
+}
+
+static inline void SET_DIR_READ(struct bb_priv *priv)
+{
+ if (priv->direction == DIR_READ)
+ return;
+
+ gpiod_direction_input(DAV);
+ gpiod_direction_input(EOI);
+
+ set_data_lines_input();
+
+ if (sn7516x) {
+ gpiod_set_value(PE, 0); /* set data lines to receive on sn75160b */
+ gpiod_set_value(TE, 0); /* set NDAC and NRFD to transmit and DAV to receive */
+ }
+
+ gpiod_direction_output(NRFD, 0); // hold off the talker
+ gpiod_direction_output(NDAC, 0); // data not accepted
+
+ priv->direction = DIR_READ;
+}
diff --git a/drivers/staging/gpib/hp_82335/Makefile b/drivers/staging/gpib/hp_82335/Makefile
new file mode 100644
index 000000000000..8b7a552e9355
--- /dev/null
+++ b/drivers/staging/gpib/hp_82335/Makefile
@@ -0,0 +1,4 @@
+
+obj-m += hp82335.o
+
+
diff --git a/drivers/staging/gpib/hp_82335/hp82335.c b/drivers/staging/gpib/hp_82335/hp82335.c
new file mode 100644
index 000000000000..40afe42aea47
--- /dev/null
+++ b/drivers/staging/gpib/hp_82335/hp82335.c
@@ -0,0 +1,360 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess *
+ ***************************************************************************/
+
+/*should enable ATN interrupts (and update board->status on occurrence),
+ * implement recovery from bus errors (if necessary)
+ */
+
+#include "hp82335.h"
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for HP 82335 interface cards");
+
+static int hp82335_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void hp82335_detach(gpib_board_t *board);
+
+// wrappers for interface functions
+int hp82335_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read);
+}
+
+int hp82335_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int hp82335_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written);
+}
+
+int hp82335_take_control(gpib_board_t *board, int synchronous)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_take_control(board, &priv->tms9914_priv, synchronous);
+}
+
+int hp82335_go_to_standby(gpib_board_t *board)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_go_to_standby(board, &priv->tms9914_priv);
+}
+
+void hp82335_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_request_system_control(board, &priv->tms9914_priv, request_control);
+}
+
+void hp82335_interface_clear(gpib_board_t *board, int assert)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_interface_clear(board, &priv->tms9914_priv, assert);
+}
+
+void hp82335_remote_enable(gpib_board_t *board, int enable)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_remote_enable(board, &priv->tms9914_priv, enable);
+}
+
+int hp82335_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits);
+}
+
+void hp82335_disable_eos(gpib_board_t *board)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_disable_eos(board, &priv->tms9914_priv);
+}
+
+unsigned int hp82335_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_update_status(board, &priv->tms9914_priv, clear_mask);
+}
+
+int hp82335_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_primary_address(board, &priv->tms9914_priv, address);
+}
+
+int hp82335_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable);
+}
+
+int hp82335_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_parallel_poll(board, &priv->tms9914_priv, result);
+}
+
+void hp82335_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config);
+}
+
+void hp82335_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist);
+}
+
+void hp82335_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_serial_poll_response(board, &priv->tms9914_priv, status);
+}
+
+static uint8_t hp82335_serial_poll_status(gpib_board_t *board)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_serial_poll_status(board, &priv->tms9914_priv);
+}
+
+static int hp82335_line_status(const gpib_board_t *board)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_line_status(board, &priv->tms9914_priv);
+}
+
+static unsigned int hp82335_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_t1_delay(board, &priv->tms9914_priv, nano_sec);
+}
+
+void hp82335_return_to_local(gpib_board_t *board)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_return_to_local(board, &priv->tms9914_priv);
+}
+
+gpib_interface_t hp82335_interface = {
+name: "hp82335",
+attach : hp82335_attach,
+detach : hp82335_detach,
+read : hp82335_read,
+write : hp82335_write,
+command : hp82335_command,
+request_system_control : hp82335_request_system_control,
+take_control : hp82335_take_control,
+go_to_standby : hp82335_go_to_standby,
+interface_clear : hp82335_interface_clear,
+remote_enable : hp82335_remote_enable,
+enable_eos : hp82335_enable_eos,
+disable_eos : hp82335_disable_eos,
+parallel_poll : hp82335_parallel_poll,
+parallel_poll_configure : hp82335_parallel_poll_configure,
+parallel_poll_response : hp82335_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : hp82335_line_status,
+update_status : hp82335_update_status,
+primary_address : hp82335_primary_address,
+secondary_address : hp82335_secondary_address,
+serial_poll_response : hp82335_serial_poll_response,
+serial_poll_status : hp82335_serial_poll_status,
+t1_delay : hp82335_t1_delay,
+return_to_local : hp82335_return_to_local,
+};
+
+int hp82335_allocate_private(gpib_board_t *board)
+{
+ board->private_data = kzalloc(sizeof(struct hp82335_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ return 0;
+}
+
+void hp82335_free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+static inline unsigned int tms9914_to_hp82335_offset(unsigned int register_num)
+{
+ return 0x1ff8 + register_num;
+}
+
+static uint8_t hp82335_read_byte(struct tms9914_priv *priv, unsigned int register_num)
+{
+ return tms9914_iomem_read_byte(priv, tms9914_to_hp82335_offset(register_num));
+}
+
+static void hp82335_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num)
+{
+ tms9914_iomem_write_byte(priv, data, tms9914_to_hp82335_offset(register_num));
+}
+
+static void hp82335_clear_interrupt(struct hp82335_priv *hp_priv)
+{
+ struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv;
+
+ writeb(0, tms_priv->iobase + HPREG_INTR_CLEAR);
+}
+
+int hp82335_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct hp82335_priv *hp_priv;
+ struct tms9914_priv *tms_priv;
+ int retval;
+ const unsigned long upper_iomem_base = (unsigned long)config->ibbase + hp82335_rom_size;
+
+ board->status = 0;
+
+ if (hp82335_allocate_private(board))
+ return -ENOMEM;
+ hp_priv = board->private_data;
+ tms_priv = &hp_priv->tms9914_priv;
+ tms_priv->read_byte = hp82335_read_byte;
+ tms_priv->write_byte = hp82335_write_byte;
+ tms_priv->offset = 1;
+
+ switch ((unsigned long)(config->ibbase)) {
+ case 0xc4000:
+ case 0xc8000:
+ case 0xcc000:
+ case 0xd0000:
+ case 0xd4000:
+ case 0xd8000:
+ case 0xdc000:
+ case 0xe0000:
+ case 0xe4000:
+ case 0xe8000:
+ case 0xec000:
+ case 0xf0000:
+ case 0xf4000:
+ case 0xf8000:
+ case 0xfc000:
+ break;
+ default:
+ pr_err("hp82335: invalid base io address 0x%p\n", config->ibbase);
+ return -EINVAL;
+ }
+ if (!request_mem_region(upper_iomem_base, hp82335_upper_iomem_size, "hp82335")) {
+ pr_err("hp82335: failed to allocate io memory region 0x%lx-0x%lx\n",
+ upper_iomem_base, upper_iomem_base + hp82335_upper_iomem_size - 1);
+ return -EBUSY;
+ }
+ hp_priv->raw_iobase = upper_iomem_base;
+ tms_priv->iobase = ioremap(upper_iomem_base, hp82335_upper_iomem_size);
+ pr_info("hp82335: upper half of 82335 iomem region 0x%lx remapped to 0x%p\n",
+ hp_priv->raw_iobase, tms_priv->iobase);
+
+ retval = request_irq(config->ibirq, hp82335_interrupt, 0, "hp82335", board);
+ if (retval) {
+ pr_err("hp82335: can't request IRQ %d\n", config->ibirq);
+ return retval;
+ }
+ hp_priv->irq = config->ibirq;
+ pr_info("hp82335: IRQ %d\n", config->ibirq);
+
+ tms9914_board_reset(tms_priv);
+
+ hp82335_clear_interrupt(hp_priv);
+
+ writeb(INTR_ENABLE, tms_priv->iobase + HPREG_CCR);
+
+ tms9914_online(board, tms_priv);
+
+ return 0;
+}
+
+void hp82335_detach(gpib_board_t *board)
+{
+ struct hp82335_priv *hp_priv = board->private_data;
+ struct tms9914_priv *tms_priv;
+
+ if (hp_priv) {
+ tms_priv = &hp_priv->tms9914_priv;
+ if (hp_priv->irq)
+ free_irq(hp_priv->irq, board);
+ if (tms_priv->iobase) {
+ writeb(0, tms_priv->iobase + HPREG_CCR);
+ tms9914_board_reset(tms_priv);
+ iounmap((void *)tms_priv->iobase);
+ }
+ if (hp_priv->raw_iobase)
+ release_mem_region(hp_priv->raw_iobase, hp82335_upper_iomem_size);
+ }
+ hp82335_free_private(board);
+}
+
+static int __init hp82335_init_module(void)
+{
+ gpib_register_driver(&hp82335_interface, THIS_MODULE);
+ return 0;
+}
+
+static void __exit hp82335_exit_module(void)
+{
+ gpib_unregister_driver(&hp82335_interface);
+}
+
+module_init(hp82335_init_module);
+module_exit(hp82335_exit_module);
+
+/*
+ * GPIB interrupt service routines
+ */
+
+irqreturn_t hp82335_interrupt(int irq, void *arg)
+{
+ int status1, status2;
+ gpib_board_t *board = arg;
+ struct hp82335_priv *priv = board->private_data;
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ status1 = read_byte(&priv->tms9914_priv, ISR0);
+ status2 = read_byte(&priv->tms9914_priv, ISR1);
+ hp82335_clear_interrupt(priv);
+ retval = tms9914_interrupt_have_status(board, &priv->tms9914_priv, status1, status2);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
diff --git a/drivers/staging/gpib/hp_82335/hp82335.h b/drivers/staging/gpib/hp_82335/hp82335.h
new file mode 100644
index 000000000000..5e5297af731a
--- /dev/null
+++ b/drivers/staging/gpib/hp_82335/hp82335.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess *
+ ***************************************************************************/
+
+#ifndef _HP82335_H
+#define _HP82335_H
+
+#include "tms9914.h"
+#include "gpibP.h"
+
+// struct which defines private_data for board
+struct hp82335_priv {
+ struct tms9914_priv tms9914_priv;
+ unsigned int irq;
+ unsigned long raw_iobase;
+};
+
+// interfaces
+extern gpib_interface_t hp82335_interface;
+
+// interface functions
+int hp82335_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read);
+int hp82335_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+int hp82335_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written);
+int hp82335_take_control(gpib_board_t *board, int synchronous);
+int hp82335_go_to_standby(gpib_board_t *board);
+void hp82335_request_system_control(gpib_board_t *board, int request_control);
+void hp82335_interface_clear(gpib_board_t *board, int assert);
+void hp82335_remote_enable(gpib_board_t *board, int enable);
+int hp82335_enable_eos(gpib_board_t *board, uint8_t eos_byte, int
+ compare_8_bits);
+void hp82335_disable_eos(gpib_board_t *board);
+unsigned int hp82335_update_status(gpib_board_t *board, unsigned int clear_mask);
+int hp82335_primary_address(gpib_board_t *board, unsigned int address);
+int hp82335_secondary_address(gpib_board_t *board, unsigned int address, int
+ enable);
+int hp82335_parallel_poll(gpib_board_t *board, uint8_t *result);
+void hp82335_parallel_poll_configure(gpib_board_t *board, uint8_t config);
+void hp82335_parallel_poll_response(gpib_board_t *board, int ist);
+void hp82335_serial_poll_response(gpib_board_t *board, uint8_t status);
+void hp82335_return_to_local(gpib_board_t *board);
+
+// interrupt service routines
+irqreturn_t hp82335_interrupt(int irq, void *arg);
+
+// utility functions
+int hp82335_allocate_private(gpib_board_t *board);
+void hp82335_free_private(gpib_board_t *board);
+
+// size of io memory region used
+static const int hp82335_rom_size = 0x2000;
+static const int hp82335_upper_iomem_size = 0x2000;
+
+// hp82335 register offsets
+enum hp_read_regs {
+ HPREG_CSR = 0x17f8,
+ HPREG_STATUS = 0x1ffc,
+};
+
+enum hp_write_regs {
+ HPREG_INTR_CLEAR = 0x17f7,
+ HPREG_CCR = HPREG_CSR,
+};
+
+enum ccr_bits {
+ DMA_ENABLE = (1 << 0), /* DMA enable */
+ DMA_CHAN_SELECT = (1 << 1), /* DMA channel select O=3,1=2 */
+ INTR_ENABLE = (1 << 2), /* interrupt enable */
+ SYS_DISABLE = (1 << 3), /* system controller disable */
+};
+
+enum csr_bits {
+ SWITCH6 = (1 << 0), /* switch 6 position */
+ SWITCH5 = (1 << 1), /* switch 5 position */
+ SYS_CONTROLLER = (1 << 2), /* system controller bit */
+ DMA_ENABLE_STATUS = (1 << 4), /* DMA enabled */
+ DMA_CHAN_STATUS = (1 << 5), /* DMA channel 0=3,1=2 */
+ INTR_ENABLE_STATUS = (1 << 6), /* Interrupt enable */
+ INTR_PENDING = (1 << 7), /* Interrupt Pending */
+};
+
+#endif // _HP82335_H
diff --git a/drivers/staging/gpib/hp_82341/Makefile b/drivers/staging/gpib/hp_82341/Makefile
new file mode 100644
index 000000000000..1fe7db4f8ca4
--- /dev/null
+++ b/drivers/staging/gpib/hp_82341/Makefile
@@ -0,0 +1,2 @@
+
+obj-m += hp_82341.o
diff --git a/drivers/staging/gpib/hp_82341/hp_82341.c b/drivers/staging/gpib/hp_82341/hp_82341.c
new file mode 100644
index 000000000000..8ad1c885a9fb
--- /dev/null
+++ b/drivers/staging/gpib/hp_82341/hp_82341.c
@@ -0,0 +1,895 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * Driver for hp 82341a/b/c/d boards. *
+ * Might be worth merging with Agilent 82350b driver. *
+ * copyright : (C) 2002, 2005 by Frank Mori Hess *
+ ***************************************************************************/
+
+#include "hp_82341.h"
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/isapnp.h>
+
+MODULE_LICENSE("GPL");
+
+int hp_82341_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read)
+{
+ struct hp_82341_priv *hp_priv = board->private_data;
+ struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv;
+ int retval = 0;
+ unsigned short event_status;
+ int i;
+ int num_fifo_bytes;
+ //hardware doesn't support checking for end-of-string character when using fifo
+ if (tms_priv->eos_flags & REOS)
+ return tms9914_read(board, tms_priv, buffer, length, end, bytes_read);
+
+ clear_bit(DEV_CLEAR_BN, &tms_priv->state);
+
+ read_and_clear_event_status(board);
+ *end = 0;
+ *bytes_read = 0;
+ if (length == 0)
+ return 0;
+ //disable fifo for the moment
+ outb(DIRECTION_GPIB_TO_HOST_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG);
+ // Handle corner case of board not in holdoff and one byte has slipped in already.
+ // Also, board sometimes has problems (spurious 1 byte reads) when read fifo is
+ // started up with board in
+ // TACS under certain data holdoff conditions. Doing a 1 byte tms9914-style
+ // read avoids these problems.
+ if (/*tms_priv->holdoff_active == 0 && */length > 1) {
+ size_t num_bytes;
+
+ retval = tms9914_read(board, tms_priv, buffer, 1, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ pr_err("tms9914_read failed retval=%i\n", retval);
+ if (retval < 0 || *end)
+ return retval;
+ ++buffer;
+ --length;
+ }
+ tms9914_set_holdoff_mode(tms_priv, TMS9914_HOLDOFF_EOI);
+ tms9914_release_holdoff(tms_priv);
+ outb(0x00, hp_priv->iobase[3] + BUFFER_FLUSH_REG);
+ i = 0;
+ num_fifo_bytes = length - 1;
+ while (i < num_fifo_bytes && *end == 0) {
+ int block_size;
+ int j;
+ int count;
+
+ if (num_fifo_bytes - i < hp_82341_fifo_size)
+ block_size = num_fifo_bytes - i;
+ else
+ block_size = hp_82341_fifo_size;
+ set_transfer_counter(hp_priv, block_size);
+ outb(ENABLE_TI_BUFFER_BIT | DIRECTION_GPIB_TO_HOST_BIT, hp_priv->iobase[3] +
+ BUFFER_CONTROL_REG);
+ if (inb(hp_priv->iobase[0] + STREAM_STATUS_REG) & HALTED_STATUS_BIT)
+ outb(RESTART_STREAM_BIT, hp_priv->iobase[0] + STREAM_STATUS_REG);
+
+ clear_bit(READ_READY_BN, &tms_priv->state);
+
+ retval = wait_event_interruptible(board->wait,
+ ((event_status =
+ read_and_clear_event_status(board)) &
+ (TERMINAL_COUNT_EVENT_BIT |
+ BUFFER_END_EVENT_BIT)) ||
+ test_bit(DEV_CLEAR_BN, &tms_priv->state) ||
+ test_bit(TIMO_NUM, &board->status));
+ if (retval) {
+ pr_warn("%s: read wait interrupted\n", __func__);
+ retval = -ERESTARTSYS;
+ break;
+ }
+ // have to disable buffer before we can read from buffer port
+ outb(DIRECTION_GPIB_TO_HOST_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG);
+ count = block_size - read_transfer_counter(hp_priv);
+ j = 0;
+ while (j < count && i < num_fifo_bytes) {
+ unsigned short data_word = inw(hp_priv->iobase[3] + BUFFER_PORT_LOW_REG);
+
+ buffer[i++] = data_word & 0xff;
+ ++j;
+ if (j < count && i < num_fifo_bytes) {
+ buffer[i++] = (data_word >> 8) & 0xff;
+ ++j;
+ }
+ }
+ if (event_status & BUFFER_END_EVENT_BIT) {
+ clear_bit(RECEIVED_END_BN, &tms_priv->state);
+
+ *end = 1;
+ tms_priv->holdoff_active = 1;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ pr_debug("%s: minor %i: read timed out\n", __FILE__, board->minor);
+ retval = -ETIMEDOUT;
+ break;
+ }
+ if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) {
+ pr_warn("%s: device clear interrupted read\n", __FILE__);
+ retval = -EINTR;
+ break;
+ }
+ }
+ *bytes_read += i;
+ buffer += i;
+ length -= i;
+ if (retval < 0)
+ return retval;
+ // read last byte if we havn't received an END yet
+ if (*end == 0) {
+ size_t num_bytes;
+ // try to make sure we holdoff after last byte read
+ retval = tms9914_read(board, tms_priv, buffer, length, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+
+static int restart_write_fifo(gpib_board_t *board, struct hp_82341_priv *hp_priv)
+{
+ struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv;
+
+ if ((inb(hp_priv->iobase[0] + STREAM_STATUS_REG) & HALTED_STATUS_BIT) == 0)
+ return 0;
+ while (1) {
+ int status;
+
+ //restart doesn't work if data holdoff is in effect
+ status = tms9914_line_status(board, tms_priv);
+ if ((status & BusNRFD) == 0) {
+ outb(RESTART_STREAM_BIT, hp_priv->iobase[0] + STREAM_STATUS_REG);
+ return 0;
+ }
+ if (test_bit(DEV_CLEAR_BN, &tms_priv->state))
+ return -EINTR;
+ if (test_bit(TIMO_NUM, &board->status))
+ return -ETIMEDOUT;
+ if (msleep_interruptible(1))
+ return -EINTR;
+ }
+ return 0;
+}
+
+int hp_82341_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ struct hp_82341_priv *hp_priv = board->private_data;
+ struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv;
+ int i, j;
+ unsigned short event_status;
+ int retval = 0;
+ int fifo_xfer_len = length;
+
+ *bytes_written = 0;
+ if (send_eoi)
+ --fifo_xfer_len;
+
+ clear_bit(DEV_CLEAR_BN, &tms_priv->state);
+
+ read_and_clear_event_status(board);
+ outb(0, hp_priv->iobase[3] + BUFFER_CONTROL_REG);
+ outb(0x00, hp_priv->iobase[3] + BUFFER_FLUSH_REG);
+ for (i = 0; i < fifo_xfer_len;) {
+ int block_size;
+
+ if (fifo_xfer_len - i < hp_82341_fifo_size)
+ block_size = fifo_xfer_len - i;
+ else
+ block_size = hp_82341_fifo_size;
+ set_transfer_counter(hp_priv, block_size);
+ // load data into board's fifo
+ for (j = 0; j < block_size;) {
+ unsigned short data_word = buffer[i++];
+ ++j;
+ if (j < block_size) {
+ data_word |= buffer[i++] << 8;
+ ++j;
+ }
+ outw(data_word, hp_priv->iobase[3] + BUFFER_PORT_LOW_REG);
+ }
+ clear_bit(WRITE_READY_BN, &tms_priv->state);
+ outb(ENABLE_TI_BUFFER_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG);
+ retval = restart_write_fifo(board, hp_priv);
+ if (retval < 0) {
+ pr_err("hp82341: failed to restart write stream\n");
+ break;
+ }
+ retval = wait_event_interruptible(board->wait,
+ ((event_status =
+ read_and_clear_event_status(board)) &
+ TERMINAL_COUNT_EVENT_BIT) ||
+ test_bit(DEV_CLEAR_BN, &tms_priv->state) ||
+ test_bit(TIMO_NUM, &board->status));
+ outb(0, hp_priv->iobase[3] + BUFFER_CONTROL_REG);
+ *bytes_written += block_size - read_transfer_counter(hp_priv);
+ if (retval) {
+ pr_warn("%s: write wait interrupted\n", __FILE__);
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ pr_debug("%s: minor %i: write timed out\n", __FILE__, board->minor);
+ retval = -ETIMEDOUT;
+ break;
+ }
+ if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) {
+ pr_warn("%s: device clear interrupted write\n", __FILE__);
+ retval = -EINTR;
+ break;
+ }
+ }
+ if (retval)
+ return retval;
+ if (send_eoi) {
+ size_t num_bytes;
+
+ retval = hp_82341_write(board, buffer + fifo_xfer_len, 1, 1, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+
+static int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void hp_82341_detach(gpib_board_t *board);
+
+// wrappers for interface functions
+int hp_82341_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read);
+}
+
+int hp_82341_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int hp_82341_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written);
+}
+
+int hp_82341_take_control(gpib_board_t *board, int synchronous)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_take_control(board, &priv->tms9914_priv, synchronous);
+}
+
+int hp_82341_go_to_standby(gpib_board_t *board)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_go_to_standby(board, &priv->tms9914_priv);
+}
+
+void hp_82341_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ if (request_control)
+ priv->mode_control_bits |= SYSTEM_CONTROLLER_BIT;
+ else
+ priv->mode_control_bits &= ~SYSTEM_CONTROLLER_BIT;
+ outb(priv->mode_control_bits, priv->iobase[0] + MODE_CONTROL_STATUS_REG);
+ tms9914_request_system_control(board, &priv->tms9914_priv, request_control);
+}
+
+void hp_82341_interface_clear(gpib_board_t *board, int assert)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_interface_clear(board, &priv->tms9914_priv, assert);
+}
+
+void hp_82341_remote_enable(gpib_board_t *board, int enable)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_remote_enable(board, &priv->tms9914_priv, enable);
+}
+
+int hp_82341_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits);
+}
+
+void hp_82341_disable_eos(gpib_board_t *board)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_disable_eos(board, &priv->tms9914_priv);
+}
+
+unsigned int hp_82341_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_update_status(board, &priv->tms9914_priv, clear_mask);
+}
+
+int hp_82341_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_primary_address(board, &priv->tms9914_priv, address);
+}
+
+int hp_82341_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable);
+}
+
+int hp_82341_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_parallel_poll(board, &priv->tms9914_priv, result);
+}
+
+void hp_82341_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config);
+}
+
+void hp_82341_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist);
+}
+
+void hp_82341_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_serial_poll_response(board, &priv->tms9914_priv, status);
+}
+
+static uint8_t hp_82341_serial_poll_status(gpib_board_t *board)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_serial_poll_status(board, &priv->tms9914_priv);
+}
+
+static int hp_82341_line_status(const gpib_board_t *board)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_line_status(board, &priv->tms9914_priv);
+}
+
+static unsigned int hp_82341_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_t1_delay(board, &priv->tms9914_priv, nano_sec);
+}
+
+void hp_82341_return_to_local(gpib_board_t *board)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_return_to_local(board, &priv->tms9914_priv);
+}
+
+gpib_interface_t hp_82341_unaccel_interface = {
+name: "hp_82341_unaccel",
+attach : hp_82341_attach,
+detach : hp_82341_detach,
+read : hp_82341_read,
+write : hp_82341_write,
+command : hp_82341_command,
+request_system_control : hp_82341_request_system_control,
+take_control : hp_82341_take_control,
+go_to_standby : hp_82341_go_to_standby,
+interface_clear : hp_82341_interface_clear,
+remote_enable : hp_82341_remote_enable,
+enable_eos : hp_82341_enable_eos,
+disable_eos : hp_82341_disable_eos,
+parallel_poll : hp_82341_parallel_poll,
+parallel_poll_configure : hp_82341_parallel_poll_configure,
+parallel_poll_response : hp_82341_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : hp_82341_line_status,
+update_status : hp_82341_update_status,
+primary_address : hp_82341_primary_address,
+secondary_address : hp_82341_secondary_address,
+serial_poll_response : hp_82341_serial_poll_response,
+serial_poll_status : hp_82341_serial_poll_status,
+t1_delay : hp_82341_t1_delay,
+return_to_local : hp_82341_return_to_local,
+};
+
+gpib_interface_t hp_82341_interface = {
+name: "hp_82341",
+attach : hp_82341_attach,
+detach : hp_82341_detach,
+read : hp_82341_accel_read,
+write : hp_82341_accel_write,
+command : hp_82341_command,
+request_system_control : hp_82341_request_system_control,
+take_control : hp_82341_take_control,
+go_to_standby : hp_82341_go_to_standby,
+interface_clear : hp_82341_interface_clear,
+remote_enable : hp_82341_remote_enable,
+enable_eos : hp_82341_enable_eos,
+disable_eos : hp_82341_disable_eos,
+parallel_poll : hp_82341_parallel_poll,
+parallel_poll_configure : hp_82341_parallel_poll_configure,
+parallel_poll_response : hp_82341_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : hp_82341_line_status,
+update_status : hp_82341_update_status,
+primary_address : hp_82341_primary_address,
+secondary_address : hp_82341_secondary_address,
+serial_poll_response : hp_82341_serial_poll_response,
+t1_delay : hp_82341_t1_delay,
+return_to_local : hp_82341_return_to_local,
+};
+
+int hp_82341_allocate_private(gpib_board_t *board)
+{
+ board->private_data = kzalloc(sizeof(struct hp_82341_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+ return 0;
+}
+
+void hp_82341_free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+static uint8_t hp_82341_read_byte(struct tms9914_priv *priv, unsigned int register_num)
+{
+ return inb((unsigned long)(priv->iobase) + register_num);
+}
+
+static void hp_82341_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num)
+{
+ outb(data, (unsigned long)(priv->iobase) + register_num);
+}
+
+static int hp_82341_find_isapnp_board(struct pnp_dev **dev)
+{
+ *dev = pnp_find_dev(NULL, ISAPNP_VENDOR('H', 'W', 'P'),
+ ISAPNP_FUNCTION(0x1411), NULL);
+ if (!*dev || !(*dev)->card) {
+ pr_err("hp_82341: failed to find isapnp board\n");
+ return -ENODEV;
+ }
+ if (pnp_device_attach(*dev) < 0) {
+ pr_err("hp_82341: board already active, skipping\n");
+ return -EBUSY;
+ }
+ if (pnp_activate_dev(*dev) < 0) {
+ pnp_device_detach(*dev);
+ pr_err("hp_82341: failed to activate() atgpib/tnt, aborting\n");
+ return -EAGAIN;
+ }
+ if (!pnp_port_valid(*dev, 0) || !pnp_irq_valid(*dev, 0)) {
+ pnp_device_detach(*dev);
+ pr_err("hp_82341: invalid port or irq for atgpib/tnt, aborting\n");
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int xilinx_ready(struct hp_82341_priv *hp_priv)
+{
+ switch (hp_priv->hw_version) {
+ case HW_VERSION_82341C:
+ if (inb(hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG) & XILINX_READY_BIT)
+ return 1;
+ else
+ return 0;
+ break;
+ case HW_VERSION_82341D:
+ if (isapnp_read_byte(PIO_DATA_REG) & HP_82341D_XILINX_READY_BIT)
+ return 1;
+ else
+ return 0;
+ default:
+ pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__);
+ break;
+ }
+ return 0;
+}
+
+static int xilinx_done(struct hp_82341_priv *hp_priv)
+{
+ switch (hp_priv->hw_version) {
+ case HW_VERSION_82341C:
+ if (inb(hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG) & DONE_PGL_BIT)
+ return 1;
+ else
+ return 0;
+ case HW_VERSION_82341D:
+ if (isapnp_read_byte(PIO_DATA_REG) & HP_82341D_XILINX_DONE_BIT)
+ return 1;
+ else
+ return 0;
+ default:
+ pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__);
+ break;
+ }
+ return 0;
+}
+
+static int irq_valid(struct hp_82341_priv *hp_priv, int irq)
+{
+ switch (hp_priv->hw_version) {
+ case HW_VERSION_82341C:
+ switch (irq) {
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ return 1;
+ default:
+ pr_err("hp_82341: invalid irq=%i for 82341C, irq must be 3, 5, 7, 9, 10, 11, 12, or 15.\n",
+ irq);
+ return 0;
+ }
+ break;
+ case HW_VERSION_82341D:
+ return 1;
+ default:
+ pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__);
+ break;
+ }
+ return 0;
+}
+
+static int hp_82341_load_firmware_array(struct hp_82341_priv *hp_priv,
+ const unsigned char *firmware_data,
+ unsigned int firmware_length)
+{
+ int i, j;
+ static const int timeout = 100;
+
+ for (i = 0; i < firmware_length; ++i) {
+ for (j = 0; j < timeout; ++j) {
+ if (need_resched())
+ schedule();
+ if (xilinx_ready(hp_priv))
+ break;
+ usleep_range(10, 15);
+ }
+ if (j == timeout) {
+ pr_err("hp_82341: timed out waiting for Xilinx ready.\n");
+ return -ETIMEDOUT;
+ }
+ outb(firmware_data[i], hp_priv->iobase[0] + XILINX_DATA_REG);
+ }
+ for (j = 0; j < timeout; ++j) {
+ if (xilinx_done(hp_priv))
+ break;
+ if (need_resched())
+ schedule();
+ usleep_range(10, 15);
+ }
+ if (j == timeout) {
+ pr_err("hp_82341: timed out waiting for Xilinx done.\n");
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+static int hp_82341_load_firmware(struct hp_82341_priv *hp_priv, const gpib_board_config_t *config)
+{
+ if (config->init_data_length == 0) {
+ if (xilinx_done(hp_priv))
+ return 0;
+ pr_err("hp_82341: board needs be initialized with firmware upload.\n"
+ "\tUse the --init-data option of gpib_config.\n");
+ return -EINVAL;
+ }
+ switch (hp_priv->hw_version) {
+ case HW_VERSION_82341C:
+ if (config->init_data_length != hp_82341c_firmware_length) {
+ pr_err("hp_82341: bad firmware length=%i for 82341c (expected %i).\n",
+ config->init_data_length, hp_82341c_firmware_length);
+ return -EINVAL;
+ }
+ break;
+ case HW_VERSION_82341D:
+ if (config->init_data_length != hp_82341d_firmware_length) {
+ pr_err("hp_82341: bad firmware length=%i for 82341d (expected %i).\n",
+ config->init_data_length, hp_82341d_firmware_length);
+ return -EINVAL;
+ }
+ break;
+ default:
+ pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__);
+ break;
+ }
+ return hp_82341_load_firmware_array(hp_priv, config->init_data, config->init_data_length);
+}
+
+static void set_xilinx_not_prog(struct hp_82341_priv *hp_priv, int assert)
+{
+ switch (hp_priv->hw_version) {
+ case HW_VERSION_82341C:
+ if (assert)
+ hp_priv->config_control_bits |= DONE_PGL_BIT;
+ else
+ hp_priv->config_control_bits &= ~DONE_PGL_BIT;
+ outb(hp_priv->config_control_bits, hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG);
+ break;
+ case HW_VERSION_82341D:
+ if (assert)
+ isapnp_write_byte(PIO_DATA_REG, HP_82341D_NOT_PROG_BIT);
+ else
+ isapnp_write_byte(PIO_DATA_REG, 0x0);
+ break;
+ default:
+ break;
+ }
+}
+
+// clear xilinx firmware
+static int clear_xilinx(struct hp_82341_priv *hp_priv)
+{
+ set_xilinx_not_prog(hp_priv, 1);
+ if (msleep_interruptible(1))
+ return -EINTR;
+ set_xilinx_not_prog(hp_priv, 0);
+ if (msleep_interruptible(1))
+ return -EINTR;
+ set_xilinx_not_prog(hp_priv, 1);
+ if (msleep_interruptible(1))
+ return -EINTR;
+ return 0;
+}
+
+int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct hp_82341_priv *hp_priv;
+ struct tms9914_priv *tms_priv;
+ unsigned long start_addr;
+ void *iobase;
+ int irq;
+ int i;
+ int retval;
+
+ board->status = 0;
+ if (hp_82341_allocate_private(board))
+ return -ENOMEM;
+ hp_priv = board->private_data;
+ tms_priv = &hp_priv->tms9914_priv;
+ tms_priv->read_byte = hp_82341_read_byte;
+ tms_priv->write_byte = hp_82341_write_byte;
+ tms_priv->offset = 1;
+
+ if (config->ibbase == 0) {
+ struct pnp_dev *dev;
+ int retval = hp_82341_find_isapnp_board(&dev);
+
+ if (retval < 0)
+ return retval;
+ hp_priv->pnp_dev = dev;
+ iobase = (void *)(pnp_port_start(dev, 0));
+ irq = pnp_irq(dev, 0);
+ hp_priv->hw_version = HW_VERSION_82341D;
+ hp_priv->io_region_offset = 0x8;
+ } else {
+ iobase = config->ibbase;
+ irq = config->ibirq;
+ hp_priv->hw_version = HW_VERSION_82341C;
+ hp_priv->io_region_offset = 0x400;
+ }
+ pr_info("hp_82341: base io 0x%p\n", iobase);
+ for (i = 0; i < hp_82341_num_io_regions; ++i) {
+ start_addr = (unsigned long)(iobase) + i * hp_priv->io_region_offset;
+ if (!request_region(start_addr, hp_82341_region_iosize, "hp_82341")) {
+ pr_err("hp_82341: failed to allocate io ports 0x%lx-0x%lx\n",
+ start_addr,
+ start_addr + hp_82341_region_iosize - 1);
+ return -EIO;
+ }
+ hp_priv->iobase[i] = start_addr;
+ }
+ tms_priv->iobase = (void *)(hp_priv->iobase[2]);
+ if (hp_priv->hw_version == HW_VERSION_82341D) {
+ retval = isapnp_cfg_begin(hp_priv->pnp_dev->card->number,
+ hp_priv->pnp_dev->number);
+ if (retval < 0) {
+ pr_err("hp_82341: isapnp_cfg_begin returned error\n");
+ return retval;
+ }
+ isapnp_write_byte(PIO_DIRECTION_REG, HP_82341D_XILINX_READY_BIT |
+ HP_82341D_XILINX_DONE_BIT);
+ }
+ retval = clear_xilinx(hp_priv);
+ if (retval < 0)
+ return retval;
+ retval = hp_82341_load_firmware(hp_priv, config);
+ if (hp_priv->hw_version == HW_VERSION_82341D)
+ isapnp_cfg_end();
+ if (retval < 0)
+ return retval;
+ if (irq_valid(hp_priv, irq) == 0)
+ return -EINVAL;
+ if (request_irq(irq, hp_82341_interrupt, 0, "hp_82341", board)) {
+ pr_err("hp_82341: failed to allocate IRQ %d\n", irq);
+ return -EIO;
+ }
+ hp_priv->irq = irq;
+ pr_info("hp_82341: IRQ %d\n", irq);
+ hp_priv->config_control_bits &= ~IRQ_SELECT_MASK;
+ hp_priv->config_control_bits |= IRQ_SELECT_BITS(irq);
+ outb(hp_priv->config_control_bits, hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG);
+ hp_priv->mode_control_bits |= ENABLE_IRQ_CONFIG_BIT;
+ outb(hp_priv->mode_control_bits, hp_priv->iobase[0] + MODE_CONTROL_STATUS_REG);
+ tms9914_board_reset(tms_priv);
+ outb(ENABLE_BUFFER_END_EVENT_BIT | ENABLE_TERMINAL_COUNT_EVENT_BIT |
+ ENABLE_TI_INTERRUPT_EVENT_BIT, hp_priv->iobase[0] + EVENT_ENABLE_REG);
+ outb(ENABLE_BUFFER_END_INTERRUPT_BIT | ENABLE_TERMINAL_COUNT_INTERRUPT_BIT |
+ ENABLE_TI_INTERRUPT_BIT, hp_priv->iobase[0] + INTERRUPT_ENABLE_REG);
+ //write clear event register
+ outb((TI_INTERRUPT_EVENT_BIT | POINTERS_EQUAL_EVENT_BIT |
+ BUFFER_END_EVENT_BIT | TERMINAL_COUNT_EVENT_BIT),
+ hp_priv->iobase[0] + EVENT_STATUS_REG);
+
+ tms9914_online(board, tms_priv);
+ pr_info("hp_82341: board id %x %x %x %x\n", inb(hp_priv->iobase[1] + ID0_REG),
+ inb(hp_priv->iobase[1] + ID1_REG), inb(hp_priv->iobase[2] + ID2_REG),
+ inb(hp_priv->iobase[2] + ID3_REG));
+ return 0;
+}
+
+void hp_82341_detach(gpib_board_t *board)
+{
+ struct hp_82341_priv *hp_priv = board->private_data;
+ struct tms9914_priv *tms_priv;
+ int i;
+
+ if (hp_priv) {
+ tms_priv = &hp_priv->tms9914_priv;
+ if (hp_priv->iobase[0]) {
+ outb(0, hp_priv->iobase[0] + INTERRUPT_ENABLE_REG);
+ if (tms_priv->iobase)
+ tms9914_board_reset(tms_priv);
+ if (hp_priv->irq)
+ free_irq(hp_priv->irq, board);
+ }
+ for (i = 0; i < hp_82341_num_io_regions; ++i) {
+ if (hp_priv->iobase[i])
+ release_region(hp_priv->iobase[i], hp_82341_region_iosize);
+ }
+ if (hp_priv->pnp_dev)
+ pnp_device_detach(hp_priv->pnp_dev);
+ }
+ hp_82341_free_private(board);
+}
+
+static const struct pnp_device_id hp_82341_pnp_table[] = {
+ {.id = "HWP1411"},
+ {.id = ""}
+};
+MODULE_DEVICE_TABLE(pnp, hp_82341_pnp_table);
+
+static int __init hp_82341_init_module(void)
+{
+ gpib_register_driver(&hp_82341_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&hp_82341_interface, THIS_MODULE);
+ return 0;
+}
+
+static void __exit hp_82341_exit_module(void)
+{
+ gpib_unregister_driver(&hp_82341_interface);
+ gpib_unregister_driver(&hp_82341_unaccel_interface);
+}
+
+module_init(hp_82341_init_module);
+module_exit(hp_82341_exit_module);
+
+/*
+ * GPIB interrupt service routines
+ */
+unsigned short read_and_clear_event_status(gpib_board_t *board)
+{
+ struct hp_82341_priv *hp_priv = board->private_data;
+ unsigned long flags;
+ unsigned short status;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ status = hp_priv->event_status_bits;
+ hp_priv->event_status_bits = 0;
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return status;
+}
+
+irqreturn_t hp_82341_interrupt(int irq, void *arg)
+{
+ int status1, status2;
+ gpib_board_t *board = arg;
+ struct hp_82341_priv *hp_priv = board->private_data;
+ struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv;
+ unsigned long flags;
+ irqreturn_t retval = IRQ_NONE;
+ int event_status;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ event_status = inb(hp_priv->iobase[0] + EVENT_STATUS_REG);
+// printk("hp_82341: interrupt event_status=0x%x\n", event_status);
+ if (event_status & INTERRUPT_PENDING_EVENT_BIT)
+ retval = IRQ_HANDLED;
+ //write-clear status bits
+ if (event_status & (TI_INTERRUPT_EVENT_BIT | POINTERS_EQUAL_EVENT_BIT |
+ BUFFER_END_EVENT_BIT | TERMINAL_COUNT_EVENT_BIT)) {
+ outb(event_status & (TI_INTERRUPT_EVENT_BIT | POINTERS_EQUAL_EVENT_BIT |
+ BUFFER_END_EVENT_BIT | TERMINAL_COUNT_EVENT_BIT),
+ hp_priv->iobase[0] + EVENT_STATUS_REG);
+ hp_priv->event_status_bits |= event_status;
+ }
+ if (event_status & TI_INTERRUPT_EVENT_BIT) {
+ status1 = read_byte(tms_priv, ISR0);
+ status2 = read_byte(tms_priv, ISR1);
+ tms9914_interrupt_have_status(board, tms_priv, status1, status2);
+/* printk("hp_82341: interrupt status1=0x%x status2=0x%x\n",
+ * status1, status2);
+ */
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+int read_transfer_counter(struct hp_82341_priv *hp_priv)
+{
+ int lo, mid, value;
+
+ lo = inb(hp_priv->iobase[1] + TRANSFER_COUNT_LOW_REG);
+ mid = inb(hp_priv->iobase[1] + TRANSFER_COUNT_MID_REG);
+ value = (lo & 0xff) | ((mid << 8) & 0x7f00);
+ value = ~(value - 1) & 0x7fff;
+ return value;
+}
+
+void set_transfer_counter(struct hp_82341_priv *hp_priv, int count)
+{
+ int complement = -count;
+
+ outb(complement & 0xff, hp_priv->iobase[1] + TRANSFER_COUNT_LOW_REG);
+ outb((complement >> 8) & 0xff, hp_priv->iobase[1] + TRANSFER_COUNT_MID_REG);
+ //I don't think the hi count reg is even used, but oh well
+ outb((complement >> 16) & 0xf, hp_priv->iobase[1] + TRANSFER_COUNT_HIGH_REG);
+}
+
diff --git a/drivers/staging/gpib/hp_82341/hp_82341.h b/drivers/staging/gpib/hp_82341/hp_82341.h
new file mode 100644
index 000000000000..7c391860b399
--- /dev/null
+++ b/drivers/staging/gpib/hp_82341/hp_82341.h
@@ -0,0 +1,207 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002, 2005 by Frank Mori Hess *
+ ***************************************************************************/
+
+#include "tms9914.h"
+#include "gpibP.h"
+
+enum hp_82341_hardware_version {
+ HW_VERSION_UNKNOWN,
+ HW_VERSION_82341C,
+ HW_VERSION_82341D,
+};
+
+// struct which defines private_data for board
+struct hp_82341_priv {
+ struct tms9914_priv tms9914_priv;
+ unsigned int irq;
+ unsigned short config_control_bits;
+ unsigned short mode_control_bits;
+ unsigned short event_status_bits;
+ struct pnp_dev *pnp_dev;
+ unsigned long iobase[4];
+ unsigned long io_region_offset;
+ enum hp_82341_hardware_version hw_version;
+};
+
+// interfaces
+extern gpib_interface_t hp_82341_interface;
+
+// interface functions
+int hp_82341_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read);
+int hp_82341_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written);
+int hp_82341_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read);
+int hp_82341_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written);
+int hp_82341_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written);
+int hp_82341_take_control(gpib_board_t *board, int synchronous);
+int hp_82341_go_to_standby(gpib_board_t *board);
+void hp_82341_request_system_control(gpib_board_t *board, int request_control);
+void hp_82341_interface_clear(gpib_board_t *board, int assert);
+void hp_82341_remote_enable(gpib_board_t *board, int enable);
+int hp_82341_enable_eos(gpib_board_t *board, uint8_t eos_byte, int
+ compare_8_bits);
+void hp_82341_disable_eos(gpib_board_t *board);
+unsigned int hp_82341_update_status(gpib_board_t *board, unsigned int clear_mask);
+int hp_82341_primary_address(gpib_board_t *board, unsigned int address);
+int hp_82341_secondary_address(gpib_board_t *board, unsigned int address, int
+ enable);
+int hp_82341_parallel_poll(gpib_board_t *board, uint8_t *result);
+void hp_82341_parallel_poll_configure(gpib_board_t *board, uint8_t config);
+void hp_82341_parallel_poll_response(gpib_board_t *board, int ist);
+void hp_82341_serial_poll_response(gpib_board_t *board, uint8_t status);
+void hp_82341_return_to_local(gpib_board_t *board);
+
+// interrupt service routines
+irqreturn_t hp_82341_interrupt(int irq, void *arg);
+
+// utility functions
+int hp_82341_allocate_private(gpib_board_t *board);
+void hp_82341_free_private(gpib_board_t *board);
+
+static const int hp_82341_region_iosize = 0x8;
+static const int hp_82341_num_io_regions = 4;
+static const int hp_82341_fifo_size = 0xffe;
+static const int hp_82341c_firmware_length = 5764;
+static const int hp_82341d_firmware_length = 5302;
+
+// hp 82341 register offsets
+enum hp_82341_region_0_registers {
+ CONFIG_CONTROL_STATUS_REG = 0x0,
+ MODE_CONTROL_STATUS_REG = 0x1,
+ MONITOR_REG = 0x2, // after initialization
+ XILINX_DATA_REG = 0x2, // before initialization, write only
+ INTERRUPT_ENABLE_REG = 0x3,
+ EVENT_STATUS_REG = 0x4,
+ EVENT_ENABLE_REG = 0x5,
+ STREAM_STATUS_REG = 0x7,
+};
+
+enum hp_82341_region_1_registers {
+ ID0_REG = 0x2,
+ ID1_REG = 0x3,
+ TRANSFER_COUNT_LOW_REG = 0x4,
+ TRANSFER_COUNT_MID_REG = 0x5,
+ TRANSFER_COUNT_HIGH_REG = 0x6,
+};
+
+enum hp_82341_region_3_registers {
+ BUFFER_PORT_LOW_REG = 0x0,
+ BUFFER_PORT_HIGH_REG = 0x1,
+ ID2_REG = 0x2,
+ ID3_REG = 0x3,
+ BUFFER_FLUSH_REG = 0x4,
+ BUFFER_CONTROL_REG = 0x7
+};
+
+enum config_control_status_bits {
+ IRQ_SELECT_MASK = 0x7,
+ DMA_CONFIG_MASK = 0x18,
+ ENABLE_DMA_CONFIG_BIT = 0x20,
+ XILINX_READY_BIT = 0x40, //read only
+ DONE_PGL_BIT = 0x80
+};
+
+static inline unsigned int IRQ_SELECT_BITS(int irq)
+{
+ switch (irq) {
+ case 3:
+ return 0x3;
+ case 5:
+ return 0x2;
+ case 7:
+ return 0x1;
+ case 9:
+ return 0x0;
+ case 10:
+ return 0x7;
+ case 11:
+ return 0x6;
+ case 12:
+ return 0x5;
+ case 15:
+ return 0x4;
+ default:
+ return 0x0;
+ }
+};
+
+enum mode_control_status_bits {
+ SLOT8_BIT = 0x1, // read only
+ ACTIVE_CONTROLLER_BIT = 0x2, // read only
+ ENABLE_DMA_BIT = 0x4,
+ SYSTEM_CONTROLLER_BIT = 0x8,
+ MONITOR_BIT = 0x10,
+ ENABLE_IRQ_CONFIG_BIT = 0x20,
+ ENABLE_TI_STREAM_BIT = 0x40
+};
+
+enum monitor_bits {
+ MONITOR_INTERRUPT_PENDING_BIT = 0x1, // read only
+ MONITOR_CLEAR_HOLDOFF_BIT = 0x2, // write only
+ MONITOR_PPOLL_BIT = 0x4, // write clear
+ MONITOR_SRQ_BIT = 0x8, // write clear
+ MONITOR_IFC_BIT = 0x10, // write clear
+ MONITOR_REN_BIT = 0x20, // write clear
+ MONITOR_END_BIT = 0x40, // write clear
+ MONITOR_DAV_BIT = 0x80 // write clear
+};
+
+enum interrupt_enable_bits {
+ ENABLE_TI_INTERRUPT_BIT = 0x1,
+ ENABLE_POINTERS_EQUAL_INTERRUPT_BIT = 0x4,
+ ENABLE_BUFFER_END_INTERRUPT_BIT = 0x10,
+ ENABLE_TERMINAL_COUNT_INTERRUPT_BIT = 0x20,
+ ENABLE_DMA_TERMINAL_COUNT_INTERRUPT_BIT = 0x80,
+};
+
+enum event_status_bits {
+ TI_INTERRUPT_EVENT_BIT = 0x1, //write clear
+ INTERRUPT_PENDING_EVENT_BIT = 0x2, // read only
+ POINTERS_EQUAL_EVENT_BIT = 0x4, //write clear
+ BUFFER_END_EVENT_BIT = 0x10, //write clear
+ TERMINAL_COUNT_EVENT_BIT = 0x20, // write clear
+ DMA_TERMINAL_COUNT_EVENT_BIT = 0x80, // write clear
+};
+
+enum event_enable_bits {
+ ENABLE_TI_INTERRUPT_EVENT_BIT = 0x1, //write clear
+ ENABLE_POINTERS_EQUAL_EVENT_BIT = 0x4, //write clear
+ ENABLE_BUFFER_END_EVENT_BIT = 0x10, //write clear
+ ENABLE_TERMINAL_COUNT_EVENT_BIT = 0x20, // write clear
+ ENABLE_DMA_TERMINAL_COUNT_EVENT_BIT = 0x80, // write clear
+};
+
+enum stream_status_bits {
+ HALTED_STATUS_BIT = 0x1, //read
+ RESTART_STREAM_BIT = 0x1 //write
+};
+
+enum buffer_control_bits {
+ DIRECTION_GPIB_TO_HOST_BIT = 0x20, // transfer direction (set for gpib to host)
+ ENABLE_TI_BUFFER_BIT = 0x40, //enable fifo
+ FAST_WR_EN_BIT = 0x80, // 350 ns t1 delay?
+};
+
+// registers accessible through isapnp chip on 82341d
+enum hp_82341d_pnp_registers {
+ PIO_DATA_REG = 0x20, //read/write pio data lines
+ PIO_DIRECTION_REG = 0x21, // set pio data line directions (set for input)
+};
+
+enum hp_82341d_pnp_pio_bits {
+ HP_82341D_XILINX_READY_BIT = 0x1,
+ HP_82341D_XILINX_DONE_BIT = 0x2,
+ // use register layout compatible with C and older versions instead of 32 contiguous ioports
+ HP_82341D_LEGACY_MODE_BIT = 0x4,
+ HP_82341D_NOT_PROG_BIT = 0x8, // clear to reinitialize xilinx
+};
+
+unsigned short read_and_clear_event_status(gpib_board_t *board);
+int read_transfer_counter(struct hp_82341_priv *hp_priv);
+void set_transfer_counter(struct hp_82341_priv *hp_priv, int count);
diff --git a/drivers/staging/gpib/include/amcc5920.h b/drivers/staging/gpib/include/amcc5920.h
new file mode 100644
index 000000000000..766b3799223f
--- /dev/null
+++ b/drivers/staging/gpib/include/amcc5920.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Header for amcc5920 pci chip
+ *
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+// plx pci chip registers and bits
+enum amcc_registers {
+ AMCC_INTCS_REG = 0x38,
+ AMCC_PASS_THRU_REG = 0x60,
+};
+
+enum amcc_incsr_bits {
+ AMCC_ADDON_INTR_ENABLE_BIT = 0x2000,
+ AMCC_ADDON_INTR_ACTIVE_BIT = 0x400000,
+ AMCC_INTR_ACTIVE_BIT = 0x800000,
+};
+
+static const int bits_per_region = 8;
+
+static inline uint32_t amcc_wait_state_bits(unsigned int region, unsigned int num_wait_states)
+{
+ return (num_wait_states & 0x7) << (-region * bits_per_region);
+};
+
+enum amcc_prefetch_bits {
+ PREFETCH_DISABLED = 0x0,
+ PREFETCH_SMALL = 0x8,
+ PREFETCH_MEDIUM = 0x10,
+ PREFETCH_LARGE = 0x18,
+};
+
+static inline uint32_t amcc_prefetch_bits(unsigned int region, enum amcc_prefetch_bits prefetch)
+{
+ return prefetch << (--region * bits_per_region);
+};
+
+static inline uint32_t amcc_PTADR_mode_bit(unsigned int region)
+{
+ return 0x80 << (--region * bits_per_region);
+};
+
+static inline uint32_t amcc_disable_write_fifo_bit(unsigned int region)
+{
+ return 0x20 << (--region * bits_per_region);
+};
+
diff --git a/drivers/staging/gpib/include/amccs5933.h b/drivers/staging/gpib/include/amccs5933.h
new file mode 100644
index 000000000000..4de0f6797458
--- /dev/null
+++ b/drivers/staging/gpib/include/amccs5933.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Registers and bits for amccs5933 pci chip
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+// register offsets
+enum {
+ MBEF_REG = 0x34, // mailbux empty/full
+ INTCSR_REG = 0x38, // interrupt control and status
+ BMCSR_REG = 0x3c, // bus master control and status
+};
+
+// incoming mailbox 0-3 register offsets
+extern inline int INCOMING_MAILBOX_REG(unsigned int mailbox)
+{
+ return (0x10 + 4 * mailbox);
+};
+
+// bit definitions
+
+// INTCSR bits
+enum {
+ OUTBOX_EMPTY_INTR_BIT = 0x10, // enable outbox empty interrupt
+ INBOX_FULL_INTR_BIT = 0x1000, // enable inbox full interrupt
+ INBOX_INTR_CS_BIT = 0x20000, // read, or write clear inbox full interrupt
+ INTR_ASSERTED_BIT = 0x800000, // read only, interrupt asserted
+};
+
+// select byte 0 to 3 of incoming mailbox
+extern inline int INBOX_BYTE_BITS(unsigned int byte)
+{
+ return (byte & 0x3) << 8;
+};
+
+// select incoming mailbox 0 to 3
+extern inline int INBOX_SELECT_BITS(unsigned int mailbox)
+{
+ return (mailbox & 0x3) << 10;
+};
+
+// select byte 0 to 3 of outgoing mailbox
+extern inline int OUTBOX_BYTE_BITS(unsigned int byte)
+{
+ return (byte & 0x3);
+};
+
+// select outgoing mailbox 0 to 3
+extern inline int OUTBOX_SELECT_BITS(unsigned int mailbox)
+{
+ return (mailbox & 0x3) << 2;
+};
+
+//BMCSR bits
+enum {
+ MBOX_FLAGS_RESET_BIT = 0x08000000, // resets mailbox empty/full flags
+};
+
diff --git a/drivers/staging/gpib/include/gpibP.h b/drivers/staging/gpib/include/gpibP.h
new file mode 100644
index 000000000000..5fc42b645ab7
--- /dev/null
+++ b/drivers/staging/gpib/include/gpibP.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002,2003 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_P_H
+#define _GPIB_P_H
+
+#include <linux/types.h>
+
+#include "gpib_types.h"
+#include "gpib_proto.h"
+#include "gpib_user.h"
+#include "gpib_ioctl.h"
+
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+
+void gpib_register_driver(gpib_interface_t *interface, struct module *mod);
+void gpib_unregister_driver(gpib_interface_t *interface);
+struct pci_dev *gpib_pci_get_device(const gpib_board_config_t *config, unsigned int vendor_id,
+ unsigned int device_id, struct pci_dev *from);
+struct pci_dev *gpib_pci_get_subsys(const gpib_board_config_t *config, unsigned int vendor_id,
+ unsigned int device_id, unsigned int ss_vendor,
+ unsigned int ss_device, struct pci_dev *from);
+unsigned int num_gpib_events(const gpib_event_queue_t *queue);
+int push_gpib_event(gpib_board_t *board, short event_type);
+int pop_gpib_event(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type);
+int gpib_request_pseudo_irq(gpib_board_t *board, irqreturn_t (*handler)(int, void *));
+void gpib_free_pseudo_irq(gpib_board_t *board);
+int gpib_match_device_path(struct device *dev, const char *device_path_in);
+
+extern gpib_board_t board_array[GPIB_MAX_NUM_BOARDS];
+
+extern struct list_head registered_drivers;
+
+#include <linux/io.h>
+
+void writeb_wrapper(unsigned int value, void *address);
+unsigned int readb_wrapper(void *address);
+void outb_wrapper(unsigned int value, void *address);
+unsigned int inb_wrapper(void *address);
+void writew_wrapper(unsigned int value, void *address);
+unsigned int readw_wrapper(void *address);
+void outw_wrapper(unsigned int value, void *address);
+unsigned int inw_wrapper(void *address);
+
+#endif // _GPIB_P_H
+
diff --git a/drivers/staging/gpib/include/gpib_pci_ids.h b/drivers/staging/gpib/include/gpib_pci_ids.h
new file mode 100644
index 000000000000..52dcab07a7d1
--- /dev/null
+++ b/drivers/staging/gpib/include/gpib_pci_ids.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __GPIB_PCI_IDS_H
+#define __GPIB_PCI_IDS_H
+
+#ifndef PCI_VENDOR_ID_AMCC
+#define PCI_VENDOR_ID_AMCC 0x10e8
+#endif
+
+#ifndef PCI_VENDOR_ID_CBOARDS
+#define PCI_VENDOR_ID_CBOARDS 0x1307
+#endif
+
+#ifndef PCI_VENDOR_ID_QUANCOM
+#define PCI_VENDOR_ID_QUANCOM 0x8008
+#endif
+
+#ifndef PCI_DEVICE_ID_QUANCOM_GPIB
+#define PCI_DEVICE_ID_QUANCOM_GPIB 0x3302
+#endif
+
+#endif // __GPIB_PCI_IDS_H
+
diff --git a/drivers/staging/gpib/include/gpib_proto.h b/drivers/staging/gpib/include/gpib_proto.h
new file mode 100644
index 000000000000..1499f954210b
--- /dev/null
+++ b/drivers/staging/gpib/include/gpib_proto.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef GPIB_PROTO_INCLUDED
+#define GPIB_PROTO_INCLUDED
+
+#include <linux/fs.h>
+
+int ibopen(struct inode *inode, struct file *filep);
+int ibclose(struct inode *inode, struct file *file);
+long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg);
+int osInit(void);
+void osReset(void);
+void os_start_timer(gpib_board_t *board, unsigned int usec_timeout);
+void os_remove_timer(gpib_board_t *board);
+void osSendEOI(void);
+void osSendEOI(void);
+void init_gpib_board(gpib_board_t *board);
+static inline unsigned long usec_to_jiffies(unsigned int usec)
+{
+ unsigned long usec_per_jiffy = 1000000 / HZ;
+
+ return 1 + (usec + usec_per_jiffy - 1) / usec_per_jiffy;
+};
+
+int serial_poll_all(gpib_board_t *board, unsigned int usec_timeout);
+void init_gpib_descriptor(gpib_descriptor_t *desc);
+int dvrsp(gpib_board_t *board, unsigned int pad, int sad,
+ unsigned int usec_timeout, uint8_t *result);
+int ibAPWait(gpib_board_t *board, int pad);
+int ibAPrsp(gpib_board_t *board, int padsad, char *spb);
+void ibAPE(gpib_board_t *board, int pad, int v);
+int ibcac(gpib_board_t *board, int sync, int fallback_to_async);
+int ibcmd(gpib_board_t *board, uint8_t *buf, size_t length, size_t *bytes_written);
+int ibgts(gpib_board_t *board);
+int ibonline(gpib_board_t *board);
+int iboffline(gpib_board_t *board);
+int iblines(const gpib_board_t *board, short *lines);
+int ibrd(gpib_board_t *board, uint8_t *buf, size_t length, int *end_flag, size_t *bytes_read);
+int ibrpp(gpib_board_t *board, uint8_t *buf);
+int ibrsv2(gpib_board_t *board, uint8_t status_byte, int new_reason_for_service);
+void ibrsc(gpib_board_t *board, int request_control);
+int ibsic(gpib_board_t *board, unsigned int usec_duration);
+int ibsre(gpib_board_t *board, int enable);
+int ibpad(gpib_board_t *board, unsigned int addr);
+int ibsad(gpib_board_t *board, int addr);
+int ibeos(gpib_board_t *board, int eos, int eosflags);
+int ibwait(gpib_board_t *board, int wait_mask, int clear_mask, int set_mask,
+ int *status, unsigned long usec_timeout, gpib_descriptor_t *desc);
+int ibwrt(gpib_board_t *board, uint8_t *buf, size_t cnt, int send_eoi, size_t *bytes_written);
+int ibstatus(gpib_board_t *board);
+int general_ibstatus(gpib_board_t *board, const gpib_status_queue_t *device,
+ int clear_mask, int set_mask, gpib_descriptor_t *desc);
+int io_timed_out(gpib_board_t *board);
+int ibppc(gpib_board_t *board, uint8_t configuration);
+
+#endif /* GPIB_PROTO_INCLUDED */
diff --git a/drivers/staging/gpib/include/gpib_state_machines.h b/drivers/staging/gpib/include/gpib_state_machines.h
new file mode 100644
index 000000000000..7488c00f191e
--- /dev/null
+++ b/drivers/staging/gpib/include/gpib_state_machines.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2006 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_STATE_MACHINES_H
+#define _GPIB_STATE_MACHINES_H
+
+enum talker_function_state {
+ talker_idle,
+ talker_addressed,
+ talker_active,
+ serial_poll_active
+};
+
+enum listener_function_state {
+ listener_idle,
+ listener_addressed,
+ listener_active
+};
+
+#endif // _GPIB_STATE_MACHINES_H
diff --git a/drivers/staging/gpib/include/gpib_types.h b/drivers/staging/gpib/include/gpib_types.h
new file mode 100644
index 000000000000..ee2643da6d71
--- /dev/null
+++ b/drivers/staging/gpib/include/gpib_types.h
@@ -0,0 +1,353 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_TYPES_H
+#define _GPIB_TYPES_H
+
+#ifdef __KERNEL__
+/* gpib_interface_t defines the interface
+ * between the board-specific details dealt with in the drivers
+ * and generic interface provided by gpib-common.
+ * This really should be in a different header file.
+ */
+#include "gpib_user.h"
+#include <linux/atomic.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+
+typedef struct gpib_interface_struct gpib_interface_t;
+typedef struct gpib_board_struct gpib_board_t;
+
+/* config parameters that are only used by driver attach functions */
+typedef struct {
+ /* firmware blob */
+ void *init_data;
+ int init_data_length;
+ /* IO base address to use for non-pnp cards (set by core, driver should make local copy) */
+ void *ibbase;
+ /* IRQ to use for non-pnp cards (set by core, driver should make local copy) */
+ unsigned int ibirq;
+ /* dma channel to use for non-pnp cards (set by core, driver should make local copy) */
+ unsigned int ibdma;
+ /* pci bus of card, useful for distinguishing multiple identical pci cards
+ * (negative means don't care)
+ */
+ int pci_bus;
+ /* pci slot of card, useful for distinguishing multiple identical pci cards
+ * (negative means don't care)
+ */
+ int pci_slot;
+ /* sysfs device path of hardware to attach */
+ char *device_path;
+ /* serial number of hardware to attach */
+ char *serial_number;
+} gpib_board_config_t;
+
+struct gpib_interface_struct {
+ /* name of board */
+ char *name;
+ /* attach() initializes board and allocates resources */
+ int (*attach)(gpib_board_t *board, const gpib_board_config_t *config);
+ /* detach() shuts down board and frees resources */
+ void (*detach)(gpib_board_t *board);
+ /* read() should read at most 'length' bytes from the bus into
+ * 'buffer'. It should return when it fills the buffer or
+ * encounters an END (EOI and or EOS if appropriate). It should set 'end'
+ * to be nonzero if the read was terminated by an END, otherwise 'end'
+ * should be zero.
+ * Ultimately, this will be changed into or replaced by an asynchronous
+ * read. Zero return value for success, negative
+ * return indicates error.
+ * nbytes returns number of bytes read
+ */
+ int (*read)(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read);
+ /* write() should write 'length' bytes from buffer to the bus.
+ * If the boolean value send_eoi is nonzero, then EOI should
+ * be sent along with the last byte. Returns number of bytes
+ * written or negative value on error.
+ */
+ int (*write)(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written);
+ /* command() writes the command bytes in 'buffer' to the bus
+ * Returns zero on success or negative value on error.
+ */
+ int (*command)(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written);
+ /* Take control (assert ATN). If 'asyncronous' is nonzero, take
+ * control asyncronously (assert ATN immediately without waiting
+ * for other processes to complete first). Should not return
+ * until board becomes controller in charge. Returns zero no success,
+ * nonzero on error.
+ */
+ int (*take_control)(gpib_board_t *board, int asyncronous);
+ /* De-assert ATN. Returns zero on success, nonzer on error.
+ */
+ int (*go_to_standby)(gpib_board_t *board);
+ /* request/release control of the IFC and REN lines (system controller) */
+ void (*request_system_control)(gpib_board_t *board, int request_control);
+ /* Asserts or de-asserts 'interface clear' (IFC) depending on
+ * boolean value of 'assert'
+ */
+ void (*interface_clear)(gpib_board_t *board, int assert);
+ /* Sends remote enable command if 'enable' is nonzero, disables remote mode
+ * if 'enable' is zero
+ */
+ void (*remote_enable)(gpib_board_t *board, int enable);
+ /* enable END for reads, when byte 'eos' is received. If
+ * 'compare_8_bits' is nonzero, then all 8 bits are compared
+ * with the eos bytes. Otherwise only the 7 least significant
+ * bits are compared.
+ */
+ int (*enable_eos)(gpib_board_t *board, uint8_t eos, int compare_8_bits);
+ /* disable END on eos byte (END on EOI only)*/
+ void (*disable_eos)(gpib_board_t *board);
+ /* configure parallel poll */
+ void (*parallel_poll_configure)(gpib_board_t *board, uint8_t configuration);
+ /* conduct parallel poll */
+ int (*parallel_poll)(gpib_board_t *board, uint8_t *result);
+ /* set/clear ist (individual status bit) */
+ void (*parallel_poll_response)(gpib_board_t *board, int ist);
+ /* select local parallel poll configuration mode PP2 versus remote PP1 */
+ void (*local_parallel_poll_mode)(gpib_board_t *board, int local);
+ /* Returns current status of the bus lines. Should be set to
+ * NULL if your board does not have the ability to query the
+ * state of the bus lines.
+ */
+ int (*line_status)(const gpib_board_t *board);
+ /* updates and returns the board's current status.
+ * The meaning of the bits are specified in gpib_user.h
+ * in the IBSTA section. The driver does not need to
+ * worry about setting the CMPL, END, TIMO, or ERR bits.
+ */
+ unsigned int (*update_status)(gpib_board_t *board, unsigned int clear_mask);
+ /* Sets primary address 0-30 for gpib interface card.
+ */
+ int (*primary_address)(gpib_board_t *board, unsigned int address);
+ /* Sets and enables, or disables secondary address 0-30
+ * for gpib interface card.
+ */
+ int (*secondary_address)(gpib_board_t *board, unsigned int address,
+ int enable);
+ /* Sets the byte the board should send in response to a serial poll.
+ * This function should also start or stop requests for service via
+ * IEEE 488.2 reqt/reqf, based on MSS (bit 6 of the status_byte).
+ * If the more flexible serial_poll_response2 is implemented by the
+ * driver, then this method should be left NULL since it will not
+ * be used. This method can generate spurious service requests
+ * which are allowed by IEEE 488.2, but not ideal.
+ *
+ * This method should implement the serial poll response method described
+ * by IEEE 488.2 section 11.3.3.4.3 "Allowed Coupled Control of
+ * STB, reqt, and reqf".
+ */
+ void (*serial_poll_response)(gpib_board_t *board, uint8_t status_byte);
+ /* Sets the byte the board should send in response to a serial poll.
+ * This function should also request service via IEEE 488.2 reqt/reqf
+ * based on MSS (bit 6 of the status_byte) and new_reason_for_service.
+ * reqt should be set true if new_reason_for_service is true,
+ * and reqf should be set true if MSS is false. This function
+ * will never be called with MSS false and new_reason_for_service
+ * true simultaneously, so don't worry about that case.
+ *
+ * This method implements the serial poll response method described
+ * by IEEE 488.2 section 11.3.3.4.1 "Preferred Implementation".
+ *
+ * If this method is left NULL by the driver, then the user library
+ * function ibrsv2 will not work.
+ */
+ void (*serial_poll_response2)(gpib_board_t *board, uint8_t status_byte,
+ int new_reason_for_service);
+ /* returns the byte the board will send in response to a serial poll.
+ */
+ uint8_t (*serial_poll_status)(gpib_board_t *board);
+ /* adjust T1 delay */
+ unsigned int (*t1_delay)(gpib_board_t *board, unsigned int nano_sec);
+ /* go to local mode */
+ void (*return_to_local)(gpib_board_t *board);
+ /* board does not support 7 bit eos comparisons */
+ unsigned no_7_bit_eos : 1;
+ /* skip check for listeners before trying to send command bytes */
+ unsigned skip_check_for_command_acceptors : 1;
+};
+
+typedef struct {
+ struct list_head event_head;
+ spinlock_t lock; // for access to event list
+ unsigned int num_events;
+ unsigned dropped_event : 1;
+} gpib_event_queue_t;
+
+static inline void init_event_queue(gpib_event_queue_t *queue)
+{
+ INIT_LIST_HEAD(&queue->event_head);
+ queue->num_events = 0;
+ queue->dropped_event = 0;
+ spin_lock_init(&queue->lock);
+}
+
+/* struct for supporting polling operation when irq is not available */
+struct gpib_pseudo_irq {
+ struct timer_list timer;
+ irqreturn_t (*handler)(int irq, void *arg);
+ gpib_board_t *board;
+ atomic_t active;
+};
+
+static inline void init_gpib_pseudo_irq(struct gpib_pseudo_irq *pseudo_irq)
+{
+ pseudo_irq->handler = NULL;
+ timer_setup(&pseudo_irq->timer, NULL, 0);
+ atomic_set(&pseudo_irq->active, 0);
+}
+
+/* list so we can make a linked list of drivers */
+typedef struct gpib_interface_list_struct {
+ struct list_head list;
+ gpib_interface_t *interface;
+ struct module *module;
+} gpib_interface_list_t;
+
+/* One gpib_board_t is allocated for each physical board in the computer.
+ * It provides storage for variables local to each board, and interface
+ * functions for performing operations on the board
+ */
+struct gpib_board_struct {
+ /* functions used by this board */
+ gpib_interface_t *interface;
+ /* Pointer to module whose use count we should increment when
+ * interface is in use
+ */
+ struct module *provider_module;
+ /* buffer used to store read/write data for this board */
+ u8 *buffer;
+ /* length of buffer */
+ unsigned int buffer_length;
+ /* Used to hold the board's current status (see update_status() above)
+ */
+ unsigned long status;
+ /* Driver should only sleep on this wait queue. It is special in that the
+ * core will wake this queue and set the TIMO bit in 'status' when the
+ * watchdog timer times out.
+ */
+ wait_queue_head_t wait;
+ /* Lock that only allows one process to access this board at a time.
+ * Has to be first in any locking order, since it can be locked over
+ * multiple ioctls.
+ */
+ struct mutex user_mutex;
+ /* Mutex which compensates for removal of "big kernel lock" from kernel.
+ * Should not be held for extended waits.
+ */
+ struct mutex big_gpib_mutex;
+ /* pid of last process to lock the board mutex */
+ pid_t locking_pid;
+ spinlock_t locking_pid_spinlock; // lock for setting locking pid
+ /* Spin lock for dealing with races with the interrupt handler */
+ spinlock_t spinlock;
+ /* Watchdog timer to enable timeouts */
+ struct timer_list timer;
+ /* device of attached driver if any */
+ struct device *dev;
+ /* gpib_common device gpibN */
+ struct device *gpib_dev;
+ /* 'private_data' can be used as seen fit by the driver to
+ * store additional variables for this board
+ */
+ void *private_data;
+ /* Number of open file descriptors using this board */
+ unsigned int use_count;
+ /* list of open devices connected to this board */
+ struct list_head device_list;
+ /* primary address */
+ unsigned int pad;
+ /* secondary address */
+ int sad;
+ /* timeout for io operations, in microseconds */
+ unsigned int usec_timeout;
+ /* board's parallel poll configuration byte */
+ u8 parallel_poll_configuration;
+ /* t1 delay we are using */
+ unsigned int t1_nano_sec;
+ /* Count that keeps track of whether board is up and running or not */
+ unsigned int online;
+ /* number of processes trying to autopoll */
+ int autospollers;
+ /* autospoll kernel thread */
+ struct task_struct *autospoll_task;
+ /* queue for recording received trigger/clear/ifc events */
+ gpib_event_queue_t event_queue;
+ /* minor number for this board's device file */
+ int minor;
+ /* struct to deal with polling mode*/
+ struct gpib_pseudo_irq pseudo_irq;
+ /* error dong autopoll */
+ atomic_t stuck_srq;
+ gpib_board_config_t config;
+ /* Flag that indicates whether board is system controller of the bus */
+ unsigned master : 1;
+ /* individual status bit */
+ unsigned ist : 1;
+ /* one means local parallel poll mode ieee 488.1 PP2 (or no parallel poll PP0),
+ * zero means remote parallel poll configuration mode ieee 488.1 PP1
+ */
+ unsigned local_ppoll_mode : 1;
+};
+
+/* element of event queue */
+typedef struct {
+ struct list_head list;
+ short event_type;
+} gpib_event_t;
+
+/* Each board has a list of gpib_status_queue_t to keep track of all open devices
+ * on the bus, so we know what address to poll when we get a service request
+ */
+typedef struct {
+ /* list_head so we can make a linked list of devices */
+ struct list_head list;
+ unsigned int pad; /* primary gpib address */
+ int sad; /* secondary gpib address (negative means disabled) */
+ /* stores serial poll bytes for this device */
+ struct list_head status_bytes;
+ unsigned int num_status_bytes;
+ /* number of times this address is opened */
+ unsigned int reference_count;
+ /* flags loss of status byte error due to limit on size of queue */
+ unsigned dropped_byte : 1;
+} gpib_status_queue_t;
+
+typedef struct {
+ struct list_head list;
+ u8 poll_byte;
+} status_byte_t;
+
+void init_gpib_status_queue(gpib_status_queue_t *device);
+
+/* Used to store device-descriptor-specific information */
+typedef struct {
+ unsigned int pad; /* primary gpib address */
+ int sad; /* secondary gpib address (negative means disabled) */
+ atomic_t io_in_progress;
+ unsigned is_board : 1;
+ unsigned autopoll_enabled : 1;
+} gpib_descriptor_t;
+
+typedef struct {
+ atomic_t holding_mutex;
+ gpib_descriptor_t *descriptors[GPIB_MAX_NUM_DESCRIPTORS];
+ /* locked while descriptors are being allocated/deallocated */
+ struct mutex descriptors_mutex;
+ unsigned got_module : 1;
+} gpib_file_private_t;
+
+#endif /* __KERNEL__ */
+
+#endif /* _GPIB_TYPES_H */
diff --git a/drivers/staging/gpib/include/nec7210.h b/drivers/staging/gpib/include/nec7210.h
new file mode 100644
index 000000000000..c00aba4ce846
--- /dev/null
+++ b/drivers/staging/gpib/include/nec7210.h
@@ -0,0 +1,138 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _NEC7210_H
+#define _NEC7210_H
+
+#include "gpib_state_machines.h"
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+
+#include "gpib_types.h"
+#include "nec7210_registers.h"
+
+/* struct used to provide variables local to a nec7210 chip */
+struct nec7210_priv {
+ void *iobase;
+ unsigned int offset; // offset between successive nec7210 io addresses
+ unsigned int dma_channel;
+ u8 *dma_buffer;
+ unsigned int dma_buffer_length; // length of dma buffer
+ dma_addr_t dma_buffer_addr; // bus address of board->buffer for use with dma
+ // software copy of bits written to registers
+ u8 reg_bits[8];
+ u8 auxa_bits; // bits written to auxiliary register A
+ u8 auxb_bits; // bits written to auxiliary register B
+ // used to keep track of board's state, bit definitions given below
+ unsigned long state;
+ /* lock for chips that extend the nec7210 registers by paging in alternate regs */
+ spinlock_t register_page_lock;
+ // wrappers for outb, inb, readb, or writeb
+ u8 (*read_byte)(struct nec7210_priv *priv, unsigned int register_number);
+ void (*write_byte)(struct nec7210_priv *priv, u8 byte, unsigned int register_number);
+ enum nec7210_chipset type;
+ enum talker_function_state talker_state;
+ enum listener_function_state listener_state;
+ void *private;
+ unsigned srq_pending : 1;
+};
+
+static inline void init_nec7210_private(struct nec7210_priv *priv)
+{
+ memset(priv, 0, sizeof(struct nec7210_priv));
+ spin_lock_init(&priv->register_page_lock);
+}
+
+// slightly shorter way to access read_byte and write_byte
+static inline u8 read_byte(struct nec7210_priv *priv, unsigned int register_number)
+{
+ return priv->read_byte(priv, register_number);
+}
+
+static inline void write_byte(struct nec7210_priv *priv, u8 byte, unsigned int register_number)
+{
+ priv->write_byte(priv, byte, register_number);
+}
+
+// struct nec7210_priv.state bit numbers
+enum {
+ PIO_IN_PROGRESS_BN, // pio transfer in progress
+ DMA_READ_IN_PROGRESS_BN, // dma read transfer in progress
+ DMA_WRITE_IN_PROGRESS_BN, // dma write transfer in progress
+ READ_READY_BN, // board has data byte available to read
+ WRITE_READY_BN, // board is ready to send a data byte
+ COMMAND_READY_BN, // board is ready to send a command byte
+ RECEIVED_END_BN, // received END
+ BUS_ERROR_BN, // output error has occurred
+ RFD_HOLDOFF_BN, // rfd holdoff in effect
+ DEV_CLEAR_BN, // device clear received
+ ADR_CHANGE_BN, // address state change occurred
+};
+
+// interface functions
+int nec7210_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read);
+int nec7210_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, int send_eoi, size_t *bytes_written);
+int nec7210_command(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, size_t *bytes_written);
+int nec7210_take_control(gpib_board_t *board, struct nec7210_priv *priv, int syncronous);
+int nec7210_go_to_standby(gpib_board_t *board, struct nec7210_priv *priv);
+void nec7210_request_system_control(gpib_board_t *board,
+ struct nec7210_priv *priv, int request_control);
+void nec7210_interface_clear(gpib_board_t *board, struct nec7210_priv *priv, int assert);
+void nec7210_remote_enable(gpib_board_t *board, struct nec7210_priv *priv, int enable);
+int nec7210_enable_eos(gpib_board_t *board, struct nec7210_priv *priv, uint8_t eos_bytes,
+ int compare_8_bits);
+void nec7210_disable_eos(gpib_board_t *board, struct nec7210_priv *priv);
+unsigned int nec7210_update_status(gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int clear_mask);
+unsigned int nec7210_update_status_nolock(gpib_board_t *board, struct nec7210_priv *priv);
+int nec7210_primary_address(const gpib_board_t *board,
+ struct nec7210_priv *priv, unsigned int address);
+int nec7210_secondary_address(const gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int address, int enable);
+int nec7210_parallel_poll(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *result);
+void nec7210_serial_poll_response(gpib_board_t *board, struct nec7210_priv *priv, uint8_t status);
+void nec7210_parallel_poll_configure(gpib_board_t *board,
+ struct nec7210_priv *priv, unsigned int configuration);
+void nec7210_parallel_poll_response(gpib_board_t *board,
+ struct nec7210_priv *priv, int ist);
+uint8_t nec7210_serial_poll_status(gpib_board_t *board,
+ struct nec7210_priv *priv);
+unsigned int nec7210_t1_delay(gpib_board_t *board,
+ struct nec7210_priv *priv, unsigned int nano_sec);
+void nec7210_return_to_local(const gpib_board_t *board, struct nec7210_priv *priv);
+
+// utility functions
+void nec7210_board_reset(struct nec7210_priv *priv, const gpib_board_t *board);
+void nec7210_board_online(struct nec7210_priv *priv, const gpib_board_t *board);
+unsigned int nec7210_set_reg_bits(struct nec7210_priv *priv, unsigned int reg,
+ unsigned int mask, unsigned int bits);
+void nec7210_set_handshake_mode(gpib_board_t *board, struct nec7210_priv *priv, int mode);
+void nec7210_release_rfd_holdoff(gpib_board_t *board, struct nec7210_priv *priv);
+uint8_t nec7210_read_data_in(gpib_board_t *board, struct nec7210_priv *priv, int *end);
+
+// wrappers for io functions
+uint8_t nec7210_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num);
+void nec7210_ioport_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num);
+uint8_t nec7210_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num);
+void nec7210_iomem_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num);
+uint8_t nec7210_locking_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num);
+void nec7210_locking_ioport_write_byte(struct nec7210_priv *priv, uint8_t data,
+ unsigned int register_num);
+uint8_t nec7210_locking_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num);
+void nec7210_locking_iomem_write_byte(struct nec7210_priv *priv, uint8_t data,
+ unsigned int register_num);
+
+// interrupt service routine
+irqreturn_t nec7210_interrupt(gpib_board_t *board, struct nec7210_priv *priv);
+irqreturn_t nec7210_interrupt_have_status(gpib_board_t *board,
+ struct nec7210_priv *priv, int status1, int status2);
+
+#endif //_NEC7210_H
diff --git a/drivers/staging/gpib/include/nec7210_registers.h b/drivers/staging/gpib/include/nec7210_registers.h
new file mode 100644
index 000000000000..888803dd97f9
--- /dev/null
+++ b/drivers/staging/gpib/include/nec7210_registers.h
@@ -0,0 +1,217 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _NEC7210_REGISTERS_H
+#define _NEC7210_REGISTERS_H
+
+enum nec7210_chipset {
+ NEC7210, // The original
+ TNT4882, // NI
+ NAT4882, // NI
+ CB7210, // measurement computing
+ IOT7210, // iotech
+ IGPIB7210, // Ines
+ TNT5004, // NI (minor differences to TNT4882)
+};
+
+/* nec7210 register numbers (might need to be multiplied by
+ * a board-dependent offset to get actually io address offset)
+ */
+// write registers
+enum nec7210_write_regs {
+ CDOR, // command/data out
+ IMR1, // interrupt mask 1
+ IMR2, // interrupt mask 2
+ SPMR, // serial poll mode
+ ADMR, // address mode
+ AUXMR, // auxiliary mode
+ ADR, // address
+ EOSR, // end-of-string
+
+ // nec7210 has 8 registers
+ nec7210_num_registers = 8,
+};
+
+// read registers
+enum nec7210_read_regs {
+ DIR, // data in
+ ISR1, // interrupt status 1
+ ISR2, // interrupt status 2
+ SPSR, // serial poll status
+ ADSR, // address status
+ CPTR, // command pass though
+ ADR0, // address 1
+ ADR1, // address 2
+};
+
+//bit definitions common to nec-7210 compatible registers
+
+// ISR1: interrupt status register 1
+enum isr1_bits {
+ HR_DI = (1 << 0),
+ HR_DO = (1 << 1),
+ HR_ERR = (1 << 2),
+ HR_DEC = (1 << 3),
+ HR_END = (1 << 4),
+ HR_DET = (1 << 5),
+ HR_APT = (1 << 6),
+ HR_CPT = (1 << 7),
+};
+
+// IMR1: interrupt mask register 1
+enum imr1_bits {
+ HR_DIIE = (1 << 0),
+ HR_DOIE = (1 << 1),
+ HR_ERRIE = (1 << 2),
+ HR_DECIE = (1 << 3),
+ HR_ENDIE = (1 << 4),
+ HR_DETIE = (1 << 5),
+ HR_APTIE = (1 << 6),
+ HR_CPTIE = (1 << 7),
+};
+
+// ISR2, interrupt status register 2
+enum isr2_bits {
+ HR_ADSC = (1 << 0),
+ HR_REMC = (1 << 1),
+ HR_LOKC = (1 << 2),
+ HR_CO = (1 << 3),
+ HR_REM = (1 << 4),
+ HR_LOK = (1 << 5),
+ HR_SRQI = (1 << 6),
+ HR_INT = (1 << 7),
+};
+
+// IMR2, interrupt mask register 2
+enum imr2_bits {
+ // all the bits in this register that enable interrupts
+ IMR2_ENABLE_INTR_MASK = 0x4f,
+ HR_ACIE = (1 << 0),
+ HR_REMIE = (1 << 1),
+ HR_LOKIE = (1 << 2),
+ HR_COIE = (1 << 3),
+ HR_DMAI = (1 << 4),
+ HR_DMAO = (1 << 5),
+ HR_SRQIE = (1 << 6),
+};
+
+// SPSR, serial poll status register
+enum spsr_bits {
+ HR_PEND = (1 << 6),
+};
+
+// SPMR, serial poll mode register
+enum spmr_bits {
+ HR_RSV = (1 << 6),
+};
+
+// ADSR, address status register
+enum adsr_bits {
+ HR_MJMN = (1 << 0),
+ HR_TA = (1 << 1),
+ HR_LA = (1 << 2),
+ HR_TPAS = (1 << 3),
+ HR_LPAS = (1 << 4),
+ HR_SPMS = (1 << 5),
+ HR_NATN = (1 << 6),
+ HR_CIC = (1 << 7),
+};
+
+// ADMR, address mode register
+enum admr_bits {
+ HR_ADM0 = (1 << 0),
+ HR_ADM1 = (1 << 1),
+ HR_TRM0 = (1 << 4),
+ HR_TRM1 = (1 << 5),
+ HR_TRM_EOIOE_TRIG = 0,
+ HR_TRM_CIC_TRIG = HR_TRM0,
+ HR_TRM_CIC_EOIOE = HR_TRM1,
+ HR_TRM_CIC_PE = HR_TRM0 | HR_TRM1,
+ HR_LON = (1 << 6),
+ HR_TON = (1 << 7),
+};
+
+// ADR, bits used in address0, address1 and address0/1 registers
+enum adr_bits {
+ ADDRESS_MASK = 0x1f, /* mask to specify lower 5 bits */
+ HR_DL = (1 << 5),
+ HR_DT = (1 << 6),
+ HR_ARS = (1 << 7),
+};
+
+// ADR1, address1 register
+enum adr1_bits {
+ HR_EOI = (1 << 7),
+};
+
+// AUXMR, auxiliary mode register
+enum auxmr_bits {
+ ICR = 0x20,
+ PPR = 0x60,
+ AUXRA = 0x80,
+ AUXRB = 0xa0,
+ AUXRE = 0xc0,
+};
+
+// auxra, auxiliary register A
+enum auxra_bits {
+ HR_HANDSHAKE_MASK = 0x3,
+ HR_HLDA = 0x1,
+ HR_HLDE = 0x2,
+ HR_LCM = 0x3, /* auxra listen continuous */
+ HR_REOS = 0x4,
+ HR_XEOS = 0x8,
+ HR_BIN = 0x10,
+};
+
+// auxrb, auxiliary register B
+enum auxrb_bits {
+ HR_CPTE = (1 << 0),
+ HR_SPEOI = (1 << 1),
+ HR_TRI = (1 << 2),
+ HR_INV = (1 << 3),
+ HR_ISS = (1 << 4),
+};
+
+enum auxre_bits {
+ HR_DAC_HLD_DCAS = 0x1, /* perform DAC holdoff on receiving clear */
+ HR_DAC_HLD_DTAS = 0x2, /* perform DAC holdoff on receiving trigger */
+};
+
+// parallel poll register
+enum ppr_bits {
+ HR_PPS = (1 << 3),
+ HR_PPU = (1 << 4),
+};
+
+/* 7210 Auxiliary Commands */
+enum aux_cmds {
+ AUX_PON = 0x0, /* Immediate Execute pon */
+ AUX_CPPF = 0x1, /* Clear Parallel Poll Flag */
+ AUX_CR = 0x2, /* Chip Reset */
+ AUX_FH = 0x3, /* Finish Handshake */
+ AUX_TRIG = 0x4, /* Trigger */
+ AUX_RTL = 0x5, /* Return to local */
+ AUX_SEOI = 0x6, /* Send EOI */
+ AUX_NVAL = 0x7, /* Non-Valid Secondary Command or Address */
+ AUX_SPPF = 0x9, /* Set Parallel Poll Flag */
+ AUX_VAL = 0xf, /* Valid Secondary Command or Address */
+ AUX_GTS = 0x10, /* Go To Standby */
+ AUX_TCA = 0x11, /* Take Control Asynchronously */
+ AUX_TCS = 0x12, /* Take Control Synchronously */
+ AUX_LTN = 0x13, /* Listen */
+ AUX_DSC = 0x14, /* Disable System Control */
+ AUX_CIFC = 0x16, /* Clear IFC */
+ AUX_CREN = 0x17, /* Clear REN */
+ AUX_TCSE = 0x1a, /* Take Control Synchronously on End */
+ AUX_LTNC = 0x1b, /* Listen in Continuous Mode */
+ AUX_LUN = 0x1c, /* Local Unlisten */
+ AUX_EPP = 0x1d, /* Execute Parallel Poll */
+ AUX_SIFC = 0x1e, /* Set IFC */
+ AUX_SREN = 0x1f, /* Set REN */
+};
+
+#endif //_NEC7210_REGISTERS_H
diff --git a/drivers/staging/gpib/include/plx9050.h b/drivers/staging/gpib/include/plx9050.h
new file mode 100644
index 000000000000..66c56335f5c0
--- /dev/null
+++ b/drivers/staging/gpib/include/plx9050.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Header for plx9050 pci chip
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _PLX9050_GPIB_H
+#define _PLX9050_GPIB_H
+
+// plx pci chip registers and bits
+enum {
+ PLX9050_INTCSR_REG = 0x4c,
+ PLX9050_CNTRL_REG = 0x50
+};
+
+enum plx9050_intcsr_bits {
+ PLX9050_LINTR1_EN_BIT = 0x1,
+ PLX9050_LINTR1_POLARITY_BIT = 0x2,
+ PLX9050_LINTR1_STATUS_BIT = 0x4,
+ PLX9050_LINTR2_EN_BIT = 0x8,
+ PLX9050_LINTR2_POLARITY_BIT = 0x10,
+ PLX9050_LINTR2_STATUS_BIT = 0x20,
+ PLX9050_PCI_INTR_EN_BIT = 0x40,
+ PLX9050_SOFT_INTR_BIT = 0x80,
+ PLX9050_LINTR1_SELECT_ENABLE_BIT = 0x100, //9052 extension
+ PLX9050_LINTR2_SELECT_ENABLE_BIT = 0x200, //9052 extension
+ PLX9050_LINTR1_EDGE_CLEAR_BIT = 0x400, //9052 extension
+ PLX9050_LINTR2_EDGE_CLEAR_BIT = 0x800, //9052 extension
+};
+
+enum plx9050_cntrl_bits {
+ PLX9050_WAITO_NOT_USER0_SELECT_BIT = 0x1,
+ PLX9050_USER0_OUTPUT_BIT = 0x2,
+ PLX9050_USER0_DATA_BIT = 0x4,
+ PLX9050_LLOCK_NOT_USER1_SELECT_BIT = 0x8,
+ PLX9050_USER1_OUTPUT_BIT = 0x10,
+ PLX9050_USER1_DATA_BIT = 0x20,
+ PLX9050_CS2_NOT_USER2_SELECT_BIT = 0x40,
+ PLX9050_USER2_OUTPUT_BIT = 0x80,
+ PLX9050_USER2_DATA_BIT = 0x100,
+ PLX9050_CS3_NOT_USER3_SELECT_BIT = 0x200,
+ PLX9050_USER3_OUTPUT_BIT = 0x400,
+ PLX9050_USER3_DATA_BIT = 0x800,
+ PLX9050_PCIBAR_ENABLE_MASK = 0x3000,
+ PLX9050_PCIBAR_MEMORY_AND_IO_ENABLE_BITS = 0x0,
+ PLX9050_PCIBAR_MEMORY_NO_IO_ENABLE_BITS = 0x1000,
+ PLX9050_PCIBAR_IO_NO_MEMORY_ENABLE_BITS = 0x2000,
+ PLX9050_PCIBAR_MEMORY_AND_IO_TOO_ENABLE_BITS = 0x3000,
+ PLX9050_PCI_READ_MODE_BIT = 0x4000,
+ PLX9050_PCI_READ_WITH_WRITE_FLUSH_MODE_BIT = 0x8000,
+ PLX9050_PCI_READ_NO_FLUSH_MODE_BIT = 0x10000,
+ PLX9050_PCI_READ_NO_WRITE_MODE_BIT = 0x20000,
+ PLX9050_PCI_WRITE_MODE_BIT = 0x40000,
+ PLX9050_PCI_RETRY_DELAY_MASK = 0x780000,
+ PLX9050_DIRECT_SLAVE_LOCK_ENABLE_BIT = 0x800000,
+ PLX9050_EEPROM_CLOCK_BIT = 0x1000000,
+ PLX9050_EEPROM_CHIP_SELECT_BIT = 0x2000000,
+ PLX9050_WRITE_TO_EEPROM_BIT = 0x4000000,
+ PLX9050_READ_EEPROM_DATA_BIT = 0x8000000,
+ PLX9050_EEPROM_VALID_BIT = 0x10000000,
+ PLX9050_RELOAD_CONFIG_REGISTERS_BIT = 0x20000000,
+ PLX9050_PCI_SOFTWARE_RESET_BIT = 0x40000000,
+ PLX9050_MASK_REVISION_BIT = 0x80000000
+};
+
+static inline unsigned int PLX9050_PCI_RETRY_DELAY_BITS(unsigned int clocks)
+{
+ return ((clocks / 8) << 19) & PLX9050_PCI_RETRY_DELAY_MASK;
+}
+
+#endif // _PLX9050_GPIB_H
diff --git a/drivers/staging/gpib/include/quancom_pci.h b/drivers/staging/gpib/include/quancom_pci.h
new file mode 100644
index 000000000000..cdaf0d056be9
--- /dev/null
+++ b/drivers/staging/gpib/include/quancom_pci.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Quancom pci stuff
+ * copyright (C) 2005 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _QUANCOM_PCI_H
+#define _QUANCOM_PCI_H
+
+/* quancom registers */
+enum quancom_regs {
+ QUANCOM_IRQ_CONTROL_STATUS_REG = 0xfc,
+};
+
+enum quancom_irq_control_status_bits {
+ QUANCOM_IRQ_ASSERTED_BIT = 0x1, /* readable */
+ /* (any write to the register clears the interrupt)*/
+ QUANCOM_IRQ_ENABLE_BIT = 0x4, /* writeable */
+};
+
+#endif // _QUANCOM_PCI_H
diff --git a/drivers/staging/gpib/include/tms9914.h b/drivers/staging/gpib/include/tms9914.h
new file mode 100644
index 000000000000..456b488212d2
--- /dev/null
+++ b/drivers/staging/gpib/include/tms9914.h
@@ -0,0 +1,274 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _TMS9914_H
+#define _TMS9914_H
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include "gpib_state_machines.h"
+#include "gpib_types.h"
+
+enum tms9914_holdoff_mode {
+ TMS9914_HOLDOFF_NONE,
+ TMS9914_HOLDOFF_EOI,
+ TMS9914_HOLDOFF_ALL,
+};
+
+/* struct used to provide variables local to a tms9914 chip */
+struct tms9914_priv {
+ void *iobase;
+ unsigned int offset; // offset between successive tms9914 io addresses
+ unsigned int dma_channel;
+ // software copy of bits written to interrupt mask registers
+ u8 imr0_bits, imr1_bits;
+ // bits written to address mode register
+ u8 admr_bits;
+ u8 auxa_bits; // bits written to auxiliary register A
+ // used to keep track of board's state, bit definitions given below
+ unsigned long state;
+ u8 eos; // eos character
+ short eos_flags;
+ u8 spoll_status;
+ enum tms9914_holdoff_mode holdoff_mode;
+ unsigned int ppoll_line;
+ enum talker_function_state talker_state;
+ enum listener_function_state listener_state;
+ unsigned ppoll_sense : 1;
+ unsigned ppoll_enable : 1;
+ unsigned ppoll_configure_state : 1;
+ unsigned primary_listen_addressed : 1;
+ unsigned primary_talk_addressed : 1;
+ unsigned holdoff_on_end : 1;
+ unsigned holdoff_on_all : 1;
+ unsigned holdoff_active : 1;
+ // wrappers for outb, inb, readb, or writeb
+ u8 (*read_byte)(struct tms9914_priv *priv, unsigned int register_number);
+ void (*write_byte)(struct tms9914_priv *priv, u8 byte, unsigned int
+ register_number);
+};
+
+// slightly shorter way to access read_byte and write_byte
+static inline u8 read_byte(struct tms9914_priv *priv, unsigned int register_number)
+{
+ return priv->read_byte(priv, register_number);
+}
+
+static inline void write_byte(struct tms9914_priv *priv, u8 byte, unsigned int register_number)
+{
+ priv->write_byte(priv, byte, register_number);
+}
+
+// struct tms9914_priv.state bit numbers
+enum {
+ PIO_IN_PROGRESS_BN, // pio transfer in progress
+ DMA_READ_IN_PROGRESS_BN, // dma read transfer in progress
+ DMA_WRITE_IN_PROGRESS_BN, // dma write transfer in progress
+ READ_READY_BN, // board has data byte available to read
+ WRITE_READY_BN, // board is ready to send a data byte
+ COMMAND_READY_BN, // board is ready to send a command byte
+ RECEIVED_END_BN, // received END
+ BUS_ERROR_BN, // bus error
+ DEV_CLEAR_BN, // device clear received
+};
+
+// interface functions
+int tms9914_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read);
+int tms9914_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, int send_eoi, size_t *bytes_written);
+int tms9914_command(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, size_t *bytes_written);
+int tms9914_take_control(gpib_board_t *board, struct tms9914_priv *priv, int syncronous);
+/* alternate version of tms9914_take_control which works around buggy tcs
+ * implementation.
+ */
+int tms9914_take_control_workaround(gpib_board_t *board, struct tms9914_priv *priv,
+ int syncronous);
+int tms9914_go_to_standby(gpib_board_t *board, struct tms9914_priv *priv);
+void tms9914_request_system_control(gpib_board_t *board, struct tms9914_priv *priv,
+ int request_control);
+void tms9914_interface_clear(gpib_board_t *board, struct tms9914_priv *priv, int assert);
+void tms9914_remote_enable(gpib_board_t *board, struct tms9914_priv *priv, int enable);
+int tms9914_enable_eos(gpib_board_t *board, struct tms9914_priv *priv, uint8_t eos_bytes,
+ int compare_8_bits);
+void tms9914_disable_eos(gpib_board_t *board, struct tms9914_priv *priv);
+unsigned int tms9914_update_status(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int clear_mask);
+int tms9914_primary_address(gpib_board_t *board,
+ struct tms9914_priv *priv, unsigned int address);
+int tms9914_secondary_address(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int address, int enable);
+int tms9914_parallel_poll(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *result);
+void tms9914_parallel_poll_configure(gpib_board_t *board,
+ struct tms9914_priv *priv, uint8_t config);
+void tms9914_parallel_poll_response(gpib_board_t *board,
+ struct tms9914_priv *priv, int ist);
+void tms9914_serial_poll_response(gpib_board_t *board, struct tms9914_priv *priv, uint8_t status);
+uint8_t tms9914_serial_poll_status(gpib_board_t *board, struct tms9914_priv *priv);
+int tms9914_line_status(const gpib_board_t *board, struct tms9914_priv *priv);
+unsigned int tms9914_t1_delay(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int nano_sec);
+void tms9914_return_to_local(const gpib_board_t *board, struct tms9914_priv *priv);
+
+// utility functions
+void tms9914_board_reset(struct tms9914_priv *priv);
+void tms9914_online(gpib_board_t *board, struct tms9914_priv *priv);
+void tms9914_release_holdoff(struct tms9914_priv *priv);
+void tms9914_set_holdoff_mode(struct tms9914_priv *priv, enum tms9914_holdoff_mode mode);
+
+// wrappers for io functions
+uint8_t tms9914_ioport_read_byte(struct tms9914_priv *priv, unsigned int register_num);
+void tms9914_ioport_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num);
+uint8_t tms9914_iomem_read_byte(struct tms9914_priv *priv, unsigned int register_num);
+void tms9914_iomem_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num);
+
+// interrupt service routine
+irqreturn_t tms9914_interrupt(gpib_board_t *board, struct tms9914_priv *priv);
+irqreturn_t tms9914_interrupt_have_status(gpib_board_t *board, struct tms9914_priv *priv,
+ int status1, int status2);
+
+// tms9914 has 8 registers
+enum {
+ ms9914_num_registers = 8,
+};
+
+/* tms9914 register numbers (might need to be multiplied by
+ * a board-dependent offset to get actually io address offset)
+ */
+// write registers
+enum {
+ IMR0 = 0, /* interrupt mask 0 */
+ IMR1 = 1, /* interrupt mask 1 */
+ AUXCR = 3, /* auxiliary command */
+ ADR = 4, // address register
+ SPMR = 5, // serial poll mode register
+ PPR = 6, /* parallel poll */
+ CDOR = 7, /* data out register */
+};
+
+// read registers
+enum {
+ ISR0 = 0, /* interrupt status 0 */
+ ISR1 = 1, /* interrupt status 1 */
+ ADSR = 2, /* address status */
+ BSR = 3, /* bus status */
+ CPTR = 6, /* command pass thru */
+ DIR = 7, /* data in register */
+};
+
+//bit definitions common to tms9914 compatible registers
+
+/* ISR0 - Register bits */
+enum isr0_bits {
+ HR_MAC = (1 << 0), /* My Address Change */
+ HR_RLC = (1 << 1), /* Remote/Local change */
+ HR_SPAS = (1 << 2), /* Serial Poll active State */
+ HR_END = (1 << 3), /* END (EOI or EOS) */
+ HR_BO = (1 << 4), /* Byte Out */
+ HR_BI = (1 << 5), /* Byte In */
+};
+
+/* IMR0 - Register bits */
+enum imr0_bits {
+ HR_MACIE = (1 << 0), /* */
+ HR_RLCIE = (1 << 1), /* */
+ HR_SPASIE = (1 << 2), /* */
+ HR_ENDIE = (1 << 3), /* */
+ HR_BOIE = (1 << 4), /* */
+ HR_BIIE = (1 << 5), /* */
+};
+
+/* ISR1 - Register bits */
+enum isr1_bits {
+ HR_IFC = (1 << 0), /* IFC asserted */
+ HR_SRQ = (1 << 1), /* SRQ asserted */
+ HR_MA = (1 << 2), /* My Address */
+ HR_DCAS = (1 << 3), /* Device Clear active State */
+ HR_APT = (1 << 4), /* Address pass Through */
+ HR_UNC = (1 << 5), /* Unrecognized Command */
+ HR_ERR = (1 << 6), /* Data Transmission Error */
+ HR_GET = (1 << 7), /* Group execute Trigger */
+};
+
+/* IMR1 - Register bits */
+enum imr1_bits {
+ HR_IFCIE = (1 << 0), /* */
+ HR_SRQIE = (1 << 1), /* */
+ HR_MAIE = (1 << 2), /* */
+ HR_DCASIE = (1 << 3), /* */
+ HR_APTIE = (1 << 4), /* */
+ HR_UNCIE = (1 << 5), /* */
+ HR_ERRIE = (1 << 6), /* */
+ HR_GETIE = (1 << 7), /* */
+};
+
+/* ADSR - Register bits */
+enum adsr_bits {
+ HR_ULPA = (1 << 0), /* Store last address LSB */
+ HR_TA = (1 << 1), /* Talker Adressed */
+ HR_LA = (1 << 2), /* Listener adressed */
+ HR_TPAS = (1 << 3), /* talker primary address state */
+ HR_LPAS = (1 << 4), /* listener " */
+ HR_ATN = (1 << 5), /* ATN active */
+ HR_LLO = (1 << 6), /* LLO active */
+ HR_REM = (1 << 7), /* REM active */
+};
+
+/* ADR - Register bits */
+enum adr_bits {
+ ADDRESS_MASK = 0x1f, /* mask to specify lower 5 bits for ADR */
+ HR_DAT = (1 << 5), /* disable talker */
+ HR_DAL = (1 << 6), /* disable listener */
+ HR_EDPA = (1 << 7), /* enable dual primary addressing */
+};
+
+enum bus_status_bits {
+ BSR_REN_BIT = 0x1,
+ BSR_IFC_BIT = 0x2,
+ BSR_SRQ_BIT = 0x4,
+ BSR_EOI_BIT = 0x8,
+ BSR_NRFD_BIT = 0x10,
+ BSR_NDAC_BIT = 0x20,
+ BSR_DAV_BIT = 0x40,
+ BSR_ATN_BIT = 0x80,
+};
+
+/*---------------------------------------------------------*/
+/* TMS 9914 Auxiliary Commands */
+/*---------------------------------------------------------*/
+
+enum aux_cmd_bits {
+ AUX_CS = 0x80, /* set bit instead of clearing it, used with commands marked 'd' below */
+ AUX_CHIP_RESET = 0x0, /* d Chip reset */
+ AUX_INVAL = 0x1, // release dac holdoff, invalid command byte
+ AUX_VAL = (AUX_INVAL | AUX_CS), // release dac holdoff, valid command byte
+ AUX_RHDF = 0x2, /* X Release RFD holdoff */
+ AUX_HLDA = 0x3, /* d holdoff on all data */
+ AUX_HLDE = 0x4, /* d holdoff on EOI only */
+ AUX_NBAF = 0x5, /* X Set new byte available false */
+ AUX_FGET = 0x6, /* d force GET */
+ AUX_RTL = 0x7, /* d return to local */
+ AUX_SEOI = 0x8, /* X send EOI with next byte */
+ AUX_LON = 0x9, /* d Listen only */
+ AUX_TON = 0xa, /* d Talk only */
+ AUX_GTS = 0xb, /* X goto standby */
+ AUX_TCA = 0xc, /* X take control asynchronously */
+ AUX_TCS = 0xd, /* X take " synchronously */
+ AUX_RPP = 0xe, /* d Request parallel poll */
+ AUX_SIC = 0xf, /* d send interface clear */
+ AUX_SRE = 0x10, /* d send remote enable */
+ AUX_RQC = 0x11, /* X request control */
+ AUX_RLC = 0x12, /* X release control */
+ AUX_DAI = 0x13, /* d disable all interrupts */
+ AUX_PTS = 0x14, /* X pass through next secondary */
+ AUX_STDL = 0x15, /* d short T1 delay */
+ AUX_SHDW = 0x16, /* d shadow handshake */
+ AUX_VSTDL = 0x17, /* d very short T1 delay (smj9914 extension) */
+ AUX_RSV2 = 0x18, /* d request service bit 2 (smj9914 extension) */
+};
+
+#endif //_TMS9914_H
diff --git a/drivers/staging/gpib/include/tnt4882_registers.h b/drivers/staging/gpib/include/tnt4882_registers.h
new file mode 100644
index 000000000000..1b1441cd03d5
--- /dev/null
+++ b/drivers/staging/gpib/include/tnt4882_registers.h
@@ -0,0 +1,192 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002, 2004 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _TNT4882_REGISTERS_H
+#define _TNT4882_REGISTERS_H
+
+// tnt4882 register offsets
+enum {
+ ACCWR = 0x5,
+ // offset of auxiliary command register in 9914 mode
+ AUXCR = 0x6,
+ INTRT = 0x7,
+ // register number for auxiliary command register when swap bit is set (9914 mode)
+ SWAPPED_AUXCR = 0xa,
+ HSSEL = 0xd, // handshake select register
+ CNT2 = 0x9,
+ CNT3 = 0xb,
+ CFG = 0x10,
+ SASR = 0x1b,
+ IMR0 = 0x1d,
+ IMR3 = 0x12,
+ CNT0 = 0x14,
+ CNT1 = 0x16,
+ KEYREG = 0x17, // key control register (7210 mode only)
+ CSR = KEYREG,
+ FIFOB = 0x18,
+ FIFOA = 0x19,
+ CCR = 0x1a, // carry cycle register
+ CMDR = 0x1c, // command register
+ TIMER = 0x1e, // timer register
+
+ STS1 = 0x10, /* T488 Status Register 1 */
+ STS2 = 0x1c, /* T488 Status Register 2 */
+ ISR0 = IMR0,
+ ISR3 = 0x1a, /* T488 Interrupt Status Register 3 */
+ BCR = 0x1f, /* bus control/status register */
+ BSR = BCR,
+};
+
+enum {
+ tnt_pagein_offset = 0x11,
+};
+
+/*============================================================*/
+
+/* TURBO-488 registers bit definitions */
+
+enum bus_control_status_bits {
+ BCSR_REN_BIT = 0x1,
+ BCSR_IFC_BIT = 0x2,
+ BCSR_SRQ_BIT = 0x4,
+ BCSR_EOI_BIT = 0x8,
+ BCSR_NRFD_BIT = 0x10,
+ BCSR_NDAC_BIT = 0x20,
+ BCSR_DAV_BIT = 0x40,
+ BCSR_ATN_BIT = 0x80,
+};
+
+/* CFG -- Configuration Register (write only) */
+enum cfg_bits {
+ TNT_COMMAND = 0x80, /* bytes are command bytes instead of data bytes
+ * (tnt4882 one-chip and newer only?)
+ */
+ TNT_TLCHE = (1 << 6), /* halt transfer on imr0, imr1, or imr2 interrupt */
+ TNT_IN = (1 << 5), /* transfer is GPIB read */
+ TNT_A_B = (1 << 4), /* order to use fifos 1=fifo A first(big endian),
+ * 0=fifo b first(little endian)
+ */
+ TNT_CCEN = (1 << 3), /* enable carry cycle */
+ TNT_TMOE = (1 << 2), /* enable CPU bus time limit */
+ TNT_TIM_BYTN = (1 << 1), /* tmot reg is: 1=125ns clocks, 0=num bytes */
+ TNT_B_16BIT = (1 << 0), /* 1=FIFO is 16-bit register, 0=8-bit */
+};
+
+/* CMDR -- Command Register */
+enum cmdr_bits {
+ CLRSC = 0x2, /* clear the system controller bit */
+ SETSC = 0x3, /* set the system controller bit */
+ GO = 0x4, /* start fifos */
+ STOP = 0x8, /* stop fifos */
+ RESET_FIFO = 0x10, /* reset the FIFOs */
+ SOFT_RESET = 0x22, /* issue a software reset */
+ HARD_RESET = 0x40 /* 500x only? */
+};
+
+/* HSSEL -- handshake select register (write only) */
+enum hssel_bits {
+ TNT_ONE_CHIP_BIT = 0x1,
+ NODMA = 0x10,
+ TNT_GO2SIDS_BIT = 0x20,
+};
+
+/* IMR0 -- Interrupt Mode Register 0 */
+enum imr0_bits {
+ TNT_SYNCIE_BIT = 0x1, /* handshake sync */
+ TNT_TOIE_BIT = 0x2, /* timeout */
+ TNT_ATNIE_BIT = 0x4, /* ATN interrupt */
+ TNT_IFCIE_BIT = 0x8, /* interface clear interrupt */
+ TNT_BTO_BIT = 0x10, /* byte timeout */
+ TNT_NLEN_BIT = 0x20, /* treat new line as EOS char */
+ TNT_STBOIE_BIT = 0x40, /* status byte out */
+ TNT_IMR0_ALWAYS_BITS = 0x80, /* always set this bit on write */
+};
+
+/* ISR0 -- Interrupt Status Register 0 */
+enum isr0_bits {
+ TNT_SYNC_BIT = 0x1, /* handshake sync */
+ TNT_TO_BIT = 0x2, /* timeout */
+ TNT_ATNI_BIT = 0x4, /* ATN interrupt */
+ TNT_IFCI_BIT = 0x8, /* interface clear interrupt */
+ TNT_EOS_BIT = 0x10, /* end of string */
+ TNT_NL_BIT = 0x20, /* new line receive */
+ TNT_STBO_BIT = 0x40, /* status byte out */
+ TNT_NBA_BIT = 0x80, /* new byte available */
+};
+
+/* ISR3 -- Interrupt Status Register 3 (read only) */
+enum isr3_bits {
+ HR_DONE = (1 << 0), /* transfer done */
+ HR_TLCI = (1 << 1), /* isr0, isr1, or isr2 interrupt asserted */
+ HR_NEF = (1 << 2), /* NOT empty fifo */
+ HR_NFF = (1 << 3), /* NOT full fifo */
+ HR_STOP = (1 << 4), /* fifo empty or STOP command issued */
+ HR_SRQI_CIC = (1 << 5), /* SRQ asserted and we are CIC (500x only?)*/
+ HR_INTR = (1 << 7), /* isr3 interrupt active */
+};
+
+enum keyreg_bits {
+ MSTD = 0x20, // enable 350ns T1 delay
+};
+
+/* STS1 -- Status Register 1 (read only) */
+enum sts1_bits {
+ S_DONE = 0x80, /* DMA done */
+ S_SC = 0x40, /* is system controller */
+ S_IN = 0x20, /* DMA in (to memory) */
+ S_DRQ = 0x10, /* DRQ line (for diagnostics) */
+ S_STOP = 0x08, /* DMA stopped */
+ S_NDAV = 0x04, /* inverse of DAV */
+ S_HALT = 0x02, /* status of transfer machine */
+ S_GSYNC = 0x01, /* indicates if GPIB is in sync w I/O */
+};
+
+/* STS2 -- Status Register 2 */
+enum sts2_bits {
+ AFFN = (1 << 3), /* "A full FIFO NOT" (0=FIFO full) */
+ AEFN = (1 << 2), /* "A empty FIFO NOT" (0=FIFO empty) */
+ BFFN = (1 << 1), /* "B full FIFO NOT" (0=FIFO full) */
+ BEFN = (1 << 0), /* "B empty FIFO NOT" (0=FIFO empty) */
+};
+
+// Auxiliary commands
+enum tnt4882_aux_cmds {
+ AUX_9914 = 0x15, // switch to 9914 mode
+ AUX_REQT = 0x18,
+ AUX_REQF = 0x19,
+ AUX_PAGEIN = 0x50, /* page in alternate registers */
+ AUX_HLDI = 0x51, // rfd holdoff immediately
+ AUX_CLEAR_END = 0x55,
+ AUX_7210 = 0x99, // switch to 7210 mode
+};
+
+enum tnt4882_aux_regs {
+ AUXRG = 0x40,
+ AUXRI = 0xe0,
+};
+
+enum auxg_bits {
+ /* no talking when no listeners bit (prevents bus errors when data written at wrong time) */
+ NTNL_BIT = 0x8,
+ RPP2_BIT = 0x4, /* set/clear local rpp message */
+ CHES_BIT = 0x1, /*clear holdoff on end select bit*/
+};
+
+enum auxi_bits {
+ SISB = 0x1, // static interrupt bits (don't clear isr1, isr2 on read)
+ PP2 = 0x4, // ignore remote parallel poll configuration
+ USTD = 0x8, // ultra short (1100 nanosec) T1 delay
+};
+
+enum sasr_bits {
+ ACRDY_BIT = 0x4, /* acceptor ready state */
+ ADHS_BIT = 0x8, /* acceptor data holdoff state */
+ ANHS2_BIT = 0x10, /* acceptor not ready holdoff immediately state */
+ ANHS1_BIT = 0x20, /* acceptor not ready holdoff state */
+ AEHS_BIT = 0x40, /* acceptor end holdoff state */
+};
+
+#endif // _TNT4882_REGISTERS_H
diff --git a/drivers/staging/gpib/ines/Makefile b/drivers/staging/gpib/ines/Makefile
new file mode 100644
index 000000000000..cdcaa59a4e39
--- /dev/null
+++ b/drivers/staging/gpib/ines/Makefile
@@ -0,0 +1,4 @@
+ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA
+obj-m += ines_gpib.o
+
+
diff --git a/drivers/staging/gpib/ines/ines.h b/drivers/staging/gpib/ines/ines.h
new file mode 100644
index 000000000000..7e8302619998
--- /dev/null
+++ b/drivers/staging/gpib/ines/ines.h
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Header for ines GPIB boards
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _INES_GPIB_H
+#define _INES_GPIB_H
+
+#include "nec7210.h"
+#include "gpibP.h"
+#include "plx9050.h"
+#include "amcc5920.h"
+#include "quancom_pci.h"
+#include <linux/interrupt.h>
+
+enum ines_pci_chip {
+ PCI_CHIP_NONE,
+ PCI_CHIP_PLX9050,
+ PCI_CHIP_AMCC5920,
+ PCI_CHIP_QUANCOM,
+ PCI_CHIP_QUICKLOGIC5030,
+};
+
+struct ines_priv {
+ struct nec7210_priv nec7210_priv;
+ struct pci_dev *pci_device;
+ // base address for plx9052 pci chip
+ unsigned long plx_iobase;
+ // base address for amcc5920 pci chip
+ unsigned long amcc_iobase;
+ unsigned int irq;
+ enum ines_pci_chip pci_chip_type;
+ u8 extend_mode_bits;
+};
+
+// interfaces
+extern gpib_interface_t ines_pci_interface;
+extern gpib_interface_t ines_pci_accel_interface;
+extern gpib_interface_t ines_pcmcia_interface;
+extern gpib_interface_t ines_pcmcia_accel_interface;
+extern gpib_interface_t ines_pcmcia_unaccel_interface;
+
+// interface functions
+int ines_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read);
+int ines_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+int ines_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read);
+int ines_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+int ines_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written);
+int ines_take_control(gpib_board_t *board, int synchronous);
+int ines_go_to_standby(gpib_board_t *board);
+void ines_request_system_control(gpib_board_t *board, int request_control);
+void ines_interface_clear(gpib_board_t *board, int assert);
+void ines_remote_enable(gpib_board_t *board, int enable);
+int ines_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits);
+void ines_disable_eos(gpib_board_t *board);
+unsigned int ines_update_status(gpib_board_t *board, unsigned int clear_mask);
+int ines_primary_address(gpib_board_t *board, unsigned int address);
+int ines_secondary_address(gpib_board_t *board, unsigned int address, int enable);
+int ines_parallel_poll(gpib_board_t *board, uint8_t *result);
+void ines_parallel_poll_configure(gpib_board_t *board, uint8_t config);
+void ines_parallel_poll_response(gpib_board_t *board, int ist);
+void ines_serial_poll_response(gpib_board_t *board, uint8_t status);
+uint8_t ines_serial_poll_status(gpib_board_t *board);
+int ines_line_status(const gpib_board_t *board);
+unsigned int ines_t1_delay(gpib_board_t *board, unsigned int nano_sec);
+void ines_return_to_local(gpib_board_t *board);
+
+// interrupt service routines
+irqreturn_t ines_pci_interrupt(int irq, void *arg);
+irqreturn_t ines_interrupt(gpib_board_t *board);
+
+// utility functions
+void ines_free_private(gpib_board_t *board);
+int ines_generic_attach(gpib_board_t *board);
+void ines_online(struct ines_priv *priv, const gpib_board_t *board, int use_accel);
+void ines_set_xfer_counter(struct ines_priv *priv, unsigned int count);
+
+/* inb/outb wrappers */
+static inline unsigned int ines_inb(struct ines_priv *priv, unsigned int register_number)
+{
+ return inb((unsigned long)(priv->nec7210_priv.iobase) +
+ register_number * priv->nec7210_priv.offset);
+}
+
+static inline void ines_outb(struct ines_priv *priv, unsigned int value,
+ unsigned int register_number)
+{
+ outb(value, (unsigned long)(priv->nec7210_priv.iobase) +
+ register_number * priv->nec7210_priv.offset);
+}
+
+// pcmcia init/cleanup
+
+int ines_pcmcia_init_module(void);
+void ines_pcmcia_cleanup_module(void);
+
+enum ines_regs {
+ // read
+ FIFO_STATUS = 0x8,
+ ISR3 = 0x9,
+ ISR4 = 0xa,
+ IN_FIFO_COUNT = 0x10,
+ OUT_FIFO_COUNT = 0x11,
+ EXTEND_STATUS = 0xf,
+
+ // write
+ XDMA_CONTROL = 0x8,
+ IMR3 = ISR3,
+ IMR4 = ISR4,
+ IN_FIFO_WATERMARK = IN_FIFO_COUNT,
+ OUT_FIFO_WATERMARK = OUT_FIFO_COUNT,
+ EXTEND_MODE = 0xf,
+
+ // read-write
+ XFER_COUNT_LOWER = 0xb,
+ XFER_COUNT_UPPER = 0xc,
+ BUS_CONTROL_MONITOR = 0x13,
+};
+
+enum isr3_imr3_bits {
+ HW_TIMEOUT_BIT = 0x1,
+ XFER_COUNT_BIT = 0x2,
+ CMD_RECEIVED_BIT = 0x4,
+ TCT_RECEIVED_BIT = 0x8,
+ IFC_ACTIVE_BIT = 0x10,
+ ATN_ACTIVE_BIT = 0x20,
+ FIFO_ERROR_BIT = 0x40,
+};
+
+enum isr4_imr4_bits {
+ IN_FIFO_WATERMARK_BIT = 0x1,
+ OUT_FIFO_WATERMARK_BIT = 0x2,
+ IN_FIFO_FULL_BIT = 0x4,
+ OUT_FIFO_EMPTY_BIT = 0x8,
+ IN_FIFO_READY_BIT = 0x10,
+ OUT_FIFO_READY_BIT = 0x20,
+ IN_FIFO_EXIT_WATERMARK_BIT = 0x40,
+ OUT_FIFO_EXIT_WATERMARK_BIT = 0x80,
+};
+
+enum extend_mode_bits {
+ TR3_TRIG_ENABLE_BIT = 0x1, // enable generation of trigger pulse T/R3 pin
+ // clear message available status bit when chip writes byte with EOI true
+ MAV_ENABLE_BIT = 0x2,
+ EOS1_ENABLE_BIT = 0x4, // enable eos register 1
+ EOS2_ENABLE_BIT = 0x8, // enable eos register 2
+ EOIDIS_BIT = 0x10, // disable EOI interrupt when doing rfd holdoff on end?
+ XFER_COUNTER_ENABLE_BIT = 0x20,
+ XFER_COUNTER_OUTPUT_BIT = 0x40, // use counter for output, clear for input
+ // when xfer counter hits 0, assert EOI on write or RFD holdoff on read
+ LAST_BYTE_HANDLING_BIT = 0x80,
+};
+
+enum extend_status_bits {
+ OUTPUT_MESSAGE_IN_PROGRESS_BIT = 0x1,
+ SCSEL_BIT = 0x2, // statue of SCSEL pin
+ LISTEN_DISABLED = 0x4,
+ IN_FIFO_EMPTY_BIT = 0x8,
+ OUT_FIFO_FULL_BIT = 0x10,
+};
+
+// ines adds fifo enable bits to address mode register
+enum ines_admr_bits {
+ IN_FIFO_ENABLE_BIT = 0x8,
+ OUT_FIFO_ENABLE_BIT = 0x4,
+};
+
+enum xdma_control_bits {
+ DMA_OUTPUT_BIT = 0x1, // use dma for output, clear for input
+ ENABLE_SYNC_DMA_BIT = 0x2,
+ DMA_ACCESS_EVERY_CYCLE = 0x4,// dma accesses fifo every cycle, clear for every other cycle
+ DMA_16BIT = 0x8, // clear for 8 bit transfers
+};
+
+enum bus_control_monitor_bits {
+ BCM_DAV_BIT = 0x1,
+ BCM_NRFD_BIT = 0x2,
+ BCM_NDAC_BIT = 0x4,
+ BCM_IFC_BIT = 0x8,
+ BCM_ATN_BIT = 0x10,
+ BCM_SRQ_BIT = 0x20,
+ BCM_REN_BIT = 0x40,
+ BCM_EOI_BIT = 0x80,
+};
+
+enum ines_aux_reg_bits {
+ INES_AUXD = 0x40,
+};
+
+enum ines_aux_cmds {
+ INES_RFD_HLD_IMMEDIATE = 0x4,
+ INES_AUX_CLR_OUT_FIFO = 0x5,
+ INES_AUX_CLR_IN_FIFO = 0x6,
+ INES_AUX_XMODE = 0xa,
+};
+
+enum ines_auxd_bits {
+ INES_FOLLOWING_T1_MASK = 0x3,
+ INES_FOLLOWING_T1_500ns = 0x0,
+ INES_FOLLOWING_T1_350ns = 0x1,
+ INES_FOLLOWING_T1_250ns = 0x2,
+ INES_INITIAL_TI_MASK = 0xc,
+ INES_INITIAL_T1_2000ns = 0x0,
+ INES_INITIAL_T1_1100ns = 0x4,
+ INES_INITIAL_T1_700ns = 0x8,
+ INES_T6_2us = 0x0,
+ INES_T6_50us = 0x10,
+};
+
+#endif // _INES_GPIB_H
diff --git a/drivers/staging/gpib/ines/ines_gpib.c b/drivers/staging/gpib/ines/ines_gpib.c
new file mode 100644
index 000000000000..9d8387c3bf01
--- /dev/null
+++ b/drivers/staging/gpib/ines/ines_gpib.c
@@ -0,0 +1,1464 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 1999 Axel Dziemba (axel.dziemba@ines.de)
+ * (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "ines.h"
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/bitops.h>
+#include <asm/dma.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include "gpib_pci_ids.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for Ines iGPIB 72010");
+
+int ines_line_status(const gpib_board_t *board)
+{
+ int status = ValidALL;
+ int bcm_bits;
+ struct ines_priv *ines_priv;
+ struct nec7210_priv *nec_priv;
+
+ ines_priv = board->private_data;
+ nec_priv = &ines_priv->nec7210_priv;
+
+ bcm_bits = ines_inb(ines_priv, BUS_CONTROL_MONITOR);
+
+ if (bcm_bits & BCM_REN_BIT)
+ status |= BusREN;
+ if (bcm_bits & BCM_IFC_BIT)
+ status |= BusIFC;
+ if (bcm_bits & BCM_SRQ_BIT)
+ status |= BusSRQ;
+ if (bcm_bits & BCM_EOI_BIT)
+ status |= BusEOI;
+ if (bcm_bits & BCM_NRFD_BIT)
+ status |= BusNRFD;
+ if (bcm_bits & BCM_NDAC_BIT)
+ status |= BusNDAC;
+ if (bcm_bits & BCM_DAV_BIT)
+ status |= BusDAV;
+ if (bcm_bits & BCM_ATN_BIT)
+ status |= BusATN;
+
+ return status;
+}
+
+void ines_set_xfer_counter(struct ines_priv *priv, unsigned int count)
+{
+ if (count > 0xffff) {
+ pr_err("ines: bug! tried to set xfer counter > 0xffff\n");
+ return;
+ }
+ ines_outb(priv, (count >> 8) & 0xff, XFER_COUNT_UPPER);
+ ines_outb(priv, count & 0xff, XFER_COUNT_LOWER);
+}
+
+unsigned int ines_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct ines_priv *ines_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv;
+ unsigned int retval;
+
+ retval = nec7210_t1_delay(board, nec_priv, nano_sec);
+
+ if (nano_sec <= 250) {
+ write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_250ns |
+ INES_INITIAL_T1_2000ns, AUXMR);
+ retval = 250;
+ } else if (nano_sec <= 350) {
+ write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_350ns |
+ INES_INITIAL_T1_2000ns, AUXMR);
+ retval = 350;
+ } else {
+ write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_500ns |
+ INES_INITIAL_T1_2000ns, AUXMR);
+ retval = 500;
+ }
+
+ return retval;
+}
+
+static inline unsigned short num_in_fifo_bytes(struct ines_priv *ines_priv)
+{
+ return ines_inb(ines_priv, IN_FIFO_COUNT);
+}
+
+static ssize_t pio_read(gpib_board_t *board, struct ines_priv *ines_priv, uint8_t *buffer,
+ size_t length, size_t *nbytes)
+{
+ ssize_t retval = 0;
+ unsigned int num_fifo_bytes, i;
+ struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv;
+
+ *nbytes = 0;
+ while (*nbytes < length) {
+ if (wait_event_interruptible(board->wait,
+ num_in_fifo_bytes(ines_priv) ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_warn("gpib: pio read wait interrupted\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ return -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ return -EINTR;
+
+ num_fifo_bytes = num_in_fifo_bytes(ines_priv);
+ if (num_fifo_bytes + *nbytes > length) {
+ pr_warn("ines: counter allowed %li extra byte(s)\n",
+ (long)(num_fifo_bytes - (length - *nbytes)));
+ num_fifo_bytes = length - *nbytes;
+ }
+ for (i = 0; i < num_fifo_bytes; i++)
+ buffer[(*nbytes)++] = read_byte(nec_priv, DIR);
+ if (test_bit(RECEIVED_END_BN, &nec_priv->state) &&
+ num_in_fifo_bytes(ines_priv) == 0)
+ break;
+ if (need_resched())
+ schedule();
+ }
+ /* make sure RECEIVED_END is in sync */
+ ines_interrupt(board);
+ return retval;
+}
+
+int ines_accel_read(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval = 0;
+ struct ines_priv *ines_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv;
+ int counter_setting;
+
+ *end = 0;
+ *bytes_read = 0;
+ if (length == 0)
+ return 0;
+
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state);
+
+ write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR);
+
+ //clear in fifo
+ nec7210_set_reg_bits(nec_priv, ADMR, IN_FIFO_ENABLE_BIT, 0);
+ nec7210_set_reg_bits(nec_priv, ADMR, IN_FIFO_ENABLE_BIT, IN_FIFO_ENABLE_BIT);
+
+ ines_priv->extend_mode_bits |= LAST_BYTE_HANDLING_BIT;
+ ines_priv->extend_mode_bits &= ~XFER_COUNTER_OUTPUT_BIT & ~XFER_COUNTER_ENABLE_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+
+ counter_setting = length - num_in_fifo_bytes(ines_priv);
+ if (counter_setting > 0) {
+ ines_set_xfer_counter(ines_priv, length);
+ ines_priv->extend_mode_bits |= XFER_COUNTER_ENABLE_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+
+ // holdoff on END
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDE);
+ /* release rfd holdoff */
+ write_byte(nec_priv, AUX_FH, AUXMR);
+ }
+
+ retval = pio_read(board, ines_priv, buffer, length, bytes_read);
+ ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+ if (retval < 0) {
+ write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR);
+ return retval;
+ }
+ if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state))
+ *end = 1;
+
+ return retval;
+}
+
+static const int out_fifo_size = 0xff;
+
+static inline unsigned short num_out_fifo_bytes(struct ines_priv *ines_priv)
+{
+ return ines_inb(ines_priv, OUT_FIFO_COUNT);
+}
+
+static int ines_write_wait(gpib_board_t *board, struct ines_priv *ines_priv,
+ unsigned int fifo_threshold)
+{
+ struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv;
+
+ // wait until byte is ready to be sent
+ if (wait_event_interruptible(board->wait,
+ num_out_fifo_bytes(ines_priv) < fifo_threshold ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(BUS_ERROR_BN, &nec_priv->state))
+ return -EIO;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ return -EINTR;
+ if (test_bit(TIMO_NUM, &board->status))
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+int ines_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ size_t count = 0;
+ ssize_t retval = 0;
+ struct ines_priv *ines_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv;
+ unsigned int num_bytes, i;
+
+ *bytes_written = 0;
+ //clear out fifo
+ nec7210_set_reg_bits(nec_priv, ADMR, OUT_FIFO_ENABLE_BIT, 0);
+ nec7210_set_reg_bits(nec_priv, ADMR, OUT_FIFO_ENABLE_BIT, OUT_FIFO_ENABLE_BIT);
+
+ ines_priv->extend_mode_bits |= XFER_COUNTER_OUTPUT_BIT;
+ ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT;
+ ines_priv->extend_mode_bits &= ~LAST_BYTE_HANDLING_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+
+ ines_set_xfer_counter(ines_priv, length);
+ if (send_eoi)
+ ines_priv->extend_mode_bits |= LAST_BYTE_HANDLING_BIT;
+ ines_priv->extend_mode_bits |= XFER_COUNTER_ENABLE_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+
+ while (count < length) {
+ retval = ines_write_wait(board, ines_priv, out_fifo_size);
+ if (retval < 0)
+ break;
+
+ num_bytes = out_fifo_size - num_out_fifo_bytes(ines_priv);
+ if (num_bytes + count > length)
+ num_bytes = length - count;
+ for (i = 0; i < num_bytes; i++)
+ write_byte(nec_priv, buffer[count++], CDOR);
+ }
+ if (retval < 0) {
+ ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+ *bytes_written = length - num_out_fifo_bytes(ines_priv);
+ return retval;
+ }
+ // wait last byte has been sent
+ retval = ines_write_wait(board, ines_priv, 1);
+ ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+ *bytes_written = length - num_out_fifo_bytes(ines_priv);
+
+ return retval;
+}
+
+irqreturn_t ines_pci_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct ines_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ if (priv->pci_chip_type == PCI_CHIP_QUANCOM) {
+ if ((inb((unsigned long)nec_priv->iobase +
+ QUANCOM_IRQ_CONTROL_STATUS_REG) &
+ QUANCOM_IRQ_ASSERTED_BIT))
+ outb(QUANCOM_IRQ_ENABLE_BIT, (unsigned long)(nec_priv->iobase) +
+ QUANCOM_IRQ_CONTROL_STATUS_REG);
+ }
+
+ return ines_interrupt(board);
+}
+
+irqreturn_t ines_interrupt(gpib_board_t *board)
+{
+ struct ines_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+ unsigned int isr3_bits, isr4_bits;
+ unsigned long flags;
+ int wake = 0;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ nec7210_interrupt(board, nec_priv);
+ isr3_bits = ines_inb(priv, ISR3);
+ isr4_bits = ines_inb(priv, ISR4);
+ if (isr3_bits & IFC_ACTIVE_BIT) {
+ push_gpib_event(board, EventIFC);
+ wake++;
+ }
+ if (isr3_bits & FIFO_ERROR_BIT)
+ pr_err("ines gpib: fifo error\n");
+ if (isr3_bits & XFER_COUNT_BIT)
+ wake++;
+
+ if (isr4_bits & (IN_FIFO_WATERMARK_BIT | IN_FIFO_FULL_BIT | OUT_FIFO_WATERMARK_BIT |
+ OUT_FIFO_EMPTY_BIT))
+ wake++;
+
+ if (wake)
+ wake_up_interruptible(&board->wait);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return IRQ_HANDLED;
+}
+
+static int ines_pci_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int ines_pci_accel_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int ines_isa_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void ines_pci_detach(gpib_board_t *board);
+static void ines_isa_detach(gpib_board_t *board);
+
+enum ines_pci_vendor_ids {
+ PCI_VENDOR_ID_INES_QUICKLOGIC = 0x16da
+};
+
+enum ines_pci_device_ids {
+ PCI_DEVICE_ID_INES_GPIB_AMCC = 0x8507,
+ PCI_DEVICE_ID_INES_GPIB_QL5030 = 0x11,
+};
+
+enum ines_pci_subdevice_ids {
+ PCI_SUBDEVICE_ID_INES_GPIB = 0x1072
+};
+
+static struct pci_device_id ines_pci_table[] = {
+ {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX,
+ PCI_SUBDEVICE_ID_INES_GPIB, 0, 0, 0},
+ {PCI_VENDOR_ID_AMCC, PCI_DEVICE_ID_INES_GPIB_AMCC, PCI_VENDOR_ID_AMCC,
+ PCI_SUBDEVICE_ID_INES_GPIB, 0, 0, 0},
+ {PCI_VENDOR_ID_INES_QUICKLOGIC, PCI_DEVICE_ID_INES_GPIB_QL5030,
+ PCI_VENDOR_ID_INES_QUICKLOGIC, PCI_DEVICE_ID_INES_GPIB_QL5030, 0, 0, 0},
+ {PCI_DEVICE(PCI_VENDOR_ID_QUANCOM, PCI_DEVICE_ID_QUANCOM_GPIB)},
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, ines_pci_table);
+
+struct ines_pci_id {
+ unsigned int vendor_id;
+ unsigned int device_id;
+ int subsystem_vendor_id;
+ int subsystem_device_id;
+ unsigned int gpib_region;
+ unsigned int io_offset;
+ enum ines_pci_chip pci_chip_type;
+};
+
+struct ines_pci_id pci_ids[] = {
+ {vendor_id: PCI_VENDOR_ID_PLX,
+ device_id : PCI_DEVICE_ID_PLX_9050,
+ subsystem_vendor_id : PCI_VENDOR_ID_PLX,
+ subsystem_device_id : PCI_SUBDEVICE_ID_INES_GPIB,
+ gpib_region : 2,
+ io_offset : 1,
+ pci_chip_type : PCI_CHIP_PLX9050,
+ },
+ {vendor_id: PCI_VENDOR_ID_AMCC,
+ device_id : PCI_DEVICE_ID_INES_GPIB_AMCC,
+ subsystem_vendor_id : PCI_VENDOR_ID_AMCC,
+ subsystem_device_id : PCI_SUBDEVICE_ID_INES_GPIB,
+ gpib_region : 1,
+ io_offset : 1,
+ pci_chip_type : PCI_CHIP_AMCC5920,
+ },
+ {vendor_id: PCI_VENDOR_ID_INES_QUICKLOGIC,
+ device_id : PCI_DEVICE_ID_INES_GPIB_QL5030,
+ subsystem_vendor_id : PCI_VENDOR_ID_INES_QUICKLOGIC,
+ subsystem_device_id : PCI_DEVICE_ID_INES_GPIB_QL5030,
+ gpib_region : 1,
+ io_offset : 1,
+ pci_chip_type : PCI_CHIP_QUICKLOGIC5030,
+ },
+ {vendor_id: PCI_VENDOR_ID_QUANCOM,
+ device_id : PCI_DEVICE_ID_QUANCOM_GPIB,
+ subsystem_vendor_id : -1,
+ subsystem_device_id : -1,
+ gpib_region : 0,
+ io_offset : 4,
+ pci_chip_type : PCI_CHIP_QUANCOM,
+ },
+};
+
+static const int num_pci_chips = ARRAY_SIZE(pci_ids);
+
+// wrappers for interface functions
+int ines_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
+{
+ struct ines_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+ ssize_t retval;
+ int dummy;
+
+ retval = nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+ if (retval < 0) {
+ write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR);
+
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+
+ nec7210_read_data_in(board, nec_priv, &dummy);
+ }
+ return retval;
+}
+
+int ines_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int ines_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+int ines_take_control(gpib_board_t *board, int synchronous)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+int ines_go_to_standby(gpib_board_t *board)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+void ines_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_request_system_control(board, &priv->nec7210_priv, request_control);
+}
+
+void ines_interface_clear(gpib_board_t *board, int assert)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+void ines_remote_enable(gpib_board_t *board, int enable)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+int ines_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+void ines_disable_eos(gpib_board_t *board)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+unsigned int ines_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
+}
+
+int ines_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+int ines_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+int ines_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
+}
+
+void ines_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config);
+}
+
+void ines_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+void ines_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
+}
+
+uint8_t ines_serial_poll_status(gpib_board_t *board)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+void ines_return_to_local(gpib_board_t *board)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_return_to_local(board, &priv->nec7210_priv);
+}
+
+gpib_interface_t ines_pci_unaccel_interface = {
+name: "ines_pci_unaccel",
+attach : ines_pci_attach,
+detach : ines_pci_detach,
+read : ines_read,
+write : ines_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+gpib_interface_t ines_pci_interface = {
+name: "ines_pci",
+attach : ines_pci_accel_attach,
+detach : ines_pci_detach,
+read : ines_accel_read,
+write : ines_accel_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+gpib_interface_t ines_pci_accel_interface = {
+name: "ines_pci_accel",
+attach : ines_pci_accel_attach,
+detach : ines_pci_detach,
+read : ines_accel_read,
+write : ines_accel_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+gpib_interface_t ines_isa_interface = {
+name: "ines_isa",
+attach : ines_isa_attach,
+detach : ines_isa_detach,
+read : ines_accel_read,
+write : ines_accel_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+static int ines_allocate_private(gpib_board_t *board)
+{
+ struct ines_priv *priv;
+
+ board->private_data = kmalloc(sizeof(struct ines_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ priv = board->private_data;
+ memset(priv, 0, sizeof(struct ines_priv));
+ init_nec7210_private(&priv->nec7210_priv);
+ return 0;
+}
+
+void ines_free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+int ines_generic_attach(gpib_board_t *board)
+{
+ struct ines_priv *ines_priv;
+ struct nec7210_priv *nec_priv;
+
+ board->status = 0;
+
+ if (ines_allocate_private(board))
+ return -ENOMEM;
+ ines_priv = board->private_data;
+ nec_priv = &ines_priv->nec7210_priv;
+ nec_priv->read_byte = nec7210_ioport_read_byte;
+ nec_priv->write_byte = nec7210_ioport_write_byte;
+ nec_priv->offset = 1;
+ nec_priv->type = IGPIB7210;
+ ines_priv->pci_chip_type = PCI_CHIP_NONE;
+
+ return 0;
+}
+
+void ines_online(struct ines_priv *ines_priv, const gpib_board_t *board, int use_accel)
+{
+ struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv;
+
+ /* ines doesn't seem to use internal count register */
+ write_byte(nec_priv, ICR | 0, AUXMR);
+
+ write_byte(nec_priv, INES_AUX_XMODE, AUXMR);
+ write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR);
+
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+
+ write_byte(nec_priv, INES_AUXD | 0, AUXMR);
+ ines_outb(ines_priv, 0, XDMA_CONTROL);
+ ines_priv->extend_mode_bits = 0;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+ if (use_accel) {
+ ines_outb(ines_priv, 0x80, OUT_FIFO_WATERMARK);
+ ines_outb(ines_priv, 0x80, IN_FIFO_WATERMARK);
+ ines_outb(ines_priv, IFC_ACTIVE_BIT | ATN_ACTIVE_BIT |
+ FIFO_ERROR_BIT | XFER_COUNT_BIT, IMR3);
+ ines_outb(ines_priv, IN_FIFO_WATERMARK_BIT | IN_FIFO_FULL_BIT |
+ OUT_FIFO_WATERMARK_BIT | OUT_FIFO_EMPTY_BIT, IMR4);
+ } else {
+ nec7210_set_reg_bits(nec_priv, ADMR, IN_FIFO_ENABLE_BIT | OUT_FIFO_ENABLE_BIT, 0);
+ ines_outb(ines_priv, IFC_ACTIVE_BIT | FIFO_ERROR_BIT, IMR3);
+ ines_outb(ines_priv, 0, IMR4);
+ }
+
+ nec7210_board_online(nec_priv, board);
+ if (use_accel)
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, 0);
+}
+
+static int ines_common_pci_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct ines_priv *ines_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = 0;
+ int retval;
+ struct ines_pci_id found_id;
+ unsigned int i;
+ struct pci_dev *pdev;
+
+ memset(&found_id, 0, sizeof(found_id));
+
+ retval = ines_generic_attach(board);
+ if (retval)
+ return retval;
+
+ ines_priv = board->private_data;
+ nec_priv = &ines_priv->nec7210_priv;
+
+ // find board
+ ines_priv->pci_device = NULL;
+ for (i = 0; i < num_pci_chips && !ines_priv->pci_device; i++) {
+ pdev = NULL;
+ do {
+ if (pci_ids[i].subsystem_vendor_id >= 0 &&
+ pci_ids[i].subsystem_device_id >= 0)
+ pdev = pci_get_subsys(pci_ids[i].vendor_id, pci_ids[i].device_id,
+ pci_ids[i].subsystem_vendor_id,
+ pci_ids[i].subsystem_device_id, pdev);
+ else
+ pdev = pci_get_device(pci_ids[i].vendor_id, pci_ids[i].device_id,
+ pdev);
+ if (!pdev)
+ break;
+ if (config->pci_bus >= 0 && config->pci_bus != pdev->bus->number)
+ continue;
+ if (config->pci_slot >= 0 && config->pci_slot != PCI_SLOT(pdev->devfn))
+ continue;
+ found_id = pci_ids[i];
+ ines_priv->pci_device = pdev;
+ break;
+ } while (1);
+ }
+ if (!ines_priv->pci_device) {
+ pr_err("gpib: could not find ines PCI board\n");
+ return -1;
+ }
+
+ if (pci_enable_device(ines_priv->pci_device)) {
+ pr_err("error enabling pci device\n");
+ return -1;
+ }
+
+ if (pci_request_regions(ines_priv->pci_device, "ines-gpib"))
+ return -1;
+ nec_priv->iobase = (void *)(pci_resource_start(ines_priv->pci_device,
+ found_id.gpib_region));
+
+ ines_priv->pci_chip_type = found_id.pci_chip_type;
+ nec_priv->offset = found_id.io_offset;
+ switch (ines_priv->pci_chip_type) {
+ case PCI_CHIP_PLX9050:
+ ines_priv->plx_iobase = pci_resource_start(ines_priv->pci_device, 1);
+ break;
+ case PCI_CHIP_AMCC5920:
+ ines_priv->amcc_iobase = pci_resource_start(ines_priv->pci_device, 0);
+ break;
+ case PCI_CHIP_QUANCOM:
+ break;
+ case PCI_CHIP_QUICKLOGIC5030:
+ break;
+ default:
+ pr_err("gpib: unspecified chip type? (bug)\n");
+ nec_priv->iobase = 0;
+ pci_release_regions(ines_priv->pci_device);
+ return -1;
+ }
+
+ nec7210_board_reset(nec_priv, board);
+#ifdef QUANCOM_PCI
+ if (ines_priv->pci_chip_type == PCI_CHIP_QUANCOM) {
+ /* change interrupt polarity */
+ nec_priv->auxb_bits |= HR_INV;
+ ines_outb(ines_priv, nec_priv->auxb_bits, AUXMR);
+ }
+#endif
+ isr_flags |= IRQF_SHARED;
+ if (request_irq(ines_priv->pci_device->irq, ines_pci_interrupt, isr_flags,
+ "pci-gpib", board)) {
+ pr_err("gpib: can't request IRQ %d\n", ines_priv->pci_device->irq);
+ return -1;
+ }
+ ines_priv->irq = ines_priv->pci_device->irq;
+
+ // enable interrupts on pci chip
+ switch (ines_priv->pci_chip_type) {
+ case PCI_CHIP_PLX9050:
+ outl(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR1_POLARITY_BIT | PLX9050_PCI_INTR_EN_BIT,
+ ines_priv->plx_iobase + PLX9050_INTCSR_REG);
+ break;
+ case PCI_CHIP_AMCC5920:
+ {
+ static const int region = 1;
+ static const int num_wait_states = 7;
+ u32 bits;
+
+ bits = amcc_prefetch_bits(region, PREFETCH_DISABLED);
+ bits |= amcc_PTADR_mode_bit(region);
+ bits |= amcc_disable_write_fifo_bit(region);
+ bits |= amcc_wait_state_bits(region, num_wait_states);
+ outl(bits, ines_priv->amcc_iobase + AMCC_PASS_THRU_REG);
+ outl(AMCC_ADDON_INTR_ENABLE_BIT, ines_priv->amcc_iobase + AMCC_INTCS_REG);
+ }
+ break;
+ case PCI_CHIP_QUANCOM:
+ outb(QUANCOM_IRQ_ENABLE_BIT, (unsigned long)(nec_priv->iobase) +
+ QUANCOM_IRQ_CONTROL_STATUS_REG);
+ break;
+ case PCI_CHIP_QUICKLOGIC5030:
+ break;
+ default:
+ pr_err("gpib: unspecified chip type? (bug)\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int ines_pci_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct ines_priv *ines_priv;
+ int retval;
+
+ retval = ines_common_pci_attach(board, config);
+ if (retval < 0)
+ return retval;
+
+ ines_priv = board->private_data;
+ ines_online(ines_priv, board, 0);
+
+ return 0;
+}
+
+int ines_pci_accel_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct ines_priv *ines_priv;
+ int retval;
+
+ retval = ines_common_pci_attach(board, config);
+ if (retval < 0)
+ return retval;
+
+ ines_priv = board->private_data;
+ ines_online(ines_priv, board, 1);
+
+ return 0;
+}
+
+static const int ines_isa_iosize = 0x20;
+
+int ines_isa_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct ines_priv *ines_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = 0;
+ int retval;
+
+ retval = ines_generic_attach(board);
+ if (retval)
+ return retval;
+
+ ines_priv = board->private_data;
+ nec_priv = &ines_priv->nec7210_priv;
+
+ if (!request_region((unsigned long)config->ibbase, ines_isa_iosize, "ines_gpib")) {
+ pr_err("ines_gpib: ioports at 0x%p already in use\n", config->ibbase);
+ return -1;
+ }
+ nec_priv->iobase = config->ibbase;
+ nec_priv->offset = 1;
+ nec7210_board_reset(nec_priv, board);
+ if (request_irq(config->ibirq, ines_pci_interrupt, isr_flags, "ines_gpib", board)) {
+ pr_err("ines_gpib: failed to allocate IRQ %d\n", config->ibirq);
+ return -1;
+ }
+ ines_priv->irq = config->ibirq;
+ ines_online(ines_priv, board, 1);
+ return 0;
+}
+
+void ines_pci_detach(gpib_board_t *board)
+{
+ struct ines_priv *ines_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (ines_priv) {
+ nec_priv = &ines_priv->nec7210_priv;
+ if (ines_priv->irq) {
+ // disable interrupts
+ switch (ines_priv->pci_chip_type) {
+ case PCI_CHIP_AMCC5920:
+ if (ines_priv->plx_iobase)
+ outl(0, ines_priv->plx_iobase + PLX9050_INTCSR_REG);
+ break;
+ case PCI_CHIP_QUANCOM:
+ if (nec_priv->iobase)
+ outb(0, (unsigned long)(nec_priv->iobase) +
+ QUANCOM_IRQ_CONTROL_STATUS_REG);
+ break;
+ default:
+ break;
+ }
+ free_irq(ines_priv->irq, board);
+ }
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ pci_release_regions(ines_priv->pci_device);
+ }
+ if (ines_priv->pci_device)
+ pci_dev_put(ines_priv->pci_device);
+ }
+ ines_free_private(board);
+}
+
+void ines_isa_detach(gpib_board_t *board)
+{
+ struct ines_priv *ines_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (ines_priv) {
+ nec_priv = &ines_priv->nec7210_priv;
+ if (ines_priv->irq)
+ free_irq(ines_priv->irq, board);
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ release_region((unsigned long)(nec_priv->iobase), ines_isa_iosize);
+ }
+ }
+ ines_free_private(board);
+}
+
+static int ines_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ return 0;
+}
+
+static struct pci_driver ines_pci_driver = {
+ .name = "ines_gpib",
+ .id_table = ines_pci_table,
+ .probe = &ines_pci_probe
+};
+
+#ifdef GPIB_PCMCIA
+
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+#define DEBUG(n, args...) do {if (pc_debug > (n)) pr_debug(args)} while (0)
+#else
+#define DEBUG(args...)
+#endif
+
+static const int ines_pcmcia_iosize = 0x20;
+
+/* The event() function is this driver's Card Services event handler.
+ * It will be called by Card Services when an appropriate card status
+ * event is received. The config() and release() entry points are
+ * used to configure or release a socket, in response to card insertion
+ * and ejection events. They are invoked from the gpib event
+ * handler.
+ */
+
+static int ines_gpib_config(struct pcmcia_device *link);
+static void ines_gpib_release(struct pcmcia_device *link);
+static int ines_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int ines_pcmcia_accel_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static void ines_pcmcia_detach(gpib_board_t *board);
+static irqreturn_t ines_pcmcia_interrupt(int irq, void *arg);
+static int ines_common_pcmcia_attach(gpib_board_t *board);
+/*
+ * A linked list of "instances" of the gpib device. Each actual
+ * PCMCIA card corresponds to one device instance, and is described
+ * by one dev_link_t structure (defined in ds.h).
+ *
+ * You may not want to use a linked list for this -- for example, the
+ * memory card driver uses an array of dev_link_t pointers, where minor
+ * device numbers are used to derive the corresponding array index.
+ */
+
+static struct pcmcia_device *curr_dev;
+
+/*
+ * A dev_link_t structure has fields for most things that are needed
+ * to keep track of a socket, but there will usually be some device
+ * specific information that also needs to be kept track of. The
+ * 'priv' pointer in a dev_link_t structure can be used to point to
+ * a device-specific private data structure, like this.
+ *
+ * A driver needs to provide a dev_node_t structure for each device
+ * on a card. In some cases, there is only one device per card (for
+ * example, ethernet cards, modems). In other cases, there may be
+ * many actual or logical devices (SCSI adapters, memory cards with
+ * multiple partitions). The dev_node_t structures need to be kept
+ * in a linked list starting at the 'dev' field of a dev_link_t
+ * structure. We allocate them in the card's private data structure,
+ * because they generally can't be allocated dynamically.
+ */
+
+struct local_info {
+ struct pcmcia_device *p_dev;
+ gpib_board_t *dev;
+ u_short manfid;
+ u_short cardid;
+};
+
+/*
+ * gpib_attach() creates an "instance" of the driver, allocating
+ * local data structures for one device. The device is registered
+ * with Card Services.
+ *
+ * The dev_link structure is initialized, but we don't actually
+ * configure the card at this point -- we wait until we receive a
+ * card insertion event.
+ */
+static int ines_gpib_probe(struct pcmcia_device *link)
+{
+ struct local_info *info;
+
+// int ret, i;
+
+ DEBUG(0, "%s(0x%p)\n", __func__ link);
+
+ /* Allocate space for private device-specific data */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->p_dev = link;
+ link->priv = info;
+
+ /* The io structure describes IO port mapping */
+ link->resource[0]->end = 32;
+ link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+ link->io_lines = 5;
+
+ /* General socket configuration */
+ link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
+ /* Register with Card Services */
+ curr_dev = link;
+ return ines_gpib_config(link);
+}
+
+/*
+ * This deletes a driver "instance". The device is de-registered
+ * with Card Services. If it has been released, all local data
+ * structures are freed. Otherwise, the structures will be freed
+ * when the device is released.
+ */
+static void ines_gpib_remove(struct pcmcia_device *link)
+{
+ struct local_info *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ if (info->dev)
+ ines_pcmcia_detach(info->dev);
+ ines_gpib_release(link);
+
+ //free_netdev(dev);
+ kfree(info);
+}
+
+static int ines_gpib_config_iteration(struct pcmcia_device *link, void *priv_data)
+{
+ return pcmcia_request_io(link);
+}
+
+/*
+ * gpib_config() is scheduled to run after a CARD_INSERTION event
+ * is received, to configure the PCMCIA socket, and to make the
+ * device available to the system.
+ */
+static int ines_gpib_config(struct pcmcia_device *link)
+{
+ struct local_info *dev;
+ int retval;
+ void *virt;
+
+ dev = link->priv;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ retval = pcmcia_loop_config(link, &ines_gpib_config_iteration, NULL);
+ if (retval) {
+ dev_warn(&link->dev, "no configuration found\n");
+ ines_gpib_release(link);
+ return -ENODEV;
+ }
+
+ pr_debug("ines_cs: manufacturer: 0x%x card: 0x%x\n",
+ link->manf_id, link->card_id);
+
+ /* for the ines card we have to setup the configuration registers in
+ * attribute memory here
+ */
+ link->resource[2]->flags |= WIN_MEMORY_TYPE_AM | WIN_DATA_WIDTH_8 | WIN_ENABLE;
+ link->resource[2]->end = 0x1000;
+ retval = pcmcia_request_window(link, link->resource[2], 250);
+ if (retval) {
+ dev_warn(&link->dev, "pcmcia_request_window failed\n");
+ ines_gpib_release(link);
+ return -ENODEV;
+ }
+ retval = pcmcia_map_mem_page(link, link->resource[2], 0);
+ if (retval) {
+ dev_warn(&link->dev, "pcmcia_map_mem_page failed\n");
+ ines_gpib_release(link);
+ return -ENODEV;
+ }
+ virt = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
+ writeb((link->resource[2]->start >> 2) & 0xff, virt + 0xf0); // IOWindow base
+ iounmap((void *)virt);
+
+ /*
+ * This actually configures the PCMCIA socket -- setting up
+ * the I/O windows and the interrupt mapping.
+ */
+ retval = pcmcia_enable_device(link);
+ if (retval) {
+ ines_gpib_release(link);
+ return -ENODEV;
+ }
+ pr_info("ines gpib device loaded\n");
+ return 0;
+} /* gpib_config */
+
+/*
+ * After a card is removed, gpib_release() will unregister the net
+ * device, and release the PCMCIA configuration. If the device is
+ * still open, this will be postponed until it is closed.
+ */
+
+static void ines_gpib_release(struct pcmcia_device *link)
+{
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+ pcmcia_disable_device(link);
+} /* gpib_release */
+
+static int ines_gpib_suspend(struct pcmcia_device *link)
+{
+ //struct local_info *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ if (link->open)
+ pr_err("Device still open ???\n");
+ //netif_device_detach(dev);
+
+ return 0;
+}
+
+static int ines_gpib_resume(struct pcmcia_device *link)
+{
+ //struct local_info_t *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ /*if (link->open) {
+ * ni_gpib_probe(dev); / really?
+ * printk("Gpib resumed ???\n");
+ * //netif_device_attach(dev);
+ *}
+ */
+ return ines_gpib_config(link);
+}
+
+static struct pcmcia_device_id ines_pcmcia_ids[] = {
+ PCMCIA_DEVICE_MANF_CARD(0x01b4, 0x4730),
+ PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, ines_pcmcia_ids);
+
+static struct pcmcia_driver ines_gpib_cs_driver = {
+ .owner = THIS_MODULE,
+ .name = "ines_gpib_cs",
+ .id_table = ines_pcmcia_ids,
+ .probe = ines_gpib_probe,
+ .remove = ines_gpib_remove,
+ .suspend = ines_gpib_suspend,
+ .resume = ines_gpib_resume,
+};
+
+int ines_pcmcia_init_module(void)
+{
+ pcmcia_register_driver(&ines_gpib_cs_driver);
+ return 0;
+}
+
+void ines_pcmcia_cleanup_module(void)
+{
+ DEBUG(0, "ines_cs: unloading\n");
+ pcmcia_unregister_driver(&ines_gpib_cs_driver);
+}
+
+gpib_interface_t ines_pcmcia_unaccel_interface = {
+name: "ines_pcmcia_unaccel",
+attach : ines_pcmcia_attach,
+detach : ines_pcmcia_detach,
+read : ines_read,
+write : ines_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+gpib_interface_t ines_pcmcia_accel_interface = {
+name: "ines_pcmcia_accel",
+attach : ines_pcmcia_accel_attach,
+detach : ines_pcmcia_detach,
+read : ines_accel_read,
+write : ines_accel_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+gpib_interface_t ines_pcmcia_interface = {
+name: "ines_pcmcia",
+attach : ines_pcmcia_accel_attach,
+detach : ines_pcmcia_detach,
+read : ines_accel_read,
+write : ines_accel_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+irqreturn_t ines_pcmcia_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+
+ return ines_interrupt(board);
+}
+
+int ines_common_pcmcia_attach(gpib_board_t *board)
+{
+ struct ines_priv *ines_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+
+ if (!curr_dev) {
+ pr_err("no ines pcmcia cards found\n");
+ return -1;
+ }
+
+ retval = ines_generic_attach(board);
+ if (retval)
+ return retval;
+
+ ines_priv = board->private_data;
+ nec_priv = &ines_priv->nec7210_priv;
+
+ if (request_region(curr_dev->resource[0]->start,
+ resource_size(curr_dev->resource[0]), "ines_gpib") == 0) {
+ pr_err("ines_gpib: ioports at 0x%lx already in use\n",
+ (unsigned long)(curr_dev->resource[0]->start));
+ return -1;
+ }
+
+ nec_priv->iobase = (void *)(unsigned long)curr_dev->resource[0]->start;
+
+ nec7210_board_reset(nec_priv, board);
+
+ if (request_irq(curr_dev->irq, ines_pcmcia_interrupt, IRQF_SHARED,
+ "pcmcia-gpib", board)) {
+ pr_err("gpib: can't request IRQ %d\n", curr_dev->irq);
+ return -1;
+ }
+ ines_priv->irq = curr_dev->irq;
+
+ return 0;
+}
+
+int ines_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct ines_priv *ines_priv;
+ int retval;
+
+ retval = ines_common_pcmcia_attach(board);
+ if (retval < 0)
+ return retval;
+
+ ines_priv = board->private_data;
+ ines_online(ines_priv, board, 0);
+
+ return 0;
+}
+
+int ines_pcmcia_accel_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct ines_priv *ines_priv;
+ int retval;
+
+ retval = ines_common_pcmcia_attach(board);
+ if (retval < 0)
+ return retval;
+
+ ines_priv = board->private_data;
+ ines_online(ines_priv, board, 1);
+
+ return 0;
+}
+
+void ines_pcmcia_detach(gpib_board_t *board)
+{
+ struct ines_priv *ines_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (ines_priv) {
+ nec_priv = &ines_priv->nec7210_priv;
+ if (ines_priv->irq)
+ free_irq(ines_priv->irq, board);
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ release_region((unsigned long)(nec_priv->iobase), ines_pcmcia_iosize);
+ }
+ }
+ ines_free_private(board);
+}
+
+#endif /* GPIB_PCMCIA */
+
+static int __init ines_init_module(void)
+{
+ int err = 0;
+
+ err = pci_register_driver(&ines_pci_driver);
+ if (err) {
+ pr_err("ines_gpib: pci_driver_register failed!\n");
+ return err;
+ }
+
+ gpib_register_driver(&ines_pci_interface, THIS_MODULE);
+ gpib_register_driver(&ines_pci_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&ines_pci_accel_interface, THIS_MODULE);
+ gpib_register_driver(&ines_isa_interface, THIS_MODULE);
+#ifdef GPIB_PCMCIA
+ gpib_register_driver(&ines_pcmcia_interface, THIS_MODULE);
+ gpib_register_driver(&ines_pcmcia_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&ines_pcmcia_accel_interface, THIS_MODULE);
+ err += ines_pcmcia_init_module();
+#endif
+ if (err)
+ return -1;
+
+ return 0;
+}
+
+static void __exit ines_exit_module(void)
+{
+ gpib_unregister_driver(&ines_pci_interface);
+ gpib_unregister_driver(&ines_pci_unaccel_interface);
+ gpib_unregister_driver(&ines_pci_accel_interface);
+ gpib_unregister_driver(&ines_isa_interface);
+#ifdef GPIB__PCMCIA
+ gpib_unregister_driver(&ines_pcmcia_interface);
+ gpib_unregister_driver(&ines_pcmcia_unaccel_interface);
+ gpib_unregister_driver(&ines_pcmcia_accel_interface);
+ ines_pcmcia_cleanup_module();
+#endif
+
+ pci_unregister_driver(&ines_pci_driver);
+}
+
+module_init(ines_init_module);
+module_exit(ines_exit_module);
diff --git a/drivers/staging/gpib/lpvo_usb_gpib/Makefile b/drivers/staging/gpib/lpvo_usb_gpib/Makefile
new file mode 100644
index 000000000000..137511acce63
--- /dev/null
+++ b/drivers/staging/gpib/lpvo_usb_gpib/Makefile
@@ -0,0 +1,3 @@
+
+obj-m += lpvo_usb_gpib.o
+
diff --git a/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c b/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c
new file mode 100644
index 000000000000..796c3a5be545
--- /dev/null
+++ b/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c
@@ -0,0 +1,2136 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * This code has been developed at the Department of Physics (University *
+ * of Florence, Italy) to support in linux-gpib the open usb-gpib adapter *
+ * implemented at the University of Ljubljana (lpvo.fe.uni-lj.si/gpib) *
+ * *
+ * copyright : (C) 2011 Marcello Carla' *
+ ***************************************************************************/
+
+/* base module includes */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/spinlock.h>
+#include <linux/file.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/sched/signal.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+
+#include "gpibP.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for LPVO usb devices");
+
+#define NAME "lpvo_usb_gpib"
+
+/*
+ * Table of devices that work with this driver.
+ *
+ * Currently, only one device is known to be used in the
+ * lpvo_usb_gpib adapter (FTDI 0403:6001).
+ * If your adapter uses a different chip, insert a line
+ * in the following table with proper <Vendor-id>, <Product-id>.
+ *
+ * To have your chip automatically handled by the driver,
+ * update files "/usr/local/etc/modprobe.d/lpvo_usb_gpib.conf"
+ * and /usr/local/etc/udev/rules.d/99-lpvo_usb_gpib.rules.
+ *
+ */
+
+static const struct usb_device_id skel_table[] = {
+ { USB_DEVICE(0x0403, 0x6001) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, skel_table);
+
+/*
+ * *** Diagnostics and Debug ***
+ *
+ * The module parameter "debug" controls the sending of debug messages to
+ * syslog. By default it is set to 0 or 1 according to GPIB_CONFIG_KERNEL_DEBUG.
+ * debug = 0: only register/deregister messages are generated
+ * 1: every action is logged
+ * 2: extended logging; each single exchanged byte is documented
+ * (about twice the log volume of [1])
+ * To switch debug level:
+ * At module loading: modprobe lpvo_usb_gpib debug={0,1,2}
+ * On the fly: echo {0,1,2} > /sys/modules/lpvo_usb_gpib/parameters/debug
+ */
+
+static int debug;
+module_param(debug, int, 0644);
+
+#define DIA_LOG(level, format, ...) \
+ do { if (debug >= (level)) \
+ pr_alert("%s:%s - " format, NAME, __func__, ## __VA_ARGS__); } \
+ while (0)
+
+/* standard and extended command sets of the usb-gpib adapter */
+
+#define USB_GPIB_ON "\nIB\n"
+#define USB_GPIB_OFF "\nIBO\n"
+#define USB_GPIB_IBm0 "\nIBm0\n" /* do not assert REN with IFC */
+#define USB_GPIB_IBm1 "\nIBm1\n" /* assert REN with IFC */
+#define USB_GPIB_IBCL "\nIBZ\n"
+#define USB_GPIB_STATUS "\nIBS\n"
+#define USB_GPIB_READ "\nIB?\n"
+#define USB_GPIB_READ_1 "\nIBB\n"
+#define USB_GPIB_EOI "\nIBe0\n"
+#define USB_GPIB_FTMO "\nIBf0\n" /* disable first byte timeout */
+#define USB_GPIB_TTMOZ "\nIBt0\n" /* disable byte timeout */
+
+/* incomplete commands */
+
+#define USB_GPIB_BTMO "\nIBt" /* set byte timeout */
+#define USB_GPIB_TTMO "\nIBT" /* set total timeout */
+
+#define USB_GPIB_DEBUG_ON "\nIBDE\xAA\n"
+#define USB_GPIB_SET_LISTEN "\nIBDT0\n"
+#define USB_GPIB_SET_TALK "\nIBDT1\n"
+#define USB_GPIB_SET_LINES "\nIBDC\n"
+#define USB_GPIB_SET_DATA "\nIBDM\n"
+#define USB_GPIB_READ_LINES "\nIBD?C\n"
+#define USB_GPIB_READ_DATA "\nIBD?M\n"
+#define USB_GPIB_READ_BUS "\nIBD??\n"
+
+/* command sequences */
+
+#define USB_GPIB_UNTALK "\nIBC_\n"
+#define USB_GPIB_UNLISTEN "\nIBC?\n"
+
+/* special characters used by the adapter */
+
+#define DLE ('\020')
+#define STX ('\02')
+#define ETX ('\03')
+#define ACK ('\06')
+#define NODATA ('\03')
+#define NODAV ('\011')
+
+#define IB_BUS_REN 0x01
+#define IB_BUS_IFC 0x02
+#define IB_BUS_NDAC 0x04
+#define IB_BUS_NRFD 0x08
+#define IB_BUS_DAV 0x10
+#define IB_BUS_EOI 0x20
+#define IB_BUS_ATN 0x40
+#define IB_BUS_SRQ 0x80
+
+#define INBUF_SIZE 128
+
+struct char_buf { /* used by one_char() routine */
+ char *inbuf;
+ int last;
+ int nchar;
+};
+
+struct usb_gpib_priv { /* private data to the device */
+ u8 eos; /* eos character */
+ short eos_flags; /* eos mode */
+ int timeout; /* current value for timeout */
+ void *dev; /* the usb device private data structure */
+};
+
+#define GPIB_DEV (((struct usb_gpib_priv *)board->private_data)->dev)
+
+#define SHOW_STATUS(board) { \
+ DIA_LOG(2, "# - board %p\n", board); \
+ DIA_LOG(2, "# - buffer_length %d\n", board->buffer_length); \
+ DIA_LOG(2, "# - status %lx\n", board->status); \
+ DIA_LOG(2, "# - use_count %d\n", board->use_count); \
+ DIA_LOG(2, "# - pad %x\n", board->pad); \
+ DIA_LOG(2, "# - sad %x\n", board->sad); \
+ DIA_LOG(2, "# - timeout %d\n", board->usec_timeout); \
+ DIA_LOG(2, "# - ppc %d\n", board->parallel_poll_configuration); \
+ DIA_LOG(2, "# - t1delay %d\n", board->t1_nano_sec); \
+ DIA_LOG(2, "# - online %d\n", board->online); \
+ DIA_LOG(2, "# - autopoll %d\n", board->autospollers); \
+ DIA_LOG(2, "# - autopoll task %p\n", board->autospoll_task); \
+ DIA_LOG(2, "# - minor %d\n", board->minor); \
+ DIA_LOG(2, "# - master %d\n", board->master); \
+ DIA_LOG(2, "# - list %d\n", board->ist); \
+ }
+/*
+ * n = 0;
+ * list_for_each (l, &board->device_list) n++;
+ * TTY_LOG ("%s:%s - devices in list %d\n", a, b, n);
+ */
+
+/*
+ * TTY_LOG - write a message to the current work terminal (if any)
+ */
+
+#define TTY_LOG(format, ...) { \
+ char buf[128]; \
+ struct tty_struct *tty = get_current_tty(); \
+ if (tty) { \
+ snprintf(buf, 128, format, __VA_ARGS__); \
+ tty->driver->ops->write(tty, buf, strlen(buf)); \
+ tty->driver->ops->write(tty, "\r", 1); \
+ } \
+ }
+
+/*
+ * GLOBAL VARIABLES: required for
+ * pairing among gpib minor and usb minor.
+ * MAX_DEV is the max number of usb-gpib adapters; free
+ * to change as you like, but no more than 32
+ */
+
+#define MAX_DEV 8
+static struct usb_interface *lpvo_usb_interfaces[MAX_DEV]; /* registered interfaces */
+static int usb_minors[MAX_DEV]; /* usb minors */
+static int assigned_usb_minors; /* mask of filled slots */
+static struct mutex minors_lock; /* operations on usb_minors are to be protected */
+
+/*
+ * usb-skeleton prototypes
+ */
+
+struct usb_skel;
+static ssize_t skel_do_write(struct usb_skel *, const char *, size_t);
+static ssize_t skel_do_read(struct usb_skel *, char *, size_t);
+static int skel_do_open(gpib_board_t *, int);
+static int skel_do_release(gpib_board_t *);
+
+/*
+ * usec_diff : take difference in MICROsec between two 'timespec'
+ * (unix time in sec and NANOsec)
+ */
+
+inline int usec_diff(struct timespec64 *a, struct timespec64 *b)
+{
+ return ((a->tv_sec - b->tv_sec) * 1000000 +
+ (a->tv_nsec - b->tv_nsec) / 1000);
+}
+
+/*
+ * *** these routines are specific to the usb-gpib adapter ***
+ */
+
+/**
+ * write_loop() - Send a byte sequence to the adapter
+ *
+ * @dev: the private device structure
+ * @msg: the byte sequence.
+ * @leng: the byte sequence length.
+ *
+ */
+
+static int write_loop(void *dev, char *msg, int leng)
+{
+// int nchar = 0, val;
+
+// do {
+
+ return skel_do_write(dev, msg, leng);
+
+// if (val < 1) {
+// printk (KERN_ALERT "%s:%s - write error: %d %d/%d\n",
+// NAME, __func__, val, nchar, leng);
+// return -EIO;
+// }
+// nchar +=val;
+// } while (nchar < leng);
+// return leng;
+}
+
+static char printable(char x)
+{
+ if (x < 32 || x > 126)
+ return ' ';
+ return x;
+}
+
+/**
+ * send_command() - Send a byte sequence and return a single byte reply.
+ *
+ * @board: the gpib_board_struct data area for this gpib interface
+ * @msg: the byte sequence.
+ * @leng the byte sequence length; can be given as zero and is
+ * computed automatically, but if 'msg' contains a zero byte,
+ * it has to be given explicitly.
+ */
+
+static int send_command(gpib_board_t *board, char *msg, int leng)
+{
+ char buffer[64];
+ int nchar, j;
+ int retval;
+ struct timespec64 before, after;
+
+ ktime_get_real_ts64 (&before);
+
+ if (!leng)
+ leng = strlen(msg);
+ retval = write_loop(GPIB_DEV, msg, leng);
+ if (retval < 0)
+ return retval;
+
+ nchar = skel_do_read(GPIB_DEV, buffer, 64);
+
+ if (nchar < 0) {
+ DIA_LOG(0, " return from read: %d\n", nchar);
+ return nchar;
+ } else if (nchar != 1) {
+ for (j = 0 ; j < leng ; j++) {
+ DIA_LOG(0, " Irregular reply to command: %d %x %c\n",
+ j, msg[j], printable(msg[j]));
+ }
+ for (j = 0 ; j < nchar ; j++) {
+ DIA_LOG(0, " Irregular command reply: %d %x %c\n",
+ j, buffer[j] & 0xff, printable(buffer[j]));
+ }
+ return -EIO;
+ }
+ ktime_get_real_ts64 (&after);
+
+ DIA_LOG(1, "Sent %d - done %d us.\n", leng, usec_diff(&after, &before));
+
+ return buffer[0] & 0xff;
+}
+
+/*
+ *
+ * set_control_line() - Set the value of a single gpib control line
+ *
+ * @board: the gpib_board_struct data area for this gpib interface
+ * @line: line mask
+ * @value: line new value (0/1)
+ *
+ */
+
+static int set_control_line(gpib_board_t *board, int line, int value)
+{
+ char msg[] = USB_GPIB_SET_LINES;
+ int retval;
+ int leng = strlen(msg);
+
+ DIA_LOG(1, "setting line %x to %x\n", line, value);
+
+ retval = send_command(board, USB_GPIB_READ_LINES, 0);
+
+ DIA_LOG(1, "old line values: %x\n", retval);
+
+ if (retval == -EIO)
+ return retval;
+
+ msg[leng - 2] = value ? (retval & ~line) : retval | line;
+
+ retval = send_command(board, msg, 0);
+
+ DIA_LOG(1, "operation result: %x\n", retval);
+
+ return retval;
+}
+
+/*
+ * one_char() - read one single byte from input buffer
+ *
+ * @board: the gpib_board_struct data area for this gpib interface
+ * @char_buf: the routine private data structure
+ */
+
+static int one_char(gpib_board_t *board, struct char_buf *b)
+{
+ struct timespec64 before, after;
+
+ if (b->nchar) {
+ DIA_LOG(2, "-> %x\n", b->inbuf[b->last - b->nchar]);
+ return b->inbuf[b->last - b->nchar--];
+ }
+ ktime_get_real_ts64 (&before);
+ b->nchar = skel_do_read(GPIB_DEV, b->inbuf, INBUF_SIZE);
+ b->last = b->nchar;
+ ktime_get_real_ts64 (&after);
+
+ DIA_LOG(2, "read %d bytes in %d usec\n",
+ b->nchar, usec_diff(&after, &before));
+
+ if (b->nchar > 0) {
+ DIA_LOG(2, "--> %x\n", b->inbuf[b->last - b->nchar]);
+ return b->inbuf[b->last - b->nchar--];
+ } else if (b->nchar == 0) {
+ dev_alert(board->gpib_dev, "%s:%s - read returned EOF\n", NAME, __func__);
+ return -EIO;
+ }
+ dev_alert(board->gpib_dev, "%s:%s - read error %d\n", NAME, __func__, b->nchar);
+ TTY_LOG("\n *** %s *** Read Error - %s\n", NAME,
+ "Reset the adapter with 'gpib_config'\n");
+ return -EIO;
+}
+
+/**
+ * set_timeout() - set single byte / total timeouts on the adapter
+ *
+ * @board: the gpib_board_struct data area for this gpib interface
+ *
+ * For sake of speed, the operation is performed only if it
+ * modifies the current (saved) value. Minimum allowed timeout
+ * is 30 ms (T30ms -> 8); timeout disable (TNONE -> 0) currently
+ * not supported.
+ */
+
+static void set_timeout(gpib_board_t *board)
+{
+ int n, val;
+ char command[sizeof(USB_GPIB_TTMO) + 6];
+ struct usb_gpib_priv *data = board->private_data;
+
+ if (data->timeout == board->usec_timeout)
+ return;
+
+ n = (board->usec_timeout + 32767) / 32768;
+ if (n < 2)
+ n = 2;
+
+ DIA_LOG(1, "Set timeout to %d us -> %d\n", board->usec_timeout, n);
+
+ sprintf(command, "%s%d\n", USB_GPIB_BTMO, n > 255 ? 255 : n);
+ val = send_command(board, command, 0);
+
+ if (val == ACK) {
+ if (n > 65535)
+ n = 65535;
+ sprintf(command, "%s%d\n", USB_GPIB_TTMO, n);
+ val = send_command(board, command, 0);
+ }
+
+ if (val != ACK) {
+ dev_alert(board->gpib_dev, "%s:%s - error in timeout set: <%s>\n",
+ NAME, __func__, command);
+ } else {
+ data->timeout = board->usec_timeout;
+ }
+}
+
+/*
+ * now the standard interface functions - attach and detach
+ */
+
+/**
+ * usb_gpib_attach() - activate the usb-gpib converter board
+ *
+ * @board: the gpib_board_struct data area for this gpib interface
+ * @config: firmware data, if any (from gpib_config -I <file>)
+ *
+ * The channel name is ttyUSBn, with n=0 by default. Other values for n
+ * passed with gpib_config -b <n>.
+ *
+ * In this routine I trust that when an error code is returned
+ * detach() will be called. Always.
+ */
+
+static int usb_gpib_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ int retval, j;
+ int base = (long)config->ibbase;
+ char *device_path;
+ int match;
+ struct usb_device *udev;
+
+ DIA_LOG(0, "Board %p -t %s -m %d -a %p -u %d -l %d -b %d\n",
+ board, board->interface->name, board->minor, config->device_path,
+ config->pci_bus, config->pci_slot, base);
+
+ board->private_data = NULL; /* to be sure - we can detach before setting */
+
+ /* identify device to be attached */
+
+ mutex_lock(&minors_lock);
+
+ if (config->device_path) {
+ /* if config->device_path given, try that first */
+ dev_alert(board->gpib_dev, "%s:%s - Looking for device_path: %s\n",
+ NAME, __func__, config->device_path);
+ for (j = 0 ; j < MAX_DEV ; j++) {
+ if ((assigned_usb_minors & 1 << j) == 0)
+ continue;
+ udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j]));
+ device_path = kobject_get_path(&udev->dev.kobj, GFP_KERNEL);
+ match = gpib_match_device_path(&lpvo_usb_interfaces[j]->dev,
+ config->device_path);
+ DIA_LOG(1, "dev. %d: minor %d path: %s --> %d\n", j,
+ lpvo_usb_interfaces[j]->minor, device_path, match);
+ kfree(device_path);
+ if (match)
+ break;
+ }
+ } else if (config->pci_bus != -1 && config->pci_slot != -1) {
+ /* second: look for bus and slot */
+ for (j = 0 ; j < MAX_DEV ; j++) {
+ if ((assigned_usb_minors & 1 << j) == 0)
+ continue;
+ udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j]));
+ DIA_LOG(1, "dev. %d: bus %d -> %d dev: %d -> %d\n", j,
+ udev->bus->busnum, config->pci_bus, udev->devnum, config->pci_slot);
+ if (config->pci_bus == udev->bus->busnum &&
+ config->pci_slot == udev->devnum)
+ break;
+ }
+ } else { /* last chance: usb_minor, given as ibbase */
+ for (j = 0 ; j < MAX_DEV ; j++) {
+ if (usb_minors[j] == base && assigned_usb_minors & 1 << j)
+ break;
+ }
+ }
+ mutex_unlock(&minors_lock);
+
+ if (j == MAX_DEV) {
+ dev_alert(board->gpib_dev, "%s:%s - Requested device is not registered.\n",
+ NAME, __func__);
+ return -EIO;
+ }
+
+ board->private_data = kzalloc(sizeof(struct usb_gpib_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+
+ retval = skel_do_open(board, usb_minors[j]);
+
+ DIA_LOG(1, "Skel open: %d\n", retval);
+
+ if (retval) {
+ TTY_LOG("%s:%s - skel open failed.\n", NAME, __func__);
+ kfree(board->private_data);
+ board->private_data = NULL;
+ return -ENODEV;
+ }
+
+ SHOW_STATUS(board);
+
+ retval = send_command(board, USB_GPIB_ON, 0);
+ DIA_LOG(1, "USB_GPIB_ON returns %x\n", retval);
+ if (retval != ACK)
+ return -EIO;
+
+ /* We must setup debug mode because we need the extended instruction
+ * set to cope with the Core (gpib_common) point of view
+ */
+
+ retval = send_command(board, USB_GPIB_DEBUG_ON, 0);
+ DIA_LOG(1, "USB_GPIB_DEBUG_ON returns %x\n", retval);
+ if (retval != ACK)
+ return -EIO;
+
+ /* We must keep REN off after an IFC because so it is
+ * assumed by the Core
+ */
+
+ retval = send_command(board, USB_GPIB_IBm0, 0);
+ DIA_LOG(1, "USB_GPIB_IBm0 returns %x\n", retval);
+ if (retval != ACK)
+ return -EIO;
+
+ retval = set_control_line(board, IB_BUS_REN, 0);
+ if (retval != ACK)
+ return -EIO;
+
+ retval = send_command(board, USB_GPIB_FTMO, 0);
+ DIA_LOG(1, "USB_GPIB_FTMO returns %x\n", retval);
+ if (retval != ACK)
+ return -EIO;
+
+ SHOW_STATUS(board);
+ TTY_LOG("Module '%s' has been sucesfully configured\n", NAME);
+ return 0;
+}
+
+/**
+ * usb_gpib_detach() - deactivate the usb-gpib converter board
+ *
+ * @board: the gpib_board data area for this gpib interface
+ *
+ */
+
+static void usb_gpib_detach(gpib_board_t *board)
+{
+ int retval;
+
+ SHOW_STATUS(board);
+
+ DIA_LOG(0, "detaching %p\n", board);
+
+ if (board->private_data) {
+ if (GPIB_DEV) {
+ write_loop(GPIB_DEV, USB_GPIB_OFF, strlen(USB_GPIB_OFF));
+ msleep(100);
+ DIA_LOG(1, "%s", "GPIB off\n");
+ retval = skel_do_release(board);
+ DIA_LOG(1, "skel release -> %d\n", retval);
+ }
+ kfree(board->private_data);
+ board->private_data = NULL;
+ }
+
+ DIA_LOG(0, "done %p\n", board);
+ TTY_LOG("Module '%s' has been detached\n", NAME);
+}
+
+/*
+ * Other functions follow in alphabetical order
+ */
+/* command */
+static int usb_gpib_command(gpib_board_t *board,
+ u8 *buffer,
+ size_t length,
+ size_t *bytes_written)
+{
+ int i, retval;
+ char command[6] = "IBc\n";
+
+ DIA_LOG(1, "enter %p\n", board);
+
+ set_timeout(board);
+
+ *bytes_written = 0;
+ for (i = 0 ; i < length ; i++) {
+ command[3] = buffer[i];
+ retval = send_command(board, command, 5);
+ DIA_LOG(2, "%d ==> %x %x\n", i, buffer[i], retval);
+ if (retval != 0x06)
+ return retval;
+ ++(*bytes_written);
+ }
+ return 0;
+}
+
+/**
+ * disable_eos() - Disable END on eos byte (END on EOI only)
+ *
+ * @board: the gpib_board data area for this gpib interface
+ *
+ * With the lpvo adapter eos can only be handled via software.
+ * Cannot do nothing here, but remember for future use.
+ */
+
+static void usb_gpib_disable_eos(gpib_board_t *board)
+{
+ ((struct usb_gpib_priv *)board->private_data)->eos_flags &= ~REOS;
+ DIA_LOG(1, "done: %x\n",
+ ((struct usb_gpib_priv *)board->private_data)->eos_flags);
+}
+
+/**
+ * enable_eos() - Enable END for reads when eos byte is received.
+ *
+ * @board: the gpib_board data area for this gpib interface
+ * @eos_byte: the 'eos' byte
+ * @compare_8_bits: if zero ignore eigthth bit when comparing
+ *
+ */
+
+static int usb_gpib_enable_eos(gpib_board_t *board,
+ u8 eos_byte,
+ int compare_8_bits)
+{
+ struct usb_gpib_priv *pd = (struct usb_gpib_priv *)board->private_data;
+
+ DIA_LOG(1, "enter with %x\n", eos_byte);
+ pd->eos = eos_byte;
+ pd->eos_flags = REOS;
+ if (compare_8_bits)
+ pd->eos_flags |= BIN;
+ return 0;
+}
+
+/**
+ * go_to_standby() - De-assert ATN
+ *
+ * @board: the gpib_board data area for this gpib interface
+ */
+
+static int usb_gpib_go_to_standby(gpib_board_t *board)
+{
+ int retval = set_control_line(board, IB_BUS_ATN, 0);
+
+ DIA_LOG(1, "done with %x\n", retval);
+
+ if (retval == ACK)
+ return 0;
+ return -EIO;
+}
+
+/**
+ * interface_clear() - Assert or de-assert IFC
+ *
+ * @board: the gpib_board data area for this gpib interface
+ * assert: 1: assert IFC; 0: de-assert IFC
+ *
+ * Currently on the assert request we issue the lpvo IBZ
+ * command that cycles IFC low for 100 usec, then we ignore
+ * the de-assert request.
+ */
+
+static void usb_gpib_interface_clear(gpib_board_t *board, int assert)
+{
+ int retval = 0;
+
+ DIA_LOG(1, "enter with %d\n", assert);
+
+ if (assert) {
+ retval = send_command(board, USB_GPIB_IBCL, 0);
+
+ set_bit(CIC_NUM, &board->status);
+ }
+
+ DIA_LOG(1, "done with %d %d\n", assert, retval);
+}
+
+/**
+ * line_status() - Read the status of the bus lines.
+ *
+ * @board: the gpib_board data area for this gpib interface
+ *
+ * We can read all lines.
+ */
+
+#define WQT wait_queue_entry_t
+#define WQH head
+#define WQE entry
+
+static int usb_gpib_line_status(const gpib_board_t *board)
+{
+ int buffer;
+ int line_status = ValidALL; /* all lines will be read */
+ struct list_head *p, *q;
+ WQT *item;
+ unsigned long flags;
+ int sleep = 0;
+
+ DIA_LOG(1, "%s\n", "request");
+
+ /* if we are on the wait queue (board->wait), do not hurry
+ * reading status line; instead, pause a little
+ */
+
+ spin_lock_irqsave((spinlock_t *)&board->wait.lock, flags);
+ q = (struct list_head *)&board->wait.WQH;
+ list_for_each(p, q) {
+ item = container_of(p, WQT, WQE);
+ if (item->private == current) {
+ sleep = 20;
+ break;
+ }
+ /* pid is: ((struct task_struct *) item->private)->pid); */
+ }
+ spin_unlock_irqrestore((spinlock_t *)&board->wait.lock, flags);
+ if (sleep) {
+ DIA_LOG(1, "we are on the wait queue - sleep %d ms\n", sleep);
+ msleep(sleep);
+ }
+
+ buffer = send_command((gpib_board_t *)board, USB_GPIB_STATUS, 0);
+
+ if (buffer < 0) {
+ dev_alert(board->gpib_dev, "%s:%s - line status read failed with %d\n",
+ NAME, __func__, buffer);
+ return -1;
+ }
+
+ if ((buffer & 0x01) == 0)
+ line_status |= BusREN;
+ if ((buffer & 0x02) == 0)
+ line_status |= BusIFC;
+ if ((buffer & 0x04) == 0)
+ line_status |= BusNDAC;
+ if ((buffer & 0x08) == 0)
+ line_status |= BusNRFD;
+ if ((buffer & 0x10) == 0)
+ line_status |= BusDAV;
+ if ((buffer & 0x20) == 0)
+ line_status |= BusEOI;
+ if ((buffer & 0x40) == 0)
+ line_status |= BusATN;
+ if ((buffer & 0x80) == 0)
+ line_status |= BusSRQ;
+
+ DIA_LOG(1, "done with %x %x\n", buffer, line_status);
+
+ return line_status;
+}
+
+/* parallel_poll */
+
+static int usb_gpib_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ /* request parallel poll asserting ATN | EOI;
+ * we suppose ATN already asserted
+ */
+
+ int retval;
+
+ DIA_LOG(1, "enter %p\n", board);
+
+ retval = set_control_line(board, IB_BUS_EOI, 1);
+ if (retval != ACK) {
+ dev_alert(board->gpib_dev, "%s:%s - assert EOI failed\n", NAME, __func__);
+ return -EIO;
+ }
+
+ *result = send_command(board, USB_GPIB_READ_DATA, 0);
+
+ DIA_LOG(1, "done with %x\n", *result);
+
+ retval = set_control_line(board, IB_BUS_EOI, 0);
+ if (retval != 0x06) {
+ dev_alert(board->gpib_dev, "%s:%s - unassert EOI failed\n", NAME, __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/* read */
+
+static int usb_gpib_read(gpib_board_t *board,
+ u8 *buffer,
+ size_t length,
+ int *end,
+ size_t *bytes_read)
+{
+#define MAX_READ_EXCESS 16384
+
+ struct char_buf b = {NULL, 0};
+
+ int retval;
+ char c, nc;
+ int ic;
+ struct timespec64 before, after;
+ int read_count = MAX_READ_EXCESS;
+ struct usb_gpib_priv *pd = (struct usb_gpib_priv *)board->private_data;
+
+ DIA_LOG(1, "enter %p -> %zu\n", board, length);
+
+ *bytes_read = 0; /* by default, things go wrong */
+ *end = 0;
+
+ set_timeout(board);
+
+ /* single byte read has a special handling */
+
+ if (length == 1) {
+ char inbuf[2] = {0, 0};
+
+ /* read a single character */
+
+ ktime_get_real_ts64 (&before);
+
+ retval = write_loop(GPIB_DEV, USB_GPIB_READ_1, strlen(USB_GPIB_READ_1));
+ if (retval < 0)
+ return retval;
+
+ retval = skel_do_read(GPIB_DEV, inbuf, 1);
+ retval += skel_do_read(GPIB_DEV, inbuf + 1, 1);
+
+ ktime_get_real_ts64 (&after);
+
+ DIA_LOG(1, "single read: %x %x %x in %d\n", retval,
+ inbuf[0], inbuf[1],
+ usec_diff(&after, &before));
+
+ /* good char / last char? */
+
+ if (retval == 2 && inbuf[1] == ACK) {
+ buffer[0] = inbuf[0];
+ *bytes_read = 1;
+ return 0;
+ }
+ if (retval < 2)
+ return -EIO;
+ else
+ return -ETIME;
+ return 0;
+ }
+
+ /* allocate buffer for multibyte read */
+
+ b.inbuf = kmalloc(INBUF_SIZE, GFP_KERNEL);
+ if (!b.inbuf)
+ return -ENOMEM;
+
+ /* send read command and check <DLE><STX> sequence */
+
+ retval = write_loop(GPIB_DEV, USB_GPIB_READ, strlen(USB_GPIB_READ));
+ if (retval < 0)
+ goto read_return;
+
+ if (one_char(board, &b) != DLE || one_char(board, &b) != STX) {
+ dev_alert(board->gpib_dev, "%s:%s - wrong <DLE><STX> sequence\n",
+ NAME, __func__);
+ retval = -EIO;
+ goto read_return;
+ }
+
+ /* get data flow */
+
+ while (1) {
+ ic = one_char(board, &b);
+ if (ic == -EIO) {
+ retval = -EIO;
+ goto read_return;
+ }
+ c = ic;
+
+ if (c == DLE)
+ nc = one_char(board, &b);
+ if (c != DLE || nc == DLE) {
+ /* data byte - store into buffer */
+
+ if (*bytes_read == length)
+ break; /* data overflow */
+ if (c == DLE)
+ c = nc;
+ buffer[(*bytes_read)++] = c;
+ if (c == pd->eos) {
+ *end = 1;
+ break;
+ }
+
+ } else {
+ /* we are in the closing <DLE><ETX> sequence */
+
+ if (c == ETX) {
+ c = one_char(board, &b);
+ if (c == ACK) {
+ *end = 1;
+ retval = 0;
+ goto read_return;
+ } else {
+ dev_alert(board->gpib_dev, "%s:%s - %s %x\n",
+ NAME, __func__,
+ "Wrong end of message", c);
+ retval = -ETIME;
+ goto read_return;
+ }
+ } else {
+ dev_alert(board->gpib_dev, "%s:%s - %s\n", NAME, __func__,
+ "lone <DLE> in stream");
+ retval = -EIO;
+ goto read_return;
+ }
+ }
+ }
+
+ /* we had a data overflow - flush excess data */
+
+ while (read_count--) {
+ if (one_char(board, &b) != DLE)
+ continue;
+ c = one_char(board, &b);
+ if (c == DLE)
+ continue;
+ if (c == ETX) {
+ c = one_char(board, &b);
+ if (c == ACK) {
+ if (MAX_READ_EXCESS - read_count > 1)
+ dev_alert(board->gpib_dev, "%s:%s - %s\n", NAME, __func__,
+ "small buffer - maybe some data lost");
+ retval = 0;
+ goto read_return;
+ }
+ break;
+ }
+ }
+
+ dev_alert(board->gpib_dev, "%s:%s - no input end - GPIB board in odd state\n",
+ NAME, __func__);
+ retval = -EIO;
+
+read_return:
+ kfree(b.inbuf);
+
+ DIA_LOG(1, "done with byte/status: %d %x %d\n",
+ (int)*bytes_read, retval, *end);
+
+ if (retval == 0 || retval == -ETIME) {
+ if (send_command(board, USB_GPIB_UNTALK, sizeof(USB_GPIB_UNTALK)) == 0x06)
+ return retval;
+ return -EIO;
+ }
+
+ return retval;
+}
+
+/* remote_enable */
+
+static void usb_gpib_remote_enable(gpib_board_t *board, int enable)
+{
+ int retval;
+
+ retval = set_control_line(board, IB_BUS_REN, enable ? 1 : 0);
+ if (retval != ACK)
+ dev_alert(board->gpib_dev, "%s:%s - could not set REN line: %x\n",
+ NAME, __func__, retval);
+
+ DIA_LOG(1, "done with %x\n", retval);
+}
+
+/* request_system_control */
+
+static void usb_gpib_request_system_control(gpib_board_t *board,
+ int request_control)
+{
+ if (request_control)
+ set_bit(CIC_NUM, &board->status);
+ else
+ clear_bit(CIC_NUM, &board->status);
+
+ DIA_LOG(1, "done with %d -> %lx\n", request_control, board->status);
+}
+
+/* take_control */
+/* beware: the sync flag is ignored; what is its real meaning? */
+
+static int usb_gpib_take_control(gpib_board_t *board, int sync)
+{
+ int retval;
+
+ retval = set_control_line(board, IB_BUS_ATN, 1);
+
+ DIA_LOG(1, "done with %d %x\n", sync, retval);
+
+ if (retval == ACK)
+ return 0;
+ return -EIO;
+}
+
+/* update_status */
+
+static unsigned int usb_gpib_update_status(gpib_board_t *board,
+ unsigned int clear_mask)
+{
+ /* There is nothing we can do here, I guess */
+
+ board->status &= ~clear_mask;
+
+ DIA_LOG(1, "done with %x %lx\n", clear_mask, board->status);
+
+ return board->status;
+}
+
+/* write */
+/* beware: DLE characters are not escaped - can only send ASCII data */
+
+static int usb_gpib_write(gpib_board_t *board,
+ u8 *buffer,
+ size_t length,
+ int send_eoi,
+ size_t *bytes_written)
+{
+ int retval;
+ char *msg;
+
+ DIA_LOG(1, "enter %p -> %zu\n", board, length);
+
+ set_timeout(board);
+
+ msg = kmalloc(length + 8, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ memcpy(msg, "\nIB\020\002", 5);
+ memcpy(msg + 5, buffer, length);
+ memcpy(msg + 5 + length, "\020\003\n", 3);
+
+ retval = send_command(board, msg, length + 8);
+ kfree(msg);
+
+ DIA_LOG(1, "<%.*s> -> %x\n", (int)length, buffer, retval);
+
+ if (retval != ACK)
+ return -EPIPE;
+
+ *bytes_written = length;
+
+ if (send_command(board, USB_GPIB_UNLISTEN, sizeof(USB_GPIB_UNLISTEN))
+ != 0x06)
+ return -EPIPE;
+
+ return length;
+}
+
+/*
+ * *** following functions not implemented yet ***
+ */
+
+/* parallel_poll configure */
+
+static void usb_gpib_parallel_poll_configure(gpib_board_t *board,
+ uint8_t configuration)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+}
+
+/* parallel_poll_response */
+
+static void usb_gpib_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+}
+
+/* primary_address */
+
+static int usb_gpib_primary_address(gpib_board_t *board, unsigned int address)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+ return 0;
+}
+
+/* return_to_local */
+
+static void usb_gpib_return_to_local(gpib_board_t *board)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+}
+
+/* secondary_address */
+
+static int usb_gpib_secondary_address(gpib_board_t *board,
+ unsigned int address,
+ int enable)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+ return 0;
+}
+
+/* serial_poll_response */
+
+static void usb_gpib_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+}
+
+/* serial_poll_status */
+
+static uint8_t usb_gpib_serial_poll_status(gpib_board_t *board)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+ return 0;
+}
+
+/* t1_delay */
+
+static unsigned int usb_gpib_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+ return 0;
+}
+
+/*
+ * *** module dispatch table and init/exit functions ***
+ */
+
+gpib_interface_t usb_gpib_interface = {
+name: NAME,
+attach : usb_gpib_attach,
+detach : usb_gpib_detach,
+read : usb_gpib_read,
+write : usb_gpib_write,
+command : usb_gpib_command,
+take_control : usb_gpib_take_control,
+go_to_standby : usb_gpib_go_to_standby,
+request_system_control : usb_gpib_request_system_control,
+interface_clear : usb_gpib_interface_clear,
+remote_enable : usb_gpib_remote_enable,
+enable_eos : usb_gpib_enable_eos,
+disable_eos : usb_gpib_disable_eos,
+parallel_poll : usb_gpib_parallel_poll,
+parallel_poll_configure : usb_gpib_parallel_poll_configure,
+parallel_poll_response : usb_gpib_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : usb_gpib_line_status,
+update_status : usb_gpib_update_status,
+primary_address : usb_gpib_primary_address,
+secondary_address : usb_gpib_secondary_address,
+serial_poll_response : usb_gpib_serial_poll_response,
+serial_poll_status : usb_gpib_serial_poll_status,
+t1_delay : usb_gpib_t1_delay,
+return_to_local : usb_gpib_return_to_local,
+skip_check_for_command_acceptors : 1
+};
+
+/*
+ * usb_gpib_init_module(), usb_gpib_exit_module()
+ *
+ * This functions are called every time a new device is detected
+ * and registered or is removed and unregistered.
+ * We must take note of created and destroyed usb minors to be used
+ * when usb_gpib_attach() and usb_gpib_detach() will be called on
+ * request by gpib_config.
+ */
+
+static int usb_gpib_init_module(struct usb_interface *interface)
+{
+ int j, mask, rv;
+
+ rv = mutex_lock_interruptible(&minors_lock);
+ if (rv < 0)
+ return rv;
+
+ if (!assigned_usb_minors) {
+ gpib_register_driver(&usb_gpib_interface, THIS_MODULE);
+ } else {
+ /* check if minor is already registered - maybe useless, but if
+ * it happens the code is inconsistent somewhere
+ */
+
+ for (j = 0 ; j < MAX_DEV ; j++) {
+ if (usb_minors[j] == interface->minor && assigned_usb_minors & 1 << j) {
+ pr_alert("%s:%s - CODE BUG: USB minor %d registered at %d.\n",
+ NAME, __func__, interface->minor, j);
+ rv = -1;
+ goto exit;
+ }
+ }
+ }
+
+ /* find a free slot */
+
+ for (j = 0 ; j < MAX_DEV ; j++) {
+ mask = 1 << j;
+ if ((assigned_usb_minors & mask) == 0) {
+ usb_minors[j] = interface->minor;
+ lpvo_usb_interfaces[j] = interface;
+ assigned_usb_minors |= mask;
+ DIA_LOG(0, "usb minor %d registered at %d\n", interface->minor, j);
+ rv = 0;
+ goto exit;
+ }
+ }
+ pr_alert("%s:%s - No slot available for interface %p minor %d\n",
+ NAME, __func__, interface, interface->minor);
+ rv = -1;
+
+exit:
+ mutex_unlock(&minors_lock);
+ return rv;
+}
+
+static void usb_gpib_exit_module(int minor)
+{
+ int j;
+
+ mutex_lock(&minors_lock);
+ for (j = 0 ; j < MAX_DEV ; j++) {
+ if (usb_minors[j] == minor && assigned_usb_minors & 1 << j) {
+ assigned_usb_minors &= ~(1 << j);
+ usb_minors[j] = -1;
+ if (assigned_usb_minors == 0)
+ gpib_unregister_driver(&usb_gpib_interface);
+ goto exit;
+ }
+ }
+ pr_alert("%s:%s - CODE BUG: USB minor %d not found.\n", NAME, __func__, minor);
+
+exit:
+ mutex_unlock(&minors_lock);
+}
+
+/*
+ * Default latency time (16 msec) is too long.
+ * We must use 1 msec (best); anyhow, no more than 5 msec.
+ *
+ * Defines and function taken and modified from the kernel tree
+ * (see ftdi_sio.h and ftdi_sio.c).
+ *
+ */
+
+#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */
+#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER
+#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40
+#define WDR_TIMEOUT 5000 /* default urb timeout */
+#define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */
+
+#define LATENCY_TIMER 1 /* use a small latency timer: 1 ... 5 msec */
+#define LATENCY_CHANNEL 0 /* channel selection in multichannel devices */
+static int write_latency_timer(struct usb_device *udev)
+{
+ int rv = usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+ FTDI_SIO_SET_LATENCY_TIMER_REQUEST,
+ FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE,
+ LATENCY_TIMER, LATENCY_CHANNEL,
+ NULL, 0, WDR_TIMEOUT);
+ if (rv < 0)
+ pr_alert("Unable to write latency timer: %i\n", rv);
+ return rv;
+}
+
+/*****************************************************************************
+ * *
+ * The following code is a modified version of the USB Skeleton driver *
+ * written by Greg Kroah-Hartman and available in the kernel tree. *
+ * *
+ * Functions skel_open() and skel_release() have been rewritten and named *
+ * skel_do_open() and skel_do_release() to process the attach and detach *
+ * requests coming from gpib_config. *
+ * *
+ * Functions skel_read() and skel_write() have been split into a *
+ * skel_do_read() and skel_do_write(), that cover the kernel stuff of read *
+ * and write operations, and the original skel_read() and skel_write(), *
+ * that handle communication with user space and call their _do_ companion. *
+ * *
+ * Only the _do_ versions are used by the lpvo_usb_gpib driver; other ones *
+ * can be (optionally) maintained in the compilation to have direct access *
+ * to a gpib controller for debug and diagnostics. *
+ * *
+ * To avoid collisions in names, devices in user space have been renamed *
+ * lpvo_raw1, lpvo_raw2 .... and the usb driver has been renamed with the *
+ * gpib module name. *
+ * *
+ *****************************************************************************/
+
+/*
+ * USB Skeleton driver - 2.2
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c
+ * but has been rewritten to be easier to read and use.
+ */
+
+#include <linux/errno.h>
+#include <linux/kref.h>
+#include <linux/uaccess.h>
+#include <linux/mutex.h>
+
+/* Get a minor range for your devices from the usb maintainer */
+#define USB_SKEL_MINOR_BASE 192
+
+/* private defines */
+
+#define MAX_TRANSFER (PAGE_SIZE - 512)
+/* MAX_TRANSFER is chosen so that the VM is not stressed by
+ * allocations > PAGE_SIZE and the number of packets in a page
+ * is an integer 512 is the largest possible packet on EHCI
+ */
+
+#define WRITES_IN_FLIGHT 1 /* we do not want more than one pending write */
+#define USER_DEVICE 1 /* compile for device(s) in user space */
+
+/* Structure to hold all of our device specific stuff */
+struct usb_skel {
+ struct usb_device *udev; /* the usb device for this device */
+ struct usb_interface *interface; /* the interface for this device */
+ struct semaphore limit_sem; /* limiting the number of writes in progress */
+ struct usb_anchor submitted; /* in case need to retract our submissions */
+ struct urb *bulk_in_urb; /* the urb to read data with */
+ unsigned char *bulk_in_buffer; /* the buffer to receive data */
+ size_t bulk_in_size; /* the size of the receive buffer */
+ size_t bulk_in_filled; /* number of bytes in the buffer */
+ size_t bulk_in_copied; /* already copied to user space */
+ __u8 bulk_in_endpoint_addr; /* the address of the bulk in endpoint */
+ __u8 bulk_out_endpoint_addr; /* the address of the bulk out endpoint */
+ int errors; /* the last request tanked */
+ bool ongoing_read; /* a read is going on */
+ spinlock_t err_lock; /* lock for errors */
+ struct kref kref;
+ struct mutex io_mutex; /* synchronize I/O with disconnect */
+ wait_queue_head_t bulk_in_wait; /* to wait for an ongoing read */
+};
+
+#define to_skel_dev(d) container_of(d, struct usb_skel, kref)
+
+static struct usb_driver skel_driver;
+static void skel_draw_down(struct usb_skel *dev);
+
+static void skel_delete(struct kref *kref)
+{
+ struct usb_skel *dev = to_skel_dev(kref);
+
+ usb_free_urb(dev->bulk_in_urb);
+ usb_put_dev(dev->udev);
+ kfree(dev->bulk_in_buffer);
+ kfree(dev);
+}
+
+/*
+ * skel_do_open() - to be called by usb_gpib_attach
+ */
+
+static int skel_do_open(gpib_board_t *board, int subminor)
+{
+ struct usb_skel *dev;
+ struct usb_interface *interface;
+ int retval = 0;
+
+ DIA_LOG(0, "Required minor: %d\n", subminor);
+
+ interface = usb_find_interface(&skel_driver, subminor);
+ if (!interface) {
+ pr_err("%s - error, can't find device for minor %d\n",
+ __func__, subminor);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ dev = usb_get_intfdata(interface);
+ if (!dev) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ retval = usb_autopm_get_interface(interface);
+ if (retval)
+ goto exit;
+
+ /* increment our usage count for the device */
+ kref_get(&dev->kref);
+
+ /* save our object in the file's private structure */
+ GPIB_DEV = dev;
+
+exit:
+ return retval;
+}
+
+/*
+ * skel_do_release() - to be called by usb_gpib_detach
+ */
+
+static int skel_do_release(gpib_board_t *board)
+{
+ struct usb_skel *dev;
+
+ dev = GPIB_DEV;
+ if (!dev)
+ return -ENODEV;
+
+ /* allow the device to be autosuspended */
+ mutex_lock(&dev->io_mutex);
+ if (dev->interface)
+ usb_autopm_put_interface(dev->interface);
+ mutex_unlock(&dev->io_mutex);
+
+ /* decrement the count on our device */
+ kref_put(&dev->kref, skel_delete);
+ return 0;
+}
+
+/*
+ * read functions
+ */
+
+static void skel_read_bulk_callback(struct urb *urb)
+{
+ struct usb_skel *dev;
+ unsigned long flags;
+
+ dev = urb->context;
+
+ spin_lock_irqsave(&dev->err_lock, flags);
+ /* sync/async unlink faults aren't errors */
+ if (urb->status) {
+ if (!(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN))
+ dev_err(&dev->interface->dev,
+ "%s - nonzero read bulk status received: %d\n",
+ __func__, urb->status);
+
+ dev->errors = urb->status;
+ } else {
+ dev->bulk_in_filled = urb->actual_length;
+ }
+ dev->ongoing_read = 0;
+ spin_unlock_irqrestore(&dev->err_lock, flags);
+
+ wake_up_interruptible(&dev->bulk_in_wait);
+}
+
+static int skel_do_read_io(struct usb_skel *dev, size_t count)
+{
+ int rv;
+
+ /* prepare a read */
+ usb_fill_bulk_urb(dev->bulk_in_urb,
+ dev->udev,
+ usb_rcvbulkpipe(dev->udev,
+ dev->bulk_in_endpoint_addr),
+ dev->bulk_in_buffer,
+ min(dev->bulk_in_size, count),
+ skel_read_bulk_callback,
+ dev);
+ /* tell everybody to leave the URB alone */
+ spin_lock_irq(&dev->err_lock);
+ dev->ongoing_read = 1;
+ spin_unlock_irq(&dev->err_lock);
+
+ /* submit bulk in urb, which means no data to deliver */
+ dev->bulk_in_filled = 0;
+ dev->bulk_in_copied = 0;
+
+ /* do it */
+ rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL);
+ if (rv < 0) {
+ dev_err(&dev->interface->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, rv);
+ rv = (rv == -ENOMEM) ? rv : -EIO;
+ spin_lock_irq(&dev->err_lock);
+ dev->ongoing_read = 0;
+ spin_unlock_irq(&dev->err_lock);
+ }
+
+ return rv;
+}
+
+/*
+ * skel_do_read() - read operations from lpvo_usb_gpib
+ */
+
+static ssize_t skel_do_read(struct usb_skel *dev, char *buffer, size_t count)
+{
+ int rv;
+ bool ongoing_io;
+
+ /* if we cannot read at all, return EOF */
+
+ if (!dev->bulk_in_urb || !count)
+ return 0;
+
+ DIA_LOG(1, "enter for %zu.\n", count);
+
+restart: /* added to comply with ftdi timeout technique */
+
+ /* no concurrent readers */
+
+ DIA_LOG(2, "restart with %zd %zd.\n", dev->bulk_in_filled, dev->bulk_in_copied);
+
+ rv = mutex_lock_interruptible(&dev->io_mutex);
+ if (rv < 0)
+ return rv;
+
+ if (!dev->interface) { /* disconnect() was called */
+ rv = -ENODEV;
+ goto exit;
+ }
+
+retry:
+ /* if IO is under way, we must not touch things */
+ spin_lock_irq(&dev->err_lock);
+ ongoing_io = dev->ongoing_read;
+ spin_unlock_irq(&dev->err_lock);
+
+ DIA_LOG(2, "retry with %d.\n", ongoing_io);
+
+ if (ongoing_io) {
+// /* nonblocking IO shall not wait */
+// /* no file, no O_NONBLOCK; maybe provide when from user space */
+// if (file->f_flags & O_NONBLOCK) {
+// rv = -EAGAIN;
+// goto exit;
+// }
+
+ /*
+ * IO may take forever
+ * hence wait in an interruptible state
+ */
+ rv = wait_event_interruptible(dev->bulk_in_wait, (!dev->ongoing_read));
+ if (rv < 0)
+ goto exit;
+ }
+
+ /* errors must be reported */
+ rv = dev->errors;
+ if (rv < 0) {
+ /* any error is reported once */
+ dev->errors = 0;
+ /* to preserve notifications about reset */
+ rv = (rv == -EPIPE) ? rv : -EIO;
+ /* report it */
+ goto exit;
+ }
+
+ /*
+ * if the buffer is filled we may satisfy the read
+ * else we need to start IO
+ */
+
+ if (dev->bulk_in_filled) {
+ /* we had read data */
+
+ size_t available = dev->bulk_in_filled - dev->bulk_in_copied;
+// size_t chunk = min(available, count); /* compute chunk later */
+ size_t chunk;
+
+ DIA_LOG(2, "we have data: %zu %zu.\n", dev->bulk_in_filled, dev->bulk_in_copied);
+
+ if (!available) {
+ /*
+ * all data has been used
+ * actual IO needs to be done
+ */
+ /* it seems that requests for less than dev->bulk_in_size
+ * are not accepted
+ */
+ rv = skel_do_read_io(dev, dev->bulk_in_size);
+ if (rv < 0)
+ goto exit;
+ else
+ goto retry;
+ }
+
+ /*
+ * data is available - chunk tells us how much shall be copied
+ */
+
+ /* Condition dev->bulk_in_copied > 0 maybe will never happen. In case,
+ * signal the event and copy using the original procedure, i.e., copy
+ * first two bytes also
+ */
+
+ if (dev->bulk_in_copied) {
+ int j;
+
+ for (j = 0 ; j < dev->bulk_in_filled ; j++) {
+ pr_alert("copy -> %x %zu %x\n",
+ j, dev->bulk_in_copied, dev->bulk_in_buffer[j]);
+ }
+ chunk = min(available, count);
+ memcpy(buffer, dev->bulk_in_buffer + dev->bulk_in_copied, chunk);
+ rv = chunk;
+ dev->bulk_in_copied += chunk;
+
+ /* copy discarding first two bytes that contain ftdi chip status */
+
+ } else {
+ /* account for two bytes to be discarded */
+ chunk = min(available, count + 2);
+ if (chunk < 2) {
+ pr_alert("BAD READ - chunk: %zu\n", chunk);
+ rv = -EIO;
+ goto exit;
+ }
+
+ memcpy(buffer, dev->bulk_in_buffer + 2, chunk - 2);
+ rv = chunk;
+ dev->bulk_in_copied += chunk;
+ }
+
+ /*
+ * if we are asked for more than we have,
+ * we start IO but don't wait
+ *
+ * No, no read ahead allowed; if the case, more data will be
+ * asked for by the lpvo_usb_gpib layer.
+ */
+// if (available < count)
+// skel_do_read_io(dev, dev->bulk_in_size);
+ } else {
+ DIA_LOG(1, "no data - start read - copied: %zd.\n", dev->bulk_in_copied);
+
+ /* no data in the buffer */
+ rv = skel_do_read_io(dev, dev->bulk_in_size);
+ if (rv < 0)
+ goto exit;
+ else
+ goto retry;
+ }
+exit:
+ mutex_unlock(&dev->io_mutex);
+ if (rv == 2)
+ goto restart; /* ftdi chip returns two status bytes after a latency anyhow */
+ DIA_LOG(1, "exit with %d.\n", rv);
+ if (rv > 0)
+ return rv - 2; /* account for 2 discarded bytes in a valid buffer */
+ return rv;
+}
+
+/*
+ * write functions
+ */
+
+static void skel_write_bulk_callback(struct urb *urb)
+{
+ struct usb_skel *dev;
+ unsigned long flags;
+
+ dev = urb->context;
+
+ /* sync/async unlink faults aren't errors */
+ if (urb->status) {
+ if (!(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN))
+ dev_err(&dev->interface->dev,
+ "%s - nonzero write bulk status received: %d\n",
+ __func__, urb->status);
+
+ spin_lock_irqsave(&dev->err_lock, flags);
+ dev->errors = urb->status;
+ spin_unlock_irqrestore(&dev->err_lock, flags);
+ }
+
+ /* free up our allocated buffer */
+ usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+ urb->transfer_buffer, urb->transfer_dma);
+ up(&dev->limit_sem);
+}
+
+/*
+ * skel_do_write() - write operations from lpvo_usb_gpib
+ */
+
+static ssize_t skel_do_write(struct usb_skel *dev, const char *buffer, size_t count)
+{
+ int retval = 0;
+ struct urb *urb = NULL;
+ char *buf = NULL;
+ size_t writesize = min_t(size_t, count, (size_t)MAX_TRANSFER);
+
+ /* verify that we actually have some data to write */
+ if (count == 0)
+ goto exit;
+
+ /*
+ * limit the number of URBs in flight to stop a user from using up all
+ * RAM
+ */
+ /* Only one URB is used, because we can't have a pending write() and go on */
+
+// if (!(file->f_flags & O_NONBLOCK)) { /* no NONBLOCK provided */
+ if (down_interruptible(&dev->limit_sem)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+// } else {
+// if (down_trylock(&dev->limit_sem)) {
+// retval = -EAGAIN;
+// goto exit;
+// }
+// }
+
+ spin_lock_irq(&dev->err_lock);
+ retval = dev->errors;
+ if (retval < 0) {
+ /* any error is reported once */
+ dev->errors = 0;
+ /* to preserve notifications about reset */
+ retval = (retval == -EPIPE) ? retval : -EIO;
+ }
+ spin_unlock_irq(&dev->err_lock);
+ if (retval < 0)
+ goto error;
+
+ /* create a urb, and a buffer for it, and copy the data to the urb */
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ buf = usb_alloc_coherent(dev->udev, writesize, GFP_KERNEL,
+ &urb->transfer_dma);
+ if (!buf) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ memcpy(buf, buffer, count);
+
+ /* this lock makes sure we don't submit URBs to gone devices */
+ mutex_lock(&dev->io_mutex);
+ if (!dev->interface) { /* disconnect() was called */
+ mutex_unlock(&dev->io_mutex);
+ retval = -ENODEV;
+ goto error;
+ }
+
+ /* initialize the urb properly */
+ usb_fill_bulk_urb(urb, dev->udev,
+ usb_sndbulkpipe(dev->udev, dev->bulk_out_endpoint_addr),
+ buf, writesize, skel_write_bulk_callback, dev);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(urb, &dev->submitted);
+
+ /* send the data out the bulk port */
+ retval = usb_submit_urb(urb, GFP_KERNEL);
+ mutex_unlock(&dev->io_mutex);
+ if (retval) {
+ dev_err(&dev->interface->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, retval);
+ goto error_unanchor;
+ }
+
+ /*
+ * release our reference to this urb, the USB core will eventually free
+ * it entirely
+ */
+ usb_free_urb(urb);
+
+ return writesize;
+
+error_unanchor:
+ usb_unanchor_urb(urb);
+error:
+ if (urb) {
+ usb_free_coherent(dev->udev, writesize, buf, urb->transfer_dma);
+ usb_free_urb(urb);
+ }
+ up(&dev->limit_sem);
+
+exit:
+ return retval;
+}
+
+/*
+ * services for the user space devices
+ */
+
+#if USER_DEVICE /* conditional compilation of user space device */
+
+static int skel_flush(struct file *file, fl_owner_t id)
+{
+ struct usb_skel *dev;
+ int res;
+
+ dev = file->private_data;
+ if (!dev)
+ return -ENODEV;
+
+ /* wait for io to stop */
+ mutex_lock(&dev->io_mutex);
+ skel_draw_down(dev);
+
+ /* read out errors, leave subsequent opens a clean slate */
+ spin_lock_irq(&dev->err_lock);
+ res = dev->errors ? (dev->errors == -EPIPE ? -EPIPE : -EIO) : 0;
+ dev->errors = 0;
+ spin_unlock_irq(&dev->err_lock);
+
+ mutex_unlock(&dev->io_mutex);
+
+ return res;
+}
+
+static int skel_open(struct inode *inode, struct file *file)
+{
+ struct usb_skel *dev;
+ struct usb_interface *interface;
+ int subminor;
+ int retval = 0;
+
+ subminor = iminor(inode);
+
+ interface = usb_find_interface(&skel_driver, subminor);
+ if (!interface) {
+ pr_err("%s - error, can't find device for minor %d\n",
+ __func__, subminor);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ dev = usb_get_intfdata(interface);
+ if (!dev) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ retval = usb_autopm_get_interface(interface);
+ if (retval)
+ goto exit;
+
+ /* increment our usage count for the device */
+ kref_get(&dev->kref);
+
+ /* save our object in the file's private structure */
+ file->private_data = dev;
+
+exit:
+ return retval;
+}
+
+static int skel_release(struct inode *inode, struct file *file)
+{
+ struct usb_skel *dev;
+
+ dev = file->private_data;
+ if (!dev)
+ return -ENODEV;
+
+ /* allow the device to be autosuspended */
+ mutex_lock(&dev->io_mutex);
+ if (dev->interface)
+ usb_autopm_put_interface(dev->interface);
+ mutex_unlock(&dev->io_mutex);
+
+ /* decrement the count on our device */
+ kref_put(&dev->kref, skel_delete);
+ return 0;
+}
+
+/*
+ * user space access to read function
+ */
+
+static ssize_t skel_read(struct file *file, char *buffer, size_t count,
+ loff_t *ppos)
+{
+ struct usb_skel *dev;
+ char *buf;
+ ssize_t rv;
+
+ dev = file->private_data;
+
+ buf = kmalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ rv = skel_do_read(dev, buf, count);
+
+ pr_alert("%s - return with %zu\n", __func__, rv);
+
+ if (rv > 0) {
+ if (copy_to_user(buffer, buf, rv)) {
+ kfree(buf);
+ return -EFAULT;
+ }
+ }
+ kfree(buf);
+ return rv;
+}
+
+/*
+ * user space access to write function
+ */
+
+static ssize_t skel_write(struct file *file, const char *user_buffer,
+ size_t count, loff_t *ppos)
+{
+ struct usb_skel *dev;
+ char *buf;
+ ssize_t rv;
+
+ dev = file->private_data;
+
+ buf = kmalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ if (copy_from_user(buf, user_buffer, count)) {
+ kfree(buf);
+ return -EFAULT;
+ }
+
+ rv = skel_do_write(dev, buf, count);
+ kfree(buf);
+ return rv;
+}
+#endif
+
+static const struct file_operations skel_fops = {
+ .owner = THIS_MODULE,
+#if USER_DEVICE
+ .read = skel_read,
+ .write = skel_write,
+ .open = skel_open,
+ .release = skel_release,
+ .flush = skel_flush,
+ .llseek = noop_llseek,
+#endif
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with the driver core
+ */
+#if USER_DEVICE
+static struct usb_class_driver skel_class = {
+ .name = "lpvo_raw%d",
+ .fops = &skel_fops,
+ .minor_base = USB_SKEL_MINOR_BASE,
+};
+#endif
+
+static int skel_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct usb_skel *dev;
+ struct usb_endpoint_descriptor *bulk_in, *bulk_out;
+ int retval;
+ char *device_path;
+
+ mutex_init(&minors_lock); /* required for handling minor numbers table */
+
+ /* allocate memory for our device state and initialize it */
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ kref_init(&dev->kref);
+ sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
+ mutex_init(&dev->io_mutex);
+ spin_lock_init(&dev->err_lock);
+ init_usb_anchor(&dev->submitted);
+ init_waitqueue_head(&dev->bulk_in_wait);
+
+ dev->udev = usb_get_dev(interface_to_usbdev(interface));
+ dev->interface = interface;
+
+ /* set up the endpoint information */
+ /* use only the first bulk-in and bulk-out endpoints */
+ retval = usb_find_common_endpoints(interface->cur_altsetting,
+ &bulk_in, &bulk_out, NULL, NULL);
+ if (retval) {
+ dev_err(&interface->dev,
+ "Could not find both bulk-in and bulk-out endpoints\n");
+ goto error;
+ }
+
+ dev->bulk_in_size = usb_endpoint_maxp(bulk_in);
+ dev->bulk_in_endpoint_addr = bulk_in->bEndpointAddress;
+ dev->bulk_in_buffer = kmalloc(dev->bulk_in_size, GFP_KERNEL);
+ if (!dev->bulk_in_buffer) {
+ retval = -ENOMEM;
+ goto error;
+ }
+ dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->bulk_in_urb) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ dev->bulk_out_endpoint_addr = bulk_out->bEndpointAddress;
+
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(interface, dev);
+
+ /* let the world know */
+
+ device_path = kobject_get_path(&dev->udev->dev.kobj, GFP_KERNEL);
+ pr_alert("%s:%s - New lpvo_usb_device -> bus: %d dev: %d path: %s\n", NAME, __func__,
+ dev->udev->bus->busnum, dev->udev->devnum, device_path);
+ kfree(device_path);
+
+#if USER_DEVICE
+ /* we can register the device now, as it is ready */
+ retval = usb_register_dev(interface, &skel_class);
+ if (retval) {
+ /* something prevented us from registering this driver */
+ dev_err(&interface->dev,
+ "Not able to get a minor for this device.\n");
+ usb_set_intfdata(interface, NULL);
+ goto error;
+ }
+
+ /* let the user know what node this device is now attached to */
+ dev_info(&interface->dev,
+ "lpvo_usb_gpib device now attached to lpvo_raw%d",
+ interface->minor);
+#endif
+
+ write_latency_timer(dev->udev); /* adjust the latency timer */
+
+ usb_gpib_init_module(interface); /* last, init the lpvo for this minor */
+
+ return 0;
+
+error:
+ /* this frees allocated memory */
+ kref_put(&dev->kref, skel_delete);
+
+ return retval;
+}
+
+static void skel_disconnect(struct usb_interface *interface)
+{
+ struct usb_skel *dev;
+ int minor = interface->minor;
+
+ usb_gpib_exit_module(minor); /* first, disactivate the lpvo */
+
+ dev = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
+
+#if USER_DEVICE
+ /* give back our minor */
+ usb_deregister_dev(interface, &skel_class);
+#endif
+
+ /* prevent more I/O from starting */
+ mutex_lock(&dev->io_mutex);
+ dev->interface = NULL;
+ mutex_unlock(&dev->io_mutex);
+
+ usb_kill_anchored_urbs(&dev->submitted);
+
+ /* decrement our usage count */
+ kref_put(&dev->kref, skel_delete);
+
+ dev_info(&interface->dev, "USB lpvo_raw #%d now disconnected", minor);
+}
+
+static void skel_draw_down(struct usb_skel *dev)
+{
+ int time;
+
+ time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
+ if (!time)
+ usb_kill_anchored_urbs(&dev->submitted);
+ usb_kill_urb(dev->bulk_in_urb);
+}
+
+static int skel_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct usb_skel *dev = usb_get_intfdata(intf);
+
+ if (!dev)
+ return 0;
+ skel_draw_down(dev);
+ return 0;
+}
+
+static int skel_resume(struct usb_interface *intf)
+{
+ return 0;
+}
+
+static int skel_pre_reset(struct usb_interface *intf)
+{
+ struct usb_skel *dev = usb_get_intfdata(intf);
+
+ mutex_lock(&dev->io_mutex);
+ skel_draw_down(dev);
+
+ return 0;
+}
+
+static int skel_post_reset(struct usb_interface *intf)
+{
+ struct usb_skel *dev = usb_get_intfdata(intf);
+
+ /* we are sure no URBs are active - no locking needed */
+ dev->errors = -EPIPE;
+ mutex_unlock(&dev->io_mutex);
+
+ return 0;
+}
+
+static struct usb_driver skel_driver = {
+ .name = NAME,
+ .probe = skel_probe,
+ .disconnect = skel_disconnect,
+ .suspend = skel_suspend,
+ .resume = skel_resume,
+ .pre_reset = skel_pre_reset,
+ .post_reset = skel_post_reset,
+ .id_table = skel_table,
+ .supports_autosuspend = 1,
+};
+
+module_usb_driver(skel_driver);
diff --git a/drivers/staging/gpib/nec7210/Makefile b/drivers/staging/gpib/nec7210/Makefile
new file mode 100644
index 000000000000..8d4d90f21109
--- /dev/null
+++ b/drivers/staging/gpib/nec7210/Makefile
@@ -0,0 +1,4 @@
+
+obj-m += nec7210.o
+
+
diff --git a/drivers/staging/gpib/nec7210/board.h b/drivers/staging/gpib/nec7210/board.h
new file mode 100644
index 000000000000..ac3fe38ade57
--- /dev/null
+++ b/drivers/staging/gpib/nec7210/board.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_PCIIA_BOARD_H
+#define _GPIB_PCIIA_BOARD_H
+
+#include "gpibP.h"
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+#include "nec7210.h"
+
+#endif //_GPIB_PCIIA_BOARD_H
+
diff --git a/drivers/staging/gpib/nec7210/nec7210.c b/drivers/staging/gpib/nec7210/nec7210.c
new file mode 100644
index 000000000000..1d9951035497
--- /dev/null
+++ b/drivers/staging/gpib/nec7210/nec7210.c
@@ -0,0 +1,1134 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "board.h"
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/dma.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB library code for NEC uPD7210");
+
+int nec7210_enable_eos(gpib_board_t *board, struct nec7210_priv *priv, uint8_t eos_byte,
+ int compare_8_bits)
+{
+ write_byte(priv, eos_byte, EOSR);
+ priv->auxa_bits |= HR_REOS;
+ if (compare_8_bits)
+ priv->auxa_bits |= HR_BIN;
+ else
+ priv->auxa_bits &= ~HR_BIN;
+ write_byte(priv, priv->auxa_bits, AUXMR);
+ return 0;
+}
+EXPORT_SYMBOL(nec7210_enable_eos);
+
+void nec7210_disable_eos(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ priv->auxa_bits &= ~HR_REOS;
+ write_byte(priv, priv->auxa_bits, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_disable_eos);
+
+int nec7210_parallel_poll(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *result)
+{
+ int ret;
+
+ clear_bit(COMMAND_READY_BN, &priv->state);
+
+ // execute parallel poll
+ write_byte(priv, AUX_EPP, AUXMR);
+ // wait for result FIXME: support timeouts
+ ret = wait_event_interruptible(board->wait, test_bit(COMMAND_READY_BN, &priv->state));
+ if (ret) {
+ dev_dbg(board->gpib_dev, "gpib: parallel poll interrupted\n");
+ return -ERESTARTSYS;
+ }
+ *result = read_byte(priv, CPTR);
+
+ return 0;
+}
+EXPORT_SYMBOL(nec7210_parallel_poll);
+
+void nec7210_parallel_poll_configure(gpib_board_t *board,
+ struct nec7210_priv *priv, unsigned int configuration)
+{
+ write_byte(priv, PPR | configuration, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_parallel_poll_configure);
+
+void nec7210_parallel_poll_response(gpib_board_t *board, struct nec7210_priv *priv, int ist)
+{
+ if (ist)
+ write_byte(priv, AUX_SPPF, AUXMR);
+ else
+ write_byte(priv, AUX_CPPF, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_parallel_poll_response);
+/* This is really only adequate for chips that do a 488.2 style reqt/reqf
+ * based on bit 6 of the SPMR (see chapter 11.3.3 of 488.2). For simpler chips that simply
+ * set rsv directly based on bit 6, we either need to do more hardware setup to expose
+ * the 488.2 capability (for example with NI chips), or we need to implement the
+ * 488.2 set srv state machine in the driver (if that is even viable).
+ */
+void nec7210_serial_poll_response(gpib_board_t *board, struct nec7210_priv *priv, uint8_t status)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (status & request_service_bit) {
+ priv->srq_pending = 1;
+ clear_bit(SPOLL_NUM, &board->status);
+
+ } else {
+ priv->srq_pending = 0;
+ }
+ write_byte(priv, status, SPMR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+EXPORT_SYMBOL(nec7210_serial_poll_response);
+
+uint8_t nec7210_serial_poll_status(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ return read_byte(priv, SPSR);
+}
+EXPORT_SYMBOL(nec7210_serial_poll_status);
+
+int nec7210_primary_address(const gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int address)
+{
+ // put primary address in address0
+ write_byte(priv, address & ADDRESS_MASK, ADR);
+ return 0;
+}
+EXPORT_SYMBOL(nec7210_primary_address);
+
+int nec7210_secondary_address(const gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int address, int enable)
+{
+ if (enable) {
+ // put secondary address in address1
+ write_byte(priv, HR_ARS | (address & ADDRESS_MASK), ADR);
+ // go to address mode 2
+ priv->reg_bits[ADMR] &= ~HR_ADM0;
+ priv->reg_bits[ADMR] |= HR_ADM1;
+ } else {
+ // disable address1 register
+ write_byte(priv, HR_ARS | HR_DT | HR_DL, ADR);
+ // go to address mode 1
+ priv->reg_bits[ADMR] |= HR_ADM0;
+ priv->reg_bits[ADMR] &= ~HR_ADM1;
+ }
+ write_byte(priv, priv->reg_bits[ADMR], ADMR);
+ return 0;
+}
+EXPORT_SYMBOL(nec7210_secondary_address);
+
+static void update_talker_state(struct nec7210_priv *priv, unsigned int address_status_bits)
+{
+ if ((address_status_bits & HR_TA)) {
+ if ((address_status_bits & HR_NATN)) {
+ if (address_status_bits & HR_SPMS)
+ priv->talker_state = serial_poll_active;
+ else
+ priv->talker_state = talker_active;
+ } else {
+ priv->talker_state = talker_addressed;
+ }
+ } else {
+ priv->talker_state = talker_idle;
+ }
+}
+
+static void update_listener_state(struct nec7210_priv *priv, unsigned int address_status_bits)
+{
+ if (address_status_bits & HR_LA) {
+ if ((address_status_bits & HR_NATN))
+ priv->listener_state = listener_active;
+ else
+ priv->listener_state = listener_addressed;
+ } else {
+ priv->listener_state = listener_idle;
+ }
+}
+
+unsigned int nec7210_update_status_nolock(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ int address_status_bits;
+ u8 spoll_status;
+
+ if (!priv)
+ return 0;
+
+ address_status_bits = read_byte(priv, ADSR);
+ if (address_status_bits & HR_CIC)
+ set_bit(CIC_NUM, &board->status);
+ else
+ clear_bit(CIC_NUM, &board->status);
+ // check for talker/listener addressed
+ update_talker_state(priv, address_status_bits);
+ if (priv->talker_state == talker_active || priv->talker_state == talker_addressed)
+ set_bit(TACS_NUM, &board->status);
+ else
+ clear_bit(TACS_NUM, &board->status);
+ update_listener_state(priv, address_status_bits);
+ if (priv->listener_state == listener_active ||
+ priv->listener_state == listener_addressed)
+ set_bit(LACS_NUM, &board->status);
+ else
+ clear_bit(LACS_NUM, &board->status);
+ if (address_status_bits & HR_NATN)
+ clear_bit(ATN_NUM, &board->status);
+ else
+ set_bit(ATN_NUM, &board->status);
+ spoll_status = nec7210_serial_poll_status(board, priv);
+ if (priv->srq_pending && (spoll_status & request_service_bit) == 0) {
+ priv->srq_pending = 0;
+ set_bit(SPOLL_NUM, &board->status);
+ }
+// dev_dbg(board->gpib_dev, "status 0x%x, state 0x%x\n", board->status, priv->state);
+
+ /* we rely on the interrupt handler to set the
+ * rest of the status bits
+ */
+
+ return board->status;
+}
+EXPORT_SYMBOL(nec7210_update_status_nolock);
+
+unsigned int nec7210_update_status(gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int clear_mask)
+{
+ unsigned long flags;
+ unsigned int retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ board->status &= ~clear_mask;
+ retval = nec7210_update_status_nolock(board, priv);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_update_status);
+
+unsigned int nec7210_set_reg_bits(struct nec7210_priv *priv, unsigned int reg,
+ unsigned int mask, unsigned int bits)
+{
+ priv->reg_bits[reg] &= ~mask;
+ priv->reg_bits[reg] |= mask & bits;
+ write_byte(priv, priv->reg_bits[reg], reg);
+ return priv->reg_bits[reg];
+}
+EXPORT_SYMBOL(nec7210_set_reg_bits);
+
+void nec7210_set_handshake_mode(gpib_board_t *board, struct nec7210_priv *priv, int mode)
+{
+ unsigned long flags;
+
+ mode &= HR_HANDSHAKE_MASK;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ if ((priv->auxa_bits & HR_HANDSHAKE_MASK) != mode) {
+ priv->auxa_bits &= ~HR_HANDSHAKE_MASK;
+ priv->auxa_bits |= mode;
+ write_byte(priv, priv->auxa_bits, AUXMR);
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+EXPORT_SYMBOL(nec7210_set_handshake_mode);
+
+uint8_t nec7210_read_data_in(gpib_board_t *board, struct nec7210_priv *priv, int *end)
+{
+ unsigned long flags;
+ u8 data;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ data = read_byte(priv, DIR);
+ clear_bit(READ_READY_BN, &priv->state);
+ if (test_and_clear_bit(RECEIVED_END_BN, &priv->state))
+ *end = 1;
+ else
+ *end = 0;
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return data;
+}
+EXPORT_SYMBOL(nec7210_read_data_in);
+
+int nec7210_take_control(gpib_board_t *board, struct nec7210_priv *priv, int syncronous)
+{
+ int i;
+ const int timeout = 100;
+ int retval = 0;
+ unsigned int adsr_bits = 0;
+
+ if (syncronous)
+ write_byte(priv, AUX_TCS, AUXMR);
+ else
+ write_byte(priv, AUX_TCA, AUXMR);
+ // busy wait until ATN is asserted
+ for (i = 0; i < timeout; i++) {
+ adsr_bits = read_byte(priv, ADSR);
+ if ((adsr_bits & HR_NATN) == 0)
+ break;
+ udelay(1);
+ }
+ if (i == timeout)
+ return -ETIMEDOUT;
+
+ clear_bit(WRITE_READY_BN, &priv->state);
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_take_control);
+
+int nec7210_go_to_standby(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ int i;
+ const int timeout = 1000;
+ unsigned int adsr_bits = 0;
+ int retval = 0;
+
+ write_byte(priv, AUX_GTS, AUXMR);
+ // busy wait until ATN is released
+ for (i = 0; i < timeout; i++) {
+ adsr_bits = read_byte(priv, ADSR);
+ if (adsr_bits & HR_NATN)
+ break;
+ udelay(1);
+ }
+ // if busy wait has failed, try sleeping
+ if (i == timeout) {
+ for (i = 0; i < HZ; i++) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (schedule_timeout(1))
+ return -ERESTARTSYS;
+ adsr_bits = read_byte(priv, ADSR);
+ if (adsr_bits & HR_NATN)
+ break;
+ }
+ if (i == HZ) {
+ pr_err("nec7210: error waiting for NATN\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ clear_bit(COMMAND_READY_BN, &priv->state);
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_go_to_standby);
+
+void nec7210_request_system_control(gpib_board_t *board, struct nec7210_priv *priv,
+ int request_control)
+{
+ if (request_control == 0) {
+ write_byte(priv, AUX_CREN, AUXMR);
+ write_byte(priv, AUX_CIFC, AUXMR);
+ write_byte(priv, AUX_DSC, AUXMR);
+ }
+}
+EXPORT_SYMBOL(nec7210_request_system_control);
+
+void nec7210_interface_clear(gpib_board_t *board, struct nec7210_priv *priv, int assert)
+{
+ if (assert)
+ write_byte(priv, AUX_SIFC, AUXMR);
+ else
+ write_byte(priv, AUX_CIFC, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_interface_clear);
+
+void nec7210_remote_enable(gpib_board_t *board, struct nec7210_priv *priv, int enable)
+{
+ if (enable)
+ write_byte(priv, AUX_SREN, AUXMR);
+ else
+ write_byte(priv, AUX_CREN, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_remote_enable);
+
+void nec7210_release_rfd_holdoff(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (test_bit(RFD_HOLDOFF_BN, &priv->state) &&
+ test_bit(READ_READY_BN, &priv->state) == 0) {
+ write_byte(priv, AUX_FH, AUXMR);
+ clear_bit(RFD_HOLDOFF_BN, &priv->state);
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+EXPORT_SYMBOL(nec7210_release_rfd_holdoff);
+
+unsigned int nec7210_t1_delay(gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int nano_sec)
+{
+ unsigned int retval;
+
+ if (nano_sec <= 500) {
+ priv->auxb_bits |= HR_TRI;
+ retval = 500;
+ } else {
+ priv->auxb_bits &= ~HR_TRI;
+ retval = 2000;
+ }
+ write_byte(priv, priv->auxb_bits, AUXMR);
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_t1_delay);
+
+void nec7210_return_to_local(const gpib_board_t *board, struct nec7210_priv *priv)
+{
+ write_byte(priv, AUX_RTL, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_return_to_local);
+
+static inline short nec7210_atn_has_changed(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ short address_status_bits = read_byte(priv, ADSR);
+
+ if (address_status_bits & HR_NATN) {
+ if (test_bit(ATN_NUM, &board->status))
+ return 1;
+ else
+ return 0;
+ } else {
+ if (test_bit(ATN_NUM, &board->status))
+ return 0;
+ else
+ return 1;
+ }
+ return -1;
+}
+
+int nec7210_command(gpib_board_t *board, struct nec7210_priv *priv, uint8_t
+ *buffer, size_t length, size_t *bytes_written)
+{
+ int retval = 0;
+ unsigned long flags;
+
+ *bytes_written = 0;
+
+ clear_bit(BUS_ERROR_BN, &priv->state);
+
+ while (*bytes_written < length) {
+ if (wait_event_interruptible(board->wait,
+ test_bit(COMMAND_READY_BN, &priv->state) ||
+ test_bit(BUS_ERROR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib command wait interrupted\n");
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ break;
+ if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) {
+ pr_err("nec7210: bus error on command byte\n");
+ break;
+ }
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ clear_bit(COMMAND_READY_BN, &priv->state);
+ write_byte(priv, buffer[*bytes_written], CDOR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ ++(*bytes_written);
+
+ if (need_resched())
+ schedule();
+ }
+ // wait for last byte to get sent
+ if (wait_event_interruptible(board->wait, test_bit(COMMAND_READY_BN, &priv->state) ||
+ test_bit(BUS_ERROR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib command wait interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ dev_dbg(board->gpib_dev, "gpib command timed out\n");
+ retval = -ETIMEDOUT;
+ }
+ if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) {
+ pr_err("nec7210: bus error on command byte\n");
+ retval = -EIO;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_command);
+
+static int pio_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval = 0;
+
+ *bytes_read = 0;
+ *end = 0;
+
+ while (*bytes_read < length) {
+ if (wait_event_interruptible(board->wait,
+ test_bit(READ_READY_BN, &priv->state) ||
+ test_bit(DEV_CLEAR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "nec7210: pio read wait interrupted\n");
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (test_bit(READ_READY_BN, &priv->state)) {
+ if (*bytes_read == 0) {
+ /* We set the handshake mode here because we know
+ * no new bytes will arrive (it has already arrived
+ * and is awaiting being read out of the chip) while we are changing
+ * modes. This ensures we can reliably keep track
+ * of the holdoff state.
+ */
+ nec7210_set_handshake_mode(board, priv, HR_HLDA);
+ }
+ buffer[(*bytes_read)++] = nec7210_read_data_in(board, priv, end);
+ if (*end)
+ break;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ dev_dbg(board->gpib_dev, "interrupted by timeout\n");
+ retval = -ETIMEDOUT;
+ break;
+ }
+ if (test_bit(DEV_CLEAR_BN, &priv->state)) {
+ dev_dbg(board->gpib_dev, "interrupted by device clear\n");
+ retval = -EINTR;
+ break;
+ }
+
+ if (*bytes_read < length)
+ nec7210_release_rfd_holdoff(board, priv);
+
+ if (need_resched())
+ schedule();
+ }
+ return retval;
+}
+
+#ifdef NEC_DMA
+static ssize_t __dma_read(gpib_board_t *board, struct nec7210_priv *priv, size_t length)
+{
+ ssize_t retval = 0;
+ size_t count = 0;
+ unsigned long flags, dma_irq_flags;
+
+ if (length == 0)
+ return 0;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ dma_irq_flags = claim_dma_lock();
+ disable_dma(priv->dma_channel);
+ /* program dma controller */
+ clear_dma_ff(priv->dma_channel);
+ set_dma_count(priv->dma_channel, length);
+ set_dma_addr(priv->dma_channel, priv->dma_buffer_addr);
+ set_dma_mode(priv->dma_channel, DMA_MODE_READ);
+ release_dma_lock(dma_irq_flags);
+
+ enable_dma(priv->dma_channel);
+
+ set_bit(DMA_READ_IN_PROGRESS_BN, &priv->state);
+ clear_bit(READ_READY_BN, &priv->state);
+
+ // enable nec7210 dma
+ nec7210_set_reg_bits(priv, IMR2, HR_DMAI, HR_DMAI);
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ // wait for data to transfer
+ if (wait_event_interruptible(board->wait,
+ test_bit(DMA_READ_IN_PROGRESS_BN, &priv->state) == 0 ||
+ test_bit(DEV_CLEAR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "nec7210: dma read wait interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &priv->state))
+ retval = -EINTR;
+
+ // disable nec7210 dma
+ nec7210_set_reg_bits(priv, IMR2, HR_DMAI, 0);
+
+ // record how many bytes we transferred
+ flags = claim_dma_lock();
+ clear_dma_ff(priv->dma_channel);
+ disable_dma(priv->dma_channel);
+ count += length - get_dma_residue(priv->dma_channel);
+ release_dma_lock(flags);
+
+ return retval ? retval : count;
+}
+
+static ssize_t dma_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length)
+{
+ size_t remain = length;
+ size_t transfer_size;
+ ssize_t retval = 0;
+
+ while (remain > 0) {
+ transfer_size = (priv->dma_buffer_length < remain) ?
+ priv->dma_buffer_length : remain;
+ retval = __dma_read(board, priv, transfer_size);
+ if (retval < 0)
+ break;
+ memcpy(buffer, priv->dma_buffer, transfer_size);
+ remain -= retval;
+ buffer += retval;
+ if (test_bit(RECEIVED_END_BN, &priv->state))
+ break;
+ }
+
+ if (retval < 0)
+ return retval;
+
+ return length - remain;
+}
+#endif
+
+int nec7210_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval = 0;
+
+ *end = 0;
+ *bytes_read = 0;
+
+ if (length == 0)
+ return 0;
+
+ clear_bit(DEV_CLEAR_BN, &priv->state); // XXX wrong
+
+ nec7210_release_rfd_holdoff(board, priv);
+
+ retval = pio_read(board, priv, buffer, length, end, bytes_read);
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_read);
+
+static int pio_write_wait(gpib_board_t *board, struct nec7210_priv *priv,
+ short wake_on_lacs, short wake_on_atn, short wake_on_bus_error)
+{
+ // wait until byte is ready to be sent
+ if (wait_event_interruptible(board->wait,
+ (test_bit(TACS_NUM, &board->status) &&
+ test_bit(WRITE_READY_BN, &priv->state)) ||
+ test_bit(DEV_CLEAR_BN, &priv->state) ||
+ (wake_on_bus_error && test_bit(BUS_ERROR_BN, &priv->state)) ||
+ (wake_on_lacs && test_bit(LACS_NUM, &board->status)) ||
+ (wake_on_atn && test_bit(ATN_NUM, &board->status)) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ dev_dbg(board->gpib_dev, "nec7210: write timed out\n");
+ return -ETIMEDOUT;
+ }
+ if (test_bit(DEV_CLEAR_BN, &priv->state)) {
+ dev_dbg(board->gpib_dev, "nec7210: write interrupted by clear\n");
+ return -EINTR;
+ }
+ if (wake_on_bus_error && test_and_clear_bit(BUS_ERROR_BN, &priv->state)) {
+ dev_dbg(board->gpib_dev, "nec7210: bus error on write\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int pio_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, size_t *bytes_written)
+{
+ size_t last_count = 0;
+ ssize_t retval = 0;
+ unsigned long flags;
+ const int max_bus_errors = (length > 1000) ? length : 1000;
+ int bus_error_count = 0;
+ *bytes_written = 0;
+
+ clear_bit(BUS_ERROR_BN, &priv->state);
+
+ while (*bytes_written < length) {
+ if (need_resched())
+ schedule();
+
+ retval = pio_write_wait(board, priv, 0, 0, priv->type == NEC7210);
+ if (retval == -EIO) {
+ /* resend last byte on bus error */
+ *bytes_written = last_count;
+ dev_dbg(board->gpib_dev, "resending %c\n", buffer[*bytes_written]);
+ /* we can get unrecoverable bus errors,
+ * so give up after a while
+ */
+ bus_error_count++;
+ if (bus_error_count > max_bus_errors)
+ return retval;
+ continue;
+ } else {
+ if (retval < 0)
+ return retval;
+ }
+ spin_lock_irqsave(&board->spinlock, flags);
+ clear_bit(BUS_ERROR_BN, &priv->state);
+ clear_bit(WRITE_READY_BN, &priv->state);
+ last_count = *bytes_written;
+ write_byte(priv, buffer[(*bytes_written)++], CDOR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ }
+ retval = pio_write_wait(board, priv, 1, 1, priv->type == NEC7210);
+ return retval;
+}
+
+#ifdef NEC_DMA
+static ssize_t __dma_write(gpib_board_t *board, struct nec7210_priv *priv, dma_addr_t address,
+ size_t length)
+{
+ unsigned long flags, dma_irq_flags;
+ int residue = 0;
+ int retval = 0;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ /* program dma controller */
+ dma_irq_flags = claim_dma_lock();
+ disable_dma(priv->dma_channel);
+ clear_dma_ff(priv->dma_channel);
+ set_dma_count(priv->dma_channel, length);
+ set_dma_addr(priv->dma_channel, address);
+ set_dma_mode(priv->dma_channel, DMA_MODE_WRITE);
+ enable_dma(priv->dma_channel);
+ release_dma_lock(dma_irq_flags);
+
+ // enable board's dma for output
+ nec7210_set_reg_bits(priv, IMR2, HR_DMAO, HR_DMAO);
+
+ clear_bit(WRITE_READY_BN, &priv->state);
+ set_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state);
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ // suspend until message is sent
+ if (wait_event_interruptible(board->wait,
+ test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state) == 0 ||
+ test_bit(BUS_ERROR_BN, &priv->state) ||
+ test_bit(DEV_CLEAR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted!\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &priv->state))
+ retval = -EINTR;
+ if (test_and_clear_bit(BUS_ERROR_BN, &priv->state))
+ retval = -EIO;
+
+ // disable board's dma
+ nec7210_set_reg_bits(priv, IMR2, HR_DMAO, 0);
+
+ dma_irq_flags = claim_dma_lock();
+ clear_dma_ff(priv->dma_channel);
+ disable_dma(priv->dma_channel);
+ residue = get_dma_residue(priv->dma_channel);
+ release_dma_lock(dma_irq_flags);
+
+ if (residue)
+ retval = -EPIPE;
+
+ return retval ? retval : length;
+}
+
+static ssize_t dma_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length)
+{
+ size_t remain = length;
+ size_t transfer_size;
+ ssize_t retval = 0;
+
+ while (remain > 0) {
+ transfer_size = (priv->dma_buffer_length < remain) ?
+ priv->dma_buffer_length : remain;
+ memcpy(priv->dma_buffer, buffer, transfer_size);
+ retval = __dma_write(board, priv, priv->dma_buffer_addr, transfer_size);
+ if (retval < 0)
+ break;
+ remain -= retval;
+ buffer += retval;
+ }
+
+ if (retval < 0)
+ return retval;
+
+ return length - remain;
+}
+#endif
+int nec7210_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ int retval = 0;
+
+ *bytes_written = 0;
+
+ clear_bit(DEV_CLEAR_BN, &priv->state); //XXX
+
+ if (send_eoi)
+ length-- ; /* save the last byte for sending EOI */
+
+ if (length > 0) {
+ // isa dma transfer
+ if (0 /*priv->dma_channel*/) {
+/*
+ * dma writes are unreliable since they can't recover from bus errors
+ * (which happen when ATN is asserted in the middle of a write)
+ */
+#ifdef NEC_DMA
+ retval = dma_write(board, priv, buffer, length);
+ if (retval < 0)
+ return retval;
+ count += retval;
+#endif
+ } else { // PIO transfer
+ size_t num_bytes;
+
+ retval = pio_write(board, priv, buffer, length, &num_bytes);
+
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ }
+ if (send_eoi) {
+ size_t num_bytes;
+
+ /* We need to wait to make sure we will immediately be able to write the data byte
+ * into the chip before sending the associated AUX_SEOI command. This is really
+ * only needed for length==1 since otherwise the earlier calls to pio_write
+ * will have dont the wait already.
+ */
+ retval = pio_write_wait(board, priv, 0, 0, priv->type == NEC7210);
+ if (retval < 0)
+ return retval;
+ /*send EOI */
+ write_byte(priv, AUX_SEOI, AUXMR);
+
+ retval = pio_write(board, priv, &buffer[*bytes_written], 1, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_write);
+
+/*
+ * interrupt service routine
+ */
+irqreturn_t nec7210_interrupt(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ int status1, status2;
+
+ // read interrupt status (also clears status)
+ status1 = read_byte(priv, ISR1);
+ status2 = read_byte(priv, ISR2);
+
+ return nec7210_interrupt_have_status(board, priv, status1, status2);
+}
+EXPORT_SYMBOL(nec7210_interrupt);
+
+irqreturn_t nec7210_interrupt_have_status(gpib_board_t *board,
+ struct nec7210_priv *priv, int status1, int status2)
+{
+#ifdef NEC_DMA
+ unsigned long dma_flags;
+#endif
+ int retval = IRQ_NONE;
+
+ // record service request in status
+ if (status2 & HR_SRQI)
+ set_bit(SRQI_NUM, &board->status);
+
+ // change in lockout status
+ if (status2 & HR_LOKC) {
+ if (status2 & HR_LOK)
+ set_bit(LOK_NUM, &board->status);
+ else
+ clear_bit(LOK_NUM, &board->status);
+ }
+
+ // change in remote status
+ if (status2 & HR_REMC) {
+ if (status2 & HR_REM)
+ set_bit(REM_NUM, &board->status);
+ else
+ clear_bit(REM_NUM, &board->status);
+ }
+
+ // record reception of END
+ if (status1 & HR_END) {
+ set_bit(RECEIVED_END_BN, &priv->state);
+ if ((priv->auxa_bits & HR_HANDSHAKE_MASK) == HR_HLDE)
+ set_bit(RFD_HOLDOFF_BN, &priv->state);
+ }
+
+ // get incoming data in PIO mode
+ if ((status1 & HR_DI)) {
+ set_bit(READ_READY_BN, &priv->state);
+ if ((priv->auxa_bits & HR_HANDSHAKE_MASK) == HR_HLDA)
+ set_bit(RFD_HOLDOFF_BN, &priv->state);
+ }
+#ifdef NEC_DMA
+ // check for dma read transfer complete
+ if (test_bit(DMA_READ_IN_PROGRESS_BN, &priv->state)) {
+ dma_flags = claim_dma_lock();
+ disable_dma(priv->dma_channel);
+ clear_dma_ff(priv->dma_channel);
+ if ((status1 & HR_END) || get_dma_residue(priv->dma_channel) == 0)
+ clear_bit(DMA_READ_IN_PROGRESS_BN, &priv->state);
+ else
+ enable_dma(priv->dma_channel);
+ release_dma_lock(dma_flags);
+ }
+#endif
+ if ((status1 & HR_DO)) {
+ if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state) == 0)
+ set_bit(WRITE_READY_BN, &priv->state);
+#ifdef NEC_DMA
+ if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state)) { // write data, isa dma mode
+ // check if dma transfer is complete
+ dma_flags = claim_dma_lock();
+ disable_dma(priv->dma_channel);
+ clear_dma_ff(priv->dma_channel);
+ if (get_dma_residue(priv->dma_channel) == 0) {
+ clear_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state);
+ // XXX race? byte may still be in CDOR reg
+ } else {
+ clear_bit(WRITE_READY_BN, &priv->state);
+ enable_dma(priv->dma_channel);
+ }
+ release_dma_lock(dma_flags);
+ }
+#endif
+ }
+
+ // outgoing command can be sent
+ if (status2 & HR_CO)
+ set_bit(COMMAND_READY_BN, &priv->state);
+
+ // command pass through received
+ if (status1 & HR_CPT) {
+ unsigned int command;
+
+ command = read_byte(priv, CPTR) & gpib_command_mask;
+ write_byte(priv, AUX_NVAL, AUXMR);
+// printk("gpib: command pass through 0x%x\n", command);
+ }
+
+ if (status1 & HR_ERR)
+ set_bit(BUS_ERROR_BN, &priv->state);
+
+ if (status1 & HR_DEC) {
+ unsigned short address_status_bits = read_byte(priv, ADSR);
+
+ // ignore device clear events if we are controller in charge
+ if ((address_status_bits & HR_CIC) == 0) {
+ push_gpib_event(board, EventDevClr);
+ set_bit(DEV_CLEAR_BN, &priv->state);
+ }
+ }
+
+ if (status1 & HR_DET)
+ push_gpib_event(board, EventDevTrg);
+
+ // Addressing status has changed
+ if (status2 & HR_ADSC)
+ set_bit(ADR_CHANGE_BN, &priv->state);
+
+ if ((status1 & priv->reg_bits[IMR1]) ||
+ (status2 & (priv->reg_bits[IMR2] & IMR2_ENABLE_INTR_MASK)) ||
+ nec7210_atn_has_changed(board, priv)) {
+ nec7210_update_status_nolock(board, priv);
+ dev_dbg(board->gpib_dev, "minor %i, stat %lx, isr1 0x%x, imr1 0x%x, isr2 0x%x, imr2 0x%x\n",
+ board->minor, board->status, status1, priv->reg_bits[IMR1], status2,
+ priv->reg_bits[IMR2]);
+ wake_up_interruptible(&board->wait); /* wake up sleeping process */
+ retval = IRQ_HANDLED;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_interrupt_have_status);
+
+void nec7210_board_reset(struct nec7210_priv *priv, const gpib_board_t *board)
+{
+ /* 7210 chip reset */
+ write_byte(priv, AUX_CR, AUXMR);
+
+ /* disable all interrupts */
+ priv->reg_bits[IMR1] = 0;
+ write_byte(priv, priv->reg_bits[IMR1], IMR1);
+ priv->reg_bits[IMR2] = 0;
+ write_byte(priv, priv->reg_bits[IMR2], IMR2);
+ write_byte(priv, 0, SPMR);
+
+ /* clear registers by reading */
+ read_byte(priv, CPTR);
+ read_byte(priv, ISR1);
+ read_byte(priv, ISR2);
+
+ /* parallel poll unconfigure */
+ write_byte(priv, PPR | HR_PPU, AUXMR);
+
+ priv->reg_bits[ADMR] = HR_TRM0 | HR_TRM1;
+
+ priv->auxa_bits = AUXRA | HR_HLDA;
+ write_byte(priv, priv->auxa_bits, AUXMR);
+
+ write_byte(priv, AUXRE | 0, AUXMR);
+
+ /* set INT pin to active high, enable command pass through of unknown commands */
+ priv->auxb_bits = AUXRB | HR_CPTE;
+ write_byte(priv, priv->auxb_bits, AUXMR);
+ write_byte(priv, AUXRE, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_board_reset);
+
+void nec7210_board_online(struct nec7210_priv *priv, const gpib_board_t *board)
+{
+ /* set GPIB address */
+ nec7210_primary_address(board, priv, board->pad);
+ nec7210_secondary_address(board, priv, board->sad, board->sad >= 0);
+
+ // enable interrupts
+ priv->reg_bits[IMR1] = HR_ERRIE | HR_DECIE | HR_ENDIE |
+ HR_DETIE | HR_CPTIE | HR_DOIE | HR_DIIE;
+ priv->reg_bits[IMR2] = IMR2_ENABLE_INTR_MASK;
+ write_byte(priv, priv->reg_bits[IMR1], IMR1);
+ write_byte(priv, priv->reg_bits[IMR2], IMR2);
+
+ write_byte(priv, AUX_PON, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_board_online);
+
+#ifdef CONFIG_HAS_IOPORT
+/* wrappers for io */
+uint8_t nec7210_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num)
+{
+ return inb((unsigned long)(priv->iobase) + register_num * priv->offset);
+}
+EXPORT_SYMBOL(nec7210_ioport_read_byte);
+
+void nec7210_ioport_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num)
+{
+ if (register_num == AUXMR)
+ /* locking makes absolutely sure noone accesses the
+ * AUXMR register faster than once per microsecond
+ */
+ nec7210_locking_ioport_write_byte(priv, data, register_num);
+ else
+ outb(data, (unsigned long)(priv->iobase) + register_num * priv->offset);
+}
+EXPORT_SYMBOL(nec7210_ioport_write_byte);
+
+/* locking variants of io wrappers, for chips that page-in registers */
+uint8_t nec7210_locking_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num)
+{
+ u8 retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->register_page_lock, flags);
+ retval = inb((unsigned long)(priv->iobase) + register_num * priv->offset);
+ spin_unlock_irqrestore(&priv->register_page_lock, flags);
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_locking_ioport_read_byte);
+
+void nec7210_locking_ioport_write_byte(struct nec7210_priv *priv, uint8_t data,
+ unsigned int register_num)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->register_page_lock, flags);
+ if (register_num == AUXMR)
+ udelay(1);
+ outb(data, (unsigned long)(priv->iobase) + register_num * priv->offset);
+ spin_unlock_irqrestore(&priv->register_page_lock, flags);
+}
+EXPORT_SYMBOL(nec7210_locking_ioport_write_byte);
+#endif
+
+uint8_t nec7210_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num)
+{
+ return readb(priv->iobase + register_num * priv->offset);
+}
+EXPORT_SYMBOL(nec7210_iomem_read_byte);
+
+void nec7210_iomem_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num)
+{
+ if (register_num == AUXMR)
+ /* locking makes absolutely sure noone accesses the
+ * AUXMR register faster than once per microsecond
+ */
+ nec7210_locking_iomem_write_byte(priv, data, register_num);
+ else
+ writeb(data, priv->iobase + register_num * priv->offset);
+}
+EXPORT_SYMBOL(nec7210_iomem_write_byte);
+
+uint8_t nec7210_locking_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num)
+{
+ u8 retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->register_page_lock, flags);
+ retval = readb(priv->iobase + register_num * priv->offset);
+ spin_unlock_irqrestore(&priv->register_page_lock, flags);
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_locking_iomem_read_byte);
+
+void nec7210_locking_iomem_write_byte(struct nec7210_priv *priv, uint8_t data,
+ unsigned int register_num)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->register_page_lock, flags);
+ if (register_num == AUXMR)
+ udelay(1);
+ writeb(data, priv->iobase + register_num * priv->offset);
+ spin_unlock_irqrestore(&priv->register_page_lock, flags);
+}
+EXPORT_SYMBOL(nec7210_locking_iomem_write_byte);
+
+static int __init nec7210_init_module(void)
+{
+ return 0;
+}
+
+static void __exit nec7210_exit_module(void)
+{
+}
+
+module_init(nec7210_init_module);
+module_exit(nec7210_exit_module);
diff --git a/drivers/staging/gpib/ni_usb/Makefile b/drivers/staging/gpib/ni_usb/Makefile
new file mode 100644
index 000000000000..e22b3b21a62c
--- /dev/null
+++ b/drivers/staging/gpib/ni_usb/Makefile
@@ -0,0 +1,4 @@
+
+obj-m += ni_usb_gpib.o
+
+
diff --git a/drivers/staging/gpib/ni_usb/ni_usb_gpib.c b/drivers/staging/gpib/ni_usb/ni_usb_gpib.c
new file mode 100644
index 000000000000..b7b6fb1be379
--- /dev/null
+++ b/drivers/staging/gpib/ni_usb/ni_usb_gpib.c
@@ -0,0 +1,2640 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * driver for National Instruments usb to gpib adapters
+ * copyright : (C) 2004 by Frank Mori Hess
+ ***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "ni_usb_gpib.h"
+#include "gpibP.h"
+#include "nec7210.h"
+#include "tnt4882_registers.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for National Instruments USB devices");
+
+#define MAX_NUM_NI_USB_INTERFACES 128
+static struct usb_interface *ni_usb_driver_interfaces[MAX_NUM_NI_USB_INTERFACES];
+
+static int ni_usb_parse_status_block(const u8 *buffer, struct ni_usb_status_block *status);
+static int ni_usb_set_interrupt_monitor(gpib_board_t *board, unsigned int monitored_bits);
+static void ni_usb_stop(struct ni_usb_priv *ni_priv);
+
+static DEFINE_MUTEX(ni_usb_hotplug_lock);
+
+//calculates a reasonable timeout in that can be passed to usb functions
+static inline unsigned long ni_usb_timeout_msecs(unsigned int usec)
+{
+ if (usec == 0)
+ return 0;
+ return 2000 + usec / 500;
+};
+
+// returns timeout code byte for use in ni-usb-b instructions
+static unsigned short ni_usb_timeout_code(unsigned int usec)
+{
+ if (usec == 0)
+ return 0xf0;
+ else if (usec <= 10)
+ return 0xf1;
+ else if (usec <= 30)
+ return 0xf2;
+ else if (usec <= 100)
+ return 0xf3;
+ else if (usec <= 300)
+ return 0xf4;
+ else if (usec <= 1000)
+ return 0xf5;
+ else if (usec <= 3000)
+ return 0xf6;
+ else if (usec <= 10000)
+ return 0xf7;
+ else if (usec <= 30000)
+ return 0xf8;
+ else if (usec <= 100000)
+ return 0xf9;
+ else if (usec <= 300000)
+ return 0xfa;
+ else if (usec <= 1000000)
+ return 0xfb;
+ else if (usec <= 3000000)
+ return 0xfc;
+ else if (usec <= 10000000)
+ return 0xfd;
+ else if (usec <= 30000000)
+ return 0xfe;
+ else if (usec <= 100000000)
+ return 0xff;
+ else if (usec <= 300000000)
+ return 0x01;
+ /* NI driver actually uses 0xff for timeout T1000s, which is a bug in their code.
+ * I've verified on a usb-b that a code of 0x2 is correct for a 1000 sec timeout
+ */
+ else if (usec <= 1000000000)
+ return 0x02;
+ pr_err("%s: bug? usec is greater than 1e9\n", __func__);
+ return 0xf0;
+}
+
+static void ni_usb_bulk_complete(struct urb *urb)
+{
+ struct ni_usb_urb_ctx *context = urb->context;
+
+// printk("debug: %s: status=0x%x, error_count=%i, actual_length=%i\n", __func__,
+// urb->status, urb->error_count, urb->actual_length);
+ up(&context->complete);
+}
+
+static void ni_usb_timeout_handler(struct timer_list *t)
+{
+ struct ni_usb_priv *ni_priv = from_timer(ni_priv, t, bulk_timer);
+ struct ni_usb_urb_ctx *context = &ni_priv->context;
+
+ context->timed_out = 1;
+ up(&context->complete);
+};
+
+// I'm using nonblocking loosely here, it only means -EAGAIN can be returned in certain cases
+static int ni_usb_nonblocking_send_bulk_msg(struct ni_usb_priv *ni_priv, void *data,
+ int data_length, int *actual_data_length,
+ int timeout_msecs)
+{
+ struct usb_device *usb_dev;
+ int retval;
+ unsigned int out_pipe;
+ struct ni_usb_urb_ctx *context = &ni_priv->context;
+
+ *actual_data_length = 0;
+ mutex_lock(&ni_priv->bulk_transfer_lock);
+ if (!ni_priv->bus_interface) {
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return -ENODEV;
+ }
+ if (ni_priv->bulk_urb) {
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return -EAGAIN;
+ }
+ ni_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ni_priv->bulk_urb) {
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return -ENOMEM;
+ }
+ usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ out_pipe = usb_sndbulkpipe(usb_dev, ni_priv->bulk_out_endpoint);
+ sema_init(&context->complete, 0);
+ context->timed_out = 0;
+ usb_fill_bulk_urb(ni_priv->bulk_urb, usb_dev, out_pipe, data, data_length,
+ &ni_usb_bulk_complete, context);
+
+ if (timeout_msecs)
+ mod_timer(&ni_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs));
+
+ retval = usb_submit_urb(ni_priv->bulk_urb, GFP_KERNEL);
+ if (retval) {
+ del_timer_sync(&ni_priv->bulk_timer);
+ usb_free_urb(ni_priv->bulk_urb);
+ ni_priv->bulk_urb = NULL;
+ dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return retval;
+ }
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ down(&context->complete); // wait for ni_usb_bulk_complete
+ if (context->timed_out) {
+ usb_kill_urb(ni_priv->bulk_urb);
+ dev_err(&usb_dev->dev, "%s: killed urb due to timeout\n", __func__);
+ retval = -ETIMEDOUT;
+ } else {
+ retval = ni_priv->bulk_urb->status;
+ }
+
+ del_timer_sync(&ni_priv->bulk_timer);
+ *actual_data_length = ni_priv->bulk_urb->actual_length;
+ mutex_lock(&ni_priv->bulk_transfer_lock);
+ usb_free_urb(ni_priv->bulk_urb);
+ ni_priv->bulk_urb = NULL;
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return retval;
+}
+
+static int ni_usb_send_bulk_msg(struct ni_usb_priv *ni_priv, void *data, int data_length,
+ int *actual_data_length, int timeout_msecs)
+{
+ int retval;
+ int timeout_msecs_remaining = timeout_msecs;
+
+ retval = ni_usb_nonblocking_send_bulk_msg(ni_priv, data, data_length, actual_data_length,
+ timeout_msecs_remaining);
+ while (retval == -EAGAIN && (timeout_msecs == 0 || timeout_msecs_remaining > 0)) {
+ usleep_range(1000, 1500);
+ retval = ni_usb_nonblocking_send_bulk_msg(ni_priv, data, data_length,
+ actual_data_length,
+ timeout_msecs_remaining);
+ if (timeout_msecs != 0)
+ --timeout_msecs_remaining;
+ }
+ if (timeout_msecs != 0 && timeout_msecs_remaining <= 0)
+ return -ETIMEDOUT;
+ return retval;
+}
+
+// I'm using nonblocking loosely here, it only means -EAGAIN can be returned in certain cases
+static int ni_usb_nonblocking_receive_bulk_msg(struct ni_usb_priv *ni_priv,
+ void *data, int data_length,
+ int *actual_data_length, int timeout_msecs,
+ int interruptible)
+{
+ struct usb_device *usb_dev;
+ int retval;
+ unsigned int in_pipe;
+ struct ni_usb_urb_ctx *context = &ni_priv->context;
+
+ *actual_data_length = 0;
+ mutex_lock(&ni_priv->bulk_transfer_lock);
+ if (!ni_priv->bus_interface) {
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return -ENODEV;
+ }
+ if (ni_priv->bulk_urb) {
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return -EAGAIN;
+ }
+ ni_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ni_priv->bulk_urb) {
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return -ENOMEM;
+ }
+ usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ in_pipe = usb_rcvbulkpipe(usb_dev, ni_priv->bulk_in_endpoint);
+ sema_init(&context->complete, 0);
+ context->timed_out = 0;
+ usb_fill_bulk_urb(ni_priv->bulk_urb, usb_dev, in_pipe, data, data_length,
+ &ni_usb_bulk_complete, context);
+
+ if (timeout_msecs)
+ mod_timer(&ni_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs));
+
+ //printk("%s: submitting urb\n", __func__);
+ retval = usb_submit_urb(ni_priv->bulk_urb, GFP_KERNEL);
+ if (retval) {
+ del_timer_sync(&ni_priv->bulk_timer);
+ usb_free_urb(ni_priv->bulk_urb);
+ ni_priv->bulk_urb = NULL;
+ dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return retval;
+ }
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ if (interruptible) {
+ if (down_interruptible(&context->complete)) {
+ /* If we got interrupted by a signal while
+ * waiting for the usb gpib to respond, we
+ * should send a stop command so it will
+ * finish up with whatever it was doing and
+ * send its response now.
+ */
+ ni_usb_stop(ni_priv);
+ retval = -ERESTARTSYS;
+ /* now do an uninterruptible wait, it shouldn't take long
+ * for the board to respond now.
+ */
+ down(&context->complete);
+ }
+ } else {
+ down(&context->complete);
+ }
+ if (context->timed_out) {
+ usb_kill_urb(ni_priv->bulk_urb);
+ dev_err(&usb_dev->dev, "%s: killed urb due to timeout\n", __func__);
+ retval = -ETIMEDOUT;
+ } else {
+ if (ni_priv->bulk_urb->status)
+ retval = ni_priv->bulk_urb->status;
+ }
+ del_timer_sync(&ni_priv->bulk_timer);
+ *actual_data_length = ni_priv->bulk_urb->actual_length;
+ mutex_lock(&ni_priv->bulk_transfer_lock);
+ usb_free_urb(ni_priv->bulk_urb);
+ ni_priv->bulk_urb = NULL;
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return retval;
+}
+
+static int ni_usb_receive_bulk_msg(struct ni_usb_priv *ni_priv, void *data,
+ int data_length, int *actual_data_length, int timeout_msecs,
+ int interruptible)
+{
+ int retval;
+ int timeout_msecs_remaining = timeout_msecs;
+
+ retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, data, data_length,
+ actual_data_length, timeout_msecs_remaining,
+ interruptible);
+ while (retval == -EAGAIN && (timeout_msecs == 0 || timeout_msecs_remaining > 0)) {
+ usleep_range(1000, 1500);
+ retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, data, data_length,
+ actual_data_length,
+ timeout_msecs_remaining,
+ interruptible);
+ if (timeout_msecs != 0)
+ --timeout_msecs_remaining;
+ }
+ if (timeout_msecs && timeout_msecs_remaining <= 0)
+ return -ETIMEDOUT;
+ return retval;
+}
+
+static int ni_usb_receive_control_msg(struct ni_usb_priv *ni_priv, __u8 request,
+ __u8 requesttype, __u16 value, __u16 index,
+ void *data, __u16 size, int timeout_msecs)
+{
+ struct usb_device *usb_dev;
+ int retval;
+ unsigned int in_pipe;
+
+ mutex_lock(&ni_priv->control_transfer_lock);
+ if (!ni_priv->bus_interface) {
+ mutex_unlock(&ni_priv->control_transfer_lock);
+ return -ENODEV;
+ }
+ usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ in_pipe = usb_rcvctrlpipe(usb_dev, 0);
+ retval = usb_control_msg(usb_dev, in_pipe, request, requesttype, value, index, data,
+ size, timeout_msecs);
+ mutex_unlock(&ni_priv->control_transfer_lock);
+ return retval;
+}
+
+static void ni_usb_soft_update_status(gpib_board_t *board, unsigned int ni_usb_ibsta,
+ unsigned int clear_mask)
+{
+ static const unsigned int ni_usb_ibsta_mask = SRQI | ATN | CIC | REM | LACS | TACS | LOK;
+
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ unsigned int need_monitoring_bits = ni_usb_ibsta_monitor_mask;
+ unsigned long flags;
+
+ board->status &= ~clear_mask;
+ board->status &= ~ni_usb_ibsta_mask;
+ board->status |= ni_usb_ibsta & ni_usb_ibsta_mask;
+ //FIXME should generate events on DTAS and DCAS
+
+ spin_lock_irqsave(&board->spinlock, flags);
+/* remove set status bits from monitored set why ?***/
+ ni_priv->monitored_ibsta_bits &= ~ni_usb_ibsta;
+ need_monitoring_bits &= ~ni_priv->monitored_ibsta_bits; /* mm - monitored set */
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ dev_dbg(&usb_dev->dev, "%s: need_monitoring_bits=0x%x\n", __func__, need_monitoring_bits);
+
+ if (need_monitoring_bits & ~ni_usb_ibsta)
+ ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask);
+ else if (need_monitoring_bits & ni_usb_ibsta)
+ wake_up_interruptible(&board->wait);
+
+ dev_dbg(&usb_dev->dev, "%s: ni_usb_ibsta=0x%x\n", __func__, ni_usb_ibsta);
+}
+
+static int ni_usb_parse_status_block(const u8 *buffer, struct ni_usb_status_block *status)
+{
+ u16 count;
+
+ status->id = buffer[0];
+ status->ibsta = (buffer[1] << 8) | buffer[2];
+ status->error_code = buffer[3];
+ count = buffer[4] | (buffer[5] << 8);
+ count = ~count;
+ count++;
+ status->count = count;
+ return 8;
+};
+
+static void ni_usb_dump_raw_block(const u8 *raw_data, int length)
+{
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 8, 1, raw_data, length, true);
+}
+
+static int ni_usb_parse_register_read_block(const u8 *raw_data, unsigned int *results,
+ int num_results)
+{
+ int i = 0;
+ int j;
+ int unexpected = 0;
+ static const int results_per_chunk = 3;
+
+ for (j = 0; j < num_results;) {
+ int k;
+
+ if (raw_data[i++] != NIUSB_REGISTER_READ_DATA_START_ID) {
+ pr_err("%s: parse error: wrong start id\n", __func__);
+ unexpected = 1;
+ }
+ for (k = 0; k < results_per_chunk && j < num_results; ++k)
+ results[j++] = raw_data[i++];
+ }
+ while (i % 4)
+ i++;
+ if (raw_data[i++] != NIUSB_REGISTER_READ_DATA_END_ID) {
+ pr_err("%s: parse error: wrong end id\n", __func__);
+ unexpected = 1;
+ }
+ if (raw_data[i++] % results_per_chunk != num_results % results_per_chunk) {
+ pr_err("%s: parse error: wrong count=%i for NIUSB_REGISTER_READ_DATA_END\n",
+ __func__, (int)raw_data[i - 1]);
+ unexpected = 1;
+ }
+ while (i % 4) {
+ if (raw_data[i++] != 0) {
+ pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n",
+ __func__, i - 1, (int)raw_data[i - 1]);
+ unexpected = 1;
+ }
+ }
+ if (unexpected)
+ ni_usb_dump_raw_block(raw_data, i);
+ return i;
+}
+
+static int ni_usb_parse_termination_block(const u8 *buffer)
+{
+ int i = 0;
+
+ if (buffer[i++] != NIUSB_TERM_ID ||
+ buffer[i++] != 0x0 ||
+ buffer[i++] != 0x0 ||
+ buffer[i++] != 0x0) {
+ pr_err("%s: received unexpected termination block\n", __func__);
+ pr_err(" expected: 0x%x 0x%x 0x%x 0x%x\n",
+ NIUSB_TERM_ID, 0x0, 0x0, 0x0);
+ pr_err(" received: 0x%x 0x%x 0x%x 0x%x\n",
+ buffer[i - 4], buffer[i - 3], buffer[i - 2], buffer[i - 1]);
+ }
+ return i;
+};
+
+static int parse_board_ibrd_readback(const u8 *raw_data, struct ni_usb_status_block *status,
+ u8 *parsed_data, int parsed_data_length,
+ int *actual_bytes_read)
+{
+ static const int ibrd_data_block_length = 0xf;
+ static const int ibrd_extended_data_block_length = 0x1e;
+ int data_block_length = 0;
+ int i = 0;
+ int j = 0;
+ int k;
+ unsigned int adr1_bits;
+ int num_data_blocks = 0;
+ struct ni_usb_status_block register_write_status;
+ int unexpected = 0;
+
+ while (raw_data[i] == NIUSB_IBRD_DATA_ID || raw_data[i] == NIUSB_IBRD_EXTENDED_DATA_ID) {
+ if (raw_data[i] == NIUSB_IBRD_DATA_ID) {
+ data_block_length = ibrd_data_block_length;
+ } else if (raw_data[i] == NIUSB_IBRD_EXTENDED_DATA_ID) {
+ data_block_length = ibrd_extended_data_block_length;
+ if (raw_data[++i] != 0) {
+ pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n",
+ __func__, i, (int)raw_data[i]);
+ unexpected = 1;
+ }
+ } else {
+ pr_err("%s: logic bug!\n", __func__);
+ return -EINVAL;
+ }
+ ++i;
+ for (k = 0; k < data_block_length; k++) {
+ if (j < parsed_data_length)
+ parsed_data[j++] = raw_data[i++];
+ else
+ ++i;
+ }
+ ++num_data_blocks;
+ }
+ i += ni_usb_parse_status_block(&raw_data[i], status);
+ if (status->id != NIUSB_IBRD_STATUS_ID) {
+ pr_err("%s: bug: status->id=%i, != ibrd_status_id\n", __func__, status->id);
+ return -EIO;
+ }
+ adr1_bits = raw_data[i++];
+ if (num_data_blocks) {
+ *actual_bytes_read = (num_data_blocks - 1) * data_block_length + raw_data[i++];
+ } else {
+ ++i;
+ *actual_bytes_read = 0;
+ }
+ if (*actual_bytes_read > j)
+ pr_err("%s: bug: discarded data. actual_bytes_read=%i, j=%i\n",
+ __func__, *actual_bytes_read, j);
+ for (k = 0; k < 2; k++)
+ if (raw_data[i++] != 0) {
+ pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n",
+ __func__, i - 1, (int)raw_data[i - 1]);
+ unexpected = 1;
+ }
+ i += ni_usb_parse_status_block(&raw_data[i], &register_write_status);
+ if (register_write_status.id != NIUSB_REG_WRITE_ID) {
+ pr_err("%s: unexpected data: register write status id=0x%x, expected 0x%x\n",
+ __func__, register_write_status.id, NIUSB_REG_WRITE_ID);
+ unexpected = 1;
+ }
+ if (raw_data[i++] != 2) {
+ pr_err("%s: unexpected data: register write count=%i, expected 2\n",
+ __func__, (int)raw_data[i - 1]);
+ unexpected = 1;
+ }
+ for (k = 0; k < 3; k++)
+ if (raw_data[i++] != 0) {
+ pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n",
+ __func__, i - 1, (int)raw_data[i - 1]);
+ unexpected = 1;
+ }
+ i += ni_usb_parse_termination_block(&raw_data[i]);
+ if (unexpected)
+ ni_usb_dump_raw_block(raw_data, i);
+ return i;
+}
+
+static int ni_usb_parse_reg_write_status_block(const u8 *raw_data,
+ struct ni_usb_status_block *status,
+ int *writes_completed)
+{
+ int i = 0;
+
+ i += ni_usb_parse_status_block(raw_data, status);
+ *writes_completed = raw_data[i++];
+ while (i % 4)
+ i++;
+ return i;
+}
+
+static int ni_usb_write_registers(struct ni_usb_priv *ni_priv,
+ const struct ni_usb_register *writes, int num_writes,
+ unsigned int *ibsta)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int retval;
+ u8 *out_data, *in_data;
+ int out_data_length;
+ static const int in_data_length = 0x20;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ int j;
+ struct ni_usb_status_block status;
+ static const int bytes_per_write = 3;
+ int reg_writes_completed;
+
+ out_data_length = num_writes * bytes_per_write + 0x10;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data) {
+ dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ i += ni_usb_bulk_register_write_header(&out_data[i], num_writes);
+ for (j = 0; j < num_writes; j++)
+ i += ni_usb_bulk_register_write(&out_data[i], writes[j]);
+ while (i % 4)
+ out_data[i++] = 0x00;
+ i += ni_usb_bulk_termination(&out_data[i]);
+ if (i > out_data_length)
+ dev_err(&usb_dev->dev, "%s: bug! buffer overrun\n", __func__);
+
+ mutex_lock(&ni_priv->addressed_transfer_lock);
+
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return retval;
+ }
+
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0);
+ if (retval || bytes_read != 16) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ ni_usb_dump_raw_block(in_data, bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ ni_usb_parse_reg_write_status_block(in_data, &status, &reg_writes_completed);
+ //FIXME parse extra 09 status bits and termination
+ kfree(in_data);
+ if (status.id != NIUSB_REG_WRITE_ID) {
+ dev_err(&usb_dev->dev, "%s: parse error, id=0x%x != NIUSB_REG_WRITE_ID\n",
+ __func__, status.id);
+ return -EIO;
+ }
+ if (status.error_code) {
+ dev_err(&usb_dev->dev, "%s: nonzero error code 0x%x\n",
+ __func__, status.error_code);
+ return -EIO;
+ }
+ if (reg_writes_completed != num_writes) {
+ dev_err(&usb_dev->dev, "%s: reg_writes_completed=%i, num_writes=%i\n",
+ __func__, reg_writes_completed, num_writes);
+ return -EIO;
+ }
+ if (ibsta)
+ *ibsta = status.ibsta;
+ return 0;
+}
+
+// interface functions
+static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read)
+{
+ int retval, parse_retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ static const int out_data_length = 0x20;
+ int in_data_length;
+ int usb_bytes_written = 0, usb_bytes_read = 0;
+ int i = 0;
+ int complement_count;
+ int actual_length;
+ struct ni_usb_status_block status;
+ static const int max_read_length = 0xffff;
+ struct ni_usb_register reg;
+
+ *bytes_read = 0;
+ if (length > max_read_length) {
+ length = max_read_length;
+ dev_err(&usb_dev->dev, "%s: read length too long\n", __func__);
+ }
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+ out_data[i++] = 0x0a;
+ out_data[i++] = ni_priv->eos_mode >> 8;
+ out_data[i++] = ni_priv->eos_char;
+ out_data[i++] = ni_usb_timeout_code(board->usec_timeout);
+ complement_count = length - 1;
+ complement_count = ~complement_count;
+ out_data[i++] = complement_count & 0xff;
+ out_data[i++] = (complement_count >> 8) & 0xff;
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_register_write_header(&out_data[i], 2);
+ reg.device = NIUSB_SUBDEV_TNT4882;
+ reg.address = nec7210_to_tnt4882_offset(AUXMR);
+ reg.value = AUX_HLDI;
+ i += ni_usb_bulk_register_write(&out_data[i], reg);
+ reg.value = AUX_CLEAR_END;
+ i += ni_usb_bulk_register_write(&out_data[i], reg);
+ while (i % 4) // pad with zeros to 4-byte boundary
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+
+ mutex_lock(&ni_priv->addressed_transfer_lock);
+
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &usb_bytes_written, 1000);
+ kfree(out_data);
+ if (retval || usb_bytes_written != i) {
+ if (retval == 0)
+ retval = -EIO;
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, usb_bytes_written=%i, i=%i\n",
+ __func__, retval, usb_bytes_written, i);
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ return retval;
+ }
+
+ in_data_length = (length / 30 + 1) * 0x20 + 0x20;
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ return -ENOMEM;
+ }
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &usb_bytes_read,
+ ni_usb_timeout_msecs(board->usec_timeout), 1);
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ if (retval == -ERESTARTSYS) {
+ } else if (retval) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, usb_bytes_read=%i\n",
+ __func__, retval, usb_bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+ parse_retval = parse_board_ibrd_readback(in_data, &status, buffer, length, &actual_length);
+ if (parse_retval != usb_bytes_read) {
+ if (parse_retval >= 0)
+ parse_retval = -EIO;
+ dev_err(&usb_dev->dev, "%s: retval=%i usb_bytes_read=%i\n",
+ __func__, parse_retval, usb_bytes_read);
+ kfree(in_data);
+ return parse_retval;
+ }
+ if (actual_length != length - status.count) {
+ dev_err(&usb_dev->dev, "%s: actual_length=%i expected=%li\n",
+ __func__, actual_length, (long)(length - status.count));
+ ni_usb_dump_raw_block(in_data, usb_bytes_read);
+ }
+ kfree(in_data);
+ switch (status.error_code) {
+ case NIUSB_NO_ERROR:
+ retval = 0;
+ break;
+ case NIUSB_ABORTED_ERROR:
+ /* this is expected if ni_usb_receive_bulk_msg got
+ * interrupted by a signal and returned -ERESTARTSYS
+ */
+ break;
+ case NIUSB_ATN_STATE_ERROR:
+ retval = -EIO;
+ dev_err(&usb_dev->dev, "%s: read when ATN set\n", __func__);
+ break;
+ case NIUSB_ADDRESSING_ERROR:
+ retval = -EIO;
+ break;
+ case NIUSB_TIMEOUT_ERROR:
+ retval = -ETIMEDOUT;
+ break;
+ case NIUSB_EOSMODE_ERROR:
+ dev_err(&usb_dev->dev, "%s: driver bug, we should have been able to avoid NIUSB_EOSMODE_ERROR.\n",
+ __func__);
+ retval = -EINVAL;
+ break;
+ default:
+ dev_err(&usb_dev->dev, "%s: unknown error code=%i\n", __func__, status.error_code);
+ retval = -EIO;
+ break;
+ }
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+ if (status.ibsta & END)
+ *end = 1;
+ else
+ *end = 0;
+ *bytes_read = actual_length;
+ return retval;
+}
+
+static int ni_usb_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ int out_data_length;
+ static const int in_data_length = 0x10;
+ int usb_bytes_written = 0, usb_bytes_read = 0;
+ int i = 0, j;
+ int complement_count;
+ struct ni_usb_status_block status;
+ static const int max_write_length = 0xffff;
+
+ *bytes_written = 0;
+ if (length > max_write_length) {
+ length = max_write_length;
+ send_eoi = 0;
+ dev_err(&usb_dev->dev, "%s: write length too long\n", __func__);
+ }
+ out_data_length = length + 0x10;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+ out_data[i++] = 0x0d;
+ complement_count = length - 1;
+ complement_count = ~complement_count;
+ out_data[i++] = complement_count & 0xff;
+ out_data[i++] = (complement_count >> 8) & 0xff;
+ out_data[i++] = ni_usb_timeout_code(board->usec_timeout);
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ if (send_eoi)
+ out_data[i++] = 0x8;
+ else
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ for (j = 0; j < length; j++)
+ out_data[i++] = buffer[j];
+ while (i % 4) // pad with zeros to 4-byte boundary
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+
+ mutex_lock(&ni_priv->addressed_transfer_lock);
+
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &usb_bytes_written,
+ ni_usb_timeout_msecs(board->usec_timeout));
+ kfree(out_data);
+ if (retval || usb_bytes_written != i) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, usb_bytes_written=%i, i=%i\n",
+ __func__, retval, usb_bytes_written, i);
+ return retval;
+ }
+
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data)
+ return -ENOMEM;
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &usb_bytes_read,
+ ni_usb_timeout_msecs(board->usec_timeout), 1);
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ if ((retval && retval != -ERESTARTSYS) || usb_bytes_read != 12) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, usb_bytes_read=%i\n",
+ __func__, retval, usb_bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+ ni_usb_parse_status_block(in_data, &status);
+ kfree(in_data);
+ switch (status.error_code) {
+ case NIUSB_NO_ERROR:
+ retval = 0;
+ break;
+ case NIUSB_ABORTED_ERROR:
+ /* this is expected if ni_usb_receive_bulk_msg got
+ * interrupted by a signal and returned -ERESTARTSYS
+ */
+ break;
+ case NIUSB_ADDRESSING_ERROR:
+ dev_err(&usb_dev->dev, "%s: Addressing error retval %d error code=%i\n",
+ __func__, retval, status.error_code);
+ retval = -ENXIO;
+ break;
+ case NIUSB_NO_LISTENER_ERROR:
+ retval = -ECOMM;
+ break;
+ case NIUSB_TIMEOUT_ERROR:
+ retval = -ETIMEDOUT;
+ break;
+ default:
+ dev_err(&usb_dev->dev, "%s: unknown error code=%i\n",
+ __func__, status.error_code);
+ retval = -EPIPE;
+ break;
+ }
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+ *bytes_written = length - status.count;
+ return retval;
+}
+
+static int ni_usb_command_chunk(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *command_bytes_written)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ int out_data_length;
+ static const int in_data_length = 0x10;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0, j;
+ unsigned int complement_count;
+ struct ni_usb_status_block status;
+ // usb-b gives error 4 if you try to send more than 16 command bytes at once
+ static const int max_command_length = 0x10;
+
+ *command_bytes_written = 0;
+ if (length > max_command_length)
+ length = max_command_length;
+ out_data_length = length + 0x10;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+ out_data[i++] = 0x0c;
+ complement_count = length - 1;
+ complement_count = ~complement_count;
+ out_data[i++] = complement_count;
+ out_data[i++] = 0x0;
+ out_data[i++] = ni_usb_timeout_code(board->usec_timeout);
+ for (j = 0; j < length; j++)
+ out_data[i++] = buffer[j];
+ while (i % 4) // pad with zeros to 4-byte boundary
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+
+ mutex_lock(&ni_priv->addressed_transfer_lock);
+
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written,
+ ni_usb_timeout_msecs(board->usec_timeout));
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return retval;
+ }
+
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ return -ENOMEM;
+ }
+
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read,
+ ni_usb_timeout_msecs(board->usec_timeout), 1);
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ if ((retval && retval != -ERESTARTSYS) || bytes_read != 12) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+ ni_usb_parse_status_block(in_data, &status);
+ kfree(in_data);
+ *command_bytes_written = length - status.count;
+ switch (status.error_code) {
+ case NIUSB_NO_ERROR:
+ break;
+ case NIUSB_ABORTED_ERROR:
+ /* this is expected if ni_usb_receive_bulk_msg got
+ * interrupted by a signal and returned -ERESTARTSYS
+ */
+ break;
+ case NIUSB_NO_BUS_ERROR:
+ return -ENOTCONN;
+ case NIUSB_EOSMODE_ERROR:
+ dev_err(&usb_dev->dev, "%s: got eosmode error. Driver bug?\n", __func__);
+ return -EIO;
+ case NIUSB_TIMEOUT_ERROR:
+ return -ETIMEDOUT;
+ default:
+ dev_err(&usb_dev->dev, "%s: unknown error code=%i\n", __func__, status.error_code);
+ return -EIO;
+ }
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+ return 0;
+}
+
+static int ni_usb_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written)
+{
+ size_t count;
+ int retval;
+
+ *bytes_written = 0;
+ while (*bytes_written < length) {
+ retval = ni_usb_command_chunk(board, buffer + *bytes_written,
+ length - *bytes_written, &count);
+ *bytes_written += count;
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+
+static int ni_usb_take_control(gpib_board_t *board, int synchronous)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ static const int out_data_length = 0x10;
+ static const int in_data_length = 0x10;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ struct ni_usb_status_block status;
+
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+ out_data[i++] = NIUSB_IBCAC_ID;
+ if (synchronous)
+ out_data[i++] = 0x1;
+ else
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+
+ mutex_lock(&ni_priv->addressed_transfer_lock);
+
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return retval;
+ }
+
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 1);
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ if ((retval && retval != -ERESTARTSYS) || bytes_read != 12) {
+ if (retval == 0)
+ retval = -EIO;
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+ ni_usb_parse_status_block(in_data, &status);
+ kfree(in_data);
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+ return retval;
+}
+
+static int ni_usb_go_to_standby(gpib_board_t *board)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ static const int out_data_length = 0x10;
+ static const int in_data_length = 0x20;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ struct ni_usb_status_block status;
+
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+
+ out_data[i++] = NIUSB_IBGTS_ID;
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+
+ mutex_lock(&ni_priv->addressed_transfer_lock);
+
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return retval;
+ }
+
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0);
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ if (retval || bytes_read != 12) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+ ni_usb_parse_status_block(in_data, &status);
+ kfree(in_data);
+ if (status.id != NIUSB_IBGTS_ID)
+ dev_err(&usb_dev->dev, "%s: bug: status.id 0x%x != INUSB_IBGTS_ID\n",
+ __func__, status.id);
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+ return 0;
+}
+
+static void ni_usb_request_system_control(gpib_board_t *board, int request_control)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[4];
+ unsigned int ibsta;
+
+ if (request_control) {
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = CMDR;
+ writes[i].value = SETSC;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CIFC;
+ i++;
+ } else {
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CREN;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CIFC;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_DSC;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = CMDR;
+ writes[i].value = CLRSC;
+ i++;
+ }
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return; // retval;
+ }
+ if (!request_control)
+ ni_priv->ren_state = 0;
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return; // 0;
+}
+
+//FIXME maybe the interface should have a "pulse interface clear" function that can return an error?
+static void ni_usb_interface_clear(gpib_board_t *board, int assert)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ static const int out_data_length = 0x10;
+ static const int in_data_length = 0x10;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ struct ni_usb_status_block status;
+
+ // FIXME: we are going to pulse when assert is true, and ignore otherwise
+ if (assert == 0)
+ return;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data) {
+ dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__);
+ return;
+ }
+ out_data[i++] = NIUSB_IBSIC_ID;
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return;
+ }
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data)
+ return;
+
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0);
+ if (retval || bytes_read != 12) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ kfree(in_data);
+ return;
+ }
+ ni_usb_parse_status_block(in_data, &status);
+ kfree(in_data);
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+}
+
+static void ni_usb_remote_enable(gpib_board_t *board, int enable)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ struct ni_usb_register reg;
+ unsigned int ibsta;
+
+ reg.device = NIUSB_SUBDEV_TNT4882;
+ reg.address = nec7210_to_tnt4882_offset(AUXMR);
+ if (enable)
+ reg.value = AUX_SREN;
+ else
+ reg.value = AUX_CREN;
+ retval = ni_usb_write_registers(ni_priv, &reg, 1, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return; //retval;
+ }
+ ni_priv->ren_state = enable;
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return;// 0;
+}
+
+static int ni_usb_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct ni_usb_priv *ni_priv = board->private_data;
+
+ ni_priv->eos_char = eos_byte;
+ ni_priv->eos_mode |= REOS;
+ if (compare_8_bits)
+ ni_priv->eos_mode |= BIN;
+ else
+ ni_priv->eos_mode &= ~BIN;
+ return 0;
+}
+
+static void ni_usb_disable_eos(gpib_board_t *board)
+{
+ struct ni_usb_priv *ni_priv = board->private_data;
+ /* adapter gets unhappy if you don't zero all the bits
+ * for the eos mode and eos char (returns error 4 on reads).
+ */
+ ni_priv->eos_mode = 0;
+ ni_priv->eos_char = 0;
+}
+
+static unsigned int ni_usb_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ static const int buffer_length = 8;
+ u8 *buffer;
+ struct ni_usb_status_block status;
+
+ //printk("%s: receive control pipe is %i\n", __func__, pipe);
+ buffer = kmalloc(buffer_length, GFP_KERNEL);
+ if (!buffer)
+ return board->status;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_WAIT_REQUEST, USB_DIR_IN |
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x200, 0x0, buffer, buffer_length, 1000);
+ if (retval != buffer_length) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg returned %i\n", __func__, retval);
+ kfree(buffer);
+ return board->status;
+ }
+ ni_usb_parse_status_block(buffer, &status);
+ kfree(buffer);
+ ni_usb_soft_update_status(board, status.ibsta, clear_mask);
+ return board->status;
+}
+
+// tells ni-usb to immediately stop an ongoing i/o operation
+static void ni_usb_stop(struct ni_usb_priv *ni_priv)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int retval;
+ static const int buffer_length = 8;
+ u8 *buffer;
+ struct ni_usb_status_block status;
+
+ //printk("%s: receive control pipe is %i\n", __func__, pipe);
+ buffer = kmalloc(buffer_length, GFP_KERNEL);
+ if (!buffer)
+ return;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_STOP_REQUEST, USB_DIR_IN |
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x0, 0x0, buffer, buffer_length, 1000);
+ if (retval != buffer_length) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg returned %i\n", __func__, retval);
+ kfree(buffer);
+ return;
+ }
+ ni_usb_parse_status_block(buffer, &status);
+ kfree(buffer);
+}
+
+static int ni_usb_primary_address(gpib_board_t *board, unsigned int address)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[2];
+ unsigned int ibsta;
+
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(ADR);
+ writes[i].value = address;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_UNKNOWN2;
+ writes[i].address = 0x0;
+ writes[i].value = address;
+ i++;
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return 0;
+}
+
+static int ni_usb_write_sad(struct ni_usb_register *writes, int address, int enable)
+{
+ unsigned int adr_bits, admr_bits;
+ int i = 0;
+
+ adr_bits = HR_ARS;
+ admr_bits = HR_TRM0 | HR_TRM1;
+ if (enable) {
+ adr_bits |= address;
+ admr_bits |= HR_ADM1;
+ } else {
+ adr_bits |= HR_DT | HR_DL;
+ admr_bits |= HR_ADM0;
+ }
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(ADR);
+ writes[i].value = adr_bits;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(ADMR);
+ writes[i].value = admr_bits;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_UNKNOWN2;
+ writes[i].address = 0x1;
+ writes[i].value = enable ? MSA(address) : 0x0;
+ i++;
+ return i;
+}
+
+static int ni_usb_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[3];
+ unsigned int ibsta;
+
+ i += ni_usb_write_sad(writes, address, enable);
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return 0;
+}
+
+static int ni_usb_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ static const int out_data_length = 0x10;
+ static const int in_data_length = 0x20;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ int j = 0;
+ struct ni_usb_status_block status;
+
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+
+ out_data[i++] = NIUSB_IBRPP_ID;
+ out_data[i++] = 0xf0; //FIXME: this should be the parallel poll timeout code
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+ /*FIXME: 1000 should use parallel poll timeout (not supported yet)*/
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000);
+
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return retval;
+ }
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data)
+ return -ENOMEM;
+
+ /*FIXME: should use parallel poll timeout (not supported yet)*/
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length,
+ &bytes_read, 1000, 1);
+
+ if (retval && retval != -ERESTARTSYS) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+ j += ni_usb_parse_status_block(in_data, &status);
+ *result = in_data[j++];
+ kfree(in_data);
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+ return retval;
+}
+
+static void ni_usb_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[1];
+ unsigned int ibsta;
+
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = PPR | config;
+ i++;
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return;// retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return;// 0;
+}
+
+static void ni_usb_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[1];
+ unsigned int ibsta;
+
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ if (ist)
+ writes[i].value = AUX_SPPF;
+ else
+ writes[i].value = AUX_CPPF;
+ i++;
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return;// retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return;// 0;
+}
+
+static void ni_usb_serial_poll_response(gpib_board_t *board, u8 status)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[1];
+ unsigned int ibsta;
+
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(SPMR);
+ writes[i].value = status;
+ i++;
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return;// retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return;// 0;
+}
+
+static uint8_t ni_usb_serial_poll_status(gpib_board_t *board)
+{
+ return 0;
+}
+
+static void ni_usb_return_to_local(gpib_board_t *board)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[1];
+ unsigned int ibsta;
+
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_RTL;
+ i++;
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return;// retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return;// 0;
+}
+
+static int ni_usb_line_status(const gpib_board_t *board)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ static const int out_data_length = 0x20;
+ static const int in_data_length = 0x20;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ unsigned int bsr_bits;
+ int line_status = ValidALL;
+ // NI windows driver reads 0xd(HSSEL), 0xc (ARD0), 0x1f (BSR)
+
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+
+ /* line status gets called during ibwait */
+ retval = mutex_trylock(&ni_priv->addressed_transfer_lock);
+
+ if (retval == 0) {
+ kfree(out_data);
+ return -EBUSY;
+ }
+ i += ni_usb_bulk_register_read_header(&out_data[i], 1);
+ i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_TNT4882, BSR);
+ while (i % 4)
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+ retval = ni_usb_nonblocking_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ if (retval != -EAGAIN)
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return retval;
+ }
+
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, in_data, in_data_length,
+ &bytes_read, 1000, 0);
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ if (retval) {
+ if (retval != -EAGAIN)
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+
+ ni_usb_parse_register_read_block(in_data, &bsr_bits, 1);
+ kfree(in_data);
+ if (bsr_bits & BCSR_REN_BIT)
+ line_status |= BusREN;
+ if (bsr_bits & BCSR_IFC_BIT)
+ line_status |= BusIFC;
+ if (bsr_bits & BCSR_SRQ_BIT)
+ line_status |= BusSRQ;
+ if (bsr_bits & BCSR_EOI_BIT)
+ line_status |= BusEOI;
+ if (bsr_bits & BCSR_NRFD_BIT)
+ line_status |= BusNRFD;
+ if (bsr_bits & BCSR_NDAC_BIT)
+ line_status |= BusNDAC;
+ if (bsr_bits & BCSR_DAV_BIT)
+ line_status |= BusDAV;
+ if (bsr_bits & BCSR_ATN_BIT)
+ line_status |= BusATN;
+ return line_status;
+}
+
+static int ni_usb_setup_t1_delay(struct ni_usb_register *reg, unsigned int nano_sec,
+ unsigned int *actual_ns)
+{
+ int i = 0;
+
+ *actual_ns = 2000;
+
+ reg[i].device = NIUSB_SUBDEV_TNT4882;
+ reg[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ if (nano_sec <= 1100) {
+ reg[i].value = AUXRI | USTD | SISB;
+ *actual_ns = 1100;
+ } else {
+ reg[i].value = AUXRI | SISB;
+ }
+ i++;
+ reg[i].device = NIUSB_SUBDEV_TNT4882;
+ reg[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ if (nano_sec <= 500) {
+ reg[i].value = AUXRB | HR_TRI;
+ *actual_ns = 500;
+ } else {
+ reg[i].value = AUXRB;
+ }
+ i++;
+ reg[i].device = NIUSB_SUBDEV_TNT4882;
+ reg[i].address = KEYREG;
+ if (nano_sec <= 350) {
+ reg[i].value = MSTD;
+ *actual_ns = 350;
+ } else {
+ reg[i].value = 0x0;
+ }
+ i++;
+ return i;
+}
+
+static unsigned int ni_usb_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ struct ni_usb_register writes[3];
+ unsigned int ibsta;
+ unsigned int actual_ns;
+ int i;
+
+ i = ni_usb_setup_t1_delay(writes, nano_sec, &actual_ns);
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return -1; //FIXME should change return type to int for error reporting
+ }
+ board->t1_nano_sec = actual_ns;
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return actual_ns;
+}
+
+static int ni_usb_allocate_private(gpib_board_t *board)
+{
+ struct ni_usb_priv *ni_priv;
+
+ board->private_data = kmalloc(sizeof(struct ni_usb_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+ ni_priv = board->private_data;
+ memset(ni_priv, 0, sizeof(struct ni_usb_priv));
+ mutex_init(&ni_priv->bulk_transfer_lock);
+ mutex_init(&ni_priv->control_transfer_lock);
+ mutex_init(&ni_priv->interrupt_transfer_lock);
+ mutex_init(&ni_priv->addressed_transfer_lock);
+ return 0;
+}
+
+static void ni_usb_free_private(struct ni_usb_priv *ni_priv)
+{
+ usb_free_urb(ni_priv->interrupt_urb);
+ kfree(ni_priv);
+}
+
+#define NUM_INIT_WRITES 26
+static int ni_usb_setup_init(gpib_board_t *board, struct ni_usb_register *writes)
+{
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ unsigned int mask, actual_ns;
+ int i = 0;
+
+ writes[i].device = NIUSB_SUBDEV_UNKNOWN3;
+ writes[i].address = 0x10;
+ writes[i].value = 0x0;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = CMDR;
+ writes[i].value = SOFT_RESET;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ mask = AUXRA | HR_HLDA;
+ if (ni_priv->eos_mode & BIN)
+ mask |= HR_BIN;
+ writes[i].value = mask;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = AUXCR;
+ writes[i].value = mask;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = HSSEL;
+ writes[i].value = TNT_ONE_CHIP_BIT;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CR;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = IMR0;
+ writes[i].value = TNT_IMR0_ALWAYS_BITS;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(IMR1);
+ writes[i].value = 0x0;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(IMR2);
+ writes[i].value = 0x0;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = IMR3;
+ writes[i].value = 0x0;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_HLDI;
+ i++;
+
+ i += ni_usb_setup_t1_delay(&writes[i], board->t1_nano_sec, &actual_ns);
+
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUXRG | NTNL_BIT;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = CMDR;
+ if (board->master)
+ mask = SETSC; // set system controller
+ else
+ mask = CLRSC; // clear system controller
+ writes[i].value = mask;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CIFC;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(ADR);
+ writes[i].value = board->pad;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_UNKNOWN2;
+ writes[i].address = 0x0;
+ writes[i].value = board->pad;
+ i++;
+
+ i += ni_usb_write_sad(&writes[i], board->sad, board->sad >= 0);
+
+ writes[i].device = NIUSB_SUBDEV_UNKNOWN2;
+ writes[i].address = 0x2; // could this be a timeout ?
+ writes[i].value = 0xfd;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = 0xf; // undocumented address
+ writes[i].value = 0x11;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_PON;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CPPF;
+ i++;
+ if (i > NUM_INIT_WRITES) {
+ dev_err(&usb_dev->dev, "%s: bug!, buffer overrun, i=%i\n", __func__, i);
+ return 0;
+ }
+ return i;
+}
+
+static int ni_usb_init(gpib_board_t *board)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ struct ni_usb_register *writes;
+ unsigned int ibsta;
+ int writes_len;
+
+ writes = kmalloc_array(NUM_INIT_WRITES, sizeof(*writes), GFP_KERNEL);
+ if (!writes)
+ return -ENOMEM;
+
+ writes_len = ni_usb_setup_init(board, writes);
+ if (writes_len)
+ retval = ni_usb_write_registers(ni_priv, writes, writes_len, &ibsta);
+ else
+ return -EFAULT;
+ kfree(writes);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return 0;
+}
+
+static void ni_usb_interrupt_complete(struct urb *urb)
+{
+ gpib_board_t *board = urb->context;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int retval;
+ struct ni_usb_status_block status;
+ unsigned long flags;
+
+// printk("debug: %s: status=0x%x, error_count=%i, actual_length=%i\n", __func__,
+// urb->status, urb->error_count, urb->actual_length);
+
+ switch (urb->status) {
+ /* success */
+ case 0:
+ break;
+ /* unlinked, don't resubmit */
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ default: /* other error, resubmit */
+ retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__);
+ return;
+ }
+
+ ni_usb_parse_status_block(urb->transfer_buffer, &status);
+// printk("debug: ibsta=0x%x\n", status.ibsta);
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ ni_priv->monitored_ibsta_bits &= ~status.ibsta;
+// printk("debug: monitored_ibsta_bits=0x%x\n", ni_priv->monitored_ibsta_bits);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ wake_up_interruptible(&board->wait);
+
+ retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__);
+}
+
+static int ni_usb_set_interrupt_monitor(gpib_board_t *board, unsigned int monitored_bits)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ static const int buffer_length = 8;
+ u8 *buffer;
+ struct ni_usb_status_block status;
+ unsigned long flags;
+ //printk("%s: receive control pipe is %i\n", __func__, pipe);
+ buffer = kmalloc(buffer_length, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ ni_priv->monitored_ibsta_bits = ni_usb_ibsta_monitor_mask & monitored_bits;
+// dev_err(&usb_dev->dev, "debug: %s: monitored_ibsta_bits=0x%x\n",
+// __func__, ni_priv->monitored_ibsta_bits);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_WAIT_REQUEST, USB_DIR_IN |
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x300, ni_usb_ibsta_monitor_mask & monitored_bits,
+ buffer, buffer_length, 1000);
+ if (retval != buffer_length) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg returned %i\n", __func__, retval);
+ kfree(buffer);
+ return -1;
+ }
+ ni_usb_parse_status_block(buffer, &status);
+ kfree(buffer);
+ return 0;
+}
+
+static int ni_usb_setup_urbs(gpib_board_t *board)
+{
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev;
+ int int_pipe;
+ int retval;
+
+ if (ni_priv->interrupt_in_endpoint < 0)
+ return 0;
+
+ mutex_lock(&ni_priv->interrupt_transfer_lock);
+ if (!ni_priv->bus_interface) {
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ return -ENODEV;
+ }
+ ni_priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ni_priv->interrupt_urb) {
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ return -ENOMEM;
+ }
+ usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int_pipe = usb_rcvintpipe(usb_dev, ni_priv->interrupt_in_endpoint);
+ usb_fill_int_urb(ni_priv->interrupt_urb, usb_dev, int_pipe, ni_priv->interrupt_buffer,
+ sizeof(ni_priv->interrupt_buffer), &ni_usb_interrupt_complete, board, 1);
+ retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_KERNEL);
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: failed to submit first interrupt urb, retval=%i\n",
+ __func__, retval);
+ return retval;
+ }
+ return 0;
+}
+
+static void ni_usb_cleanup_urbs(struct ni_usb_priv *ni_priv)
+{
+ if (ni_priv && ni_priv->bus_interface) {
+ if (ni_priv->interrupt_urb)
+ usb_kill_urb(ni_priv->interrupt_urb);
+ if (ni_priv->bulk_urb)
+ usb_kill_urb(ni_priv->bulk_urb);
+ }
+}
+
+static int ni_usb_b_read_serial_number(struct ni_usb_priv *ni_priv)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int retval;
+ u8 *out_data;
+ u8 *in_data;
+ static const int out_data_length = 0x20;
+ static const int in_data_length = 0x20;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ static const int num_reads = 4;
+ unsigned int results[4];
+ int j;
+ unsigned int serial_number;
+
+// printk("%s: %s\n", __func__);
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data)
+ return -ENOMEM;
+
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data) {
+ kfree(in_data);
+ return -ENOMEM;
+ }
+ i += ni_usb_bulk_register_read_header(&out_data[i], num_reads);
+ i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_1_REG);
+ i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_2_REG);
+ i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_3_REG);
+ i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_4_REG);
+ while (i % 4)
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, out_data_length, &bytes_written, 1000);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%li\n",
+ __func__,
+ retval, bytes_written, (long)out_data_length);
+ goto serial_out;
+ }
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ ni_usb_dump_raw_block(in_data, bytes_read);
+ goto serial_out;
+ }
+ if (ARRAY_SIZE(results) < num_reads) {
+ dev_err(&usb_dev->dev, "Setup bug\n");
+ retval = -EINVAL;
+ goto serial_out;
+ }
+ ni_usb_parse_register_read_block(in_data, results, num_reads);
+ serial_number = 0;
+ for (j = 0; j < num_reads; ++j)
+ serial_number |= (results[j] & 0xff) << (8 * j);
+ dev_info(&usb_dev->dev, "%s: board serial number is 0x%x\n", __func__, serial_number);
+ retval = 0;
+serial_out:
+ kfree(in_data);
+ kfree(out_data);
+ return retval;
+}
+
+static int ni_usb_hs_wait_for_ready(struct ni_usb_priv *ni_priv)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ static const int buffer_size = 0x10;
+ static const int timeout = 50;
+ static const int msec_sleep_duration = 100;
+ int i; int retval;
+ int j;
+ int unexpected = 0;
+ unsigned int serial_number;
+ u8 *buffer;
+
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_SERIAL_NUMBER_REQUEST,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x0, 0x0, buffer, buffer_size, 1000);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n",
+ __func__, NI_USB_SERIAL_NUMBER_REQUEST, retval);
+ goto ready_out;
+ }
+ j = 0;
+ if (buffer[j] != NI_USB_SERIAL_NUMBER_REQUEST) {
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x%x\n",
+ __func__, j, (int)buffer[j], NI_USB_SERIAL_NUMBER_REQUEST);
+ unexpected = 1;
+ }
+ if (unexpected)
+ ni_usb_dump_raw_block(buffer, retval);
+ // NI-USB-HS+ pads the serial with 0x0 to make 16 bytes
+ if (retval != 5 && retval != 16) {
+ dev_err(&usb_dev->dev, "%s: received unexpected number of bytes = %i, expected 5 or 16\n",
+ __func__, retval);
+ ni_usb_dump_raw_block(buffer, retval);
+ }
+ serial_number = 0;
+ serial_number |= buffer[++j];
+ serial_number |= (buffer[++j] << 8);
+ serial_number |= (buffer[++j] << 16);
+ serial_number |= (buffer[++j] << 24);
+ dev_info(&usb_dev->dev, "%s: board serial number is 0x%x\n", __func__, serial_number);
+ for (i = 0; i < timeout; ++i) {
+ int ready = 0;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_POLL_READY_REQUEST,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x0, 0x0, buffer, buffer_size, 100);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n",
+ __func__, NI_USB_POLL_READY_REQUEST, retval);
+ goto ready_out;
+ }
+ j = 0;
+ unexpected = 0;
+ if (buffer[j] != NI_USB_POLL_READY_REQUEST) { // [0]
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x%x\n",
+ __func__, j, (int)buffer[j], NI_USB_POLL_READY_REQUEST);
+ unexpected = 1;
+ }
+ ++j;
+ if (buffer[j] != 0x1 && buffer[j] != 0x0) { // [1] HS+ sends 0x0
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x1 or 0x0\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ if (buffer[++j] != 0x0) { // [2]
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x%x\n",
+ __func__, j, (int)buffer[j], 0x0);
+ unexpected = 1;
+ }
+ ++j;
+ // MC usb-488 (and sometimes NI-USB-HS?) sends 0x8 here; MC usb-488A sends 0x7 here
+ // NI-USB-HS+ sends 0x0
+ if (buffer[j] != 0x1 && buffer[j] != 0x8 && buffer[j] != 0x7 && buffer[j] != 0x0) {
+ // [3]
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0, 0x1, 0x7 or 0x8\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ ++j;
+ // NI-USB-HS+ sends 0 here
+ if (buffer[j] != 0x30 && buffer[j] != 0x0) { // [4]
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0 or 0x30\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ ++j;
+ // MC usb-488 (and sometimes NI-USB-HS?) and NI-USB-HS+ sends 0x0 here
+ if (buffer[j] != 0x1 && buffer[j] != 0x0) { // [5]
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x1 or 0x0\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ if (buffer[++j] != 0x0) { // [6]
+ ready = 1;
+ // NI-USB-HS+ sends 0xf here
+ if (buffer[j] != 0x2 && buffer[j] != 0xe && buffer[j] != 0xf &&
+ buffer[j] != 0x16) {
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x2, 0xe, 0xf or 0x16\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ }
+ if (buffer[++j] != 0x0) { // [7]
+ ready = 1;
+ // MC usb-488 sends 0x5 here; MC usb-488A sends 0x6 here
+ if (buffer[j] != 0x3 && buffer[j] != 0x5 && buffer[j] != 0x6 &&
+ buffer[j] != 0x8) {
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x3 or 0x5, 0x6 or 0x08\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ }
+ ++j;
+ if (buffer[j] != 0x0 && buffer[j] != 0x2) { // [8] MC usb-488 sends 0x2 here
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0 or 0x2\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ ++j;
+ // MC usb-488A and NI-USB-HS sends 0x3 here; NI-USB-HS+ sends 0x30 here
+ if (buffer[j] != 0x0 && buffer[j] != 0x3 && buffer[j] != 0x30) { // [9]
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0, 0x3 or 0x30\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ if (buffer[++j] != 0x0) {
+ ready = 1;
+ if (buffer[j] != 0x96 && buffer[j] != 0x7 && buffer[j] != 0x6e) {
+// [10] MC usb-488 sends 0x7 here
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x96, 0x07 or 0x6e\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ }
+ if (unexpected)
+ ni_usb_dump_raw_block(buffer, retval);
+ if (ready)
+ break;
+ retval = msleep_interruptible(msec_sleep_duration);
+ if (retval) {
+ dev_err(&usb_dev->dev, "ni_usb_gpib: msleep interrupted\n");
+ retval = -ERESTARTSYS;
+ goto ready_out;
+ }
+ }
+ retval = 0;
+
+ready_out:
+ kfree(buffer);
+ dev_dbg(&usb_dev->dev, "%s: exit retval=%d\n", __func__, retval);
+ return retval;
+}
+
+/* This does some extra init for HS+ models, as observed on Windows. One of the
+ * control requests causes the LED to stop blinking.
+ * I'm not sure what the other 2 requests do. None of these requests are actually required
+ * for the adapter to work, maybe they do some init for the analyzer interface
+ * (which we don't use).
+ */
+static int ni_usb_hs_plus_extra_init(struct ni_usb_priv *ni_priv)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int retval;
+ u8 *buffer;
+ static const int buffer_size = 16;
+ int transfer_size;
+
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+ do {
+ transfer_size = 16;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_HS_PLUS_0x48_REQUEST,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x0, 0x0, buffer, transfer_size, 1000);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n",
+ __func__, NI_USB_HS_PLUS_0x48_REQUEST, retval);
+ break;
+ }
+ // expected response data: 48 f3 30 00 00 00 00 00 00 00 00 00 00 00 00 00
+ if (buffer[0] != NI_USB_HS_PLUS_0x48_REQUEST)
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[0]=0x%x, expected 0x%x\n",
+ __func__, (int)buffer[0], NI_USB_HS_PLUS_0x48_REQUEST);
+
+ transfer_size = 2;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_HS_PLUS_LED_REQUEST,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x1, 0x0, buffer, transfer_size, 1000);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n",
+ __func__, NI_USB_HS_PLUS_LED_REQUEST, retval);
+ break;
+ }
+ // expected response data: 4b 00
+ if (buffer[0] != NI_USB_HS_PLUS_LED_REQUEST)
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[0]=0x%x, expected 0x%x\n",
+ __func__, (int)buffer[0], NI_USB_HS_PLUS_LED_REQUEST);
+
+ transfer_size = 9;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_HS_PLUS_0xf8_REQUEST,
+ USB_DIR_IN | USB_TYPE_VENDOR |
+ USB_RECIP_INTERFACE,
+ 0x0, 0x1, buffer, transfer_size, 1000);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n",
+ __func__, NI_USB_HS_PLUS_0xf8_REQUEST, retval);
+ break;
+ }
+ // expected response data: f8 01 00 00 00 01 00 00 00
+ if (buffer[0] != NI_USB_HS_PLUS_0xf8_REQUEST)
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[0]=0x%x, expected 0x%x\n",
+ __func__, (int)buffer[0], NI_USB_HS_PLUS_0xf8_REQUEST);
+
+ } while (0);
+
+ // cleanup
+ kfree(buffer);
+ return retval;
+}
+
+static inline int ni_usb_device_match(struct usb_interface *interface,
+ const gpib_board_config_t *config)
+{
+ if (gpib_match_device_path(&interface->dev, config->device_path) == 0)
+ return 0;
+ return 1;
+}
+
+static int ni_usb_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ int retval;
+ int i;
+ struct ni_usb_priv *ni_priv;
+ int product_id;
+ struct usb_device *usb_dev;
+
+ mutex_lock(&ni_usb_hotplug_lock);
+ retval = ni_usb_allocate_private(board);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ ni_priv = board->private_data;
+ for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) {
+ if (ni_usb_driver_interfaces[i] &&
+ !usb_get_intfdata(ni_usb_driver_interfaces[i]) &&
+ ni_usb_device_match(ni_usb_driver_interfaces[i], config)) {
+ ni_priv->bus_interface = ni_usb_driver_interfaces[i];
+ usb_set_intfdata(ni_usb_driver_interfaces[i], board);
+ usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d attached to gpib minor %d, NI usb interface %i\n",
+ usb_dev->bus->busnum, usb_dev->devnum, board->minor, i);
+ break;
+ }
+ }
+ if (i == MAX_NUM_NI_USB_INTERFACES) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ pr_err("No supported NI usb gpib adapters found, have you loaded its firmware?\n");
+ return -ENODEV;
+ }
+ if (usb_reset_configuration(interface_to_usbdev(ni_priv->bus_interface)))
+ dev_err(&usb_dev->dev, "ni_usb_gpib: usb_reset_configuration() failed.\n");
+
+ product_id = le16_to_cpu(usb_dev->descriptor.idProduct);
+ ni_priv->product_id = product_id;
+
+ timer_setup(&ni_priv->bulk_timer, ni_usb_timeout_handler, 0);
+
+ switch (product_id) {
+ case USB_DEVICE_ID_NI_USB_B:
+ ni_priv->bulk_out_endpoint = NIUSB_B_BULK_OUT_ENDPOINT;
+ ni_priv->bulk_in_endpoint = NIUSB_B_BULK_IN_ENDPOINT;
+ ni_priv->interrupt_in_endpoint = NIUSB_B_INTERRUPT_IN_ENDPOINT;
+ ni_usb_b_read_serial_number(ni_priv);
+ break;
+ case USB_DEVICE_ID_NI_USB_HS:
+ case USB_DEVICE_ID_MC_USB_488:
+ case USB_DEVICE_ID_KUSB_488A:
+ ni_priv->bulk_out_endpoint = NIUSB_HS_BULK_OUT_ENDPOINT;
+ ni_priv->bulk_in_endpoint = NIUSB_HS_BULK_IN_ENDPOINT;
+ ni_priv->interrupt_in_endpoint = NIUSB_HS_INTERRUPT_IN_ENDPOINT;
+ retval = ni_usb_hs_wait_for_ready(ni_priv);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ break;
+ case USB_DEVICE_ID_NI_USB_HS_PLUS:
+ ni_priv->bulk_out_endpoint = NIUSB_HS_PLUS_BULK_OUT_ENDPOINT;
+ ni_priv->bulk_in_endpoint = NIUSB_HS_PLUS_BULK_IN_ENDPOINT;
+ ni_priv->interrupt_in_endpoint = NIUSB_HS_PLUS_INTERRUPT_IN_ENDPOINT;
+ retval = ni_usb_hs_wait_for_ready(ni_priv);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ retval = ni_usb_hs_plus_extra_init(ni_priv);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ break;
+ default:
+ mutex_unlock(&ni_usb_hotplug_lock);
+ dev_err(&usb_dev->dev, "\tDriver bug: unknown endpoints for usb device id %x\n",
+ product_id);
+ return -EINVAL;
+ }
+
+ retval = ni_usb_setup_urbs(board);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ retval = ni_usb_set_interrupt_monitor(board, 0);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+
+ board->t1_nano_sec = 500;
+
+ retval = ni_usb_init(board);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ retval = ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+
+ mutex_unlock(&ni_usb_hotplug_lock);
+ dev_info(&usb_dev->dev, "%s: attached\n", __func__);
+ return retval;
+}
+
+static int ni_usb_shutdown_hardware(struct ni_usb_priv *ni_priv)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int retval;
+ int i = 0;
+ struct ni_usb_register writes[2];
+ static const int writes_length = ARRAY_SIZE(writes);
+ unsigned int ibsta;
+
+// printk("%s: %s\n", __func__);
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CR;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_UNKNOWN3;
+ writes[i].address = 0x10;
+ writes[i].value = 0x0;
+ i++;
+ if (i > writes_length) {
+ dev_err(&usb_dev->dev, "%s: bug!, buffer overrun, i=%i\n", __func__, i);
+ return -EINVAL;
+ }
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return retval;
+ }
+ return 0;
+}
+
+static void ni_usb_detach(gpib_board_t *board)
+{
+ struct ni_usb_priv *ni_priv;
+
+ mutex_lock(&ni_usb_hotplug_lock);
+// under windows, software unplug does chip_reset nec7210 aux command,
+// then writes 0x0 to address 0x10 of device 3
+ ni_priv = board->private_data;
+ if (ni_priv) {
+ if (ni_priv->bus_interface) {
+ ni_usb_set_interrupt_monitor(board, 0);
+ ni_usb_shutdown_hardware(ni_priv);
+ usb_set_intfdata(ni_priv->bus_interface, NULL);
+ }
+ mutex_lock(&ni_priv->bulk_transfer_lock);
+ mutex_lock(&ni_priv->control_transfer_lock);
+ mutex_lock(&ni_priv->interrupt_transfer_lock);
+ ni_usb_cleanup_urbs(ni_priv);
+ ni_usb_free_private(ni_priv);
+ }
+ mutex_unlock(&ni_usb_hotplug_lock);
+}
+
+gpib_interface_t ni_usb_gpib_interface = {
+name: "ni_usb_b",
+attach : ni_usb_attach,
+detach : ni_usb_detach,
+read : ni_usb_read,
+write : ni_usb_write,
+command : ni_usb_command,
+take_control : ni_usb_take_control,
+go_to_standby : ni_usb_go_to_standby,
+request_system_control : ni_usb_request_system_control,
+interface_clear : ni_usb_interface_clear,
+remote_enable : ni_usb_remote_enable,
+enable_eos : ni_usb_enable_eos,
+disable_eos : ni_usb_disable_eos,
+parallel_poll : ni_usb_parallel_poll,
+parallel_poll_configure : ni_usb_parallel_poll_configure,
+parallel_poll_response : ni_usb_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ni_usb_line_status,
+update_status : ni_usb_update_status,
+primary_address : ni_usb_primary_address,
+secondary_address : ni_usb_secondary_address,
+serial_poll_response : ni_usb_serial_poll_response,
+serial_poll_status : ni_usb_serial_poll_status,
+t1_delay : ni_usb_t1_delay,
+return_to_local : ni_usb_return_to_local,
+skip_check_for_command_acceptors : 1
+};
+
+// Table with the USB-devices: just now only testing IDs
+static struct usb_device_id ni_usb_driver_device_table[] = {
+ {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_NI_USB_B)},
+ {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_NI_USB_HS)},
+ // gpib-usb-hs+ has a second interface for the analyzer, which we ignore
+ {USB_DEVICE_INTERFACE_NUMBER(USB_VENDOR_ID_NI, USB_DEVICE_ID_NI_USB_HS_PLUS, 0)},
+ {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_KUSB_488A)},
+ {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_MC_USB_488)},
+ {} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, ni_usb_driver_device_table);
+
+static int ni_usb_driver_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+ int i;
+ char *path;
+ static const int path_length = 1024;
+
+ mutex_lock(&ni_usb_hotplug_lock);
+ usb_get_dev(usb_dev);
+ for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) {
+ if (!ni_usb_driver_interfaces[i]) {
+ ni_usb_driver_interfaces[i] = interface;
+ usb_set_intfdata(interface, NULL);
+ break;
+ }
+ }
+ if (i == MAX_NUM_NI_USB_INTERFACES) {
+ usb_put_dev(usb_dev);
+ mutex_unlock(&ni_usb_hotplug_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_driver_interfaces[] full\n", __func__);
+ return -1;
+ }
+ path = kmalloc(path_length, GFP_KERNEL);
+ if (!path) {
+ usb_put_dev(usb_dev);
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return -ENOMEM;
+ }
+ usb_make_path(usb_dev, path, path_length);
+ dev_info(&usb_dev->dev, "ni_usb_gpib: probe succeeded for path: %s\n", path);
+ kfree(path);
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return 0;
+}
+
+static void ni_usb_driver_disconnect(struct usb_interface *interface)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+ int i;
+
+ mutex_lock(&ni_usb_hotplug_lock);
+ for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) {
+ if (ni_usb_driver_interfaces[i] == interface) {
+ gpib_board_t *board = usb_get_intfdata(interface);
+
+ if (board) {
+ struct ni_usb_priv *ni_priv = board->private_data;
+
+ if (ni_priv) {
+ mutex_lock(&ni_priv->bulk_transfer_lock);
+ mutex_lock(&ni_priv->control_transfer_lock);
+ mutex_lock(&ni_priv->interrupt_transfer_lock);
+ ni_usb_cleanup_urbs(ni_priv);
+ ni_priv->bus_interface = NULL;
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ mutex_unlock(&ni_priv->control_transfer_lock);
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ }
+ }
+ ni_usb_driver_interfaces[i] = NULL;
+ break;
+ }
+ }
+ if (i == MAX_NUM_NI_USB_INTERFACES)
+ dev_err(&usb_dev->dev, "%s: unable to find interface in ni_usb_driver_interfaces[]? bug?\n",
+ __func__);
+ usb_put_dev(usb_dev);
+ mutex_unlock(&ni_usb_hotplug_lock);
+}
+
+static int ni_usb_driver_suspend(struct usb_interface *interface, pm_message_t message)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+ gpib_board_t *board;
+ int i, retval;
+
+ mutex_lock(&ni_usb_hotplug_lock);
+
+ for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) {
+ if (ni_usb_driver_interfaces[i] == interface) {
+ board = usb_get_intfdata(interface);
+ if (board)
+ break;
+ }
+ }
+ if (i == MAX_NUM_NI_USB_INTERFACES) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return 0;
+ }
+
+ struct ni_usb_priv *ni_priv = board->private_data;
+
+ if (ni_priv) {
+ ni_usb_set_interrupt_monitor(board, 0);
+ retval = ni_usb_shutdown_hardware(ni_priv);
+ if (retval) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ if (ni_priv->interrupt_urb) {
+ mutex_lock(&ni_priv->interrupt_transfer_lock);
+ ni_usb_cleanup_urbs(ni_priv);
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ }
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d gpib minor %d, ni usb interface %i suspended\n",
+ usb_dev->bus->busnum, usb_dev->devnum, board->minor, i);
+ }
+
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return 0;
+}
+
+static int ni_usb_driver_resume(struct usb_interface *interface)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+
+ gpib_board_t *board;
+ int i, retval;
+
+ mutex_lock(&ni_usb_hotplug_lock);
+
+ for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) {
+ if (ni_usb_driver_interfaces[i] == interface) {
+ board = usb_get_intfdata(interface);
+ if (board)
+ break;
+ }
+ }
+ if (i == MAX_NUM_NI_USB_INTERFACES) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return 0;
+ }
+
+ struct ni_usb_priv *ni_priv = board->private_data;
+
+ if (ni_priv) {
+ if (ni_priv->interrupt_urb) {
+ mutex_lock(&ni_priv->interrupt_transfer_lock);
+ retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ } else {
+ dev_err(&usb_dev->dev, "%s: bug! int urb not set up\n", __func__);
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return -EINVAL;
+ }
+
+ switch (ni_priv->product_id) {
+ case USB_DEVICE_ID_NI_USB_B:
+ ni_usb_b_read_serial_number(ni_priv);
+ break;
+ case USB_DEVICE_ID_NI_USB_HS:
+ case USB_DEVICE_ID_MC_USB_488:
+ case USB_DEVICE_ID_KUSB_488A:
+ retval = ni_usb_hs_wait_for_ready(ni_priv);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ break;
+ case USB_DEVICE_ID_NI_USB_HS_PLUS:
+ retval = ni_usb_hs_wait_for_ready(ni_priv);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ retval = ni_usb_hs_plus_extra_init(ni_priv);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ break;
+ default:
+ mutex_unlock(&ni_usb_hotplug_lock);
+ dev_err(&usb_dev->dev, "\tDriver bug: unknown endpoints for usb device id\n");
+ return -EINVAL;
+ }
+
+ retval = ni_usb_set_interrupt_monitor(board, 0);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+
+ retval = ni_usb_init(board);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ retval = ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ if (board->master)
+ ni_usb_interface_clear(board, 1); // this is a pulsed action
+ if (ni_priv->ren_state)
+ ni_usb_remote_enable(board, 1);
+
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d gpib minor %d, ni usb interface %i resumed\n",
+ usb_dev->bus->busnum, usb_dev->devnum, board->minor, i);
+ }
+
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return 0;
+}
+
+static struct usb_driver ni_usb_bus_driver = {
+ .name = "ni_usb_gpib",
+ .probe = ni_usb_driver_probe,
+ .disconnect = ni_usb_driver_disconnect,
+ .suspend = ni_usb_driver_suspend,
+ .resume = ni_usb_driver_resume,
+ .id_table = ni_usb_driver_device_table,
+};
+
+static int __init ni_usb_init_module(void)
+{
+ int i;
+
+ pr_info("ni_usb_gpib driver loading\n");
+ for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++)
+ ni_usb_driver_interfaces[i] = NULL;
+ usb_register(&ni_usb_bus_driver);
+ gpib_register_driver(&ni_usb_gpib_interface, THIS_MODULE);
+
+ return 0;
+}
+
+static void __exit ni_usb_exit_module(void)
+{
+ pr_info("ni_usb_gpib driver unloading\n");
+ gpib_unregister_driver(&ni_usb_gpib_interface);
+ usb_deregister(&ni_usb_bus_driver);
+}
+
+module_init(ni_usb_init_module);
+module_exit(ni_usb_exit_module);
diff --git a/drivers/staging/gpib/ni_usb/ni_usb_gpib.h b/drivers/staging/gpib/ni_usb/ni_usb_gpib.h
new file mode 100644
index 000000000000..9b21dfa0f3f6
--- /dev/null
+++ b/drivers/staging/gpib/ni_usb/ni_usb_gpib.h
@@ -0,0 +1,216 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2004 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _NI_USB_GPIB_H
+#define _NI_USB_GPIB_H
+
+#include <linux/mutex.h>
+#include <linux/semaphore.h>
+#include <linux/usb.h>
+#include <linux/timer.h>
+#include "gpibP.h"
+
+enum {
+ USB_VENDOR_ID_NI = 0x3923
+};
+
+enum {
+ USB_DEVICE_ID_NI_USB_B = 0x702a,
+ USB_DEVICE_ID_NI_USB_B_PREINIT = 0x702b, // device id before firmware is loaded
+ USB_DEVICE_ID_NI_USB_HS = 0x709b,
+ USB_DEVICE_ID_NI_USB_HS_PLUS = 0x7618,
+ USB_DEVICE_ID_KUSB_488A = 0x725c,
+ USB_DEVICE_ID_MC_USB_488 = 0x725d
+};
+
+enum ni_usb_device {
+ NIUSB_SUBDEV_TNT4882 = 1,
+ NIUSB_SUBDEV_UNKNOWN2 = 2,
+ NIUSB_SUBDEV_UNKNOWN3 = 3,
+};
+
+enum endpoint_addresses {
+ NIUSB_B_BULK_OUT_ENDPOINT = 0x2,
+ NIUSB_B_BULK_IN_ENDPOINT = 0x2,
+ NIUSB_B_BULK_IN_ALT_ENDPOINT = 0x6,
+ NIUSB_B_INTERRUPT_IN_ENDPOINT = 0x4,
+};
+
+enum hs_enpoint_addresses {
+ NIUSB_HS_BULK_OUT_ENDPOINT = 0x2,
+ NIUSB_HS_BULK_OUT_ALT_ENDPOINT = 0x6,
+ NIUSB_HS_BULK_IN_ENDPOINT = 0x4,
+ NIUSB_HS_BULK_IN_ALT_ENDPOINT = 0x8,
+ NIUSB_HS_INTERRUPT_IN_ENDPOINT = 0x1,
+};
+
+enum hs_plus_endpoint_addresses {
+ NIUSB_HS_PLUS_BULK_OUT_ENDPOINT = 0x1,
+ NIUSB_HS_PLUS_BULK_OUT_ALT_ENDPOINT = 0x4,
+ NIUSB_HS_PLUS_BULK_IN_ENDPOINT = 0x2,
+ NIUSB_HS_PLUS_BULK_IN_ALT_ENDPOINT = 0x5,
+ NIUSB_HS_PLUS_INTERRUPT_IN_ENDPOINT = 0x3,
+};
+
+struct ni_usb_urb_ctx {
+ struct semaphore complete;
+ unsigned timed_out : 1;
+};
+
+// struct which defines private_data for ni_usb devices
+struct ni_usb_priv {
+ struct usb_interface *bus_interface;
+ int bulk_out_endpoint;
+ int bulk_in_endpoint;
+ int interrupt_in_endpoint;
+ u8 eos_char;
+ unsigned short eos_mode;
+ unsigned int monitored_ibsta_bits;
+ struct urb *bulk_urb;
+ struct urb *interrupt_urb;
+ u8 interrupt_buffer[0x11];
+ struct mutex addressed_transfer_lock; // protect transfer lock
+ struct mutex bulk_transfer_lock; // protect bulk message sends
+ struct mutex control_transfer_lock; // protect control messages
+ struct mutex interrupt_transfer_lock; // protect interrupt messages
+ struct timer_list bulk_timer;
+ struct ni_usb_urb_ctx context;
+ int product_id;
+ unsigned short ren_state;
+};
+
+struct ni_usb_status_block {
+ short id;
+ unsigned short ibsta;
+ short error_code;
+ unsigned short count;
+};
+
+struct ni_usb_register {
+ enum ni_usb_device device;
+ short address;
+ unsigned short value;
+};
+
+enum ni_usb_bulk_ids {
+ NIUSB_IBCAC_ID = 0x1,
+ NIUSB_UNKNOWN3_ID = 0x3, // device level function id?
+ NIUSB_TERM_ID = 0x4,
+ NIUSB_IBGTS_ID = 0x6,
+ NIUSB_IBRPP_ID = 0x7,
+ NIUSB_REG_READ_ID = 0x8,
+ NIUSB_REG_WRITE_ID = 0x9,
+ NIUSB_IBSIC_ID = 0xf,
+ NIUSB_REGISTER_READ_DATA_START_ID = 0x34,
+ NIUSB_REGISTER_READ_DATA_END_ID = 0x35,
+ NIUSB_IBRD_DATA_ID = 0x36,
+ NIUSB_IBRD_EXTENDED_DATA_ID = 0x37,
+ NIUSB_IBRD_STATUS_ID = 0x38
+};
+
+enum ni_usb_error_codes {
+ NIUSB_NO_ERROR = 0,
+ /* NIUSB_ABORTED_ERROR occurs when I/O is interrupted early by
+ * doing a NI_USB_STOP_REQUEST on the control endpoint.
+ */
+ NIUSB_ABORTED_ERROR = 1,
+ // NIUSB_READ_ATN_ERROR occurs when you do a board read while
+ // ATN is set
+ NIUSB_ATN_STATE_ERROR = 2,
+ // NIUSB_ADDRESSING_ERROR occurs when you do a board
+ // read/write as CIC but are not in LACS/TACS
+ NIUSB_ADDRESSING_ERROR = 3,
+ /* NIUSB_EOSMODE_ERROR occurs on reads if any eos mode or char
+ * bits are set when REOS is not set.
+ * Have also seen error 4 if you try to send more than 16
+ * command bytes at once on a usb-b.
+ */
+ NIUSB_EOSMODE_ERROR = 4,
+ // NIUSB_NO_BUS_ERROR occurs when you try to write a command
+ // byte but there are no devices connected to the gpib bus
+ NIUSB_NO_BUS_ERROR = 5,
+ // NIUSB_NO_LISTENER_ERROR occurs when you do a board write as
+ // CIC with no listener
+ NIUSB_NO_LISTENER_ERROR = 8,
+ // get NIUSB_TIMEOUT_ERROR on board read/write timeout
+ NIUSB_TIMEOUT_ERROR = 10,
+};
+
+enum ni_usb_control_requests {
+ NI_USB_STOP_REQUEST = 0x20,
+ NI_USB_WAIT_REQUEST = 0x21,
+ NI_USB_POLL_READY_REQUEST = 0x40,
+ NI_USB_SERIAL_NUMBER_REQUEST = 0x41,
+ NI_USB_HS_PLUS_0x48_REQUEST = 0x48,
+ NI_USB_HS_PLUS_LED_REQUEST = 0x4b,
+ NI_USB_HS_PLUS_0xf8_REQUEST = 0xf8
+};
+
+static const unsigned int ni_usb_ibsta_monitor_mask =
+ SRQI | LOK | REM | CIC | ATN | TACS | LACS | DTAS | DCAS;
+
+static inline int nec7210_to_tnt4882_offset(int offset)
+{
+ return 2 * offset;
+};
+
+static inline int ni_usb_bulk_termination(u8 *buffer)
+{
+ int i = 0;
+
+ buffer[i++] = NIUSB_TERM_ID;
+ buffer[i++] = 0x0;
+ buffer[i++] = 0x0;
+ buffer[i++] = 0x0;
+ return i;
+}
+
+enum ni_usb_unknown3_register {
+ SERIAL_NUMBER_4_REG = 0x8,
+ SERIAL_NUMBER_3_REG = 0x9,
+ SERIAL_NUMBER_2_REG = 0xa,
+ SERIAL_NUMBER_1_REG = 0xb,
+};
+
+static inline int ni_usb_bulk_register_write_header(u8 *buffer, int num_writes)
+{
+ int i = 0;
+
+ buffer[i++] = NIUSB_REG_WRITE_ID;
+ buffer[i++] = num_writes;
+ buffer[i++] = 0x0;
+ return i;
+}
+
+static inline int ni_usb_bulk_register_write(u8 *buffer, struct ni_usb_register reg)
+{
+ int i = 0;
+
+ buffer[i++] = reg.device;
+ buffer[i++] = reg.address;
+ buffer[i++] = reg.value;
+ return i;
+}
+
+static inline int ni_usb_bulk_register_read_header(u8 *buffer, int num_reads)
+{
+ int i = 0;
+
+ buffer[i++] = NIUSB_REG_READ_ID;
+ buffer[i++] = num_reads;
+ return i;
+}
+
+static inline int ni_usb_bulk_register_read(u8 *buffer, int device, int address)
+{
+ int i = 0;
+
+ buffer[i++] = device;
+ buffer[i++] = address;
+ return i;
+}
+
+#endif // _NI_USB_GPIB_H
diff --git a/drivers/staging/gpib/pc2/Makefile b/drivers/staging/gpib/pc2/Makefile
new file mode 100644
index 000000000000..8148425e0f87
--- /dev/null
+++ b/drivers/staging/gpib/pc2/Makefile
@@ -0,0 +1,5 @@
+
+obj-m += pc2_gpib.o
+
+
+
diff --git a/drivers/staging/gpib/pc2/pc2_gpib.c b/drivers/staging/gpib/pc2/pc2_gpib.c
new file mode 100644
index 000000000000..7b3b34f47341
--- /dev/null
+++ b/drivers/staging/gpib/pc2/pc2_gpib.c
@@ -0,0 +1,656 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <asm/dma.h>
+#include <linux/dma-mapping.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include "nec7210.h"
+#include "gpibP.h"
+
+// struct which defines private_data for pc2 driver
+struct pc2_priv {
+ struct nec7210_priv nec7210_priv;
+ unsigned int irq;
+ // io address that clears interrupt for pc2a (0x2f0 + irq)
+ unsigned int clear_intr_addr;
+};
+
+// pc2 uses 8 consecutive io addresses
+static const int pc2_iosize = 8;
+static const int pc2a_iosize = 8;
+static const int pc2_2a_iosize = 16;
+
+// offset between io addresses of successive nec7210 registers
+static const int pc2a_reg_offset = 0x400;
+static const int pc2_reg_offset = 1;
+
+//interrupt service routine
+static irqreturn_t pc2_interrupt(int irq, void *arg);
+static irqreturn_t pc2a_interrupt(int irq, void *arg);
+
+// pc2 specific registers and bits
+
+// interrupt clear register address
+static const int pc2a_clear_intr_iobase = 0x2f0;
+static inline unsigned int CLEAR_INTR_REG(unsigned int irq)
+{
+ return pc2a_clear_intr_iobase + irq;
+}
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for PC2/PC2a and compatible devices");
+
+static int pc2_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int pc2a_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int pc2a_cb7210_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int pc2_2a_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void pc2_detach(gpib_board_t *board);
+static void pc2a_detach(gpib_board_t *board);
+static void pc2_2a_detach(gpib_board_t *board);
+
+/*
+ * GPIB interrupt service routines
+ */
+
+irqreturn_t pc2_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct pc2_priv *priv = board->private_data;
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = nec7210_interrupt(board, &priv->nec7210_priv);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+irqreturn_t pc2a_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct pc2_priv *priv = board->private_data;
+ int status1, status2;
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ // read interrupt status (also clears status)
+ status1 = read_byte(&priv->nec7210_priv, ISR1);
+ status2 = read_byte(&priv->nec7210_priv, ISR2);
+ /* clear interrupt circuit */
+ if (priv->irq)
+ outb(0xff, CLEAR_INTR_REG(priv->irq));
+ retval = nec7210_interrupt_have_status(board, &priv->nec7210_priv, status1, status2);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+// wrappers for interface functions
+static int pc2_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+}
+
+static int pc2_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+static int pc2_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+static int pc2_take_control(gpib_board_t *board, int synchronous)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+static int pc2_go_to_standby(gpib_board_t *board)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+static void pc2_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_request_system_control(board, &priv->nec7210_priv, request_control);
+}
+
+static void pc2_interface_clear(gpib_board_t *board, int assert)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+static void pc2_remote_enable(gpib_board_t *board, int enable)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+static int pc2_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+static void pc2_disable_eos(gpib_board_t *board)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+static unsigned int pc2_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
+}
+
+static int pc2_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+static int pc2_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+static int pc2_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
+}
+
+static void pc2_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config);
+}
+
+static void pc2_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+static void pc2_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
+}
+
+static uint8_t pc2_serial_poll_status(gpib_board_t *board)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+static unsigned int pc2_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_t1_delay(board, &priv->nec7210_priv, nano_sec);
+}
+
+static void pc2_return_to_local(gpib_board_t *board)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_return_to_local(board, &priv->nec7210_priv);
+}
+
+gpib_interface_t pc2_interface = {
+name: "pcII",
+attach : pc2_attach,
+detach : pc2_detach,
+read : pc2_read,
+write : pc2_write,
+command : pc2_command,
+take_control : pc2_take_control,
+go_to_standby : pc2_go_to_standby,
+request_system_control : pc2_request_system_control,
+interface_clear : pc2_interface_clear,
+remote_enable : pc2_remote_enable,
+enable_eos : pc2_enable_eos,
+disable_eos : pc2_disable_eos,
+parallel_poll : pc2_parallel_poll,
+parallel_poll_configure : pc2_parallel_poll_configure,
+parallel_poll_response : pc2_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL,
+update_status : pc2_update_status,
+primary_address : pc2_primary_address,
+secondary_address : pc2_secondary_address,
+serial_poll_response : pc2_serial_poll_response,
+serial_poll_status : pc2_serial_poll_status,
+t1_delay : pc2_t1_delay,
+return_to_local : pc2_return_to_local,
+};
+
+gpib_interface_t pc2a_interface = {
+name: "pcIIa",
+attach : pc2a_attach,
+detach : pc2a_detach,
+read : pc2_read,
+write : pc2_write,
+command : pc2_command,
+take_control : pc2_take_control,
+go_to_standby : pc2_go_to_standby,
+request_system_control : pc2_request_system_control,
+interface_clear : pc2_interface_clear,
+remote_enable : pc2_remote_enable,
+enable_eos : pc2_enable_eos,
+disable_eos : pc2_disable_eos,
+parallel_poll : pc2_parallel_poll,
+parallel_poll_configure : pc2_parallel_poll_configure,
+parallel_poll_response : pc2_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL,
+update_status : pc2_update_status,
+primary_address : pc2_primary_address,
+secondary_address : pc2_secondary_address,
+serial_poll_response : pc2_serial_poll_response,
+serial_poll_status : pc2_serial_poll_status,
+t1_delay : pc2_t1_delay,
+return_to_local : pc2_return_to_local,
+};
+
+gpib_interface_t pc2a_cb7210_interface = {
+name: "pcIIa_cb7210",
+attach : pc2a_cb7210_attach,
+detach : pc2a_detach,
+read : pc2_read,
+write : pc2_write,
+command : pc2_command,
+take_control : pc2_take_control,
+go_to_standby : pc2_go_to_standby,
+request_system_control : pc2_request_system_control,
+interface_clear : pc2_interface_clear,
+remote_enable : pc2_remote_enable,
+enable_eos : pc2_enable_eos,
+disable_eos : pc2_disable_eos,
+parallel_poll : pc2_parallel_poll,
+parallel_poll_configure : pc2_parallel_poll_configure,
+parallel_poll_response : pc2_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL, //XXX
+update_status : pc2_update_status,
+primary_address : pc2_primary_address,
+secondary_address : pc2_secondary_address,
+serial_poll_response : pc2_serial_poll_response,
+serial_poll_status : pc2_serial_poll_status,
+t1_delay : pc2_t1_delay,
+return_to_local : pc2_return_to_local,
+};
+
+gpib_interface_t pc2_2a_interface = {
+name: "pcII_IIa",
+attach : pc2_2a_attach,
+detach : pc2_2a_detach,
+read : pc2_read,
+write : pc2_write,
+command : pc2_command,
+take_control : pc2_take_control,
+go_to_standby : pc2_go_to_standby,
+request_system_control : pc2_request_system_control,
+interface_clear : pc2_interface_clear,
+remote_enable : pc2_remote_enable,
+enable_eos : pc2_enable_eos,
+disable_eos : pc2_disable_eos,
+parallel_poll : pc2_parallel_poll,
+parallel_poll_configure : pc2_parallel_poll_configure,
+parallel_poll_response : pc2_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL,
+update_status : pc2_update_status,
+primary_address : pc2_primary_address,
+secondary_address : pc2_secondary_address,
+serial_poll_response : pc2_serial_poll_response,
+serial_poll_status : pc2_serial_poll_status,
+t1_delay : pc2_t1_delay,
+return_to_local : pc2_return_to_local,
+};
+
+static int allocate_private(gpib_board_t *board)
+{
+ struct pc2_priv *priv;
+
+ board->private_data = kmalloc(sizeof(struct pc2_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ priv = board->private_data;
+ memset(priv, 0, sizeof(struct pc2_priv));
+ init_nec7210_private(&priv->nec7210_priv);
+ return 0;
+}
+
+static void free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+static int pc2_generic_attach(gpib_board_t *board, const gpib_board_config_t *config,
+ enum nec7210_chipset chipset)
+{
+ struct pc2_priv *pc2_priv;
+ struct nec7210_priv *nec_priv;
+
+ board->status = 0;
+ if (allocate_private(board))
+ return -ENOMEM;
+ pc2_priv = board->private_data;
+ nec_priv = &pc2_priv->nec7210_priv;
+ nec_priv->read_byte = nec7210_ioport_read_byte;
+ nec_priv->write_byte = nec7210_ioport_write_byte;
+ nec_priv->type = chipset;
+
+#ifndef PC2_DMA
+ /* board->dev hasn't been initialized, so forget about DMA until this driver
+ * is adapted to use isa_register_driver.
+ */
+ if (config->ibdma)
+ pr_err("DMA disabled for pc2 gpib, driver needs to be adapted to use isa_register_driver to get a struct device*");
+#else
+ if (config->ibdma) {
+ nec_priv->dma_buffer_length = 0x1000;
+ nec_priv->dma_buffer = dma_alloc_coherent(board->dev,
+ nec_priv->dma_buffer_length, &
+ nec_priv->dma_buffer_addr, GFP_ATOMIC);
+ if (!nec_priv->dma_buffer)
+ return -ENOMEM;
+
+ // request isa dma channel
+ if (request_dma(config->ibdma, "pc2")) {
+ pr_err("gpib: can't request DMA %d\n", config->ibdma);
+ return -1;
+ }
+ nec_priv->dma_channel = config->ibdma;
+ }
+#endif
+
+ return 0;
+}
+
+int pc2_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ int isr_flags = 0;
+ struct pc2_priv *pc2_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+
+ retval = pc2_generic_attach(board, config, NEC7210);
+ if (retval)
+ return retval;
+
+ pc2_priv = board->private_data;
+ nec_priv = &pc2_priv->nec7210_priv;
+ nec_priv->offset = pc2_reg_offset;
+
+ if (request_region((unsigned long)config->ibbase, pc2_iosize, "pc2") == 0) {
+ pr_err("gpib: ioports are already in use\n");
+ return -1;
+ }
+ nec_priv->iobase = config->ibbase;
+
+ nec7210_board_reset(nec_priv, board);
+
+ // install interrupt handler
+ if (config->ibirq) {
+ if (request_irq(config->ibirq, pc2_interrupt, isr_flags, "pc2", board)) {
+ pr_err("gpib: can't request IRQ %d\n", config->ibirq);
+ return -1;
+ }
+ }
+ pc2_priv->irq = config->ibirq;
+ /* poll so we can detect assertion of ATN */
+ if (gpib_request_pseudo_irq(board, pc2_interrupt)) {
+ pr_err("pc2_gpib: failed to allocate pseudo_irq\n");
+ return -1;
+ }
+ /* set internal counter register for 8 MHz input clock */
+ write_byte(nec_priv, ICR | 8, AUXMR);
+
+ nec7210_board_online(nec_priv, board);
+
+ return 0;
+}
+
+void pc2_detach(gpib_board_t *board)
+{
+ struct pc2_priv *pc2_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (pc2_priv) {
+ nec_priv = &pc2_priv->nec7210_priv;
+#ifdef PC2_DMA
+ if (nec_priv->dma_channel)
+ free_dma(nec_priv->dma_channel);
+#endif
+ gpib_free_pseudo_irq(board);
+ if (pc2_priv->irq)
+ free_irq(pc2_priv->irq, board);
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ release_region((unsigned long)(nec_priv->iobase), pc2_iosize);
+ }
+ if (nec_priv->dma_buffer) {
+ dma_free_coherent(board->dev, nec_priv->dma_buffer_length,
+ nec_priv->dma_buffer, nec_priv->dma_buffer_addr);
+ nec_priv->dma_buffer = NULL;
+ }
+ }
+ free_private(board);
+}
+
+static int pc2a_common_attach(gpib_board_t *board, const gpib_board_config_t *config,
+ unsigned int num_registers, enum nec7210_chipset chipset)
+{
+ unsigned int i, j;
+ struct pc2_priv *pc2_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+
+ retval = pc2_generic_attach(board, config, chipset);
+ if (retval)
+ return retval;
+
+ pc2_priv = board->private_data;
+ nec_priv = &pc2_priv->nec7210_priv;
+ nec_priv->offset = pc2a_reg_offset;
+
+ switch ((unsigned long)(config->ibbase)) {
+ case 0x02e1:
+ case 0x22e1:
+ case 0x42e1:
+ case 0x62e1:
+ break;
+ default:
+ pr_err("PCIIa base range invalid, must be one of 0x[0246]2e1, but is 0x%p\n",
+ config->ibbase);
+ return -1;
+ }
+
+ if (config->ibirq) {
+ if (config->ibirq < 2 || config->ibirq > 7) {
+ pr_err("pc2_gpib: illegal interrupt level %i\n", config->ibirq);
+ return -1;
+ }
+ } else {
+ pr_err("pc2_gpib: interrupt disabled, using polling mode (slow)\n");
+ }
+#ifdef CHECK_IOPORTS
+ unsigned int err = 0;
+
+ for (i = 0; i < num_registers; i++) {
+ if (check_region((unsigned long)config->ibbase + i * pc2a_reg_offset, 1))
+ err++;
+ }
+ if (config->ibirq && check_region(pc2a_clear_intr_iobase + config->ibirq, 1))
+ err++;
+ if (err) {
+ pr_err("gpib: ioports are already in use");
+ return -1;
+ }
+#endif
+ for (i = 0; i < num_registers; i++) {
+ if (!request_region((unsigned long)config->ibbase +
+ i * pc2a_reg_offset, 1, "pc2a")) {
+ pr_err("gpib: ioports are already in use");
+ for (j = 0; j < i; j++)
+ release_region((unsigned long)(config->ibbase) +
+ j * pc2a_reg_offset, 1);
+ return -1;
+ }
+ }
+ nec_priv->iobase = config->ibbase;
+ if (config->ibirq) {
+ if (!request_region(pc2a_clear_intr_iobase + config->ibirq, 1, "pc2a")) {
+ pr_err("gpib: ioports are already in use");
+ return -1;
+ }
+ pc2_priv->clear_intr_addr = pc2a_clear_intr_iobase + config->ibirq;
+ if (request_irq(config->ibirq, pc2a_interrupt, 0, "pc2a", board)) {
+ pr_err("gpib: can't request IRQ %d\n", config->ibirq);
+ return -1;
+ }
+ }
+ pc2_priv->irq = config->ibirq;
+ /* poll so we can detect assertion of ATN */
+ if (gpib_request_pseudo_irq(board, pc2_interrupt)) {
+ pr_err("pc2_gpib: failed to allocate pseudo_irq\n");
+ return -1;
+ }
+
+ // make sure interrupt is clear
+ if (pc2_priv->irq)
+ outb(0xff, CLEAR_INTR_REG(pc2_priv->irq));
+
+ nec7210_board_reset(nec_priv, board);
+
+ /* set internal counter register for 8 MHz input clock */
+ write_byte(nec_priv, ICR | 8, AUXMR);
+
+ nec7210_board_online(nec_priv, board);
+
+ return 0;
+}
+
+int pc2a_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return pc2a_common_attach(board, config, pc2a_iosize, NEC7210);
+}
+
+int pc2a_cb7210_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return pc2a_common_attach(board, config, pc2a_iosize, CB7210);
+}
+
+int pc2_2a_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return pc2a_common_attach(board, config, pc2_2a_iosize, NAT4882);
+}
+
+static void pc2a_common_detach(gpib_board_t *board, unsigned int num_registers)
+{
+ int i;
+ struct pc2_priv *pc2_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (pc2_priv) {
+ nec_priv = &pc2_priv->nec7210_priv;
+#ifdef PC2_DMA
+ if (nec_priv->dma_channel)
+ free_dma(nec_priv->dma_channel);
+#endif
+ gpib_free_pseudo_irq(board);
+ if (pc2_priv->irq)
+ free_irq(pc2_priv->irq, board);
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ for (i = 0; i < num_registers; i++)
+ release_region((unsigned long)nec_priv->iobase +
+ i * pc2a_reg_offset, 1);
+ }
+ if (pc2_priv->clear_intr_addr)
+ release_region(pc2_priv->clear_intr_addr, 1);
+ if (nec_priv->dma_buffer) {
+ dma_free_coherent(board->dev, nec_priv->dma_buffer_length,
+ nec_priv->dma_buffer,
+ nec_priv->dma_buffer_addr);
+ nec_priv->dma_buffer = NULL;
+ }
+ }
+ free_private(board);
+}
+
+void pc2a_detach(gpib_board_t *board)
+{
+ pc2a_common_detach(board, pc2a_iosize);
+}
+
+void pc2_2a_detach(gpib_board_t *board)
+{
+ pc2a_common_detach(board, pc2_2a_iosize);
+}
+
+static int __init pc2_init_module(void)
+{
+ gpib_register_driver(&pc2_interface, THIS_MODULE);
+ gpib_register_driver(&pc2a_interface, THIS_MODULE);
+ gpib_register_driver(&pc2a_cb7210_interface, THIS_MODULE);
+ gpib_register_driver(&pc2_2a_interface, THIS_MODULE);
+
+ return 0;
+}
+
+static void __exit pc2_exit_module(void)
+{
+ gpib_unregister_driver(&pc2_interface);
+ gpib_unregister_driver(&pc2a_interface);
+ gpib_unregister_driver(&pc2a_cb7210_interface);
+ gpib_unregister_driver(&pc2_2a_interface);
+}
+
+module_init(pc2_init_module);
+module_exit(pc2_exit_module);
+
diff --git a/drivers/staging/gpib/tms9914/Makefile b/drivers/staging/gpib/tms9914/Makefile
new file mode 100644
index 000000000000..81b7e3cf104c
--- /dev/null
+++ b/drivers/staging/gpib/tms9914/Makefile
@@ -0,0 +1,6 @@
+
+obj-m += tms9914.o
+
+
+
+
diff --git a/drivers/staging/gpib/tms9914/tms9914.c b/drivers/staging/gpib/tms9914/tms9914.c
new file mode 100644
index 000000000000..152b243b845b
--- /dev/null
+++ b/drivers/staging/gpib/tms9914/tms9914.c
@@ -0,0 +1,910 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/dma.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+
+#include "gpibP.h"
+#include "tms9914.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB library for tms9914");
+
+static unsigned int update_status_nolock(gpib_board_t *board, struct tms9914_priv *priv);
+
+int tms9914_take_control(gpib_board_t *board, struct tms9914_priv *priv, int synchronous)
+{
+ int i;
+ const int timeout = 100;
+
+ if (synchronous)
+ write_byte(priv, AUX_TCS, AUXCR);
+ else
+ write_byte(priv, AUX_TCA, AUXCR);
+ // busy wait until ATN is asserted
+ for (i = 0; i < timeout; i++) {
+ if ((read_byte(priv, ADSR) & HR_ATN))
+ break;
+ udelay(1);
+ }
+ if (i == timeout)
+ return -ETIMEDOUT;
+
+ clear_bit(WRITE_READY_BN, &priv->state);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tms9914_take_control);
+
+/* The agilent 82350B has a buggy implementation of tcs which interferes with the
+ * operation of tca. It appears to be based on the controller state machine
+ * described in the TI 9900 TMS9914A data manual published in 1982. This
+ * manual describes tcs as putting the controller into a CWAS
+ * state where it waits indefinitely for ANRS and ignores tca. Since a
+ * functioning tca is far more important than tcs, we work around the
+ * problem by never issuing tcs.
+ *
+ * I don't know if this problem exists in the real tms9914a or just in the fpga
+ * of the 82350B. For now, only the agilent_82350b uses this workaround.
+ * The rest of the tms9914 based drivers still use tms9914_take_control
+ * directly (which does issue tcs).
+ */
+int tms9914_take_control_workaround(gpib_board_t *board, struct tms9914_priv *priv, int synchronous)
+{
+ if (synchronous)
+ return -ETIMEDOUT;
+ return tms9914_take_control(board, priv, synchronous);
+}
+EXPORT_SYMBOL_GPL(tms9914_take_control_workaround);
+
+int tms9914_go_to_standby(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ int i;
+ const int timeout = 1000;
+
+ write_byte(priv, AUX_GTS, AUXCR);
+ // busy wait until ATN is released
+ for (i = 0; i < timeout; i++) {
+ if ((read_byte(priv, ADSR) & HR_ATN) == 0)
+ break;
+ udelay(1);
+ }
+ if (i == timeout) {
+ pr_err("error waiting for NATN\n");
+ return -ETIMEDOUT;
+ }
+
+ clear_bit(COMMAND_READY_BN, &priv->state);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tms9914_go_to_standby);
+
+void tms9914_interface_clear(gpib_board_t *board, struct tms9914_priv *priv, int assert)
+{
+ if (assert) {
+ write_byte(priv, AUX_SIC | AUX_CS, AUXCR);
+
+ set_bit(CIC_NUM, &board->status);
+ } else {
+ write_byte(priv, AUX_SIC, AUXCR);
+ }
+}
+EXPORT_SYMBOL_GPL(tms9914_interface_clear);
+
+void tms9914_remote_enable(gpib_board_t *board, struct tms9914_priv *priv, int enable)
+{
+ if (enable)
+ write_byte(priv, AUX_SRE | AUX_CS, AUXCR);
+ else
+ write_byte(priv, AUX_SRE, AUXCR);
+}
+EXPORT_SYMBOL_GPL(tms9914_remote_enable);
+
+void tms9914_request_system_control(gpib_board_t *board, struct tms9914_priv *priv,
+ int request_control)
+{
+ if (request_control) {
+ write_byte(priv, AUX_RQC, AUXCR);
+ } else {
+ clear_bit(CIC_NUM, &board->status);
+ write_byte(priv, AUX_RLC, AUXCR);
+ }
+}
+EXPORT_SYMBOL_GPL(tms9914_request_system_control);
+
+unsigned int tms9914_t1_delay(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int nano_sec)
+{
+ static const int clock_period = 200; // assuming 5Mhz input clock
+ int num_cycles;
+
+ num_cycles = 12;
+
+ if (nano_sec <= 8 * clock_period) {
+ write_byte(priv, AUX_STDL | AUX_CS, AUXCR);
+ num_cycles = 8;
+ } else {
+ write_byte(priv, AUX_STDL, AUXCR);
+ }
+
+ if (nano_sec <= 4 * clock_period) {
+ write_byte(priv, AUX_VSTDL | AUX_CS, AUXCR);
+ num_cycles = 4;
+ } else {
+ write_byte(priv, AUX_VSTDL, AUXCR);
+ }
+
+ return num_cycles * clock_period;
+}
+EXPORT_SYMBOL_GPL(tms9914_t1_delay);
+
+void tms9914_return_to_local(const gpib_board_t *board, struct tms9914_priv *priv)
+{
+ write_byte(priv, AUX_RTL, AUXCR);
+}
+EXPORT_SYMBOL_GPL(tms9914_return_to_local);
+
+void tms9914_set_holdoff_mode(struct tms9914_priv *priv, enum tms9914_holdoff_mode mode)
+{
+ switch (mode) {
+ case TMS9914_HOLDOFF_NONE:
+ write_byte(priv, AUX_HLDE, AUXCR);
+ write_byte(priv, AUX_HLDA, AUXCR);
+ break;
+ case TMS9914_HOLDOFF_EOI:
+ write_byte(priv, AUX_HLDE | AUX_CS, AUXCR);
+ write_byte(priv, AUX_HLDA, AUXCR);
+ break;
+ case TMS9914_HOLDOFF_ALL:
+ write_byte(priv, AUX_HLDE, AUXCR);
+ write_byte(priv, AUX_HLDA | AUX_CS, AUXCR);
+ break;
+ default:
+ pr_err("%s: bug! bad holdoff mode %i\n", __func__, mode);
+ break;
+ }
+ priv->holdoff_mode = mode;
+}
+EXPORT_SYMBOL_GPL(tms9914_set_holdoff_mode);
+
+void tms9914_release_holdoff(struct tms9914_priv *priv)
+{
+ if (priv->holdoff_active) {
+ write_byte(priv, AUX_RHDF, AUXCR);
+ priv->holdoff_active = 0;
+ }
+}
+EXPORT_SYMBOL_GPL(tms9914_release_holdoff);
+
+int tms9914_enable_eos(gpib_board_t *board, struct tms9914_priv *priv, uint8_t eos_byte,
+ int compare_8_bits)
+{
+ priv->eos = eos_byte;
+ priv->eos_flags = REOS;
+ if (compare_8_bits)
+ priv->eos_flags |= BIN;
+ return 0;
+}
+EXPORT_SYMBOL(tms9914_enable_eos);
+
+void tms9914_disable_eos(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ priv->eos_flags &= ~REOS;
+}
+EXPORT_SYMBOL(tms9914_disable_eos);
+
+int tms9914_parallel_poll(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *result)
+{
+ // execute parallel poll
+ write_byte(priv, AUX_CS | AUX_RPP, AUXCR);
+ udelay(2);
+ *result = read_byte(priv, CPTR);
+ // clear parallel poll state
+ write_byte(priv, AUX_RPP, AUXCR);
+ return 0;
+}
+EXPORT_SYMBOL(tms9914_parallel_poll);
+
+static void set_ppoll_reg(struct tms9914_priv *priv, int enable,
+ unsigned int dio_line, int sense, int ist)
+{
+ u8 dio_byte;
+
+ if (enable && ((sense && ist) || (!sense && !ist))) {
+ dio_byte = 1 << (dio_line - 1);
+ write_byte(priv, dio_byte, PPR);
+ } else {
+ write_byte(priv, 0, PPR);
+ }
+}
+
+void tms9914_parallel_poll_configure(gpib_board_t *board,
+ struct tms9914_priv *priv, uint8_t config)
+{
+ priv->ppoll_enable = (config & PPC_DISABLE) == 0;
+ priv->ppoll_line = (config & PPC_DIO_MASK) + 1;
+ priv->ppoll_sense = (config & PPC_SENSE) != 0;
+ set_ppoll_reg(priv, priv->ppoll_enable, priv->ppoll_line, priv->ppoll_sense, board->ist);
+}
+EXPORT_SYMBOL(tms9914_parallel_poll_configure);
+
+void tms9914_parallel_poll_response(gpib_board_t *board,
+ struct tms9914_priv *priv, int ist)
+{
+ set_ppoll_reg(priv, priv->ppoll_enable, priv->ppoll_line, priv->ppoll_sense, ist);
+}
+EXPORT_SYMBOL(tms9914_parallel_poll_response);
+
+void tms9914_serial_poll_response(gpib_board_t *board, struct tms9914_priv *priv, uint8_t status)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ write_byte(priv, status, SPMR);
+ priv->spoll_status = status;
+ if (status & request_service_bit)
+ write_byte(priv, AUX_RSV2 | AUX_CS, AUXCR);
+ else
+ write_byte(priv, AUX_RSV2, AUXCR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+EXPORT_SYMBOL(tms9914_serial_poll_response);
+
+uint8_t tms9914_serial_poll_status(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ u8 status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ status = priv->spoll_status;
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return status;
+}
+EXPORT_SYMBOL(tms9914_serial_poll_status);
+
+int tms9914_primary_address(gpib_board_t *board, struct tms9914_priv *priv, unsigned int address)
+{
+ // put primary address in address0
+ write_byte(priv, address & ADDRESS_MASK, ADR);
+ return 0;
+}
+EXPORT_SYMBOL(tms9914_primary_address);
+
+int tms9914_secondary_address(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int address, int enable)
+{
+ if (enable)
+ priv->imr1_bits |= HR_APTIE;
+ else
+ priv->imr1_bits &= ~HR_APTIE;
+
+ write_byte(priv, priv->imr1_bits, IMR1);
+ return 0;
+}
+EXPORT_SYMBOL(tms9914_secondary_address);
+
+unsigned int tms9914_update_status(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int clear_mask)
+{
+ unsigned long flags;
+ unsigned int retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = update_status_nolock(board, priv);
+ board->status &= ~clear_mask;
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return retval;
+}
+EXPORT_SYMBOL(tms9914_update_status);
+
+static void update_talker_state(struct tms9914_priv *priv, unsigned int address_status_bits)
+{
+ if (address_status_bits & HR_TA) {
+ if (address_status_bits & HR_ATN)
+ priv->talker_state = talker_addressed;
+ else
+ /* this could also be serial_poll_active, but the tms9914 provides no
+ * way to distinguish, so we'll assume talker_active
+ */
+ priv->talker_state = talker_active;
+ } else {
+ priv->talker_state = talker_idle;
+ }
+}
+
+static void update_listener_state(struct tms9914_priv *priv, unsigned int address_status_bits)
+{
+ if (address_status_bits & HR_LA) {
+ if (address_status_bits & HR_ATN)
+ priv->listener_state = listener_addressed;
+ else
+ priv->listener_state = listener_active;
+ } else {
+ priv->listener_state = listener_idle;
+ }
+}
+
+static unsigned int update_status_nolock(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ int address_status;
+ int bsr_bits;
+
+ address_status = read_byte(priv, ADSR);
+
+ // check for remote/local
+ if (address_status & HR_REM)
+ set_bit(REM_NUM, &board->status);
+ else
+ clear_bit(REM_NUM, &board->status);
+ // check for lockout
+ if (address_status & HR_LLO)
+ set_bit(LOK_NUM, &board->status);
+ else
+ clear_bit(LOK_NUM, &board->status);
+ // check for ATN
+ if (address_status & HR_ATN)
+ set_bit(ATN_NUM, &board->status);
+ else
+ clear_bit(ATN_NUM, &board->status);
+ // check for talker/listener addressed
+ update_talker_state(priv, address_status);
+ if (priv->talker_state == talker_active || priv->talker_state == talker_addressed)
+ set_bit(TACS_NUM, &board->status);
+ else
+ clear_bit(TACS_NUM, &board->status);
+
+ update_listener_state(priv, address_status);
+ if (priv->listener_state == listener_active || priv->listener_state == listener_addressed)
+ set_bit(LACS_NUM, &board->status);
+ else
+ clear_bit(LACS_NUM, &board->status);
+ // Check for SRQI - not reset elsewhere except in autospoll
+ if (board->status & SRQI) {
+ bsr_bits = read_byte(priv, BSR);
+ if (!(bsr_bits & BSR_SRQ_BIT))
+ clear_bit(SRQI_NUM, &board->status);
+ }
+
+ dev_dbg(board->gpib_dev, "status 0x%lx, state 0x%lx\n", board->status, priv->state);
+
+ return board->status;
+}
+
+int tms9914_line_status(const gpib_board_t *board, struct tms9914_priv *priv)
+{
+ int bsr_bits;
+ int status = ValidALL;
+
+ bsr_bits = read_byte(priv, BSR);
+
+ if (bsr_bits & BSR_REN_BIT)
+ status |= BusREN;
+ if (bsr_bits & BSR_IFC_BIT)
+ status |= BusIFC;
+ if (bsr_bits & BSR_SRQ_BIT)
+ status |= BusSRQ;
+ if (bsr_bits & BSR_EOI_BIT)
+ status |= BusEOI;
+ if (bsr_bits & BSR_NRFD_BIT)
+ status |= BusNRFD;
+ if (bsr_bits & BSR_NDAC_BIT)
+ status |= BusNDAC;
+ if (bsr_bits & BSR_DAV_BIT)
+ status |= BusDAV;
+ if (bsr_bits & BSR_ATN_BIT)
+ status |= BusATN;
+
+ return status;
+}
+EXPORT_SYMBOL(tms9914_line_status);
+
+static int check_for_eos(struct tms9914_priv *priv, uint8_t byte)
+{
+ static const u8 seven_bit_compare_mask = 0x7f;
+
+ if ((priv->eos_flags & REOS) == 0)
+ return 0;
+
+ if (priv->eos_flags & BIN) {
+ if (priv->eos == byte)
+ return 1;
+ } else {
+ if ((priv->eos & seven_bit_compare_mask) == (byte & seven_bit_compare_mask))
+ return 1;
+ }
+ return 0;
+}
+
+static int wait_for_read_byte(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ if (wait_event_interruptible(board->wait,
+ test_bit(READ_READY_BN, &priv->state) ||
+ test_bit(DEV_CLEAR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_debug("gpib: pio read wait interrupted\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ return -ETIMEDOUT;
+
+ if (test_bit(DEV_CLEAR_BN, &priv->state))
+ return -EINTR;
+ return 0;
+}
+
+static inline uint8_t tms9914_read_data_in(gpib_board_t *board, struct tms9914_priv *priv, int *end)
+{
+ unsigned long flags;
+ u8 data;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ clear_bit(READ_READY_BN, &priv->state);
+ data = read_byte(priv, DIR);
+ if (test_and_clear_bit(RECEIVED_END_BN, &priv->state))
+ *end = 1;
+ else
+ *end = 0;
+ switch (priv->holdoff_mode) {
+ case TMS9914_HOLDOFF_EOI:
+ if (*end)
+ priv->holdoff_active = 1;
+ break;
+ case TMS9914_HOLDOFF_ALL:
+ priv->holdoff_active = 1;
+ break;
+ case TMS9914_HOLDOFF_NONE:
+ break;
+ default:
+ pr_err("%s: bug! bad holdoff mode %i\n", __func__, priv->holdoff_mode);
+ break;
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return data;
+}
+
+static int pio_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval = 0;
+
+ *bytes_read = 0;
+ *end = 0;
+ while (*bytes_read < length && *end == 0) {
+ tms9914_release_holdoff(priv);
+ retval = wait_for_read_byte(board, priv);
+ if (retval < 0)
+ return retval;
+ buffer[(*bytes_read)++] = tms9914_read_data_in(board, priv, end);
+
+ if (check_for_eos(priv, buffer[*bytes_read - 1]))
+ *end = 1;
+ }
+
+ return retval;
+}
+
+int tms9914_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval = 0;
+ size_t num_bytes;
+
+ *end = 0;
+ *bytes_read = 0;
+ if (length == 0)
+ return 0;
+
+ clear_bit(DEV_CLEAR_BN, &priv->state);
+
+ // transfer data (except for last byte)
+ if (length > 1) {
+ if (priv->eos_flags & REOS)
+ tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_ALL);
+ else
+ tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_EOI);
+ // PIO transfer
+ retval = pio_read(board, priv, buffer, length - 1, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ return retval;
+ buffer += num_bytes;
+ length -= num_bytes;
+ }
+ // read last bytes if we havn't received an END yet
+ if (*end == 0) {
+ // make sure we holdoff after last byte read
+ tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_ALL);
+ retval = pio_read(board, priv, buffer, length, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(tms9914_read);
+
+static int pio_write_wait(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ // wait until next byte is ready to be sent
+ if (wait_event_interruptible(board->wait,
+ test_bit(WRITE_READY_BN, &priv->state) ||
+ test_bit(BUS_ERROR_BN, &priv->state) ||
+ test_bit(DEV_CLEAR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted!\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ return -ETIMEDOUT;
+ if (test_bit(BUS_ERROR_BN, &priv->state))
+ return -EIO;
+ if (test_bit(DEV_CLEAR_BN, &priv->state))
+ return -EINTR;
+
+ return 0;
+}
+
+static int pio_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, size_t *bytes_written)
+{
+ ssize_t retval = 0;
+ unsigned long flags;
+
+ *bytes_written = 0;
+ while (*bytes_written < length) {
+ retval = pio_write_wait(board, priv);
+ if (retval < 0)
+ break;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ clear_bit(WRITE_READY_BN, &priv->state);
+ write_byte(priv, buffer[(*bytes_written)++], CDOR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ }
+ retval = pio_write_wait(board, priv);
+ if (retval < 0)
+ return retval;
+
+ return length;
+}
+
+int tms9914_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ ssize_t retval = 0;
+
+ *bytes_written = 0;
+ if (length == 0)
+ return 0;
+
+ clear_bit(BUS_ERROR_BN, &priv->state);
+ clear_bit(DEV_CLEAR_BN, &priv->state);
+
+ if (send_eoi)
+ length-- ; /* save the last byte for sending EOI */
+
+ if (length > 0) {
+ size_t num_bytes;
+ // PIO transfer
+ retval = pio_write(board, priv, buffer, length, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ if (send_eoi) {
+ size_t num_bytes;
+ /*send EOI */
+ write_byte(priv, AUX_SEOI, AUXCR);
+
+ retval = pio_write(board, priv, &buffer[*bytes_written], 1, &num_bytes);
+ *bytes_written += num_bytes;
+ }
+ return retval;
+}
+EXPORT_SYMBOL(tms9914_write);
+
+static void check_my_address_state(gpib_board_t *board, struct tms9914_priv *priv, int cmd_byte)
+{
+ if (cmd_byte == MLA(board->pad)) {
+ priv->primary_listen_addressed = 1;
+ // become active listener
+ if (board->sad < 0)
+ write_byte(priv, AUX_LON | AUX_CS, AUXCR);
+ } else if (board->sad >= 0 && priv->primary_listen_addressed &&
+ cmd_byte == MSA(board->sad)) {
+ // become active listener
+ write_byte(priv, AUX_LON | AUX_CS, AUXCR);
+ } else if (cmd_byte != MLA(board->pad) && (cmd_byte & 0xe0) == LAD) {
+ priv->primary_listen_addressed = 0;
+ } else if (cmd_byte == UNL) {
+ priv->primary_listen_addressed = 0;
+ write_byte(priv, AUX_LON, AUXCR);
+ } else if (cmd_byte == MTA(board->pad)) {
+ priv->primary_talk_addressed = 1;
+ if (board->sad < 0)
+ //make active talker
+ write_byte(priv, AUX_TON | AUX_CS, AUXCR);
+ } else if (board->sad >= 0 && priv->primary_talk_addressed &&
+ cmd_byte == MSA(board->sad)) {
+ // become active talker
+ write_byte(priv, AUX_TON | AUX_CS, AUXCR);
+ } else if (cmd_byte != MTA(board->pad) && (cmd_byte & 0xe0) == TAD) {
+ // Other Talk Address
+ priv->primary_talk_addressed = 0;
+ write_byte(priv, AUX_TON, AUXCR);
+ } else if (cmd_byte == UNT) {
+ priv->primary_talk_addressed = 0;
+ write_byte(priv, AUX_TON, AUXCR);
+ }
+}
+
+int tms9914_command(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, size_t *bytes_written)
+{
+ int retval = 0;
+ unsigned long flags;
+
+ *bytes_written = 0;
+ while (*bytes_written < length) {
+ if (wait_event_interruptible(board->wait,
+ test_bit(COMMAND_READY_BN,
+ &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_debug("gpib command wait interrupted\n");
+ break;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ break;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ clear_bit(COMMAND_READY_BN, &priv->state);
+ write_byte(priv, buffer[*bytes_written], CDOR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ check_my_address_state(board, priv, buffer[*bytes_written]);
+
+ ++(*bytes_written);
+ }
+ // wait until last command byte is written
+ if (wait_event_interruptible(board->wait,
+ test_bit(COMMAND_READY_BN,
+ &priv->state) || test_bit(TIMO_NUM, &board->status)))
+ retval = -ERESTARTSYS;
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+
+ return retval;
+}
+EXPORT_SYMBOL(tms9914_command);
+
+irqreturn_t tms9914_interrupt(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ int status0, status1;
+
+ // read interrupt status (also clears status)
+ status0 = read_byte(priv, ISR0);
+ status1 = read_byte(priv, ISR1);
+ return tms9914_interrupt_have_status(board, priv, status0, status1);
+}
+EXPORT_SYMBOL(tms9914_interrupt);
+
+irqreturn_t tms9914_interrupt_have_status(gpib_board_t *board, struct tms9914_priv *priv,
+ int status0, int status1)
+{
+ // record reception of END
+ if (status0 & HR_END)
+ set_bit(RECEIVED_END_BN, &priv->state);
+ // get incoming data in PIO mode
+ if ((status0 & HR_BI))
+ set_bit(READ_READY_BN, &priv->state);
+ if ((status0 & HR_BO)) {
+ if (read_byte(priv, ADSR) & HR_ATN)
+ set_bit(COMMAND_READY_BN, &priv->state);
+ else
+ set_bit(WRITE_READY_BN, &priv->state);
+ }
+
+ if (status0 & HR_SPAS) {
+ priv->spoll_status &= ~request_service_bit;
+ write_byte(priv, priv->spoll_status, SPMR);
+ //FIXME: set SPOLL status bit
+ }
+ // record service request in status
+ if (status1 & HR_SRQ)
+ set_bit(SRQI_NUM, &board->status);
+ // have been addressed (with secondary addressing disabled)
+ if (status1 & HR_MA)
+ // clear dac holdoff
+ write_byte(priv, AUX_VAL, AUXCR);
+ // unrecognized command received
+ if (status1 & HR_UNC) {
+ unsigned short command_byte = read_byte(priv, CPTR) & gpib_command_mask;
+
+ switch (command_byte) {
+ case PPConfig:
+ priv->ppoll_configure_state = 1;
+ /* AUX_PTS generates another UNC interrupt on the next command byte
+ * if it is in the secondary address group (such as PPE and PPD).
+ */
+ write_byte(priv, AUX_PTS, AUXCR);
+ write_byte(priv, AUX_VAL, AUXCR);
+ break;
+ case PPU:
+ tms9914_parallel_poll_configure(board, priv, command_byte);
+ write_byte(priv, AUX_VAL, AUXCR);
+ break;
+ default:
+ if (is_PPE(command_byte) || is_PPD(command_byte)) {
+ if (priv->ppoll_configure_state) {
+ tms9914_parallel_poll_configure(board, priv, command_byte);
+ write_byte(priv, AUX_VAL, AUXCR);
+ } else {// bad parallel poll configure byte
+ // clear dac holdoff
+ write_byte(priv, AUX_INVAL, AUXCR);
+ }
+ } else {
+ // printk("tms9914: unrecognized gpib command pass thru 0x%x\n",
+ // command_byte);
+ // clear dac holdoff
+ write_byte(priv, AUX_INVAL, AUXCR);
+ }
+ break;
+ }
+
+ if (in_primary_command_group(command_byte) && command_byte != PPConfig)
+ priv->ppoll_configure_state = 0;
+ }
+
+ if (status1 & HR_ERR) {
+ dev_dbg(board->gpib_dev, "gpib bus error\n");
+ set_bit(BUS_ERROR_BN, &priv->state);
+ }
+
+ if (status1 & HR_IFC) {
+ push_gpib_event(board, EventIFC);
+ clear_bit(CIC_NUM, &board->status);
+ }
+
+ if (status1 & HR_GET) {
+ push_gpib_event(board, EventDevTrg);
+ // clear dac holdoff
+ write_byte(priv, AUX_VAL, AUXCR);
+ }
+
+ if (status1 & HR_DCAS) {
+ push_gpib_event(board, EventDevClr);
+ // clear dac holdoff
+ write_byte(priv, AUX_VAL, AUXCR);
+ set_bit(DEV_CLEAR_BN, &priv->state);
+ }
+
+ // check for being addressed with secondary addressing
+ if (status1 & HR_APT) {
+ if (board->sad < 0)
+ pr_err("tms9914: bug, APT interrupt without secondary addressing?\n");
+ if ((read_byte(priv, CPTR) & gpib_command_mask) == MSA(board->sad))
+ write_byte(priv, AUX_VAL, AUXCR);
+ else
+ write_byte(priv, AUX_INVAL, AUXCR);
+ }
+
+ if ((status0 & priv->imr0_bits) || (status1 & priv->imr1_bits)) {
+// dev_dbg(board->gpib_dev, "isr0 0x%x, imr0 0x%x, isr1 0x%x, imr1 0x%x\n",
+// status0, priv->imr0_bits, status1, priv->imr1_bits);
+ update_status_nolock(board, priv);
+ wake_up_interruptible(&board->wait);
+ }
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(tms9914_interrupt_have_status);
+
+void tms9914_board_reset(struct tms9914_priv *priv)
+{
+ /* chip reset */
+ write_byte(priv, AUX_CHIP_RESET | AUX_CS, AUXCR);
+
+ /* disable all interrupts */
+ priv->imr0_bits = 0;
+ write_byte(priv, priv->imr0_bits, IMR0);
+ priv->imr1_bits = 0;
+ write_byte(priv, priv->imr1_bits, IMR1);
+ write_byte(priv, AUX_DAI | AUX_CS, AUXCR);
+
+ /* clear registers by reading */
+ read_byte(priv, CPTR);
+ read_byte(priv, ISR0);
+ read_byte(priv, ISR1);
+
+ write_byte(priv, 0, SPMR);
+
+ /* parallel poll unconfigure */
+ write_byte(priv, 0, PPR);
+ // request for data holdoff
+ tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_ALL);
+}
+EXPORT_SYMBOL_GPL(tms9914_board_reset);
+
+void tms9914_online(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ /* set GPIB address */
+ tms9914_primary_address(board, priv, board->pad);
+ tms9914_secondary_address(board, priv, board->sad, board->sad >= 0);
+
+ // enable tms9914 interrupts
+ priv->imr0_bits |= HR_MACIE | HR_RLCIE | HR_ENDIE | HR_BOIE | HR_BIIE |
+ HR_SPASIE;
+ priv->imr1_bits |= HR_MAIE | HR_SRQIE | HR_UNCIE | HR_ERRIE | HR_IFCIE |
+ HR_GETIE | HR_DCASIE;
+ write_byte(priv, priv->imr0_bits, IMR0);
+ write_byte(priv, priv->imr1_bits, IMR1);
+ write_byte(priv, AUX_DAI, AUXCR);
+
+ // turn off reset state
+ write_byte(priv, AUX_CHIP_RESET, AUXCR);
+}
+EXPORT_SYMBOL_GPL(tms9914_online);
+
+#ifdef CONFIG_HAS_IOPORT
+// wrapper for inb
+uint8_t tms9914_ioport_read_byte(struct tms9914_priv *priv, unsigned int register_num)
+{
+ return inb((unsigned long)(priv->iobase) + register_num * priv->offset);
+}
+EXPORT_SYMBOL_GPL(tms9914_ioport_read_byte);
+
+// wrapper for outb
+void tms9914_ioport_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num)
+{
+ outb(data, (unsigned long)(priv->iobase) + register_num * priv->offset);
+ if (register_num == AUXCR)
+ udelay(1);
+}
+EXPORT_SYMBOL_GPL(tms9914_ioport_write_byte);
+#endif
+
+// wrapper for readb
+uint8_t tms9914_iomem_read_byte(struct tms9914_priv *priv, unsigned int register_num)
+{
+ return readb(priv->iobase + register_num * priv->offset);
+}
+EXPORT_SYMBOL_GPL(tms9914_iomem_read_byte);
+
+// wrapper for writeb
+void tms9914_iomem_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num)
+{
+ writeb(data, priv->iobase + register_num * priv->offset);
+ if (register_num == AUXCR)
+ udelay(1);
+}
+EXPORT_SYMBOL_GPL(tms9914_iomem_write_byte);
+
+static int __init tms9914_init_module(void)
+{
+ return 0;
+}
+
+static void __exit tms9914_exit_module(void)
+{
+}
+
+module_init(tms9914_init_module);
+module_exit(tms9914_exit_module);
+
diff --git a/drivers/staging/gpib/tnt4882/Makefile b/drivers/staging/gpib/tnt4882/Makefile
new file mode 100644
index 000000000000..f767c990db7a
--- /dev/null
+++ b/drivers/staging/gpib/tnt4882/Makefile
@@ -0,0 +1,7 @@
+ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA
+obj-m += tnt4882.o
+
+tnt4882-objs := tnt4882_gpib.o mite.o
+
+
+
diff --git a/drivers/staging/gpib/tnt4882/mite.c b/drivers/staging/gpib/tnt4882/mite.c
new file mode 100644
index 000000000000..0edf34d243e9
--- /dev/null
+++ b/drivers/staging/gpib/tnt4882/mite.c
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2
+
+/*
+ * Hardware driver for NI Mite PCI interface chip,
+ * adapted from COMEDI
+ *
+ * Copyright (C) 1997-8 David A. Schleef
+ * Copyright (C) 2002 Frank Mori Hess
+ *
+ * The PCI-MIO E series driver was originally written by
+ * Tomasz Motylewski <...>, and ported to comedi by ds.
+ *
+ * References for specifications:
+ *
+ * 321747b.pdf Register Level Programmer Manual (obsolete)
+ * 321747c.pdf Register Level Programmer Manual (new)
+ * DAQ-STC reference manual
+ *
+ * Other possibly relevant info:
+ *
+ * 320517c.pdf User manual (obsolete)
+ * 320517f.pdf User manual (new)
+ * 320889a.pdf delete
+ * 320906c.pdf maximum signal ratings
+ * 321066a.pdf about 16x
+ * 321791a.pdf discontinuation of at-mio-16e-10 rev. c
+ * 321808a.pdf about at-mio-16e-10 rev P
+ * 321837a.pdf discontinuation of at-mio-16de-10 rev d
+ * 321838a.pdf about at-mio-16de-10 rev N
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "mite.h"
+
+#define PCI_MITE_SIZE 4096
+#define PCI_DAQ_SIZE 4096
+
+struct mite_struct *mite_devices;
+
+#define TOP_OF_PAGE(x) ((x) | (~(PAGE_MASK)))
+
+void mite_init(void)
+{
+ struct pci_dev *pcidev;
+ struct mite_struct *mite;
+
+ for (pcidev = pci_get_device(PCI_VENDOR_ID_NATINST, PCI_ANY_ID, NULL);
+ pcidev;
+ pcidev = pci_get_device(PCI_VENDOR_ID_NATINST, PCI_ANY_ID, pcidev)) {
+ mite = kzalloc(sizeof(*mite), GFP_KERNEL);
+ if (!mite)
+ return;
+
+ mite->pcidev = pcidev;
+ pci_dev_get(mite->pcidev);
+ mite->next = mite_devices;
+ mite_devices = mite;
+ }
+}
+
+int mite_setup(struct mite_struct *mite)
+{
+ u32 addr;
+
+ if (pci_enable_device(mite->pcidev)) {
+ pr_err("mite: error enabling mite.\n");
+ return -EIO;
+ }
+ pci_set_master(mite->pcidev);
+ if (pci_request_regions(mite->pcidev, "mite")) {
+ pr_err("mite: failed to request mite io regions.\n");
+ return -EIO;
+ }
+ addr = pci_resource_start(mite->pcidev, 0);
+ mite->mite_phys_addr = addr;
+ mite->mite_io_addr = ioremap(addr, pci_resource_len(mite->pcidev, 0));
+ if (!mite->mite_io_addr) {
+ pr_err("mite: failed to remap mite io memory address.\n");
+ return -ENOMEM;
+ }
+ pr_info("mite: 0x%08lx mapped to %p\n", mite->mite_phys_addr, mite->mite_io_addr);
+ addr = pci_resource_start(mite->pcidev, 1);
+ mite->daq_phys_addr = addr;
+ mite->daq_io_addr = ioremap(mite->daq_phys_addr, pci_resource_len(mite->pcidev, 1));
+ if (!mite->daq_io_addr) {
+ pr_err("mite: failed to remap daq io memory address.\n");
+ return -ENOMEM;
+ }
+ pr_info("mite: daq: 0x%08lx mapped to %p\n", mite->daq_phys_addr, mite->daq_io_addr);
+ writel(mite->daq_phys_addr | WENAB, mite->mite_io_addr + MITE_IODWBSR);
+ mite->used = 1;
+ return 0;
+}
+
+void mite_cleanup(void)
+{
+ struct mite_struct *mite, *next;
+
+ for (mite = mite_devices; mite; mite = next) {
+ next = mite->next;
+ if (mite->pcidev)
+ pci_dev_put(mite->pcidev);
+ kfree(mite);
+ }
+}
+
+void mite_unsetup(struct mite_struct *mite)
+{
+ if (!mite)
+ return;
+ if (mite->mite_io_addr) {
+ iounmap(mite->mite_io_addr);
+ mite->mite_io_addr = NULL;
+ }
+ if (mite->daq_io_addr) {
+ iounmap(mite->daq_io_addr);
+ mite->daq_io_addr = NULL;
+ }
+ if (mite->mite_phys_addr) {
+ pci_release_regions(mite->pcidev);
+ pci_disable_device(mite->pcidev);
+ mite->mite_phys_addr = 0;
+ }
+ mite->used = 0;
+}
+
+void mite_list_devices(void)
+{
+ struct mite_struct *mite, *next;
+
+ pr_info("Available NI PCI device IDs:");
+ if (mite_devices)
+ for (mite = mite_devices; mite; mite = next) {
+ next = mite->next;
+ pr_info(" 0x%04x", mite_device_id(mite));
+ if (mite->used)
+ pr_info("(used)");
+ }
+ pr_info("\n");
+}
+
+int mite_bytes_transferred(struct mite_struct *mite, int chan)
+{
+ int dar, fcr;
+
+ dar = readl(mite->mite_io_addr + MITE_DAR + CHAN_OFFSET(chan));
+ fcr = readl(mite->mite_io_addr + MITE_FCR + CHAN_OFFSET(chan)) & 0x000000FF;
+ return dar - fcr;
+}
+
+int mite_dma_tcr(struct mite_struct *mite)
+{
+ int tcr;
+ int lkar;
+
+ lkar = readl(mite->mite_io_addr + CHAN_OFFSET(0) + MITE_LKAR);
+ tcr = readl(mite->mite_io_addr + CHAN_OFFSET(0) + MITE_TCR);
+ MDPRINTK("lkar=0x%08x tcr=%d\n", lkar, tcr);
+
+ return tcr;
+}
+
+void mite_dma_disarm(struct mite_struct *mite)
+{
+ int chor;
+
+ /* disarm */
+ chor = CHOR_ABORT;
+ writel(chor, mite->mite_io_addr + CHAN_OFFSET(0) + MITE_CHOR);
+}
+
+void mite_dump_regs(struct mite_struct *mite)
+{
+ void *addr = 0;
+ unsigned long temp = 0;
+
+ pr_info("mite address is =0x%p\n", mite->mite_io_addr);
+
+ addr = mite->mite_io_addr + MITE_CHOR + CHAN_OFFSET(0);
+ pr_info("mite status[CHOR]at 0x%p =0x%08lx\n", addr, temp = readl(addr));
+ //mite_decode(mite_CHOR_strings,temp);
+ addr = mite->mite_io_addr + MITE_CHCR + CHAN_OFFSET(0);
+ pr_info("mite status[CHCR]at 0x%p =0x%08lx\n", addr, temp = readl(addr));
+ //mite_decode(mite_CHCR_strings,temp);
+ addr = mite->mite_io_addr + MITE_TCR + CHAN_OFFSET(0);
+ pr_info("mite status[TCR] at 0x%p =0x%08x\n", addr, readl(addr));
+ addr = mite->mite_io_addr + MITE_MCR + CHAN_OFFSET(0);
+ pr_info("mite status[MCR] at 0x%p =0x%08lx\n", addr, temp = readl(addr));
+ //mite_decode(mite_MCR_strings,temp);
+ addr = mite->mite_io_addr + MITE_MAR + CHAN_OFFSET(0);
+ pr_info("mite status[MAR] at 0x%p =0x%08x\n", addr, readl(addr));
+ addr = mite->mite_io_addr + MITE_DCR + CHAN_OFFSET(0);
+ pr_info("mite status[DCR] at 0x%p =0x%08lx\n", addr, temp = readl(addr));
+ //mite_decode(mite_CR_strings,temp);
+ addr = mite->mite_io_addr + MITE_DAR + CHAN_OFFSET(0);
+ pr_info("mite status[DAR] at 0x%p =0x%08x\n", addr, readl(addr));
+ addr = mite->mite_io_addr + MITE_LKCR + CHAN_OFFSET(0);
+ pr_info("mite status[LKCR]at 0x%p =0x%08lx\n", addr, temp = readl(addr));
+ //mite_decode(mite_CR_strings,temp);
+ addr = mite->mite_io_addr + MITE_LKAR + CHAN_OFFSET(0);
+ pr_info("mite status[LKAR]at 0x%p =0x%08x\n", addr, readl(addr));
+
+ addr = mite->mite_io_addr + MITE_CHSR + CHAN_OFFSET(0);
+ pr_info("mite status[CHSR]at 0x%p =0x%08lx\n", addr, temp = readl(addr));
+ //mite_decode(mite_CHSR_strings,temp);
+ addr = mite->mite_io_addr + MITE_FCR + CHAN_OFFSET(0);
+ pr_info("mite status[FCR] at 0x%p =0x%08x\n\n", addr, readl(addr));
+}
+
diff --git a/drivers/staging/gpib/tnt4882/mite.h b/drivers/staging/gpib/tnt4882/mite.h
new file mode 100644
index 000000000000..6454d069b8cc
--- /dev/null
+++ b/drivers/staging/gpib/tnt4882/mite.h
@@ -0,0 +1,243 @@
+/* SPDX-License-Identifier: GPL-2 */
+
+/*
+ * Hardware driver for NI Mite PCI interface chip
+ *
+ * Copyright (C) 1999 David A. Schleef <ds@stm.lbl.gov>
+ */
+
+#ifndef _MITE_H_
+#define _MITE_H_
+
+#include <linux/pci.h>
+
+#define PCI_VENDOR_ID_NATINST 0x1093
+
+//#define DEBUG_MITE
+
+#ifdef DEBUG_MITE
+#define MDPRINTK(format, args...) pr_debug(format, ## args)
+#else
+#define MDPRINTK(args...)
+#endif
+
+#define MITE_RING_SIZE 3000
+struct mite_dma_chain {
+ u32 count;
+ u32 addr;
+ u32 next;
+};
+
+struct mite_struct {
+ struct mite_struct *next;
+ int used;
+
+ struct pci_dev *pcidev;
+ unsigned long mite_phys_addr;
+ void *mite_io_addr;
+ unsigned long daq_phys_addr;
+ void *daq_io_addr;
+
+ int DMA_CheckNearEnd;
+
+ struct mite_dma_chain ring[MITE_RING_SIZE];
+};
+
+extern struct mite_struct *mite_devices;
+
+extern inline unsigned int mite_irq(struct mite_struct *mite)
+{
+ return mite->pcidev->irq;
+};
+
+extern inline unsigned int mite_device_id(struct mite_struct *mite)
+{
+ return mite->pcidev->device;
+};
+
+void mite_init(void);
+void mite_cleanup(void);
+int mite_setup(struct mite_struct *mite);
+void mite_unsetup(struct mite_struct *mite);
+void mite_list_devices(void);
+
+int mite_dma_tcr(struct mite_struct *mite);
+
+void mite_dma_arm(struct mite_struct *mite);
+void mite_dma_disarm(struct mite_struct *mite);
+
+void mite_dump_regs(struct mite_struct *mite);
+void mite_setregs(struct mite_struct *mite, unsigned long ll_start, int chan, int dir);
+int mite_bytes_transferred(struct mite_struct *mite, int chan);
+
+#define CHAN_OFFSET(x) (0x100 * (x))
+
+/* DMA base for chan 0 is 0x500, chan 1 is 0x600 */
+
+#define MITE_CHOR 0x500
+#define CHOR_DMARESET BIT(31)
+#define CHOR_SET_SEND_TC BIT(11)
+#define CHOR_CLR_SEND_TC BIT(10)
+#define CHOR_SET_LPAUSE BIT(9)
+#define CHOR_CLR_LPAUSE BIT(8)
+#define CHOR_CLRDONE BIT(7)
+#define CHOR_CLRRB BIT(6)
+#define CHOR_CLRLC BIT(5)
+#define CHOR_FRESET BIT(4)
+#define CHOR_ABORT BIT(3)
+#define CHOR_STOP BIT(2)
+#define CHOR_CONT BIT(1)
+#define CHOR_START BIT(0)
+#define CHOR_PON (CHOR_CLR_SEND_TC | CHOR_CLR_LPAUSE)
+
+#define MITE_CHCR 0x504
+#define CHCR_SET_DMA_IE BIT(31)
+#define CHCR_CLR_DMA_IE BIT(30)
+#define CHCR_SET_LINKP_IE BIT(29)
+#define CHCR_CLR_LINKP_IE BIT(28)
+#define CHCR_SET_SAR_IE BIT(27)
+#define CHCR_CLR_SAR_IE BIT(26)
+#define CHCR_SET_DONE_IE BIT(25)
+#define CHCR_CLR_DONE_IE BIT(24)
+#define CHCR_SET_MRDY_IE BIT(23)
+#define CHCR_CLR_MRDY_IE BIT(22)
+#define CHCR_SET_DRDY_IE BIT(21)
+#define CHCR_CLR_DRDY_IE BIT(20)
+#define CHCR_SET_LC_IE BIT(19)
+#define CHCR_CLR_LC_IE BIT(18)
+#define CHCR_SET_CONT_RB_IE BIT(17)
+#define CHCR_CLR_CONT_RB_IE BIT(16)
+#define CHCR_FIFODIS BIT(15)
+#define CHCR_FIFO_ON 0
+#define CHCR_BURSTEN BIT(14)
+#define CHCR_NO_BURSTEN 0
+#define CHCR_NFTP(x) ((x) << 11)
+#define CHCR_NFTP0 CHCR_NFTP(0)
+#define CHCR_NFTP1 CHCR_NFTP(1)
+#define CHCR_NFTP2 CHCR_NFTP(2)
+#define CHCR_NFTP4 CHCR_NFTP(3)
+#define CHCR_NFTP8 CHCR_NFTP(4)
+#define CHCR_NFTP16 CHCR_NFTP(5)
+#define CHCR_NETP(x) ((x) << 11)
+#define CHCR_NETP0 CHCR_NETP(0)
+#define CHCR_NETP1 CHCR_NETP(1)
+#define CHCR_NETP2 CHCR_NETP(2)
+#define CHCR_NETP4 CHCR_NETP(3)
+#define CHCR_NETP8 CHCR_NETP(4)
+#define CHCR_CHEND1 BIT(5)
+#define CHCR_CHEND0 BIT(4)
+#define CHCR_DIR BIT(3)
+#define CHCR_DEV_TO_MEM CHCR_DIR
+#define CHCR_MEM_TO_DEV 0
+#define CHCR_NORMAL ((0) << 0)
+#define CHCR_CONTINUE ((1) << 0)
+#define CHCR_RINGBUFF ((2) << 0)
+#define CHCR_LINKSHORT ((4) << 0)
+#define CHCR_LINKLONG ((5) << 0)
+#define CHCRPON (CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE | CHCR_CLR_SAR_IE | \
+ CHCR_CLR_DONE_IE | CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE | \
+ CHCR_CLR_LC_IE | CHCR_CLR_CONT_IE)
+
+#define MITE_TCR 0x508
+
+/* CR bits */
+#define CR_RL(x) ((x) << 21)
+#define CR_RL0 CR_RL(0)
+#define CR_RL1 CR_RL(1)
+#define CR_RL2 CR_RL(2)
+#define CR_RL4 CR_RL(3)
+#define CR_RL8 CR_RL(4)
+#define CR_RL16 CR_RL(5)
+#define CR_RL32 CR_RL(6)
+#define CR_RL64 CR_RL(7)
+#define CR_RD(x) ((x) << 19)
+#define CR_RD0 CR_RD(0)
+#define CR_RD32 CR_RD(1)
+#define CR_RD512 CR_RD(2)
+#define CR_RD8192 CR_RD(3)
+#define CR_REQS(x) ((x) << 16)
+#define CR_REQSDRQ0 CR_REQS(4)
+#define CR_REQSDRQ1 CR_REQS(5)
+#define CR_REQSDRQ2 CR_REQS(6)
+#define CR_REQSDRQ3 CR_REQS(7)
+#define CR_ASEQX(x) ((x) << 10)
+#define CR_ASEQX0 CR_ASEQX(0)
+#define CR_ASEQDONT CR_ASEQX0
+#define CR_ASEQXP1 CR_ASEQX(1)
+#define CR_ASEQUP CR_ASEQXP1
+#define CR_ASEQXP2 CR_ASEQX(2)
+#define CR_ASEQDOWN CR_ASEQXP2
+#define CR_ASEQXP4 CR_ASEQX(3)
+#define CR_ASEQXP8 CR_ASEQX(4)
+#define CR_ASEQXP16 CR_ASEQX(5)
+#define CR_ASEQXP32 CR_ASEQX(6)
+#define CR_ASEQXP64 CR_ASEQX(7)
+#define CR_ASEQXM1 CR_ASEQX(9)
+#define CR_ASEQXM2 CR_ASEQX(10)
+#define CR_ASEQXM4 CR_ASEQX(11)
+#define CR_ASEQXM8 CR_ASEQX(12)
+#define CR_ASEQXM16 CR_ASEQX(13)
+#define CR_ASEQXM32 CR_ASEQX(14)
+#define CR_ASEQXM64 CR_ASEQX(15)
+#define CR_PSIZEBYTE BIT(8)
+#define CR_PSIZEHALF (2 << 8)
+#define CR_PSIZEWORD (3 << 8)
+#define CR_PORTCPU (0 << 6)
+#define CR_PORTIO BIT(6)
+#define CR_PORTVXI (2 << 6)
+#define CR_PORTMXI (3 << 6)
+#define CR_AMDEVICE BIT(0)
+
+#define CHSR_INT 0x80000000
+#define CHSR_DONE 0x02000000
+#define CHSR_LINKC 0x00080000
+
+#define MITE_MCR 0x50c
+#define MCRPON 0
+
+#define MITE_MAR 0x510
+
+#define MITE_DCR 0x514
+#define DCR_NORMAL BIT(29)
+#define DCRPON 0
+
+#define MITE_DAR 0x518
+
+#define MITE_LKCR 0x51c
+
+#define MITE_LKAR 0x520
+#define MITE_LLKAR 0x524
+#define MITE_BAR 0x528
+#define MITE_BCR 0x52c
+#define MITE_SAR 0x530
+#define MITE_WSCR 0x534
+#define MITE_WSER 0x538
+#define MITE_CHSR 0x53c
+#define MITE_FCR 0x540
+
+#define MITE_FIFO 0x80
+#define MITE_FIFOEND 0xff
+
+#define MITE_AMRAM 0x00
+#define MITE_AMDEVICE 0x01
+#define MITE_AMHOST_A32_SINGLE 0x09
+#define MITE_AMHOST_A24_SINGLE 0x39
+#define MITE_AMHOST_A16_SINGLE 0x29
+#define MITE_AMHOST_A32_BLOCK 0x0b
+#define MITE_AMHOST_A32D64_BLOCK 0x08
+#define MITE_AMHOST_A24_BLOCK 0x3b
+
+enum mite_registers {
+ MITE_IODWBSR = 0xc0, //IO Device Window Base Size Register
+ MITE_CSIGR = 0x460, //chip signature
+ MITE_IODWBSR_1 = 0xc4, // IO Device Window Base Size Register 1 (used by 6602 boards)
+ MITE_IODWCR_1 = 0xf4
+};
+
+enum MITE_IODWBSR_bits {
+ WENAB = 0x80, // window enable
+ WENAB_6602 = 0x8c // window enable for 6602 boards
+};
+
+#endif
+
diff --git a/drivers/staging/gpib/tnt4882/tnt4882_gpib.c b/drivers/staging/gpib/tnt4882/tnt4882_gpib.c
new file mode 100644
index 000000000000..e49a952fa0d8
--- /dev/null
+++ b/drivers/staging/gpib/tnt4882/tnt4882_gpib.c
@@ -0,0 +1,1874 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * National Instruments boards using tnt4882 or compatible chips (at-gpib, etc).
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/isapnp.h>
+
+#include "nec7210.h"
+#include "gpibP.h"
+#include "mite.h"
+#include "tnt4882_registers.h"
+
+static const int ISAPNP_VENDOR_ID_NI = ISAPNP_VENDOR('N', 'I', 'C');
+static const int ISAPNP_ID_NI_ATGPIB_TNT = 0xc601;
+enum {
+ PCI_DEVICE_ID_NI_GPIB = 0xc801,
+ PCI_DEVICE_ID_NI_GPIB_PLUS = 0xc811,
+ PCI_DEVICE_ID_NI_GPIB_PLUS2 = 0x71ad,
+ PCI_DEVICE_ID_NI_PXIGPIB = 0xc821,
+ PCI_DEVICE_ID_NI_PMCGPIB = 0xc831,
+ PCI_DEVICE_ID_NI_PCIEGPIB = 0x70cf,
+ PCI_DEVICE_ID_NI_PCIE2GPIB = 0x710e,
+// Measurement Computing PCI-488 same design as PCI-GPIB with TNT5004
+ PCI_DEVICE_ID_MC_PCI488 = 0x7259,
+ PCI_DEVICE_ID_CEC_NI_GPIB = 0x7258
+};
+
+// struct which defines private_data for tnt4882 devices
+struct tnt4882_priv {
+ struct nec7210_priv nec7210_priv;
+ struct mite_struct *mite;
+ struct pnp_dev *pnp_dev;
+ unsigned int irq;
+ unsigned short imr0_bits;
+ unsigned short imr3_bits;
+ unsigned short auxg_bits; // bits written to auxiliary register G
+ void (*io_writeb)(unsigned int value, void *address);
+ void (*io_writew)(unsigned int value, void *address);
+ unsigned int (*io_readb)(void *address);
+ unsigned int (*io_readw)(void *address);
+};
+
+// interface functions
+static int tnt4882_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read);
+static int tnt4882_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read);
+static int tnt4882_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+static int tnt4882_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+static int tnt4882_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written);
+static int tnt4882_command_unaccel(gpib_board_t *board, uint8_t *buffer,
+ size_t length, size_t *bytes_written);
+static int tnt4882_take_control(gpib_board_t *board, int synchronous);
+static int tnt4882_go_to_standby(gpib_board_t *board);
+static void tnt4882_request_system_control(gpib_board_t *board, int request_control);
+static void tnt4882_interface_clear(gpib_board_t *board, int assert);
+static void tnt4882_remote_enable(gpib_board_t *board, int enable);
+static int tnt4882_enable_eos(gpib_board_t *board, uint8_t eos_byte, int
+ compare_8_bits);
+static void tnt4882_disable_eos(gpib_board_t *board);
+static unsigned int tnt4882_update_status(gpib_board_t *board, unsigned int clear_mask);
+static int tnt4882_primary_address(gpib_board_t *board, unsigned int address);
+static int tnt4882_secondary_address(gpib_board_t *board, unsigned int address,
+ int enable);
+static int tnt4882_parallel_poll(gpib_board_t *board, uint8_t *result);
+static void tnt4882_parallel_poll_configure(gpib_board_t *board, uint8_t config);
+static void tnt4882_parallel_poll_response(gpib_board_t *board, int ist);
+static void tnt4882_serial_poll_response(gpib_board_t *board, uint8_t status);
+static uint8_t tnt4882_serial_poll_status(gpib_board_t *board);
+static int tnt4882_line_status(const gpib_board_t *board);
+static unsigned int tnt4882_t1_delay(gpib_board_t *board, unsigned int nano_sec);
+static void tnt4882_return_to_local(gpib_board_t *board);
+
+// interrupt service routines
+static irqreturn_t tnt4882_internal_interrupt(gpib_board_t *board);
+static irqreturn_t tnt4882_interrupt(int irq, void *arg);
+
+// utility functions
+static int tnt4882_allocate_private(gpib_board_t *board);
+static void tnt4882_free_private(gpib_board_t *board);
+static void tnt4882_init(struct tnt4882_priv *tnt_priv, const gpib_board_t *board);
+static void tnt4882_board_reset(struct tnt4882_priv *tnt_priv, gpib_board_t *board);
+
+// register offset for nec7210 compatible registers
+static const int atgpib_reg_offset = 2;
+
+// number of ioports used
+static const int atgpib_iosize = 32;
+
+/* paged io */
+static inline unsigned int tnt_paged_readb(struct tnt4882_priv *priv, unsigned long offset)
+{
+ priv->io_writeb(AUX_PAGEIN, priv->nec7210_priv.iobase + AUXMR * priv->nec7210_priv.offset);
+ udelay(1);
+ return priv->io_readb(priv->nec7210_priv.iobase + offset);
+}
+
+static inline void tnt_paged_writeb(struct tnt4882_priv *priv, unsigned int value,
+ unsigned long offset)
+{
+ priv->io_writeb(AUX_PAGEIN, priv->nec7210_priv.iobase + AUXMR * priv->nec7210_priv.offset);
+ udelay(1);
+ priv->io_writeb(value, priv->nec7210_priv.iobase + offset);
+}
+
+/* readb/writeb wrappers */
+static inline unsigned short tnt_readb(struct tnt4882_priv *priv, unsigned long offset)
+{
+ void *address = priv->nec7210_priv.iobase + offset;
+ unsigned long flags;
+ unsigned short retval;
+ spinlock_t *register_lock = &priv->nec7210_priv.register_page_lock;
+
+ spin_lock_irqsave(register_lock, flags);
+ switch (offset) {
+ case CSR:
+ case SASR:
+ case ISR0:
+ case BSR:
+ switch (priv->nec7210_priv.type) {
+ case TNT4882:
+ case TNT5004:
+ retval = priv->io_readb(address);
+ break;
+ case NAT4882:
+ retval = tnt_paged_readb(priv, offset - tnt_pagein_offset);
+ break;
+ case NEC7210:
+ retval = 0;
+ break;
+ default:
+ pr_err("tnt4882: bug! unsupported ni_chipset\n");
+ retval = 0;
+ break;
+ }
+ break;
+ default:
+ retval = priv->io_readb(address);
+ break;
+ }
+ spin_unlock_irqrestore(register_lock, flags);
+ return retval;
+}
+
+static inline void tnt_writeb(struct tnt4882_priv *priv, unsigned short value, unsigned long offset)
+{
+ void *address = priv->nec7210_priv.iobase + offset;
+ unsigned long flags;
+ spinlock_t *register_lock = &priv->nec7210_priv.register_page_lock;
+
+ spin_lock_irqsave(register_lock, flags);
+ switch (offset) {
+ case KEYREG:
+ case IMR0:
+ case BCR:
+ switch (priv->nec7210_priv.type) {
+ case TNT4882:
+ case TNT5004:
+ priv->io_writeb(value, address);
+ break;
+ case NAT4882:
+ tnt_paged_writeb(priv, value, offset - tnt_pagein_offset);
+ break;
+ case NEC7210:
+ break;
+ default:
+ pr_err("tnt4882: bug! unsupported ni_chipset\n");
+ break;
+ }
+ break;
+ default:
+ priv->io_writeb(value, address);
+ break;
+ }
+ spin_unlock_irqrestore(register_lock, flags);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for National Instruments boards using tnt4882 or compatible chips");
+
+int tnt4882_line_status(const gpib_board_t *board)
+{
+ int status = ValidALL;
+ int bcsr_bits;
+ struct tnt4882_priv *tnt_priv;
+
+ tnt_priv = board->private_data;
+
+ bcsr_bits = tnt_readb(tnt_priv, BSR);
+
+ if (bcsr_bits & BCSR_REN_BIT)
+ status |= BusREN;
+ if (bcsr_bits & BCSR_IFC_BIT)
+ status |= BusIFC;
+ if (bcsr_bits & BCSR_SRQ_BIT)
+ status |= BusSRQ;
+ if (bcsr_bits & BCSR_EOI_BIT)
+ status |= BusEOI;
+ if (bcsr_bits & BCSR_NRFD_BIT)
+ status |= BusNRFD;
+ if (bcsr_bits & BCSR_NDAC_BIT)
+ status |= BusNDAC;
+ if (bcsr_bits & BCSR_DAV_BIT)
+ status |= BusDAV;
+ if (bcsr_bits & BCSR_ATN_BIT)
+ status |= BusATN;
+
+ return status;
+}
+
+unsigned int tnt4882_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct tnt4882_priv *tnt_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+ unsigned int retval;
+
+ retval = nec7210_t1_delay(board, nec_priv, nano_sec);
+ if (nec_priv->type == NEC7210)
+ return retval;
+
+ if (nano_sec <= 350) {
+ tnt_writeb(tnt_priv, MSTD, KEYREG);
+ retval = 350;
+ } else {
+ tnt_writeb(tnt_priv, 0, KEYREG);
+ }
+ if (nano_sec > 500 && nano_sec <= 1100) {
+ write_byte(nec_priv, AUXRI | USTD, AUXMR);
+ retval = 1100;
+ } else {
+ write_byte(nec_priv, AUXRI, AUXMR);
+ }
+ return retval;
+}
+
+static int fifo_word_available(struct tnt4882_priv *tnt_priv)
+{
+ int status2;
+ int retval;
+
+ status2 = tnt_readb(tnt_priv, STS2);
+ retval = (status2 & AEFN) && (status2 & BEFN);
+
+ return retval;
+}
+
+static int fifo_byte_available(struct tnt4882_priv *tnt_priv)
+{
+ int status2;
+ int retval;
+
+ status2 = tnt_readb(tnt_priv, STS2);
+ retval = (status2 & AEFN) || (status2 & BEFN);
+
+ return retval;
+}
+
+static int fifo_xfer_done(struct tnt4882_priv *tnt_priv)
+{
+ int status1;
+ int retval;
+
+ status1 = tnt_readb(tnt_priv, STS1);
+ retval = status1 & (S_DONE | S_HALT);
+
+ return retval;
+}
+
+static int drain_fifo_words(struct tnt4882_priv *tnt_priv, uint8_t *buffer, int num_bytes)
+{
+ int count = 0;
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+
+ while (fifo_word_available(tnt_priv) && count + 2 <= num_bytes) {
+ short word;
+
+ word = tnt_priv->io_readw(nec_priv->iobase + FIFOB);
+ buffer[count++] = word & 0xff;
+ buffer[count++] = (word >> 8) & 0xff;
+ }
+ return count;
+}
+
+static void tnt4882_release_holdoff(gpib_board_t *board, struct tnt4882_priv *tnt_priv)
+{
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+ unsigned short sasr_bits;
+
+ sasr_bits = tnt_readb(tnt_priv, SASR);
+
+ /*tnt4882 not in one-chip mode won't always release holdoff unless we
+ * are in the right mode when release handshake command is given
+ */
+ if (sasr_bits & AEHS_BIT) /* holding off due to holdoff on end mode*/ {
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDE);
+ write_byte(nec_priv, AUX_FH, AUXMR);
+ } else if (sasr_bits & ANHS1_BIT) { /* held off due to holdoff on all data mode*/
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDA);
+ write_byte(nec_priv, AUX_FH, AUXMR);
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDE);
+ } else { /* held off due to holdoff immediately command */
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDE);
+ write_byte(nec_priv, AUX_FH, AUXMR);
+ }
+}
+
+int tnt4882_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read)
+{
+ size_t count = 0;
+ ssize_t retval = 0;
+ struct tnt4882_priv *tnt_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+ unsigned int bits;
+ s32 hw_count;
+ unsigned long flags;
+
+ *bytes_read = 0;
+ // FIXME: really, DEV_CLEAR_BN should happen elsewhere to prevent race
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state);
+ clear_bit(ADR_CHANGE_BN, &nec_priv->state);
+
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_ENDIE, HR_ENDIE);
+ if (nec_priv->type != TNT4882 && nec_priv->type != TNT5004)
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI);
+ else
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+ tnt_writeb(tnt_priv, nec_priv->auxa_bits | HR_HLDA, CCR);
+ bits = TNT_B_16BIT | TNT_IN | TNT_CCEN;
+ tnt_writeb(tnt_priv, bits, CFG);
+ tnt_writeb(tnt_priv, RESET_FIFO, CMDR);
+ udelay(1);
+ // load 2's complement of count into hardware counters
+ hw_count = -length;
+ tnt_writeb(tnt_priv, hw_count & 0xff, CNT0);
+ tnt_writeb(tnt_priv, (hw_count >> 8) & 0xff, CNT1);
+ tnt_writeb(tnt_priv, (hw_count >> 16) & 0xff, CNT2);
+ tnt_writeb(tnt_priv, (hw_count >> 24) & 0xff, CNT3);
+
+ tnt4882_release_holdoff(board, tnt_priv);
+
+ tnt_writeb(tnt_priv, GO, CMDR);
+ udelay(1);
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ tnt_priv->imr3_bits |= HR_DONE | HR_NEF;
+ tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ while (count + 2 <= length &&
+ test_bit(RECEIVED_END_BN, &nec_priv->state) == 0 &&
+ fifo_xfer_done(tnt_priv) == 0) {
+ // wait until a word is ready
+ if (wait_event_interruptible(board->wait,
+ fifo_word_available(tnt_priv) ||
+ fifo_xfer_done(tnt_priv) ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(ADR_CHANGE_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_err("tnt4882: read interrupted\n");
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ //pr_info("tnt4882: minor %i read timed out\n", board->minor);
+ retval = -ETIMEDOUT;
+ break;
+ }
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) {
+ pr_err("tnt4882: device clear interrupted read\n");
+ retval = -EINTR;
+ break;
+ }
+ if (test_bit(ADR_CHANGE_BN, &nec_priv->state)) {
+ pr_err("tnt4882: address change interrupted read\n");
+ retval = -EINTR;
+ break;
+ }
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ count += drain_fifo_words(tnt_priv, &buffer[count], length - count);
+ tnt_priv->imr3_bits |= HR_NEF;
+ tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ if (need_resched())
+ schedule();
+ }
+ // wait for last byte
+ if (count < length) {
+ spin_lock_irqsave(&board->spinlock, flags);
+ tnt_priv->imr3_bits |= HR_DONE | HR_NEF;
+ tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ if (wait_event_interruptible(board->wait,
+ fifo_xfer_done(tnt_priv) ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(ADR_CHANGE_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_err("tnt4882: read interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ //pr_info("tnt4882: read timed out\n");
+ retval = -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) {
+ pr_err("tnt4882: device clear interrupted read\n");
+ retval = -EINTR;
+ }
+ if (test_bit(ADR_CHANGE_BN, &nec_priv->state)) {
+ pr_err("tnt4882: address change interrupted read\n");
+ retval = -EINTR;
+ }
+ count += drain_fifo_words(tnt_priv, &buffer[count], length - count);
+ if (fifo_byte_available(tnt_priv) && count < length)
+ buffer[count++] = tnt_readb(tnt_priv, FIFOB);
+ }
+ if (count < length)
+ tnt_writeb(tnt_priv, STOP, CMDR);
+ udelay(1);
+
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_ENDIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+ /* force handling of any pending interrupts (seems to be needed
+ * to keep interrupts from getting hosed, plus for syncing
+ * with RECEIVED_END below)
+ */
+ tnt4882_internal_interrupt(board);
+ /* RECEIVED_END should be in sync now */
+ if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state))
+ *end = 1;
+ if (retval < 0) {
+ // force immediate holdoff
+ write_byte(nec_priv, AUX_HLDI, AUXMR);
+
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ }
+ *bytes_read = count;
+
+ return retval;
+}
+
+static int fifo_space_available(struct tnt4882_priv *tnt_priv)
+{
+ int status2;
+ int retval;
+
+ status2 = tnt_readb(tnt_priv, STS2);
+ retval = (status2 & AFFN) && (status2 & BFFN);
+
+ return retval;
+}
+
+static unsigned int tnt_transfer_count(struct tnt4882_priv *tnt_priv)
+{
+ unsigned int count = 0;
+
+ count |= tnt_readb(tnt_priv, CNT0) & 0xff;
+ count |= (tnt_readb(tnt_priv, CNT1) << 8) & 0xff00;
+ count |= (tnt_readb(tnt_priv, CNT2) << 16) & 0xff0000;
+ count |= (tnt_readb(tnt_priv, CNT3) << 24) & 0xff000000;
+ // return two's complement
+ return -count;
+};
+
+static int write_wait(gpib_board_t *board, struct tnt4882_priv *tnt_priv,
+ int wait_for_done, int send_commands)
+{
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+
+ if (wait_event_interruptible(board->wait,
+ (!wait_for_done && fifo_space_available(tnt_priv)) ||
+ fifo_xfer_done(tnt_priv) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ pr_info("tnt4882: write timed out\n");
+ return -ETIMEDOUT;
+ }
+ if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state)) {
+ pr_err("tnt4882: write bus error\n");
+ return (send_commands) ? -ENOTCONN : -ECOMM;
+ }
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) {
+ pr_err("tnt4882: device clear interrupted write\n");
+ return -EINTR;
+ }
+ return 0;
+}
+
+static int generic_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, int send_commands, size_t *bytes_written)
+{
+ size_t count = 0;
+ ssize_t retval = 0;
+ struct tnt4882_priv *tnt_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+ unsigned int bits;
+ s32 hw_count;
+ unsigned long flags;
+
+ *bytes_written = 0;
+ // FIXME: really, DEV_CLEAR_BN should happen elsewhere to prevent race
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state);
+
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_ERRIE, HR_ERRIE);
+
+ if (nec_priv->type != TNT4882 && nec_priv->type != TNT5004)
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO);
+ else
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0);
+
+ tnt_writeb(tnt_priv, RESET_FIFO, CMDR);
+ udelay(1);
+
+ bits = TNT_B_16BIT;
+ if (send_eoi) {
+ bits |= TNT_CCEN;
+ if (nec_priv->type != TNT4882 && nec_priv->type != TNT5004)
+ tnt_writeb(tnt_priv, AUX_SEOI, CCR);
+ }
+ if (send_commands)
+ bits |= TNT_COMMAND;
+ tnt_writeb(tnt_priv, bits, CFG);
+
+ // load 2's complement of count into hardware counters
+ hw_count = -length;
+ tnt_writeb(tnt_priv, hw_count & 0xff, CNT0);
+ tnt_writeb(tnt_priv, (hw_count >> 8) & 0xff, CNT1);
+ tnt_writeb(tnt_priv, (hw_count >> 16) & 0xff, CNT2);
+ tnt_writeb(tnt_priv, (hw_count >> 24) & 0xff, CNT3);
+
+ tnt_writeb(tnt_priv, GO, CMDR);
+ udelay(1);
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ tnt_priv->imr3_bits |= HR_DONE;
+ tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ while (count < length) {
+ // wait until byte is ready to be sent
+ retval = write_wait(board, tnt_priv, 0, send_commands);
+ if (retval < 0)
+ break;
+ if (fifo_xfer_done(tnt_priv))
+ break;
+ spin_lock_irqsave(&board->spinlock, flags);
+ while (fifo_space_available(tnt_priv) && count < length) {
+ u16 word;
+
+ word = buffer[count++] & 0xff;
+ if (count < length)
+ word |= (buffer[count++] << 8) & 0xff00;
+ tnt_priv->io_writew(word, nec_priv->iobase + FIFOB);
+ }
+// avoid unnecessary HR_NFF interrupts
+// tnt_priv->imr3_bits |= HR_NFF;
+// tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ if (need_resched())
+ schedule();
+ }
+ // wait last byte has been sent
+ if (retval == 0)
+ retval = write_wait(board, tnt_priv, 1, send_commands);
+
+ tnt_writeb(tnt_priv, STOP, CMDR);
+ udelay(1);
+
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_ERR, 0x0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0x0);
+ /* force handling of any interrupts that happened
+ * while they were masked (this appears to be needed)
+ */
+ tnt4882_internal_interrupt(board);
+ *bytes_written = length - tnt_transfer_count(tnt_priv);
+ return retval;
+}
+
+int tnt4882_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ return generic_write(board, buffer, length, send_eoi, 0, bytes_written);
+}
+
+int tnt4882_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ return generic_write(board, buffer, length, 0, 1, bytes_written);
+}
+
+irqreturn_t tnt4882_internal_interrupt(gpib_board_t *board)
+{
+ struct tnt4882_priv *priv = board->private_data;
+ int isr0_bits, isr3_bits, imr3_bits;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ nec7210_interrupt(board, &priv->nec7210_priv);
+
+ isr0_bits = tnt_readb(priv, ISR0);
+ isr3_bits = tnt_readb(priv, ISR3);
+ imr3_bits = priv->imr3_bits;
+
+ if (isr0_bits & TNT_IFCI_BIT)
+ push_gpib_event(board, EventIFC);
+ //XXX don't need this wakeup, one below should do?
+// wake_up_interruptible(&board->wait);
+
+ if (isr3_bits & HR_NFF)
+ priv->imr3_bits &= ~HR_NFF;
+ if (isr3_bits & HR_NEF)
+ priv->imr3_bits &= ~HR_NEF;
+ if (isr3_bits & HR_DONE)
+ priv->imr3_bits &= ~HR_DONE;
+ if (isr3_bits & (HR_INTR | HR_TLCI)) {
+ dev_dbg(board->gpib_dev, "tnt4882: minor %i isr0 0x%x imr0 0x%x isr3 0x%x imr3 0x%x\n",
+ board->minor, isr0_bits, priv->imr0_bits, isr3_bits, imr3_bits);
+ tnt_writeb(priv, priv->imr3_bits, IMR3);
+ wake_up_interruptible(&board->wait);
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return IRQ_HANDLED;
+}
+
+irqreturn_t tnt4882_interrupt(int irq, void *arg)
+{
+ return tnt4882_internal_interrupt(arg);
+}
+
+static int ni_tnt_isa_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int ni_nat4882_isa_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int ni_nec_isa_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int ni_pci_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void ni_isa_detach(gpib_board_t *board);
+static void ni_pci_detach(gpib_board_t *board);
+
+#ifdef GPIB_PCMCIA
+static int ni_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static void ni_pcmcia_detach(gpib_board_t *board);
+static int init_ni_gpib_cs(void);
+static void __exit exit_ni_gpib_cs(void);
+#endif
+
+// wrappers for interface functions
+int tnt4882_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
+{
+ struct tnt4882_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+ int retval;
+ int dummy;
+
+ retval = nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+
+ if (retval < 0) { // force immediate holdoff
+ write_byte(nec_priv, AUX_HLDI, AUXMR);
+
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+
+ nec7210_read_data_in(board, nec_priv, &dummy);
+ }
+ return retval;
+}
+
+int tnt4882_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int tnt4882_command_unaccel(gpib_board_t *board, uint8_t *buffer,
+ size_t length, size_t *bytes_written)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+int tnt4882_take_control(gpib_board_t *board, int synchronous)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+int tnt4882_go_to_standby(gpib_board_t *board)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+void tnt4882_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ if (request_control) {
+ tnt_writeb(priv, SETSC, CMDR);
+ udelay(1);
+ }
+ nec7210_request_system_control(board, &priv->nec7210_priv, request_control);
+ if (!request_control) {
+ tnt_writeb(priv, CLRSC, CMDR);
+ udelay(1);
+ }
+}
+
+void tnt4882_interface_clear(gpib_board_t *board, int assert)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+void tnt4882_remote_enable(gpib_board_t *board, int enable)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+int tnt4882_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+void tnt4882_disable_eos(gpib_board_t *board)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+unsigned int tnt4882_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ unsigned long flags;
+ u8 line_status;
+ unsigned int retval;
+ struct tnt4882_priv *priv = board->private_data;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ board->status &= ~clear_mask;
+ retval = nec7210_update_status_nolock(board, &priv->nec7210_priv);
+ /* set / clear SRQ state since it is not cleared by interrupt */
+ line_status = tnt_readb(priv, BSR);
+ if (line_status & BCSR_SRQ_BIT)
+ set_bit(SRQI_NUM, &board->status);
+ else
+ clear_bit(SRQI_NUM, &board->status);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return board->status;
+}
+
+int tnt4882_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+int tnt4882_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+int tnt4882_parallel_poll(gpib_board_t *board, uint8_t *result)
+
+{
+ struct tnt4882_priv *tnt_priv = board->private_data;
+
+ if (tnt_priv->nec7210_priv.type != NEC7210) {
+ tnt_priv->auxg_bits |= RPP2_BIT;
+ write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR);
+ udelay(2); //FIXME use parallel poll timeout
+ *result = read_byte(&tnt_priv->nec7210_priv, CPTR);
+ tnt_priv->auxg_bits &= ~RPP2_BIT;
+ write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR);
+ return 0;
+ } else {
+ return nec7210_parallel_poll(board, &tnt_priv->nec7210_priv, result);
+ }
+}
+
+void tnt4882_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ if (priv->nec7210_priv.type == TNT5004) {
+ /* configure locally */
+ write_byte(&priv->nec7210_priv, AUXRI | 0x4, AUXMR);
+ if (config)
+ /* set response + clear sense */
+ write_byte(&priv->nec7210_priv, PPR | config, AUXMR);
+ else
+ /* disable ppoll */
+ write_byte(&priv->nec7210_priv, PPR | 0x10, AUXMR);
+ } else {
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config);
+ }
+}
+
+void tnt4882_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+/* this is just used by the old nec7210 isa interfaces, the newer
+ * boards use tnt4882_serial_poll_response2
+ */
+void tnt4882_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
+}
+
+static void tnt4882_serial_poll_response2(gpib_board_t *board, uint8_t status,
+ int new_reason_for_service)
+{
+ struct tnt4882_priv *priv = board->private_data;
+ unsigned long flags;
+ const int MSS = status & request_service_bit;
+ const int reqt = MSS && new_reason_for_service;
+ const int reqf = MSS == 0;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (reqt) {
+ priv->nec7210_priv.srq_pending = 1;
+ clear_bit(SPOLL_NUM, &board->status);
+ } else {
+ if (reqf)
+ priv->nec7210_priv.srq_pending = 0;
+ }
+ if (reqt)
+ /* It may seem like a race to issue reqt before updating
+ * the status byte, but it is not. The chip does not
+ * issue the reqt until the SPMR is written to at
+ * a later time.
+ */
+ write_byte(&priv->nec7210_priv, AUX_REQT, AUXMR);
+ else if (reqf)
+ write_byte(&priv->nec7210_priv, AUX_REQF, AUXMR);
+ /* We need to always zero bit 6 of the status byte before writing it to
+ * the SPMR to insure we are using
+ * serial poll mode SP1, and not accidentally triggering mode SP3.
+ */
+ write_byte(&priv->nec7210_priv, status & ~request_service_bit, SPMR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+uint8_t tnt4882_serial_poll_status(gpib_board_t *board)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+void tnt4882_return_to_local(gpib_board_t *board)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ nec7210_return_to_local(board, &priv->nec7210_priv);
+}
+
+gpib_interface_t ni_pci_interface = {
+name: "ni_pci",
+attach : ni_pci_attach,
+detach : ni_pci_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response2 : tnt4882_serial_poll_response2,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_pci_accel_interface = {
+name: "ni_pci_accel",
+attach : ni_pci_attach,
+detach : ni_pci_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response2 : tnt4882_serial_poll_response2,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_isa_interface = {
+name: "ni_isa",
+attach : ni_tnt_isa_attach,
+detach : ni_isa_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response2 : tnt4882_serial_poll_response2,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_nat4882_isa_interface = {
+name: "ni_nat4882_isa",
+attach : ni_nat4882_isa_attach,
+detach : ni_isa_detach,
+read : tnt4882_read,
+write : tnt4882_write,
+command : tnt4882_command_unaccel,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response2 : tnt4882_serial_poll_response2,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_nec_isa_interface = {
+name: "ni_nec_isa",
+attach : ni_nec_isa_attach,
+detach : ni_isa_detach,
+read : tnt4882_read,
+write : tnt4882_write,
+command : tnt4882_command_unaccel,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response : tnt4882_serial_poll_response,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_isa_accel_interface = {
+name: "ni_isa_accel",
+attach : ni_tnt_isa_attach,
+detach : ni_isa_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response2 : tnt4882_serial_poll_response2,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_nat4882_isa_accel_interface = {
+name: "ni_nat4882_isa_accel",
+attach : ni_nat4882_isa_attach,
+detach : ni_isa_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command_unaccel,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response2 : tnt4882_serial_poll_response2,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_nec_isa_accel_interface = {
+name: "ni_nec_isa_accel",
+attach : ni_nec_isa_attach,
+detach : ni_isa_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command_unaccel,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response : tnt4882_serial_poll_response,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+#ifdef GPIB_PCMCIA
+gpib_interface_t ni_pcmcia_interface = {
+name: "ni_pcmcia",
+attach : ni_pcmcia_attach,
+detach : ni_pcmcia_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response : tnt4882_serial_poll_response,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_pcmcia_accel_interface = {
+name: "ni_pcmcia_accel",
+attach : ni_pcmcia_attach,
+detach : ni_pcmcia_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response : tnt4882_serial_poll_response,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+#endif
+
+void tnt4882_board_reset(struct tnt4882_priv *tnt_priv, gpib_board_t *board)
+{
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+
+ tnt_priv->imr0_bits = 0;
+ tnt_writeb(tnt_priv, tnt_priv->imr0_bits, IMR0);
+ tnt_priv->imr3_bits = 0;
+ tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+ tnt_readb(tnt_priv, IMR0);
+ tnt_readb(tnt_priv, IMR3);
+ nec7210_board_reset(nec_priv, board);
+}
+
+int tnt4882_allocate_private(gpib_board_t *board)
+{
+ struct tnt4882_priv *tnt_priv;
+
+ board->private_data = kmalloc(sizeof(struct tnt4882_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ tnt_priv = board->private_data;
+ memset(tnt_priv, 0, sizeof(struct tnt4882_priv));
+ init_nec7210_private(&tnt_priv->nec7210_priv);
+ return 0;
+}
+
+void tnt4882_free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+void tnt4882_init(struct tnt4882_priv *tnt_priv, const gpib_board_t *board)
+{
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+
+ /* Turbo488 software reset */
+ tnt_writeb(tnt_priv, SOFT_RESET, CMDR);
+ udelay(1);
+
+ // turn off one-chip mode
+ tnt_writeb(tnt_priv, NODMA, HSSEL);
+ tnt_writeb(tnt_priv, 0, ACCWR);
+ // make sure we are in 7210 mode
+ tnt_writeb(tnt_priv, AUX_7210, AUXCR);
+ udelay(1);
+ // registers might be swapped, so write it to the swapped address too
+ tnt_writeb(tnt_priv, AUX_7210, SWAPPED_AUXCR);
+ udelay(1);
+ // turn on one-chip mode
+ if (nec_priv->type == TNT4882 || nec_priv->type == TNT5004)
+ tnt_writeb(tnt_priv, NODMA | TNT_ONE_CHIP_BIT, HSSEL);
+ else
+ tnt_writeb(tnt_priv, NODMA, HSSEL);
+
+ nec7210_board_reset(nec_priv, board);
+ // read-clear isr0
+ tnt_readb(tnt_priv, ISR0);
+
+ // enable passing of nat4882 interrupts
+ tnt_priv->imr3_bits = HR_TLCI;
+ tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+
+ // enable interrupt
+ tnt_writeb(tnt_priv, 0x1, INTRT);
+
+ // force immediate holdoff
+ write_byte(&tnt_priv->nec7210_priv, AUX_HLDI, AUXMR);
+
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+
+ tnt_priv->auxg_bits = AUXRG | NTNL_BIT;
+ write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR);
+
+ nec7210_board_online(nec_priv, board);
+ // enable interface clear interrupt for event queue
+ tnt_priv->imr0_bits = TNT_IMR0_ALWAYS_BITS | TNT_ATNI_BIT | TNT_IFCIE_BIT;
+ tnt_writeb(tnt_priv, tnt_priv->imr0_bits, IMR0);
+}
+
+int ni_pci_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct tnt4882_priv *tnt_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = IRQF_SHARED;
+ int retval;
+ struct mite_struct *mite;
+
+ board->status = 0;
+
+ if (tnt4882_allocate_private(board))
+ return -ENOMEM;
+ tnt_priv = board->private_data;
+ tnt_priv->io_writeb = writeb_wrapper;
+ tnt_priv->io_readb = readb_wrapper;
+ tnt_priv->io_writew = writew_wrapper;
+ tnt_priv->io_readw = readw_wrapper;
+ nec_priv = &tnt_priv->nec7210_priv;
+ nec_priv->type = TNT4882;
+ nec_priv->read_byte = nec7210_locking_iomem_read_byte;
+ nec_priv->write_byte = nec7210_locking_iomem_write_byte;
+ nec_priv->offset = atgpib_reg_offset;
+
+ if (!mite_devices) {
+ pr_err("no National Instruments PCI boards found\n");
+ return -1;
+ }
+
+ for (mite = mite_devices; mite; mite = mite->next) {
+ short found_board;
+
+ if (mite->used)
+ continue;
+ if (config->pci_bus >= 0 && config->pci_bus != mite->pcidev->bus->number)
+ continue;
+ if (config->pci_slot >= 0 && config->pci_slot != PCI_SLOT(mite->pcidev->devfn))
+ continue;
+ switch (mite_device_id(mite)) {
+ case PCI_DEVICE_ID_NI_GPIB:
+ case PCI_DEVICE_ID_NI_GPIB_PLUS:
+ case PCI_DEVICE_ID_NI_GPIB_PLUS2:
+ case PCI_DEVICE_ID_NI_PXIGPIB:
+ case PCI_DEVICE_ID_NI_PMCGPIB:
+ case PCI_DEVICE_ID_NI_PCIEGPIB:
+ case PCI_DEVICE_ID_NI_PCIE2GPIB:
+// support for Measurement Computing PCI-488
+ case PCI_DEVICE_ID_MC_PCI488:
+ case PCI_DEVICE_ID_CEC_NI_GPIB:
+ found_board = 1;
+ break;
+ default:
+ found_board = 0;
+ break;
+ }
+ if (found_board)
+ break;
+ }
+ if (!mite) {
+ pr_err("no NI PCI-GPIB boards found\n");
+ return -1;
+ }
+ tnt_priv->mite = mite;
+ retval = mite_setup(tnt_priv->mite);
+ if (retval < 0) {
+ pr_err("tnt4882: error setting up mite.\n");
+ return retval;
+ }
+
+ nec_priv->iobase = tnt_priv->mite->daq_io_addr;
+
+ // get irq
+ if (request_irq(mite_irq(tnt_priv->mite), tnt4882_interrupt, isr_flags,
+ "ni-pci-gpib", board)) {
+ pr_err("gpib: can't request IRQ %d\n", mite_irq(tnt_priv->mite));
+ return -1;
+ }
+ tnt_priv->irq = mite_irq(tnt_priv->mite);
+ pr_info("tnt4882: irq %i\n", tnt_priv->irq);
+
+ // TNT5004 detection
+ switch (tnt_readb(tnt_priv, CSR) & 0xf0) {
+ case 0x30:
+ nec_priv->type = TNT4882;
+ pr_info("tnt4882: TNT4882 chipset detected\n");
+ break;
+ case 0x40:
+ nec_priv->type = TNT5004;
+ pr_info("tnt4882: TNT5004 chipset detected\n");
+ break;
+ }
+ tnt4882_init(tnt_priv, board);
+
+ return 0;
+}
+
+void ni_pci_detach(gpib_board_t *board)
+{
+ struct tnt4882_priv *tnt_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (tnt_priv) {
+ nec_priv = &tnt_priv->nec7210_priv;
+
+ if (nec_priv->iobase)
+ tnt4882_board_reset(tnt_priv, board);
+ if (tnt_priv->irq)
+ free_irq(tnt_priv->irq, board);
+ if (tnt_priv->mite)
+ mite_unsetup(tnt_priv->mite);
+ }
+ tnt4882_free_private(board);
+}
+
+static int ni_isapnp_find(struct pnp_dev **dev)
+{
+ *dev = pnp_find_dev(NULL, ISAPNP_VENDOR_ID_NI,
+ ISAPNP_FUNCTION(ISAPNP_ID_NI_ATGPIB_TNT), NULL);
+ if (!*dev || !(*dev)->card) {
+ pr_err("tnt4882: failed to find isapnp board\n");
+ return -ENODEV;
+ }
+ if (pnp_device_attach(*dev) < 0) {
+ pr_err("tnt4882: atgpib/tnt board already active, skipping\n");
+ return -EBUSY;
+ }
+ if (pnp_activate_dev(*dev) < 0) {
+ pnp_device_detach(*dev);
+ pr_err("tnt4882: failed to activate() atgpib/tnt, aborting\n");
+ return -EAGAIN;
+ }
+ if (!pnp_port_valid(*dev, 0) || !pnp_irq_valid(*dev, 0)) {
+ pnp_device_detach(*dev);
+ pr_err("tnt4882: invalid port or irq for atgpib/tnt, aborting\n");
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int ni_isa_attach_common(gpib_board_t *board, const gpib_board_config_t *config,
+ enum nec7210_chipset chipset)
+{
+ struct tnt4882_priv *tnt_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = 0;
+ void *iobase;
+ int irq;
+
+ board->status = 0;
+
+ if (tnt4882_allocate_private(board))
+ return -ENOMEM;
+ tnt_priv = board->private_data;
+ tnt_priv->io_writeb = outb_wrapper;
+ tnt_priv->io_readb = inb_wrapper;
+ tnt_priv->io_writew = outw_wrapper;
+ tnt_priv->io_readw = inw_wrapper;
+ nec_priv = &tnt_priv->nec7210_priv;
+ nec_priv->type = chipset;
+ nec_priv->read_byte = nec7210_locking_ioport_read_byte;
+ nec_priv->write_byte = nec7210_locking_ioport_write_byte;
+ nec_priv->offset = atgpib_reg_offset;
+
+ // look for plug-n-play board
+ if (config->ibbase == 0) {
+ struct pnp_dev *dev;
+ int retval;
+
+ retval = ni_isapnp_find(&dev);
+ if (retval < 0)
+ return retval;
+ tnt_priv->pnp_dev = dev;
+ iobase = (void *)(pnp_port_start(dev, 0));
+ irq = pnp_irq(dev, 0);
+ } else {
+ iobase = config->ibbase;
+ irq = config->ibirq;
+ }
+ // allocate ioports
+ if (!request_region((unsigned long)(iobase), atgpib_iosize, "atgpib")) {
+ pr_err("tnt4882: failed to allocate ioports\n");
+ return -1;
+ }
+ nec_priv->iobase = iobase;
+
+ // get irq
+ if (request_irq(irq, tnt4882_interrupt, isr_flags, "atgpib", board)) {
+ pr_err("gpib: can't request IRQ %d\n", irq);
+ return -1;
+ }
+ tnt_priv->irq = irq;
+
+ tnt4882_init(tnt_priv, board);
+
+ return 0;
+}
+
+int ni_tnt_isa_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return ni_isa_attach_common(board, config, TNT4882);
+}
+
+int ni_nat4882_isa_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return ni_isa_attach_common(board, config, NAT4882);
+}
+
+int ni_nec_isa_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return ni_isa_attach_common(board, config, NEC7210);
+}
+
+void ni_isa_detach(gpib_board_t *board)
+{
+ struct tnt4882_priv *tnt_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (tnt_priv) {
+ nec_priv = &tnt_priv->nec7210_priv;
+ if (nec_priv->iobase)
+ tnt4882_board_reset(tnt_priv, board);
+ if (tnt_priv->irq)
+ free_irq(tnt_priv->irq, board);
+ if (nec_priv->iobase)
+ release_region((unsigned long)(nec_priv->iobase), atgpib_iosize);
+ if (tnt_priv->pnp_dev)
+ pnp_device_detach(tnt_priv->pnp_dev);
+ }
+ tnt4882_free_private(board);
+}
+
+static int tnt4882_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ return 0;
+}
+
+static const struct pci_device_id tnt4882_pci_table[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB_PLUS)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB_PLUS2)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PXIGPIB)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PMCGPIB)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PCIEGPIB)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PCIE2GPIB)},
+ // support for Measurement Computing PCI-488
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_MC_PCI488)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_CEC_NI_GPIB)},
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, tnt4882_pci_table);
+
+static struct pci_driver tnt4882_pci_driver = {
+ .name = "tnt4882",
+ .id_table = tnt4882_pci_table,
+ .probe = &tnt4882_pci_probe
+};
+
+static const struct pnp_device_id tnt4882_pnp_table[] = {
+ {.id = "NICC601"},
+ {.id = ""}
+};
+MODULE_DEVICE_TABLE(pnp, tnt4882_pnp_table);
+
+static int __init tnt4882_init_module(void)
+{
+ int result;
+
+ result = pci_register_driver(&tnt4882_pci_driver);
+ if (result) {
+ pr_err("tnt4882: pci_driver_register failed!\n");
+ return result;
+ }
+
+ gpib_register_driver(&ni_isa_interface, THIS_MODULE);
+ gpib_register_driver(&ni_isa_accel_interface, THIS_MODULE);
+ gpib_register_driver(&ni_nat4882_isa_interface, THIS_MODULE);
+ gpib_register_driver(&ni_nat4882_isa_accel_interface, THIS_MODULE);
+ gpib_register_driver(&ni_nec_isa_interface, THIS_MODULE);
+ gpib_register_driver(&ni_nec_isa_accel_interface, THIS_MODULE);
+ gpib_register_driver(&ni_pci_interface, THIS_MODULE);
+ gpib_register_driver(&ni_pci_accel_interface, THIS_MODULE);
+#ifdef GPIB_PCMCIA
+ gpib_register_driver(&ni_pcmcia_interface, THIS_MODULE);
+ gpib_register_driver(&ni_pcmcia_accel_interface, THIS_MODULE);
+ if (init_ni_gpib_cs() < 0)
+ return -1;
+#endif
+
+ mite_init();
+ mite_list_devices();
+
+ return 0;
+}
+
+static void __exit tnt4882_exit_module(void)
+{
+ gpib_unregister_driver(&ni_isa_interface);
+ gpib_unregister_driver(&ni_isa_accel_interface);
+ gpib_unregister_driver(&ni_nat4882_isa_interface);
+ gpib_unregister_driver(&ni_nat4882_isa_accel_interface);
+ gpib_unregister_driver(&ni_nec_isa_interface);
+ gpib_unregister_driver(&ni_nec_isa_accel_interface);
+ gpib_unregister_driver(&ni_pci_interface);
+ gpib_unregister_driver(&ni_pci_accel_interface);
+#ifdef GPIB_PCMCIA
+ gpib_unregister_driver(&ni_pcmcia_interface);
+ gpib_unregister_driver(&ni_pcmcia_accel_interface);
+ exit_ni_gpib_cs();
+#endif
+
+ mite_cleanup();
+
+ pci_unregister_driver(&tnt4882_pci_driver);
+}
+
+#ifdef GPIB_PCMCIA
+
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+
+/*
+ * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
+ * you do not define PCMCIA_DEBUG at all, all the debug code will be
+ * left out. If you compile with PCMCIA_DEBUG=0, the debug code will
+ * be present but disabled -- but it can then be enabled for specific
+ * modules at load time with a 'pc_debug=#' option to insmod.
+ */
+#define PCMCIA_DEBUG 1
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+module_param(pc_debug, int, 0);
+#define DEBUG(n, args...) \
+ do {if (pc_debug > (n)) \
+ pr_debug(args); } \
+ while (0)
+#else
+#define DEBUG(args...)
+#endif
+
+static int ni_gpib_config(struct pcmcia_device *link);
+static void ni_gpib_release(struct pcmcia_device *link);
+static int ni_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static void ni_pcmcia_detach(gpib_board_t *board);
+
+/*
+ * A linked list of "instances" of the dummy device. Each actual
+ * PCMCIA card corresponds to one device instance, and is described
+ * by one dev_link_t structure (defined in ds.h).
+ *
+ * You may not want to use a linked list for this -- for example, the
+ * memory card driver uses an array of dev_link_t pointers, where minor
+ * device numbers are used to derive the corresponding array index.
+ *
+ * I think this dev_list is obsolete but the pointer is needed to keep
+ * the module instance for the ni_pcmcia_attach function.
+ */
+
+static struct pcmcia_device *curr_dev;
+
+struct local_info_t {
+ struct pcmcia_device *p_dev;
+ gpib_board_t *dev;
+ int stop;
+ struct bus_operations *bus;
+};
+
+/*
+ * ni_gpib_probe() creates an "instance" of the driver, allocating
+ * local data structures for one device. The device is registered
+ * with Card Services.
+ */
+
+static int ni_gpib_probe(struct pcmcia_device *link)
+{
+ struct local_info_t *info;
+ //struct gpib_board_t *dev;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ /* Allocate space for private device-specific data */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->p_dev = link;
+ link->priv = info;
+
+ /*
+ * General socket configuration defaults can go here. In this
+ * client, we assume very little, and rely on the CIS for almost
+ * everything. In most clients, many details (i.e., number, sizes,
+ * and attributes of IO windows) are fixed by the nature of the
+ * device, and can be hard-wired here.
+ */
+ link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
+ /* Register with Card Services */
+ curr_dev = link;
+ return ni_gpib_config(link);
+}
+
+/*
+ * This deletes a driver "instance". The device is de-registered
+ * with Card Services. If it has been released, all local data
+ * structures are freed. Otherwise, the structures will be freed
+ * when the device is released.
+ */
+static void ni_gpib_remove(struct pcmcia_device *link)
+{
+ struct local_info_t *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+
+ DEBUG(0, "%s(%p)\n", __func__, link);
+
+ if (info->dev)
+ ni_pcmcia_detach(info->dev);
+ ni_gpib_release(link);
+
+ //free_netdev(dev);
+ kfree(info);
+}
+
+static int ni_gpib_config_iteration(struct pcmcia_device *link, void *priv_data)
+{
+ int retval;
+
+ retval = pcmcia_request_io(link);
+ if (retval != 0)
+ return retval;
+
+ return 0;
+}
+
+/*
+ * ni_gpib_config() is scheduled to run after a CARD_INSERTION event
+ * is received, to configure the PCMCIA socket, and to make the
+ * device available to the system.
+ */
+static int ni_gpib_config(struct pcmcia_device *link)
+{
+ //struct local_info_t *info = link->priv;
+ //gpib_board_t *dev = info->dev;
+ int last_ret;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ last_ret = pcmcia_loop_config(link, &ni_gpib_config_iteration, NULL);
+ if (last_ret) {
+ dev_warn(&link->dev, "no configuration found\n");
+ ni_gpib_release(link);
+ return last_ret;
+ }
+
+ last_ret = pcmcia_enable_device(link);
+ if (last_ret) {
+ ni_gpib_release(link);
+ return last_ret;
+ }
+ return 0;
+} /* ni_gpib_config */
+
+/*
+ * After a card is removed, ni_gpib_release() will unregister the
+ * device, and release the PCMCIA configuration. If the device is
+ * still open, this will be postponed until it is closed.
+ */
+static void ni_gpib_release(struct pcmcia_device *link)
+{
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+ pcmcia_disable_device(link);
+} /* ni_gpib_release */
+
+static int ni_gpib_suspend(struct pcmcia_device *link)
+{
+ //struct local_info_t *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ if (link->open)
+ pr_err("Device still open ???\n");
+ //netif_device_detach(dev);
+
+ return 0;
+}
+
+static int ni_gpib_resume(struct pcmcia_device *link)
+{
+ //struct local_info_t *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ /*if (link->open) {
+ * ni_gpib_probe(dev); / really?
+ * printk("Gpib resumed ???\n");
+ * //netif_device_attach(dev);
+ *}
+ */
+ return ni_gpib_config(link);
+}
+
+static struct pcmcia_device_id ni_pcmcia_ids[] = {
+ PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4882),
+ PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0c71), // NI PCMCIA-GPIB+
+ PCMCIA_DEVICE_NULL
+};
+
+MODULE_DEVICE_TABLE(pcmcia, ni_pcmcia_ids);
+
+static struct pcmcia_driver ni_gpib_cs_driver = {
+ .name = "ni_gpib_cs",
+ .owner = THIS_MODULE,
+ .drv = { .name = "ni_gpib_cs", },
+ .id_table = ni_pcmcia_ids,
+ .probe = ni_gpib_probe,
+ .remove = ni_gpib_remove,
+ .suspend = ni_gpib_suspend,
+ .resume = ni_gpib_resume,
+};
+
+int __init init_ni_gpib_cs(void)
+{
+ return pcmcia_register_driver(&ni_gpib_cs_driver);
+}
+
+void __exit exit_ni_gpib_cs(void)
+{
+ DEBUG(0, "ni_gpib_cs: unloading\n");
+ pcmcia_unregister_driver(&ni_gpib_cs_driver);
+}
+
+static const int pcmcia_gpib_iosize = 32;
+
+int ni_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct local_info_t *info;
+ struct tnt4882_priv *tnt_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = IRQF_SHARED;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, board);
+
+ if (!curr_dev) {
+ pr_err("gpib: no NI PCMCIA board found\n");
+ return -1;
+ }
+
+ info = curr_dev->priv;
+ info->dev = board;
+
+ board->status = 0;
+
+ if (tnt4882_allocate_private(board))
+ return -ENOMEM;
+ tnt_priv = board->private_data;
+ tnt_priv->io_writeb = outb_wrapper;
+ tnt_priv->io_readb = inb_wrapper;
+ tnt_priv->io_writew = outw_wrapper;
+ tnt_priv->io_readw = inw_wrapper;
+ nec_priv = &tnt_priv->nec7210_priv;
+ nec_priv->type = TNT4882;
+ nec_priv->read_byte = nec7210_locking_ioport_read_byte;
+ nec_priv->write_byte = nec7210_locking_ioport_write_byte;
+ nec_priv->offset = atgpib_reg_offset;
+
+ DEBUG(0, "ioport1 window attributes: 0x%lx\n", curr_dev->resource[0]->flags);
+ if (request_region(curr_dev->resource[0]->start, resource_size(curr_dev->resource[0]),
+ "tnt4882") == 0) {
+ pr_err("gpib: ioports starting at 0x%lx are already in use\n",
+ (unsigned long)curr_dev->resource[0]->start);
+ return -EIO;
+ }
+
+ nec_priv->iobase = (void *)(unsigned long)curr_dev->resource[0]->start;
+
+ // get irq
+ if (request_irq(curr_dev->irq, tnt4882_interrupt, isr_flags, "tnt4882", board)) {
+ pr_err("gpib: can't request IRQ %d\n", curr_dev->irq);
+ return -1;
+ }
+ tnt_priv->irq = curr_dev->irq;
+
+ tnt4882_init(tnt_priv, board);
+
+ return 0;
+}
+
+void ni_pcmcia_detach(gpib_board_t *board)
+{
+ struct tnt4882_priv *tnt_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, board);
+
+ if (tnt_priv) {
+ nec_priv = &tnt_priv->nec7210_priv;
+ if (tnt_priv->irq)
+ free_irq(tnt_priv->irq, board);
+ if (nec_priv->iobase) {
+ tnt4882_board_reset(tnt_priv, board);
+ release_region((unsigned long)nec_priv->iobase, pcmcia_gpib_iosize);
+ }
+ }
+ tnt4882_free_private(board);
+}
+
+#endif // GPIB_PCMCIA
+
+module_init(tnt4882_init_module);
+module_exit(tnt4882_exit_module);
diff --git a/drivers/staging/gpib/uapi/gpib_ioctl.h b/drivers/staging/gpib/uapi/gpib_ioctl.h
new file mode 100644
index 000000000000..6202865278ea
--- /dev/null
+++ b/drivers/staging/gpib/uapi/gpib_ioctl.h
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_IOCTL_H
+#define _GPIB_IOCTL_H
+
+#include <asm/ioctl.h>
+#include <linux/types.h>
+
+#define GPIB_CODE 160
+
+typedef struct {
+ char name[100];
+} board_type_ioctl_t;
+
+/* argument for read/write/command ioctls */
+typedef struct {
+ uint64_t buffer_ptr;
+ unsigned int requested_transfer_count;
+ unsigned int completed_transfer_count;
+ int end; /* end flag return for reads, end io suppression request for cmd*/
+ int handle;
+} read_write_ioctl_t;
+
+typedef struct {
+ unsigned int handle;
+ unsigned int pad;
+ int sad;
+ unsigned is_board : 1;
+} open_dev_ioctl_t;
+
+typedef struct {
+ unsigned int handle;
+} close_dev_ioctl_t;
+
+typedef struct {
+ unsigned int pad;
+ int sad;
+ uint8_t status_byte;
+} serial_poll_ioctl_t;
+
+typedef struct {
+ int eos;
+ int eos_flags;
+} eos_ioctl_t;
+
+typedef struct {
+ int handle;
+ int wait_mask;
+ int clear_mask;
+ int set_mask;
+ int ibsta;
+ int pad;
+ int sad;
+ unsigned int usec_timeout;
+} wait_ioctl_t;
+
+typedef struct {
+ uint64_t init_data_ptr;
+ int init_data_length;
+ int online;
+} online_ioctl_t;
+
+typedef struct {
+ unsigned int num_bytes;
+ unsigned int pad;
+ int sad;
+} spoll_bytes_ioctl_t;
+
+typedef struct {
+ unsigned int pad;
+ int sad;
+ int parallel_poll_configuration;
+ int autopolling;
+ int is_system_controller;
+ unsigned int t1_delay;
+ unsigned ist : 1;
+ unsigned no_7_bit_eos : 1;
+} board_info_ioctl_t;
+
+typedef struct {
+ int pci_bus;
+ int pci_slot;
+} select_pci_ioctl_t;
+
+typedef struct {
+ uint8_t config;
+ unsigned set_ist : 1;
+ unsigned clear_ist : 1;
+} ppoll_config_ioctl_t;
+
+typedef struct {
+ unsigned int handle;
+ unsigned int pad;
+} pad_ioctl_t;
+
+typedef struct {
+ unsigned int handle;
+ int sad;
+} sad_ioctl_t;
+
+// select a piece of hardware to attach by its sysfs device path
+typedef struct {
+ char device_path[0x1000];
+} select_device_path_ioctl_t;
+
+typedef short event_ioctl_t;
+typedef int rsc_ioctl_t;
+typedef unsigned int t1_delay_ioctl_t;
+typedef short autospoll_ioctl_t;
+typedef short local_ppoll_mode_ioctl_t;
+
+// update status byte and request service
+typedef struct {
+ uint8_t status_byte;
+ int new_reason_for_service;
+} request_service2_t;
+
+/* Standard functions. */
+enum gpib_ioctl {
+ IBRD = _IOWR(GPIB_CODE, 100, read_write_ioctl_t),
+ IBWRT = _IOWR(GPIB_CODE, 101, read_write_ioctl_t),
+ IBCMD = _IOWR(GPIB_CODE, 102, read_write_ioctl_t),
+ IBOPENDEV = _IOWR(GPIB_CODE, 3, open_dev_ioctl_t),
+ IBCLOSEDEV = _IOW(GPIB_CODE, 4, close_dev_ioctl_t),
+ IBWAIT = _IOWR(GPIB_CODE, 5, wait_ioctl_t),
+ IBRPP = _IOWR(GPIB_CODE, 6, uint8_t),
+
+ IBSIC = _IOW(GPIB_CODE, 9, unsigned int),
+ IBSRE = _IOW(GPIB_CODE, 10, int),
+ IBGTS = _IO(GPIB_CODE, 11),
+ IBCAC = _IOW(GPIB_CODE, 12, int),
+ IBLINES = _IOR(GPIB_CODE, 14, short),
+ IBPAD = _IOW(GPIB_CODE, 15, pad_ioctl_t),
+ IBSAD = _IOW(GPIB_CODE, 16, sad_ioctl_t),
+ IBTMO = _IOW(GPIB_CODE, 17, unsigned int),
+ IBRSP = _IOWR(GPIB_CODE, 18, serial_poll_ioctl_t),
+ IBEOS = _IOW(GPIB_CODE, 19, eos_ioctl_t),
+ IBRSV = _IOW(GPIB_CODE, 20, uint8_t),
+ CFCBASE = _IOW(GPIB_CODE, 21, uint64_t),
+ CFCIRQ = _IOW(GPIB_CODE, 22, unsigned int),
+ CFCDMA = _IOW(GPIB_CODE, 23, unsigned int),
+ CFCBOARDTYPE = _IOW(GPIB_CODE, 24, board_type_ioctl_t),
+
+ IBMUTEX = _IOW(GPIB_CODE, 26, int),
+ IBSPOLL_BYTES = _IOWR(GPIB_CODE, 27, spoll_bytes_ioctl_t),
+ IBPPC = _IOW(GPIB_CODE, 28, ppoll_config_ioctl_t),
+ IBBOARD_INFO = _IOR(GPIB_CODE, 29, board_info_ioctl_t),
+
+ IBQUERY_BOARD_RSV = _IOR(GPIB_CODE, 31, int),
+ IBSELECT_PCI = _IOWR(GPIB_CODE, 32, select_pci_ioctl_t),
+ IBEVENT = _IOR(GPIB_CODE, 33, event_ioctl_t),
+ IBRSC = _IOW(GPIB_CODE, 34, rsc_ioctl_t),
+ IB_T1_DELAY = _IOW(GPIB_CODE, 35, t1_delay_ioctl_t),
+ IBLOC = _IO(GPIB_CODE, 36),
+
+ IBAUTOSPOLL = _IOW(GPIB_CODE, 38, autospoll_ioctl_t),
+ IBONL = _IOW(GPIB_CODE, 39, online_ioctl_t),
+ IBPP2_SET = _IOW(GPIB_CODE, 40, local_ppoll_mode_ioctl_t),
+ IBPP2_GET = _IOR(GPIB_CODE, 41, local_ppoll_mode_ioctl_t),
+ IBSELECT_DEVICE_PATH = _IOW(GPIB_CODE, 43, select_device_path_ioctl_t),
+ // 44 was IBSELECT_SERIAL_NUMBER
+ IBRSV2 = _IOW(GPIB_CODE, 45, request_service2_t)
+};
+
+#endif /* _GPIB_IOCTL_H */
diff --git a/drivers/staging/gpib/uapi/gpib_user.h b/drivers/staging/gpib/uapi/gpib_user.h
new file mode 100644
index 000000000000..0896a55a758f
--- /dev/null
+++ b/drivers/staging/gpib/uapi/gpib_user.h
@@ -0,0 +1,363 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_USER_H
+#define _GPIB_USER_H
+
+#define GPIB_MAX_NUM_BOARDS 16
+#define GPIB_MAX_NUM_DESCRIPTORS 0x1000
+
+enum ibsta_bit_numbers {
+ DCAS_NUM = 0,
+ DTAS_NUM = 1,
+ LACS_NUM = 2,
+ TACS_NUM = 3,
+ ATN_NUM = 4,
+ CIC_NUM = 5,
+ REM_NUM = 6,
+ LOK_NUM = 7,
+ CMPL_NUM = 8,
+ EVENT_NUM = 9,
+ SPOLL_NUM = 10,
+ RQS_NUM = 11,
+ SRQI_NUM = 12,
+ END_NUM = 13,
+ TIMO_NUM = 14,
+ ERR_NUM = 15
+};
+
+/* IBSTA status bits (returned by all functions) */
+enum ibsta_bits {
+ DCAS = (1 << DCAS_NUM), /* device clear state */
+ DTAS = (1 << DTAS_NUM), /* device trigger state */
+ LACS = (1 << LACS_NUM), /* GPIB interface is addressed as Listener */
+ TACS = (1 << TACS_NUM), /* GPIB interface is addressed as Talker */
+ ATN = (1 << ATN_NUM), /* Attention is asserted */
+ CIC = (1 << CIC_NUM), /* GPIB interface is Controller-in-Charge */
+ REM = (1 << REM_NUM), /* remote state */
+ LOK = (1 << LOK_NUM), /* lockout state */
+ CMPL = (1 << CMPL_NUM), /* I/O is complete */
+ EVENT = (1 << EVENT_NUM), /* DCAS, DTAS, or IFC has occurred */
+ SPOLL = (1 << SPOLL_NUM), /* board serial polled by busmaster */
+ RQS = (1 << RQS_NUM), /* Device requesting service */
+ SRQI = (1 << SRQI_NUM), /* SRQ is asserted */
+ END = (1 << END_NUM), /* EOI or EOS encountered */
+ TIMO = (1 << TIMO_NUM), /* Time limit on I/O or wait function exceeded */
+ ERR = (1 << ERR_NUM), /* Function call terminated on error */
+
+ device_status_mask = ERR | TIMO | END | CMPL | RQS,
+ board_status_mask = ERR | TIMO | END | CMPL | SPOLL |
+ EVENT | LOK | REM | CIC | ATN | TACS | LACS | DTAS | DCAS | SRQI,
+};
+
+/* IBERR error codes */
+enum iberr_code {
+ EDVR = 0, /* system error */
+ ECIC = 1, /* not CIC */
+ ENOL = 2, /* no listeners */
+ EADR = 3, /* CIC and not addressed before I/O */
+ EARG = 4, /* bad argument to function call */
+ ESAC = 5, /* not SAC */
+ EABO = 6, /* I/O operation was aborted */
+ ENEB = 7, /* non-existent board (GPIB interface offline) */
+ EDMA = 8, /* DMA hardware error detected */
+ EOIP = 10, /* new I/O attempted with old I/O in progress */
+ ECAP = 11, /* no capability for intended opeation */
+ EFSO = 12, /* file system operation error */
+ EBUS = 14, /* bus error */
+ ESTB = 15, /* lost serial poll bytes */
+ ESRQ = 16, /* SRQ stuck on */
+ ETAB = 20 /* Table Overflow */
+};
+
+/* Timeout values and meanings */
+enum gpib_timeout {
+ TNONE = 0, /* Infinite timeout (disabled) */
+ T10us = 1, /* Timeout of 10 usec (ideal) */
+ T30us = 2, /* Timeout of 30 usec (ideal) */
+ T100us = 3, /* Timeout of 100 usec (ideal) */
+ T300us = 4, /* Timeout of 300 usec (ideal) */
+ T1ms = 5, /* Timeout of 1 msec (ideal) */
+ T3ms = 6, /* Timeout of 3 msec (ideal) */
+ T10ms = 7, /* Timeout of 10 msec (ideal) */
+ T30ms = 8, /* Timeout of 30 msec (ideal) */
+ T100ms = 9, /* Timeout of 100 msec (ideal) */
+ T300ms = 10, /* Timeout of 300 msec (ideal) */
+ T1s = 11, /* Timeout of 1 sec (ideal) */
+ T3s = 12, /* Timeout of 3 sec (ideal) */
+ T10s = 13, /* Timeout of 10 sec (ideal) */
+ T30s = 14, /* Timeout of 30 sec (ideal) */
+ T100s = 15, /* Timeout of 100 sec (ideal) */
+ T300s = 16, /* Timeout of 300 sec (ideal) */
+ T1000s = 17 /* Timeout of 1000 sec (maximum) */
+};
+
+/* End-of-string (EOS) modes for use with ibeos */
+
+enum eos_flags {
+ EOS_MASK = 0x1c00,
+ REOS = 0x0400, /* Terminate reads on EOS */
+ XEOS = 0x800, /* assert EOI when EOS char is sent */
+ BIN = 0x1000 /* Do 8-bit compare on EOS */
+};
+
+/* GPIB Bus Control Lines bit vector */
+enum bus_control_line {
+ ValidDAV = 0x01,
+ ValidNDAC = 0x02,
+ ValidNRFD = 0x04,
+ ValidIFC = 0x08,
+ ValidREN = 0x10,
+ ValidSRQ = 0x20,
+ ValidATN = 0x40,
+ ValidEOI = 0x80,
+ ValidALL = 0xff,
+ BusDAV = 0x0100, /* DAV line status bit */
+ BusNDAC = 0x0200, /* NDAC line status bit */
+ BusNRFD = 0x0400, /* NRFD line status bit */
+ BusIFC = 0x0800, /* IFC line status bit */
+ BusREN = 0x1000, /* REN line status bit */
+ BusSRQ = 0x2000, /* SRQ line status bit */
+ BusATN = 0x4000, /* ATN line status bit */
+ BusEOI = 0x8000 /* EOI line status bit */
+};
+
+enum old_bus_control_line {
+ BUS_DAV = 0x0100, /* DAV line status bit */
+ BUS_NDAC = 0x0200, /* NDAC line status bit */
+ BUS_NRFD = 0x0400, /* NRFD line status bit */
+ BUS_IFC = 0x0800, /* IFC line status bit */
+ BUS_REN = 0x1000, /* REN line status bit */
+ BUS_SRQ = 0x2000, /* SRQ line status bit */
+ BUS_ATN = 0x4000, /* ATN line status bit */
+ BUS_EOI = 0x8000 /* EOI line status bit */
+};
+
+/* Possible GPIB command messages */
+
+enum cmd_byte {
+ GTL = 0x1, /* go to local */
+ SDC = 0x4, /* selected device clear */
+ PPConfig = 0x5,
+#ifndef PPC
+ PPC = PPConfig, /* parallel poll configure */
+#endif
+ GET = 0x8, /* group execute trigger */
+ TCT = 0x9, /* take control */
+ LLO = 0x11, /* local lockout */
+ DCL = 0x14, /* device clear */
+ PPU = 0x15, /* parallel poll unconfigure */
+ SPE = 0x18, /* serial poll enable */
+ SPD = 0x19, /* serial poll disable */
+ CFE = 0x1f, /* configure enable */
+ LAD = 0x20, /* value to be 'ored' in to obtain listen address */
+ UNL = 0x3F, /* unlisten */
+ TAD = 0x40, /* value to be 'ored' in to obtain talk address */
+ UNT = 0x5F, /* untalk */
+ SAD = 0x60, /* my secondary address (base) */
+ PPE = 0x60, /* parallel poll enable (base) */
+ PPD = 0x70 /* parallel poll disable */
+};
+
+enum ppe_bits {
+ PPC_DISABLE = 0x10,
+ PPC_SENSE = 0x8, /* parallel poll sense bit */
+ PPC_DIO_MASK = 0x7
+};
+
+/* confine address to range 0 to 30. */
+static inline unsigned int gpib_address_restrict(unsigned int addr)
+{
+ addr &= 0x1f;
+ if (addr == 0x1f)
+ addr = 0;
+ return addr;
+}
+
+static inline uint8_t MLA(unsigned int addr)
+{
+ return gpib_address_restrict(addr) | LAD;
+}
+
+static inline uint8_t MTA(unsigned int addr)
+{
+ return gpib_address_restrict(addr) | TAD;
+}
+
+static inline uint8_t MSA(unsigned int addr)
+{
+ return gpib_address_restrict(addr) | SAD;
+}
+
+static inline uint8_t PPE_byte(unsigned int dio_line, int sense)
+{
+ uint8_t cmd;
+
+ cmd = PPE;
+ if (sense)
+ cmd |= PPC_SENSE;
+ cmd |= (dio_line - 1) & 0x7;
+ return cmd;
+}
+
+static inline uint8_t CFGn(unsigned int meters)
+{
+ return 0x6 | (meters & 0xf);
+}
+
+/* mask of bits that actually matter in a command byte */
+enum {
+ gpib_command_mask = 0x7f,
+};
+
+static inline int is_PPE(uint8_t command)
+{
+ return (command & 0x70) == 0x60;
+}
+
+static inline int is_PPD(uint8_t command)
+{
+ return (command & 0x70) == 0x70;
+}
+
+static inline int in_addressed_command_group(uint8_t command)
+{
+ return (command & 0x70) == 0x0;
+}
+
+static inline int in_universal_command_group(uint8_t command)
+{
+ return (command & 0x70) == 0x10;
+}
+
+static inline int in_listen_address_group(uint8_t command)
+{
+ return (command & 0x60) == 0x20;
+}
+
+static inline int in_talk_address_group(uint8_t command)
+{
+ return (command & 0x60) == 0x40;
+}
+
+static inline int in_primary_command_group(uint8_t command)
+{
+ return in_addressed_command_group(command) ||
+ in_universal_command_group(command) ||
+ in_listen_address_group(command) ||
+ in_talk_address_group(command);
+}
+
+static inline int gpib_address_equal(unsigned int pad1, int sad1, unsigned int pad2, int sad2)
+{
+ if (pad1 == pad2) {
+ if (sad1 == sad2)
+ return 1;
+ if (sad1 < 0 && sad2 < 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+enum ibask_option {
+ IbaPAD = 0x1,
+ IbaSAD = 0x2,
+ IbaTMO = 0x3,
+ IbaEOT = 0x4,
+ IbaPPC = 0x5, /* board only */
+ IbaREADDR = 0x6, /* device only */
+ IbaAUTOPOLL = 0x7, /* board only */
+ IbaCICPROT = 0x8, /* board only */
+ IbaIRQ = 0x9, /* board only */
+ IbaSC = 0xa, /* board only */
+ IbaSRE = 0xb, /* board only */
+ IbaEOSrd = 0xc,
+ IbaEOSwrt = 0xd,
+ IbaEOScmp = 0xe,
+ IbaEOSchar = 0xf,
+ IbaPP2 = 0x10, /* board only */
+ IbaTIMING = 0x11, /* board only */
+ IbaDMA = 0x12, /* board only */
+ IbaReadAdjust = 0x13,
+ IbaWriteAdjust = 0x14,
+ IbaEventQueue = 0x15, /* board only */
+ IbaSPollBit = 0x16, /* board only */
+ IbaSpollBit = 0x16, /* board only */
+ IbaSendLLO = 0x17, /* board only */
+ IbaSPollTime = 0x18, /* device only */
+ IbaPPollTime = 0x19, /* board only */
+ IbaEndBitIsNormal = 0x1a,
+ IbaUnAddr = 0x1b, /* device only */
+ IbaHSCableLength = 0x1f, /* board only */
+ IbaIst = 0x20, /* board only */
+ IbaRsv = 0x21, /* board only */
+ IbaBNA = 0x200, /* device only */
+ /* linux-gpib extensions */
+ Iba7BitEOS = 0x1000 /* board only. Returns 1 if board supports 7 bit eos compares*/
+};
+
+enum ibconfig_option {
+ IbcPAD = 0x1,
+ IbcSAD = 0x2,
+ IbcTMO = 0x3,
+ IbcEOT = 0x4,
+ IbcPPC = 0x5, /* board only */
+ IbcREADDR = 0x6, /* device only */
+ IbcAUTOPOLL = 0x7, /* board only */
+ IbcCICPROT = 0x8, /* board only */
+ IbcIRQ = 0x9, /* board only */
+ IbcSC = 0xa, /* board only */
+ IbcSRE = 0xb, /* board only */
+ IbcEOSrd = 0xc,
+ IbcEOSwrt = 0xd,
+ IbcEOScmp = 0xe,
+ IbcEOSchar = 0xf,
+ IbcPP2 = 0x10, /* board only */
+ IbcTIMING = 0x11, /* board only */
+ IbcDMA = 0x12, /* board only */
+ IbcReadAdjust = 0x13,
+ IbcWriteAdjust = 0x14,
+ IbcEventQueue = 0x15, /* board only */
+ IbcSPollBit = 0x16, /* board only */
+ IbcSpollBit = 0x16, /* board only */
+ IbcSendLLO = 0x17, /* board only */
+ IbcSPollTime = 0x18, /* device only */
+ IbcPPollTime = 0x19, /* board only */
+ IbcEndBitIsNormal = 0x1a,
+ IbcUnAddr = 0x1b, /* device only */
+ IbcHSCableLength = 0x1f, /* board only */
+ IbcIst = 0x20, /* board only */
+ IbcRsv = 0x21, /* board only */
+ IbcBNA = 0x200 /* device only */
+};
+
+enum t1_delays {
+ T1_DELAY_2000ns = 1,
+ T1_DELAY_500ns = 2,
+ T1_DELAY_350ns = 3
+};
+
+enum {
+ request_service_bit = 0x40,
+};
+
+enum gpib_events {
+ EventNone = 0,
+ EventDevTrg = 1,
+ EventDevClr = 2,
+ EventIFC = 3
+};
+
+enum gpib_stb {
+ IbStbRQS = 0x40, /* IEEE 488.1 & 2 */
+ IbStbESB = 0x20, /* IEEE 488.2 only */
+ IbStbMAV = 0x10 /* IEEE 488.2 only */
+};
+
+#endif /* _GPIB_USER_H */
+
+/* Check for errors */
diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c
index aa6f266b62a1..90ab32638d3f 100644
--- a/drivers/staging/greybus/arche-apb-ctrl.c
+++ b/drivers/staging/greybus/arche-apb-ctrl.c
@@ -470,7 +470,7 @@ MODULE_DEVICE_TABLE(of, arche_apb_ctrl_of_match);
static struct platform_driver arche_apb_ctrl_device_driver = {
.probe = arche_apb_ctrl_probe,
- .remove_new = arche_apb_ctrl_remove,
+ .remove = arche_apb_ctrl_remove,
.shutdown = arche_apb_ctrl_shutdown,
.driver = {
.name = "arche-apb-ctrl",
diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c
index b33977ccd527..d48464390f58 100644
--- a/drivers/staging/greybus/arche-platform.c
+++ b/drivers/staging/greybus/arche-platform.c
@@ -623,7 +623,7 @@ MODULE_DEVICE_TABLE(of, arche_platform_of_match);
static struct platform_driver arche_platform_device_driver = {
.probe = arche_platform_probe,
- .remove_new = arche_platform_remove,
+ .remove = arche_platform_remove,
.shutdown = arche_platform_shutdown,
.driver = {
.name = "arche-platform-ctrl",
diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c
index 9b26e148d40f..16bcf7fc8158 100644
--- a/drivers/staging/greybus/gpio.c
+++ b/drivers/staging/greybus/gpio.c
@@ -42,11 +42,6 @@ struct gb_gpio_controller {
struct mutex irq_lock;
};
-static inline struct gb_gpio_controller *gpio_chip_to_gb_gpio_controller(struct gpio_chip *chip)
-{
- return container_of(chip, struct gb_gpio_controller, chip);
-}
-
static struct gpio_chip *irq_data_to_gpio_chip(struct irq_data *d)
{
return d->domain->host_data;
@@ -278,7 +273,7 @@ static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc,
static void gb_gpio_irq_mask(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
struct gb_gpio_line *line = &ggc->lines[d->hwirq];
line->masked = true;
@@ -288,7 +283,7 @@ static void gb_gpio_irq_mask(struct irq_data *d)
static void gb_gpio_irq_unmask(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
struct gb_gpio_line *line = &ggc->lines[d->hwirq];
line->masked = false;
@@ -298,7 +293,7 @@ static void gb_gpio_irq_unmask(struct irq_data *d)
static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
struct gb_gpio_line *line = &ggc->lines[d->hwirq];
struct device *dev = &ggc->gbphy_dev->dev;
u8 irq_type;
@@ -336,7 +331,7 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
static void gb_gpio_irq_bus_lock(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
mutex_lock(&ggc->irq_lock);
}
@@ -344,7 +339,7 @@ static void gb_gpio_irq_bus_lock(struct irq_data *d)
static void gb_gpio_irq_bus_sync_unlock(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
struct gb_gpio_line *line = &ggc->lines[d->hwirq];
if (line->irq_type_pending) {
@@ -407,21 +402,21 @@ static int gb_gpio_request_handler(struct gb_operation *op)
static int gb_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
return gb_gpio_activate_operation(ggc, (u8)offset);
}
static void gb_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
gb_gpio_deactivate_operation(ggc, (u8)offset);
}
static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
u8 which;
int ret;
@@ -435,7 +430,7 @@ static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
return gb_gpio_direction_in_operation(ggc, (u8)offset);
}
@@ -443,14 +438,14 @@ static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
int value)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
return gb_gpio_direction_out_operation(ggc, (u8)offset, !!value);
}
static int gb_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
u8 which;
int ret;
@@ -464,7 +459,7 @@ static int gb_gpio_get(struct gpio_chip *chip, unsigned int offset)
static void gb_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
gb_gpio_set_value_operation(ggc, (u8)offset, !!value);
}
@@ -472,7 +467,7 @@ static void gb_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
static int gb_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
@@ -579,7 +574,7 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev,
if (ret)
goto exit_line_free;
- ret = gpiochip_add_data(gpio, NULL);
+ ret = gpiochip_add_data(gpio, ggc);
if (ret) {
dev_err(&gbphy_dev->dev, "failed to add gpio chip: %d\n", ret);
goto exit_line_free;
diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c
index cdf4ebb93b10..8eab94cb06fa 100644
--- a/drivers/staging/greybus/uart.c
+++ b/drivers/staging/greybus/uart.c
@@ -596,11 +596,13 @@ static int get_serial_info(struct tty_struct *tty,
struct gb_tty *gb_tty = tty->driver_data;
ss->line = gb_tty->minor;
+ mutex_lock(&gb_tty->port.mutex);
ss->close_delay = jiffies_to_msecs(gb_tty->port.close_delay) / 10;
ss->closing_wait =
gb_tty->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
ASYNC_CLOSING_WAIT_NONE :
jiffies_to_msecs(gb_tty->port.closing_wait) / 10;
+ mutex_unlock(&gb_tty->port.mutex);
return 0;
}
diff --git a/drivers/staging/iio/TODO b/drivers/staging/iio/TODO
deleted file mode 100644
index 0fa6a5500bdb..000000000000
--- a/drivers/staging/iio/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-2020-02-25
-
-
-Contact: Jonathan Cameron <jic23@kernel.org>.
-Mailing list: linux-iio@vger.kernel.org
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index 4ae1a7039418..d5544fc2fe98 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -628,9 +628,9 @@ static void ad5933_work(struct work_struct *work)
int scan_count = bitmap_weight(indio_dev->active_scan_mask,
iio_get_masklength(indio_dev));
ret = ad5933_i2c_read(st->client,
- test_bit(1, indio_dev->active_scan_mask) ?
- AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA,
- scan_count * 2, (u8 *)buf);
+ test_bit(1, indio_dev->active_scan_mask) ?
+ AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA,
+ scan_count * 2, (u8 *)buf);
if (ret)
return;
diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
index 712f916f0935..71e6e278a4b3 100644
--- a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
+++ b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
@@ -629,7 +629,7 @@ MODULE_DEVICE_TABLE(of, atmel_isc_of_match);
static struct platform_driver atmel_isc_driver = {
.probe = atmel_isc_probe,
- .remove_new = atmel_isc_remove,
+ .remove = atmel_isc_remove,
.driver = {
.name = "atmel-sama5d2-isc",
.pm = &atmel_isc_dev_pm_ops,
diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
index 9485167d5b7d..1f74c2dd044c 100644
--- a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
+++ b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
@@ -592,7 +592,7 @@ MODULE_DEVICE_TABLE(of, microchip_xisc_of_match);
static struct platform_driver microchip_xisc_driver = {
.probe = microchip_xisc_probe,
- .remove_new = microchip_xisc_remove,
+ .remove = microchip_xisc_remove,
.driver = {
.name = "microchip-sama7g5-xisc",
.pm = &microchip_xisc_dev_pm_ops,
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index 785aac881922..3edbc57be2ca 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -2076,7 +2076,7 @@ MODULE_DEVICE_TABLE(platform, imx_csi_ids);
static struct platform_driver imx_csi_driver = {
.probe = imx_csi_probe,
- .remove_new = imx_csi_remove,
+ .remove = imx_csi_remove,
.id_table = imx_csi_ids,
.driver = {
.name = "imx-ipuv3-csi",
diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
index be54dca11465..a08389b99d14 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -129,7 +129,7 @@ MODULE_DEVICE_TABLE(of, imx_media_dt_ids);
static struct platform_driver imx_media_pdrv = {
.probe = imx_media_probe,
- .remove_new = imx_media_remove,
+ .remove = imx_media_remove,
.driver = {
.name = "imx-media",
.of_match_table = imx_media_dt_ids,
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 0d8b42061623..dd8c7b3233bc 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -836,7 +836,7 @@ static struct platform_driver csi2_driver = {
.of_match_table = csi2_dt_ids,
},
.probe = csi2_probe,
- .remove_new = csi2_remove,
+ .remove = csi2_remove,
};
module_platform_driver(csi2_driver);
diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c
index 52185090129b..6d34a482492e 100644
--- a/drivers/staging/media/meson/vdec/vdec.c
+++ b/drivers/staging/media/meson/vdec/vdec.c
@@ -1117,7 +1117,7 @@ static void vdec_remove(struct platform_device *pdev)
static struct platform_driver meson_vdec_driver = {
.probe = vdec_probe,
- .remove_new = vdec_remove,
+ .remove = vdec_remove,
.driver = {
.name = "meson-vdec",
.of_match_table = vdec_dt_match,
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
index f468af64bbef..f9bef5173bf2 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -1101,7 +1101,7 @@ static const struct dev_pm_ops rkvdec_pm_ops = {
static struct platform_driver rkvdec_driver = {
.probe = rkvdec_probe,
- .remove_new = rkvdec_remove,
+ .remove = rkvdec_remove,
.driver = {
.name = "rkvdec",
.of_match_table = of_rkvdec_match,
diff --git a/drivers/staging/media/starfive/camss/stf-camss.c b/drivers/staging/media/starfive/camss/stf-camss.c
index b6d34145bc19..259aaad010d2 100644
--- a/drivers/staging/media/starfive/camss/stf-camss.c
+++ b/drivers/staging/media/starfive/camss/stf-camss.c
@@ -422,7 +422,7 @@ static const struct dev_pm_ops stfcamss_pm_ops = {
static struct platform_driver stfcamss_driver = {
.probe = stfcamss_probe,
- .remove_new = stfcamss_remove,
+ .remove = stfcamss_remove,
.driver = {
.name = "starfive-camss",
.pm = &stfcamss_pm_ops,
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
index f52df6836045..52a9588462ce 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -705,7 +705,7 @@ static const struct dev_pm_ops cedrus_dev_pm_ops = {
static struct platform_driver cedrus_driver = {
.probe = cedrus_probe,
- .remove_new = cedrus_remove,
+ .remove = cedrus_remove,
.driver = {
.name = CEDRUS_NAME,
.of_match_table = cedrus_dt_match,
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c
index 58f8ae92320d..6877f2beee8c 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c
@@ -536,7 +536,7 @@ MODULE_DEVICE_TABLE(of, sun6i_isp_of_match);
static struct platform_driver sun6i_isp_platform_driver = {
.probe = sun6i_isp_probe,
- .remove_new = sun6i_isp_remove,
+ .remove = sun6i_isp_remove,
.driver = {
.name = SUN6I_ISP_NAME,
.of_match_table = sun6i_isp_of_match,
diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c
index 255cccd0c5fd..604185c00a1a 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -858,5 +858,5 @@ struct platform_driver tegra_csi_driver = {
.pm = &tegra_csi_pm_ops,
},
.probe = tegra_csi_probe,
- .remove_new = tegra_csi_remove,
+ .remove = tegra_csi_remove,
};
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index ad481b35e618..c9276ff76157 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -1977,5 +1977,5 @@ struct platform_driver tegra_vi_driver = {
.pm = &tegra_vi_pm_ops,
},
.probe = tegra_vi_probe,
- .remove_new = tegra_vi_remove,
+ .remove = tegra_vi_remove,
};
diff --git a/drivers/staging/media/tegra-video/vip.c b/drivers/staging/media/tegra-video/vip.c
index 8504b9ea9cea..5ec717f3afd5 100644
--- a/drivers/staging/media/tegra-video/vip.c
+++ b/drivers/staging/media/tegra-video/vip.c
@@ -281,5 +281,5 @@ struct platform_driver tegra_vip_driver = {
.of_match_table = tegra_vip_of_id_table,
},
.probe = tegra_vip_probe,
- .remove_new = tegra_vip_remove,
+ .remove = tegra_vip_remove,
};
diff --git a/drivers/staging/most/TODO b/drivers/staging/most/TODO
index 4fa11a9d2cf7..a6448a05ed46 100644
--- a/drivers/staging/most/TODO
+++ b/drivers/staging/most/TODO
@@ -1,8 +1 @@
* Get through code review with Greg Kroah-Hartman
-
-Contact:
-To:
-Christian Gromm <christian.gromm@microchip.com>
-Cc:
-Michael Fabry <Michael.Fabry@microchip.com>
-Christian Gromm <chris@engineersdelight.de>
diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c
index ed6a9cc88541..dad2abe6c0c9 100644
--- a/drivers/staging/most/dim2/dim2.c
+++ b/drivers/staging/most/dim2/dim2.c
@@ -1090,7 +1090,7 @@ MODULE_DEVICE_TABLE(of, dim2_of_match);
static struct platform_driver dim2_driver = {
.probe = dim2_probe,
- .remove_new = dim2_remove,
+ .remove = dim2_remove,
.driver = {
.name = "hdm_dim2",
.of_match_table = dim2_of_match,
diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c
index ce869280a056..184b2dd11fc3 100644
--- a/drivers/staging/most/i2c/i2c.c
+++ b/drivers/staging/most/i2c/i2c.c
@@ -352,8 +352,8 @@ static void i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id i2c_id[] = {
- { "most_i2c", 0 },
- { }, /* Terminating entry */
+ { "most_i2c" },
+ { } /* Terminating entry */
};
MODULE_DEVICE_TABLE(i2c, i2c_id);
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 977f8fc29e63..263774e6a78c 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -952,7 +952,7 @@ MODULE_DEVICE_TABLE(of, nvidia_nvec_of_match);
static struct platform_driver nvec_device_driver = {
.probe = tegra_nvec_probe,
- .remove_new = tegra_nvec_remove,
+ .remove = tegra_nvec_remove,
.driver = {
.name = "nvec",
.pm = &nvec_pm_ops,
diff --git a/drivers/staging/nvec/nvec_kbd.c b/drivers/staging/nvec/nvec_kbd.c
index d0259c80f810..d2b91318f151 100644
--- a/drivers/staging/nvec/nvec_kbd.c
+++ b/drivers/staging/nvec/nvec_kbd.c
@@ -175,7 +175,7 @@ static void nvec_kbd_remove(struct platform_device *pdev)
static struct platform_driver nvec_kbd_driver = {
.probe = nvec_kbd_probe,
- .remove_new = nvec_kbd_remove,
+ .remove = nvec_kbd_remove,
.driver = {
.name = "nvec-kbd",
},
diff --git a/drivers/staging/nvec/nvec_power.c b/drivers/staging/nvec/nvec_power.c
index 9943b1fff190..e0e67a3eb722 100644
--- a/drivers/staging/nvec/nvec_power.c
+++ b/drivers/staging/nvec/nvec_power.c
@@ -433,7 +433,7 @@ static void nvec_power_remove(struct platform_device *pdev)
static struct platform_driver nvec_power_driver = {
.probe = nvec_power_probe,
- .remove_new = nvec_power_remove,
+ .remove = nvec_power_remove,
.driver = {
.name = "nvec-power",
}
diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c
index f34016c4a26b..575233fa1677 100644
--- a/drivers/staging/nvec/nvec_ps2.c
+++ b/drivers/staging/nvec/nvec_ps2.c
@@ -175,7 +175,7 @@ static SIMPLE_DEV_PM_OPS(nvec_mouse_pm_ops, nvec_mouse_suspend,
static struct platform_driver nvec_mouse_driver = {
.probe = nvec_mouse_probe,
- .remove_new = nvec_mouse_remove,
+ .remove = nvec_mouse_remove,
.driver = {
.name = "nvec-mouse",
.pm = &nvec_mouse_pm_ops,
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index bbf33b88bb7c..261f8dbdc382 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -40,8 +40,8 @@
#define GET_SKBUFF_QOS(skb) 0
#endif
-static void cvm_oct_tx_do_cleanup(unsigned long arg);
-static DECLARE_TASKLET_OLD(cvm_oct_tx_cleanup_tasklet, cvm_oct_tx_do_cleanup);
+static void cvm_oct_tx_do_cleanup(struct tasklet_struct *clean);
+static DECLARE_TASKLET(cvm_oct_tx_cleanup_tasklet, cvm_oct_tx_do_cleanup);
/* Maximum number of SKBs to try to free per xmit packet. */
#define MAX_SKB_TO_FREE (MAX_OUT_QUEUE_DEPTH * 2)
@@ -670,7 +670,7 @@ void cvm_oct_tx_shutdown_dev(struct net_device *dev)
}
}
-static void cvm_oct_tx_do_cleanup(unsigned long arg)
+static void cvm_oct_tx_do_cleanup(struct tasklet_struct *clean)
{
int port;
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index a5e99cc78a45..eadb74fc14c8 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -977,7 +977,7 @@ MODULE_DEVICE_TABLE(of, cvm_oct_match);
static struct platform_driver cvm_oct_driver = {
.probe = cvm_oct_probe,
- .remove_new = cvm_oct_remove,
+ .remove = cvm_oct_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = cvm_oct_match,
diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig
deleted file mode 100644
index d0ba34cc32f7..000000000000
--- a/drivers/staging/olpc_dcon/Kconfig
+++ /dev/null
@@ -1,17 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config FB_OLPC_DCON
- tristate "One Laptop Per Child Display CONtroller support"
- depends on OLPC && FB && BROKEN
- depends on I2C
- depends on GPIO_CS5535 && ACPI
- select BACKLIGHT_CLASS_DEVICE
- help
- In order to support very low power operation, the XO laptop uses a
- secondary Display CONtroller, or DCON. This secondary controller
- is present in the video pipeline between the primary display
- controller (integrate into the processor or chipset) and the LCD
- panel. It allows the main processor/display controller to be
- completely powered off while still retaining an image on the display.
- This controller is only available on OLPC platforms. Unless you have
- one of these platforms, you will want to say 'N'.
-
diff --git a/drivers/staging/olpc_dcon/Makefile b/drivers/staging/olpc_dcon/Makefile
deleted file mode 100644
index 734b2ce26066..000000000000
--- a/drivers/staging/olpc_dcon/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-olpc-dcon-objs += olpc_dcon.o olpc_dcon_xo_1.o olpc_dcon_xo_1_5.o
-obj-$(CONFIG_FB_OLPC_DCON) += olpc-dcon.o
-
-
diff --git a/drivers/staging/olpc_dcon/TODO b/drivers/staging/olpc_dcon/TODO
deleted file mode 100644
index 7c263358b44a..000000000000
--- a/drivers/staging/olpc_dcon/TODO
+++ /dev/null
@@ -1,15 +0,0 @@
-TODO:
- - complete rewrite:
- 1. The underlying fbdev drivers need to be converted into drm kernel
- modesetting drivers.
- 2. The dcon low-power display mode can then be integrated using the
- drm damage tracking and self-refresh helpers.
- This bolted-on self-refresh support that digs around in fbdev
- internals, but isn't properly integrated, is not the correct solution.
- - see if vx855 gpio API can be made similar enough to cs5535 so we can
- share more code
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
-copy:
- Daniel Drake <dsd@laptop.org>
- Jens Frederich <jfrederich@gmail.com>
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
deleted file mode 100644
index 4cb904a5f8f4..000000000000
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ /dev/null
@@ -1,807 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Mainly by David Woodhouse, somewhat modified by Jordan Crouse
- *
- * Copyright © 2006-2007 Red Hat, Inc.
- * Copyright © 2006-2007 Advanced Micro Devices, Inc.
- * Copyright © 2009 VIA Technology, Inc.
- * Copyright (c) 2010-2011 Andres Salomon <dilinger@queued.net>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/backlight.h>
-#include <linux/device.h>
-#include <linux/uaccess.h>
-#include <linux/ctype.h>
-#include <linux/panic_notifier.h>
-#include <linux/reboot.h>
-#include <linux/olpc-ec.h>
-#include <asm/tsc.h>
-#include <asm/olpc.h>
-
-#include "olpc_dcon.h"
-
-/* Module definitions */
-
-static ushort resumeline = 898;
-module_param(resumeline, ushort, 0444);
-
-static struct dcon_platform_data *pdata;
-
-/* I2C structures */
-
-/* Platform devices */
-static struct platform_device *dcon_device;
-
-static unsigned short normal_i2c[] = { 0x0d, I2C_CLIENT_END };
-
-static s32 dcon_write(struct dcon_priv *dcon, u8 reg, u16 val)
-{
- return i2c_smbus_write_word_data(dcon->client, reg, val);
-}
-
-static s32 dcon_read(struct dcon_priv *dcon, u8 reg)
-{
- return i2c_smbus_read_word_data(dcon->client, reg);
-}
-
-/* ===== API functions - these are called by a variety of users ==== */
-
-static int dcon_hw_init(struct dcon_priv *dcon, int is_init)
-{
- u16 ver;
- int rc = 0;
-
- ver = dcon_read(dcon, DCON_REG_ID);
- if ((ver >> 8) != 0xDC) {
- pr_err("DCON ID not 0xDCxx: 0x%04x instead.\n", ver);
- rc = -ENXIO;
- goto err;
- }
-
- if (is_init) {
- pr_info("Discovered DCON version %x\n", ver & 0xFF);
- rc = pdata->init(dcon);
- if (rc != 0) {
- pr_err("Unable to init.\n");
- goto err;
- }
- }
-
- if (ver < 0xdc02) {
- dev_err(&dcon->client->dev,
- "DCON v1 is unsupported, giving up..\n");
- rc = -ENODEV;
- goto err;
- }
-
- /* SDRAM setup/hold time */
- dcon_write(dcon, 0x3a, 0xc040);
- dcon_write(dcon, DCON_REG_MEM_OPT_A, 0x0000); /* clear option bits */
- dcon_write(dcon, DCON_REG_MEM_OPT_A,
- MEM_DLL_CLOCK_DELAY | MEM_POWER_DOWN);
- dcon_write(dcon, DCON_REG_MEM_OPT_B, MEM_SOFT_RESET);
-
- /* Colour swizzle, AA, no passthrough, backlight */
- if (is_init) {
- dcon->disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE |
- MODE_CSWIZZLE | MODE_COL_AA;
- }
- dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
-
- /* Set the scanline to interrupt on during resume */
- dcon_write(dcon, DCON_REG_SCAN_INT, resumeline);
-
-err:
- return rc;
-}
-
-/*
- * The smbus doesn't always come back due to what is believed to be
- * hardware (power rail) bugs. For older models where this is known to
- * occur, our solution is to attempt to wait for the bus to stabilize;
- * if it doesn't happen, cut power to the dcon, repower it, and wait
- * for the bus to stabilize. Rinse, repeat until we have a working
- * smbus. For newer models, we simply BUG(); we want to know if this
- * still happens despite the power fixes that have been made!
- */
-static int dcon_bus_stabilize(struct dcon_priv *dcon, int is_powered_down)
-{
- unsigned long timeout;
- u8 pm;
- int x;
-
-power_up:
- if (is_powered_down) {
- pm = 1;
- x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0);
- if (x) {
- pr_warn("unable to force dcon to power up: %d!\n", x);
- return x;
- }
- usleep_range(10000, 11000); /* we'll be conservative */
- }
-
- pdata->bus_stabilize_wiggle();
-
- for (x = -1, timeout = 50; timeout && x < 0; timeout--) {
- usleep_range(1000, 1100);
- x = dcon_read(dcon, DCON_REG_ID);
- }
- if (x < 0) {
- pr_err("unable to stabilize dcon's smbus, reasserting power and praying.\n");
- BUG_ON(olpc_board_at_least(olpc_board(0xc2)));
- pm = 0;
- olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0);
- msleep(100);
- is_powered_down = 1;
- goto power_up; /* argh, stupid hardware.. */
- }
-
- if (is_powered_down)
- return dcon_hw_init(dcon, 0);
- return 0;
-}
-
-static void dcon_set_backlight(struct dcon_priv *dcon, u8 level)
-{
- dcon->bl_val = level;
- dcon_write(dcon, DCON_REG_BRIGHT, dcon->bl_val);
-
- /* Purposely turn off the backlight when we go to level 0 */
- if (dcon->bl_val == 0) {
- dcon->disp_mode &= ~MODE_BL_ENABLE;
- dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
- } else if (!(dcon->disp_mode & MODE_BL_ENABLE)) {
- dcon->disp_mode |= MODE_BL_ENABLE;
- dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
- }
-}
-
-/* Set the output type to either color or mono */
-static int dcon_set_mono_mode(struct dcon_priv *dcon, bool enable_mono)
-{
- if (dcon->mono == enable_mono)
- return 0;
-
- dcon->mono = enable_mono;
-
- if (enable_mono) {
- dcon->disp_mode &= ~(MODE_CSWIZZLE | MODE_COL_AA);
- dcon->disp_mode |= MODE_MONO_LUMA;
- } else {
- dcon->disp_mode &= ~(MODE_MONO_LUMA);
- dcon->disp_mode |= MODE_CSWIZZLE | MODE_COL_AA;
- }
-
- dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
- return 0;
-}
-
-/* For now, this will be really stupid - we need to address how
- * DCONLOAD works in a sleep and account for it accordingly
- */
-
-static void dcon_sleep(struct dcon_priv *dcon, bool sleep)
-{
- int x;
-
- /* Turn off the backlight and put the DCON to sleep */
-
- if (dcon->asleep == sleep)
- return;
-
- if (!olpc_board_at_least(olpc_board(0xc2)))
- return;
-
- if (sleep) {
- u8 pm = 0;
-
- x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0);
- if (x)
- pr_warn("unable to force dcon to power down: %d!\n", x);
- else
- dcon->asleep = sleep;
- } else {
- /* Only re-enable the backlight if the backlight value is set */
- if (dcon->bl_val != 0)
- dcon->disp_mode |= MODE_BL_ENABLE;
- x = dcon_bus_stabilize(dcon, 1);
- if (x)
- pr_warn("unable to reinit dcon hardware: %d!\n", x);
- else
- dcon->asleep = sleep;
-
- /* Restore backlight */
- dcon_set_backlight(dcon, dcon->bl_val);
- }
-
- /* We should turn off some stuff in the framebuffer - but what? */
-}
-
-/* the DCON seems to get confused if we change DCONLOAD too
- * frequently -- i.e., approximately faster than frame time.
- * normally we don't change it this fast, so in general we won't
- * delay here.
- */
-static void dcon_load_holdoff(struct dcon_priv *dcon)
-{
- ktime_t delta_t, now;
-
- while (1) {
- now = ktime_get();
- delta_t = ktime_sub(now, dcon->load_time);
- if (ktime_to_ns(delta_t) > NSEC_PER_MSEC * 20)
- break;
- mdelay(4);
- }
-}
-
-static bool dcon_blank_fb(struct dcon_priv *dcon, bool blank)
-{
- int err;
-
- console_lock();
- lock_fb_info(dcon->fbinfo);
-
- dcon->ignore_fb_events = true;
- err = fb_blank(dcon->fbinfo,
- blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
- dcon->ignore_fb_events = false;
- unlock_fb_info(dcon->fbinfo);
- console_unlock();
-
- if (err) {
- dev_err(&dcon->client->dev, "couldn't %sblank framebuffer\n",
- blank ? "" : "un");
- return false;
- }
- return true;
-}
-
-/* Set the source of the display (CPU or DCON) */
-static void dcon_source_switch(struct work_struct *work)
-{
- struct dcon_priv *dcon = container_of(work, struct dcon_priv,
- switch_source);
- int source = dcon->pending_src;
-
- if (dcon->curr_src == source)
- return;
-
- dcon_load_holdoff(dcon);
-
- dcon->switched = false;
-
- switch (source) {
- case DCON_SOURCE_CPU:
- pr_info("%s to CPU\n", __func__);
- /* Enable the scanline interrupt bit */
- if (dcon_write(dcon, DCON_REG_MODE,
- dcon->disp_mode | MODE_SCAN_INT))
- pr_err("couldn't enable scanline interrupt!\n");
- else
- /* Wait up to one second for the scanline interrupt */
- wait_event_timeout(dcon->waitq, dcon->switched, HZ);
-
- if (!dcon->switched)
- pr_err("Timeout entering CPU mode; expect a screen glitch.\n");
-
- /* Turn off the scanline interrupt */
- if (dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode))
- pr_err("couldn't disable scanline interrupt!\n");
-
- /*
- * Ideally we'd like to disable interrupts here so that the
- * fb unblanking and DCON turn on happen at a known time value;
- * however, we can't do that right now with fb_blank
- * messing with semaphores.
- *
- * For now, we just hope..
- */
- if (!dcon_blank_fb(dcon, false)) {
- pr_err("Failed to enter CPU mode\n");
- dcon->pending_src = DCON_SOURCE_DCON;
- return;
- }
-
- /* And turn off the DCON */
- pdata->set_dconload(1);
- dcon->load_time = ktime_get();
-
- pr_info("The CPU has control\n");
- break;
- case DCON_SOURCE_DCON:
- {
- ktime_t delta_t;
-
- pr_info("%s to DCON\n", __func__);
-
- /* Clear DCONLOAD - this implies that the DCON is in control */
- pdata->set_dconload(0);
- dcon->load_time = ktime_get();
-
- wait_event_timeout(dcon->waitq, dcon->switched, HZ / 2);
-
- if (!dcon->switched) {
- pr_err("Timeout entering DCON mode; expect a screen glitch.\n");
- } else {
- /* sometimes the DCON doesn't follow its own rules,
- * and doesn't wait for two vsync pulses before
- * ack'ing the frame load with an IRQ. the result
- * is that the display shows the *previously*
- * loaded frame. we can detect this by looking at
- * the time between asserting DCONLOAD and the IRQ --
- * if it's less than 20msec, then the DCON couldn't
- * have seen two VSYNC pulses. in that case we
- * deassert and reassert, and hope for the best.
- * see http://dev.laptop.org/ticket/9664
- */
- delta_t = ktime_sub(dcon->irq_time, dcon->load_time);
- if (dcon->switched && ktime_to_ns(delta_t)
- < NSEC_PER_MSEC * 20) {
- pr_err("missed loading, retrying\n");
- pdata->set_dconload(1);
- mdelay(41);
- pdata->set_dconload(0);
- dcon->load_time = ktime_get();
- mdelay(41);
- }
- }
-
- dcon_blank_fb(dcon, true);
- pr_info("The DCON has control\n");
- break;
- }
- default:
- BUG();
- }
-
- dcon->curr_src = source;
-}
-
-static void dcon_set_source(struct dcon_priv *dcon, int arg)
-{
- if (dcon->pending_src == arg)
- return;
-
- dcon->pending_src = arg;
-
- if (dcon->curr_src != arg)
- schedule_work(&dcon->switch_source);
-}
-
-static void dcon_set_source_sync(struct dcon_priv *dcon, int arg)
-{
- dcon_set_source(dcon, arg);
- flush_work(&dcon->switch_source);
-}
-
-static ssize_t dcon_mode_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
-
- return sprintf(buf, "%4.4X\n", dcon->disp_mode);
-}
-
-static ssize_t dcon_sleep_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", dcon->asleep);
-}
-
-static ssize_t dcon_freeze_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", dcon->curr_src == DCON_SOURCE_DCON ? 1 : 0);
-}
-
-static ssize_t dcon_mono_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", dcon->mono);
-}
-
-static ssize_t dcon_resumeline_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%d\n", resumeline);
-}
-
-static ssize_t dcon_mono_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned long enable_mono;
- int rc;
-
- rc = kstrtoul(buf, 10, &enable_mono);
- if (rc)
- return rc;
-
- dcon_set_mono_mode(dev_get_drvdata(dev), enable_mono ? true : false);
-
- return count;
-}
-
-static ssize_t dcon_freeze_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
- unsigned long output;
- int ret;
-
- ret = kstrtoul(buf, 10, &output);
- if (ret)
- return ret;
-
- switch (output) {
- case 0:
- dcon_set_source(dcon, DCON_SOURCE_CPU);
- break;
- case 1:
- dcon_set_source_sync(dcon, DCON_SOURCE_DCON);
- break;
- case 2: /* normally unused */
- dcon_set_source(dcon, DCON_SOURCE_DCON);
- break;
- default:
- return -EINVAL;
- }
-
- return count;
-}
-
-static ssize_t dcon_resumeline_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned short rl;
- int rc;
-
- rc = kstrtou16(buf, 10, &rl);
- if (rc)
- return rc;
-
- resumeline = rl;
- dcon_write(dev_get_drvdata(dev), DCON_REG_SCAN_INT, resumeline);
-
- return count;
-}
-
-static ssize_t dcon_sleep_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned long output;
- int ret;
-
- ret = kstrtoul(buf, 10, &output);
- if (ret)
- return ret;
-
- dcon_sleep(dev_get_drvdata(dev), output ? true : false);
- return count;
-}
-
-static struct device_attribute dcon_device_files[] = {
- __ATTR(mode, 0444, dcon_mode_show, NULL),
- __ATTR(sleep, 0644, dcon_sleep_show, dcon_sleep_store),
- __ATTR(freeze, 0644, dcon_freeze_show, dcon_freeze_store),
- __ATTR(monochrome, 0644, dcon_mono_show, dcon_mono_store),
- __ATTR(resumeline, 0644, dcon_resumeline_show, dcon_resumeline_store),
-};
-
-static int dcon_bl_update(struct backlight_device *dev)
-{
- struct dcon_priv *dcon = bl_get_data(dev);
- u8 level = backlight_get_brightness(dev) & 0x0F;
-
- if (level != dcon->bl_val)
- dcon_set_backlight(dcon, level);
-
- /* power down the DCON when the screen is blanked */
- if (!dcon->ignore_fb_events)
- dcon_sleep(dcon, !!(dev->props.state & BL_CORE_FBBLANK));
-
- return 0;
-}
-
-static int dcon_bl_get(struct backlight_device *dev)
-{
- struct dcon_priv *dcon = bl_get_data(dev);
-
- return dcon->bl_val;
-}
-
-static const struct backlight_ops dcon_bl_ops = {
- .update_status = dcon_bl_update,
- .get_brightness = dcon_bl_get,
-};
-
-static struct backlight_properties dcon_bl_props = {
- .max_brightness = 15,
- .type = BACKLIGHT_RAW,
- .power = BACKLIGHT_POWER_ON,
-};
-
-static int dcon_reboot_notify(struct notifier_block *nb,
- unsigned long foo, void *bar)
-{
- struct dcon_priv *dcon = container_of(nb, struct dcon_priv, reboot_nb);
-
- if (!dcon || !dcon->client)
- return NOTIFY_DONE;
-
- /* Turn off the DCON. Entirely. */
- dcon_write(dcon, DCON_REG_MODE, 0x39);
- dcon_write(dcon, DCON_REG_MODE, 0x32);
- return NOTIFY_DONE;
-}
-
-static int unfreeze_on_panic(struct notifier_block *nb,
- unsigned long e, void *p)
-{
- pdata->set_dconload(1);
- return NOTIFY_DONE;
-}
-
-static struct notifier_block dcon_panic_nb = {
- .notifier_call = unfreeze_on_panic,
-};
-
-static int dcon_detect(struct i2c_client *client, struct i2c_board_info *info)
-{
- strscpy(info->type, "olpc_dcon", I2C_NAME_SIZE);
-
- return 0;
-}
-
-static int dcon_probe(struct i2c_client *client)
-{
- struct dcon_priv *dcon;
- int rc, i, j;
-
- if (!pdata)
- return -ENXIO;
-
- dcon = kzalloc(sizeof(*dcon), GFP_KERNEL);
- if (!dcon)
- return -ENOMEM;
-
- dcon->client = client;
- init_waitqueue_head(&dcon->waitq);
- INIT_WORK(&dcon->switch_source, dcon_source_switch);
- dcon->reboot_nb.notifier_call = dcon_reboot_notify;
- dcon->reboot_nb.priority = -1;
-
- i2c_set_clientdata(client, dcon);
-
- if (num_registered_fb < 1) {
- dev_err(&client->dev, "DCON driver requires a registered fb\n");
- rc = -EIO;
- goto einit;
- }
- dcon->fbinfo = registered_fb[0];
-
- rc = dcon_hw_init(dcon, 1);
- if (rc)
- goto einit;
-
- /* Add the DCON device */
-
- dcon_device = platform_device_alloc("dcon", -1);
-
- if (!dcon_device) {
- pr_err("Unable to create the DCON device\n");
- rc = -ENOMEM;
- goto eirq;
- }
- rc = platform_device_add(dcon_device);
- platform_set_drvdata(dcon_device, dcon);
-
- if (rc) {
- pr_err("Unable to add the DCON device\n");
- goto edev;
- }
-
- for (i = 0; i < ARRAY_SIZE(dcon_device_files); i++) {
- rc = device_create_file(&dcon_device->dev,
- &dcon_device_files[i]);
- if (rc) {
- dev_err(&dcon_device->dev, "Cannot create sysfs file\n");
- goto ecreate;
- }
- }
-
- dcon->bl_val = dcon_read(dcon, DCON_REG_BRIGHT) & 0x0F;
-
- /* Add the backlight device for the DCON */
- dcon_bl_props.brightness = dcon->bl_val;
- dcon->bl_dev = backlight_device_register("dcon-bl", &dcon_device->dev,
- dcon, &dcon_bl_ops,
- &dcon_bl_props);
- if (IS_ERR(dcon->bl_dev)) {
- dev_err(&client->dev, "cannot register backlight dev (%ld)\n",
- PTR_ERR(dcon->bl_dev));
- dcon->bl_dev = NULL;
- }
-
- register_reboot_notifier(&dcon->reboot_nb);
- atomic_notifier_chain_register(&panic_notifier_list, &dcon_panic_nb);
-
- return 0;
-
- ecreate:
- for (j = 0; j < i; j++)
- device_remove_file(&dcon_device->dev, &dcon_device_files[j]);
- platform_device_del(dcon_device);
- edev:
- platform_device_put(dcon_device);
- dcon_device = NULL;
- eirq:
- free_irq(DCON_IRQ, dcon);
- einit:
- kfree(dcon);
- return rc;
-}
-
-static void dcon_remove(struct i2c_client *client)
-{
- struct dcon_priv *dcon = i2c_get_clientdata(client);
-
- unregister_reboot_notifier(&dcon->reboot_nb);
- atomic_notifier_chain_unregister(&panic_notifier_list, &dcon_panic_nb);
-
- free_irq(DCON_IRQ, dcon);
-
- backlight_device_unregister(dcon->bl_dev);
-
- if (dcon_device)
- platform_device_unregister(dcon_device);
- cancel_work_sync(&dcon->switch_source);
-
- kfree(dcon);
-}
-
-#ifdef CONFIG_PM
-static int dcon_suspend(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct dcon_priv *dcon = i2c_get_clientdata(client);
-
- if (!dcon->asleep) {
- /* Set up the DCON to have the source */
- dcon_set_source_sync(dcon, DCON_SOURCE_DCON);
- }
-
- return 0;
-}
-
-static int dcon_resume(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct dcon_priv *dcon = i2c_get_clientdata(client);
-
- if (!dcon->asleep) {
- dcon_bus_stabilize(dcon, 0);
- dcon_set_source(dcon, DCON_SOURCE_CPU);
- }
-
- return 0;
-}
-
-#else
-
-#define dcon_suspend NULL
-#define dcon_resume NULL
-
-#endif /* CONFIG_PM */
-
-irqreturn_t dcon_interrupt(int irq, void *id)
-{
- struct dcon_priv *dcon = id;
- u8 status;
-
- if (pdata->read_status(&status))
- return IRQ_NONE;
-
- switch (status & 3) {
- case 3:
- pr_debug("DCONLOAD_MISSED interrupt\n");
- break;
-
- case 2: /* switch to DCON mode */
- case 1: /* switch to CPU mode */
- dcon->switched = true;
- dcon->irq_time = ktime_get();
- wake_up(&dcon->waitq);
- break;
-
- case 0:
- /* workaround resume case: the DCON (on 1.5) doesn't
- * ever assert status 0x01 when switching to CPU mode
- * during resume. this is because DCONLOAD is de-asserted
- * _immediately_ upon exiting S3, so the actual release
- * of the DCON happened long before this point.
- * see http://dev.laptop.org/ticket/9869
- */
- if (dcon->curr_src != dcon->pending_src && !dcon->switched) {
- dcon->switched = true;
- dcon->irq_time = ktime_get();
- wake_up(&dcon->waitq);
- pr_debug("switching w/ status 0/0\n");
- } else {
- pr_debug("scanline interrupt w/CPU\n");
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static const struct dev_pm_ops dcon_pm_ops = {
- .suspend = dcon_suspend,
- .resume = dcon_resume,
-};
-
-static const struct i2c_device_id dcon_idtable[] = {
- { "olpc_dcon", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, dcon_idtable);
-
-static struct i2c_driver dcon_driver = {
- .driver = {
- .name = "olpc_dcon",
- .pm = &dcon_pm_ops,
- },
- .class = I2C_CLASS_HWMON,
- .id_table = dcon_idtable,
- .probe = dcon_probe,
- .remove = dcon_remove,
- .detect = dcon_detect,
- .address_list = normal_i2c,
-};
-
-static int __init olpc_dcon_init(void)
-{
- /* XO-1.5 */
- if (olpc_board_at_least(olpc_board(0xd0)))
- pdata = &dcon_pdata_xo_1_5;
- else
- pdata = &dcon_pdata_xo_1;
-
- return i2c_add_driver(&dcon_driver);
-}
-
-static void __exit olpc_dcon_exit(void)
-{
- i2c_del_driver(&dcon_driver);
-}
-
-module_init(olpc_dcon_init);
-module_exit(olpc_dcon_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h
deleted file mode 100644
index 41bd1360b56e..000000000000
--- a/drivers/staging/olpc_dcon/olpc_dcon.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef OLPC_DCON_H_
-#define OLPC_DCON_H_
-
-#include <linux/notifier.h>
-#include <linux/workqueue.h>
-
-/* DCON registers */
-
-#define DCON_REG_ID 0
-#define DCON_REG_MODE 1
-
-#define MODE_PASSTHRU BIT(0)
-#define MODE_SLEEP BIT(1)
-#define MODE_SLEEP_AUTO BIT(2)
-#define MODE_BL_ENABLE BIT(3)
-#define MODE_BLANK BIT(4)
-#define MODE_CSWIZZLE BIT(5)
-#define MODE_COL_AA BIT(6)
-#define MODE_MONO_LUMA BIT(7)
-#define MODE_SCAN_INT BIT(8)
-#define MODE_CLOCKDIV BIT(9)
-#define MODE_DEBUG BIT(14)
-#define MODE_SELFTEST BIT(15)
-
-#define DCON_REG_HRES 0x2
-#define DCON_REG_HTOTAL 0x3
-#define DCON_REG_HSYNC_WIDTH 0x4
-#define DCON_REG_VRES 0x5
-#define DCON_REG_VTOTAL 0x6
-#define DCON_REG_VSYNC_WIDTH 0x7
-#define DCON_REG_TIMEOUT 0x8
-#define DCON_REG_SCAN_INT 0x9
-#define DCON_REG_BRIGHT 0xa
-#define DCON_REG_MEM_OPT_A 0x41
-#define DCON_REG_MEM_OPT_B 0x42
-
-/* Load Delay Locked Loop (DLL) settings for clock delay */
-#define MEM_DLL_CLOCK_DELAY BIT(0)
-/* Memory controller power down function */
-#define MEM_POWER_DOWN BIT(8)
-/* Memory controller software reset */
-#define MEM_SOFT_RESET BIT(0)
-
-/* Status values */
-
-#define DCONSTAT_SCANINT 0
-#define DCONSTAT_SCANINT_DCON 1
-#define DCONSTAT_DISPLAYLOAD 2
-#define DCONSTAT_MISSED 3
-
-/* Source values */
-
-#define DCON_SOURCE_DCON 0
-#define DCON_SOURCE_CPU 1
-
-/* Interrupt */
-#define DCON_IRQ 6
-
-struct dcon_priv {
- struct i2c_client *client;
- struct fb_info *fbinfo;
- struct backlight_device *bl_dev;
-
- wait_queue_head_t waitq;
- struct work_struct switch_source;
- struct notifier_block reboot_nb;
-
- /* Shadow register for the DCON_REG_MODE register */
- u8 disp_mode;
-
- /* The current backlight value - this saves us some smbus traffic */
- u8 bl_val;
-
- /* Current source, initialized at probe time */
- int curr_src;
-
- /* Desired source */
- int pending_src;
-
- /* Variables used during switches */
- bool switched;
- ktime_t irq_time;
- ktime_t load_time;
-
- /* Current output type; true == mono, false == color */
- bool mono;
- bool asleep;
- /* This get set while controlling fb blank state from the driver */
- bool ignore_fb_events;
-};
-
-struct dcon_platform_data {
- int (*init)(struct dcon_priv *dcon);
- void (*bus_stabilize_wiggle)(void);
- void (*set_dconload)(int load);
- int (*read_status)(u8 *status);
-};
-
-struct dcon_gpio {
- const char *name;
- unsigned long flags;
-};
-
-#include <linux/interrupt.h>
-
-irqreturn_t dcon_interrupt(int irq, void *id);
-
-extern struct dcon_platform_data dcon_pdata_xo_1;
-extern struct dcon_platform_data dcon_pdata_xo_1_5;
-
-#endif
diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
deleted file mode 100644
index 02c059897784..000000000000
--- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
+++ /dev/null
@@ -1,201 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Mainly by David Woodhouse, somewhat modified by Jordan Crouse
- *
- * Copyright © 2006-2007 Red Hat, Inc.
- * Copyright © 2006-2007 Advanced Micro Devices, Inc.
- * Copyright © 2009 VIA Technology, Inc.
- * Copyright (c) 2010 Andres Salomon <dilinger@queued.net>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/cs5535.h>
-#include <linux/gpio/consumer.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <asm/olpc.h>
-
-#include "olpc_dcon.h"
-
-enum dcon_gpios {
- OLPC_DCON_STAT0,
- OLPC_DCON_STAT1,
- OLPC_DCON_IRQ,
- OLPC_DCON_LOAD,
- OLPC_DCON_BLANK,
-};
-
-static const struct dcon_gpio gpios_asis[] = {
- [OLPC_DCON_STAT0] = { .name = "dcon_stat0", .flags = GPIOD_ASIS },
- [OLPC_DCON_STAT1] = { .name = "dcon_stat1", .flags = GPIOD_ASIS },
- [OLPC_DCON_IRQ] = { .name = "dcon_irq", .flags = GPIOD_ASIS },
- [OLPC_DCON_LOAD] = { .name = "dcon_load", .flags = GPIOD_ASIS },
- [OLPC_DCON_BLANK] = { .name = "dcon_blank", .flags = GPIOD_ASIS },
-};
-
-static struct gpio_desc *gpios[5];
-
-static int dcon_init_xo_1(struct dcon_priv *dcon)
-{
- unsigned char lob;
- int ret, i;
- const struct dcon_gpio *pin = &gpios_asis[0];
-
- for (i = 0; i < ARRAY_SIZE(gpios_asis); i++) {
- gpios[i] = devm_gpiod_get(&dcon->client->dev, pin[i].name,
- pin[i].flags);
- if (IS_ERR(gpios[i])) {
- ret = PTR_ERR(gpios[i]);
- pr_err("failed to request %s GPIO: %d\n", pin[i].name,
- ret);
- return ret;
- }
- }
-
- /* Turn off the event enable for GPIO7 just to be safe */
- cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE);
-
- /*
- * Determine the current state by reading the GPIO bit; earlier
- * stages of the boot process have established the state.
- *
- * Note that we read GPIO_OUTPUT_VAL rather than GPIO_READ_BACK here;
- * this is because OFW will disable input for the pin and set a value..
- * READ_BACK will only contain a valid value if input is enabled and
- * then a value is set. So, future readings of the pin can use
- * READ_BACK, but the first one cannot. Awesome, huh?
- */
- dcon->curr_src = cs5535_gpio_isset(OLPC_GPIO_DCON_LOAD, GPIO_OUTPUT_VAL)
- ? DCON_SOURCE_CPU
- : DCON_SOURCE_DCON;
- dcon->pending_src = dcon->curr_src;
-
- /* Set the directions for the GPIO pins */
- gpiod_direction_input(gpios[OLPC_DCON_STAT0]);
- gpiod_direction_input(gpios[OLPC_DCON_STAT1]);
- gpiod_direction_input(gpios[OLPC_DCON_IRQ]);
- gpiod_direction_input(gpios[OLPC_DCON_BLANK]);
- gpiod_direction_output(gpios[OLPC_DCON_LOAD],
- dcon->curr_src == DCON_SOURCE_CPU);
-
- /* Set up the interrupt mappings */
-
- /* Set the IRQ to pair 2 */
- cs5535_gpio_setup_event(OLPC_GPIO_DCON_IRQ, 2, 0);
-
- /* Enable group 2 to trigger the DCON interrupt */
- cs5535_gpio_set_irq(2, DCON_IRQ);
-
- /* Select edge level for interrupt (in PIC) */
- lob = inb(0x4d0);
- lob &= ~(1 << DCON_IRQ);
- outb(lob, 0x4d0);
-
- /* Register the interrupt handler */
- if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", dcon)) {
- pr_err("failed to request DCON's irq\n");
- return -EIO;
- }
-
- /* Clear INV_EN for GPIO7 (DCONIRQ) */
- cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_INVERT);
-
- /* Enable filter for GPIO12 (DCONBLANK) */
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_FILTER);
-
- /* Disable filter for GPIO7 */
- cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_FILTER);
-
- /* Disable event counter for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */
- cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_EVENT_COUNT);
- cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_EVENT_COUNT);
-
- /* Add GPIO12 to the Filter Event Pair #7 */
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_FE7_SEL);
-
- /* Turn off negative Edge Enable for GPIO12 */
- cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_EN);
-
- /* Enable negative Edge Enable for GPIO7 */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_EN);
-
- /* Zero the filter amount for Filter Event Pair #7 */
- cs5535_gpio_set(0, GPIO_FLTR7_AMOUNT);
-
- /* Clear the negative edge status for GPIO7 and GPIO12 */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS);
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_STS);
-
- /* FIXME: Clear the positive status as well, just to be sure */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_POSITIVE_EDGE_STS);
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_POSITIVE_EDGE_STS);
-
- /* Enable events for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE);
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_EVENTS_ENABLE);
-
- return 0;
-}
-
-static void dcon_wiggle_xo_1(void)
-{
- int x;
-
- /*
- * According to HiMax, when powering the DCON up we should hold
- * SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON
- * state machine to reset to a (sane) initial state. Mitch Bradley
- * did some testing and discovered that holding for 16 SMB_CLK cycles
- * worked a lot more reliably, so that's what we do here.
- *
- * According to the cs5536 spec, to set GPIO14 to SMB_CLK we must
- * simultaneously set AUX1 IN/OUT to GPIO14; ditto for SMB_DATA and
- * GPIO15.
- */
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL);
- cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_VAL);
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_ENABLE);
- cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_ENABLE);
- cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1);
- cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1);
- cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX2);
- cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX2);
- cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1);
- cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1);
-
- for (x = 0; x < 16; x++) {
- udelay(5);
- cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL);
- udelay(5);
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL);
- }
- udelay(5);
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1);
- cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1);
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1);
- cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1);
-}
-
-static void dcon_set_dconload_1(int val)
-{
- gpiod_set_value(gpios[OLPC_DCON_LOAD], val);
-}
-
-static int dcon_read_status_xo_1(u8 *status)
-{
- *status = gpiod_get_value(gpios[OLPC_DCON_STAT0]);
- *status |= gpiod_get_value(gpios[OLPC_DCON_STAT1]) << 1;
-
- /* Clear the negative edge status for GPIO7 */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS);
-
- return 0;
-}
-
-struct dcon_platform_data dcon_pdata_xo_1 = {
- .init = dcon_init_xo_1,
- .bus_stabilize_wiggle = dcon_wiggle_xo_1,
- .set_dconload = dcon_set_dconload_1,
- .read_status = dcon_read_status_xo_1,
-};
diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
deleted file mode 100644
index 52cdcd2a89d6..000000000000
--- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
+++ /dev/null
@@ -1,204 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2009,2010 One Laptop per Child
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/acpi.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/gpio/consumer.h>
-#include <linux/gpio/machine.h>
-#include <asm/olpc.h>
-
-/* TODO: this eventually belongs in linux/vx855.h */
-#define NR_VX855_GPI 14
-#define NR_VX855_GPO 13
-#define NR_VX855_GPIO 15
-
-#define VX855_GPI(n) (n)
-#define VX855_GPO(n) (NR_VX855_GPI + (n))
-#define VX855_GPIO(n) (NR_VX855_GPI + NR_VX855_GPO + (n))
-
-#include "olpc_dcon.h"
-
-/* Hardware setup on the XO 1.5:
- * DCONLOAD connects to VX855_GPIO1 (not SMBCK2)
- * DCONBLANK connects to VX855_GPIO8 (not SSPICLK) unused in driver
- * DCONSTAT0 connects to VX855_GPI10 (not SSPISDI)
- * DCONSTAT1 connects to VX855_GPI11 (not nSSPISS)
- * DCONIRQ connects to VX855_GPIO12
- * DCONSMBDATA connects to VX855 graphics CRTSPD
- * DCONSMBCLK connects to VX855 graphics CRTSPCLK
- */
-
-#define VX855_GENL_PURPOSE_OUTPUT 0x44c /* PMIO_Rx4c-4f */
-#define VX855_GPI_STATUS_CHG 0x450 /* PMIO_Rx50 */
-#define VX855_GPI_SCI_SMI 0x452 /* PMIO_Rx52 */
-#define BIT_GPIO12 0x40
-
-#define PREFIX "OLPC DCON:"
-
-enum dcon_gpios {
- OLPC_DCON_STAT0,
- OLPC_DCON_STAT1,
- OLPC_DCON_LOAD,
-};
-
-struct gpiod_lookup_table gpios_table = {
- .dev_id = NULL,
- .table = {
- GPIO_LOOKUP("VX855 South Bridge", VX855_GPIO(1), "dcon_load",
- GPIO_ACTIVE_LOW),
- GPIO_LOOKUP("VX855 South Bridge", VX855_GPI(10), "dcon_stat0",
- GPIO_ACTIVE_LOW),
- GPIO_LOOKUP("VX855 South Bridge", VX855_GPI(11), "dcon_stat1",
- GPIO_ACTIVE_LOW),
- { },
- },
-};
-
-static const struct dcon_gpio gpios_asis[] = {
- [OLPC_DCON_STAT0] = { .name = "dcon_stat0", .flags = GPIOD_ASIS },
- [OLPC_DCON_STAT1] = { .name = "dcon_stat1", .flags = GPIOD_ASIS },
- [OLPC_DCON_LOAD] = { .name = "dcon_load", .flags = GPIOD_ASIS },
-};
-
-static struct gpio_desc *gpios[3];
-
-static void dcon_clear_irq(void)
-{
- /* irq status will appear in PMIO_Rx50[6] (RW1C) on gpio12 */
- outb(BIT_GPIO12, VX855_GPI_STATUS_CHG);
-}
-
-static int dcon_was_irq(void)
-{
- u8 tmp;
-
- /* irq status will appear in PMIO_Rx50[6] on gpio12 */
- tmp = inb(VX855_GPI_STATUS_CHG);
-
- return !!(tmp & BIT_GPIO12);
-}
-
-static int dcon_init_xo_1_5(struct dcon_priv *dcon)
-{
- unsigned int irq;
- const struct dcon_gpio *pin = &gpios_asis[0];
- int i;
- int ret;
-
- /* Add GPIO look up table */
- gpios_table.dev_id = dev_name(&dcon->client->dev);
- gpiod_add_lookup_table(&gpios_table);
-
- /* Get GPIO descriptor */
- for (i = 0; i < ARRAY_SIZE(gpios_asis); i++) {
- gpios[i] = devm_gpiod_get(&dcon->client->dev, pin[i].name,
- pin[i].flags);
- if (IS_ERR(gpios[i])) {
- ret = PTR_ERR(gpios[i]);
- pr_err("failed to request %s GPIO: %d\n", pin[i].name,
- ret);
- return ret;
- }
- }
-
- dcon_clear_irq();
-
- /* set PMIO_Rx52[6] to enable SCI/SMI on gpio12 */
- outb(inb(VX855_GPI_SCI_SMI) | BIT_GPIO12, VX855_GPI_SCI_SMI);
-
- /* Determine the current state of DCONLOAD, likely set by firmware */
- /* GPIO1 */
- dcon->curr_src = (inl(VX855_GENL_PURPOSE_OUTPUT) & 0x1000) ?
- DCON_SOURCE_CPU : DCON_SOURCE_DCON;
- dcon->pending_src = dcon->curr_src;
-
- /* we're sharing the IRQ with ACPI */
- irq = acpi_gbl_FADT.sci_interrupt;
- if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", dcon)) {
- pr_err("DCON (IRQ%d) allocation failed\n", irq);
- return 1;
- }
-
- return 0;
-}
-
-static void set_i2c_line(int sda, int scl)
-{
- unsigned char tmp;
- unsigned int port = 0x26;
-
- /* FIXME: This directly accesses the CRT GPIO controller !!! */
- outb(port, 0x3c4);
- tmp = inb(0x3c5);
-
- if (scl)
- tmp |= 0x20;
- else
- tmp &= ~0x20;
-
- if (sda)
- tmp |= 0x10;
- else
- tmp &= ~0x10;
-
- tmp |= 0x01;
-
- outb(port, 0x3c4);
- outb(tmp, 0x3c5);
-}
-
-static void dcon_wiggle_xo_1_5(void)
-{
- int x;
-
- /*
- * According to HiMax, when powering the DCON up we should hold
- * SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON
- * state machine to reset to a (sane) initial state. Mitch Bradley
- * did some testing and discovered that holding for 16 SMB_CLK cycles
- * worked a lot more reliably, so that's what we do here.
- */
- set_i2c_line(1, 1);
-
- for (x = 0; x < 16; x++) {
- udelay(5);
- set_i2c_line(1, 0);
- udelay(5);
- set_i2c_line(1, 1);
- }
- udelay(5);
-
- /* set PMIO_Rx52[6] to enable SCI/SMI on gpio12 */
- outb(inb(VX855_GPI_SCI_SMI) | BIT_GPIO12, VX855_GPI_SCI_SMI);
-}
-
-static void dcon_set_dconload_xo_1_5(int val)
-{
- gpiod_set_value(gpios[OLPC_DCON_LOAD], val);
-}
-
-static int dcon_read_status_xo_1_5(u8 *status)
-{
- if (!dcon_was_irq())
- return -1;
-
- /* i believe this is the same as "inb(0x44b) & 3" */
- *status = gpiod_get_value(gpios[OLPC_DCON_STAT0]);
- *status |= gpiod_get_value(gpios[OLPC_DCON_STAT1]) << 1;
-
- dcon_clear_irq();
-
- return 0;
-}
-
-struct dcon_platform_data dcon_pdata_xo_1_5 = {
- .init = dcon_init_xo_1_5,
- .bus_stabilize_wiggle = dcon_wiggle_xo_1_5,
- .set_dconload = dcon_set_dconload_xo_1_5,
- .read_status = dcon_read_status_xo_1_5,
-};
diff --git a/drivers/staging/rtl8712/Kconfig b/drivers/staging/rtl8712/Kconfig
deleted file mode 100644
index 8de26425225b..000000000000
--- a/drivers/staging/rtl8712/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config R8712U
- tristate "RealTek RTL8712U (RTL8192SU) Wireless LAN NIC driver"
- depends on WLAN && USB && CFG80211
- select WIRELESS_EXT
- select WEXT_PRIV
- select FW_LOADER
- help
- This option adds the Realtek RTL8712 USB device such as the
- D-Link DWA-130.
-
- If built as a module, it will be called r8712u.
-
-config R8712_TX_AGGR
- bool "Realtek RTL8712U Transmit Aggregation code"
- depends on R8712U && BROKEN
- help
- This option provides transmit aggregation for the Realtek
- RTL8712 USB device.
-
-
diff --git a/drivers/staging/rtl8712/Makefile b/drivers/staging/rtl8712/Makefile
deleted file mode 100644
index 3ae216b6621b..000000000000
--- a/drivers/staging/rtl8712/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-r8712u-y := \
- rtl871x_cmd.o \
- rtl8712_cmd.o \
- rtl871x_security.o \
- rtl871x_eeprom.o \
- rtl8712_efuse.o \
- hal_init.o \
- usb_halinit.o \
- usb_ops.o \
- usb_ops_linux.o \
- rtl871x_io.o \
- rtl8712_io.o \
- rtl871x_ioctl_linux.o \
- rtl871x_ioctl_rtl.o \
- rtl871x_ioctl_set.o \
- rtl8712_led.o \
- rtl871x_mlme.o \
- ieee80211.o \
- rtl871x_mp_ioctl.o \
- rtl871x_mp.o \
- mlme_linux.o \
- recv_linux.o \
- xmit_linux.o \
- usb_intf.o \
- os_intfs.o \
- rtl871x_pwrctrl.o \
- rtl8712_recv.o \
- rtl871x_recv.o \
- rtl871x_sta_mgt.o \
- rtl871x_xmit.o \
- rtl8712_xmit.o
-
-obj-$(CONFIG_R8712U) := r8712u.o
-
diff --git a/drivers/staging/rtl8712/TODO b/drivers/staging/rtl8712/TODO
deleted file mode 100644
index 5aed36efa7cb..000000000000
--- a/drivers/staging/rtl8712/TODO
+++ /dev/null
@@ -1,12 +0,0 @@
-TODO:
-- merge Realtek's bugfixes and new features into the driver
-- switch to use MAC80211
-- checkpatch.pl fixes - only a few remain
-
-A replacement for this driver with MAC80211 support is available
-at https://github.com/chunkeey/rtl8192su
-
-Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
-Larry Finger <Larry.Finger@lwfinger.net>,
-Florian Schilhabel <florian.c.schilhabel@googlemail.com> and
-Linux Driver Project Developer List <driverdev-devel@linuxdriverproject.org>.
diff --git a/drivers/staging/rtl8712/basic_types.h b/drivers/staging/rtl8712/basic_types.h
deleted file mode 100644
index aecded87dd4c..000000000000
--- a/drivers/staging/rtl8712/basic_types.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __BASIC_TYPES_H__
-#define __BASIC_TYPES_H__
-
-#include <linux/types.h>
-
-#define sint signed int
-
-/* Should we extend this to be host_addr_t and target_addr_t for case:
- * host : x86_64
- * target : mips64
- */
-#define addr_t unsigned long
-
-#endif /*__BASIC_TYPES_H__*/
-
diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h
deleted file mode 100644
index 76ac798642bd..000000000000
--- a/drivers/staging/rtl8712/drv_types.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-/* ---------------------------------------------------------------------
- *
- * For type defines and data structure defines
- *
- * ---------------------------------------------------------------------
- */
-#ifndef __DRV_TYPES_H__
-#define __DRV_TYPES_H__
-
-struct _adapter;
-
-#include "osdep_service.h"
-#include "wlan_bssdef.h"
-#include "rtl8712_spec.h"
-#include "rtl8712_hal.h"
-#include <linux/mutex.h>
-#include <linux/completion.h>
-
-enum _NIC_VERSION {
- RTL8711_NIC,
- RTL8712_NIC,
- RTL8713_NIC,
- RTL8716_NIC
-};
-
-struct qos_priv {
- /* bit mask option: u-apsd, s-apsd, ts, block ack... */
- unsigned int qos_option;
-};
-
-#include "rtl871x_ht.h"
-#include "rtl871x_cmd.h"
-#include "rtl871x_xmit.h"
-#include "rtl871x_recv.h"
-#include "rtl871x_security.h"
-#include "rtl871x_pwrctrl.h"
-#include "rtl871x_io.h"
-#include "rtl871x_eeprom.h"
-#include "sta_info.h"
-#include "rtl871x_mlme.h"
-#include "rtl871x_mp.h"
-#include "rtl871x_debug.h"
-#include "rtl871x_rf.h"
-#include "rtl871x_event.h"
-#include "rtl871x_led.h"
-
-#define SPEC_DEV_ID_DISABLE_HT BIT(1)
-
-struct specific_device_id {
- u32 flags;
- u16 idVendor;
- u16 idProduct;
-
-};
-
-struct registry_priv {
- u8 chip_version;
- u8 rfintfs;
- u8 lbkmode;
- u8 hci;
- u8 network_mode; /*infra, ad-hoc, auto*/
- struct ndis_802_11_ssid ssid;
- u8 channel;/* ad-hoc support requirement */
- u8 wireless_mode;/* A, B, G, auto */
- u8 vrtl_carrier_sense; /*Enable, Disable, Auto*/
- u8 vcs_type;/*RTS/CTS, CTS-to-self*/
- u16 rts_thresh;
- u16 frag_thresh;
- u8 preamble;/*long, short, auto*/
- u8 scan_mode;/*active, passive*/
- u8 adhoc_tx_pwr;
- u8 soft_ap;
- u8 smart_ps;
- u8 power_mgnt;
- u8 radio_enable;
- u8 long_retry_lmt;
- u8 short_retry_lmt;
- u16 busy_thresh;
- u8 ack_policy;
- u8 mp_mode;
- u8 software_encrypt;
- u8 software_decrypt;
- /* UAPSD */
- u8 wmm_enable;
- u8 uapsd_enable;
- u8 uapsd_max_sp;
- u8 uapsd_acbk_en;
- u8 uapsd_acbe_en;
- u8 uapsd_acvi_en;
- u8 uapsd_acvo_en;
-
- struct wlan_bssid_ex dev_network;
-
- u8 ht_enable;
- u8 cbw40_enable;
- u8 ampdu_enable;/*for tx*/
- u8 rf_config;
- u8 low_power;
- u8 wifi_test;
-};
-
-struct dvobj_priv {
- struct _adapter *padapter;
- u32 nr_endpoint;
- u8 ishighspeed;
- uint (*inirp_init)(struct _adapter *adapter);
- uint (*inirp_deinit)(struct _adapter *adapter);
- struct usb_device *pusbdev;
-};
-
-/**
- * struct _adapter - the main adapter structure for this device.
- *
- * bup: True indicates that the interface is up.
- */
-struct _adapter {
- struct dvobj_priv dvobjpriv;
- struct mlme_priv mlmepriv;
- struct cmd_priv cmdpriv;
- struct evt_priv evtpriv;
- struct io_queue *pio_queue;
- struct xmit_priv xmitpriv;
- struct recv_priv recvpriv;
- struct sta_priv stapriv;
- struct security_priv securitypriv;
- struct registry_priv registrypriv;
- struct wlan_acl_pool acl_list;
- struct pwrctrl_priv pwrctrlpriv;
- struct eeprom_priv eeprompriv;
- struct hal_priv halpriv;
- struct led_priv ledpriv;
- struct mp_priv mppriv;
- bool driver_stopped;
- bool surprise_removed;
- bool suspended;
- u8 eeprom_address_size;
- u8 hw_init_completed;
- struct task_struct *cmd_thread;
- uint (*dvobj_init)(struct _adapter *adapter);
- void (*dvobj_deinit)(struct _adapter *adapter);
- struct net_device *pnetdev;
- int bup;
- struct net_device_stats stats;
- struct iw_statistics iwstats;
- int pid; /*process id from UI*/
- struct work_struct wk_filter_rx_ff0;
- const struct firmware *fw;
- struct usb_interface *pusb_intf;
- struct mutex mutex_start;
- struct completion rtl8712_fw_ready;
- struct completion rx_filter_ready;
-};
-
-static inline u8 *myid(struct eeprom_priv *peepriv)
-{
- return peepriv->mac_addr;
-}
-
-u8 r8712_usb_hal_bus_init(struct _adapter *adapter);
-
-#endif /*__DRV_TYPES_H__*/
-
diff --git a/drivers/staging/rtl8712/ethernet.h b/drivers/staging/rtl8712/ethernet.h
deleted file mode 100644
index 4b9b8a97a0bc..000000000000
--- a/drivers/staging/rtl8712/ethernet.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __INC_ETHERNET_H
-#define __INC_ETHERNET_H
-
-#define ETHERNET_HEADER_SIZE 14 /*!< Ethernet Header Length*/
-#define LLC_HEADER_SIZE 6 /*!< LLC Header Length*/
-
-#endif /* #ifndef __INC_ETHERNET_H */
-
diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c
deleted file mode 100644
index 1148075f0cd6..000000000000
--- a/drivers/staging/rtl8712/hal_init.c
+++ /dev/null
@@ -1,401 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _HAL_INIT_C_
-
-#include <linux/usb.h>
-#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/firmware.h>
-#include <linux/module.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "usb_osintf.h"
-
-#define FWBUFF_ALIGN_SZ 512
-#define MAX_DUMP_FWSZ (48 * 1024)
-
-static void rtl871x_load_fw_fail(struct _adapter *adapter)
-{
- struct usb_device *udev = adapter->dvobjpriv.pusbdev;
- struct device *dev = &udev->dev;
- struct device *parent = dev->parent;
-
- complete(&adapter->rtl8712_fw_ready);
-
- dev_err(&udev->dev, "r8712u: Firmware request failed\n");
-
- if (parent)
- device_lock(parent);
-
- device_release_driver(dev);
-
- if (parent)
- device_unlock(parent);
-}
-
-static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
-{
- struct _adapter *adapter = context;
-
- if (!firmware) {
- rtl871x_load_fw_fail(adapter);
- return;
- }
- adapter->fw = firmware;
- /* firmware available - start netdev */
- register_netdev(adapter->pnetdev);
- complete(&adapter->rtl8712_fw_ready);
-}
-
-static const char firmware_file[] = "rtlwifi/rtl8712u.bin";
-
-int rtl871x_load_fw(struct _adapter *padapter)
-{
- struct device *dev = &padapter->dvobjpriv.pusbdev->dev;
- int rc;
-
- init_completion(&padapter->rtl8712_fw_ready);
- dev_info(dev, "r8712u: Loading firmware from \"%s\"\n", firmware_file);
- rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev,
- GFP_KERNEL, padapter, rtl871x_load_fw_cb);
- if (rc)
- dev_err(dev, "r8712u: Firmware request error %d\n", rc);
- return rc;
-}
-MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
-
-static u32 rtl871x_open_fw(struct _adapter *adapter, const u8 **mappedfw)
-{
- if (adapter->fw->size > 200000) {
- dev_err(&adapter->pnetdev->dev, "r8712u: Bad fw->size of %zu\n",
- adapter->fw->size);
- return 0;
- }
- *mappedfw = adapter->fw->data;
- return adapter->fw->size;
-}
-
-static void fill_fwpriv(struct _adapter *adapter, struct fw_priv *fwpriv)
-{
- struct dvobj_priv *dvobj = &adapter->dvobjpriv;
- struct registry_priv *regpriv = &adapter->registrypriv;
-
- memset(fwpriv, 0, sizeof(struct fw_priv));
- /* todo: check if needs endian conversion */
- fwpriv->hci_sel = RTL8712_HCI_TYPE_72USB;
- fwpriv->usb_ep_num = (u8)dvobj->nr_endpoint;
- fwpriv->bw_40MHz_en = regpriv->cbw40_enable;
- switch (regpriv->rf_config) {
- case RTL8712_RF_1T1R:
- fwpriv->rf_config = RTL8712_RFC_1T1R;
- break;
- case RTL8712_RF_2T2R:
- fwpriv->rf_config = RTL8712_RFC_2T2R;
- break;
- case RTL8712_RF_1T2R:
- default:
- fwpriv->rf_config = RTL8712_RFC_1T2R;
- }
- fwpriv->mp_mode = (regpriv->mp_mode == 1);
- /* 0:off 1:on 2:auto */
- fwpriv->vcs_type = regpriv->vrtl_carrier_sense;
- fwpriv->vcs_mode = regpriv->vcs_type; /* 1:RTS/CTS 2:CTS to self */
- /* default enable turbo_mode */
- fwpriv->turbo_mode = (regpriv->wifi_test != 1);
- fwpriv->low_power_mode = regpriv->low_power;
-}
-
-static void update_fwhdr(struct fw_hdr *pfwhdr, const u8 *pmappedfw)
-{
- pfwhdr->signature = le16_to_cpu(*(__le16 *)pmappedfw);
- pfwhdr->version = le16_to_cpu(*(__le16 *)(pmappedfw + 2));
- /* define the size of boot loader */
- pfwhdr->dmem_size = le32_to_cpu(*(__le32 *)(pmappedfw + 4));
- /* define the size of FW in IMEM */
- pfwhdr->img_IMEM_size = le32_to_cpu(*(__le32 *)(pmappedfw + 8));
- /* define the size of FW in SRAM */
- pfwhdr->img_SRAM_size = le32_to_cpu(*(__le32 *)(pmappedfw + 12));
- /* define the size of DMEM variable */
- pfwhdr->fw_priv_sz = le32_to_cpu(*(__le32 *)(pmappedfw + 16));
-}
-
-static u8 chk_fwhdr(struct fw_hdr *pfwhdr, u32 ulfilelength)
-{
- u32 fwhdrsz, fw_sz;
-
- /* check signature */
- if ((pfwhdr->signature != 0x8712) && (pfwhdr->signature != 0x8192))
- return _FAIL;
- /* check fw_priv_sze & sizeof(struct fw_priv) */
- if (pfwhdr->fw_priv_sz != sizeof(struct fw_priv))
- return _FAIL;
- /* check fw_sz & image_fw_sz */
- fwhdrsz = offsetof(struct fw_hdr, fwpriv) + pfwhdr->fw_priv_sz;
- fw_sz = fwhdrsz + pfwhdr->img_IMEM_size + pfwhdr->img_SRAM_size +
- pfwhdr->dmem_size;
- if (fw_sz != ulfilelength)
- return _FAIL;
- return _SUCCESS;
-}
-
-static u8 rtl8712_dl_fw(struct _adapter *adapter)
-{
- sint i;
- u8 tmp8, tmp8_a;
- u16 tmp16;
- u32 maxlen = 0; /* for compare usage */
- uint dump_imem_sz, imem_sz, dump_emem_sz, emem_sz; /* max = 49152; */
- struct fw_hdr fwhdr;
- u32 ulfilelength; /* FW file size */
- const u8 *mappedfw = NULL;
- u8 *tmpchar = NULL, *payload, *ptr;
- struct tx_desc *txdesc;
- u32 txdscp_sz = sizeof(struct tx_desc);
- u8 ret = _FAIL;
-
- ulfilelength = rtl871x_open_fw(adapter, &mappedfw);
- if (mappedfw && (ulfilelength > 0)) {
- update_fwhdr(&fwhdr, mappedfw);
- if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL)
- return ret;
- fill_fwpriv(adapter, &fwhdr.fwpriv);
- /* firmware check ok */
- maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ?
- fwhdr.img_IMEM_size : fwhdr.img_SRAM_size;
- maxlen += txdscp_sz;
- tmpchar = kmalloc(maxlen + FWBUFF_ALIGN_SZ, GFP_KERNEL);
- if (!tmpchar)
- return ret;
-
- txdesc = (struct tx_desc *)(tmpchar + FWBUFF_ALIGN_SZ -
- ((addr_t)(tmpchar) & (FWBUFF_ALIGN_SZ - 1)));
- payload = (u8 *)(txdesc) + txdscp_sz;
- ptr = (u8 *)mappedfw + offsetof(struct fw_hdr, fwpriv) +
- fwhdr.fw_priv_sz;
- /* Download FirmWare */
- /* 1. determine IMEM code size and Load IMEM Code Section */
- imem_sz = fwhdr.img_IMEM_size;
- do {
- memset(txdesc, 0, TXDESC_SIZE);
- if (imem_sz > MAX_DUMP_FWSZ/*49152*/) {
- dump_imem_sz = MAX_DUMP_FWSZ;
- } else {
- dump_imem_sz = imem_sz;
- txdesc->txdw0 |= cpu_to_le32(BIT(28));
- }
- txdesc->txdw0 |= cpu_to_le32(dump_imem_sz &
- 0x0000ffff);
- memcpy(payload, ptr, dump_imem_sz);
- r8712_write_mem(adapter, RTL8712_DMA_VOQ,
- dump_imem_sz + TXDESC_SIZE,
- (u8 *)txdesc);
- ptr += dump_imem_sz;
- imem_sz -= dump_imem_sz;
- } while (imem_sz > 0);
- i = 10;
- tmp16 = r8712_read16(adapter, TCR);
- while (((tmp16 & _IMEM_CODE_DONE) == 0) && (i > 0)) {
- usleep_range(10, 1000);
- tmp16 = r8712_read16(adapter, TCR);
- i--;
- }
- if (i == 0 || (tmp16 & _IMEM_CHK_RPT) == 0)
- goto exit_fail;
-
- /* 2.Download EMEM code size and Load EMEM Code Section */
- emem_sz = fwhdr.img_SRAM_size;
- do {
- memset(txdesc, 0, TXDESC_SIZE);
- if (emem_sz > MAX_DUMP_FWSZ) { /* max=48k */
- dump_emem_sz = MAX_DUMP_FWSZ;
- } else {
- dump_emem_sz = emem_sz;
- txdesc->txdw0 |= cpu_to_le32(BIT(28));
- }
- txdesc->txdw0 |= cpu_to_le32(dump_emem_sz &
- 0x0000ffff);
- memcpy(payload, ptr, dump_emem_sz);
- r8712_write_mem(adapter, RTL8712_DMA_VOQ,
- dump_emem_sz + TXDESC_SIZE,
- (u8 *)txdesc);
- ptr += dump_emem_sz;
- emem_sz -= dump_emem_sz;
- } while (emem_sz > 0);
- i = 5;
- tmp16 = r8712_read16(adapter, TCR);
- while (((tmp16 & _EMEM_CODE_DONE) == 0) && (i > 0)) {
- usleep_range(10, 1000);
- tmp16 = r8712_read16(adapter, TCR);
- i--;
- }
- if (i == 0 || (tmp16 & _EMEM_CHK_RPT) == 0)
- goto exit_fail;
-
- /* 3.Enable CPU */
- tmp8 = r8712_read8(adapter, SYS_CLKR);
- r8712_write8(adapter, SYS_CLKR, tmp8 | BIT(2));
- tmp8_a = r8712_read8(adapter, SYS_CLKR);
- if (tmp8_a != (tmp8 | BIT(2)))
- goto exit_fail;
-
- tmp8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, tmp8 | BIT(2));
- tmp8_a = r8712_read8(adapter, SYS_FUNC_EN + 1);
- if (tmp8_a != (tmp8 | BIT(2)))
- goto exit_fail;
-
- r8712_read32(adapter, TCR);
-
- /* 4.polling IMEM Ready */
- i = 100;
- tmp16 = r8712_read16(adapter, TCR);
- while (((tmp16 & _IMEM_RDY) == 0) && (i > 0)) {
- msleep(20);
- tmp16 = r8712_read16(adapter, TCR);
- i--;
- }
- if (i == 0) {
- r8712_write16(adapter, 0x10250348, 0xc000);
- r8712_write16(adapter, 0x10250348, 0xc001);
- r8712_write16(adapter, 0x10250348, 0x2000);
- r8712_write16(adapter, 0x10250348, 0x2001);
- r8712_write16(adapter, 0x10250348, 0x2002);
- r8712_write16(adapter, 0x10250348, 0x2003);
- goto exit_fail;
- }
- /* 5.Download DMEM code size and Load EMEM Code Section */
- memset(txdesc, 0, TXDESC_SIZE);
- txdesc->txdw0 |= cpu_to_le32(fwhdr.fw_priv_sz & 0x0000ffff);
- txdesc->txdw0 |= cpu_to_le32(BIT(28));
- memcpy(payload, &fwhdr.fwpriv, fwhdr.fw_priv_sz);
- r8712_write_mem(adapter, RTL8712_DMA_VOQ,
- fwhdr.fw_priv_sz + TXDESC_SIZE, (u8 *)txdesc);
-
- /* polling dmem code done */
- i = 100;
- tmp16 = r8712_read16(adapter, TCR);
- while (((tmp16 & _DMEM_CODE_DONE) == 0) && (i > 0)) {
- msleep(20);
- tmp16 = r8712_read16(adapter, TCR);
- i--;
- }
- if (i == 0)
- goto exit_fail;
-
- tmp8 = r8712_read8(adapter, 0x1025000A);
- if (tmp8 & BIT(4)) /* When boot from EEPROM,
- * & FW need more time to read EEPROM
- */
- i = 60;
- else /* boot from EFUSE */
- i = 30;
- tmp16 = r8712_read16(adapter, TCR);
- while (((tmp16 & _FWRDY) == 0) && (i > 0)) {
- msleep(100);
- tmp16 = r8712_read16(adapter, TCR);
- i--;
- }
- if (i == 0)
- goto exit_fail;
- } else {
- goto exit_fail;
- }
- ret = _SUCCESS;
-
-exit_fail:
- kfree(tmpchar);
- return ret;
-}
-
-uint rtl8712_hal_init(struct _adapter *padapter)
-{
- u32 val32;
- int i;
-
- /* r8712 firmware download */
- if (rtl8712_dl_fw(padapter) != _SUCCESS)
- return _FAIL;
-
- netdev_info(padapter->pnetdev, "1 RCR=0x%x\n",
- r8712_read32(padapter, RCR));
- val32 = r8712_read32(padapter, RCR);
- r8712_write32(padapter, RCR, (val32 | BIT(26))); /* Enable RX TCP
- * Checksum offload
- */
- netdev_info(padapter->pnetdev, "2 RCR=0x%x\n",
- r8712_read32(padapter, RCR));
- val32 = r8712_read32(padapter, RCR);
- r8712_write32(padapter, RCR, (val32 | BIT(25))); /* Append PHY status */
- val32 = r8712_read32(padapter, 0x10250040);
- r8712_write32(padapter, 0x10250040, (val32 & 0x00FFFFFF));
- /* for usb rx aggregation */
- r8712_write8(padapter, 0x102500B5, r8712_read8(padapter, 0x102500B5) |
- BIT(0)); /* page = 128bytes */
- r8712_write8(padapter, 0x102500BD, r8712_read8(padapter, 0x102500BD) |
- BIT(7)); /* enable usb rx aggregation */
- r8712_write8(padapter, 0x102500D9, 1); /* TH=1 => means that invalidate
- * usb rx aggregation
- */
- r8712_write8(padapter, 0x1025FE5B, 0x04); /* 1.7ms/4 */
- /* Fix the RX FIFO issue(USB error) */
- r8712_write8(padapter, 0x1025fe5C, r8712_read8(padapter, 0x1025fe5C)
- | BIT(7));
- for (i = 0; i < ETH_ALEN; i++)
- padapter->eeprompriv.mac_addr[i] = r8712_read8(padapter,
- MACID + i);
- return _SUCCESS;
-}
-
-uint rtl8712_hal_deinit(struct _adapter *padapter)
-{
- r8712_write8(padapter, RF_CTRL, 0x00);
- /* Turn off BB */
- msleep(20);
- /* Turn off MAC */
- r8712_write8(padapter, SYS_CLKR + 1, 0x38); /* Switch Control Path */
- r8712_write8(padapter, SYS_FUNC_EN + 1, 0x70);
- r8712_write8(padapter, PMC_FSM, 0x06); /* Enable Loader Data Keep */
- r8712_write8(padapter, SYS_ISO_CTRL, 0xF9); /* Isolation signals from
- * CORE, PLL
- */
- r8712_write8(padapter, SYS_ISO_CTRL + 1, 0xe8); /* Enable EFUSE 1.2V */
- r8712_write8(padapter, AFE_PLL_CTRL, 0x00); /* Disable AFE PLL. */
- r8712_write8(padapter, LDOA15_CTRL, 0x54); /* Disable A15V */
- r8712_write8(padapter, SYS_FUNC_EN + 1, 0x50); /* Disable E-Fuse 1.2V */
- r8712_write8(padapter, LDOV12D_CTRL, 0x24); /* Disable LDO12(for CE) */
- r8712_write8(padapter, AFE_MISC, 0x30); /* Disable AFE BG&MB */
- /* Option for Disable 1.6V LDO. */
- r8712_write8(padapter, SPS0_CTRL, 0x56); /* Disable 1.6V LDO */
- r8712_write8(padapter, SPS0_CTRL + 1, 0x43); /* Set SW PFM */
- return _SUCCESS;
-}
-
-uint rtl871x_hal_init(struct _adapter *padapter)
-{
- padapter->hw_init_completed = false;
- if (!padapter->halpriv.hal_bus_init)
- return _FAIL;
- if (padapter->halpriv.hal_bus_init(padapter) != _SUCCESS)
- return _FAIL;
- if (rtl8712_hal_init(padapter) == _SUCCESS) {
- padapter->hw_init_completed = true;
- } else {
- padapter->hw_init_completed = false;
- return _FAIL;
- }
- return _SUCCESS;
-}
diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c
deleted file mode 100644
index 7d8f1a29d18a..000000000000
--- a/drivers/staging/rtl8712/ieee80211.c
+++ /dev/null
@@ -1,415 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * ieee80211.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _IEEE80211_C
-
-#include "drv_types.h"
-#include "ieee80211.h"
-#include "wifi.h"
-#include "osdep_service.h"
-#include "wlan_bssdef.h"
-
-static const u8 WPA_OUI_TYPE[] = {0x00, 0x50, 0xf2, 1};
-static const u8 WPA_CIPHER_SUITE_NONE[] = {0x00, 0x50, 0xf2, 0};
-static const u8 WPA_CIPHER_SUITE_WEP40[] = {0x00, 0x50, 0xf2, 1};
-static const u8 WPA_CIPHER_SUITE_TKIP[] = {0x00, 0x50, 0xf2, 2};
-static const u8 WPA_CIPHER_SUITE_CCMP[] = {0x00, 0x50, 0xf2, 4};
-static const u8 WPA_CIPHER_SUITE_WEP104[] = {0x00, 0x50, 0xf2, 5};
-
-static const u8 RSN_CIPHER_SUITE_NONE[] = {0x00, 0x0f, 0xac, 0};
-static const u8 RSN_CIPHER_SUITE_WEP40[] = {0x00, 0x0f, 0xac, 1};
-static const u8 RSN_CIPHER_SUITE_TKIP[] = {0x00, 0x0f, 0xac, 2};
-static const u8 RSN_CIPHER_SUITE_CCMP[] = {0x00, 0x0f, 0xac, 4};
-static const u8 RSN_CIPHER_SUITE_WEP104[] = {0x00, 0x0f, 0xac, 5};
-
-/*-----------------------------------------------------------
- * for adhoc-master to generate ie and provide supported-rate to fw
- *-----------------------------------------------------------
- */
-
-static u8 WIFI_CCKRATES[] = {
- (IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK),
- (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK),
- (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK),
- (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK)
-};
-
-static u8 WIFI_OFDMRATES[] = {
- (IEEE80211_OFDM_RATE_6MB),
- (IEEE80211_OFDM_RATE_9MB),
- (IEEE80211_OFDM_RATE_12MB),
- (IEEE80211_OFDM_RATE_18MB),
- (IEEE80211_OFDM_RATE_24MB),
- (IEEE80211_OFDM_RATE_36MB),
- (IEEE80211_OFDM_RATE_48MB),
- (IEEE80211_OFDM_RATE_54MB)
-};
-
-uint r8712_is_cckrates_included(u8 *rate)
-{
- u32 i = 0;
-
- while (rate[i] != 0) {
- if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
- (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22))
- return true;
- i++;
- }
- return false;
-}
-
-uint r8712_is_cckratesonly_included(u8 *rate)
-{
- u32 i = 0;
-
- while (rate[i] != 0) {
- if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
- (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22))
- return false;
- i++;
- }
- return true;
-}
-
-/* r8712_set_ie will update frame length */
-u8 *r8712_set_ie(u8 *pbuf, sint index, uint len, u8 *source, uint *frlen)
-{
- *pbuf = (u8)index;
- *(pbuf + 1) = (u8)len;
- if (len > 0)
- memcpy((void *)(pbuf + 2), (void *)source, len);
- *frlen = *frlen + (len + 2);
- return pbuf + len + 2;
-}
-
-/* ---------------------------------------------------------------------------
- * index: the information element id index, limit is the limit for search
- * ---------------------------------------------------------------------------
- */
-u8 *r8712_get_ie(u8 *pbuf, sint index, uint *len, sint limit)
-{
- sint tmp, i;
- u8 *p;
-
- if (limit < 1)
- return NULL;
- p = pbuf;
- i = 0;
- *len = 0;
- while (1) {
- if (*p == index) {
- *len = *(p + 1);
- return p;
- }
- tmp = *(p + 1);
- p += (tmp + 2);
- i += (tmp + 2);
- if (i >= limit)
- break;
- }
- return NULL;
-}
-
-static void set_supported_rate(u8 *rates, uint mode)
-{
- memset(rates, 0, NDIS_802_11_LENGTH_RATES_EX);
- switch (mode) {
- case WIRELESS_11B:
- memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
- break;
- case WIRELESS_11G:
- case WIRELESS_11A:
- memcpy(rates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
- break;
- case WIRELESS_11BG:
- memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
- memcpy(rates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES,
- IEEE80211_NUM_OFDM_RATESLEN);
- break;
- }
-}
-
-static uint r8712_get_rateset_len(u8 *rateset)
-{
- uint i = 0;
-
- while (1) {
- if ((rateset[i]) == 0)
- break;
- if (i > 12)
- break;
- i++;
- }
- return i;
-}
-
-int r8712_generate_ie(struct registry_priv *registrypriv)
-{
- int rate_len;
- uint sz = 0;
- struct wlan_bssid_ex *dev_network = &registrypriv->dev_network;
- u8 *ie = dev_network->IEs;
- u16 beacon_period = (u16)dev_network->Configuration.BeaconPeriod;
-
- /*timestamp will be inserted by hardware*/
- sz += 8;
- ie += sz;
- /*beacon interval : 2bytes*/
- *(__le16 *)ie = cpu_to_le16(beacon_period);
- sz += 2;
- ie += 2;
- /*capability info*/
- *(u16 *)ie = 0;
- *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_IBSS);
- if (registrypriv->preamble == PREAMBLE_SHORT)
- *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
- if (dev_network->Privacy)
- *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
- sz += 2;
- ie += 2;
- /*SSID*/
- ie = r8712_set_ie(ie, WLAN_EID_SSID, dev_network->Ssid.SsidLength,
- dev_network->Ssid.Ssid, &sz);
- /*supported rates*/
- set_supported_rate(dev_network->rates, registrypriv->wireless_mode);
- rate_len = r8712_get_rateset_len(dev_network->rates);
- if (rate_len > 8) {
- ie = r8712_set_ie(ie, WLAN_EID_SUPP_RATES, 8,
- dev_network->rates, &sz);
- ie = r8712_set_ie(ie, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8),
- (dev_network->rates + 8), &sz);
- } else {
- ie = r8712_set_ie(ie, WLAN_EID_SUPP_RATES,
- rate_len, dev_network->rates, &sz);
- }
- /*DS parameter set*/
- ie = r8712_set_ie(ie, WLAN_EID_DS_PARAMS, 1,
- (u8 *)&dev_network->Configuration.DSConfig, &sz);
- /*IBSS Parameter Set*/
- ie = r8712_set_ie(ie, WLAN_EID_IBSS_PARAMS, 2,
- (u8 *)&dev_network->Configuration.ATIMWindow, &sz);
- return sz;
-}
-
-unsigned char *r8712_get_wpa_ie(unsigned char *ie, uint *wpa_ie_len, int limit)
-{
- u32 len;
- u16 val16;
- unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
- u8 *buf = ie;
-
- while (1) {
- buf = r8712_get_ie(buf, _WPA_IE_ID_, &len, limit);
- if (buf) {
- /*check if oui matches...*/
- if (memcmp((buf + 2), wpa_oui_type,
- sizeof(wpa_oui_type)))
- goto check_next_ie;
- /*check version...*/
- memcpy((u8 *)&val16, (buf + 6), sizeof(val16));
- le16_to_cpus(&val16);
- if (val16 != 0x0001)
- goto check_next_ie;
- *wpa_ie_len = *(buf + 1);
- return buf;
- }
- *wpa_ie_len = 0;
- return NULL;
-check_next_ie:
- limit = limit - (buf - ie) - 2 - len;
- if (limit <= 0)
- break;
- buf += (2 + len);
- }
- *wpa_ie_len = 0;
- return NULL;
-}
-
-unsigned char *r8712_get_wpa2_ie(unsigned char *pie, uint *rsn_ie_len,
- int limit)
-{
- return r8712_get_ie(pie, _WPA2_IE_ID_, rsn_ie_len, limit);
-}
-
-static int r8712_get_wpa_cipher_suite(u8 *s)
-{
- if (!memcmp(s, (void *)WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN))
- return WPA_CIPHER_NONE;
- if (!memcmp(s, (void *)WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN))
- return WPA_CIPHER_WEP40;
- if (!memcmp(s, (void *)WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN))
- return WPA_CIPHER_TKIP;
- if (!memcmp(s, (void *)WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN))
- return WPA_CIPHER_CCMP;
- if (!memcmp(s, (void *)WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN))
- return WPA_CIPHER_WEP104;
- return 0;
-}
-
-static int r8712_get_wpa2_cipher_suite(u8 *s)
-{
- if (!memcmp(s, (void *)RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN))
- return WPA_CIPHER_NONE;
- if (!memcmp(s, (void *)RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN))
- return WPA_CIPHER_WEP40;
- if (!memcmp(s, (void *)RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN))
- return WPA_CIPHER_TKIP;
- if (!memcmp(s, (void *)RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN))
- return WPA_CIPHER_CCMP;
- if (!memcmp(s, (void *)RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN))
- return WPA_CIPHER_WEP104;
- return 0;
-}
-
-int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
- int *pairwise_cipher)
-{
- int i;
- int left, count;
- u8 *pos;
-
- if (wpa_ie_len <= 0) {
- /* No WPA IE - fail silently */
- return -EINVAL;
- }
- if ((*wpa_ie != _WPA_IE_ID_) ||
- (*(wpa_ie + 1) != (u8)(wpa_ie_len - 2)) ||
- (memcmp(wpa_ie + 2, (void *)WPA_OUI_TYPE, WPA_SELECTOR_LEN)))
- return -EINVAL;
- pos = wpa_ie;
- pos += 8;
- left = wpa_ie_len - 8;
- /*group_cipher*/
- if (left >= WPA_SELECTOR_LEN) {
- *group_cipher = r8712_get_wpa_cipher_suite(pos);
- pos += WPA_SELECTOR_LEN;
- left -= WPA_SELECTOR_LEN;
- } else if (left > 0) {
- return -EINVAL;
- }
- /*pairwise_cipher*/
- if (left >= 2) {
- count = le16_to_cpu(*(__le16 *)pos);
- pos += 2;
- left -= 2;
- if (count == 0 || left < count * WPA_SELECTOR_LEN)
- return -EINVAL;
- for (i = 0; i < count; i++) {
- *pairwise_cipher |= r8712_get_wpa_cipher_suite(pos);
- pos += WPA_SELECTOR_LEN;
- left -= WPA_SELECTOR_LEN;
- }
- } else if (left == 1) {
- return -EINVAL;
- }
- return 0;
-}
-
-int r8712_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
- int *pairwise_cipher)
-{
- int i;
- int left, count;
- u8 *pos;
-
- if (rsn_ie_len <= 0) {
- /* No RSN IE - fail silently */
- return -EINVAL;
- }
- if ((*rsn_ie != _WPA2_IE_ID_) ||
- (*(rsn_ie + 1) != (u8)(rsn_ie_len - 2)))
- return -EINVAL;
- pos = rsn_ie;
- pos += 4;
- left = rsn_ie_len - 4;
- /*group_cipher*/
- if (left >= RSN_SELECTOR_LEN) {
- *group_cipher = r8712_get_wpa2_cipher_suite(pos);
- pos += RSN_SELECTOR_LEN;
- left -= RSN_SELECTOR_LEN;
- } else if (left > 0) {
- return -EINVAL;
- }
- /*pairwise_cipher*/
- if (left >= 2) {
- count = le16_to_cpu(*(__le16 *)pos);
- pos += 2;
- left -= 2;
- if (count == 0 || left < count * RSN_SELECTOR_LEN)
- return -EINVAL;
- for (i = 0; i < count; i++) {
- *pairwise_cipher |= r8712_get_wpa2_cipher_suite(pos);
- pos += RSN_SELECTOR_LEN;
- left -= RSN_SELECTOR_LEN;
- }
- } else if (left == 1) {
- return -EINVAL;
- }
- return 0;
-}
-
-int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
- u8 *wpa_ie, u16 *wpa_len)
-{
- u8 authmode;
- u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
- uint cnt;
-
- /*Search required WPA or WPA2 IE and copy to sec_ie[ ]*/
- cnt = _TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_;
- while (cnt < in_len) {
- authmode = in_ie[cnt];
- if ((authmode == _WPA_IE_ID_) &&
- (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
- memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
- *wpa_len = in_ie[cnt + 1] + 2;
- cnt += in_ie[cnt + 1] + 2; /*get next */
- } else {
- if (authmode == _WPA2_IE_ID_) {
- memcpy(rsn_ie, &in_ie[cnt],
- in_ie[cnt + 1] + 2);
- *rsn_len = in_ie[cnt + 1] + 2;
- cnt += in_ie[cnt + 1] + 2; /*get next*/
- } else {
- cnt += in_ie[cnt + 1] + 2; /*get next*/
- }
- }
- }
- return *rsn_len + *wpa_len;
-}
-
-int r8712_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
-{
- int match;
- uint cnt;
- u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
-
- cnt = 12;
- match = false;
- while (cnt < in_len) {
- eid = in_ie[cnt];
- if ((eid == _WPA_IE_ID_) &&
- (!memcmp(&in_ie[cnt + 2], wps_oui, 4))) {
- memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
- *wps_ielen = in_ie[cnt + 1] + 2;
- cnt += in_ie[cnt + 1] + 2;
- match = true;
- break;
- }
- cnt += in_ie[cnt + 1] + 2; /* goto next */
- }
- return match;
-}
diff --git a/drivers/staging/rtl8712/ieee80211.h b/drivers/staging/rtl8712/ieee80211.h
deleted file mode 100644
index 65ceaca9b51e..000000000000
--- a/drivers/staging/rtl8712/ieee80211.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __IEEE80211_H
-#define __IEEE80211_H
-
-#include <linux/ieee80211.h>
-
-#define IEEE_CMD_SET_WPA_PARAM 1
-#define IEEE_CMD_SET_WPA_IE 2
-#define IEEE_CMD_SET_ENCRYPTION 3
-#define IEEE_CMD_MLME 4
-
-#define IEEE_PARAM_WPA_ENABLED 1
-#define IEEE_PARAM_TKIP_COUNTERMEASURES 2
-#define IEEE_PARAM_DROP_UNENCRYPTED 3
-#define IEEE_PARAM_PRIVACY_INVOKED 4
-#define IEEE_PARAM_AUTH_ALGS 5
-#define IEEE_PARAM_IEEE_802_1X 6
-#define IEEE_PARAM_WPAX_SELECT 7
-
-#define AUTH_ALG_OPEN_SYSTEM 0x1
-#define AUTH_ALG_SHARED_KEY 0x2
-#define AUTH_ALG_LEAP 0x00000004
-
-#define IEEE_MLME_STA_DEAUTH 1
-#define IEEE_MLME_STA_DISASSOC 2
-
-#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2
-#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3
-#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4
-#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5
-#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6
-#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7
-
-#define IEEE_CRYPT_ALG_NAME_LEN 16
-
-#define WPA_CIPHER_NONE BIT(0)
-#define WPA_CIPHER_WEP40 BIT(1)
-#define WPA_CIPHER_WEP104 BIT(2)
-#define WPA_CIPHER_TKIP BIT(3)
-#define WPA_CIPHER_CCMP BIT(4)
-
-#define WPA_SELECTOR_LEN 4
-#define RSN_HEADER_LEN 4
-
-#define RSN_SELECTOR_LEN 4
-
-enum NETWORK_TYPE {
- WIRELESS_INVALID = 0,
- WIRELESS_11B = 1,
- WIRELESS_11G = 2,
- WIRELESS_11BG = (WIRELESS_11B | WIRELESS_11G),
- WIRELESS_11A = 4,
- WIRELESS_11N = 8,
- WIRELESS_11GN = (WIRELESS_11G | WIRELESS_11N),
- WIRELESS_11BGN = (WIRELESS_11B | WIRELESS_11G | WIRELESS_11N),
-};
-
-struct ieee_param {
- u32 cmd;
- u8 sta_addr[ETH_ALEN];
- union {
- struct {
- u8 name;
- u32 value;
- } wpa_param;
- struct {
- u32 len;
- u8 reserved[32];
- u8 data[];
- } wpa_ie;
- struct {
- int command;
- int reason_code;
- } mlme;
- struct {
- u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
- u8 set_tx;
- u32 err;
- u8 idx;
- u8 seq[8]; /* sequence counter (set: RX, get: TX) */
- u16 key_len;
- u8 key[];
- } crypt;
- } u;
-};
-
-#define MIN_FRAG_THRESHOLD 256U
-#define MAX_FRAG_THRESHOLD 2346U
-
-/* QoS,QOS */
-#define NORMAL_ACK 0
-
-/* IEEE 802.11 defines */
-
-#define P80211_OUI_LEN 3
-
-struct ieee80211_snap_hdr {
- u8 dsap; /* always 0xAA */
- u8 ssap; /* always 0xAA */
- u8 ctrl; /* always 0x03 */
- u8 oui[P80211_OUI_LEN]; /* organizational universal id */
-} __packed;
-
-#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
-
-#define IEEE80211_CCK_RATE_LEN 4
-#define IEEE80211_NUM_OFDM_RATESLEN 8
-
-#define IEEE80211_CCK_RATE_1MB 0x02
-#define IEEE80211_CCK_RATE_2MB 0x04
-#define IEEE80211_CCK_RATE_5MB 0x0B
-#define IEEE80211_CCK_RATE_11MB 0x16
-#define IEEE80211_OFDM_RATE_6MB 0x0C
-#define IEEE80211_OFDM_RATE_9MB 0x12
-#define IEEE80211_OFDM_RATE_12MB 0x18
-#define IEEE80211_OFDM_RATE_18MB 0x24
-#define IEEE80211_OFDM_RATE_24MB 0x30
-#define IEEE80211_OFDM_RATE_36MB 0x48
-#define IEEE80211_OFDM_RATE_48MB 0x60
-#define IEEE80211_OFDM_RATE_54MB 0x6C
-#define IEEE80211_BASIC_RATE_MASK 0x80
-
-#define WEP_KEYS 4
-
-/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs
- * only use 8, and then use extended rates for the remaining supported
- * rates. Other APs, however, stick all of their supported rates on the
- * main rates information element...
- */
-#define MAX_RATES_LENGTH ((u8)12)
-#define MAX_WPA_IE_LEN 128
-
-struct registry_priv;
-
-u8 *r8712_set_ie(u8 *pbuf, sint index, uint len, u8 *source, uint *frlen);
-u8 *r8712_get_ie(u8 *pbuf, sint index, uint *len, sint limit);
-unsigned char *r8712_get_wpa_ie(unsigned char *pie, uint *rsn_ie_len,
- int limit);
-unsigned char *r8712_get_wpa2_ie(unsigned char *pie, uint *rsn_ie_len,
- int limit);
-int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
- int *pairwise_cipher);
-int r8712_parse_wpa2_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
- int *pairwise_cipher);
-int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
- u8 *wpa_ie, u16 *wpa_len);
-int r8712_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen);
-int r8712_generate_ie(struct registry_priv *pregistrypriv);
-uint r8712_is_cckrates_included(u8 *rate);
-uint r8712_is_cckratesonly_included(u8 *rate);
-
-#endif /* IEEE80211_H */
-
diff --git a/drivers/staging/rtl8712/mlme_linux.c b/drivers/staging/rtl8712/mlme_linux.c
deleted file mode 100644
index 436816d14cdf..000000000000
--- a/drivers/staging/rtl8712/mlme_linux.c
+++ /dev/null
@@ -1,160 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * mlme_linux.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _MLME_OSDEP_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "mlme_osdep.h"
-
-static void sitesurvey_ctrl_handler(struct timer_list *t)
-{
- struct _adapter *adapter =
- from_timer(adapter, t,
- mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer);
-
- _r8712_sitesurvey_ctrl_handler(adapter);
- mod_timer(&adapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer,
- jiffies + msecs_to_jiffies(3000));
-}
-
-static void join_timeout_handler (struct timer_list *t)
-{
- struct _adapter *adapter =
- from_timer(adapter, t, mlmepriv.assoc_timer);
-
- _r8712_join_timeout_handler(adapter);
-}
-
-static void _scan_timeout_handler (struct timer_list *t)
-{
- struct _adapter *adapter =
- from_timer(adapter, t, mlmepriv.scan_to_timer);
-
- r8712_scan_timeout_handler(adapter);
-}
-
-static void dhcp_timeout_handler (struct timer_list *t)
-{
- struct _adapter *adapter =
- from_timer(adapter, t, mlmepriv.dhcp_timer);
-
- _r8712_dhcp_timeout_handler(adapter);
-}
-
-static void wdg_timeout_handler (struct timer_list *t)
-{
- struct _adapter *adapter =
- from_timer(adapter, t, mlmepriv.wdg_timer);
-
- r8712_wdg_wk_cmd(adapter);
-
- mod_timer(&adapter->mlmepriv.wdg_timer,
- jiffies + msecs_to_jiffies(2000));
-}
-
-void r8712_init_mlme_timer(struct _adapter *adapter)
-{
- struct mlme_priv *mlmepriv = &adapter->mlmepriv;
-
- timer_setup(&mlmepriv->assoc_timer, join_timeout_handler, 0);
- timer_setup(&mlmepriv->sitesurveyctrl.sitesurvey_ctrl_timer,
- sitesurvey_ctrl_handler, 0);
- timer_setup(&mlmepriv->scan_to_timer, _scan_timeout_handler, 0);
- timer_setup(&mlmepriv->dhcp_timer, dhcp_timeout_handler, 0);
- timer_setup(&mlmepriv->wdg_timer, wdg_timeout_handler, 0);
-}
-
-void r8712_os_indicate_connect(struct _adapter *adapter)
-{
- r8712_indicate_wx_assoc_event(adapter);
- netif_carrier_on(adapter->pnetdev);
-}
-
-static struct RT_PMKID_LIST backup_PMKID_list[NUM_PMKID_CACHE];
-void r8712_os_indicate_disconnect(struct _adapter *adapter)
-{
- u8 backup_PMKID_index = 0;
- u8 backup_TKIP_countermeasure = 0x00;
-
- r8712_indicate_wx_disassoc_event(adapter);
- netif_carrier_off(adapter->pnetdev);
- if (adapter->securitypriv.AuthAlgrthm == 2) { /*/802.1x*/
- /* We have to backup the PMK information for WiFi PMK Caching
- * test item. Backup the btkip_countermeasure information.
- * When the countermeasure is trigger, the driver have to
- * disconnect with AP for 60 seconds.
- */
-
- memcpy(&backup_PMKID_list[0],
- &adapter->securitypriv.PMKIDList[0],
- sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
- backup_PMKID_index = adapter->securitypriv.PMKIDIndex;
- backup_TKIP_countermeasure =
- adapter->securitypriv.btkip_countermeasure;
- memset((unsigned char *)&adapter->securitypriv, 0,
- sizeof(struct security_priv));
- timer_setup(&adapter->securitypriv.tkip_timer,
- r8712_use_tkipkey_handler, 0);
- /* Restore the PMK information to securitypriv structure
- * for the following connection.
- */
- memcpy(&adapter->securitypriv.PMKIDList[0],
- &backup_PMKID_list[0],
- sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
- adapter->securitypriv.PMKIDIndex = backup_PMKID_index;
- adapter->securitypriv.btkip_countermeasure =
- backup_TKIP_countermeasure;
- } else { /*reset values in securitypriv*/
- struct security_priv *sec_priv = &adapter->securitypriv;
-
- sec_priv->AuthAlgrthm = 0; /*open system*/
- sec_priv->PrivacyAlgrthm = _NO_PRIVACY_;
- sec_priv->PrivacyKeyIndex = 0;
- sec_priv->XGrpPrivacy = _NO_PRIVACY_;
- sec_priv->XGrpKeyid = 1;
- sec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
- sec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
- sec_priv->wps_phase = false;
- }
-}
-
-void r8712_report_sec_ie(struct _adapter *adapter, u8 authmode, u8 *sec_ie)
-{
- uint len;
- u8 *buff, *p, i;
- union iwreq_data wrqu;
-
- buff = NULL;
- if (authmode == _WPA_IE_ID_) {
- buff = kzalloc(IW_CUSTOM_MAX, GFP_ATOMIC);
- if (!buff)
- return;
- p = buff;
- p += sprintf(p, "ASSOCINFO(ReqIEs=");
- len = sec_ie[1] + 2;
- len = (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX;
- for (i = 0; i < len; i++)
- p += sprintf(p, "%02x", sec_ie[i]);
- p += sprintf(p, ")");
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = p - buff;
- wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ?
- wrqu.data.length : IW_CUSTOM_MAX;
- wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
- kfree(buff);
- }
-}
diff --git a/drivers/staging/rtl8712/mlme_osdep.h b/drivers/staging/rtl8712/mlme_osdep.h
deleted file mode 100644
index a02c782588dd..000000000000
--- a/drivers/staging/rtl8712/mlme_osdep.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __MLME_OSDEP_H_
-#define __MLME_OSDEP_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-void r8712_init_mlme_timer(struct _adapter *padapter);
-void r8712_os_indicate_disconnect(struct _adapter *adapter);
-void r8712_os_indicate_connect(struct _adapter *adapter);
-void r8712_report_sec_ie(struct _adapter *adapter, u8 authmode, u8 *sec_ie);
-int r8712_recv_indicatepkts_in_order(struct _adapter *adapter,
- struct recv_reorder_ctrl *precvreorder_ctrl,
- int bforced);
-void r8712_indicate_wx_assoc_event(struct _adapter *padapter);
-void r8712_indicate_wx_disassoc_event(struct _adapter *padapter);
-
-#endif /*_MLME_OSDEP_H_*/
-
diff --git a/drivers/staging/rtl8712/mp_custom_oid.h b/drivers/staging/rtl8712/mp_custom_oid.h
deleted file mode 100644
index a9fac87fcabc..000000000000
--- a/drivers/staging/rtl8712/mp_custom_oid.h
+++ /dev/null
@@ -1,287 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __CUSTOM_OID_H
-#define __CUSTOM_OID_H
-
-/* 0xFF818000 - 0xFF81802F RTL8180 Mass Production Kit
- * 0xFF818500 - 0xFF81850F RTL8185 Setup Utility
- * 0xFF818580 - 0xFF81858F RTL8185 Phy Status Utility
- *
- * by Owen for Production Kit
- * For Production Kit with Agilent Equipments
- * in order to make our custom oids hopefully somewhat unique
- * we will use 0xFF (indicating implementation specific OID)
- * 81(first byte of non zero Realtek unique identifier)
- * 80 (second byte of non zero Realtek unique identifier)
- * XX (the custom OID number - providing 255 possible custom oids)
- */
-#define OID_RT_PRO_RESET_DUT 0xFF818000
-#define OID_RT_PRO_SET_DATA_RATE 0xFF818001
-#define OID_RT_PRO_START_TEST 0xFF818002
-#define OID_RT_PRO_STOP_TEST 0xFF818003
-#define OID_RT_PRO_SET_PREAMBLE 0xFF818004
-#define OID_RT_PRO_SET_SCRAMBLER 0xFF818005
-#define OID_RT_PRO_SET_FILTER_BB 0xFF818006
-#define OID_RT_PRO_SET_MANUAL_DIVERSITY_BB 0xFF818007
-#define OID_RT_PRO_SET_CHANNEL_DIRECT_CALL 0xFF818008
-#define OID_RT_PRO_SET_SLEEP_MODE_DIRECT_CALL 0xFF818009
-#define OID_RT_PRO_SET_WAKE_MODE_DIRECT_CALL 0xFF81800A
-
-#define OID_RT_PRO_SET_TX_ANTENNA_BB 0xFF81800D
-#define OID_RT_PRO_SET_ANTENNA_BB 0xFF81800E
-#define OID_RT_PRO_SET_CR_SCRAMBLER 0xFF81800F
-#define OID_RT_PRO_SET_CR_NEW_FILTER 0xFF818010
-#define OID_RT_PRO_SET_TX_POWER_CONTROL 0xFF818011
-#define OID_RT_PRO_SET_CR_TX_CONFIG 0xFF818012
-#define OID_RT_PRO_GET_TX_POWER_CONTROL 0xFF818013
-#define OID_RT_PRO_GET_CR_SIGNAL_QUALITY 0xFF818014
-#define OID_RT_PRO_SET_CR_SETPOINT 0xFF818015
-#define OID_RT_PRO_SET_INTEGRATOR 0xFF818016
-#define OID_RT_PRO_SET_SIGNAL_QUALITY 0xFF818017
-#define OID_RT_PRO_GET_INTEGRATOR 0xFF818018
-#define OID_RT_PRO_GET_SIGNAL_QUALITY 0xFF818019
-#define OID_RT_PRO_QUERY_EEPROM_TYPE 0xFF81801A
-#define OID_RT_PRO_WRITE_MAC_ADDRESS 0xFF81801B
-#define OID_RT_PRO_READ_MAC_ADDRESS 0xFF81801C
-#define OID_RT_PRO_WRITE_CIS_DATA 0xFF81801D
-#define OID_RT_PRO_READ_CIS_DATA 0xFF81801E
-#define OID_RT_PRO_WRITE_POWER_CONTROL 0xFF81801F
-#define OID_RT_PRO_READ_POWER_CONTROL 0xFF818020
-#define OID_RT_PRO_WRITE_EEPROM 0xFF818021
-#define OID_RT_PRO_READ_EEPROM 0xFF818022
-#define OID_RT_PRO_RESET_TX_PACKET_SENT 0xFF818023
-#define OID_RT_PRO_QUERY_TX_PACKET_SENT 0xFF818024
-#define OID_RT_PRO_RESET_RX_PACKET_RECEIVED 0xFF818025
-#define OID_RT_PRO_QUERY_RX_PACKET_RECEIVED 0xFF818026
-#define OID_RT_PRO_QUERY_RX_PACKET_CRC32_ERROR 0xFF818027
-#define OID_RT_PRO_QUERY_CURRENT_ADDRESS 0xFF818028
-#define OID_RT_PRO_QUERY_PERMANENT_ADDRESS 0xFF818029
-#define OID_RT_PRO_SET_PHILIPS_RF_PARAMETERS 0xFF81802A
-#define OID_RT_PRO_RECEIVE_PACKET 0xFF81802C
-#define OID_RT_PRO_WRITE_EEPROM_BYTE 0xFF81802D
-#define OID_RT_PRO_READ_EEPROM_BYTE 0xFF81802E
-#define OID_RT_PRO_SET_MODULATION 0xFF81802F
-#define OID_RT_DRIVER_OPTION 0xFF818080
-#define OID_RT_RF_OFF 0xFF818081
-#define OID_RT_AUTH_STATUS 0xFF818082
-#define OID_RT_PRO_SET_CONTINUOUS_TX 0xFF81800B
-#define OID_RT_PRO_SET_SINGLE_CARRIER_TX 0xFF81800C
-#define OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX 0xFF81802B
-#define OID_RT_PRO_SET_SINGLE_TONE_TX 0xFF818043
-#define OID_RT_UTILITY_FALSE_ALARM_COUNTERS 0xFF818580
-#define OID_RT_UTILITY_SELECT_DEBUG_MODE 0xFF818581
-#define OID_RT_UTILITY_SELECT_SUBCARRIER_NUMBER 0xFF818582
-#define OID_RT_UTILITY_GET_RSSI_STATUS 0xFF818583
-#define OID_RT_UTILITY_GET_FRAME_DETECTION_STATUS 0xFF818584
-#define OID_RT_UTILITY_GET_AGC_AND_FREQUENCY_OFFSET_ESTIMATION_STATUS \
- 0xFF818585
-#define OID_RT_UTILITY_GET_CHANNEL_ESTIMATION_STATUS 0xFF818586
-#define OID_RT_WIRELESS_MODE 0xFF818500
-#define OID_RT_SUPPORTED_RATES 0xFF818501
-#define OID_RT_DESIRED_RATES 0xFF818502
-#define OID_RT_WIRELESS_MODE_STARTING_ADHOC 0xFF818503
-#define OID_RT_GET_CONNECT_STATE 0xFF030001
-#define OID_RT_RESCAN 0xFF030002
-#define OID_RT_SET_KEY_LENGTH 0xFF030003
-#define OID_RT_SET_DEFAULT_KEY_ID 0xFF030004
-#define OID_RT_SET_CHANNEL 0xFF010182
-#define OID_RT_SET_SNIFFER_MODE 0xFF010183
-#define OID_RT_GET_SIGNAL_QUALITY 0xFF010184
-#define OID_RT_GET_SMALL_PACKET_CRC 0xFF010185
-#define OID_RT_GET_MIDDLE_PACKET_CRC 0xFF010186
-#define OID_RT_GET_LARGE_PACKET_CRC 0xFF010187
-#define OID_RT_GET_TX_RETRY 0xFF010188
-#define OID_RT_GET_RX_RETRY 0xFF010189
-#define OID_RT_PRO_SET_FW_DIG_STATE 0xFF01018A
-#define OID_RT_PRO_SET_FW_RA_STATE 0xFF01018B
-#define OID_RT_GET_RX_TOTAL_PACKET 0xFF010190
-#define OID_RT_GET_TX_BEACON_OK 0xFF010191
-#define OID_RT_GET_TX_BEACON_ERR 0xFF010192
-#define OID_RT_GET_RX_ICV_ERR 0xFF010193
-#define OID_RT_SET_ENCRYPTION_ALGORITHM 0xFF010194
-#define OID_RT_SET_NO_AUTO_RESCAN 0xFF010195
-#define OID_RT_GET_PREAMBLE_MODE 0xFF010196
-#define OID_RT_GET_DRIVER_UP_DELTA_TIME 0xFF010197
-#define OID_RT_GET_AP_IP 0xFF010198
-#define OID_RT_GET_CHANNELPLAN 0xFF010199
-#define OID_RT_SET_PREAMBLE_MODE 0xFF01019A
-#define OID_RT_SET_BCN_INTVL 0xFF01019B
-#define OID_RT_GET_RF_VENDER 0xFF01019C
-#define OID_RT_DEDICATE_PROBE 0xFF01019D
-#define OID_RT_PRO_RX_FILTER_PATTERN 0xFF01019E
-#define OID_RT_GET_DCST_CURRENT_THRESHOLD 0xFF01019F
-#define OID_RT_GET_CCA_ERR 0xFF0101A0
-#define OID_RT_GET_CCA_UPGRADE_THRESHOLD 0xFF0101A1
-#define OID_RT_GET_CCA_FALLBACK_THRESHOLD 0xFF0101A2
-#define OID_RT_GET_CCA_UPGRADE_EVALUATE_TIMES 0xFF0101A3
-#define OID_RT_GET_CCA_FALLBACK_EVALUATE_TIMES 0xFF0101A4
-#define OID_RT_SET_RATE_ADAPTIVE 0xFF0101A5
-#define OID_RT_GET_DCST_EVALUATE_PERIOD 0xFF0101A5
-#define OID_RT_GET_DCST_TIME_UNIT_INDEX 0xFF0101A6
-#define OID_RT_GET_TOTAL_TX_BYTES 0xFF0101A7
-#define OID_RT_GET_TOTAL_RX_BYTES 0xFF0101A8
-#define OID_RT_CURRENT_TX_POWER_LEVEL 0xFF0101A9
-#define OID_RT_GET_ENC_KEY_MISMATCH_COUNT 0xFF0101AA
-#define OID_RT_GET_ENC_KEY_MATCH_COUNT 0xFF0101AB
-#define OID_RT_GET_CHANNEL 0xFF0101AC
-#define OID_RT_SET_CHANNELPLAN 0xFF0101AD
-#define OID_RT_GET_HARDWARE_RADIO_OFF 0xFF0101AE
-#define OID_RT_CHANNELPLAN_BY_COUNTRY 0xFF0101AF
-#define OID_RT_SCAN_AVAILABLE_BSSID 0xFF0101B0
-#define OID_RT_GET_HARDWARE_VERSION 0xFF0101B1
-#define OID_RT_GET_IS_ROAMING 0xFF0101B2
-#define OID_RT_GET_IS_PRIVACY 0xFF0101B3
-#define OID_RT_GET_KEY_MISMATCH 0xFF0101B4
-#define OID_RT_SET_RSSI_ROAM_TRAFFIC_TH 0xFF0101B5
-#define OID_RT_SET_RSSI_ROAM_SIGNAL_TH 0xFF0101B6
-#define OID_RT_RESET_LOG 0xFF0101B7
-#define OID_RT_GET_LOG 0xFF0101B8
-#define OID_RT_SET_INDICATE_HIDDEN_AP 0xFF0101B9
-#define OID_RT_GET_HEADER_FAIL 0xFF0101BA
-#define OID_RT_SUPPORTED_WIRELESS_MODE 0xFF0101BB
-#define OID_RT_GET_CHANNEL_LIST 0xFF0101BC
-#define OID_RT_GET_SCAN_IN_PROGRESS 0xFF0101BD
-#define OID_RT_GET_TX_INFO 0xFF0101BE
-#define OID_RT_RF_READ_WRITE_OFFSET 0xFF0101BF
-#define OID_RT_RF_READ_WRITE 0xFF0101C0
-#define OID_RT_FORCED_DATA_RATE 0xFF0101C1
-#define OID_RT_WIRELESS_MODE_FOR_SCAN_LIST 0xFF0101C2
-#define OID_RT_GET_BSS_WIRELESS_MODE 0xFF0101C3
-#define OID_RT_SCAN_WITH_MAGIC_PACKET 0xFF0101C4
-#define OID_RT_PRO_RX_FILTER 0xFF0111C0
-#define OID_CE_USB_WRITE_REGISTRY 0xFF0111C1
-#define OID_CE_USB_READ_REGISTRY 0xFF0111C2
-#define OID_RT_PRO_SET_INITIAL_GAIN 0xFF0111C3
-#define OID_RT_PRO_SET_BB_RF_STANDBY_MODE 0xFF0111C4
-#define OID_RT_PRO_SET_BB_RF_SHUTDOWN_MODE 0xFF0111C5
-#define OID_RT_PRO_SET_TX_CHARGE_PUMP 0xFF0111C6
-#define OID_RT_PRO_SET_RX_CHARGE_PUMP 0xFF0111C7
-#define OID_RT_PRO_RF_WRITE_REGISTRY 0xFF0111C8
-#define OID_RT_PRO_RF_READ_REGISTRY 0xFF0111C9
-#define OID_RT_PRO_QUERY_RF_TYPE 0xFF0111CA
-#define OID_RT_AP_GET_ASSOCIATED_STATION_LIST 0xFF010300
-#define OID_RT_AP_GET_CURRENT_TIME_STAMP 0xFF010301
-#define OID_RT_AP_SWITCH_INTO_AP_MODE 0xFF010302
-#define OID_RT_AP_SET_DTIM_PERIOD 0xFF010303
-#define OID_RT_AP_SUPPORTED 0xFF010304
-#define OID_RT_AP_SET_PASSPHRASE 0xFF010305
-#define OID_RT_PRO8187_WI_POLL 0xFF818780
-#define OID_RT_PRO_WRITE_BB_REG 0xFF818781
-#define OID_RT_PRO_READ_BB_REG 0xFF818782
-#define OID_RT_PRO_WRITE_RF_REG 0xFF818783
-#define OID_RT_PRO_READ_RF_REG 0xFF818784
-#define OID_RT_MH_VENDER_ID 0xFFEDC100
-#define OID_RT_PRO8711_JOIN_BSS 0xFF871100
-#define OID_RT_PRO_READ_REGISTER 0xFF871101
-#define OID_RT_PRO_WRITE_REGISTER 0xFF871102
-#define OID_RT_PRO_BURST_READ_REGISTER 0xFF871103
-#define OID_RT_PRO_BURST_WRITE_REGISTER 0xFF871104
-#define OID_RT_PRO_WRITE_TXCMD 0xFF871105
-#define OID_RT_PRO_READ16_EEPROM 0xFF871106
-#define OID_RT_PRO_WRITE16_EEPROM 0xFF871107
-#define OID_RT_PRO_H2C_SET_COMMAND 0xFF871108
-#define OID_RT_PRO_H2C_QUERY_RESULT 0xFF871109
-#define OID_RT_PRO8711_WI_POLL 0xFF87110A
-#define OID_RT_PRO8711_PKT_LOSS 0xFF87110B
-#define OID_RT_RD_ATTRIB_MEM 0xFF87110C
-#define OID_RT_WR_ATTRIB_MEM 0xFF87110D
-/*Method 2 for H2C/C2H*/
-#define OID_RT_PRO_H2C_CMD_MODE 0xFF871110
-#define OID_RT_PRO_H2C_CMD_RSP_MODE 0xFF871111
-#define OID_RT_PRO_H2C_CMD_EVENT_MODE 0xFF871112
-#define OID_RT_PRO_WAIT_C2H_EVENT 0xFF871113
-#define OID_RT_PRO_RW_ACCESS_PROTOCOL_TEST 0xFF871114
-#define OID_RT_PRO_SCSI_ACCESS_TEST 0xFF871115
-#define OID_RT_PRO_SCSI_TCPIPOFFLOAD_OUT 0xFF871116
-#define OID_RT_PRO_SCSI_TCPIPOFFLOAD_IN 0xFF871117
-#define OID_RT_RRO_RX_PKT_VIA_IOCTRL 0xFF871118
-#define OID_RT_RRO_RX_PKTARRAY_VIA_IOCTRL 0xFF871119
-#define OID_RT_RPO_SET_PWRMGT_TEST 0xFF87111A
-#define OID_RT_PRO_QRY_PWRMGT_TEST 0XFF87111B
-#define OID_RT_RPO_ASYNC_RWIO_TEST 0xFF87111C
-#define OID_RT_RPO_ASYNC_RWIO_POLL 0xFF87111D
-#define OID_RT_PRO_SET_RF_INTFS 0xFF87111E
-#define OID_RT_POLL_RX_STATUS 0xFF87111F
-#define OID_RT_PRO_CFG_DEBUG_MESSAGE 0xFF871120
-#define OID_RT_PRO_SET_DATA_RATE_EX 0xFF871121
-#define OID_RT_PRO_SET_BASIC_RATE 0xFF871122
-#define OID_RT_PRO_READ_TSSI 0xFF871123
-#define OID_RT_PRO_SET_POWER_TRACKING 0xFF871124
-#define OID_RT_PRO_QRY_PWRSTATE 0xFF871150
-#define OID_RT_PRO_SET_PWRSTATE 0xFF871151
-/*Method 2 , using workitem */
-#define OID_RT_SET_READ_REG 0xFF871181
-#define OID_RT_SET_WRITE_REG 0xFF871182
-#define OID_RT_SET_BURST_READ_REG 0xFF871183
-#define OID_RT_SET_BURST_WRITE_REG 0xFF871184
-#define OID_RT_SET_WRITE_TXCMD 0xFF871185
-#define OID_RT_SET_READ16_EEPROM 0xFF871186
-#define OID_RT_SET_WRITE16_EEPROM 0xFF871187
-#define OID_RT_QRY_POLL_WKITEM 0xFF871188
-
-/*For SDIO INTERFACE only*/
-#define OID_RT_PRO_SYNCPAGERW_SRAM 0xFF8711A0
-#define OID_RT_PRO_871X_DRV_EXT 0xFF8711A1
-
-/*For USB INTERFACE only*/
-#define OID_RT_PRO_USB_VENDOR_REQ 0xFF8711B0
-#define OID_RT_PRO_SCSI_AUTO_TEST 0xFF8711B1
-#define OID_RT_PRO_USB_MAC_AC_FIFO_WRITE 0xFF8711B2
-#define OID_RT_PRO_USB_MAC_RX_FIFO_READ 0xFF8711B3
-#define OID_RT_PRO_USB_MAC_RX_FIFO_POLLING 0xFF8711B4
-
-#define OID_RT_PRO_H2C_SET_RATE_TABLE 0xFF8711FB
-#define OID_RT_PRO_H2C_GET_RATE_TABLE 0xFF8711FC
-#define OID_RT_PRO_H2C_C2H_LBK_TEST 0xFF8711FE
-
-#define OID_RT_PRO_ENCRYPTION_CTRL 0xFF871200
-#define OID_RT_PRO_ADD_STA_INFO 0xFF871201
-#define OID_RT_PRO_DELE_STA_INFO 0xFF871202
-#define OID_RT_PRO_QUERY_DR_VARIABLE 0xFF871203
-
-#define OID_RT_PRO_RX_PACKET_TYPE 0xFF871204
-
-#define OID_RT_PRO_READ_EFUSE 0xFF871205
-#define OID_RT_PRO_WRITE_EFUSE 0xFF871206
-#define OID_RT_PRO_RW_EFUSE_PGPKT 0xFF871207
-#define OID_RT_GET_EFUSE_CURRENT_SIZE 0xFF871208
-
-#define OID_RT_SET_BANDWIDTH 0xFF871209
-#define OID_RT_SET_CRYSTAL_CAP 0xFF87120A
-
-#define OID_RT_SET_RX_PACKET_TYPE 0xFF87120B
-
-#define OID_RT_GET_EFUSE_MAX_SIZE 0xFF87120C
-
-#define OID_RT_PRO_SET_TX_AGC_OFFSET 0xFF87120D
-
-#define OID_RT_PRO_SET_PKT_TEST_MODE 0xFF87120E
-
-#define OID_RT_PRO_FOR_EVM_TEST_SETTING 0xFF87120F
-
-#define OID_RT_PRO_GET_THERMAL_METER 0xFF871210
-
-#define OID_RT_RESET_PHY_RX_PACKET_COUNT 0xFF871211
-#define OID_RT_GET_PHY_RX_PACKET_RECEIVED 0xFF871212
-#define OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR 0xFF871213
-
-#define OID_RT_SET_POWER_DOWN 0xFF871214
-
-#define OID_RT_GET_POWER_MODE 0xFF871215
-
-#define OID_RT_PRO_EFUSE 0xFF871216
-#define OID_RT_PRO_EFUSE_MAP 0xFF871217
-
-#endif /*#ifndef __CUSTOM_OID_H */
-
diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
deleted file mode 100644
index 1b11f8b04e13..000000000000
--- a/drivers/staging/rtl8712/os_intfs.c
+++ /dev/null
@@ -1,482 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * os_intfs.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _OS_INTFS_C_
-
-#include <linux/module.h>
-#include <linux/kthread.h>
-#include <linux/firmware.h>
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "xmit_osdep.h"
-#include "recv_osdep.h"
-#include "rtl871x_ioctl.h"
-#include "usb_osintf.h"
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("rtl871x wireless lan driver");
-MODULE_AUTHOR("Larry Finger");
-
-static char ifname[IFNAMSIZ] = "wlan%d";
-
-/* module param defaults */
-static int chip_version = RTL8712_2ndCUT;
-static int rfintfs = HWPI;
-static int lbkmode = RTL8712_AIR_TRX;
-static int hci = RTL8712_USB;
-static int ampdu_enable = 1;/*for enable tx_ampdu*/
-
-/* The video_mode variable is for video mode.*/
-/* It may be specify when inserting module with video_mode=1 parameter.*/
-static int video_mode = 1; /* enable video mode*/
-
-/*Ndis802_11Infrastructure; infra, ad-hoc, auto*/
-static int network_mode = Ndis802_11IBSS;
-static int channel = 1;/*ad-hoc support requirement*/
-static int wireless_mode = WIRELESS_11BG;
-static int vrtl_carrier_sense = AUTO_VCS;
-static int vcs_type = RTS_CTS;
-static int frag_thresh = 2346;
-static int preamble = PREAMBLE_LONG;/*long, short, auto*/
-static int scan_mode = 1;/*active, passive*/
-static int adhoc_tx_pwr = 1;
-static int soft_ap;
-static int smart_ps = 1;
-static int power_mgnt = PS_MODE_ACTIVE;
-static int radio_enable = 1;
-static int long_retry_lmt = 7;
-static int short_retry_lmt = 7;
-static int busy_thresh = 40;
-static int ack_policy = NORMAL_ACK;
-static int mp_mode;
-static int software_encrypt;
-static int software_decrypt;
-
-static int wmm_enable;/* default is set to disable the wmm.*/
-static int uapsd_enable;
-static int uapsd_max_sp = NO_LIMIT;
-static int uapsd_acbk_en;
-static int uapsd_acbe_en;
-static int uapsd_acvi_en;
-static int uapsd_acvo_en;
-
-static int ht_enable = 1;
-static int cbw40_enable = 1;
-static int rf_config = RTL8712_RF_1T2R; /* 1T2R*/
-static int low_power;
-/* mac address to use instead of the one stored in Efuse */
-char *r8712_initmac;
-static char *initmac;
-/* if wifi_test = 1, driver will disable the turbo mode and pass it to
- * firmware private.
- */
-static int wifi_test;
-
-module_param_string(ifname, ifname, sizeof(ifname), 0644);
-module_param(wifi_test, int, 0644);
-module_param(initmac, charp, 0644);
-module_param(video_mode, int, 0644);
-module_param(chip_version, int, 0644);
-module_param(rfintfs, int, 0644);
-module_param(lbkmode, int, 0644);
-module_param(hci, int, 0644);
-module_param(network_mode, int, 0644);
-module_param(channel, int, 0644);
-module_param(mp_mode, int, 0644);
-module_param(wmm_enable, int, 0644);
-module_param(vrtl_carrier_sense, int, 0644);
-module_param(vcs_type, int, 0644);
-module_param(busy_thresh, int, 0644);
-module_param(ht_enable, int, 0644);
-module_param(cbw40_enable, int, 0644);
-module_param(ampdu_enable, int, 0644);
-module_param(rf_config, int, 0644);
-module_param(power_mgnt, int, 0644);
-module_param(low_power, int, 0644);
-
-MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default");
-MODULE_PARM_DESC(initmac, "MAC-Address, default: use FUSE");
-
-static int netdev_open(struct net_device *pnetdev);
-static int netdev_close(struct net_device *pnetdev);
-
-static void loadparam(struct _adapter *padapter, struct net_device *pnetdev)
-{
- struct registry_priv *registry_par = &padapter->registrypriv;
-
- registry_par->chip_version = (u8)chip_version;
- registry_par->rfintfs = (u8)rfintfs;
- registry_par->lbkmode = (u8)lbkmode;
- registry_par->hci = (u8)hci;
- registry_par->network_mode = (u8)network_mode;
- memcpy(registry_par->ssid.Ssid, "ANY", 3);
- registry_par->ssid.SsidLength = 3;
- registry_par->channel = (u8)channel;
- registry_par->wireless_mode = (u8)wireless_mode;
- registry_par->vrtl_carrier_sense = (u8)vrtl_carrier_sense;
- registry_par->vcs_type = (u8)vcs_type;
- registry_par->frag_thresh = (u16)frag_thresh;
- registry_par->preamble = (u8)preamble;
- registry_par->scan_mode = (u8)scan_mode;
- registry_par->adhoc_tx_pwr = (u8)adhoc_tx_pwr;
- registry_par->soft_ap = (u8)soft_ap;
- registry_par->smart_ps = (u8)smart_ps;
- registry_par->power_mgnt = (u8)power_mgnt;
- registry_par->radio_enable = (u8)radio_enable;
- registry_par->long_retry_lmt = (u8)long_retry_lmt;
- registry_par->short_retry_lmt = (u8)short_retry_lmt;
- registry_par->busy_thresh = (u16)busy_thresh;
- registry_par->ack_policy = (u8)ack_policy;
- registry_par->mp_mode = (u8)mp_mode;
- registry_par->software_encrypt = (u8)software_encrypt;
- registry_par->software_decrypt = (u8)software_decrypt;
- /*UAPSD*/
- registry_par->wmm_enable = (u8)wmm_enable;
- registry_par->uapsd_enable = (u8)uapsd_enable;
- registry_par->uapsd_max_sp = (u8)uapsd_max_sp;
- registry_par->uapsd_acbk_en = (u8)uapsd_acbk_en;
- registry_par->uapsd_acbe_en = (u8)uapsd_acbe_en;
- registry_par->uapsd_acvi_en = (u8)uapsd_acvi_en;
- registry_par->uapsd_acvo_en = (u8)uapsd_acvo_en;
- registry_par->ht_enable = (u8)ht_enable;
- registry_par->cbw40_enable = (u8)cbw40_enable;
- registry_par->ampdu_enable = (u8)ampdu_enable;
- registry_par->rf_config = (u8)rf_config;
- registry_par->low_power = (u8)low_power;
- registry_par->wifi_test = (u8)wifi_test;
- r8712_initmac = initmac;
-}
-
-static int r871x_net_set_mac_address(struct net_device *pnetdev, void *p)
-{
- struct _adapter *padapter = netdev_priv(pnetdev);
- struct sockaddr *addr = p;
-
- if (!padapter->bup)
- eth_hw_addr_set(pnetdev, addr->sa_data);
- return 0;
-}
-
-static struct net_device_stats *r871x_net_get_stats(struct net_device *pnetdev)
-{
- struct _adapter *padapter = netdev_priv(pnetdev);
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- padapter->stats.tx_packets = pxmitpriv->tx_pkts;
- padapter->stats.rx_packets = precvpriv->rx_pkts;
- padapter->stats.tx_dropped = pxmitpriv->tx_drop;
- padapter->stats.rx_dropped = precvpriv->rx_drop;
- padapter->stats.tx_bytes = pxmitpriv->tx_bytes;
- padapter->stats.rx_bytes = precvpriv->rx_bytes;
- return &padapter->stats;
-}
-
-static const struct net_device_ops rtl8712_netdev_ops = {
- .ndo_open = netdev_open,
- .ndo_stop = netdev_close,
- .ndo_start_xmit = r8712_xmit_entry,
- .ndo_set_mac_address = r871x_net_set_mac_address,
- .ndo_get_stats = r871x_net_get_stats,
- .ndo_do_ioctl = r871x_ioctl,
-};
-
-struct net_device *r8712_init_netdev(void)
-{
- struct _adapter *padapter;
- struct net_device *pnetdev;
-
- pnetdev = alloc_etherdev(sizeof(struct _adapter));
- if (!pnetdev)
- return NULL;
- if (dev_alloc_name(pnetdev, ifname) < 0) {
- strscpy(ifname, "wlan%d", sizeof(ifname));
- dev_alloc_name(pnetdev, ifname);
- }
- padapter = netdev_priv(pnetdev);
- padapter->pnetdev = pnetdev;
- pr_info("r8712u: register rtl8712_netdev_ops to netdev_ops\n");
- pnetdev->netdev_ops = &rtl8712_netdev_ops;
- pnetdev->watchdog_timeo = HZ; /* 1 second timeout */
- pnetdev->wireless_handlers = (struct iw_handler_def *)
- &r871x_handlers_def;
- loadparam(padapter, pnetdev);
- netif_carrier_off(pnetdev);
- padapter->pid = 0; /* Initial the PID value used for HW PBC.*/
- return pnetdev;
-}
-
-static u32 start_drv_threads(struct _adapter *padapter)
-{
- padapter->cmd_thread = kthread_run(r8712_cmd_thread, padapter, "%s",
- padapter->pnetdev->name);
- if (IS_ERR(padapter->cmd_thread))
- return _FAIL;
- return _SUCCESS;
-}
-
-void r8712_stop_drv_threads(struct _adapter *padapter)
-{
- struct completion *completion =
- &padapter->cmdpriv.terminate_cmdthread_comp;
-
- /*Below is to terminate r8712_cmd_thread & event_thread...*/
- complete(&padapter->cmdpriv.cmd_queue_comp);
- if (padapter->cmd_thread)
- wait_for_completion_interruptible(completion);
- padapter->cmdpriv.cmd_seq = 1;
-}
-
-static void start_drv_timers(struct _adapter *padapter)
-{
- mod_timer(&padapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer,
- jiffies + msecs_to_jiffies(5000));
- mod_timer(&padapter->mlmepriv.wdg_timer,
- jiffies + msecs_to_jiffies(2000));
-}
-
-void r8712_stop_drv_timers(struct _adapter *padapter)
-{
- del_timer_sync(&padapter->mlmepriv.assoc_timer);
- del_timer_sync(&padapter->securitypriv.tkip_timer);
- del_timer_sync(&padapter->mlmepriv.scan_to_timer);
- del_timer_sync(&padapter->mlmepriv.dhcp_timer);
- del_timer_sync(&padapter->mlmepriv.wdg_timer);
- del_timer_sync(&padapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer);
-}
-
-static void init_default_value(struct _adapter *padapter)
-{
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- /*xmit_priv*/
- pxmitpriv->vcs_setting = pregistrypriv->vrtl_carrier_sense;
- pxmitpriv->vcs = pregistrypriv->vcs_type;
- pxmitpriv->vcs_type = pregistrypriv->vcs_type;
- pxmitpriv->rts_thresh = pregistrypriv->rts_thresh;
- pxmitpriv->frag_len = pregistrypriv->frag_thresh;
- /* mlme_priv */
- /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/
- pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */
- /*ht_priv*/
- {
- int i;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-
- phtpriv->ampdu_enable = false;/*set to disabled*/
- for (i = 0; i < 16; i++)
- phtpriv->baddbareq_issued[i] = false;
- }
- /*security_priv*/
- psecuritypriv->sw_encrypt = pregistrypriv->software_encrypt;
- psecuritypriv->sw_decrypt = pregistrypriv->software_decrypt;
- psecuritypriv->binstallGrpkey = _FAIL;
- /*pwrctrl_priv*/
- /*registry_priv*/
- r8712_init_registrypriv_dev_network(padapter);
- r8712_update_registrypriv_dev_network(padapter);
- /*misc.*/
-}
-
-int r8712_init_drv_sw(struct _adapter *padapter)
-{
- int ret;
-
- ret = r8712_init_cmd_priv(&padapter->cmdpriv);
- if (ret)
- return ret;
- padapter->cmdpriv.padapter = padapter;
- ret = r8712_init_evt_priv(&padapter->evtpriv);
- if (ret)
- goto free_cmd;
- ret = r8712_init_mlme_priv(padapter);
- if (ret)
- goto free_evt;
- ret = _r8712_init_xmit_priv(&padapter->xmitpriv, padapter);
- if (ret)
- goto free_mlme;
- ret = _r8712_init_recv_priv(&padapter->recvpriv, padapter);
- if (ret)
- goto free_xmit;
- memset((unsigned char *)&padapter->securitypriv, 0,
- sizeof(struct security_priv));
- timer_setup(&padapter->securitypriv.tkip_timer,
- r8712_use_tkipkey_handler, 0);
- ret = _r8712_init_sta_priv(&padapter->stapriv);
- if (ret)
- goto free_recv;
- padapter->stapriv.padapter = padapter;
- r8712_init_bcmc_stainfo(padapter);
- r8712_init_pwrctrl_priv(padapter);
- mp871xinit(padapter);
- init_default_value(padapter);
- r8712_InitSwLeds(padapter);
- mutex_init(&padapter->mutex_start);
-
- return 0;
-
-free_recv:
- _r8712_free_recv_priv(&padapter->recvpriv);
-free_xmit:
- _free_xmit_priv(&padapter->xmitpriv);
-free_mlme:
- r8712_free_mlme_priv(&padapter->mlmepriv);
-free_evt:
- r8712_free_evt_priv(&padapter->evtpriv);
-free_cmd:
- r8712_free_cmd_priv(&padapter->cmdpriv);
- return ret;
-}
-
-void r8712_free_drv_sw(struct _adapter *padapter)
-{
- r8712_free_cmd_priv(&padapter->cmdpriv);
- r8712_free_evt_priv(&padapter->evtpriv);
- r8712_DeInitSwLeds(padapter);
- r8712_free_mlme_priv(&padapter->mlmepriv);
- _free_xmit_priv(&padapter->xmitpriv);
- _r8712_free_sta_priv(&padapter->stapriv);
- _r8712_free_recv_priv(&padapter->recvpriv);
- mp871xdeinit(padapter);
-}
-
-static void enable_video_mode(struct _adapter *padapter, int cbw40_value)
-{
- /* bit 8:
- * 1 -> enable video mode to 96B AP
- * 0 -> disable video mode to 96B AP
- * bit 9:
- * 1 -> enable 40MHz mode
- * 0 -> disable 40MHz mode
- * bit 10:
- * 1 -> enable STBC
- * 0 -> disable STBC
- */
- u32 intcmd = 0xf4000500; /* enable bit8, bit10*/
-
- if (cbw40_value) {
- /* if the driver supports the 40M bandwidth,
- * we can enable the bit 9.
- */
- intcmd |= 0x200;
- }
- r8712_fw_cmd(padapter, intcmd);
-}
-
-/*
- *
- * This function intends to handle the activation of an interface
- * i.e. when it is brought Up/Active from a Down state.
- *
- */
-static int netdev_open(struct net_device *pnetdev)
-{
- struct _adapter *padapter = netdev_priv(pnetdev);
-
- mutex_lock(&padapter->mutex_start);
- if (!padapter->bup) {
- padapter->driver_stopped = false;
- padapter->surprise_removed = false;
- padapter->bup = true;
- if (rtl871x_hal_init(padapter) != _SUCCESS)
- goto netdev_open_error;
- if (!r8712_initmac) {
- /* Use the mac address stored in the Efuse */
- eth_hw_addr_set(pnetdev,
- padapter->eeprompriv.mac_addr);
- } else {
- /* We have to inform f/w to use user-supplied MAC
- * address.
- */
- msleep(200);
- r8712_setMacAddr_cmd(padapter,
- (const u8 *)pnetdev->dev_addr);
- /*
- * The "myid" function will get the wifi mac address
- * from eeprompriv structure instead of netdev
- * structure. So, we have to overwrite the mac_addr
- * stored in the eeprompriv structure. In this case,
- * the real mac address won't be used anymore. So that,
- * the eeprompriv.mac_addr should store the mac which
- * users specify.
- */
- memcpy(padapter->eeprompriv.mac_addr,
- pnetdev->dev_addr, ETH_ALEN);
- }
- if (start_drv_threads(padapter) != _SUCCESS)
- goto netdev_open_error;
- if (!padapter->dvobjpriv.inirp_init)
- goto netdev_open_error;
- else
- padapter->dvobjpriv.inirp_init(padapter);
- r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
- padapter->registrypriv.smart_ps);
- }
- if (!netif_queue_stopped(pnetdev))
- netif_start_queue(pnetdev);
- else
- netif_wake_queue(pnetdev);
-
- if (video_mode)
- enable_video_mode(padapter, cbw40_enable);
- /* start driver mlme relation timer */
- start_drv_timers(padapter);
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
- mutex_unlock(&padapter->mutex_start);
- return 0;
-netdev_open_error:
- padapter->bup = false;
- netif_carrier_off(pnetdev);
- netif_stop_queue(pnetdev);
- mutex_unlock(&padapter->mutex_start);
- return -1;
-}
-
-/*
- *
- * This function intends to handle the shutdown of an interface
- * i.e. when it is brought Down from an Up/Active state.
- *
- */
-static int netdev_close(struct net_device *pnetdev)
-{
- struct _adapter *padapter = netdev_priv(pnetdev);
-
- /* Close LED*/
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_POWER_OFF);
- msleep(200);
-
- /*s1.*/
- if (pnetdev) {
- if (!netif_queue_stopped(pnetdev))
- netif_stop_queue(pnetdev);
- }
- /*s2.*/
- /*s2-1. issue disassoc_cmd to fw*/
- r8712_disassoc_cmd(padapter);
- /*s2-2. indicate disconnect to os*/
- r8712_ind_disconnect(padapter);
- /*s2-3.*/
- r8712_free_assoc_resources(padapter);
- /*s2-4.*/
- r8712_free_network_queue(padapter);
- return 0;
-}
-
-#include "mlme_osdep.h"
diff --git a/drivers/staging/rtl8712/osdep_intf.h b/drivers/staging/rtl8712/osdep_intf.h
deleted file mode 100644
index 9e75116c987e..000000000000
--- a/drivers/staging/rtl8712/osdep_intf.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __OSDEP_INTF_H_
-#define __OSDEP_INTF_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#define RND4(x) (((x >> 2) + ((x & 3) != 0)) << 2)
-
-struct intf_priv {
- u8 *intf_dev;
- /* when in USB, IO is through interrupt in/out endpoints */
- struct usb_device *udev;
- struct urb *piorw_urb;
- struct completion io_retevt_comp;
-};
-
-int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-
-#endif /*_OSDEP_INTF_H_*/
diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h
deleted file mode 100644
index 0d9bb42cbc58..000000000000
--- a/drivers/staging/rtl8712/osdep_service.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __OSDEP_SERVICE_H_
-#define __OSDEP_SERVICE_H_
-
-#define _SUCCESS 1
-#define _FAIL 0
-
-#include <linux/spinlock.h>
-
-#include <linux/interrupt.h>
-#include <linux/semaphore.h>
-#include <linux/sched/signal.h>
-#include <linux/sem.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <net/iw_handler.h>
-#include <linux/proc_fs.h> /* Necessary because we use the proc fs */
-
-#include "basic_types.h"
-
-struct __queue {
- struct list_head queue;
- spinlock_t lock;
-};
-
-#define _pkt struct sk_buff
-#define _buffer unsigned char
-
-#define _init_queue(pqueue) \
- do { \
- INIT_LIST_HEAD(&((pqueue)->queue)); \
- spin_lock_init(&((pqueue)->lock)); \
- } while (0)
-
-static inline u32 end_of_queue_search(struct list_head *head,
- struct list_head *plist)
-{
- return (head == plist);
-}
-
-static inline void flush_signals_thread(void)
-{
- if (signal_pending(current))
- flush_signals(current);
-}
-
-#endif
-
diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c
deleted file mode 100644
index 215fca4abb3a..000000000000
--- a/drivers/staging/rtl8712/recv_linux.c
+++ /dev/null
@@ -1,139 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * recv_linux.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RECV_OSDEP_C_
-
-#include <linux/usb.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "wifi.h"
-#include "recv_osdep.h"
-#include "osdep_intf.h"
-#include "ethernet.h"
-#include <linux/if_arp.h>
-#include "usb_ops.h"
-
-/*init os related resource in struct recv_priv*/
-/*alloc os related resource in union recv_frame*/
-void r8712_os_recv_resource_alloc(struct _adapter *padapter,
- union recv_frame *precvframe)
-{
- precvframe->u.hdr.pkt_newalloc = NULL;
- precvframe->u.hdr.pkt = NULL;
-}
-
-/*alloc os related resource in struct recv_buf*/
-int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter,
- struct recv_buf *precvbuf)
-{
- int res = 0;
-
- precvbuf->irp_pending = false;
- precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
- if (!precvbuf->purb)
- res = -ENOMEM;
- precvbuf->pskb = NULL;
- precvbuf->pallocated_buf = NULL;
- precvbuf->pbuf = NULL;
- precvbuf->pdata = NULL;
- precvbuf->phead = NULL;
- precvbuf->ptail = NULL;
- precvbuf->pend = NULL;
- precvbuf->transfer_len = 0;
- precvbuf->len = 0;
- return res;
-}
-
-/*free os related resource in struct recv_buf*/
-void r8712_os_recvbuf_resource_free(struct _adapter *padapter,
- struct recv_buf *precvbuf)
-{
- if (precvbuf->pskb)
- dev_kfree_skb_any(precvbuf->pskb);
- if (precvbuf->purb) {
- usb_kill_urb(precvbuf->purb);
- usb_free_urb(precvbuf->purb);
- }
-}
-
-void r8712_handle_tkip_mic_err(struct _adapter *adapter, u8 bgroup)
-{
- union iwreq_data wrqu;
- struct iw_michaelmicfailure ev;
- struct mlme_priv *mlmepriv = &adapter->mlmepriv;
-
- memset(&ev, 0x00, sizeof(ev));
- if (bgroup)
- ev.flags |= IW_MICFAILURE_GROUP;
- else
- ev.flags |= IW_MICFAILURE_PAIRWISE;
- ev.src_addr.sa_family = ARPHRD_ETHER;
- ether_addr_copy(ev.src_addr.sa_data, &mlmepriv->assoc_bssid[0]);
- memset(&wrqu, 0x00, sizeof(wrqu));
- wrqu.data.length = sizeof(ev);
- wireless_send_event(adapter->pnetdev, IWEVMICHAELMICFAILURE, &wrqu,
- (char *)&ev);
-}
-
-void r8712_recv_indicatepkt(struct _adapter *adapter,
- union recv_frame *recvframe)
-{
- struct recv_priv *recvpriv;
- struct __queue *free_recv_queue;
- _pkt *skb;
- struct rx_pkt_attrib *attrib = &recvframe->u.hdr.attrib;
-
- recvpriv = &adapter->recvpriv;
- free_recv_queue = &recvpriv->free_recv_queue;
- skb = recvframe->u.hdr.pkt;
- if (!skb)
- goto _recv_indicatepkt_drop;
- skb->data = recvframe->u.hdr.rx_data;
- skb->len = recvframe->u.hdr.len;
- skb_set_tail_pointer(skb, skb->len);
- if ((attrib->tcpchk_valid == 1) && (attrib->tcp_chkrpt == 1))
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- else
- skb->ip_summed = CHECKSUM_NONE;
- skb->dev = adapter->pnetdev;
- skb->protocol = eth_type_trans(skb, adapter->pnetdev);
- netif_rx(skb);
- recvframe->u.hdr.pkt = NULL; /* pointers to NULL before
- * r8712_free_recvframe()
- */
- r8712_free_recvframe(recvframe, free_recv_queue);
- return;
-_recv_indicatepkt_drop:
- /*enqueue back to free_recv_queue*/
- if (recvframe)
- r8712_free_recvframe(recvframe, free_recv_queue);
- recvpriv->rx_drop++;
-}
-
-static void _r8712_reordering_ctrl_timeout_handler (struct timer_list *t)
-{
- struct recv_reorder_ctrl *reorder_ctrl =
- from_timer(reorder_ctrl, t, reordering_ctrl_timer);
-
- r8712_reordering_ctrl_timeout_handler(reorder_ctrl);
-}
-
-void r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
-{
- timer_setup(&preorder_ctrl->reordering_ctrl_timer,
- _r8712_reordering_ctrl_timeout_handler, 0);
-}
diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h
deleted file mode 100644
index fbe3f2868506..000000000000
--- a/drivers/staging/rtl8712/recv_osdep.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RECV_OSDEP_H_
-#define __RECV_OSDEP_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include <linux/skbuff.h>
-
-int _r8712_init_recv_priv(struct recv_priv *precvpriv,
- struct _adapter *padapter);
-void _r8712_free_recv_priv(struct recv_priv *precvpriv);
-void r8712_recv_entry(union recv_frame *precv_frame);
-void r8712_recv_indicatepkt(struct _adapter *adapter,
- union recv_frame *precv_frame);
-void r8712_handle_tkip_mic_err(struct _adapter *padapter, u8 bgroup);
-int r8712_init_recv_priv(struct recv_priv *precvpriv,
- struct _adapter *padapter);
-void r8712_free_recv_priv(struct recv_priv *precvpriv);
-void r8712_os_recv_resource_alloc(struct _adapter *padapter,
- union recv_frame *precvframe);
-int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter,
- struct recv_buf *precvbuf);
-void r8712_os_recvbuf_resource_free(struct _adapter *padapter,
- struct recv_buf *precvbuf);
-void r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl);
-
-#endif
diff --git a/drivers/staging/rtl8712/rtl8712_bitdef.h b/drivers/staging/rtl8712/rtl8712_bitdef.h
deleted file mode 100644
index a4a687dcc2e7..000000000000
--- a/drivers/staging/rtl8712/rtl8712_bitdef.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#ifndef __RTL8712_BITDEF_H__
-#define __RTL8712_BITDEF_H__
-
-#include "rtl8712_cmdctrl_bitdef.h"
-#include "rtl8712_syscfg_bitdef.h"
-#include "rtl8712_macsetting_bitdef.h"
-#include "rtl8712_timectrl_bitdef.h"
-#include "rtl8712_fifoctrl_bitdef.h"
-#include "rtl8712_ratectrl_bitdef.h"
-#include "rtl8712_edcasetting_bitdef.h"
-#include "rtl8712_wmac_bitdef.h"
-#include "rtl8712_security_bitdef.h"
-#include "rtl8712_powersave_bitdef.h"
-#include "rtl8712_gp_bitdef.h"
-#include "rtl8712_interrupt_bitdef.h"
-#include "rtl8712_debugctrl_bitdef.h"
-
-#endif /* __RTL8712_BITDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c
deleted file mode 100644
index bb7db96ed821..000000000000
--- a/drivers/staging/rtl8712/rtl8712_cmd.c
+++ /dev/null
@@ -1,409 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl8712_cmd.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL8712_CMD_C_
-
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/sched/signal.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/usb.h>
-#include <linux/usb/ch9.h>
-#include <linux/circ_buf.h>
-#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-#include <linux/atomic.h>
-#include <linux/semaphore.h>
-#include <linux/rtnetlink.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "mlme_osdep.h"
-#include "rtl871x_ioctl_set.h"
-
-static void check_hw_pbc(struct _adapter *padapter)
-{
- u8 tmp1byte;
-
- r8712_write8(padapter, MAC_PINMUX_CTRL, (GPIOMUX_EN | GPIOSEL_GPIO));
- tmp1byte = r8712_read8(padapter, GPIO_IO_SEL);
- tmp1byte &= ~(HAL_8192S_HW_GPIO_WPS_BIT);
- r8712_write8(padapter, GPIO_IO_SEL, tmp1byte);
- tmp1byte = r8712_read8(padapter, GPIO_CTRL);
- if (tmp1byte == 0xff)
- return;
- if (tmp1byte & HAL_8192S_HW_GPIO_WPS_BIT) {
- /* Here we only set bPbcPressed to true
- * After trigger PBC, the variable will be set to false
- */
- netdev_dbg(padapter->pnetdev, "CheckPbcGPIO - PBC is pressed !!!!\n");
- /* 0 is the default value and it means the application monitors
- * the HW PBC doesn't provide its pid to driver.
- */
- if (padapter->pid == 0)
- return;
- kill_pid(find_vpid(padapter->pid), SIGUSR1, 1);
- }
-}
-
-/* query rx phy status from fw.
- * Adhoc mode: beacon.
- * Infrastructure mode: beacon , data.
- */
-static void query_fw_rx_phy_status(struct _adapter *padapter)
-{
- u32 val32 = 0;
- int pollingcnts = 50;
-
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
- r8712_write32(padapter, IOCMD_CTRL_REG, 0xf4000001);
- msleep(100);
- /* Wait FW complete IO Cmd */
- while ((r8712_read32(padapter, IOCMD_CTRL_REG)) &&
- (pollingcnts > 0)) {
- pollingcnts--;
- msleep(20);
- }
- if (pollingcnts != 0)
- val32 = r8712_read32(padapter, IOCMD_DATA_REG);
- else /* time out */
- val32 = 0;
- val32 >>= 4;
- padapter->recvpriv.fw_rssi =
- (u8)r8712_signal_scale_mapping(val32);
- }
-}
-
-/* check mlme, hw, phy, or dynamic algorithm status. */
-static void StatusWatchdogCallback(struct _adapter *padapter)
-{
- check_hw_pbc(padapter);
- query_fw_rx_phy_status(padapter);
-}
-
-static void r871x_internal_cmd_hdl(struct _adapter *padapter, u8 *pbuf)
-{
- struct drvint_cmd_parm *pdrvcmd;
-
- if (!pbuf)
- return;
- pdrvcmd = (struct drvint_cmd_parm *)pbuf;
- switch (pdrvcmd->i_cid) {
- case WDG_WK_CID:
- StatusWatchdogCallback(padapter);
- break;
- default:
- break;
- }
- kfree(pdrvcmd->pbuf);
-}
-
-static u8 read_bbreg_hdl(struct _adapter *padapter, u8 *pbuf)
-{
- struct cmd_obj *pcmd = (struct cmd_obj *)pbuf;
-
- r8712_free_cmd_obj(pcmd);
- return H2C_SUCCESS;
-}
-
-static u8 write_bbreg_hdl(struct _adapter *padapter, u8 *pbuf)
-{
- void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd);
- struct cmd_obj *pcmd = (struct cmd_obj *)pbuf;
-
- pcmd_callback = cmd_callback[pcmd->cmdcode].callback;
- if (!pcmd_callback)
- r8712_free_cmd_obj(pcmd);
- else
- pcmd_callback(padapter, pcmd);
- return H2C_SUCCESS;
-}
-
-static u8 read_rfreg_hdl(struct _adapter *padapter, u8 *pbuf)
-{
- u32 val;
- void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd);
- struct cmd_obj *pcmd = (struct cmd_obj *)pbuf;
-
- if (pcmd->rsp && pcmd->rspsz > 0)
- memcpy(pcmd->rsp, (u8 *)&val, pcmd->rspsz);
- pcmd_callback = cmd_callback[pcmd->cmdcode].callback;
- if (!pcmd_callback)
- r8712_free_cmd_obj(pcmd);
- else
- pcmd_callback(padapter, pcmd);
- return H2C_SUCCESS;
-}
-
-static u8 write_rfreg_hdl(struct _adapter *padapter, u8 *pbuf)
-{
- void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd);
- struct cmd_obj *pcmd = (struct cmd_obj *)pbuf;
-
- pcmd_callback = cmd_callback[pcmd->cmdcode].callback;
- if (!pcmd_callback)
- r8712_free_cmd_obj(pcmd);
- else
- pcmd_callback(padapter, pcmd);
- return H2C_SUCCESS;
-}
-
-static u8 sys_suspend_hdl(struct _adapter *padapter, u8 *pbuf)
-{
- struct cmd_obj *pcmd = (struct cmd_obj *)pbuf;
-
- r8712_free_cmd_obj(pcmd);
- return H2C_SUCCESS;
-}
-
-static struct cmd_obj *cmd_hdl_filter(struct _adapter *padapter,
- struct cmd_obj *pcmd)
-{
- struct cmd_obj *pcmd_r;
-
- if (!pcmd)
- return pcmd;
- pcmd_r = NULL;
-
- switch (pcmd->cmdcode) {
- case GEN_CMD_CODE(_Read_BBREG):
- read_bbreg_hdl(padapter, (u8 *)pcmd);
- break;
- case GEN_CMD_CODE(_Write_BBREG):
- write_bbreg_hdl(padapter, (u8 *)pcmd);
- break;
- case GEN_CMD_CODE(_Read_RFREG):
- read_rfreg_hdl(padapter, (u8 *)pcmd);
- break;
- case GEN_CMD_CODE(_Write_RFREG):
- write_rfreg_hdl(padapter, (u8 *)pcmd);
- break;
- case GEN_CMD_CODE(_SetUsbSuspend):
- sys_suspend_hdl(padapter, (u8 *)pcmd);
- break;
- case GEN_CMD_CODE(_JoinBss):
- r8712_joinbss_reset(padapter);
- /* Before set JoinBss_CMD to FW, driver must ensure FW is in
- * PS_MODE_ACTIVE. Directly write rpwm to radio on and assign
- * new pwr_mode to Driver, instead of use workitem to change
- * state.
- */
- if (padapter->pwrctrlpriv.pwr_mode > PS_MODE_ACTIVE) {
- padapter->pwrctrlpriv.pwr_mode = PS_MODE_ACTIVE;
- mutex_lock(&padapter->pwrctrlpriv.mutex_lock);
- r8712_set_rpwm(padapter, PS_STATE_S4);
- mutex_unlock(&padapter->pwrctrlpriv.mutex_lock);
- }
- pcmd_r = pcmd;
- break;
- case _DRV_INT_CMD_:
- r871x_internal_cmd_hdl(padapter, pcmd->parmbuf);
- r8712_free_cmd_obj(pcmd);
- pcmd_r = NULL;
- break;
- default:
- pcmd_r = pcmd;
- break;
- }
- return pcmd_r; /* if returning pcmd_r == NULL, pcmd must be free. */
-}
-
-u8 r8712_fw_cmd(struct _adapter *pAdapter, u32 cmd)
-{
- int pollingcnts = 50;
-
- r8712_write32(pAdapter, IOCMD_CTRL_REG, cmd);
- msleep(100);
- while ((r8712_read32(pAdapter, IOCMD_CTRL_REG != 0)) &&
- (pollingcnts > 0)) {
- pollingcnts--;
- msleep(20);
- }
- if (pollingcnts == 0)
- return false;
- return true;
-}
-
-void r8712_fw_cmd_data(struct _adapter *pAdapter, u32 *value, u8 flag)
-{
- if (flag == 0) /* set */
- r8712_write32(pAdapter, IOCMD_DATA_REG, *value);
- else /* query */
- *value = r8712_read32(pAdapter, IOCMD_DATA_REG);
-}
-
-int r8712_cmd_thread(void *context)
-{
- struct cmd_obj *pcmd;
- unsigned int cmdsz, wr_sz;
- __le32 *pcmdbuf;
- struct tx_desc *pdesc;
- void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd);
- struct _adapter *padapter = context;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct completion *cmd_queue_comp =
- &pcmdpriv->cmd_queue_comp;
- struct mutex *pwctrl_lock = &padapter->pwrctrlpriv.mutex_lock;
-
- allow_signal(SIGTERM);
- while (1) {
- if (wait_for_completion_interruptible(cmd_queue_comp))
- break;
- if (padapter->driver_stopped || padapter->surprise_removed)
- break;
- if (r8712_register_cmd_alive(padapter))
- continue;
-_next:
- pcmd = r8712_dequeue_cmd(&pcmdpriv->cmd_queue);
- if (!(pcmd)) {
- r8712_unregister_cmd_alive(padapter);
- continue;
- }
- pcmdbuf = (__le32 *)pcmdpriv->cmd_buf;
- pdesc = (struct tx_desc *)pcmdbuf;
- memset(pdesc, 0, TXDESC_SIZE);
- pcmd = cmd_hdl_filter(padapter, pcmd);
- if (pcmd) { /* if pcmd != NULL, cmd will be handled by f/w */
- struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
- u8 blnPending = 0;
- u16 cmdcode = pcmd->cmdcode;
-
- pcmdpriv->cmd_issued_cnt++;
- cmdsz = round_up(pcmd->cmdsz, 8);
- wr_sz = TXDESC_SIZE + 8 + cmdsz;
- pdesc->txdw0 |= cpu_to_le32((wr_sz - TXDESC_SIZE) &
- 0x0000ffff);
- if (pdvobj->ishighspeed) {
- if ((wr_sz % 512) == 0)
- blnPending = 1;
- } else {
- if ((wr_sz % 64) == 0)
- blnPending = 1;
- }
- if (blnPending) { /* 32 bytes for TX Desc - 8 offset */
- pdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE +
- OFFSET_SZ + 8) << OFFSET_SHT) &
- 0x00ff0000);
- } else {
- pdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE +
- OFFSET_SZ) <<
- OFFSET_SHT) &
- 0x00ff0000);
- }
- pdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
- pdesc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) &
- 0x00001f00);
- pcmdbuf += (TXDESC_SIZE >> 2);
- *pcmdbuf = cpu_to_le32((cmdsz & 0x0000ffff) |
- (pcmd->cmdcode << 16) |
- (pcmdpriv->cmd_seq << 24));
- pcmdbuf += 2; /* 8 bytes alignment */
- memcpy((u8 *)pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
- if (blnPending)
- wr_sz += 8; /* Append 8 bytes */
- r8712_write_mem(padapter, RTL8712_DMA_H2CCMD, wr_sz,
- (u8 *)pdesc);
- pcmdpriv->cmd_seq++;
- if (cmdcode == GEN_CMD_CODE(_CreateBss)) {
- pcmd->res = H2C_SUCCESS;
- pcmd_callback = cmd_callback[cmdcode].callback;
- if (pcmd_callback)
- pcmd_callback(padapter, pcmd);
- continue;
- }
- if (cmdcode == GEN_CMD_CODE(_SetPwrMode)) {
- if (padapter->pwrctrlpriv.bSleep) {
- mutex_lock(pwctrl_lock);
- r8712_set_rpwm(padapter, PS_STATE_S2);
- mutex_unlock(pwctrl_lock);
- }
- }
- r8712_free_cmd_obj(pcmd);
- if (list_empty(&pcmdpriv->cmd_queue.queue)) {
- r8712_unregister_cmd_alive(padapter);
- continue;
- } else {
- goto _next;
- }
- } else {
- goto _next;
- }
- flush_signals_thread();
- }
- /* free all cmd_obj resources */
- do {
- pcmd = r8712_dequeue_cmd(&pcmdpriv->cmd_queue);
- if (!pcmd)
- break;
- r8712_free_cmd_obj(pcmd);
- } while (1);
- complete(&pcmdpriv->terminate_cmdthread_comp);
- return 0;
-}
-
-void r8712_event_handle(struct _adapter *padapter, __le32 *peventbuf)
-{
- u8 evt_code, evt_seq;
- u16 evt_sz;
- void (*event_callback)(struct _adapter *dev, u8 *pbuf);
- struct evt_priv *pevt_priv = &padapter->evtpriv;
-
- if (!peventbuf)
- goto _abort_event_;
- evt_sz = (u16)(le32_to_cpu(*peventbuf) & 0xffff);
- evt_seq = (u8)((le32_to_cpu(*peventbuf) >> 24) & 0x7f);
- evt_code = (u8)((le32_to_cpu(*peventbuf) >> 16) & 0xff);
- /* checking event sequence... */
- if ((evt_seq & 0x7f) != pevt_priv->event_seq) {
- pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
- goto _abort_event_;
- }
- /* checking if event code is valid */
- if (evt_code >= MAX_C2HEVT) {
- pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
- goto _abort_event_;
- } else if ((evt_code == GEN_EVT_CODE(_Survey)) &&
- (evt_sz > sizeof(struct wlan_bssid_ex))) {
- pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
- goto _abort_event_;
- }
- /* checking if event size match the event parm size */
- if ((wlanevents[evt_code].parmsize) &&
- (wlanevents[evt_code].parmsize != evt_sz)) {
- pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
- goto _abort_event_;
- } else if ((evt_sz == 0) && (evt_code != GEN_EVT_CODE(_WPS_PBC))) {
- pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
- goto _abort_event_;
- }
- pevt_priv->event_seq++; /* update evt_seq */
- if (pevt_priv->event_seq > 127)
- pevt_priv->event_seq = 0;
- /* move to event content, 8 bytes alignment */
- peventbuf = peventbuf + 2;
- event_callback = wlanevents[evt_code].event_callback;
- if (event_callback)
- event_callback(padapter, (u8 *)peventbuf);
- pevt_priv->evt_done_cnt++;
-_abort_event_:
- return;
-}
diff --git a/drivers/staging/rtl8712/rtl8712_cmd.h b/drivers/staging/rtl8712/rtl8712_cmd.h
deleted file mode 100644
index a34d0dd023f3..000000000000
--- a/drivers/staging/rtl8712/rtl8712_cmd.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_CMD_H_
-#define __RTL8712_CMD_H_
-
-#define CMD_HDR_SZ 8
-
-u8 r8712_fw_cmd(struct _adapter *pAdapter, u32 cmd);
-void r8712_fw_cmd_data(struct _adapter *pAdapter, u32 *value, u8 flag);
-
-struct cmd_hdr {
- u32 cmd_dw0;
- u32 cmd_dw1;
-};
-
-enum rtl8712_h2c_cmd {
- GEN_CMD_CODE(_Read_MACREG), /*0*/
- GEN_CMD_CODE(_Write_MACREG),
- GEN_CMD_CODE(_Read_BBREG),
- GEN_CMD_CODE(_Write_BBREG),
- GEN_CMD_CODE(_Read_RFREG),
- GEN_CMD_CODE(_Write_RFREG), /*5*/
- GEN_CMD_CODE(_Read_EEPROM),
- GEN_CMD_CODE(_Write_EEPROM),
- GEN_CMD_CODE(_Read_EFUSE),
- GEN_CMD_CODE(_Write_EFUSE),
-
- GEN_CMD_CODE(_Read_CAM), /*10*/
- GEN_CMD_CODE(_Write_CAM),
- GEN_CMD_CODE(_setBCNITV),
- GEN_CMD_CODE(_setMBIDCFG),
- GEN_CMD_CODE(_JoinBss), /*14*/
- GEN_CMD_CODE(_DisConnect), /*15*/
- GEN_CMD_CODE(_CreateBss),
- GEN_CMD_CODE(_SetOpMode),
- GEN_CMD_CODE(_SiteSurvey), /*18*/
- GEN_CMD_CODE(_SetAuth),
-
- GEN_CMD_CODE(_SetKey), /*20*/
- GEN_CMD_CODE(_SetStaKey),
- GEN_CMD_CODE(_SetAssocSta),
- GEN_CMD_CODE(_DelAssocSta),
- GEN_CMD_CODE(_SetStaPwrState),
- GEN_CMD_CODE(_SetBasicRate), /*25*/
- GEN_CMD_CODE(_GetBasicRate),
- GEN_CMD_CODE(_SetDataRate),
- GEN_CMD_CODE(_GetDataRate),
- GEN_CMD_CODE(_SetPhyInfo),
-
- GEN_CMD_CODE(_GetPhyInfo), /*30*/
- GEN_CMD_CODE(_SetPhy),
- GEN_CMD_CODE(_GetPhy),
- GEN_CMD_CODE(_readRssi),
- GEN_CMD_CODE(_readGain),
- GEN_CMD_CODE(_SetAtim), /*35*/
- GEN_CMD_CODE(_SetPwrMode),
- GEN_CMD_CODE(_JoinbssRpt),
- GEN_CMD_CODE(_SetRaTable),
- GEN_CMD_CODE(_GetRaTable),
-
- GEN_CMD_CODE(_GetCCXReport), /*40*/
- GEN_CMD_CODE(_GetDTMReport),
- GEN_CMD_CODE(_GetTXRateStatistics),
- GEN_CMD_CODE(_SetUsbSuspend),
- GEN_CMD_CODE(_SetH2cLbk),
- GEN_CMD_CODE(_AddBAReq), /*45*/
-
- GEN_CMD_CODE(_SetChannel), /*46*/
-/* MP_OFFLOAD Start (47~54)*/
- GEN_CMD_CODE(_SetTxPower),
- GEN_CMD_CODE(_SwitchAntenna),
- GEN_CMD_CODE(_SetCrystalCap),
- GEN_CMD_CODE(_SetSingleCarrierTx), /*50*/
- GEN_CMD_CODE(_SetSingleToneTx),
- GEN_CMD_CODE(_SetCarrierSuppressionTx),
- GEN_CMD_CODE(_SetContinuousTx),
- GEN_CMD_CODE(_SwitchBandwidth), /*54*/
-/* MP_OFFLOAD End*/
- GEN_CMD_CODE(_TX_Beacon), /*55*/
- GEN_CMD_CODE(_SetPowerTracking),
- GEN_CMD_CODE(_AMSDU_TO_AMPDU), /*57*/
- GEN_CMD_CODE(_SetMacAddress), /*58*/
-
- GEN_CMD_CODE(_DisconnectCtrl), /*59*/
- GEN_CMD_CODE(_SetChannelPlan), /*60*/
- GEN_CMD_CODE(_DisconnectCtrlEx), /*61*/
-
- /* To do, modify these h2c cmd, add or delete */
- GEN_CMD_CODE(_GetH2cLbk),
-
- /* WPS extra IE */
- GEN_CMD_CODE(_SetProbeReqExtraIE),
- GEN_CMD_CODE(_SetAssocReqExtraIE),
- GEN_CMD_CODE(_SetProbeRspExtraIE),
- GEN_CMD_CODE(_SetAssocRspExtraIE),
-
- /* the following is driver will do */
- GEN_CMD_CODE(_GetCurDataRate),
-
- GEN_CMD_CODE(_GetTxRetrycnt), /* to record times that Tx retry to
- * transmit packet after association
- */
- GEN_CMD_CODE(_GetRxRetrycnt), /* to record total number of the
- * received frame with ReTry bit set in
- * the WLAN header
- */
-
- GEN_CMD_CODE(_GetBCNOKcnt),
- GEN_CMD_CODE(_GetBCNERRcnt),
- GEN_CMD_CODE(_GetCurTxPwrLevel),
-
- GEN_CMD_CODE(_SetDIG),
- GEN_CMD_CODE(_SetRA),
- GEN_CMD_CODE(_SetPT),
- GEN_CMD_CODE(_ReadTSSI),
-
- MAX_H2CCMD
-};
-
-#define _GetBBReg_CMD_ _Read_BBREG_CMD_
-#define _SetBBReg_CMD_ _Write_BBREG_CMD_
-#define _GetRFReg_CMD_ _Read_RFREG_CMD_
-#define _SetRFReg_CMD_ _Write_RFREG_CMD_
-#define _DRV_INT_CMD_ (MAX_H2CCMD + 1)
-#define _SetRFIntFs_CMD_ (MAX_H2CCMD + 2)
-
-#ifdef _RTL8712_CMD_C_
-static struct _cmd_callback cmd_callback[] = {
- {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/
- {GEN_CMD_CODE(_Write_MACREG), NULL},
- {GEN_CMD_CODE(_Read_BBREG), NULL},
- {GEN_CMD_CODE(_Write_BBREG), NULL},
- {GEN_CMD_CODE(_Read_RFREG), &r8712_getbbrfreg_cmdrsp_callback},
- {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/
- {GEN_CMD_CODE(_Read_EEPROM), NULL},
- {GEN_CMD_CODE(_Write_EEPROM), NULL},
- {GEN_CMD_CODE(_Read_EFUSE), NULL},
- {GEN_CMD_CODE(_Write_EFUSE), NULL},
-
- {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/
- {GEN_CMD_CODE(_Write_CAM), NULL},
- {GEN_CMD_CODE(_setBCNITV), NULL},
- {GEN_CMD_CODE(_setMBIDCFG), NULL},
- {GEN_CMD_CODE(_JoinBss), &r8712_joinbss_cmd_callback}, /*14*/
- {GEN_CMD_CODE(_DisConnect), &r8712_disassoc_cmd_callback}, /*15*/
- {GEN_CMD_CODE(_CreateBss), &r8712_createbss_cmd_callback},
- {GEN_CMD_CODE(_SetOpMode), NULL},
- {GEN_CMD_CODE(_SiteSurvey), &r8712_survey_cmd_callback}, /*18*/
- {GEN_CMD_CODE(_SetAuth), NULL},
-
- {GEN_CMD_CODE(_SetKey), NULL}, /*20*/
- {GEN_CMD_CODE(_SetStaKey), &r8712_setstaKey_cmdrsp_callback},
- {GEN_CMD_CODE(_SetAssocSta), &r8712_setassocsta_cmdrsp_callback},
- {GEN_CMD_CODE(_DelAssocSta), NULL},
- {GEN_CMD_CODE(_SetStaPwrState), NULL},
- {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/
- {GEN_CMD_CODE(_GetBasicRate), NULL},
- {GEN_CMD_CODE(_SetDataRate), NULL},
- {GEN_CMD_CODE(_GetDataRate), NULL},
- {GEN_CMD_CODE(_SetPhyInfo), NULL},
-
- {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/
- {GEN_CMD_CODE(_SetPhy), NULL},
- {GEN_CMD_CODE(_GetPhy), NULL},
- {GEN_CMD_CODE(_readRssi), NULL},
- {GEN_CMD_CODE(_readGain), NULL},
- {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/
- {GEN_CMD_CODE(_SetPwrMode), NULL},
- {GEN_CMD_CODE(_JoinbssRpt), NULL},
- {GEN_CMD_CODE(_SetRaTable), NULL},
- {GEN_CMD_CODE(_GetRaTable), NULL},
-
- {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/
- {GEN_CMD_CODE(_GetDTMReport), NULL},
- {GEN_CMD_CODE(_GetTXRateStatistics), NULL},
- {GEN_CMD_CODE(_SetUsbSuspend), NULL},
- {GEN_CMD_CODE(_SetH2cLbk), NULL},
- {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/
-
- {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/
-/* MP_OFFLOAD Start (47~54)*/
- {GEN_CMD_CODE(_SetTxPower), NULL},
- {GEN_CMD_CODE(_SwitchAntenna), NULL},
- {GEN_CMD_CODE(_SetCrystalCap), NULL},
- {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/
- {GEN_CMD_CODE(_SetSingleToneTx), NULL},
- {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL},
- {GEN_CMD_CODE(_SetContinuousTx), NULL},
- {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/
-/* MP_OFFLOAD End*/
- {GEN_CMD_CODE(_TX_Beacon), NULL}, /*55*/
- {GEN_CMD_CODE(_SetPowerTracking), NULL},
- {GEN_CMD_CODE(_AMSDU_TO_AMPDU), NULL}, /*57*/
- {GEN_CMD_CODE(_SetMacAddress), NULL}, /*58*/
-
- {GEN_CMD_CODE(_DisconnectCtrl), NULL}, /*59*/
- {GEN_CMD_CODE(_SetChannelPlan), NULL}, /*60*/
- {GEN_CMD_CODE(_DisconnectCtrlEx), NULL}, /*61*/
-
- /* To do, modify these h2c cmd, add or delete */
- {GEN_CMD_CODE(_GetH2cLbk), NULL},
-
- {_SetProbeReqExtraIE_CMD_, NULL},
- {_SetAssocReqExtraIE_CMD_, NULL},
- {_SetProbeRspExtraIE_CMD_, NULL},
- {_SetAssocRspExtraIE_CMD_, NULL},
- {_GetCurDataRate_CMD_, NULL},
- {_GetTxRetrycnt_CMD_, NULL},
- {_GetRxRetrycnt_CMD_, NULL},
- {_GetBCNOKcnt_CMD_, NULL},
- {_GetBCNERRcnt_CMD_, NULL},
- {_GetCurTxPwrLevel_CMD_, NULL},
- {_SetDIG_CMD_, NULL},
- {_SetRA_CMD_, NULL},
- {_SetPT_CMD_, NULL},
- {GEN_CMD_CODE(_ReadTSSI), &r8712_readtssi_cmdrsp_callback}
-};
-#endif
-
-#endif
diff --git a/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h
deleted file mode 100644
index 68bdec07f51e..000000000000
--- a/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_CMDCTRL_BITDEF_H__
-#define __RTL8712_CMDCTRL_BITDEF_H__
-
-/*
- * 2. Command Control Registers (Offset: 0x0040 - 0x004F)
- */
-/*--------------------------------------------------------------------------*/
-/* 8192S (CMD) command register bits (Offset 0x40, 16 bits)*/
-/*--------------------------------------------------------------------------*/
-#define _APSDOFF_STATUS BIT(15)
-#define _APSDOFF BIT(14)
-#define _BBRSTn BIT(13) /*Enable OFDM/CCK*/
-#define _BB_GLB_RSTn BIT(12) /*Enable BB*/
-#define _SCHEDULE_EN BIT(10) /*Enable MAC scheduler*/
-#define _MACRXEN BIT(9)
-#define _MACTXEN BIT(8)
-#define _DDMA_EN BIT(7) /*FW off load function enable*/
-#define _FW2HW_EN BIT(6) /*MAC every module reset */
-#define _RXDMA_EN BIT(5)
-#define _TXDMA_EN BIT(4)
-#define _HCI_RXDMA_EN BIT(3)
-#define _HCI_TXDMA_EN BIT(2)
-
-/*TXPAUSE*/
-#define _STOPHCCA BIT(6)
-#define _STOPHIGH BIT(5)
-#define _STOPMGT BIT(4)
-#define _STOPVO BIT(3)
-#define _STOPVI BIT(2)
-#define _STOPBE BIT(1)
-#define _STOPBK BIT(0)
-
-/*TCR*/
-#define _DISCW BIT(20)
-#define _ICV BIT(19)
-#define _CFEND_FMT BIT(17)
-#define _CRC BIT(16)
-#define _FWRDY BIT(7)
-#define _BASECHG BIT(6)
-#define _IMEM_RDY BIT(5)
-#define _DMEM_CODE_DONE BIT(4)
-#define _EMEM_CHK_RPT BIT(3)
-#define _EMEM_CODE_DONE BIT(2)
-#define _IMEM_CHK_RPT BIT(1)
-#define _IMEM_CODE_DONE BIT(0)
-
-#define _TXDMA_INIT_VALUE (_IMEM_CHK_RPT | _EMEM_CHK_RPT)
-
-/*RCR*/
-#define _ENMBID BIT(27)
-#define _APP_PHYST_RXFF BIT(25)
-#define _APP_PHYST_STAFF BIT(24)
-#define _CBSSID BIT(23)
-#define _APWRMGT BIT(22)
-#define _ADD3 BIT(21)
-#define _AMF BIT(20)
-#define _ACF BIT(19)
-#define _ADF BIT(18)
-#define _APP_MIC BIT(17)
-#define _APP_ICV BIT(16)
-#define _RXFTH_MSK 0x0000E000
-#define _RXFTH_SHT 13
-#define _AICV BIT(12)
-#define _RXPKTLMT_MSK 0x00000FC0
-#define _RXPKTLMT_SHT 6
-#define _ACRC32 BIT(5)
-#define _AB BIT(3)
-#define _AM BIT(2)
-#define _APM BIT(1)
-#define _AAP BIT(0)
-
-/*MSR*/
-#define _NETTYPE_MSK 0x03
-#define _NETTYPE_SHT 0
-
-/*BT*/
-#define _BTMODE_MSK 0x06
-#define _BTMODE_SHT 1
-#define _ENBT BIT(0)
-
-/*MBIDCTRL*/
-#define _ENMBID_MODE BIT(15)
-#define _BCNNO_MSK 0x7000
-#define _BCNNO_SHT 12
-#define _BCNSPACE_MSK 0x0FFF
-#define _BCNSPACE_SHT 0
-
-#endif /* __RTL8712_CMDCTRL_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h b/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h
deleted file mode 100644
index fc67771c89b7..000000000000
--- a/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_CMDCTRL_REGDEF_H__
-#define __RTL8712_CMDCTRL_REGDEF_H__
-
-#define CR (RTL8712_CMDCTRL_ + 0x0000)
-#define TXPAUSE (RTL8712_CMDCTRL_ + 0x0002)
-#define TCR (RTL8712_CMDCTRL_ + 0x0004)
-#define RCR (RTL8712_CMDCTRL_ + 0x0008)
-#define MSR (RTL8712_CMDCTRL_ + 0x000C)
-#define SYSF_CFG (RTL8712_CMDCTRL_ + 0x000D)
-#define MBIDCTRL (RTL8712_CMDCTRL_ + 0x000E)
-
-#endif /* __RTL8712_CMDCTRL_REGDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h
deleted file mode 100644
index bb3863467f0d..000000000000
--- a/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_DEBUGCTRL_BITDEF_H__
-#define __RTL8712_DEBUGCTRL_BITDEF_H__
-
-/*BIST*/
-#define _BIST_RST BIT(0)
-
-/*LMS*/
-#define _LMS_MSK 0x03
-
-/*WDG_CTRL*/
-#define _OVSEL_MSK 0x0600
-#define _OVSEL_SHT 9
-#define _WDGCLR BIT(8)
-#define _WDGEN_MSK 0x00FF
-#define _WDGEN_SHT 0
-
-/*INTM*/
-#define _TXTIMER_MSK 0xF000
-#define _TXTIMER_SHT 12
-#define _TXNUM_MSK 0x0F00
-#define _TXNUM_SHT 8
-#define _RXTIMER_MSK 0x00F0
-#define _RXTIMER_SHT 4
-#define _RXNUM_MSK 0x000F
-#define _RXNUM_SHT 0
-
-/*FDLOCKTURN0*/
-/*FDLOCKTURN1*/
-#define _TURN1 BIT(0)
-
-/*FDLOCKFLAG0*/
-/*FDLOCKFLAG1*/
-#define _LOCKFLAG1_MSK 0x03
-
-#endif /* __RTL8712_DEBUGCTRL_BITDEF_H__ */
diff --git a/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h b/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h
deleted file mode 100644
index 319220e9d53d..000000000000
--- a/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_DEBUGCTRL_REGDEF_H__
-#define __RTL8712_DEBUGCTRL_REGDEF_H__
-
-#define BIST (RTL8712_DEBUGCTRL_ + 0x00)
-#define DBS (RTL8712_DEBUGCTRL_ + 0x04)
-#define LMS (RTL8712_DEBUGCTRL_ + 0x05)
-#define CPUINST (RTL8712_DEBUGCTRL_ + 0x08)
-#define CPUCAUSE (RTL8712_DEBUGCTRL_ + 0x0C)
-#define LBUS_ERR_ADDR (RTL8712_DEBUGCTRL_ + 0x10)
-#define LBUS_ERR_CMD (RTL8712_DEBUGCTRL_ + 0x14)
-#define LBUS_ERR_DATA_L (RTL8712_DEBUGCTRL_ + 0x18)
-#define LBUS_ERR_DATA_H (RTL8712_DEBUGCTRL_ + 0x1C)
-#define LBUS_EXCEPTION_ADDR (RTL8712_DEBUGCTRL_ + 0x20)
-#define WDG_CTRL (RTL8712_DEBUGCTRL_ + 0x24)
-#define INTMTU (RTL8712_DEBUGCTRL_ + 0x28)
-#define INTM (RTL8712_DEBUGCTRL_ + 0x2A)
-#define FDLOCKTURN0 (RTL8712_DEBUGCTRL_ + 0x2C)
-#define FDLOCKTURN1 (RTL8712_DEBUGCTRL_ + 0x2D)
-#define FDLOCKFLAG0 (RTL8712_DEBUGCTRL_ + 0x2E)
-#define FDLOCKFLAG1 (RTL8712_DEBUGCTRL_ + 0x2F)
-#define TRXPKTBUF_DBG_DATA (RTL8712_DEBUGCTRL_ + 0x30)
-#define TRXPKTBUF_DBG_CTRL (RTL8712_DEBUGCTRL_ + 0x38)
-#define DPLL_MON (RTL8712_DEBUGCTRL_ + 0x3A)
-
-#endif /* __RTL8712_DEBUGCTRL_REGDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h b/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h
deleted file mode 100644
index 9048d6a65296..000000000000
--- a/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_EDCASETTING_BITDEF_H__
-#define __RTL8712_EDCASETTING_BITDEF_H__
-
-/*EDCAPARAM*/
-#define _TXOPLIMIT_MSK 0xFFFF0000
-#define _TXOPLIMIT_SHT 16
-#define _ECWIN_MSK 0x0000FF00
-#define _ECWIN_SHT 8
-#define _AIFS_MSK 0x000000FF
-#define _AIFS_SHT 0
-
-/*BCNTCFG*/
-#define _BCNECW_MSK 0xFF00
-#define _BCNECW_SHT 8
-#define _BCNIFS_MSK 0x00FF
-#define _BCNIFS_SHT 0
-
-/*CWRR*/
-#define _CWRR_MSK 0x03FF
-
-/*ACMAVG*/
-#define _AVG_TIME_UP BIT(3)
-#define _AVGPERIOD_MSK 0x03
-
-/*ACMHWCTRL*/
-#define _VOQ_ACM_STATUS BIT(6)
-#define _VIQ_ACM_STATUS BIT(5)
-#define _BEQ_ACM_STATUS BIT(4)
-#define _VOQ_ACM_EN BIT(3)
-#define _VIQ_ACM_EN BIT(2)
-#define _BEQ_ACM_EN BIT(1)
-#define _ACMHWEN BIT(0)
-
-/*VO_ADMTIME*/
-#define _VO_ACM_RUT BIT(18)
-#define _VO_ADMTIME_MSK 0x0003FFF
-
-/*VI_ADMTIME*/
-#define _VI_ACM_RUT BIT(18)
-#define _VI_ADMTIME_MSK 0x0003FFF
-
-/*BE_ADMTIME*/
-#define _BE_ACM_RUT BIT(18)
-#define _BE_ADMTIME_MSK 0x0003FFF
-
-/*Retry limit reg*/
-#define _SRL_MSK 0xFF00
-#define _SRL_SHT 8
-#define _LRL_MSK 0x00FF
-#define _LRL_SHT 0
-
-#endif /* __RTL8712_EDCASETTING_BITDEF_H__*/
diff --git a/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h b/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h
deleted file mode 100644
index 02ec9f3bba66..000000000000
--- a/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_EDCASETTING_REGDEF_H__
-#define __RTL8712_EDCASETTING_REGDEF_H__
-
-#define EDCA_VO_PARAM (RTL8712_EDCASETTING_ + 0x00)
-#define EDCA_VI_PARAM (RTL8712_EDCASETTING_ + 0x04)
-#define EDCA_BE_PARAM (RTL8712_EDCASETTING_ + 0x08)
-#define EDCA_BK_PARAM (RTL8712_EDCASETTING_ + 0x0C)
-#define BCNTCFG (RTL8712_EDCASETTING_ + 0x10)
-#define CWRR (RTL8712_EDCASETTING_ + 0x12)
-#define ACMAVG (RTL8712_EDCASETTING_ + 0x16)
-#define ACMHWCTRL (RTL8712_EDCASETTING_ + 0x17)
-#define VO_ADMTIME (RTL8712_EDCASETTING_ + 0x18)
-#define VI_ADMTIME (RTL8712_EDCASETTING_ + 0x1C)
-#define BE_ADMTIME (RTL8712_EDCASETTING_ + 0x20)
-#define RL (RTL8712_EDCASETTING_ + 0x24)
-
-#endif /* __RTL8712_EDCASETTING_REGDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_efuse.c b/drivers/staging/rtl8712/rtl8712_efuse.c
deleted file mode 100644
index a39d6c06648f..000000000000
--- a/drivers/staging/rtl8712/rtl8712_efuse.c
+++ /dev/null
@@ -1,563 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * rtl8712_efuse.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL8712_EFUSE_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "rtl8712_efuse.h"
-
-/* reserve 3 bytes for HW stop read */
-static int efuse_available_max_size = EFUSE_MAX_SIZE - 3 /*0x1FD*/;
-
-static void efuse_reg_ctrl(struct _adapter *adapter, u8 bPowerOn)
-{
- u8 tmpu8 = 0;
-
- if (bPowerOn) {
- /* -----------------e-fuse pwr & clk reg ctrl ---------------
- * Enable LDOE25 Macro Block
- */
- tmpu8 = r8712_read8(adapter, EFUSE_TEST + 3);
- tmpu8 |= 0x80;
- r8712_write8(adapter, EFUSE_TEST + 3, tmpu8);
- msleep(20); /* for some platform , need some delay time */
- /* Change Efuse Clock for write action to 40MHZ */
- r8712_write8(adapter, EFUSE_CLK_CTRL, 0x03);
- msleep(20); /* for some platform , need some delay time */
- } else {
- /* -----------------e-fuse pwr & clk reg ctrl -----------------
- * Disable LDOE25 Macro Block
- */
- tmpu8 = r8712_read8(adapter, EFUSE_TEST + 3);
- tmpu8 &= 0x7F;
- r8712_write8(adapter, EFUSE_TEST + 3, tmpu8);
- /* Change Efuse Clock for write action to 500K */
- r8712_write8(adapter, EFUSE_CLK_CTRL, 0x02);
- }
-}
-
-/*
- * Before write E-Fuse, this function must be called.
- */
-u8 r8712_efuse_reg_init(struct _adapter *adapter)
-{
- return true;
-}
-
-void r8712_efuse_reg_uninit(struct _adapter *adapter)
-{
- efuse_reg_ctrl(adapter, false);
-}
-
-static u8 efuse_one_byte_read(struct _adapter *adapter, u16 addr, u8 *data)
-{
- u8 tmpidx = 0, bResult;
-
- /* -----------------e-fuse reg ctrl --------------------------------- */
- r8712_write8(adapter, EFUSE_CTRL + 1, (u8)(addr & 0xFF)); /* address */
- r8712_write8(adapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
- (r8712_read8(adapter, EFUSE_CTRL + 2) & 0xFC));
- r8712_write8(adapter, EFUSE_CTRL + 3, 0x72); /* read cmd */
- /* wait for complete */
- while (!(0x80 & r8712_read8(adapter, EFUSE_CTRL + 3)) &&
- (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100) {
- *data = r8712_read8(adapter, EFUSE_CTRL);
- bResult = true;
- } else {
- *data = 0xff;
- bResult = false;
- }
- return bResult;
-}
-
-static u8 efuse_one_byte_write(struct _adapter *adapter, u16 addr, u8 data)
-{
- u8 tmpidx = 0, bResult;
-
- /* -----------------e-fuse reg ctrl -------------------------------- */
- r8712_write8(adapter, EFUSE_CTRL + 1, (u8)(addr & 0xFF)); /* address */
- r8712_write8(adapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
- (r8712_read8(adapter, EFUSE_CTRL + 2) & 0xFC));
- r8712_write8(adapter, EFUSE_CTRL, data); /* data */
- r8712_write8(adapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */
- /* wait for complete */
- while ((0x80 & r8712_read8(adapter, EFUSE_CTRL + 3)) &&
- (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100)
- bResult = true;
- else
- bResult = false;
- return bResult;
-}
-
-static u8 efuse_one_byte_rw(struct _adapter *adapter, u8 bRead, u16 addr,
- u8 *data)
-{
- u8 tmpidx = 0, tmpv8 = 0, bResult;
-
- /* -----------------e-fuse reg ctrl --------------------------------- */
- r8712_write8(adapter, EFUSE_CTRL + 1, (u8)(addr & 0xFF)); /* address */
- tmpv8 = ((u8)((addr >> 8) & 0x03)) |
- (r8712_read8(adapter, EFUSE_CTRL + 2) & 0xFC);
- r8712_write8(adapter, EFUSE_CTRL + 2, tmpv8);
- if (bRead) {
- r8712_write8(adapter, EFUSE_CTRL + 3, 0x72); /* read cmd */
- while (!(0x80 & r8712_read8(adapter, EFUSE_CTRL + 3)) &&
- (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100) {
- *data = r8712_read8(adapter, EFUSE_CTRL);
- bResult = true;
- } else {
- *data = 0;
- bResult = false;
- }
- } else {
- r8712_write8(adapter, EFUSE_CTRL, *data); /* data */
- r8712_write8(adapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */
- while ((0x80 & r8712_read8(adapter, EFUSE_CTRL + 3)) &&
- (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100)
- bResult = true;
- else
- bResult = false;
- }
- return bResult;
-}
-
-static u8 efuse_is_empty(struct _adapter *adapter, u8 *empty)
-{
- u8 value, ret = true;
-
- /* read one byte to check if E-Fuse is empty */
- if (efuse_one_byte_rw(adapter, true, 0, &value)) {
- if (value == 0xFF)
- *empty = true;
- else
- *empty = false;
- } else {
- ret = false;
- }
- return ret;
-}
-
-void r8712_efuse_change_max_size(struct _adapter *adapter)
-{
- u16 pre_pg_data_saddr = 0x1FB;
- u16 i;
- u16 pre_pg_data_size = 5;
- u8 pre_pg_data[5];
-
- for (i = 0; i < pre_pg_data_size; i++)
- efuse_one_byte_read(adapter, pre_pg_data_saddr + i,
- &pre_pg_data[i]);
- if ((pre_pg_data[0] == 0x03) && (pre_pg_data[1] == 0x00) &&
- (pre_pg_data[2] == 0x00) && (pre_pg_data[3] == 0x00) &&
- (pre_pg_data[4] == 0x0C))
- efuse_available_max_size -= pre_pg_data_size;
-}
-
-int r8712_efuse_get_max_size(struct _adapter *adapter)
-{
- return efuse_available_max_size;
-}
-
-static u8 calculate_word_cnts(const u8 word_en)
-{
- u8 word_cnts = 0;
- u8 word_idx;
-
- for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++)
- if (!(word_en & BIT(word_idx)))
- word_cnts++; /* 0 : write enable */
- return word_cnts;
-}
-
-static void pgpacket_copy_data(const u8 word_en, const u8 *sourdata,
- u8 *targetdata)
-{
- u8 tmpindex = 0;
- u8 word_idx, byte_idx;
-
- for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++) {
- if (!(word_en & BIT(word_idx))) {
- byte_idx = word_idx * 2;
- targetdata[byte_idx] = sourdata[tmpindex++];
- targetdata[byte_idx + 1] = sourdata[tmpindex++];
- }
- }
-}
-
-u16 r8712_efuse_get_current_size(struct _adapter *adapter)
-{
- int bContinual = true;
- u16 efuse_addr = 0;
- u8 hworden = 0;
- u8 efuse_data, word_cnts = 0;
-
- while (bContinual && efuse_one_byte_read(adapter, efuse_addr, &efuse_data) &&
- (efuse_addr < efuse_available_max_size)) {
- if (efuse_data != 0xFF) {
- hworden = efuse_data & 0x0F;
- word_cnts = calculate_word_cnts(hworden);
- /* read next header */
- efuse_addr = efuse_addr + (word_cnts * 2) + 1;
- } else {
- bContinual = false;
- }
- }
- return efuse_addr;
-}
-
-u8 r8712_efuse_pg_packet_read(struct _adapter *adapter, u8 offset, u8 *data)
-{
- u8 hoffset = 0, hworden = 0, word_cnts = 0;
- u16 efuse_addr = 0;
- u8 efuse_data;
- u8 tmpidx = 0;
- u8 tmpdata[PGPKT_DATA_SIZE];
- u8 ret = true;
-
- if (!data)
- return false;
- if (offset > 0x0f)
- return false;
- memset(data, 0xFF, sizeof(u8) * PGPKT_DATA_SIZE);
- while (efuse_addr < efuse_available_max_size) {
- if (efuse_one_byte_read(adapter, efuse_addr, &efuse_data)) {
- if (efuse_data == 0xFF)
- break;
- hoffset = (efuse_data >> 4) & 0x0F;
- hworden = efuse_data & 0x0F;
- word_cnts = calculate_word_cnts(hworden);
- if (hoffset == offset) {
- memset(tmpdata, 0xFF, PGPKT_DATA_SIZE);
- for (tmpidx = 0; tmpidx < word_cnts * 2;
- tmpidx++) {
- if (efuse_one_byte_read(adapter, efuse_addr + 1 + tmpidx,
- &efuse_data)) {
- tmpdata[tmpidx] = efuse_data;
- } else {
- ret = false;
- }
- }
- pgpacket_copy_data(hworden, tmpdata, data);
- }
- efuse_addr += 1 + (word_cnts * 2);
- } else {
- ret = false;
- break;
- }
- }
- return ret;
-}
-
-static u8 fix_header(struct _adapter *adapter, u8 header, u16 header_addr)
-{
- struct PGPKT_STRUCT pkt;
- u8 offset, word_en, value;
- u16 addr;
- int i;
- u8 ret = true;
-
- pkt.offset = GET_EFUSE_OFFSET(header);
- pkt.word_en = GET_EFUSE_WORD_EN(header);
- addr = header_addr + 1 + calculate_word_cnts(pkt.word_en) * 2;
- if (addr > efuse_available_max_size)
- return false;
- /* retrieve original data */
- addr = 0;
- while (addr < header_addr) {
- if (!efuse_one_byte_read(adapter, addr++, &value)) {
- ret = false;
- break;
- }
- offset = GET_EFUSE_OFFSET(value);
- word_en = GET_EFUSE_WORD_EN(value);
- if (pkt.offset != offset) {
- addr += calculate_word_cnts(word_en) * 2;
- continue;
- }
- for (i = 0; i < PGPKG_MAX_WORDS; i++) {
- if (!(BIT(i) & word_en))
- continue;
- if (BIT(i) & pkt.word_en) {
- if (efuse_one_byte_read(adapter,
- addr,
- &value))
- pkt.data[i * 2] = value;
- else
- return false;
- if (efuse_one_byte_read(adapter,
- addr + 1,
- &value))
- pkt.data[i * 2 + 1] = value;
- else
- return false;
- }
- addr += 2;
- }
- }
- if (addr != header_addr)
- return false;
- addr++;
- /* fill original data */
- for (i = 0; i < PGPKG_MAX_WORDS; i++) {
- if (BIT(i) & pkt.word_en) {
- efuse_one_byte_write(adapter, addr, pkt.data[i * 2]);
- efuse_one_byte_write(adapter, addr + 1,
- pkt.data[i * 2 + 1]);
- /* additional check */
- if (!efuse_one_byte_read(adapter, addr, &value)) {
- ret = false;
- } else if (pkt.data[i * 2] != value) {
- ret = false;
- if (value == 0xFF) /* write again */
- efuse_one_byte_write(adapter, addr,
- pkt.data[i * 2]);
- }
- if (!efuse_one_byte_read(adapter, addr + 1, &value)) {
- ret = false;
- } else if (pkt.data[i * 2 + 1] != value) {
- ret = false;
- if (value == 0xFF) /* write again */
- efuse_one_byte_write(adapter, addr + 1,
- pkt.data[i * 2 +
- 1]);
- }
- }
- addr += 2;
- }
- return ret;
-}
-
-u8 r8712_efuse_pg_packet_write(struct _adapter *adapter, const u8 offset,
- const u8 word_en, const u8 *data)
-{
- u8 pg_header = 0;
- u16 efuse_addr = 0, curr_size = 0;
- u8 efuse_data, target_word_cnts = 0;
- int repeat_times;
- int sub_repeat;
- u8 bResult = true;
-
- /* check if E-Fuse Clock Enable and E-Fuse Clock is 40M */
- efuse_data = r8712_read8(adapter, EFUSE_CLK_CTRL);
- if (efuse_data != 0x03)
- return false;
- pg_header = MAKE_EFUSE_HEADER(offset, word_en);
- target_word_cnts = calculate_word_cnts(word_en);
- repeat_times = 0;
- efuse_addr = 0;
- while (efuse_addr < efuse_available_max_size) {
- curr_size = r8712_efuse_get_current_size(adapter);
- if ((curr_size + 1 + target_word_cnts * 2) >
- efuse_available_max_size)
- return false; /*target_word_cnts + pg header(1 byte)*/
- efuse_addr = curr_size; /* current size is also the last addr*/
- efuse_one_byte_write(adapter, efuse_addr, pg_header); /*hdr*/
- sub_repeat = 0;
- /* check if what we read is what we write */
- while (!efuse_one_byte_read(adapter, efuse_addr,
- &efuse_data)) {
- if (++sub_repeat > _REPEAT_THRESHOLD_) {
- bResult = false; /* continue to blind write */
- break; /* continue to blind write */
- }
- }
- if ((sub_repeat > _REPEAT_THRESHOLD_) ||
- (pg_header == efuse_data)) {
- /* write header ok OR can't check header(creep) */
- u8 i;
-
- /* go to next address */
- efuse_addr++;
- for (i = 0; i < target_word_cnts * 2; i++) {
- efuse_one_byte_write(adapter,
- efuse_addr + i,
- *(data + i));
- if (!efuse_one_byte_read(adapter,
- efuse_addr + i,
- &efuse_data))
- bResult = false;
- else if (*(data + i) != efuse_data) /* fail */
- bResult = false;
- }
- break;
- }
- /* write header fail */
- bResult = false;
- if (efuse_data == 0xFF)
- return bResult; /* nothing damaged. */
- /* call rescue procedure */
- if (!fix_header(adapter, efuse_data, efuse_addr))
- return false; /* rescue fail */
-
- if (++repeat_times > _REPEAT_THRESHOLD_) /* fail */
- break;
- /* otherwise, take another risk... */
- }
- return bResult;
-}
-
-u8 r8712_efuse_access(struct _adapter *adapter, u8 bRead, u16 start_addr,
- u16 cnts, u8 *data)
-{
- int i;
- u8 res = true;
-
- if (start_addr > EFUSE_MAX_SIZE)
- return false;
- if (!bRead && ((start_addr + cnts) >
- efuse_available_max_size))
- return false;
- if (!bRead && !r8712_efuse_reg_init(adapter))
- return false;
- /* -----------------e-fuse one byte read / write ---------------------*/
- for (i = 0; i < cnts; i++) {
- if ((start_addr + i) > EFUSE_MAX_SIZE) {
- res = false;
- break;
- }
- res = efuse_one_byte_rw(adapter, bRead, start_addr + i,
- data + i);
- if (!bRead && !res)
- break;
- }
- if (!bRead)
- r8712_efuse_reg_uninit(adapter);
- return res;
-}
-
-u8 r8712_efuse_map_read(struct _adapter *adapter, u16 addr, u16 cnts, u8 *data)
-{
- u8 offset, ret = true;
- u8 pktdata[PGPKT_DATA_SIZE];
- int i, idx;
-
- if ((addr + cnts) > EFUSE_MAP_MAX_SIZE)
- return false;
- if (efuse_is_empty(adapter, &offset) && offset) {
- for (i = 0; i < cnts; i++)
- data[i] = 0xFF;
- return ret;
- }
- offset = (addr >> 3) & 0xF;
- ret = r8712_efuse_pg_packet_read(adapter, offset, pktdata);
- i = addr & 0x7; /* pktdata index */
- idx = 0; /* data index */
-
- do {
- for (; i < PGPKT_DATA_SIZE; i++) {
- data[idx++] = pktdata[i];
- if (idx == cnts)
- return ret;
- }
- offset++;
- if (!r8712_efuse_pg_packet_read(adapter, offset, pktdata))
- ret = false;
- i = 0;
- } while (1);
- return ret;
-}
-
-u8 r8712_efuse_map_write(struct _adapter *adapter, u16 addr, u16 cnts,
- u8 *data)
-{
- u8 offset, word_en, empty;
- u8 pktdata[PGPKT_DATA_SIZE], newdata[PGPKT_DATA_SIZE];
- int i, j, idx;
-
- if ((addr + cnts) > EFUSE_MAP_MAX_SIZE)
- return false;
- /* check if E-Fuse Clock Enable and E-Fuse Clock is 40M */
- empty = r8712_read8(adapter, EFUSE_CLK_CTRL);
- if (empty != 0x03)
- return false;
- if (efuse_is_empty(adapter, &empty)) {
- if (empty)
- memset(pktdata, 0xFF, PGPKT_DATA_SIZE);
- } else {
- return false;
- }
- offset = (addr >> 3) & 0xF;
- if (!empty)
- if (!r8712_efuse_pg_packet_read(adapter, offset, pktdata))
- return false;
- word_en = 0xF;
- memset(newdata, 0xFF, PGPKT_DATA_SIZE);
- i = addr & 0x7; /* pktdata index */
- j = 0; /* newdata index */
- idx = 0; /* data index */
-
- if (i & 0x1) {
- /* odd start */
- if (data[idx] != pktdata[i]) {
- word_en &= ~BIT(i >> 1);
- newdata[j++] = pktdata[i - 1];
- newdata[j++] = data[idx];
- }
- i++;
- idx++;
- }
- do {
- for (; i < PGPKT_DATA_SIZE; i += 2) {
- if ((cnts - idx) == 1) {
- if (data[idx] != pktdata[i]) {
- word_en &= ~BIT(i >> 1);
- newdata[j++] = data[idx];
- newdata[j++] = pktdata[1 + 1];
- }
- idx++;
- break;
- }
-
- if ((data[idx] != pktdata[i]) || (data[idx + 1] !=
- pktdata[i + 1])) {
- word_en &= ~BIT(i >> 1);
- newdata[j++] = data[idx];
- newdata[j++] = data[idx + 1];
- }
- idx += 2;
-
- if (idx == cnts)
- break;
- }
-
- if (word_en != 0xF)
- if (!r8712_efuse_pg_packet_write(adapter, offset,
- word_en, newdata))
- return false;
- if (idx == cnts)
- break;
- offset++;
- if (!empty)
- if (!r8712_efuse_pg_packet_read(adapter, offset,
- pktdata))
- return false;
- i = 0;
- j = 0;
- word_en = 0xF;
- memset(newdata, 0xFF, PGPKT_DATA_SIZE);
- } while (1);
-
- return true;
-}
diff --git a/drivers/staging/rtl8712/rtl8712_efuse.h b/drivers/staging/rtl8712/rtl8712_efuse.h
deleted file mode 100644
index 7a49740212eb..000000000000
--- a/drivers/staging/rtl8712/rtl8712_efuse.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __RTL8712_EFUSE_H__
-#define __RTL8712_EFUSE_H__
-
-#include "osdep_service.h"
-
-#define _REPEAT_THRESHOLD_ 3
-
-#define EFUSE_MAX_SIZE 512
-#define EFUSE_MAP_MAX_SIZE 128
-
-#define PGPKG_MAX_WORDS 4
-#define PGPKT_DATA_SIZE 8 /* PGPKG_MAX_WORDS*2; BYTES sizeof(u8)*8*/
-#define MAX_PGPKT_SIZE 9 /* 1 + PGPKT_DATA_SIZE; header + 2 * 4 words (BYTES)*/
-
-#define GET_EFUSE_OFFSET(header) ((header & 0xF0) >> 4)
-#define GET_EFUSE_WORD_EN(header) (header & 0x0F)
-#define MAKE_EFUSE_HEADER(offset, word_en) ((((offset) & 0x0F) << 4) | \
- ((word_en) & 0x0F))
-/*--------------------------------------------------------------------------*/
-struct PGPKT_STRUCT {
- u8 offset;
- u8 word_en;
- u8 data[PGPKT_DATA_SIZE];
-};
-
-/*--------------------------------------------------------------------------*/
-u8 r8712_efuse_reg_init(struct _adapter *padapter);
-void r8712_efuse_reg_uninit(struct _adapter *padapter);
-u16 r8712_efuse_get_current_size(struct _adapter *padapter);
-int r8712_efuse_get_max_size(struct _adapter *padapter);
-void r8712_efuse_change_max_size(struct _adapter *padapter);
-u8 r8712_efuse_pg_packet_read(struct _adapter *padapter,
- u8 offset, u8 *data);
-u8 r8712_efuse_pg_packet_write(struct _adapter *padapter,
- const u8 offset, const u8 word_en,
- const u8 *data);
-u8 r8712_efuse_access(struct _adapter *padapter, u8 bRead,
- u16 start_addr, u16 cnts, u8 *data);
-u8 r8712_efuse_map_read(struct _adapter *padapter, u16 addr,
- u16 cnts, u8 *data);
-u8 r8712_efuse_map_write(struct _adapter *padapter, u16 addr,
- u16 cnts, u8 *data);
-#endif
diff --git a/drivers/staging/rtl8712/rtl8712_event.h b/drivers/staging/rtl8712/rtl8712_event.h
deleted file mode 100644
index 0d3e5feadcc0..000000000000
--- a/drivers/staging/rtl8712/rtl8712_event.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL8712_EVENT_H_
-#define _RTL8712_EVENT_H_
-
-void r8712_event_handle(struct _adapter *padapter, __le32 *peventbuf);
-void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf);
-
-enum rtl8712_c2h_event {
- GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/
- GEN_EVT_CODE(_Read_BBREG),
- GEN_EVT_CODE(_Read_RFREG),
- GEN_EVT_CODE(_Read_EEPROM),
- GEN_EVT_CODE(_Read_EFUSE),
- GEN_EVT_CODE(_Read_CAM), /*5*/
- GEN_EVT_CODE(_Get_BasicRate),
- GEN_EVT_CODE(_Get_DataRate),
- GEN_EVT_CODE(_Survey), /*8*/
- GEN_EVT_CODE(_SurveyDone), /*9*/
-
- GEN_EVT_CODE(_JoinBss), /*10*/
- GEN_EVT_CODE(_AddSTA),
- GEN_EVT_CODE(_DelSTA),
- GEN_EVT_CODE(_AtimDone),
- GEN_EVT_CODE(_TX_Report),
- GEN_EVT_CODE(_CCX_Report), /*15*/
- GEN_EVT_CODE(_DTM_Report),
- GEN_EVT_CODE(_TX_Rate_Statistics),
- GEN_EVT_CODE(_C2HLBK),
- GEN_EVT_CODE(_FWDBG),
- GEN_EVT_CODE(_C2HFEEDBACK), /*20*/
- GEN_EVT_CODE(_ADDBA),
- GEN_EVT_CODE(_C2HBCN),
- GEN_EVT_CODE(_ReportPwrState), /*filen: only for PCIE, USB*/
- GEN_EVT_CODE(_WPS_PBC), /*24*/
- GEN_EVT_CODE(_ADDBAReq_Report), /*25*/
- MAX_C2HEVT
-};
-
-#ifdef _RTL8712_CMD_C_
-
-static struct fwevent wlanevents[] = {
- {0, NULL}, /*0*/
- {0, NULL},
- {0, NULL},
- {0, NULL},
- {0, NULL},
- {0, NULL},
- {0, NULL},
- {0, NULL},
- {0, &r8712_survey_event_callback}, /*8*/
- {sizeof(struct surveydone_event),
- &r8712_surveydone_event_callback}, /*9*/
-
- {0, &r8712_joinbss_event_callback}, /*10*/
- {sizeof(struct stassoc_event), &r8712_stassoc_event_callback},
- {sizeof(struct stadel_event), &r8712_stadel_event_callback},
- {0, &r8712_atimdone_event_callback},
- {0, NULL},
- {0, NULL}, /*15*/
- {0, NULL},
- {0, NULL},
- {0, NULL},
- {0, NULL}, /*fwdbg_event_callback},*/
- {0, NULL}, /*20*/
- {0, NULL},
- {0, NULL},
- {0, &r8712_cpwm_event_callback},
- {0, &r8712_wpspbc_event_callback},
- {0, &r8712_got_addbareq_event_callback},
-};
-
-#endif/*_RTL8712_CMD_C_*/
-
-#endif
diff --git a/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h
deleted file mode 100644
index f09645fa1886..000000000000
--- a/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_FIFOCTRL_BITDEF_H__
-#define __RTL8712_FIFOCTRL_BITDEF_H__
-
-/*PBP*/
-#define _PSTX_MSK 0xF0
-#define _PSTX_SHT 4
-#define _PSRX_MSK 0x0F
-#define _PSRX_SHT 0
-
-/*TXFF_STATUS*/
-#define _TXSTATUS_OVF BIT(15)
-
-/*RXFF_STATUS*/
-#define _STATUSFF1_OVF BIT(7)
-#define _STATUSFF1_EMPTY BIT(6)
-#define _STATUSFF0_OVF BIT(5)
-#define _STATUSFF0_EMPTY BIT(4)
-#define _RXFF1_OVF BIT(3)
-#define _RXFF1_EMPTY BIT(2)
-#define _RXFF0_OVF BIT(1)
-#define _RXFF0_EMPTY BIT(0)
-
-/*TXFF_EMPTY_TH*/
-#define _BKQ_EMPTY_TH_MSK 0x0F0000
-#define _BKQ_EMPTY_TH_SHT 16
-#define _BEQ_EMPTY_TH_MSK 0x00F000
-#define _BEQ_EMPTY_TH_SHT 12
-#define _VIQ_EMPTY_TH_MSK 0x000F00
-#define _VIQ_EMPTY_TH_SHT 8
-#define _VOQ_EMPTY_TH_MSK 0x0000F0
-#define _VOQ_EMPTY_TH_SHT 4
-#define _BMCQ_EMPTY_TH_MSK 0x00000F
-#define _BMCQ_EMPTY_TH_SHT 0
-
-/*SDIO_RX_BLKSZ*/
-#define _SDIO_RX_BLKSZ_MSK 0x07
-
-/*RXDMA_CTRL*/
-#define _C2HFF_POLL BIT(4)
-#define _RXPKT_POLL BIT(0)
-
-/*RXPKT_NUM*/
-#define _RXCMD_NUM_MSK 0xFF00
-#define _RXCMD_NUM_SHT 8
-#define _RXFF0_NUM_MSK 0x00FF
-#define _RXFF0_NUM_SHT 0
-
-/*FIFOPAGE2*/
-#define _PUB_AVAL_PG_MSK 0xFFFF0000
-#define _PUB_AVAL_PG_SHT 16
-#define _BCN_AVAL_PG_MSK 0x0000FFFF
-#define _BCN_AVAL_PG_SHT 0
-
-/*RX0PKTNUM*/
-#define _RXFF0_DEC_POLL BIT(15)
-#define _RXFF0_PKT_DEC_NUM_MSK 0x3F00
-#define _RXFF0_PKT_DEC_NUM_SHT 8
-#define _RXFF0_PKTNUM_RPT_MSK 0x00FF
-#define _RXFF0_PKTNUM_RPT_SHT 0
-
-/*RX1PKTNUM*/
-#define _RXFF1_DEC_POLL BIT(15)
-#define _RXFF1_PKT_DEC_NUM_MSK 0x3F00
-#define _RXFF1_PKT_DEC_NUM_SHT 8
-#define _RXFF1_PKTNUM_RPT_MSK 0x00FF
-#define _RXFF1_PKTNUM_RPT_SHT 0
-
-/*RXFLTMAP0*/
-#define _MGTFLT13EN BIT(13)
-#define _MGTFLT12EN BIT(12)
-#define _MGTFLT11EN BIT(11)
-#define _MGTFLT10EN BIT(10)
-#define _MGTFLT9EN BIT(9)
-#define _MGTFLT8EN BIT(8)
-#define _MGTFLT5EN BIT(5)
-#define _MGTFLT4EN BIT(4)
-#define _MGTFLT3EN BIT(3)
-#define _MGTFLT2EN BIT(2)
-#define _MGTFLT1EN BIT(1)
-#define _MGTFLT0EN BIT(0)
-
-/*RXFLTMAP1*/
-#define _CTRLFLT15EN BIT(15)
-#define _CTRLFLT14EN BIT(14)
-#define _CTRLFLT13EN BIT(13)
-#define _CTRLFLT12EN BIT(12)
-#define _CTRLFLT11EN BIT(11)
-#define _CTRLFLT10EN BIT(10)
-#define _CTRLFLT9EN BIT(9)
-#define _CTRLFLT8EN BIT(8)
-#define _CTRLFLT7EN BIT(7)
-#define _CTRLFLT6EN BIT(6)
-
-/*RXFLTMAP2*/
-#define _DATAFLT15EN BIT(15)
-#define _DATAFLT14EN BIT(14)
-#define _DATAFLT13EN BIT(13)
-#define _DATAFLT12EN BIT(12)
-#define _DATAFLT11EN BIT(11)
-#define _DATAFLT10EN BIT(10)
-#define _DATAFLT9EN BIT(9)
-#define _DATAFLT8EN BIT(8)
-#define _DATAFLT7EN BIT(7)
-#define _DATAFLT6EN BIT(6)
-#define _DATAFLT5EN BIT(5)
-#define _DATAFLT4EN BIT(4)
-#define _DATAFLT3EN BIT(3)
-#define _DATAFLT2EN BIT(2)
-#define _DATAFLT1EN BIT(1)
-#define _DATAFLT0EN BIT(0)
-
-/*RXFLTMAP3*/
-#define _MESHAFLT1EN BIT(1)
-#define _MESHAFLT0EN BIT(0)
-
-/*TXPKT_NUM_CTRL*/
-#define _TXPKTNUM_DEC BIT(8)
-#define _TXPKTNUM_MSK 0x00FF
-#define _TXPKTNUM_SHT 0
-
-/*TXFF_PG_NUM*/
-#define _TXFF_PG_NUM_MSK 0x0FFF
-
-#endif /* __RTL8712_FIFOCTRL_BITDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h b/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h
deleted file mode 100644
index 189fdeb16d7d..000000000000
--- a/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_FIFOCTRL_REGDEF_H__
-#define __RTL8712_FIFOCTRL_REGDEF_H__
-
-#define RQPN (RTL8712_FIFOCTRL_ + 0x00)
-#define RXFF_BNDY (RTL8712_FIFOCTRL_ + 0x0C)
-#define RXRPT_BNDY (RTL8712_FIFOCTRL_ + 0x10)
-#define TXPKTBUF_PGBNDY (RTL8712_FIFOCTRL_ + 0x14)
-#define PBP (RTL8712_FIFOCTRL_ + 0x15)
-#define RX_DRVINFO_SZ (RTL8712_FIFOCTRL_ + 0x16)
-#define TXFF_STATUS (RTL8712_FIFOCTRL_ + 0x17)
-#define RXFF_STATUS (RTL8712_FIFOCTRL_ + 0x18)
-#define TXFF_EMPTY_TH (RTL8712_FIFOCTRL_ + 0x19)
-#define SDIO_RX_BLKSZ (RTL8712_FIFOCTRL_ + 0x1C)
-#define RXDMA_RXCTRL (RTL8712_FIFOCTRL_ + 0x1D)
-#define RXPKT_NUM (RTL8712_FIFOCTRL_ + 0x1E)
-#define RXPKT_NUM_C2H (RTL8712_FIFOCTRL_ + 0x1F)
-#define C2HCMD_UDT_SIZE (RTL8712_FIFOCTRL_ + 0x20)
-#define C2HCMD_UDT_ADDR (RTL8712_FIFOCTRL_ + 0x22)
-#define FIFOPAGE2 (RTL8712_FIFOCTRL_ + 0x24)
-#define FIFOPAGE1 (RTL8712_FIFOCTRL_ + 0x28)
-#define FW_RSVD_PG_CTRL (RTL8712_FIFOCTRL_ + 0x30)
-#define TXRPTFF_RDPTR (RTL8712_FIFOCTRL_ + 0x40)
-#define TXRPTFF_WTPTR (RTL8712_FIFOCTRL_ + 0x44)
-#define C2HFF_RDPTR (RTL8712_FIFOCTRL_ + 0x48)
-#define C2HFF_WTPTR (RTL8712_FIFOCTRL_ + 0x4C)
-#define RXFF0_RDPTR (RTL8712_FIFOCTRL_ + 0x50)
-#define RXFF0_WTPTR (RTL8712_FIFOCTRL_ + 0x54)
-#define RXFF1_RDPTR (RTL8712_FIFOCTRL_ + 0x58)
-#define RXFF1_WTPTR (RTL8712_FIFOCTRL_ + 0x5C)
-#define RXRPT0FF_RDPTR (RTL8712_FIFOCTRL_ + 0x60)
-#define RXRPT0FF_WTPTR (RTL8712_FIFOCTRL_ + 0x64)
-#define RXRPT1FF_RDPTR (RTL8712_FIFOCTRL_ + 0x68)
-#define RXRPT1FF_WTPTR (RTL8712_FIFOCTRL_ + 0x6C)
-#define RX0PKTNUM (RTL8712_FIFOCTRL_ + 0x72)
-#define RX1PKTNUM (RTL8712_FIFOCTRL_ + 0x74)
-#define RXFLTMAP0 (RTL8712_FIFOCTRL_ + 0x76)
-#define RXFLTMAP1 (RTL8712_FIFOCTRL_ + 0x78)
-#define RXFLTMAP2 (RTL8712_FIFOCTRL_ + 0x7A)
-#define RXFLTMAP3 (RTL8712_FIFOCTRL_ + 0x7c)
-#define TBDA (RTL8712_FIFOCTRL_ + 0x84)
-#define THPDA (RTL8712_FIFOCTRL_ + 0x88)
-#define TCDA (RTL8712_FIFOCTRL_ + 0x8C)
-#define TMDA (RTL8712_FIFOCTRL_ + 0x90)
-#define HDA (RTL8712_FIFOCTRL_ + 0x94)
-#define TVODA (RTL8712_FIFOCTRL_ + 0x98)
-#define TVIDA (RTL8712_FIFOCTRL_ + 0x9C)
-#define TBEDA (RTL8712_FIFOCTRL_ + 0xA0)
-#define TBKDA (RTL8712_FIFOCTRL_ + 0xA4)
-#define RCDA (RTL8712_FIFOCTRL_ + 0xA8)
-#define RDSA (RTL8712_FIFOCTRL_ + 0xAC)
-#define TXPKT_NUM_CTRL (RTL8712_FIFOCTRL_ + 0xB0)
-#define TXQ_PGADD (RTL8712_FIFOCTRL_ + 0xB3)
-#define TXFF_PG_NUM (RTL8712_FIFOCTRL_ + 0xB4)
-
-#endif /* __RTL8712_FIFOCTRL_REGDEF_H__ */
diff --git a/drivers/staging/rtl8712/rtl8712_gp_bitdef.h b/drivers/staging/rtl8712/rtl8712_gp_bitdef.h
deleted file mode 100644
index ee651fb3fde3..000000000000
--- a/drivers/staging/rtl8712/rtl8712_gp_bitdef.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_GP_BITDEF_H__
-#define __RTL8712_GP_BITDEF_H__
-
-/*GPIO_CTRL*/
-#define _GPIO_MOD_MSK 0xFF000000
-#define _GPIO_MOD_SHT 24
-#define _GPIO_IO_SEL_MSK 0x00FF0000
-#define _GPIO_IO_SEL_SHT 16
-#define _GPIO_OUT_MSK 0x0000FF00
-#define _GPIO_OUT_SHT 8
-#define _GPIO_IN_MSK 0x000000FF
-#define _GPIO_IN_SHT 0
-
-/*SYS_PINMUX_CFG*/
-#define _GPIOSEL_MSK 0x0003
-#define _GPIOSEL_SHT 0
-
-/*LED_CFG*/
-#define _LED1SV BIT(7)
-#define _LED1CM_MSK 0x0070
-#define _LED1CM_SHT 4
-#define _LED0SV BIT(3)
-#define _LED0CM_MSK 0x0007
-#define _LED0CM_SHT 0
-
-/*PHY_REG*/
-#define _HST_RDRDY_SHT 0
-#define _HST_RDRDY_MSK 0xFF
-#define _HST_RDRDY BIT(_HST_RDRDY_SHT)
-#define _CPU_WTBUSY_SHT 1
-#define _CPU_WTBUSY_MSK 0xFF
-#define _CPU_WTBUSY BIT(_CPU_WTBUSY_SHT)
-
-/* 11. General Purpose Registers (Offset: 0x02E0 - 0x02FF)*/
-
-/* 8192S GPIO Config Setting (offset 0x2F1, 1 byte)*/
-
-/*----------------------------------------------------------------------------*/
-
-#define GPIOMUX_EN BIT(3) /* When this bit is set to "1",
- * GPIO PINs will switch to MAC
- * GPIO Function
- */
-#define GPIOSEL_GPIO 0 /* UART or JTAG or pure GPIO*/
-#define GPIOSEL_PHYDBG 1 /* PHYDBG*/
-#define GPIOSEL_BT 2 /* BT_coex*/
-#define GPIOSEL_WLANDBG 3 /* WLANDBG*/
-#define GPIOSEL_GPIO_MASK (~(BIT(0) | BIT(1)))
-/* HW Radio OFF switch (GPIO BIT) */
-#define HAL_8192S_HW_GPIO_OFF_BIT BIT(3)
-#define HAL_8192S_HW_GPIO_OFF_MASK 0xF7
-#define HAL_8192S_HW_GPIO_WPS_BIT BIT(4)
-
-#endif /*__RTL8712_GP_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_gp_regdef.h b/drivers/staging/rtl8712/rtl8712_gp_regdef.h
deleted file mode 100644
index 892a7fb13923..000000000000
--- a/drivers/staging/rtl8712/rtl8712_gp_regdef.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_GP_REGDEF_H__
-#define __RTL8712_GP_REGDEF_H__
-
-#define PSTIMER (RTL8712_GP_ + 0x00)
-#define TIMER1 (RTL8712_GP_ + 0x04)
-#define TIMER2 (RTL8712_GP_ + 0x08)
-#define GPIO_CTRL (RTL8712_GP_ + 0x0C)
-#define GPIO_IO_SEL (RTL8712_GP_ + 0x0E)
-#define GPIO_INTCTRL (RTL8712_GP_ + 0x10)
-#define MAC_PINMUX_CTRL (RTL8712_GP_ + 0x11)
-#define LEDCFG (RTL8712_GP_ + 0x12)
-#define PHY_REG_RPT (RTL8712_GP_ + 0x13)
-#define PHY_REG_DATA (RTL8712_GP_ + 0x14)
-
-#endif /*__RTL8712_GP_REGDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_hal.h b/drivers/staging/rtl8712/rtl8712_hal.h
deleted file mode 100644
index 66cc4645e2d1..000000000000
--- a/drivers/staging/rtl8712/rtl8712_hal.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_HAL_H__
-#define __RTL8712_HAL_H__
-
-enum _HW_VERSION {
- RTL8712_FPGA,
- RTL8712_1stCUT, /*A Cut (RTL8712_ASIC)*/
- RTL8712_2ndCUT, /*B Cut*/
- RTL8712_3rdCUT, /*C Cut*/
-};
-
-enum _LOOPBACK_TYPE {
- RTL8712_AIR_TRX = 0,
- RTL8712_MAC_LBK,
- RTL8712_BB_LBK,
- RTL8712_MAC_FW_LBK = 4,
- RTL8712_BB_FW_LBK = 8,
-};
-
-enum RTL871X_HCI_TYPE {
- RTL8712_SDIO,
- RTL8712_USB,
-};
-
-enum RTL8712_RF_CONFIG {
- RTL8712_RF_1T1R,
- RTL8712_RF_1T2R,
- RTL8712_RF_2T2R
-};
-
-enum _RTL8712_HCI_TYPE_ {
- RTL8712_HCI_TYPE_PCIE = 0x01,
- RTL8712_HCI_TYPE_AP_PCIE = 0x81,
- RTL8712_HCI_TYPE_USB = 0x02,
- RTL8712_HCI_TYPE_92USB = 0x02,
- RTL8712_HCI_TYPE_AP_USB = 0x82,
- RTL8712_HCI_TYPE_72USB = 0x12,
- RTL8712_HCI_TYPE_SDIO = 0x04,
- RTL8712_HCI_TYPE_72SDIO = 0x14
-};
-
-struct fw_priv { /*8-bytes alignment required*/
- /*--- long word 0 ----*/
- unsigned char signature_0; /*0x12: CE product, 0x92: IT product*/
- unsigned char signature_1; /*0x87: CE product, 0x81: IT product*/
- unsigned char hci_sel; /*0x81: PCI-AP, 01:PCIe, 02: 92S-U, 0x82: USB-AP,
- * 0x12: 72S-U, 03:SDIO
- */
- unsigned char chip_version; /*the same value as register value*/
- unsigned char customer_ID_0; /*customer ID low byte*/
- unsigned char customer_ID_1; /*customer ID high byte*/
- unsigned char rf_config; /*0x11: 1T1R, 0x12: 1T2R, 0x92: 1T2R turbo,
- * 0x22: 2T2R
- */
- unsigned char usb_ep_num; /* 4: 4EP, 6: 6EP, 11: 11EP*/
- /*--- long word 1 ----*/
- unsigned char regulatory_class_0; /*regulatory class bit map 0*/
- unsigned char regulatory_class_1; /*regulatory class bit map 1*/
- unsigned char regulatory_class_2; /*regulatory class bit map 2*/
- unsigned char regulatory_class_3; /*regulatory class bit map 3*/
- unsigned char rfintfs; /* 0:SWSI, 1:HWSI, 2:HWPI*/
- unsigned char def_nettype;
- unsigned char turbo_mode;
- unsigned char low_power_mode;/* 0: normal mode, 1: low power mode*/
- /*--- long word 2 ----*/
- unsigned char lbk_mode; /*0x00: normal, 0x03: MACLBK, 0x01: PHYLBK*/
- unsigned char mp_mode; /* 1: for MP use, 0: for normal driver */
- unsigned char vcs_type; /* 0:off 1:on 2:auto */
- unsigned char vcs_mode; /* 1:RTS/CTS 2:CTS to self */
- unsigned char rsvd022;
- unsigned char rsvd023;
- unsigned char rsvd024;
- unsigned char rsvd025;
- /*--- long word 3 ----*/
- unsigned char qos_en; /*1: QoS enable*/
- unsigned char bw_40MHz_en; /*1: 40MHz BW enable*/
- unsigned char AMSDU2AMPDU_en; /*1: 4181 convert AMSDU to AMPDU,
- * 0: disable
- */
- unsigned char AMPDU_en; /*1: 11n AMPDU enable*/
- unsigned char rate_control_offload; /*1: FW offloads,0: driver handles*/
- unsigned char aggregation_offload; /*1: FW offloads,0: driver handles*/
- unsigned char rsvd030;
- unsigned char rsvd031;
- /*--- long word 4 ----*/
- unsigned char beacon_offload; /* 1. FW offloads, 0: driver handles*/
- unsigned char MLME_offload; /* 2. FW offloads, 0: driver handles*/
- unsigned char hwpc_offload; /* 3. FW offloads, 0: driver handles*/
- unsigned char tcp_checksum_offload; /*4. FW offloads,0: driver handles*/
- unsigned char tcp_offload; /* 5. FW offloads, 0: driver handles*/
- unsigned char ps_control_offload; /* 6. FW offloads, 0: driver handles*/
- unsigned char WWLAN_offload; /* 7. FW offloads, 0: driver handles*/
- unsigned char rsvd040;
- /*--- long word 5 ----*/
- unsigned char tcp_tx_frame_len_L; /*tcp tx packet length low byte*/
- unsigned char tcp_tx_frame_len_H; /*tcp tx packet length high byte*/
- unsigned char tcp_rx_frame_len_L; /*tcp rx packet length low byte*/
- unsigned char tcp_rx_frame_len_H; /*tcp rx packet length high byte*/
- unsigned char rsvd050;
- unsigned char rsvd051;
- unsigned char rsvd052;
- unsigned char rsvd053;
-};
-
-struct fw_hdr {/*8-byte alignment required*/
- unsigned short signature;
- unsigned short version; /* 0x8000 ~ 0x8FFF for FPGA version,
- * 0x0000 ~ 0x7FFF for ASIC version,
- */
- unsigned int dmem_size; /*define the size of boot loader*/
- unsigned int img_IMEM_size; /*define the size of FW in IMEM*/
- unsigned int img_SRAM_size; /*define the size of FW in SRAM*/
- unsigned int fw_priv_sz; /*define the size of DMEM variable*/
- unsigned short efuse_addr;
- unsigned short h2ccnd_resp_addr;
- unsigned int SVNRevision;
- unsigned int release_time; /*Mon:Day:Hr:Min*/
- struct fw_priv fwpriv;
-};
-
-struct hal_priv {
- /*Endpoint handles*/
- struct net_device *pipehdls_r8712[10];
- u8 (*hal_bus_init)(struct _adapter *adapter);
-};
-
-uint rtl8712_hal_init(struct _adapter *padapter);
-int rtl871x_load_fw(struct _adapter *padapter);
-
-#endif
diff --git a/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h b/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h
deleted file mode 100644
index e9732a1bcd7e..000000000000
--- a/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_INTERRUPT_BITDEF_H__
-#define __RTL8712_INTERRUPT_BITDEF_H__
-
-/*HIMR*/
-/*HISR*/
-#define _CPUERR BIT(29)
-#define _ATIMEND BIT(28)
-#define _TXBCNOK BIT(27)
-#define _TXBCNERR BIT(26)
-#define _BCNDMAINT4 BIT(25)
-#define _BCNDMAINT3 BIT(24)
-#define _BCNDMAINT2 BIT(23)
-#define _BCNDMAINT1 BIT(22)
-#define _BCNDOK4 BIT(21)
-#define _BCNDOK3 BIT(20)
-#define _BCNDOK2 BIT(19)
-#define _BCNDOK1 BIT(18)
-#define _TIMEOUT2 BIT(17)
-#define _TIMEOUT1 BIT(16)
-#define _TXFOVW BIT(15)
-#define _PSTIMEOUT BIT(14)
-#define _BCNDMAINT0 BIT(13)
-#define _FOVW BIT(12)
-#define _RDU BIT(11)
-#define _RXCMDOK BIT(10)
-#define _BCNDOK0 BIT(9)
-#define _HIGHDOK BIT(8)
-#define _COMDOK BIT(7)
-#define _MGTDOK BIT(6)
-#define _HCCADOK BIT(5)
-#define _BKDOK BIT(4)
-#define _BEDOK BIT(3)
-#define _VIDOK BIT(2)
-#define _VODOK BIT(1)
-#define _RXOK BIT(0)
-
-#endif /*__RTL8712_INTERRUPT_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_io.c b/drivers/staging/rtl8712/rtl8712_io.c
deleted file mode 100644
index 384cbdb05e19..000000000000
--- a/drivers/staging/rtl8712/rtl8712_io.c
+++ /dev/null
@@ -1,99 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl8712_io.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL8712_IO_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "rtl871x_io.h"
-#include "osdep_intf.h"
-#include "usb_ops.h"
-
-u8 r8712_read8(struct _adapter *adapter, u32 addr)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- return hdl->io_ops._read8(hdl, addr);
-}
-
-u16 r8712_read16(struct _adapter *adapter, u32 addr)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- return hdl->io_ops._read16(hdl, addr);
-}
-
-u32 r8712_read32(struct _adapter *adapter, u32 addr)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- return hdl->io_ops._read32(hdl, addr);
-}
-
-void r8712_write8(struct _adapter *adapter, u32 addr, u8 val)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- hdl->io_ops._write8(hdl, addr, val);
-}
-
-void r8712_write16(struct _adapter *adapter, u32 addr, u16 val)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- hdl->io_ops._write16(hdl, addr, val);
-}
-
-void r8712_write32(struct _adapter *adapter, u32 addr, u32 val)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- hdl->io_ops._write32(hdl, addr, val);
-}
-
-void r8712_read_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- if (adapter->driver_stopped || adapter->surprise_removed)
- return;
-
- hdl->io_ops._read_mem(hdl, addr, cnt, pmem);
-}
-
-void r8712_write_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- hdl->io_ops._write_mem(hdl, addr, cnt, pmem);
-}
-
-void r8712_read_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- if (adapter->driver_stopped || adapter->surprise_removed)
- return;
-
- hdl->io_ops._read_port(hdl, addr, cnt, pmem);
-}
-
-void r8712_write_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- hdl->io_ops._write_port(hdl, addr, cnt, pmem);
-}
diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c
deleted file mode 100644
index 6d9be5dec4e7..000000000000
--- a/drivers/staging/rtl8712/rtl8712_led.c
+++ /dev/null
@@ -1,1830 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl8712_led.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#include "drv_types.h"
-
-/*===========================================================================
- * Constant.
- *===========================================================================
-
- *
- * Default LED behavior.
- */
-#define LED_BLINK_NORMAL_INTERVAL 100
-#define LED_BLINK_SLOWLY_INTERVAL 200
-#define LED_BLINK_LONG_INTERVAL 400
-
-#define LED_BLINK_NO_LINK_INTERVAL_ALPHA 1000
-#define LED_BLINK_LINK_INTERVAL_ALPHA 500
-#define LED_BLINK_SCAN_INTERVAL_ALPHA 180
-#define LED_BLINK_FASTER_INTERVAL_ALPHA 50
-#define LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA 5000
-
-/*===========================================================================
- * LED object.
- *===========================================================================
- */
-enum _LED_STATE_871x {
- LED_UNKNOWN = 0,
- LED_STATE_ON = 1,
- LED_STATE_OFF = 2,
- LED_BLINK_NORMAL = 3,
- LED_BLINK_SLOWLY = 4,
- LED_POWER_ON_BLINK = 5,
- LED_SCAN_BLINK = 6, /* LED is blinking during scanning period,
- * the # of times to blink is depend on time
- * for scanning.
- */
- LED_NO_LINK_BLINK = 7, /* LED is blinking during no link state. */
- LED_BLINK_StartToBlink = 8,/* Customized for Sercomm Printer
- * Server case
- */
- LED_BLINK_WPS = 9, /* LED is blinkg during WPS communication */
- LED_TXRX_BLINK = 10,
- LED_BLINK_WPS_STOP = 11, /*for ALPHA */
- LED_BLINK_WPS_STOP_OVERLAP = 12, /*for BELKIN */
-};
-
-/*===========================================================================
- * Prototype of protected function.
- *===========================================================================
- */
-static void BlinkTimerCallback(struct timer_list *t);
-
-static void BlinkWorkItemCallback(struct work_struct *work);
-/*===========================================================================
- * LED_819xUsb routines.
- *===========================================================================
- *
- *
- *
- * Description:
- * Initialize an LED_871x object.
- */
-static void InitLed871x(struct _adapter *padapter, struct LED_871x *pLed,
- enum LED_PIN_871x LedPin)
-{
- pLed->padapter = padapter;
- pLed->LedPin = LedPin;
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->bLedOn = false;
- pLed->bLedBlinkInProgress = false;
- pLed->BlinkTimes = 0;
- pLed->BlinkingLedState = LED_UNKNOWN;
- timer_setup(&pLed->BlinkTimer, BlinkTimerCallback, 0);
- INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback);
-}
-
-/*
- * Description:
- * DeInitialize an LED_871x object.
- */
-static void DeInitLed871x(struct LED_871x *pLed)
-{
- del_timer_sync(&pLed->BlinkTimer);
- /* We should reset bLedBlinkInProgress if we cancel
- * the LedControlTimer,
- */
- pLed->bLedBlinkInProgress = false;
-}
-
-/*
- * Description:
- * Turn on LED according to LedPin specified.
- */
-static void SwLedOn(struct _adapter *padapter, struct LED_871x *pLed)
-{
- u8 LedCfg;
-
- if (padapter->surprise_removed || padapter->driver_stopped)
- return;
- LedCfg = r8712_read8(padapter, LEDCFG);
- switch (pLed->LedPin) {
- case LED_PIN_GPIO0:
- break;
- case LED_PIN_LED0:
- /* SW control led0 on.*/
- r8712_write8(padapter, LEDCFG, LedCfg & 0xf0);
- break;
- case LED_PIN_LED1:
- /* SW control led1 on.*/
- r8712_write8(padapter, LEDCFG, LedCfg & 0x0f);
- break;
- default:
- break;
- }
- pLed->bLedOn = true;
-}
-
-/*
- * Description:
- * Turn off LED according to LedPin specified.
- */
-static void SwLedOff(struct _adapter *padapter, struct LED_871x *pLed)
-{
- u8 LedCfg;
-
- if (padapter->surprise_removed || padapter->driver_stopped)
- return;
- LedCfg = r8712_read8(padapter, LEDCFG);
- switch (pLed->LedPin) {
- case LED_PIN_GPIO0:
- break;
- case LED_PIN_LED0:
- LedCfg &= 0xf0; /* Set to software control.*/
- r8712_write8(padapter, LEDCFG, (LedCfg | BIT(3)));
- break;
- case LED_PIN_LED1:
- LedCfg &= 0x0f; /* Set to software control.*/
- r8712_write8(padapter, LEDCFG, (LedCfg | BIT(7)));
- break;
- default:
- break;
- }
- pLed->bLedOn = false;
-}
-
-/*===========================================================================
- * Interface to manipulate LED objects.
- *===========================================================================
- *
- * Description:
- * Initialize all LED_871x objects.
- */
-void r8712_InitSwLeds(struct _adapter *padapter)
-{
- struct led_priv *pledpriv = &padapter->ledpriv;
-
- pledpriv->LedControlHandler = LedControl871x;
- InitLed871x(padapter, &pledpriv->SwLed0, LED_PIN_LED0);
- InitLed871x(padapter, &pledpriv->SwLed1, LED_PIN_LED1);
-}
-
-/* Description:
- * DeInitialize all LED_819xUsb objects.
- */
-void r8712_DeInitSwLeds(struct _adapter *padapter)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
-
- DeInitLed871x(&ledpriv->SwLed0);
- DeInitLed871x(&ledpriv->SwLed1);
-}
-
-/* Description:
- * Implementation of LED blinking behavior.
- * It toggle off LED and schedule corresponding timer if necessary.
- */
-static void SwLedBlink(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 bStopBlinking = false;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- SwLedOff(padapter, pLed);
- /* Determine if we shall change LED state again. */
- pLed->BlinkTimes--;
- switch (pLed->CurrLedState) {
- case LED_BLINK_NORMAL:
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- break;
- case LED_BLINK_StartToBlink:
- if (check_fwstate(pmlmepriv, _FW_LINKED) &&
- (pmlmepriv->fw_state & WIFI_STATION_STATE))
- bStopBlinking = true;
- if (check_fwstate(pmlmepriv, _FW_LINKED) &&
- ((pmlmepriv->fw_state & WIFI_ADHOC_STATE) ||
- (pmlmepriv->fw_state & WIFI_ADHOC_MASTER_STATE)))
- bStopBlinking = true;
- else if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- break;
- case LED_BLINK_WPS:
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- break;
- default:
- bStopBlinking = true;
- break;
- }
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED) &&
- !pLed->bLedOn)
- SwLedOn(padapter, pLed);
- else if (check_fwstate(pmlmepriv, _FW_LINKED) && pLed->bLedOn)
- SwLedOff(padapter, pLed);
- pLed->BlinkTimes = 0;
- pLed->bLedBlinkInProgress = false;
- } else {
- /* Assign LED state to toggle. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
-
- /* Schedule a timer to toggle LED state. */
- switch (pLed->CurrLedState) {
- case LED_BLINK_NORMAL:
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- break;
- case LED_BLINK_SLOWLY:
- case LED_BLINK_StartToBlink:
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
- break;
- case LED_BLINK_WPS:
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LONG_INTERVAL));
- break;
- default:
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
- break;
- }
- }
-}
-
-static void SwLedBlink1(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
- struct LED_871x *pLed1 = &ledpriv->SwLed1;
- u8 bStopBlinking = false;
-
- if (peeprompriv->CustomerID == RT_CID_819x_CAMEO)
- pLed = &ledpriv->SwLed1;
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- SwLedOff(padapter, pLed);
- if (peeprompriv->CustomerID == RT_CID_DEFAULT) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (!pLed1->bSWLedCtrl) {
- SwLedOn(padapter, pLed1);
- pLed1->bSWLedCtrl = true;
- } else if (!pLed1->bLedOn) {
- SwLedOn(padapter, pLed1);
- }
- } else {
- if (!pLed1->bSWLedCtrl) {
- SwLedOff(padapter, pLed1);
- pLed1->bSWLedCtrl = true;
- } else if (pLed1->bLedOn) {
- SwLedOff(padapter, pLed1);
- }
- }
- }
- switch (pLed->CurrLedState) {
- case LED_BLINK_SLOWLY:
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- break;
- case LED_BLINK_NORMAL:
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- break;
- case LED_SCAN_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->bLedLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_NORMAL;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- }
- pLed->bLedScanBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_TXRX_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->bLedLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_NORMAL;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- }
- pLed->BlinkTimes = 0;
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_BLINK_WPS:
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- break;
- case LED_BLINK_WPS_STOP: /* WPS success */
- if (pLed->BlinkingLedState == LED_STATE_ON) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
- bStopBlinking = false;
- } else {
- bStopBlinking = true;
- }
- if (bStopBlinking) {
- pLed->bLedLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_NORMAL;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- }
- pLed->bLedWPSBlinkInProgress = false;
- break;
- default:
- break;
- }
-}
-
-static void SwLedBlink2(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 bStopBlinking = false;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- SwLedOff(padapter, pLed);
- switch (pLed->CurrLedState) {
- case LED_SCAN_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- SwLedOn(padapter, pLed);
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- SwLedOff(padapter, pLed);
- }
- pLed->bLedScanBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_TXRX_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- SwLedOn(padapter, pLed);
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- SwLedOff(padapter, pLed);
- }
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- default:
- break;
- }
-}
-
-static void SwLedBlink3(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 bStopBlinking = false;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- if (pLed->CurrLedState != LED_BLINK_WPS_STOP)
- SwLedOff(padapter, pLed);
- switch (pLed->CurrLedState) {
- case LED_SCAN_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (!pLed->bLedOn)
- SwLedOn(padapter, pLed);
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedOn)
- SwLedOff(padapter, pLed);
- }
- pLed->bLedScanBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_TXRX_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (!pLed->bLedOn)
- SwLedOn(padapter, pLed);
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedOn)
- SwLedOff(padapter, pLed);
- }
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_BLINK_WPS:
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- break;
- case LED_BLINK_WPS_STOP: /*WPS success*/
- if (pLed->BlinkingLedState == LED_STATE_ON) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
- bStopBlinking = false;
- } else {
- bStopBlinking = true;
- }
- if (bStopBlinking) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- SwLedOn(padapter, pLed);
- pLed->bLedWPSBlinkInProgress = false;
- }
- break;
- default:
- break;
- }
-}
-
-static void SwLedBlink4(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct LED_871x *pLed1 = &ledpriv->SwLed1;
- u8 bStopBlinking = false;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- SwLedOff(padapter, pLed);
- if (!pLed1->bLedWPSBlinkInProgress &&
- pLed1->BlinkingLedState == LED_UNKNOWN) {
- pLed1->BlinkingLedState = LED_STATE_OFF;
- pLed1->CurrLedState = LED_STATE_OFF;
- SwLedOff(padapter, pLed1);
- }
- switch (pLed->CurrLedState) {
- case LED_BLINK_SLOWLY:
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- break;
- case LED_BLINK_StartToBlink:
- if (pLed->bLedOn) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
- } else {
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- }
- break;
- case LED_SCAN_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- pLed->bLedScanBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_TXRX_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_BLINK_WPS:
- if (pLed->bLedOn) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
- } else {
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- }
- break;
- case LED_BLINK_WPS_STOP: /*WPS authentication fail*/
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- break;
- case LED_BLINK_WPS_STOP_OVERLAP: /*WPS session overlap */
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0) {
- if (pLed->bLedOn)
- pLed->BlinkTimes = 1;
- else
- bStopBlinking = true;
- }
- if (bStopBlinking) {
- pLed->BlinkTimes = 10;
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- }
- break;
- default:
- break;
- }
-}
-
-static void SwLedBlink5(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- u8 bStopBlinking = false;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- SwLedOff(padapter, pLed);
- switch (pLed->CurrLedState) {
- case LED_SCAN_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (!pLed->bLedOn)
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- pLed->bLedScanBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_TXRX_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (!pLed->bLedOn)
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- default:
- break;
- }
-}
-
-static void SwLedBlink6(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- u8 bStopBlinking = false;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- SwLedOff(padapter, pLed);
- switch (pLed->CurrLedState) {
- case LED_TXRX_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (!pLed->bLedOn)
- SwLedOn(padapter, pLed);
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_BLINK_WPS:
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- break;
-
- default:
- break;
- }
-}
-
-/* Description:
- * Callback function of LED BlinkTimer,
- * it just schedules to corresponding BlinkWorkItem.
- */
-static void BlinkTimerCallback(struct timer_list *t)
-{
- struct LED_871x *pLed = from_timer(pLed, t, BlinkTimer);
-
- /* This fixed the crash problem on Fedora 12 when trying to do the
- * insmod;ifconfig up;rmmod commands.
- */
- if (pLed->padapter->surprise_removed || pLed->padapter->driver_stopped)
- return;
- schedule_work(&pLed->BlinkWorkItem);
-}
-
-/* Description:
- * Callback function of LED BlinkWorkItem.
- * We dispatch actual LED blink action according to LedStrategy.
- */
-static void BlinkWorkItemCallback(struct work_struct *work)
-{
- struct LED_871x *pLed = container_of(work, struct LED_871x,
- BlinkWorkItem);
- struct led_priv *ledpriv = &pLed->padapter->ledpriv;
-
- switch (ledpriv->LedStrategy) {
- case SW_LED_MODE0:
- SwLedBlink(pLed);
- break;
- case SW_LED_MODE1:
- SwLedBlink1(pLed);
- break;
- case SW_LED_MODE2:
- SwLedBlink2(pLed);
- break;
- case SW_LED_MODE3:
- SwLedBlink3(pLed);
- break;
- case SW_LED_MODE4:
- SwLedBlink4(pLed);
- break;
- case SW_LED_MODE5:
- SwLedBlink5(pLed);
- break;
- case SW_LED_MODE6:
- SwLedBlink6(pLed);
- break;
- default:
- SwLedBlink(pLed);
- break;
- }
-}
-
-/*============================================================================
- * Default LED behavior.
- *============================================================================
- *
- * Description:
- * Implement each led action for SW_LED_MODE0.
- * This is default strategy.
- */
-
-static void SwLedControlMode1(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct LED_871x *pLed = &ledpriv->SwLed0;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct sitesurvey_ctrl *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
-
- if (padapter->eeprompriv.CustomerID == RT_CID_819x_CAMEO)
- pLed = &ledpriv->SwLed1;
- switch (LedAction) {
- case LED_CTL_START_TO_LINK:
- case LED_CTL_NO_LINK:
- if (!pLed->bLedNoLinkBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_LINK:
- if (!pLed->bLedLinkBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_NORMAL;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_SITE_SURVEY:
- if (psitesurveyctrl->traffic_busy &&
- check_fwstate(pmlmepriv, _FW_LINKED))
- ; /* dummy branch */
- else if (!pLed->bLedScanBlinkInProgress) {
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedScanBlinkInProgress = true;
- pLed->CurrLedState = LED_SCAN_BLINK;
- pLed->BlinkTimes = 24;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (!pLed->bLedBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_TXRX_BLINK;
- pLed->BlinkTimes = 2;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
-
- case LED_CTL_START_WPS: /*wait until xinpin finish */
- case LED_CTL_START_WPS_BOTTON:
- if (!pLed->bLedWPSBlinkInProgress) {
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_WPS;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_STOP_WPS:
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress)
- del_timer(&pLed->BlinkTimer);
- else
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_WPS_STOP;
- if (pLed->bLedOn) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
- } else {
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- break;
- case LED_CTL_STOP_WPS_FAIL:
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- default:
- break;
- }
-}
-
-static void SwLedControlMode2(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct LED_871x *pLed = &ledpriv->SwLed0;
-
- switch (LedAction) {
- case LED_CTL_SITE_SURVEY:
- if (pmlmepriv->sitesurveyctrl.traffic_busy)
- ; /* dummy branch */
- else if (!pLed->bLedScanBlinkInProgress) {
- if (IS_LED_WPS_BLINKING(pLed))
- return;
-
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedScanBlinkInProgress = true;
- pLed->CurrLedState = LED_SCAN_BLINK;
- pLed->BlinkTimes = 24;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
-
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (!pLed->bLedBlinkInProgress &&
- check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_TXRX_BLINK;
- pLed->BlinkTimes = 2;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
-
- case LED_CTL_LINK:
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
-
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
-
- case LED_CTL_START_WPS: /*wait until xinpin finish*/
- case LED_CTL_START_WPS_BOTTON:
- if (!pLed->bLedWPSBlinkInProgress) {
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- break;
-
- case LED_CTL_STOP_WPS:
- pLed->bLedWPSBlinkInProgress = false;
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
-
- case LED_CTL_STOP_WPS_FAIL:
- pLed->bLedWPSBlinkInProgress = false;
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
-
- case LED_CTL_START_TO_LINK:
- case LED_CTL_NO_LINK:
- if (!IS_LED_BLINKING(pLed)) {
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- default:
- break;
- }
-}
-
-static void SwLedControlMode3(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct LED_871x *pLed = &ledpriv->SwLed0;
-
- switch (LedAction) {
- case LED_CTL_SITE_SURVEY:
- if (pmlmepriv->sitesurveyctrl.traffic_busy)
- ; /* dummy branch */
- else if (!pLed->bLedScanBlinkInProgress) {
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedScanBlinkInProgress = true;
- pLed->CurrLedState = LED_SCAN_BLINK;
- pLed->BlinkTimes = 24;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (!pLed->bLedBlinkInProgress &&
- check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_TXRX_BLINK;
- pLed->BlinkTimes = 2;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_LINK:
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- case LED_CTL_START_WPS: /* wait until xinpin finish */
- case LED_CTL_START_WPS_BOTTON:
- if (!pLed->bLedWPSBlinkInProgress) {
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_WPS;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_STOP_WPS:
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- } else {
- pLed->bLedWPSBlinkInProgress = true;
- }
- pLed->CurrLedState = LED_BLINK_WPS_STOP;
- if (pLed->bLedOn) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
- } else {
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- break;
- case LED_CTL_STOP_WPS_FAIL:
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- case LED_CTL_START_TO_LINK:
- case LED_CTL_NO_LINK:
- if (!IS_LED_BLINKING(pLed)) {
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- default:
- break;
- }
-}
-
-static void SwLedControlMode4(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct LED_871x *pLed = &ledpriv->SwLed0;
- struct LED_871x *pLed1 = &ledpriv->SwLed1;
-
- switch (LedAction) {
- case LED_CTL_START_TO_LINK:
- if (pLed1->bLedWPSBlinkInProgress) {
- pLed1->bLedWPSBlinkInProgress = false;
- del_timer(&pLed1->BlinkTimer);
- pLed1->BlinkingLedState = LED_STATE_OFF;
- pLed1->CurrLedState = LED_STATE_OFF;
- if (pLed1->bLedOn)
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- if (!pLed->bLedStartToLinkBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- pLed->bLedStartToLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_StartToBlink;
- if (pLed->bLedOn) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
- } else {
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- }
- }
- break;
- case LED_CTL_LINK:
- case LED_CTL_NO_LINK:
- /*LED1 settings*/
- if (LedAction == LED_CTL_LINK) {
- if (pLed1->bLedWPSBlinkInProgress) {
- pLed1->bLedWPSBlinkInProgress = false;
- del_timer(&pLed1->BlinkTimer);
- pLed1->BlinkingLedState = LED_STATE_OFF;
- pLed1->CurrLedState = LED_STATE_OFF;
- if (pLed1->bLedOn)
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- }
- if (!pLed->bLedNoLinkBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_SITE_SURVEY:
- if (pmlmepriv->sitesurveyctrl.traffic_busy &&
- check_fwstate(pmlmepriv, _FW_LINKED))
- ;
- else if (!pLed->bLedScanBlinkInProgress) {
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedScanBlinkInProgress = true;
- pLed->CurrLedState = LED_SCAN_BLINK;
- pLed->BlinkTimes = 24;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (!pLed->bLedBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_TXRX_BLINK;
- pLed->BlinkTimes = 2;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_START_WPS: /*wait until xinpin finish*/
- case LED_CTL_START_WPS_BOTTON:
- if (pLed1->bLedWPSBlinkInProgress) {
- pLed1->bLedWPSBlinkInProgress = false;
- del_timer(&pLed1->BlinkTimer);
- pLed1->BlinkingLedState = LED_STATE_OFF;
- pLed1->CurrLedState = LED_STATE_OFF;
- if (pLed1->bLedOn)
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- if (!pLed->bLedWPSBlinkInProgress) {
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_WPS;
- if (pLed->bLedOn) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
- } else {
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- }
- }
- break;
- case LED_CTL_STOP_WPS: /*WPS connect success*/
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- break;
- case LED_CTL_STOP_WPS_FAIL: /*WPS authentication fail*/
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- /*LED1 settings*/
- if (pLed1->bLedWPSBlinkInProgress)
- del_timer(&pLed1->BlinkTimer);
- else
- pLed1->bLedWPSBlinkInProgress = true;
- pLed1->CurrLedState = LED_BLINK_WPS_STOP;
- if (pLed1->bLedOn)
- pLed1->BlinkingLedState = LED_STATE_OFF;
- else
- pLed1->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- break;
- case LED_CTL_STOP_WPS_FAIL_OVERLAP: /*WPS session overlap*/
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- /*LED1 settings*/
- if (pLed1->bLedWPSBlinkInProgress)
- del_timer(&pLed1->BlinkTimer);
- else
- pLed1->bLedWPSBlinkInProgress = true;
- pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP;
- pLed1->BlinkTimes = 10;
- if (pLed1->bLedOn)
- pLed1->BlinkingLedState = LED_STATE_OFF;
- else
- pLed1->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- if (pLed->bLedStartToLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedStartToLinkBlinkInProgress = false;
- }
- if (pLed1->bLedWPSBlinkInProgress) {
- del_timer(&pLed1->BlinkTimer);
- pLed1->bLedWPSBlinkInProgress = false;
- }
- pLed1->BlinkingLedState = LED_UNKNOWN;
- SwLedOff(padapter, pLed);
- SwLedOff(padapter, pLed1);
- break;
- default:
- break;
- }
-}
-
-static void SwLedControlMode5(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct LED_871x *pLed = &ledpriv->SwLed0;
-
- if (padapter->eeprompriv.CustomerID == RT_CID_819x_CAMEO)
- pLed = &ledpriv->SwLed1;
-
- switch (LedAction) {
- case LED_CTL_POWER_ON:
- case LED_CTL_NO_LINK:
- case LED_CTL_LINK: /* solid blue */
- if (pLed->CurrLedState == LED_SCAN_BLINK)
- return;
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- pLed->bLedBlinkInProgress = false;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- case LED_CTL_SITE_SURVEY:
- if (pmlmepriv->sitesurveyctrl.traffic_busy &&
- check_fwstate(pmlmepriv, _FW_LINKED))
- ; /* dummy branch */
- else if (!pLed->bLedScanBlinkInProgress) {
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedScanBlinkInProgress = true;
- pLed->CurrLedState = LED_SCAN_BLINK;
- pLed->BlinkTimes = 24;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (!pLed->bLedBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK)
- return;
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_TXRX_BLINK;
- pLed->BlinkTimes = 2;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- SwLedOff(padapter, pLed);
- break;
- default:
- break;
- }
-}
-
-static void SwLedControlMode6(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct LED_871x *pLed = &ledpriv->SwLed0;
-
- switch (LedAction) {
- case LED_CTL_POWER_ON:
- case LED_CTL_NO_LINK:
- case LED_CTL_LINK: /*solid blue*/
- case LED_CTL_SITE_SURVEY:
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- pLed->bLedBlinkInProgress = false;
- mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0));
- break;
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (!pLed->bLedBlinkInProgress &&
- check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_TXRX_BLINK;
- pLed->BlinkTimes = 2;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_START_WPS: /*wait until xinpin finish*/
- case LED_CTL_START_WPS_BOTTON:
- if (!pLed->bLedWPSBlinkInProgress) {
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_WPS;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_STOP_WPS_FAIL:
- case LED_CTL_STOP_WPS:
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- SwLedOff(padapter, pLed);
- break;
- default:
- break;
- }
-}
-
-/* Description:
- * Dispatch LED action according to pHalData->LedStrategy.
- */
-void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
-
- if (!ledpriv->bRegUseLed)
- return;
- switch (ledpriv->LedStrategy) {
- case SW_LED_MODE0:
- break;
- case SW_LED_MODE1:
- SwLedControlMode1(padapter, LedAction);
- break;
- case SW_LED_MODE2:
- SwLedControlMode2(padapter, LedAction);
- break;
- case SW_LED_MODE3:
- SwLedControlMode3(padapter, LedAction);
- break;
- case SW_LED_MODE4:
- SwLedControlMode4(padapter, LedAction);
- break;
- case SW_LED_MODE5:
- SwLedControlMode5(padapter, LedAction);
- break;
- case SW_LED_MODE6:
- SwLedControlMode6(padapter, LedAction);
- break;
- default:
- break;
- }
-}
-
-void r8712_flush_led_works(struct _adapter *padapter)
-{
- struct led_priv *pledpriv = &padapter->ledpriv;
-
- flush_work(&pledpriv->SwLed0.BlinkWorkItem);
- flush_work(&pledpriv->SwLed1.BlinkWorkItem);
-}
diff --git a/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h b/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h
deleted file mode 100644
index 46d758d3f3a4..000000000000
--- a/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_MACSETTING_BITDEF_H__
-#define __RTL8712_MACSETTING_BITDEF_H__
-
-/*MACID*/
-/*BSSID*/
-
-/*HWVID*/
-#define _HWVID_MSK 0x0F
-
-/*MAR*/
-/*MBIDCANCONTENT*/
-
-/*MBIDCANCFG*/
-#define _POOLING BIT(31)
-#define _WRITE_EN BIT(16)
-#define _CAM_ADDR_MSK 0x001F
-#define _CAM_ADDR_SHT 0
-
-/*BUILDTIME*/
-#define _BUILDTIME_MSK 0x3FFFFFFF
-
-/*BUILDUSER*/
-
-#endif /* __RTL8712_MACSETTING_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h b/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h
deleted file mode 100644
index 64740d99c252..000000000000
--- a/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_MACSETTING_REGDEF_H__
-#define __RTL8712_MACSETTING_REGDEF_H__
-
-#define MACID (RTL8712_MACIDSETTING_ + 0x0000)
-#define BSSIDR (RTL8712_MACIDSETTING_ + 0x0008)
-#define HWVID (RTL8712_MACIDSETTING_ + 0x000E)
-#define MAR (RTL8712_MACIDSETTING_ + 0x0010)
-#define MBIDCANCONTENT (RTL8712_MACIDSETTING_ + 0x0018)
-#define MBIDCANCFG (RTL8712_MACIDSETTING_ + 0x0020)
-#define BUILDTIME (RTL8712_MACIDSETTING_ + 0x0024)
-#define BUILDUSER (RTL8712_MACIDSETTING_ + 0x0028)
-
-#endif /*__RTL8712_MACSETTING_REGDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h b/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h
deleted file mode 100644
index 53e0d6b440f3..000000000000
--- a/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_POWERSAVE_BITDEF_H__
-#define __RTL8712_POWERSAVE_BITDEF_H__
-
-/*WOWCTRL*/
-#define _UWF BIT(3)
-#define _MAGIC BIT(2)
-#define _WOW_EN BIT(1)
-#define _PMEN BIT(0)
-
-/*PSSTATUS*/
-#define _PSSTATUS_SEL_MSK 0x0F
-
-/*PSSWITCH*/
-#define _PSSWITCH_ACT BIT(7)
-#define _PSSWITCH_SEL_MSK 0x0F
-#define _PSSWITCH_SEL_SHT 0
-
-/*LPNAV_CTRL*/
-#define _LPNAV_EN BIT(31)
-#define _LPNAV_EARLY_MSK 0x7FFF0000
-#define _LPNAV_EARLY_SHT 16
-#define _LPNAV_TH_MSK 0x0000FFFF
-#define _LPNAV_TH_SHT 0
-
-/*RPWM*/
-/*CPWM*/
-#define _TOGGLING BIT(7)
-#define _WWLAN BIT(3)
-#define _RPS_ST BIT(2)
-#define _WLAN_TRX BIT(1)
-#define _SYS_CLK BIT(0)
-
-#endif /* __RTL8712_POWERSAVE_BITDEF_H__*/
diff --git a/drivers/staging/rtl8712/rtl8712_powersave_regdef.h b/drivers/staging/rtl8712/rtl8712_powersave_regdef.h
deleted file mode 100644
index 1bcfde4b1c11..000000000000
--- a/drivers/staging/rtl8712/rtl8712_powersave_regdef.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_POWERSAVE_REGDEF_H__
-#define __RTL8712_POWERSAVE_REGDEF_H__
-
-#define WOWCTRL (RTL8712_POWERSAVE_ + 0x00)
-#define PSSTATUS (RTL8712_POWERSAVE_ + 0x01)
-#define PSSWITCH (RTL8712_POWERSAVE_ + 0x02)
-#define MIMOPS_WAITPERIOD (RTL8712_POWERSAVE_ + 0x03)
-#define LPNAV_CTRL (RTL8712_POWERSAVE_ + 0x04)
-#define WFM0 (RTL8712_POWERSAVE_ + 0x10)
-#define WFM1 (RTL8712_POWERSAVE_ + 0x20)
-#define WFM2 (RTL8712_POWERSAVE_ + 0x30)
-#define WFM3 (RTL8712_POWERSAVE_ + 0x40)
-#define WFM4 (RTL8712_POWERSAVE_ + 0x50)
-#define WFM5 (RTL8712_POWERSAVE_ + 0x60)
-#define WFCRC (RTL8712_POWERSAVE_ + 0x70)
-#define RPWM (RTL8712_POWERSAVE_ + 0x7C)
-#define CPWM (RTL8712_POWERSAVE_ + 0x7D)
-
-#endif /* __RTL8712_POWERSAVE_REGDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h
deleted file mode 100644
index 1de51c48f9c1..000000000000
--- a/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_RATECTRL_BITDEF_H__
-#define __RTL8712_RATECTRL_BITDEF_H__
-
-/*INIRTSMCS_SEL*/
-#define _INIRTSMCS_SEL_MSK 0x3F
-
-/* RRSR*/
-#define _RRSR_SHORT BIT(23)
-#define _RRSR_RSC_MSK 0x600000
-#define _RRSR_RSC_SHT 21
-#define _RRSR_BITMAP_MSK 0x0FFFFF
-#define _RRSR_BITMAP_SHT 0
-
-/* AGGLEN_LMT_H*/
-#define _AGGLMT_MCS32_MSK 0xF0
-#define _AGGLMT_MCS32_SHT 4
-#define _AGGLMT_MCS15_SGI_MSK 0x0F
-#define _AGGLMT_MCS15_SGI_SHT 0
-
-/* DARFRC*/
-/* RARFRC*/
-/* MCS_TXAGC*/
-/* CCK_TXAGC*/
-#define _CCK_MSK 0xFF00
-#define _CCK_SHT 8
-#define _BARKER_MSK 0x00FF
-#define _BARKER_SHT 0
-
-#endif /* __RTL8712_RATECTRL_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h b/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h
deleted file mode 100644
index 9ed5653f3f7f..000000000000
--- a/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_RATECTRL_REGDEF_H__
-#define __RTL8712_RATECTRL_REGDEF_H__
-
-#define INIMCS_SEL (RTL8712_RATECTRL_ + 0x00)
-#define INIRTSMCS_SEL (RTL8712_RATECTRL_ + 0x20)
-#define RRSR (RTL8712_RATECTRL_ + 0x21)
-#define ARFR0 (RTL8712_RATECTRL_ + 0x24)
-#define ARFR1 (RTL8712_RATECTRL_ + 0x28)
-#define ARFR2 (RTL8712_RATECTRL_ + 0x2C)
-#define ARFR3 (RTL8712_RATECTRL_ + 0x30)
-#define ARFR4 (RTL8712_RATECTRL_ + 0x34)
-#define ARFR5 (RTL8712_RATECTRL_ + 0x38)
-#define ARFR6 (RTL8712_RATECTRL_ + 0x3C)
-#define ARFR7 (RTL8712_RATECTRL_ + 0x40)
-#define AGGLEN_LMT_H (RTL8712_RATECTRL_ + 0x47)
-#define AGGLEN_LMT_L (RTL8712_RATECTRL_ + 0x48)
-#define DARFRC (RTL8712_RATECTRL_ + 0x50)
-#define RARFRC (RTL8712_RATECTRL_ + 0x58)
-#define MCS_TXAGC0 (RTL8712_RATECTRL_ + 0x60)
-#define MCS_TXAGC1 (RTL8712_RATECTRL_ + 0x61)
-#define MCS_TXAGC2 (RTL8712_RATECTRL_ + 0x62)
-#define MCS_TXAGC3 (RTL8712_RATECTRL_ + 0x63)
-#define MCS_TXAGC4 (RTL8712_RATECTRL_ + 0x64)
-#define MCS_TXAGC5 (RTL8712_RATECTRL_ + 0x65)
-#define MCS_TXAGC6 (RTL8712_RATECTRL_ + 0x66)
-#define MCS_TXAGC7 (RTL8712_RATECTRL_ + 0x67)
-#define CCK_TXAGC (RTL8712_RATECTRL_ + 0x68)
-
-#endif /*__RTL8712_RATECTRL_REGDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c
deleted file mode 100644
index ab344d676bb9..000000000000
--- a/drivers/staging/rtl8712/rtl8712_recv.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl8712_recv.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL8712_RECV_C_
-
-#include <linux/if_ether.h>
-#include <linux/ip.h>
-#include <net/cfg80211.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "mlme_osdep.h"
-#include "ethernet.h"
-#include "usb_ops.h"
-#include "wifi.h"
-
-static void recv_tasklet(struct tasklet_struct *t);
-
-int r8712_init_recv_priv(struct recv_priv *precvpriv,
- struct _adapter *padapter)
-{
- int i;
- struct recv_buf *precvbuf;
- addr_t tmpaddr = 0;
- int alignment = 0;
- struct sk_buff *pskb = NULL;
-
- /*init recv_buf*/
- _init_queue(&precvpriv->free_recv_buf_queue);
- precvpriv->pallocated_recv_buf =
- kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, GFP_ATOMIC);
- if (!precvpriv->pallocated_recv_buf)
- return -ENOMEM;
- precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 -
- ((addr_t)(precvpriv->pallocated_recv_buf) & 3);
- precvbuf = (struct recv_buf *)precvpriv->precv_buf;
- for (i = 0; i < NR_RECVBUFF; i++) {
- INIT_LIST_HEAD(&precvbuf->list);
- spin_lock_init(&precvbuf->recvbuf_lock);
- if (r8712_os_recvbuf_resource_alloc(padapter, precvbuf))
- break;
- precvbuf->ref_cnt = 0;
- precvbuf->adapter = padapter;
- list_add_tail(&precvbuf->list,
- &precvpriv->free_recv_buf_queue.queue);
- precvbuf++;
- }
- precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
- tasklet_setup(&precvpriv->recv_tasklet, recv_tasklet);
- skb_queue_head_init(&precvpriv->rx_skb_queue);
-
- skb_queue_head_init(&precvpriv->free_recv_skb_queue);
- for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
- pskb = netdev_alloc_skb(padapter->pnetdev, MAX_RECVBUF_SZ +
- RECVBUFF_ALIGN_SZ);
- if (pskb) {
- tmpaddr = (addr_t)pskb->data;
- alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
- skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
- skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
- }
- pskb = NULL;
- }
- return 0;
-}
-
-void r8712_free_recv_priv(struct recv_priv *precvpriv)
-{
- int i;
- struct recv_buf *precvbuf;
- struct _adapter *padapter = precvpriv->adapter;
-
- precvbuf = (struct recv_buf *)precvpriv->precv_buf;
- for (i = 0; i < NR_RECVBUFF; i++) {
- r8712_os_recvbuf_resource_free(padapter, precvbuf);
- precvbuf++;
- }
- kfree(precvpriv->pallocated_recv_buf);
- skb_queue_purge(&precvpriv->rx_skb_queue);
- if (skb_queue_len(&precvpriv->rx_skb_queue))
- netdev_warn(padapter->pnetdev, "r8712u: rx_skb_queue not empty\n");
- skb_queue_purge(&precvpriv->free_recv_skb_queue);
- if (skb_queue_len(&precvpriv->free_recv_skb_queue))
- netdev_warn(padapter->pnetdev, "r8712u: free_recv_skb_queue not empty %d\n",
- skb_queue_len(&precvpriv->free_recv_skb_queue));
-}
-
-void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf)
-{
- precvbuf->transfer_len = 0;
- precvbuf->len = 0;
- precvbuf->ref_cnt = 0;
- if (precvbuf->pbuf) {
- precvbuf->pdata = precvbuf->pbuf;
- precvbuf->phead = precvbuf->pbuf;
- precvbuf->ptail = precvbuf->pbuf;
- precvbuf->pend = precvbuf->pdata + MAX_RECVBUF_SZ;
- }
-}
-
-void r8712_free_recvframe(union recv_frame *precvframe,
- struct __queue *pfree_recv_queue)
-{
- unsigned long irqL;
- struct _adapter *padapter = precvframe->u.hdr.adapter;
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- if (precvframe->u.hdr.pkt) {
- dev_kfree_skb_any(precvframe->u.hdr.pkt);/*free skb by driver*/
- precvframe->u.hdr.pkt = NULL;
- }
- spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
- list_del_init(&precvframe->u.hdr.list);
- list_add_tail(&precvframe->u.hdr.list, &pfree_recv_queue->queue);
- if (padapter) {
- if (pfree_recv_queue == &precvpriv->free_recv_queue)
- precvpriv->free_recvframe_cnt++;
- }
- spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL);
-}
-
-static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib,
- struct recv_stat *prxstat)
-{
- /*TODO:
- * Offset 0
- */
- pattrib->bdecrypted = (le32_to_cpu(prxstat->rxdw0) & BIT(27)) == 0;
- pattrib->crc_err = (le32_to_cpu(prxstat->rxdw0) & BIT(14)) != 0;
- /*Offset 4*/
- /*Offset 8*/
- /*Offset 12*/
- if (le32_to_cpu(prxstat->rxdw3) & BIT(13)) {
- pattrib->tcpchk_valid = 1; /* valid */
- if (le32_to_cpu(prxstat->rxdw3) & BIT(11))
- pattrib->tcp_chkrpt = 1; /* correct */
- else
- pattrib->tcp_chkrpt = 0; /* incorrect */
- if (le32_to_cpu(prxstat->rxdw3) & BIT(12))
- pattrib->ip_chkrpt = 1; /* correct */
- else
- pattrib->ip_chkrpt = 0; /* incorrect */
- } else {
- pattrib->tcpchk_valid = 0; /* invalid */
- }
- pattrib->mcs_rate = (u8)((le32_to_cpu(prxstat->rxdw3)) & 0x3f);
- pattrib->htc = (u8)((le32_to_cpu(prxstat->rxdw3) >> 14) & 0x1);
- /*Offset 16*/
- /*Offset 20*/
- /*phy_info*/
-}
-
-/*perform defrag*/
-static union recv_frame *recvframe_defrag(struct _adapter *adapter,
- struct __queue *defrag_q)
-{
- struct list_head *plist, *phead;
- u8 wlanhdr_offset;
- u8 curfragnum;
- struct recv_frame_hdr *pfhdr, *pnfhdr;
- union recv_frame *prframe, *pnextrframe;
- struct __queue *pfree_recv_queue;
-
- pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
- phead = &defrag_q->queue;
- plist = phead->next;
- prframe = container_of(plist, union recv_frame, u.list);
- list_del_init(&prframe->u.list);
- pfhdr = &prframe->u.hdr;
- curfragnum = 0;
- if (curfragnum != pfhdr->attrib.frag_num) {
- /*the first fragment number must be 0
- *free the whole queue
- */
- r8712_free_recvframe(prframe, pfree_recv_queue);
- r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
- return NULL;
- }
- curfragnum++;
- plist = &defrag_q->queue;
- plist = plist->next;
- while (!end_of_queue_search(phead, plist)) {
- pnextrframe = container_of(plist, union recv_frame, u.list);
- pnfhdr = &pnextrframe->u.hdr;
- /*check the fragment sequence (2nd ~n fragment frame) */
- if (curfragnum != pnfhdr->attrib.frag_num) {
- /* the fragment number must increase (after decache)
- * release the defrag_q & prframe
- */
- r8712_free_recvframe(prframe, pfree_recv_queue);
- r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
- return NULL;
- }
- curfragnum++;
- /* copy the 2nd~n fragment frame's payload to the first fragment
- * get the 2nd~last fragment frame's payload
- */
- wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
- recvframe_pull(pnextrframe, wlanhdr_offset);
- /* append to first fragment frame's tail (if privacy frame,
- * pull the ICV)
- */
- recvframe_pull_tail(prframe, pfhdr->attrib.icv_len);
- memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len);
- recvframe_put(prframe, pnfhdr->len);
- pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
- plist = plist->next;
- }
- /* free the defrag_q queue and return the prframe */
- r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
- return prframe;
-}
-
-/* check if need to defrag, if needed queue the frame to defrag_q */
-union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter,
- union recv_frame *precv_frame)
-{
- u8 ismfrag;
- u8 fragnum;
- u8 *psta_addr;
- struct recv_frame_hdr *pfhdr;
- struct sta_info *psta;
- struct sta_priv *pstapriv;
- struct list_head *phead;
- union recv_frame *prtnframe = NULL;
- struct __queue *pfree_recv_queue, *pdefrag_q;
-
- pstapriv = &padapter->stapriv;
- pfhdr = &precv_frame->u.hdr;
- pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
- /* need to define struct of wlan header frame ctrl */
- ismfrag = pfhdr->attrib.mfrag;
- fragnum = pfhdr->attrib.frag_num;
- psta_addr = pfhdr->attrib.ta;
- psta = r8712_get_stainfo(pstapriv, psta_addr);
- if (!psta)
- pdefrag_q = NULL;
- else
- pdefrag_q = &psta->sta_recvpriv.defrag_q;
-
- if ((ismfrag == 0) && (fragnum == 0))
- prtnframe = precv_frame;/*isn't a fragment frame*/
- if (ismfrag == 1) {
- /* 0~(n-1) fragment frame
- * enqueue to defraf_g
- */
- if (pdefrag_q) {
- if (fragnum == 0) {
- /*the first fragment*/
- if (!list_empty(&pdefrag_q->queue)) {
- /*free current defrag_q */
- r8712_free_recvframe_queue(pdefrag_q, pfree_recv_queue);
- }
- }
- /* Then enqueue the 0~(n-1) fragment to the defrag_q */
- phead = &pdefrag_q->queue;
- list_add_tail(&pfhdr->list, phead);
- prtnframe = NULL;
- } else {
- /* can't find this ta's defrag_queue, so free this
- * recv_frame
- */
- r8712_free_recvframe(precv_frame, pfree_recv_queue);
- prtnframe = NULL;
- }
- }
- if ((ismfrag == 0) && (fragnum != 0)) {
- /* the last fragment frame
- * enqueue the last fragment
- */
- if (pdefrag_q) {
- phead = &pdefrag_q->queue;
- list_add_tail(&pfhdr->list, phead);
- /*call recvframe_defrag to defrag*/
- precv_frame = recvframe_defrag(padapter, pdefrag_q);
- prtnframe = precv_frame;
- } else {
- /* can't find this ta's defrag_queue, so free this
- * recv_frame
- */
- r8712_free_recvframe(precv_frame, pfree_recv_queue);
- prtnframe = NULL;
- }
- }
- if (prtnframe && (prtnframe->u.hdr.attrib.privacy)) {
- /* after defrag we must check tkip mic code */
- if (r8712_recvframe_chkmic(padapter, prtnframe) == _FAIL) {
- r8712_free_recvframe(prtnframe, pfree_recv_queue);
- prtnframe = NULL;
- }
- }
- return prtnframe;
-}
-
-static void amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe)
-{
- int a_len, padding_len;
- u16 eth_type, nSubframe_Length;
- u8 nr_subframes, i;
- unsigned char *pdata;
- struct rx_pkt_attrib *pattrib;
- _pkt *sub_skb, *subframes[MAX_SUBFRAME_COUNT];
- struct recv_priv *precvpriv = &padapter->recvpriv;
- struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue;
-
- nr_subframes = 0;
- pattrib = &prframe->u.hdr.attrib;
- recvframe_pull(prframe, prframe->u.hdr.attrib.hdrlen);
- if (prframe->u.hdr.attrib.iv_len > 0)
- recvframe_pull(prframe, prframe->u.hdr.attrib.iv_len);
- a_len = prframe->u.hdr.len;
- pdata = prframe->u.hdr.rx_data;
- while (a_len > ETH_HLEN) {
- /* Offset 12 denote 2 mac address */
- nSubframe_Length = *((u16 *)(pdata + 12));
- /*==m==>change the length order*/
- nSubframe_Length = (nSubframe_Length >> 8) +
- (nSubframe_Length << 8);
- if (a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
- netdev_warn(padapter->pnetdev, "r8712u: nRemain_Length is %d and nSubframe_Length is: %d\n",
- a_len, nSubframe_Length);
- goto exit;
- }
- /* move the data point to data content */
- pdata += ETH_HLEN;
- a_len -= ETH_HLEN;
- /* Allocate new skb for releasing to upper layer */
- sub_skb = dev_alloc_skb(nSubframe_Length + 12);
- if (!sub_skb)
- break;
- skb_reserve(sub_skb, 12);
- skb_put_data(sub_skb, pdata, nSubframe_Length);
- subframes[nr_subframes++] = sub_skb;
- if (nr_subframes >= MAX_SUBFRAME_COUNT) {
- netdev_warn(padapter->pnetdev, "r8712u: ParseSubframe(): Too many Subframes! Packets dropped!\n");
- break;
- }
- pdata += nSubframe_Length;
- a_len -= nSubframe_Length;
- if (a_len != 0) {
- padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & 3);
- if (padding_len == 4)
- padding_len = 0;
- if (a_len < padding_len)
- goto exit;
- pdata += padding_len;
- a_len -= padding_len;
- }
- }
- for (i = 0; i < nr_subframes; i++) {
- sub_skb = subframes[i];
- /* convert hdr + possible LLC headers into Ethernet header */
- eth_type = (sub_skb->data[6] << 8) | sub_skb->data[7];
- if (sub_skb->len >= 8 &&
- ((!memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) &&
- eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
- !memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE))) {
- /* remove RFC1042 or Bridge-Tunnel encapsulation and
- * replace EtherType
- */
- skb_pull(sub_skb, SNAP_SIZE);
- memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src,
- ETH_ALEN);
- memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst,
- ETH_ALEN);
- } else {
- __be16 len;
- /* Leave Ethernet header part of hdr and full payload */
- len = htons(sub_skb->len);
- memcpy(skb_push(sub_skb, 2), &len, 2);
- memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src,
- ETH_ALEN);
- memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst,
- ETH_ALEN);
- }
- /* Indicate the packets to upper layer */
- if (sub_skb) {
- sub_skb->protocol =
- eth_type_trans(sub_skb, padapter->pnetdev);
- sub_skb->dev = padapter->pnetdev;
- if ((pattrib->tcpchk_valid == 1) &&
- (pattrib->tcp_chkrpt == 1)) {
- sub_skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else {
- sub_skb->ip_summed = CHECKSUM_NONE;
- }
- netif_rx(sub_skb);
- }
- }
-exit:
- prframe->u.hdr.len = 0;
- r8712_free_recvframe(prframe, pfree_recv_queue);
-}
-
-void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf)
-{
- __le32 voffset;
- u8 *poffset;
- u16 cmd_len, drvinfo_sz;
- struct recv_stat *prxstat;
-
- poffset = prxcmdbuf;
- voffset = *(__le32 *)poffset;
- prxstat = prxcmdbuf;
- drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16;
- drvinfo_sz <<= 3;
- poffset += RXDESC_SIZE + drvinfo_sz;
- do {
- voffset = *(__le32 *)poffset;
- cmd_len = (u16)(le32_to_cpu(voffset) & 0xffff);
- r8712_event_handle(padapter, (__le32 *)poffset);
- poffset += (cmd_len + 8);/*8 bytes alignment*/
- } while (le32_to_cpu(voffset) & BIT(31));
-}
-
-static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl,
- u16 seq_num)
-{
- u8 wsize = preorder_ctrl->wsize_b;
- u16 wend = (preorder_ctrl->indicate_seq + wsize - 1) % 4096;
-
- /* Rx Reorder initialize condition.*/
- if (preorder_ctrl->indicate_seq == 0xffff)
- preorder_ctrl->indicate_seq = seq_num;
- /* Drop out the packet which SeqNum is smaller than WinStart */
- if (SN_LESS(seq_num, preorder_ctrl->indicate_seq))
- return false;
- /*
- * Sliding window manipulation. Conditions includes:
- * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
- * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
- */
- if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq))
- preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq +
- 1) % 4096;
- else if (SN_LESS(wend, seq_num)) {
- if (seq_num >= (wsize - 1))
- preorder_ctrl->indicate_seq = seq_num + 1 - wsize;
- else
- preorder_ctrl->indicate_seq = 4095 - (wsize -
- (seq_num + 1)) + 1;
- }
- return true;
-}
-
-static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl,
- union recv_frame *prframe)
-{
- struct list_head *phead, *plist;
- union recv_frame *pnextrframe;
- struct rx_pkt_attrib *pnextattrib;
- struct __queue *ppending_recvframe_queue =
- &preorder_ctrl->pending_recvframe_queue;
- struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
-
- phead = &ppending_recvframe_queue->queue;
- plist = phead->next;
- while (!end_of_queue_search(phead, plist)) {
- pnextrframe = container_of(plist, union recv_frame, u.list);
- pnextattrib = &pnextrframe->u.hdr.attrib;
-
- if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num))
- return false;
-
- if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num))
- plist = plist->next;
- else
- break;
- }
- list_del_init(&prframe->u.hdr.list);
- list_add_tail(&prframe->u.hdr.list, plist);
- return true;
-}
-
-int r8712_recv_indicatepkts_in_order(struct _adapter *padapter,
- struct recv_reorder_ctrl *preorder_ctrl,
- int bforced)
-{
- struct list_head *phead, *plist;
- union recv_frame *prframe;
- struct rx_pkt_attrib *pattrib;
- int bPktInBuf = false;
- struct __queue *ppending_recvframe_queue =
- &preorder_ctrl->pending_recvframe_queue;
-
- phead = &ppending_recvframe_queue->queue;
- plist = phead->next;
- /* Handling some condition for forced indicate case.*/
- if (bforced) {
- if (list_empty(phead))
- return true;
-
- prframe = container_of(plist, union recv_frame, u.list);
- pattrib = &prframe->u.hdr.attrib;
- preorder_ctrl->indicate_seq = pattrib->seq_num;
- }
- /* Prepare indication list and indication.
- * Check if there is any packet need indicate.
- */
- while (!list_empty(phead)) {
- prframe = container_of(plist, union recv_frame, u.list);
- pattrib = &prframe->u.hdr.attrib;
- if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
- plist = plist->next;
- list_del_init(&prframe->u.hdr.list);
- if (SN_EQUAL(preorder_ctrl->indicate_seq,
- pattrib->seq_num))
- preorder_ctrl->indicate_seq =
- (preorder_ctrl->indicate_seq + 1) % 4096;
- /*indicate this recv_frame*/
- if (!pattrib->amsdu) {
- if (!padapter->driver_stopped &&
- !padapter->surprise_removed) {
- /* indicate this recv_frame */
- r8712_recv_indicatepkt(padapter,
- prframe);
- }
- } else if (pattrib->amsdu == 1) {
- amsdu_to_msdu(padapter, prframe);
- }
- /* Update local variables. */
- bPktInBuf = false;
- } else {
- bPktInBuf = true;
- break;
- }
- }
- return bPktInBuf;
-}
-
-static int recv_indicatepkt_reorder(struct _adapter *padapter,
- union recv_frame *prframe)
-{
- unsigned long irql;
- struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
- struct recv_reorder_ctrl *preorder_ctrl = prframe->u.hdr.preorder_ctrl;
- struct __queue *ppending_recvframe_queue =
- &preorder_ctrl->pending_recvframe_queue;
-
- if (!pattrib->amsdu) {
- /* s1. */
- r8712_wlanhdr_to_ethhdr(prframe);
- if (pattrib->qos != 1) {
- if (!padapter->driver_stopped &&
- !padapter->surprise_removed) {
- r8712_recv_indicatepkt(padapter, prframe);
- return 0;
- } else {
- return -EINVAL;
- }
- }
- }
- spin_lock_irqsave(&ppending_recvframe_queue->lock, irql);
- /*s2. check if winstart_b(indicate_seq) needs to be updated*/
- if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num))
- goto _err_exit;
- /*s3. Insert all packet into Reorder Queue to maintain its ordering.*/
- if (!enqueue_reorder_recvframe(preorder_ctrl, prframe))
- goto _err_exit;
- /*s4.
- * Indication process.
- * After Packet dropping and Sliding Window shifting as above, we can
- * now just indicate the packets with the SeqNum smaller than latest
- * WinStart and buffer other packets.
- *
- * For Rx Reorder condition:
- * 1. All packets with SeqNum smaller than WinStart => Indicate
- * 2. All packets with SeqNum larger than or equal to
- * WinStart => Buffer it.
- */
- if (r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, false)) {
- mod_timer(&preorder_ctrl->reordering_ctrl_timer,
- jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
- spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
- } else {
- spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
- del_timer(&preorder_ctrl->reordering_ctrl_timer);
- }
- return 0;
-_err_exit:
- spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
- return -ENOMEM;
-}
-
-void r8712_reordering_ctrl_timeout_handler(void *pcontext)
-{
- unsigned long irql;
- struct recv_reorder_ctrl *preorder_ctrl = pcontext;
- struct _adapter *padapter = preorder_ctrl->padapter;
- struct __queue *ppending_recvframe_queue =
- &preorder_ctrl->pending_recvframe_queue;
-
- if (padapter->driver_stopped || padapter->surprise_removed)
- return;
- spin_lock_irqsave(&ppending_recvframe_queue->lock, irql);
- r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, true);
- spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
-}
-
-static int r8712_process_recv_indicatepkts(struct _adapter *padapter,
- union recv_frame *prframe)
-{
- int retval = _SUCCESS;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-
- if (phtpriv->ht_option == 1) { /*B/G/N Mode*/
- if (recv_indicatepkt_reorder(padapter, prframe)) {
- /* including perform A-MPDU Rx Ordering Buffer Control*/
- if (!padapter->driver_stopped &&
- !padapter->surprise_removed)
- return _FAIL;
- }
- } else { /*B/G mode*/
- retval = r8712_wlanhdr_to_ethhdr(prframe);
- if (retval)
- return _FAIL;
- if (!padapter->driver_stopped && !padapter->surprise_removed) {
- /* indicate this recv_frame */
- r8712_recv_indicatepkt(padapter, prframe);
- } else {
- return _FAIL;
- }
- }
- return retval;
-}
-
-static u8 query_rx_pwr_percentage(s8 antpower)
-{
- if ((antpower <= -100) || (antpower >= 20))
- return 0;
- else if (antpower >= 0)
- return 100;
- else
- return 100 + antpower;
-}
-
-static u8 evm_db2percentage(s8 value)
-{
- /*
- * -33dB~0dB to 0%~99%
- */
- s8 ret_val = clamp(-value, 0, 33) * 3;
-
- if (ret_val == 99)
- ret_val = 100;
-
- return ret_val;
-}
-
-s32 r8712_signal_scale_mapping(s32 cur_sig)
-{
- s32 ret_sig;
-
- if (cur_sig >= 51 && cur_sig <= 100)
- ret_sig = 100;
- else if (cur_sig >= 41 && cur_sig <= 50)
- ret_sig = 80 + ((cur_sig - 40) * 2);
- else if (cur_sig >= 31 && cur_sig <= 40)
- ret_sig = 66 + (cur_sig - 30);
- else if (cur_sig >= 21 && cur_sig <= 30)
- ret_sig = 54 + (cur_sig - 20);
- else if (cur_sig >= 10 && cur_sig <= 20)
- ret_sig = 42 + (((cur_sig - 10) * 2) / 3);
- else if (cur_sig >= 5 && cur_sig <= 9)
- ret_sig = 22 + (((cur_sig - 5) * 3) / 2);
- else if (cur_sig >= 1 && cur_sig <= 4)
- ret_sig = 6 + (((cur_sig - 1) * 3) / 2);
- else
- ret_sig = cur_sig;
- return ret_sig;
-}
-
-static s32 translate2dbm(struct _adapter *padapter, u8 signal_strength_idx)
-{
- s32 signal_power; /* in dBm.*/
- /* Translate to dBm (x=0.5y-95).*/
- signal_power = (s32)((signal_strength_idx + 1) >> 1);
- signal_power -= 95;
- return signal_power;
-}
-
-static void query_rx_phy_status(struct _adapter *padapter,
- union recv_frame *prframe)
-{
- u8 i, max_spatial_stream, evm;
- struct recv_stat *prxstat = (struct recv_stat *)prframe->u.hdr.rx_head;
- struct phy_stat *pphy_stat = (struct phy_stat *)(prxstat + 1);
- u8 *pphy_head = (u8 *)(prxstat + 1);
- s8 rx_pwr[4], rx_pwr_all;
- u8 pwdb_all;
- u32 rssi, total_rssi = 0;
- u8 bcck_rate = 0, rf_rx_num = 0, cck_highpwr = 0;
- struct phy_cck_rx_status *pcck_buf;
- u8 sq;
-
- /* Record it for next packet processing*/
- bcck_rate = (prframe->u.hdr.attrib.mcs_rate <= 3 ? 1 : 0);
- if (bcck_rate) {
- u8 report;
-
- /* CCK Driver info Structure is not the same as OFDM packet.*/
- pcck_buf = (struct phy_cck_rx_status *)pphy_stat;
- /* (1)Hardware does not provide RSSI for CCK
- * (2)PWDB, Average PWDB calculated by hardware
- * (for rate adaptive)
- */
- if (!cck_highpwr) {
- report = pcck_buf->cck_agc_rpt & 0xc0;
- report >>= 6;
- switch (report) {
- /* Modify the RF RNA gain value to -40, -20,
- * -2, 14 by Jenyu's suggestion
- * Note: different RF with the different
- * RNA gain.
- */
- case 0x3:
- rx_pwr_all = -40 - (pcck_buf->cck_agc_rpt &
- 0x3e);
- break;
- case 0x2:
- rx_pwr_all = -20 - (pcck_buf->cck_agc_rpt &
- 0x3e);
- break;
- case 0x1:
- rx_pwr_all = -2 - (pcck_buf->cck_agc_rpt &
- 0x3e);
- break;
- case 0x0:
- rx_pwr_all = 14 - (pcck_buf->cck_agc_rpt &
- 0x3e);
- break;
- }
- } else {
- report = ((u8)(le32_to_cpu(pphy_stat->phydw1) >> 8)) &
- 0x60;
- report >>= 5;
- switch (report) {
- case 0x3:
- rx_pwr_all = -40 - ((pcck_buf->cck_agc_rpt &
- 0x1f) << 1);
- break;
- case 0x2:
- rx_pwr_all = -20 - ((pcck_buf->cck_agc_rpt &
- 0x1f) << 1);
- break;
- case 0x1:
- rx_pwr_all = -2 - ((pcck_buf->cck_agc_rpt &
- 0x1f) << 1);
- break;
- case 0x0:
- rx_pwr_all = 14 - ((pcck_buf->cck_agc_rpt &
- 0x1f) << 1);
- break;
- }
- }
- pwdb_all = query_rx_pwr_percentage(rx_pwr_all);
- /* CCK gain is smaller than OFDM/MCS gain,*/
- /* so we add gain diff by experiences, the val is 6 */
- pwdb_all += 6;
- if (pwdb_all > 100)
- pwdb_all = 100;
- /* modify the offset to make the same gain index with OFDM.*/
- if (pwdb_all > 34 && pwdb_all <= 42)
- pwdb_all -= 2;
- else if (pwdb_all > 26 && pwdb_all <= 34)
- pwdb_all -= 6;
- else if (pwdb_all > 14 && pwdb_all <= 26)
- pwdb_all -= 8;
- else if (pwdb_all > 4 && pwdb_all <= 14)
- pwdb_all -= 4;
- /*
- * (3) Get Signal Quality (EVM)
- */
- if (pwdb_all > 40) {
- sq = 100;
- } else {
- sq = pcck_buf->sq_rpt;
- if (pcck_buf->sq_rpt > 64)
- sq = 0;
- else if (pcck_buf->sq_rpt < 20)
- sq = 100;
- else
- sq = ((64 - sq) * 100) / 44;
- }
- prframe->u.hdr.attrib.signal_qual = sq;
- prframe->u.hdr.attrib.rx_mimo_signal_qual[0] = sq;
- prframe->u.hdr.attrib.rx_mimo_signal_qual[1] = -1;
- } else {
- /* (1)Get RSSI for HT rate */
- for (i = 0; i < ((padapter->registrypriv.rf_config) &
- 0x0f); i++) {
- rf_rx_num++;
- rx_pwr[i] = ((pphy_head[PHY_STAT_GAIN_TRSW_SHT + i]
- & 0x3F) * 2) - 110;
- /* Translate DBM to percentage. */
- rssi = query_rx_pwr_percentage(rx_pwr[i]);
- total_rssi += rssi;
- }
- /* (2)PWDB, Average PWDB calculated by hardware (for
- * rate adaptive)
- */
- rx_pwr_all = (((pphy_head[PHY_STAT_PWDB_ALL_SHT]) >> 1) & 0x7f)
- - 106;
- pwdb_all = query_rx_pwr_percentage(rx_pwr_all);
-
- {
- /* (3)EVM of HT rate */
- if (prframe->u.hdr.attrib.htc &&
- prframe->u.hdr.attrib.mcs_rate >= 20 &&
- prframe->u.hdr.attrib.mcs_rate <= 27) {
- /* both spatial stream make sense */
- max_spatial_stream = 2;
- } else {
- /* only spatial stream 1 makes sense */
- max_spatial_stream = 1;
- }
- for (i = 0; i < max_spatial_stream; i++) {
- evm = evm_db2percentage((pphy_head
- [PHY_STAT_RXEVM_SHT + i]));/*dbm*/
- prframe->u.hdr.attrib.signal_qual =
- (u8)(evm & 0xff);
- prframe->u.hdr.attrib.rx_mimo_signal_qual[i] =
- (u8)(evm & 0xff);
- }
- }
- }
- /* UI BSS List signal strength(in percentage), make it good looking,
- * from 0~100. It is assigned to the BSS List in
- * GetValueFromBeaconOrProbeRsp().
- */
- if (bcck_rate) {
- prframe->u.hdr.attrib.signal_strength =
- (u8)r8712_signal_scale_mapping(pwdb_all);
- } else {
- if (rf_rx_num != 0)
- prframe->u.hdr.attrib.signal_strength =
- (u8)(r8712_signal_scale_mapping(total_rssi /=
- rf_rx_num));
- }
-}
-
-static void process_link_qual(struct _adapter *padapter,
- union recv_frame *prframe)
-{
- u32 last_evm = 0, avg_val;
- struct rx_pkt_attrib *pattrib;
- struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data;
-
- if (!prframe || !padapter)
- return;
- pattrib = &prframe->u.hdr.attrib;
- if (pattrib->signal_qual != 0) {
- /*
- * 1. Record the general EVM to the sliding window.
- */
- if (sqd->total_num++ >= PHY_LINKQUALITY_SLID_WIN_MAX) {
- sqd->total_num = PHY_LINKQUALITY_SLID_WIN_MAX;
- last_evm = sqd->elements[sqd->index];
- sqd->total_val -= last_evm;
- }
- sqd->total_val += pattrib->signal_qual;
- sqd->elements[sqd->index++] = pattrib->signal_qual;
- if (sqd->index >= PHY_LINKQUALITY_SLID_WIN_MAX)
- sqd->index = 0;
-
- /* <1> Showed on UI for user, in percentage. */
- avg_val = sqd->total_val / sqd->total_num;
- padapter->recvpriv.signal = (u8)avg_val;
- }
-}
-
-static void process_rssi(struct _adapter *padapter, union recv_frame *prframe)
-{
- u32 last_rssi, tmp_val;
- struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
- struct smooth_rssi_data *ssd = &padapter->recvpriv.signal_strength_data;
-
- if (ssd->total_num++ >= PHY_RSSI_SLID_WIN_MAX) {
- ssd->total_num = PHY_RSSI_SLID_WIN_MAX;
- last_rssi = ssd->elements[ssd->index];
- ssd->total_val -= last_rssi;
- }
- ssd->total_val += pattrib->signal_strength;
- ssd->elements[ssd->index++] = pattrib->signal_strength;
- if (ssd->index >= PHY_RSSI_SLID_WIN_MAX)
- ssd->index = 0;
- tmp_val = ssd->total_val / ssd->total_num;
- padapter->recvpriv.rssi = (s8)translate2dbm(padapter, (u8)tmp_val);
-}
-
-static void process_phy_info(struct _adapter *padapter,
- union recv_frame *prframe)
-{
- query_rx_phy_status(padapter, prframe);
- process_rssi(padapter, prframe);
- process_link_qual(padapter, prframe);
-}
-
-int recv_func(struct _adapter *padapter, void *pcontext)
-{
- struct rx_pkt_attrib *pattrib;
- union recv_frame *prframe, *orig_prframe;
- int retval = _SUCCESS;
- struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- prframe = pcontext;
- orig_prframe = prframe;
- pattrib = &prframe->u.hdr.attrib;
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- if (pattrib->crc_err == 1)
- padapter->mppriv.rx_crcerrpktcount++;
- else
- padapter->mppriv.rx_pktcount++;
- if (!check_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE)) {
- /* free this recv_frame */
- r8712_free_recvframe(orig_prframe, pfree_recv_queue);
- goto _exit_recv_func;
- }
- }
- /* check the frame crtl field and decache */
- retval = r8712_validate_recv_frame(padapter, prframe);
- if (retval != _SUCCESS) {
- /* free this recv_frame */
- r8712_free_recvframe(orig_prframe, pfree_recv_queue);
- goto _exit_recv_func;
- }
- process_phy_info(padapter, prframe);
- prframe = r8712_decryptor(padapter, prframe);
- if (!prframe) {
- retval = _FAIL;
- goto _exit_recv_func;
- }
- prframe = r8712_recvframe_chk_defrag(padapter, prframe);
- if (!prframe)
- goto _exit_recv_func;
- prframe = r8712_portctrl(padapter, prframe);
- if (!prframe) {
- retval = _FAIL;
- goto _exit_recv_func;
- }
- retval = r8712_process_recv_indicatepkts(padapter, prframe);
- if (retval != _SUCCESS) {
- r8712_free_recvframe(orig_prframe, pfree_recv_queue);
- goto _exit_recv_func;
- }
-_exit_recv_func:
- return retval;
-}
-
-static void recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb)
-{
- u8 *pbuf, shift_sz = 0;
- u8 frag, mf;
- uint pkt_len;
- u32 transfer_len;
- struct recv_stat *prxstat;
- u16 pkt_cnt, drvinfo_sz, pkt_offset, tmp_len, alloc_sz;
- struct __queue *pfree_recv_queue;
- _pkt *pkt_copy = NULL;
- union recv_frame *precvframe = NULL;
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- pfree_recv_queue = &precvpriv->free_recv_queue;
- pbuf = pskb->data;
- prxstat = (struct recv_stat *)pbuf;
- pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
- pkt_len = le32_to_cpu(prxstat->rxdw0) & 0x00003fff;
- transfer_len = pskb->len;
- /* Test throughput with Netgear 3700 (No security) with Chariot 3T3R
- * pairs. The packet count will be a big number so that the containing
- * packet will effect the Rx reordering.
- */
- if (transfer_len < pkt_len) {
- /* In this case, it means the MAX_RECVBUF_SZ is too small to
- * get the data from 8712u.
- */
- return;
- }
- do {
- prxstat = (struct recv_stat *)pbuf;
- pkt_len = le32_to_cpu(prxstat->rxdw0) & 0x00003fff;
- /* more fragment bit */
- mf = (le32_to_cpu(prxstat->rxdw1) >> 27) & 0x1;
- /* ragmentation number */
- frag = (le32_to_cpu(prxstat->rxdw2) >> 12) & 0xf;
- /* uint 2^3 = 8 bytes */
- drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16;
- drvinfo_sz <<= 3;
- if (pkt_len <= 0)
- return;
- /* Qos data, wireless lan header length is 26 */
- if ((le32_to_cpu(prxstat->rxdw0) >> 23) & 0x01)
- shift_sz = 2;
- precvframe = r8712_alloc_recvframe(pfree_recv_queue);
- if (!precvframe)
- return;
- INIT_LIST_HEAD(&precvframe->u.hdr.list);
- precvframe->u.hdr.precvbuf = NULL; /*can't access the precvbuf*/
- precvframe->u.hdr.len = 0;
- tmp_len = pkt_len + drvinfo_sz + RXDESC_SIZE;
- pkt_offset = (u16)round_up(tmp_len, 128);
- /* for first fragment packet, driver need allocate 1536 +
- * drvinfo_sz + RXDESC_SIZE to defrag packet.
- */
- if ((mf == 1) && (frag == 0))
- /*1658+6=1664, 1664 is 128 alignment.*/
- alloc_sz = max_t(u16, tmp_len, 1658);
- else
- alloc_sz = tmp_len;
- /* 2 is for IP header 4 bytes alignment in QoS packet case.
- * 4 is for skb->data 4 bytes alignment.
- */
- alloc_sz += 6;
- pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz);
- if (!pkt_copy)
- return;
-
- precvframe->u.hdr.pkt = pkt_copy;
- skb_reserve(pkt_copy, 4 - ((addr_t)(pkt_copy->data) % 4));
- skb_reserve(pkt_copy, shift_sz);
- memcpy(pkt_copy->data, pbuf, tmp_len);
- precvframe->u.hdr.rx_head = pkt_copy->data;
- precvframe->u.hdr.rx_data = pkt_copy->data;
- precvframe->u.hdr.rx_tail = pkt_copy->data;
- precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz;
-
- recvframe_put(precvframe, tmp_len);
- recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
- /* because the endian issue, driver avoid reference to the
- * rxstat after calling update_recvframe_attrib_from_recvstat();
- */
- update_recvframe_attrib_from_recvstat(&precvframe->u.hdr.attrib,
- prxstat);
- r8712_recv_entry(precvframe);
- transfer_len -= pkt_offset;
- pbuf += pkt_offset;
- pkt_cnt--;
- precvframe = NULL;
- pkt_copy = NULL;
- } while ((transfer_len > 0) && pkt_cnt > 0);
-}
-
-static void recv_tasklet(struct tasklet_struct *t)
-{
- struct sk_buff *pskb;
- struct _adapter *padapter = from_tasklet(padapter, t,
- recvpriv.recv_tasklet);
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
- recvbuf2recvframe(padapter, pskb);
- skb_reset_tail_pointer(pskb);
- pskb->len = 0;
- if (!skb_cloned(pskb))
- skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
- else
- consume_skb(pskb);
- }
-}
diff --git a/drivers/staging/rtl8712/rtl8712_recv.h b/drivers/staging/rtl8712/rtl8712_recv.h
deleted file mode 100644
index a1360dcf91ce..000000000000
--- a/drivers/staging/rtl8712/rtl8712_recv.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL8712_RECV_H_
-#define _RTL8712_RECV_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-/* Realtek's v2.6.6 reduced this to 4. However, under heavy network and CPU
- * loads, even 8 receive buffers might not be enough; cutting it to 4 seemed
- * unwise.
- */
-#define NR_RECVBUFF (8)
-
-#define NR_PREALLOC_RECV_SKB (8)
-#define RXDESC_SIZE 24
-#define RXDESC_OFFSET RXDESC_SIZE
-#define RECV_BLK_SZ 512
-#define RECV_BLK_CNT 16
-#define RECV_BLK_TH RECV_BLK_CNT
-#define MAX_RECVBUF_SZ 9100
-#define RECVBUFF_ALIGN_SZ 512
-#define RSVD_ROOM_SZ (0)
-/*These definition is used for Rx packet reordering.*/
-#define SN_LESS(a, b) (((a-b) & 0x800) != 0)
-#define SN_EQUAL(a, b) (a == b)
-#define REORDER_WAIT_TIME 30 /* (ms)*/
-
-struct recv_stat {
- __le32 rxdw0;
- __le32 rxdw1;
- __le32 rxdw2;
- __le32 rxdw3;
- __le32 rxdw4;
- __le32 rxdw5;
-};
-
-struct phy_cck_rx_status {
- /* For CCK rate descriptor. This is a unsigned 8:1 variable.
- * LSB bit present 0.5. And MSB 7 bts present a signed value.
- * Range from -64~+63.5.
- */
- u8 adc_pwdb_X[4];
- u8 sq_rpt;
- u8 cck_agc_rpt;
-};
-
-struct phy_stat {
- __le32 phydw0;
- __le32 phydw1;
- __le32 phydw2;
- __le32 phydw3;
- __le32 phydw4;
- __le32 phydw5;
- __le32 phydw6;
- __le32 phydw7;
-};
-
-#define PHY_STAT_GAIN_TRSW_SHT 0
-#define PHY_STAT_PWDB_ALL_SHT 4
-#define PHY_STAT_CFOSHO_SHT 5
-#define PHY_STAT_CCK_AGC_RPT_SHT 5
-#define PHY_STAT_CFOTAIL_SHT 9
-#define PHY_STAT_RXEVM_SHT 13
-#define PHY_STAT_RXSNR_SHT 15
-#define PHY_STAT_PDSNR_SHT 19
-#define PHY_STAT_CSI_CURRENT_SHT 21
-#define PHY_STAT_CSI_TARGET_SHT 23
-#define PHY_STAT_SIGEVM_SHT 25
-#define PHY_STAT_MAX_EX_PWR_SHT 26
-
-union recvstat {
- struct recv_stat recv_stat;
- unsigned int value[RXDESC_SIZE >> 2];
-};
-
-struct recv_buf {
- struct list_head list;
- spinlock_t recvbuf_lock;
- u32 ref_cnt;
- struct _adapter *adapter;
- struct urb *purb;
- _pkt *pskb;
- u8 irp_pending;
- u32 transfer_len;
- uint len;
- u8 *phead;
- u8 *pdata;
- u8 *ptail;
- u8 *pend;
- u8 *pbuf;
- u8 *pallocated_buf;
-};
-
-/*
- * head ----->
- * data ----->
- * payload
- * tail ----->
- * end ----->
- * len = (unsigned int )(tail - data);
- */
-struct recv_frame_hdr {
- struct list_head list;
- _pkt *pkt;
- _pkt *pkt_newalloc;
- struct _adapter *adapter;
- u8 fragcnt;
- struct rx_pkt_attrib attrib;
- uint len;
- u8 *rx_head;
- u8 *rx_data;
- u8 *rx_tail;
- u8 *rx_end;
- void *precvbuf;
- struct sta_info *psta;
- /*for A-MPDU Rx reordering buffer control*/
- struct recv_reorder_ctrl *preorder_ctrl;
-};
-
-union recv_frame {
- union {
- struct list_head list;
- struct recv_frame_hdr hdr;
- } u;
-};
-
-void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf);
-void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf);
-s32 r8712_signal_scale_mapping(s32 cur_sig);
-void r8712_reordering_ctrl_timeout_handler(void *pcontext);
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl8712_regdef.h b/drivers/staging/rtl8712/rtl8712_regdef.h
deleted file mode 100644
index 28aec9aa539f..000000000000
--- a/drivers/staging/rtl8712/rtl8712_regdef.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_REGDEF_H__
-#define __RTL8712_REGDEF_H__
-
-#include "rtl8712_syscfg_regdef.h"
-#include "rtl8712_cmdctrl_regdef.h"
-#include "rtl8712_macsetting_regdef.h"
-#include "rtl8712_timectrl_regdef.h"
-#include "rtl8712_fifoctrl_regdef.h"
-#include "rtl8712_ratectrl_regdef.h"
-#include "rtl8712_edcasetting_regdef.h"
-#include "rtl8712_wmac_regdef.h"
-#include "rtl8712_powersave_regdef.h"
-#include "rtl8712_gp_regdef.h"
-#include "rtl8712_debugctrl_regdef.h"
-
-#define HIMR (RTL8712_INTERRUPT_ + 0x08)
-
-#endif /* __RTL8712_REGDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_security_bitdef.h b/drivers/staging/rtl8712/rtl8712_security_bitdef.h
deleted file mode 100644
index 44275ef455a0..000000000000
--- a/drivers/staging/rtl8712/rtl8712_security_bitdef.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_SECURITY_BITDEF_H__
-#define __RTL8712_SECURITY_BITDEF_H__
-
-/*CAMCMD*/
-#define _SECCAM_POLLING BIT(31)
-#define _SECCAM_CLR BIT(30)
-#define _SECCAM_WE BIT(16)
-#define _SECCAM_ADR_MSK 0x000000FF
-#define _SECCAM_ADR_SHT 0
-
-/*CAMDBG*/
-#define _SECCAM_INFO BIT(31)
-#define _SEC_KEYFOUND BIT(30)
-#define _SEC_CONFIG_MSK 0x3F000000
-#define _SEC_CONFIG_SHT 24
-#define _SEC_KEYCONTENT_MSK 0x00FFFFFF
-#define _SEC_KEYCONTENT_SHT 0
-
-/*SECCFG*/
-#define _NOSKMC BIT(5)
-#define _SKBYA2 BIT(4)
-#define _RXDEC BIT(3)
-#define _TXENC BIT(2)
-#define _RXUSEDK BIT(1)
-#define _TXUSEDK BIT(0)
-
-#endif /*__RTL8712_SECURITY_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_spec.h b/drivers/staging/rtl8712/rtl8712_spec.h
deleted file mode 100644
index 613a410e5714..000000000000
--- a/drivers/staging/rtl8712/rtl8712_spec.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_SPEC_H__
-#define __RTL8712_SPEC_H__
-
-#define RTL8712_IOBASE_TXPKT 0x10200000 /*IOBASE_TXPKT*/
-#define RTL8712_IOBASE_RXPKT 0x10210000 /*IOBASE_RXPKT*/
-#define RTL8712_IOBASE_RXCMD 0x10220000 /*IOBASE_RXCMD*/
-#define RTL8712_IOBASE_TXSTATUS 0x10230000 /*IOBASE_TXSTATUS*/
-#define RTL8712_IOBASE_RXSTATUS 0x10240000 /*IOBASE_RXSTATUS*/
-#define RTL8712_IOBASE_IOREG 0x10250000 /*IOBASE_IOREG ADDR*/
-#define RTL8712_IOBASE_SCHEDULER 0x10260000 /*IOBASE_SCHEDULE*/
-
-#define RTL8712_IOBASE_TRXDMA 0x10270000 /*IOBASE_TRXDMA*/
-#define RTL8712_IOBASE_TXLLT 0x10280000 /*IOBASE_TXLLT*/
-#define RTL8712_IOBASE_WMAC 0x10290000 /*IOBASE_WMAC*/
-#define RTL8712_IOBASE_FW2HW 0x102A0000 /*IOBASE_FW2HW*/
-#define RTL8712_IOBASE_ACCESS_PHYREG 0x102B0000 /*IOBASE_ACCESS_PHYREG*/
-
-#define RTL8712_IOBASE_FF 0x10300000 /*IOBASE_FIFO 0x1031000~0x103AFFFF*/
-
-/*IOREG Offset for 8712*/
-#define RTL8712_SYSCFG_ RTL8712_IOBASE_IOREG
-#define RTL8712_CMDCTRL_ (RTL8712_IOBASE_IOREG + 0x40)
-#define RTL8712_MACIDSETTING_ (RTL8712_IOBASE_IOREG + 0x50)
-#define RTL8712_TIMECTRL_ (RTL8712_IOBASE_IOREG + 0x80)
-#define RTL8712_FIFOCTRL_ (RTL8712_IOBASE_IOREG + 0xA0)
-#define RTL8712_RATECTRL_ (RTL8712_IOBASE_IOREG + 0x160)
-#define RTL8712_EDCASETTING_ (RTL8712_IOBASE_IOREG + 0x1D0)
-#define RTL8712_WMAC_ (RTL8712_IOBASE_IOREG + 0x200)
-#define RTL8712_SECURITY_ (RTL8712_IOBASE_IOREG + 0x240)
-#define RTL8712_POWERSAVE_ (RTL8712_IOBASE_IOREG + 0x260)
-#define RTL8712_GP_ (RTL8712_IOBASE_IOREG + 0x2E0)
-#define RTL8712_INTERRUPT_ (RTL8712_IOBASE_IOREG + 0x300)
-#define RTL8712_DEBUGCTRL_ (RTL8712_IOBASE_IOREG + 0x310)
-#define RTL8712_OFFLOAD_ (RTL8712_IOBASE_IOREG + 0x2D0)
-
-/*FIFO for 8712*/
-#define RTL8712_DMA_BCNQ (RTL8712_IOBASE_FF + 0x10000)
-#define RTL8712_DMA_MGTQ (RTL8712_IOBASE_FF + 0x20000)
-#define RTL8712_DMA_BMCQ (RTL8712_IOBASE_FF + 0x30000)
-#define RTL8712_DMA_VOQ (RTL8712_IOBASE_FF + 0x40000)
-#define RTL8712_DMA_VIQ (RTL8712_IOBASE_FF + 0x50000)
-#define RTL8712_DMA_BEQ (RTL8712_IOBASE_FF + 0x60000)
-#define RTL8712_DMA_BKQ (RTL8712_IOBASE_FF + 0x70000)
-#define RTL8712_DMA_RX0FF (RTL8712_IOBASE_FF + 0x80000)
-#define RTL8712_DMA_H2CCMD (RTL8712_IOBASE_FF + 0x90000)
-#define RTL8712_DMA_C2HCMD (RTL8712_IOBASE_FF + 0xA0000)
-
-/*------------------------------*/
-
-/*BIT 16 15*/
-#define DID_SDIO_LOCAL 0 /* 0 0*/
-#define DID_WLAN_IOREG 1 /* 0 1*/
-#define DID_WLAN_FIFO 3 /* 1 1*/
-#define DID_UNDEFINE (-1)
-
-#define CMD_ADDR_MAPPING_SHIFT 2 /*SDIO CMD ADDR MAPPING,
- *shift 2 bit for match
- * offset[14:2]
- */
-
-/*Offset for SDIO LOCAL*/
-#define OFFSET_SDIO_LOCAL 0x0FFF
-
-/*Offset for WLAN IOREG*/
-#define OFFSET_WLAN_IOREG 0x0FFF
-
-/*Offset for WLAN FIFO*/
-#define OFFSET_TX_BCNQ 0x0300
-#define OFFSET_TX_HIQ 0x0310
-#define OFFSET_TX_CMDQ 0x0320
-#define OFFSET_TX_MGTQ 0x0330
-#define OFFSET_TX_HCCAQ 0x0340
-#define OFFSET_TX_VOQ 0x0350
-#define OFFSET_TX_VIQ 0x0360
-#define OFFSET_TX_BEQ 0x0370
-#define OFFSET_TX_BKQ 0x0380
-#define OFFSET_RX_RX0FFQ 0x0390
-#define OFFSET_RX_C2HFFQ 0x03A0
-
-#define BK_QID_01 1
-#define BK_QID_02 2
-#define BE_QID_01 0
-#define BE_QID_02 3
-#define VI_QID_01 4
-#define VI_QID_02 5
-#define VO_QID_01 6
-#define VO_QID_02 7
-#define HCCA_QID_01 8
-#define HCCA_QID_02 9
-#define HCCA_QID_03 10
-#define HCCA_QID_04 11
-#define HCCA_QID_05 12
-#define HCCA_QID_06 13
-#define HCCA_QID_07 14
-#define HCCA_QID_08 15
-#define HI_QID 17
-#define CMD_QID 19
-#define MGT_QID 18
-#define BCN_QID 16
-
-#include "rtl8712_regdef.h"
-
-#include "rtl8712_bitdef.h"
-
-#include "basic_types.h"
-
-#endif /* __RTL8712_SPEC_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h b/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h
deleted file mode 100644
index d92df3fbd2b1..000000000000
--- a/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_SYSCFG_BITDEF_H__
-#define __RTL8712_SYSCFG_BITDEF_H__
-
-/*SYS_PWR_CTRL*/
-/*SRCTRL0*/
-/*SRCTRL1*/
-/*SYS_CLKR*/
-
-/*SYS_IOS_CTRL*/
-#define iso_LDR2RP_SHT 8 /* EE Loader to Retention Path*/
-#define iso_LDR2RP BIT(iso_LDR2RP_SHT) /* 1:isolation, 0:attach*/
-
-/*SYS_CTRL*/
-#define FEN_DIO_SDIO_SHT 0
-#define FEN_DIO_SDIO BIT(FEN_DIO_SDIO_SHT)
-#define FEN_SDIO_SHT 1
-#define FEN_SDIO BIT(FEN_SDIO_SHT)
-#define FEN_USBA_SHT 2
-#define FEN_USBA BIT(FEN_USBA_SHT)
-#define FEN_UPLL_SHT 3
-#define FEN_UPLL BIT(FEN_UPLL_SHT)
-#define FEN_USBD_SHT 4
-#define FEN_USBD BIT(FEN_USBD_SHT)
-#define FEN_DIO_PCIE_SHT 5
-#define FEN_DIO_PCIE BIT(FEN_DIO_PCIE_SHT)
-#define FEN_PCIEA_SHT 6
-#define FEN_PCIEA BIT(FEN_PCIEA_SHT)
-#define FEN_PPLL_SHT 7
-#define FEN_PPLL BIT(FEN_PPLL_SHT)
-#define FEN_PCIED_SHT 8
-#define FEN_PCIED BIT(FEN_PCIED_SHT)
-#define FEN_CPUEN_SHT 10
-#define FEN_CPUEN BIT(FEN_CPUEN_SHT)
-#define FEN_DCORE_SHT 11
-#define FEN_DCORE BIT(FEN_DCORE_SHT)
-#define FEN_ELDR_SHT 12
-#define FEN_ELDR BIT(FEN_ELDR_SHT)
-#define PWC_DV2LDR_SHT 13
-#define PWC_DV2LDR BIT(PWC_DV2LDR_SHT) /* Loader Power Enable*/
-
-/*=== SYS_CLKR ===*/
-#define SYS_CLKSEL_SHT 0
-#define SYS_CLKSEL BIT(SYS_CLKSEL_SHT) /* System Clock 80MHz*/
-#define PS_CLKSEL_SHT 1
-#define PS_CLKSEL BIT(PS_CLKSEL_SHT) /*System power save
- * clock select.
- */
-#define CPU_CLKSEL_SHT 2
-#define CPU_CLKSEL BIT(CPU_CLKSEL_SHT) /* System Clock select,
- * 1: AFE source,
- * 0: System clock(L-Bus)
- */
-#define INT32K_EN_SHT 3
-#define INT32K_EN BIT(INT32K_EN_SHT)
-#define MACSLP_SHT 4
-#define MACSLP BIT(MACSLP_SHT)
-#define MAC_CLK_EN_SHT 11
-#define MAC_CLK_EN BIT(MAC_CLK_EN_SHT) /* MAC Clock Enable.*/
-#define SYS_CLK_EN_SHT 12
-#define SYS_CLK_EN BIT(SYS_CLK_EN_SHT)
-#define RING_CLK_EN_SHT 13
-#define RING_CLK_EN BIT(RING_CLK_EN_SHT)
-#define SWHW_SEL_SHT 14
-#define SWHW_SEL BIT(SWHW_SEL_SHT) /* Load done,
- * control path switch.
- */
-#define FWHW_SEL_SHT 15
-#define FWHW_SEL BIT(FWHW_SEL_SHT) /* Sleep exit,
- * control path switch.
- */
-
-/*9346CR*/
-#define _VPDIDX_MSK 0xFF00
-#define _VPDIDX_SHT 8
-#define _EEM_MSK 0x00C0
-#define _EEM_SHT 6
-#define _EEM0 BIT(6)
-#define _EEM1 BIT(7)
-#define _EEPROM_EN BIT(5)
-#define _9356SEL BIT(4)
-#define _EECS BIT(3)
-#define _EESK BIT(2)
-#define _EEDI BIT(1)
-#define _EEDO BIT(0)
-
-/*AFE_MISC*/
-#define AFE_MISC_USB_MBEN_SHT 7
-#define AFE_MISC_USB_MBEN BIT(AFE_MISC_USB_MBEN_SHT)
-#define AFE_MISC_USB_BGEN_SHT 6
-#define AFE_MISC_USB_BGEN BIT(AFE_MISC_USB_BGEN_SHT)
-#define AFE_MISC_LD12_VDAJ_SHT 4
-#define AFE_MISC_LD12_VDAJ_MSK 0X0030
-#define AFE_MISC_LD12_VDAJ BIT(AFE_MISC_LD12_VDAJ_SHT)
-#define AFE_MISC_I32_EN_SHT 3
-#define AFE_MISC_I32_EN BIT(AFE_MISC_I32_EN_SHT)
-#define AFE_MISC_E32_EN_SHT 2
-#define AFE_MISC_E32_EN BIT(AFE_MISC_E32_EN_SHT)
-#define AFE_MISC_MBEN_SHT 1
-#define AFE_MISC_MBEN BIT(AFE_MISC_MBEN_SHT)/* Enable AFE Macro
- * Block's Mbias.
- */
-#define AFE_MISC_BGEN_SHT 0
-#define AFE_MISC_BGEN BIT(AFE_MISC_BGEN_SHT)/* Enable AFE Macro
- * Block's Bandgap.
- */
-
-/*--------------------------------------------------------------------------*/
-/* SPS1_CTRL bits (Offset 0x18-1E, 56bits)*/
-/*--------------------------------------------------------------------------*/
-#define SPS1_SWEN BIT(1) /* Enable vsps18 SW Macro Block.*/
-#define SPS1_LDEN BIT(0) /* Enable VSPS12 LDO Macro block.*/
-
-/*----------------------------------------------------------------------------*/
-/* LDOA15_CTRL bits (Offset 0x20, 8bits)*/
-/*----------------------------------------------------------------------------*/
-#define LDA15_EN BIT(0) /* Enable LDOA15 Macro Block*/
-
-/*----------------------------------------------------------------------------*/
-/* 8192S LDOV12D_CTRL bit (Offset 0x21, 8bits)*/
-/*----------------------------------------------------------------------------*/
-#define LDV12_EN BIT(0) /* Enable LDOVD12 Macro Block*/
-#define LDV12_SDBY BIT(1) /* LDOVD12 standby mode*/
-
-/*CLK_PS_CTRL*/
-#define _CLK_GATE_EN BIT(0)
-
-/* EFUSE_CTRL*/
-#define EF_FLAG BIT(31) /* Access Flag, Write:1;
- * Read:0
- */
-#define EF_PGPD 0x70000000 /* E-fuse Program time*/
-#define EF_RDT 0x0F000000 /* E-fuse read time: in the
- * unit of cycle time
- */
-#define EF_PDN_EN BIT(19) /* EFuse Power down enable*/
-#define ALD_EN BIT(18) /* Autoload Enable*/
-#define EF_ADDR 0x0003FF00 /* Access Address*/
-#define EF_DATA 0x000000FF /* Access Data*/
-
-/* EFUSE_TEST*/
-#define LDOE25_EN BIT(31) /* Enable LDOE25 Macro Block*/
-
-/* EFUSE_CLK_CTRL*/
-#define EFUSE_CLK_EN BIT(1) /* E-Fuse Clock Enable*/
-#define EFUSE_CLK_SEL BIT(0) /* E-Fuse Clock Select,
- * 0:500K, 1:40M
- */
-
-#endif /*__RTL8712_SYSCFG_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h b/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h
deleted file mode 100644
index da5efcdedabe..000000000000
--- a/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_SYSCFG_REGDEF_H__
-#define __RTL8712_SYSCFG_REGDEF_H__
-
-#define SYS_ISO_CTRL (RTL8712_SYSCFG_ + 0x0000)
-#define SYS_FUNC_EN (RTL8712_SYSCFG_ + 0x0002)
-#define PMC_FSM (RTL8712_SYSCFG_ + 0x0004)
-#define SYS_CLKR (RTL8712_SYSCFG_ + 0x0008)
-#define EE_9346CR (RTL8712_SYSCFG_ + 0x000A)
-#define EE_VPD (RTL8712_SYSCFG_ + 0x000C)
-#define AFE_MISC (RTL8712_SYSCFG_ + 0x0010)
-#define SPS0_CTRL (RTL8712_SYSCFG_ + 0x0011)
-#define SPS1_CTRL (RTL8712_SYSCFG_ + 0x0018)
-#define RF_CTRL (RTL8712_SYSCFG_ + 0x001F)
-#define LDOA15_CTRL (RTL8712_SYSCFG_ + 0x0020)
-#define LDOV12D_CTRL (RTL8712_SYSCFG_ + 0x0021)
-#define LDOHCI12_CTRL (RTL8712_SYSCFG_ + 0x0022)
-#define LDO_USB_CTRL (RTL8712_SYSCFG_ + 0x0023)
-#define LPLDO_CTRL (RTL8712_SYSCFG_ + 0x0024)
-#define AFE_XTAL_CTRL (RTL8712_SYSCFG_ + 0x0026)
-#define AFE_PLL_CTRL (RTL8712_SYSCFG_ + 0x0028)
-#define EFUSE_CTRL (RTL8712_SYSCFG_ + 0x0030)
-#define EFUSE_TEST (RTL8712_SYSCFG_ + 0x0034)
-#define PWR_DATA (RTL8712_SYSCFG_ + 0x0038)
-#define DPS_TIMER (RTL8712_SYSCFG_ + 0x003C)
-#define RCLK_MON (RTL8712_SYSCFG_ + 0x003E)
-#define EFUSE_CLK_CTRL (RTL8712_SYSCFG_ + 0x02F8)
-
-#endif /*__RTL8712_SYSCFG_REGDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h
deleted file mode 100644
index d7bc9dd5cecd..000000000000
--- a/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_TIMECTRL_BITDEF_H__
-#define __RTL8712_TIMECTRL_BITDEF_H__
-
-/*TSFTR*/
-/*SLOT*/
-/*USTIME*/
-
-/*TUBASE*/
-#define _TUBASE_MSK 0x07FF
-
-/*SIFS_CCK*/
-#define _SIFS_CCK_TRX_MSK 0xFF00
-#define _SIFS_CCK_TRX_SHT 0x8
-#define _SIFS_CCK_CTX_MSK 0x00FF
-#define _SIFS_CCK_CTX_SHT 0
-
-/*SIFS_OFDM*/
-#define _SIFS_OFDM_TRX_MSK 0xFF00
-#define _SIFS_OFDM_TRX_SHT 0x8
-#define _SIFS_OFDM_CTX_MSK 0x00FF
-#define _SIFS_OFDM_CTX_SHT 0
-
-/*PIFS*/
-/*ACKTO*/
-/*EIFS*/
-/*BCNITV*/
-/*ATIMWND*/
-
-/*DRVERLYINT*/
-#define _ENSWBCN BIT(15)
-#define _DRVERLY_TU_MSK 0x0FF0
-#define _DRVERLY_TU_SHT 4
-#define _DRVERLY_US_MSK 0x000F
-#define _DRVERLY_US_SHT 0
-
-/*BCNDMATIM*/
-#define _BCNDMATIM_MSK 0x03FF
-
-/*BCNERRTH*/
-/*MLT*/
-
-#endif /* __RTL8712_TIMECTRL_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h b/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h
deleted file mode 100644
index b51603f1b880..000000000000
--- a/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_TIMECTRL_REGDEF_H__
-#define __RTL8712_TIMECTRL_REGDEF_H__
-
-#define TSFTR (RTL8712_TIMECTRL_ + 0x00)
-#define USTIME (RTL8712_TIMECTRL_ + 0x08)
-#define SLOT (RTL8712_TIMECTRL_ + 0x09)
-#define TUBASE (RTL8712_TIMECTRL_ + 0x0A)
-#define SIFS_CCK (RTL8712_TIMECTRL_ + 0x0C)
-#define SIFS_OFDM (RTL8712_TIMECTRL_ + 0x0E)
-#define PIFS (RTL8712_TIMECTRL_ + 0x10)
-#define ACKTO (RTL8712_TIMECTRL_ + 0x11)
-#define EIFS (RTL8712_TIMECTRL_ + 0x12)
-#define BCNITV (RTL8712_TIMECTRL_ + 0x14)
-#define ATIMWND (RTL8712_TIMECTRL_ + 0x16)
-#define DRVERLYINT (RTL8712_TIMECTRL_ + 0x18)
-#define BCNDMATIM (RTL8712_TIMECTRL_ + 0x1A)
-#define BCNERRTH (RTL8712_TIMECTRL_ + 0x1C)
-#define MLT (RTL8712_TIMECTRL_ + 0x1D)
-
-#endif /* __RTL8712_TIMECTRL_REGDEF_H__ */
diff --git a/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h b/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h
deleted file mode 100644
index ea164e482347..000000000000
--- a/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_WMAC_BITDEF_H__
-#define __RTL8712_WMAC_BITDEF_H__
-
-/*NAVCTRL*/
-#define _NAV_UPPER_EN BIT(18)
-#define _NAV_MTO_EN BIT(17)
-#define _NAV_UPPER BIT(16)
-#define _NAV_MTO_MSK 0xFF00
-#define _NAV_MTO_SHT 8
-#define _RTSRST_MSK 0x00FF
-#define _RTSRST_SHT 0
-
-/*BWOPMODE*/
-#define _20MHZBW BIT(2)
-
-/*BACAMCMD*/
-#define _BACAM_POLL BIT(31)
-#define _BACAM_RST BIT(17)
-#define _BACAM_RW BIT(16)
-#define _BACAM_ADDR_MSK 0x0000007F
-#define _BACAM_ADDR_SHT 0
-
-/*LBDLY*/
-#define _LBDLY_MSK 0x1F
-
-/*FWDLY*/
-#define _FWDLY_MSK 0x0F
-
-/*RXERR_RPT*/
-#define _RXERR_RPT_SEL_MSK 0xF0000000
-#define _RXERR_RPT_SEL_SHT 28
-#define _RPT_CNT_MSK 0x000FFFFF
-#define _RPT_CNT_SHT 0
-
-#endif /*__RTL8712_WMAC_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_wmac_regdef.h b/drivers/staging/rtl8712/rtl8712_wmac_regdef.h
deleted file mode 100644
index dfe3e9fbed43..000000000000
--- a/drivers/staging/rtl8712/rtl8712_wmac_regdef.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_WMAC_REGDEF_H__
-#define __RTL8712_WMAC_REGDEF_H__
-
-#define NAVCTRL (RTL8712_WMAC_ + 0x00)
-#define BWOPMODE (RTL8712_WMAC_ + 0x03)
-#define BACAMCMD (RTL8712_WMAC_ + 0x04)
-#define BACAMCONTENT (RTL8712_WMAC_ + 0x08)
-#define LBDLY (RTL8712_WMAC_ + 0x10)
-#define FWDLY (RTL8712_WMAC_ + 0x11)
-#define HWPC_RX_CTRL (RTL8712_WMAC_ + 0x18)
-#define MQ (RTL8712_WMAC_ + 0x20)
-#define MA (RTL8712_WMAC_ + 0x22)
-#define MS (RTL8712_WMAC_ + 0x24)
-#define CLM_RESULT (RTL8712_WMAC_ + 0x27)
-#define NHM_RPI_CNT (RTL8712_WMAC_ + 0x28)
-#define RXERR_RPT (RTL8712_WMAC_ + 0x30)
-#define NAV_PROT_LEN (RTL8712_WMAC_ + 0x34)
-#define CFEND_TH (RTL8712_WMAC_ + 0x36)
-#define AMPDU_MIN_SPACE (RTL8712_WMAC_ + 0x37)
-#define TXOP_STALL_CTRL (RTL8712_WMAC_ + 0x38)
-
-#endif /*__RTL8712_WMAC_REGDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c
deleted file mode 100644
index 12f2fdb1b3cb..000000000000
--- a/drivers/staging/rtl8712/rtl8712_xmit.c
+++ /dev/null
@@ -1,732 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl8712_xmit.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL8712_XMIT_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "wifi.h"
-#include "osdep_intf.h"
-#include "usb_ops.h"
-
-static void dump_xframe(struct _adapter *padapter,
- struct xmit_frame *pxmitframe);
-static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz);
-
-sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag)
-{
- phw_txqueue->ac_tag = ac_tag;
- switch (ac_tag) {
- case BE_QUEUE_INX:
- phw_txqueue->ff_hwaddr = RTL8712_DMA_BEQ;
- break;
- case BK_QUEUE_INX:
- phw_txqueue->ff_hwaddr = RTL8712_DMA_BKQ;
- break;
- case VI_QUEUE_INX:
- phw_txqueue->ff_hwaddr = RTL8712_DMA_VIQ;
- break;
- case VO_QUEUE_INX:
- phw_txqueue->ff_hwaddr = RTL8712_DMA_VOQ;
- break;
- case BMC_QUEUE_INX:
- phw_txqueue->ff_hwaddr = RTL8712_DMA_BEQ;
- break;
- }
- return _SUCCESS;
-}
-
-int r8712_txframes_sta_ac_pending(struct _adapter *padapter,
- struct pkt_attrib *pattrib)
-{
- struct sta_info *psta;
- struct tx_servq *ptxservq;
- int priority = pattrib->priority;
-
- psta = pattrib->psta;
- switch (priority) {
- case 1:
- case 2:
- ptxservq = &psta->sta_xmitpriv.bk_q;
- break;
- case 4:
- case 5:
- ptxservq = &psta->sta_xmitpriv.vi_q;
- break;
- case 6:
- case 7:
- ptxservq = &psta->sta_xmitpriv.vo_q;
- break;
- case 0:
- case 3:
- default:
- ptxservq = &psta->sta_xmitpriv.be_q;
- break;
- }
- return ptxservq->qcnt;
-}
-
-static u32 get_ff_hwaddr(struct xmit_frame *pxmitframe)
-{
- u32 addr = 0;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct _adapter *padapter = pxmitframe->padapter;
- struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
-
- if (pxmitframe->frame_tag == TXAGG_FRAMETAG) {
- addr = RTL8712_DMA_H2CCMD;
- } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
- addr = RTL8712_DMA_MGTQ;
- } else if (pdvobj->nr_endpoint == 6) {
- switch (pattrib->priority) {
- case 0:
- case 3:
- addr = RTL8712_DMA_BEQ;
- break;
- case 1:
- case 2:
- addr = RTL8712_DMA_BKQ;
- break;
- case 4:
- case 5:
- addr = RTL8712_DMA_VIQ;
- break;
- case 6:
- case 7:
- addr = RTL8712_DMA_VOQ;
- break;
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- addr = RTL8712_DMA_H2CCMD;
- break;
- default:
- addr = RTL8712_DMA_BEQ;
- break;
- }
- } else if (pdvobj->nr_endpoint == 4) {
- switch (pattrib->qsel) {
- case 0:
- case 3:
- case 1:
- case 2:
- addr = RTL8712_DMA_BEQ;/*RTL8712_EP_LO;*/
- break;
- case 4:
- case 5:
- case 6:
- case 7:
- addr = RTL8712_DMA_VOQ;/*RTL8712_EP_HI;*/
- break;
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- addr = RTL8712_DMA_H2CCMD;
- break;
- default:
- addr = RTL8712_DMA_BEQ;/*RTL8712_EP_LO;*/
- break;
- }
- }
- return addr;
-}
-
-static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv,
- struct hw_xmit *phwxmit, struct tx_servq *ptxservq,
- struct __queue *pframe_queue)
-{
- struct list_head *xmitframe_plist, *xmitframe_phead;
- struct xmit_frame *pxmitframe = NULL;
-
- xmitframe_phead = &pframe_queue->queue;
- xmitframe_plist = xmitframe_phead->next;
- if (!end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
- pxmitframe = container_of(xmitframe_plist,
- struct xmit_frame, list);
- list_del_init(&pxmitframe->list);
- ptxservq->qcnt--;
- phwxmit->txcmdcnt++;
- }
- return pxmitframe;
-}
-
-static struct xmit_frame *dequeue_xframe_ex(struct xmit_priv *pxmitpriv,
- struct hw_xmit *phwxmit_i, sint entry)
-{
- unsigned long irqL0;
- struct list_head *sta_plist, *sta_phead;
- struct hw_xmit *phwxmit;
- struct tx_servq *ptxservq = NULL;
- struct __queue *pframe_queue = NULL;
- struct xmit_frame *pxmitframe = NULL;
- int i, inx[4];
- int j, acirp_cnt[4];
-
- /*entry indx: 0->vo, 1->vi, 2->be, 3->bk.*/
- inx[0] = 0; acirp_cnt[0] = pxmitpriv->voq_cnt;
- inx[1] = 1; acirp_cnt[1] = pxmitpriv->viq_cnt;
- inx[2] = 2; acirp_cnt[2] = pxmitpriv->beq_cnt;
- inx[3] = 3; acirp_cnt[3] = pxmitpriv->bkq_cnt;
- for (i = 0; i < 4; i++) {
- for (j = i + 1; j < 4; j++) {
- if (acirp_cnt[j] < acirp_cnt[i]) {
- swap(acirp_cnt[i], acirp_cnt[j]);
- swap(inx[i], inx[j]);
- }
- }
- }
- spin_lock_irqsave(&pxmitpriv->lock, irqL0);
- for (i = 0; i < entry; i++) {
- phwxmit = phwxmit_i + inx[i];
- sta_phead = &phwxmit->sta_queue->queue;
- sta_plist = sta_phead->next;
- while (!end_of_queue_search(sta_phead, sta_plist)) {
- ptxservq = container_of(sta_plist, struct tx_servq, tx_pending);
- pframe_queue = &ptxservq->sta_pending;
- pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq,
- pframe_queue);
- if (pxmitframe) {
- phwxmit->accnt--;
- goto exit_dequeue_xframe_ex;
- }
- sta_plist = sta_plist->next;
- /*Remove sta node when there are no pending packets.*/
- if (list_empty(&pframe_queue->queue)) {
- /* must be done after sta_plist->next
- * and before break
- */
- list_del_init(&ptxservq->tx_pending);
- }
- }
- }
-exit_dequeue_xframe_ex:
- spin_unlock_irqrestore(&pxmitpriv->lock, irqL0);
- return pxmitframe;
-}
-
-void r8712_do_queue_select(struct _adapter *padapter, struct pkt_attrib *pattrib)
-{
- unsigned int qsel = 0;
- struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
-
- if (pdvobj->nr_endpoint == 6) {
- qsel = (unsigned int)pattrib->priority;
- } else if (pdvobj->nr_endpoint == 4) {
- qsel = (unsigned int)pattrib->priority;
- if (qsel == 0 || qsel == 3)
- qsel = 3;
- else if (qsel == 1 || qsel == 2)
- qsel = 1;
- else if (qsel == 4 || qsel == 5)
- qsel = 5;
- else if (qsel == 6 || qsel == 7)
- qsel = 7;
- else
- qsel = 3;
- }
- pattrib->qsel = qsel;
-}
-
-#ifdef CONFIG_R8712_TX_AGGR
-void r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf)
-{
- struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf;
-
- /* Fill up TxCmd Descriptor according as USB FW Tx Aggregation info.*/
- /* dw0 */
- ptx_desc->txdw0 = cpu_to_le32(CMD_HDR_SZ & 0xffff);
- ptx_desc->txdw0 |=
- cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) &
- 0x00ff0000);
- ptx_desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
-
- /* dw1 */
- ptx_desc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 0x00001f00);
-}
-
-void r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf)
-{
- struct xmit_frame *pxmitframe = (struct xmit_frame *)
- pxmitbuf->priv_data;
- struct _adapter *padapter = pxmitframe->padapter;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *)
- (pxmitbuf->pbuf + TXDESC_SIZE);
-
- /* Fill up Cmd Header for USB FW Tx Aggregation.*/
- /* dw0 */
- pcmd_hdr->cmd_dw0 = cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU) << 16) |
- (pcmdpriv->cmd_seq << 24));
- pcmdpriv->cmd_seq++;
-}
-
-void r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf,
- struct xmit_frame *pxmitframe)
-{
- struct _adapter *padapter = pxmitframe->padapter;
- struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf;
- int last_txcmdsz = 0;
- int padding_sz = 0;
-
- /* 802.3->802.11 converter */
- r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
- /* free skb struct */
- r8712_xmit_complete(padapter, pxmitframe);
- if (pxmitframe->attrib.ether_type != 0x0806) {
- if ((pxmitframe->attrib.ether_type != 0x888e) &&
- (pxmitframe->attrib.dhcp_pkt != 1)) {
- r8712_issue_addbareq_cmd(padapter, pxmitframe->attrib.priority);
- }
- }
- pxmitframe->last[0] = 1;
- update_txdesc(pxmitframe, (uint *)(pxmitframe->buf_addr), pxmitframe->attrib.last_txcmdsz);
- /*padding zero */
- last_txcmdsz = pxmitframe->attrib.last_txcmdsz;
- padding_sz = (8 - (last_txcmdsz % 8));
- if ((last_txcmdsz % 8) != 0) {
- int i;
-
- for (i = 0; i < padding_sz; i++)
- *(pxmitframe->buf_addr + TXDESC_SIZE + last_txcmdsz +
- i) = 0;
- }
- /* Add the new mpdu's length */
- ptx_desc->txdw0 = cpu_to_le32((ptx_desc->txdw0 & 0xffff0000) |
- ((ptx_desc->txdw0 & 0x0000ffff) +
- ((TXDESC_SIZE + last_txcmdsz + padding_sz) &
- 0x0000ffff)));
-}
-
-void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf,
- struct xmit_frame *pxmitframe)
-{
- /* linux complete context doesn't need to protect */
- pxmitframe->pxmitbuf = pxmitbuf;
- pxmitbuf->priv_data = pxmitframe;
- pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
- /* buffer addr assoc */
- pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + CMD_HDR_SZ;
- /*RTL8712_DMA_H2CCMD */
- r8712_construct_txaggr_cmd_desc(pxmitbuf);
- r8712_construct_txaggr_cmd_hdr(pxmitbuf);
- r8712_append_mpdu_unit(pxmitbuf, pxmitframe);
- pxmitbuf->aggr_nr = 1;
-}
-
-u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf, struct xmit_frame *pxmitframe)
-{
- pxmitframe->pxmitbuf = pxmitbuf;
- pxmitbuf->priv_data = pxmitframe;
- pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
- /* buffer addr assoc */
- pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE +
- (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff);
- r8712_append_mpdu_unit(pxmitbuf, pxmitframe);
- r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv,
- pxmitframe);
- pxmitbuf->aggr_nr++;
-
- return TXDESC_SIZE +
- (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff);
-}
-
-void r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf,
- struct xmit_frame *pxmitframe)
-{
- struct _adapter *padapter = pxmitframe->padapter;
- struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
- struct tx_desc *ptxdesc = pxmitbuf->pbuf;
- struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *)
- (pxmitbuf->pbuf + TXDESC_SIZE);
- u16 total_length = (u16)(ptxdesc->txdw0 & 0xffff);
-
- /* use 1st xmitframe as media */
- xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
- pcmd_hdr->cmd_dw0 = cpu_to_le32(((total_length - CMD_HDR_SZ) &
- 0x0000ffff) | (pcmd_hdr->cmd_dw0 &
- 0xffff0000));
-
- /* urb length in cmd_dw1 */
- pcmd_hdr->cmd_dw1 = cpu_to_le32((pxmitbuf->aggr_nr & 0xff) |
- ((total_length + TXDESC_SIZE) << 16));
- pxmitframe->last[0] = 1;
- pxmitframe->bpending[0] = false;
- pxmitframe->mem_addr = pxmitbuf->pbuf;
-
- if ((pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) % 0x200) == 0) ||
- ((!pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) %
- 0x40) == 0))) {
- ptxdesc->txdw0 |= cpu_to_le32
- (((TXDESC_SIZE + OFFSET_SZ + 8) << OFFSET_SHT) &
- 0x00ff0000);
- /*32 bytes for TX Desc + 8 bytes pending*/
- } else {
- ptxdesc->txdw0 |= cpu_to_le32
- (((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) &
- 0x00ff0000);
- /*default = 32 bytes for TX Desc*/
- }
- r8712_write_port(pxmitframe->padapter, RTL8712_DMA_H2CCMD, total_length + TXDESC_SIZE,
- (u8 *)pxmitframe);
-}
-
-#endif
-
-static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz)
-{
- uint qsel;
- struct _adapter *padapter = pxmitframe->padapter;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
- struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
-#ifdef CONFIG_R8712_TX_AGGR
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-#endif
- u8 blnSetTxDescOffset;
- bool bmcst = is_multicast_ether_addr(pattrib->ra);
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
- struct tx_desc txdesc_mp;
-
- memcpy(&txdesc_mp, ptxdesc, sizeof(struct tx_desc));
- memset(ptxdesc, 0, sizeof(struct tx_desc));
- /* offset 0 */
- ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff);
- if (pdvobj->ishighspeed) {
- if (((sz + TXDESC_SIZE) % 512) == 0)
- blnSetTxDescOffset = 1;
- else
- blnSetTxDescOffset = 0;
- } else {
- if (((sz + TXDESC_SIZE) % 64) == 0)
- blnSetTxDescOffset = 1;
- else
- blnSetTxDescOffset = 0;
- }
- if (blnSetTxDescOffset) {
- /* 32 bytes for TX Desc + 8 bytes pending */
- ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ + 8) <<
- OFFSET_SHT) & 0x00ff0000);
- } else {
- /* default = 32 bytes for TX Desc */
- ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) <<
- OFFSET_SHT) & 0x00ff0000);
- }
- ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
- if (pxmitframe->frame_tag == DATA_FRAMETAG) {
- /* offset 4 */
- ptxdesc->txdw1 |= cpu_to_le32((pattrib->mac_id) & 0x1f);
-
-#ifdef CONFIG_R8712_TX_AGGR
- /* dirty workaround, need to check if it is aggr cmd. */
- if ((u8 *)pmem != (u8 *)pxmitframe->pxmitbuf->pbuf) {
- ptxdesc->txdw0 |= cpu_to_le32
- ((0x3 << TYPE_SHT) & TYPE_MSK);
- qsel = (uint)(pattrib->qsel & 0x0000001f);
- if (qsel == 2)
- qsel = 0;
- ptxdesc->txdw1 |= cpu_to_le32
- ((qsel << QSEL_SHT) & 0x00001f00);
- ptxdesc->txdw2 = cpu_to_le32
- ((qsel << RTS_RC_SHT) & 0x001f0000);
- ptxdesc->txdw6 |= cpu_to_le32
- ((0x5 << RSVD6_SHT) & RSVD6_MSK);
- } else {
- ptxdesc->txdw0 |= cpu_to_le32
- ((0x3 << TYPE_SHT) & TYPE_MSK);
- ptxdesc->txdw1 |= cpu_to_le32
- ((0x13 << QSEL_SHT) & 0x00001f00);
- qsel = (uint)(pattrib->qsel & 0x0000001f);
- if (qsel == 2)
- qsel = 0;
- ptxdesc->txdw2 = cpu_to_le32
- ((qsel << RTS_RC_SHT) & 0x0001f000);
- ptxdesc->txdw7 |= cpu_to_le32
- (pcmdpriv->cmd_seq << 24);
- pcmdpriv->cmd_seq++;
- }
- pattrib->qsel = 0x13;
-#else
- qsel = (uint)(pattrib->qsel & 0x0000001f);
- ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
-#endif
- if (!pqospriv->qos_option)
- ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/*Non-QoS*/
- if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
- switch (pattrib->encrypt) { /*SEC_TYPE*/
- case _WEP40_:
- case _WEP104_:
- ptxdesc->txdw1 |= cpu_to_le32((0x01 << 22) &
- 0x00c00000);
- /*KEY_ID when WEP is used;*/
- ptxdesc->txdw1 |=
- cpu_to_le32((psecuritypriv->PrivacyKeyIndex << 17) &
- 0x00060000);
- break;
- case _TKIP_:
- case _TKIP_WTMIC_:
- ptxdesc->txdw1 |= cpu_to_le32((0x02 << 22) &
- 0x00c00000);
- break;
- case _AES_:
- ptxdesc->txdw1 |= cpu_to_le32((0x03 << 22) &
- 0x00c00000);
- break;
- case _NO_PRIVACY_:
- default:
- break;
- }
- }
- /*offset 8*/
- if (bmcst)
- ptxdesc->txdw2 |= cpu_to_le32(BMC);
-
- /*offset 12*/
- /* f/w will increase the seqnum by itself, driver pass the
- * correct priority to fw.
- * fw will check the correct priority for increasing the
- * seqnum per tid. about usb using 4-endpoint, qsel points out
- * the correct mapping between AC&Endpoint,
- * the purpose is that correct mapping lets the MAC release
- * the AC Queue list correctly.
- */
- ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) &
- 0x0fff0000);
- if ((pattrib->ether_type != 0x888e) &&
- (pattrib->ether_type != 0x0806) &&
- (pattrib->dhcp_pkt != 1)) {
- /*Not EAP & ARP type data packet*/
- if (phtpriv->ht_option == 1) { /*B/G/N Mode*/
- if (!phtpriv->ampdu_enable)
- ptxdesc->txdw2 |= cpu_to_le32(BK);
- }
- } else {
- /* EAP data packet and ARP packet.
- * Use the 1M data rate to send the EAP/ARP packet.
- * This will maybe make the handshake smooth.
- */
- /*driver uses data rate*/
- ptxdesc->txdw4 = cpu_to_le32(0x80000000);
- ptxdesc->txdw5 = cpu_to_le32(0x001f8000);/*1M*/
- }
- if (pattrib->pctrl == 1) { /* mp tx packets */
- struct tx_desc *ptxdesc_mp;
-
- ptxdesc_mp = &txdesc_mp;
- /* offset 8 */
- ptxdesc->txdw2 = ptxdesc_mp->txdw2;
- if (bmcst)
- ptxdesc->txdw2 |= cpu_to_le32(BMC);
- ptxdesc->txdw2 |= cpu_to_le32(BK);
- /* offset 16 */
- ptxdesc->txdw4 = ptxdesc_mp->txdw4;
- /* offset 20 */
- ptxdesc->txdw5 = ptxdesc_mp->txdw5;
- pattrib->pctrl = 0;/* reset to zero; */
- }
- } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
- /* offset 4 */
- /* CAM_ID(MAC_ID), default=5; */
- ptxdesc->txdw1 |= cpu_to_le32((0x05) & 0x1f);
- qsel = (uint)(pattrib->qsel & 0x0000001f);
- ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
- ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/* Non-QoS */
- /* offset 8 */
- if (bmcst)
- ptxdesc->txdw2 |= cpu_to_le32(BMC);
- /* offset 12 */
- /* f/w will increase the seqnum by itself, driver pass the
- * correct priority to fw.
- * fw will check the correct priority for increasing the seqnum
- * per tid. about usb using 4-endpoint, qsel points out the
- * correct mapping between AC&Endpoint,
- * the purpose is that correct mapping let the MAC releases
- * the AC Queue list correctly.
- */
- ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) &
- 0x0fff0000);
- /* offset 16 */
- ptxdesc->txdw4 = cpu_to_le32(0x80002040);/*gtest*/
- /* offset 20 */
- ptxdesc->txdw5 = cpu_to_le32(0x001f8000);/* gtest 1M */
- } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) {
- /* offset 4 */
- qsel = 0x13;
- ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
- } else {
- /* offset 4 */
- qsel = (uint)(pattrib->priority & 0x0000001f);
- ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
- /*offset 8*/
- /*offset 12*/
- ptxdesc->txdw3 = cpu_to_le32((pattrib->seqnum << SEQ_SHT) &
- 0x0fff0000);
- /*offset 16*/
- ptxdesc->txdw4 = cpu_to_le32(0x80002040);/*gtest*/
- /*offset 20*/
- ptxdesc->txdw5 = cpu_to_le32(0x001f9600);/*gtest*/
- }
-}
-
-int r8712_xmitframe_complete(struct _adapter *padapter,
- struct xmit_priv *pxmitpriv,
- struct xmit_buf *pxmitbuf)
-{
- struct hw_xmit *phwxmits;
- sint hwentry;
- struct xmit_frame *pxmitframe = NULL;
-#ifdef CONFIG_R8712_TX_AGGR
- struct xmit_frame *p2ndxmitframe = NULL;
-#else
- int res = _SUCCESS;
-#endif
-
- phwxmits = pxmitpriv->hwxmits;
- hwentry = pxmitpriv->hwxmit_entry;
- if (!pxmitbuf) {
- pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv);
- if (!pxmitbuf)
- return false;
-#ifdef CONFIG_R8712_TX_AGGR
- pxmitbuf->aggr_nr = 0;
-#endif
- }
- /* 1st frame dequeued */
- pxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry);
- /* need to remember the 1st frame */
- if (pxmitframe) {
-#ifdef CONFIG_R8712_TX_AGGR
- /* 1. dequeue 2nd frame
- * 2. aggr if 2nd xframe is dequeued, else dump directly
- */
- if (AGGR_NR_HIGH_BOUND > 1)
- p2ndxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry);
- if (pxmitframe->frame_tag != DATA_FRAMETAG) {
- r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
- return false;
- }
- if (p2ndxmitframe)
- if (p2ndxmitframe->frame_tag != DATA_FRAMETAG) {
- r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
- return false;
- }
- r8712_xmitframe_aggr_1st(pxmitbuf, pxmitframe);
- if (p2ndxmitframe) {
- u16 total_length;
-
- total_length = r8712_xmitframe_aggr_next(pxmitbuf, p2ndxmitframe);
- do {
- p2ndxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry);
- if (p2ndxmitframe)
- total_length =
- r8712_xmitframe_aggr_next(pxmitbuf, p2ndxmitframe);
- else
- break;
- } while (total_length <= 0x1800 &&
- pxmitbuf->aggr_nr <= AGGR_NR_HIGH_BOUND);
- }
- if (pxmitbuf->aggr_nr > 0)
- r8712_dump_aggr_xframe(pxmitbuf, pxmitframe);
-
-#else
-
- xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
- if (pxmitframe->frame_tag == DATA_FRAMETAG) {
- if (pxmitframe->attrib.priority <= 15)
- res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt,
- pxmitframe);
- /* always return ndis_packet after
- * r8712_xmitframe_coalesce
- */
- r8712_xmit_complete(padapter, pxmitframe);
- }
- if (res == _SUCCESS)
- dump_xframe(padapter, pxmitframe);
- else
- r8712_free_xmitframe_ex(pxmitpriv, pxmitframe);
-#endif
-
- } else { /* pxmitframe == NULL && p2ndxmitframe == NULL */
- r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
- return false;
- }
- return true;
-}
-
-static void dump_xframe(struct _adapter *padapter,
- struct xmit_frame *pxmitframe)
-{
- int t, sz, w_sz;
- u8 *mem_addr;
- u32 ff_hwaddr;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- if (pxmitframe->attrib.ether_type != 0x0806) {
- if (pxmitframe->attrib.ether_type != 0x888e)
- r8712_issue_addbareq_cmd(padapter, pattrib->priority);
- }
- mem_addr = pxmitframe->buf_addr;
- for (t = 0; t < pattrib->nr_frags; t++) {
- if (t != (pattrib->nr_frags - 1)) {
- sz = pxmitpriv->frag_len;
- sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 :
- pattrib->icv_len);
- pxmitframe->last[t] = 0;
- } else {
- sz = pattrib->last_txcmdsz;
- pxmitframe->last[t] = 1;
- }
- update_txdesc(pxmitframe, (uint *)mem_addr, sz);
- w_sz = sz + TXDESC_SIZE;
- pxmitframe->mem_addr = mem_addr;
- pxmitframe->bpending[t] = false;
- ff_hwaddr = get_ff_hwaddr(pxmitframe);
-#ifdef CONFIG_R8712_TX_AGGR
- r8712_write_port(padapter, RTL8712_DMA_H2CCMD, w_sz,
- (unsigned char *)pxmitframe);
-#else
- r8712_write_port(padapter, ff_hwaddr, w_sz,
- (unsigned char *)pxmitframe);
-#endif
- mem_addr += w_sz;
- mem_addr = (u8 *)RND4(((addr_t)(mem_addr)));
- }
-}
-
-void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe)
-{
- int res;
-
- res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
- pxmitframe->pkt = NULL;
- if (res == _SUCCESS)
- dump_xframe(padapter, pxmitframe);
-}
-
-int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe)
-{
- if (r8712_xmit_classifier(padapter, pxmitframe)) {
- pxmitframe->pkt = NULL;
- return _FAIL;
- }
- return _SUCCESS;
-}
diff --git a/drivers/staging/rtl8712/rtl8712_xmit.h b/drivers/staging/rtl8712/rtl8712_xmit.h
deleted file mode 100644
index 5cd651a0de75..000000000000
--- a/drivers/staging/rtl8712/rtl8712_xmit.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL8712_XMIT_H_
-#define _RTL8712_XMIT_H_
-
-#define HWXMIT_ENTRY 4
-
-#define VO_QUEUE_INX 0
-#define VI_QUEUE_INX 1
-#define BE_QUEUE_INX 2
-#define BK_QUEUE_INX 3
-#define TS_QUEUE_INX 4
-#define MGT_QUEUE_INX 5
-#define BMC_QUEUE_INX 6
-#define BCN_QUEUE_INX 7
-
-#define HW_QUEUE_ENTRY 8
-
-#define TXDESC_SIZE 32
-#define TXDESC_OFFSET TXDESC_SIZE
-
-#define NR_AMSDU_XMITFRAME 8
-#define NR_TXAGG_XMITFRAME 8
-
-#define MAX_AMSDU_XMITBUF_SZ 8704
-#define MAX_TXAGG_XMITBUF_SZ 16384 /*16k*/
-
-#define tx_cmd tx_desc
-
-/*
- *defined for TX DESC Operation
- */
-
-#define MAX_TID (15)
-
-/*OFFSET 0*/
-#define OFFSET_SZ (0)
-#define OFFSET_SHT (16)
-#define OWN BIT(31)
-#define FSG BIT(27)
-#define LSG BIT(26)
-#define TYPE_SHT (24)
-#define TYPE_MSK (0x03000000)
-
-/*OFFSET 4*/
-#define PKT_OFFSET_SZ (0)
-#define QSEL_SHT (8)
-#define HWPC BIT(31)
-
-/*OFFSET 8*/
-#define BMC BIT(7)
-#define BK BIT(30)
-#define AGG_EN BIT(29)
-#define RTS_RC_SHT (16)
-
-/*OFFSET 12*/
-#define SEQ_SHT (16)
-
-/*OFFSET 16*/
-#define TXBW BIT(18)
-
-/*OFFSET 20*/
-#define DISFB BIT(15)
-#define RSVD6_MSK (0x00E00000)
-#define RSVD6_SHT (21)
-
-struct tx_desc {
- /*DWORD 0*/
- __le32 txdw0;
- __le32 txdw1;
- __le32 txdw2;
- __le32 txdw3;
- __le32 txdw4;
- __le32 txdw5;
- __le32 txdw6;
- __le32 txdw7;
-};
-
-union txdesc {
- struct tx_desc txdesc;
- unsigned int value[TXDESC_SIZE >> 2];
-};
-
-int r8712_xmitframe_complete(struct _adapter *padapter,
- struct xmit_priv *pxmitpriv,
- struct xmit_buf *pxmitbuf);
-void r8712_do_queue_select(struct _adapter *padapter,
- struct pkt_attrib *pattrib);
-
-#ifdef CONFIG_R8712_TX_AGGR
-void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf,
- struct xmit_frame *pxmitframe);
-void r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf,
- struct xmit_frame *pxmitframe);
-#endif
-
-#endif
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c
deleted file mode 100644
index ffeb91dd28c4..000000000000
--- a/drivers/staging/rtl8712/rtl871x_cmd.c
+++ /dev/null
@@ -1,750 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_cmd.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_CMD_C_
-
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/usb.h>
-#include <linux/usb/ch9.h>
-#include <linux/circ_buf.h>
-#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-#include <linux/atomic.h>
-#include <linux/semaphore.h>
-#include <linux/rtnetlink.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "mlme_osdep.h"
-
-/*
- * Caller and the r8712_cmd_thread can protect cmd_q by spin_lock.
- * No irqsave is necessary.
- */
-
-int r8712_init_cmd_priv(struct cmd_priv *pcmdpriv)
-{
- init_completion(&pcmdpriv->cmd_queue_comp);
- init_completion(&pcmdpriv->terminate_cmdthread_comp);
-
- _init_queue(&(pcmdpriv->cmd_queue));
-
- /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
- pcmdpriv->cmd_seq = 1;
- pcmdpriv->cmd_allocated_buf = kmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ,
- GFP_ATOMIC);
- if (!pcmdpriv->cmd_allocated_buf)
- return -ENOMEM;
- pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ -
- ((addr_t)(pcmdpriv->cmd_allocated_buf) &
- (CMDBUFF_ALIGN_SZ - 1));
- pcmdpriv->rsp_allocated_buf = kmalloc(MAX_RSPSZ + 4, GFP_ATOMIC);
- if (!pcmdpriv->rsp_allocated_buf) {
- kfree(pcmdpriv->cmd_allocated_buf);
- pcmdpriv->cmd_allocated_buf = NULL;
- return -ENOMEM;
- }
- pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 -
- ((addr_t)(pcmdpriv->rsp_allocated_buf) & 3);
- pcmdpriv->cmd_issued_cnt = 0;
- pcmdpriv->cmd_done_cnt = 0;
- pcmdpriv->rsp_cnt = 0;
- return 0;
-}
-
-int r8712_init_evt_priv(struct evt_priv *pevtpriv)
-{
- /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
- pevtpriv->event_seq = 0;
- pevtpriv->evt_allocated_buf = kmalloc(MAX_EVTSZ + 4, GFP_ATOMIC);
-
- if (!pevtpriv->evt_allocated_buf)
- return -ENOMEM;
- pevtpriv->evt_buf = pevtpriv->evt_allocated_buf + 4 -
- ((addr_t)(pevtpriv->evt_allocated_buf) & 3);
- pevtpriv->evt_done_cnt = 0;
- return 0;
-}
-
-void r8712_free_evt_priv(struct evt_priv *pevtpriv)
-{
- kfree(pevtpriv->evt_allocated_buf);
-}
-
-void r8712_free_cmd_priv(struct cmd_priv *pcmdpriv)
-{
- if (pcmdpriv) {
- kfree(pcmdpriv->cmd_allocated_buf);
- kfree(pcmdpriv->rsp_allocated_buf);
- }
-}
-
-/*
- * Calling Context:
- *
- * r8712_enqueue_cmd can only be called between kernel thread,
- * since only spin_lock is used.
- *
- * ISR/Call-Back functions can't call this sub-function.
- *
- */
-
-void r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
-{
- struct __queue *queue;
- unsigned long irqL;
-
- if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag)
- return;
- if (!obj)
- return;
- queue = &pcmdpriv->cmd_queue;
- spin_lock_irqsave(&queue->lock, irqL);
- list_add_tail(&obj->list, &queue->queue);
- spin_unlock_irqrestore(&queue->lock, irqL);
- complete(&pcmdpriv->cmd_queue_comp);
-}
-
-struct cmd_obj *r8712_dequeue_cmd(struct __queue *queue)
-{
- unsigned long irqL;
- struct cmd_obj *obj;
-
- spin_lock_irqsave(&queue->lock, irqL);
- obj = list_first_entry_or_null(&queue->queue,
- struct cmd_obj, list);
- if (obj)
- list_del_init(&obj->list);
- spin_unlock_irqrestore(&queue->lock, irqL);
- return obj;
-}
-
-void r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
-{
- unsigned long irqL;
- struct __queue *queue;
-
- if (!obj)
- return;
- if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag)
- return;
- queue = &pcmdpriv->cmd_queue;
- spin_lock_irqsave(&queue->lock, irqL);
- list_add_tail(&obj->list, &queue->queue);
- spin_unlock_irqrestore(&queue->lock, irqL);
- complete(&pcmdpriv->cmd_queue_comp);
-}
-
-void r8712_free_cmd_obj(struct cmd_obj *pcmd)
-{
- if ((pcmd->cmdcode != _JoinBss_CMD_) &&
- (pcmd->cmdcode != _CreateBss_CMD_))
- kfree(pcmd->parmbuf);
- if (pcmd->rsp) {
- if (pcmd->rspsz != 0)
- kfree(pcmd->rsp);
- }
- kfree(pcmd);
-}
-
-u8 r8712_sitesurvey_cmd(struct _adapter *padapter,
- struct ndis_802_11_ssid *pssid)
- __must_hold(&padapter->mlmepriv.lock)
-{
- struct cmd_obj *ph2c;
- struct sitesurvey_parm *psurveyPara;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return _FAIL;
- psurveyPara = kmalloc(sizeof(*psurveyPara), GFP_ATOMIC);
- if (!psurveyPara) {
- kfree(ph2c);
- return _FAIL;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
- GEN_CMD_CODE(_SiteSurvey));
- psurveyPara->bsslimit = cpu_to_le32(48);
- psurveyPara->passive_mode = cpu_to_le32(pmlmepriv->passive_mode);
- psurveyPara->ss_ssidlen = 0;
- memset(psurveyPara->ss_ssid, 0, IW_ESSID_MAX_SIZE + 1);
- if (pssid && pssid->SsidLength) {
- int len = min_t(int, pssid->SsidLength, IW_ESSID_MAX_SIZE);
-
- memcpy(psurveyPara->ss_ssid, pssid->Ssid, len);
- psurveyPara->ss_ssidlen = cpu_to_le32(len);
- }
- set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
- r8712_enqueue_cmd(pcmdpriv, ph2c);
- mod_timer(&pmlmepriv->scan_to_timer,
- jiffies + msecs_to_jiffies(SCANNING_TIMEOUT));
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_SITE_SURVEY);
- complete(&padapter->rx_filter_ready);
- return _SUCCESS;
-}
-
-int r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset)
-{
- struct cmd_obj *ph2c;
- struct setdatarate_parm *pbsetdataratepara;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return -ENOMEM;
- pbsetdataratepara = kmalloc(sizeof(*pbsetdataratepara), GFP_ATOMIC);
- if (!pbsetdataratepara) {
- kfree(ph2c);
- return -ENOMEM;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara,
- GEN_CMD_CODE(_SetDataRate));
- pbsetdataratepara->mac_id = 5;
- memcpy(pbsetdataratepara->datarates, rateset, NumRates);
- r8712_enqueue_cmd(pcmdpriv, ph2c);
- return 0;
-}
-
-void r8712_set_chplan_cmd(struct _adapter *padapter, int chplan)
-{
- struct cmd_obj *ph2c;
- struct SetChannelPlan_param *psetchplanpara;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- psetchplanpara = kmalloc(sizeof(*psetchplanpara), GFP_ATOMIC);
- if (!psetchplanpara) {
- kfree(ph2c);
- return;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetchplanpara, GEN_CMD_CODE(_SetChannelPlan));
- psetchplanpara->ChannelPlan = chplan;
- r8712_enqueue_cmd(pcmdpriv, ph2c);
-}
-
-int r8712_setrfreg_cmd(struct _adapter *padapter, u8 offset, u32 val)
-{
- struct cmd_obj *ph2c;
- struct writeRF_parm *pwriterfparm;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return -ENOMEM;
- pwriterfparm = kmalloc(sizeof(*pwriterfparm), GFP_ATOMIC);
- if (!pwriterfparm) {
- kfree(ph2c);
- return -ENOMEM;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
- pwriterfparm->offset = offset;
- pwriterfparm->value = val;
- r8712_enqueue_cmd(pcmdpriv, ph2c);
- return 0;
-}
-
-int r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval)
-{
- struct cmd_obj *ph2c;
- struct readRF_parm *prdrfparm;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return -ENOMEM;
- prdrfparm = kmalloc(sizeof(*prdrfparm), GFP_ATOMIC);
- if (!prdrfparm) {
- kfree(ph2c);
- return -ENOMEM;
- }
- INIT_LIST_HEAD(&ph2c->list);
- ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
- ph2c->parmbuf = (unsigned char *)prdrfparm;
- ph2c->cmdsz = sizeof(struct readRF_parm);
- ph2c->rsp = pval;
- ph2c->rspsz = sizeof(struct readRF_rsp);
- prdrfparm->offset = offset;
- r8712_enqueue_cmd(pcmdpriv, ph2c);
- return 0;
-}
-
-void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter,
- struct cmd_obj *pcmd)
-{
- kfree(pcmd->parmbuf);
- kfree(pcmd);
- padapter->mppriv.workparam.bcompleted = true;
-}
-
-void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
-{
- kfree(pcmd->parmbuf);
- kfree(pcmd);
-
- padapter->mppriv.workparam.bcompleted = true;
-}
-
-int r8712_createbss_cmd(struct _adapter *padapter)
-{
- struct cmd_obj *pcmd;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct wlan_bssid_ex *pdev_network =
- &padapter->registrypriv.dev_network;
-
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
- pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
- if (!pcmd)
- return -ENOMEM;
- INIT_LIST_HEAD(&pcmd->list);
- pcmd->cmdcode = _CreateBss_CMD_;
- pcmd->parmbuf = (unsigned char *)pdev_network;
- pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(pdev_network);
- pcmd->rsp = NULL;
- pcmd->rspsz = 0;
- /* notes: translate IELength & Length after assign to cmdsz; */
- pdev_network->Length = pcmd->cmdsz;
- pdev_network->IELength = pdev_network->IELength;
- pdev_network->Ssid.SsidLength = pdev_network->Ssid.SsidLength;
- r8712_enqueue_cmd(pcmdpriv, pcmd);
- return 0;
-}
-
-int r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork)
-{
- struct wlan_bssid_ex *psecnetwork;
- struct cmd_obj *pcmd;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode =
- pnetwork->network.InfrastructureMode;
-
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
- pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
- if (!pcmd)
- return -ENOMEM;
-
- /* for hidden ap to set fw_state here */
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) !=
- true) {
- switch (ndis_network_mode) {
- case Ndis802_11IBSS:
- pmlmepriv->fw_state |= WIFI_ADHOC_STATE;
- break;
- case Ndis802_11Infrastructure:
- pmlmepriv->fw_state |= WIFI_STATION_STATE;
- break;
- case Ndis802_11APMode:
- case Ndis802_11AutoUnknown:
- case Ndis802_11InfrastructureMax:
- break;
- }
- }
- psecnetwork = &psecuritypriv->sec_bss;
- memcpy(psecnetwork, &pnetwork->network, sizeof(*psecnetwork));
- psecuritypriv->authenticator_ie[0] = (unsigned char)
- psecnetwork->IELength;
- if ((psecnetwork->IELength - 12) < (256 - 1))
- memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12],
- psecnetwork->IELength - 12);
- else
- memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256 - 1));
- psecnetwork->IELength = 0;
- /*
- * If the driver wants to use the bssid to create the connection.
- * If not, we copy the connecting AP's MAC address to it so that
- * the driver just has the bssid information for PMKIDList searching.
- */
- if (!pmlmepriv->assoc_by_bssid)
- ether_addr_copy(&pmlmepriv->assoc_bssid[0],
- &pnetwork->network.MacAddress[0]);
- psecnetwork->IELength = r8712_restruct_sec_ie(padapter, &pnetwork->network.IEs[0],
- &psecnetwork->IEs[0], pnetwork->network.IELength);
- pqospriv->qos_option = 0;
- if (pregistrypriv->wmm_enable) {
- u32 tmp_len;
-
- tmp_len = r8712_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0],
- &psecnetwork->IEs[0], pnetwork->network.IELength,
- psecnetwork->IELength);
- if (psecnetwork->IELength != tmp_len) {
- psecnetwork->IELength = tmp_len;
- pqospriv->qos_option = 1; /* WMM IE in beacon */
- } else {
- pqospriv->qos_option = 0; /* no WMM IE in beacon */
- }
- }
- if (pregistrypriv->ht_enable) {
- /*
- * For WEP mode, we will use the bg mode to do the connection
- * to avoid some IOT issues, especially for Realtek 8192u
- * SoftAP.
- */
- if ((padapter->securitypriv.PrivacyAlgrthm != _WEP40_) &&
- (padapter->securitypriv.PrivacyAlgrthm != _WEP104_)) {
- /* restructure_ht_ie */
- r8712_restructure_ht_ie(padapter,
- &pnetwork->network.IEs[0],
- &psecnetwork->IEs[0],
- pnetwork->network.IELength,
- &psecnetwork->IELength);
- }
- }
- psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
- if (psecnetwork->IELength < 255)
- memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
- psecnetwork->IELength);
- else
- memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
- 255);
- /* get cmdsz before endian conversion */
- pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(psecnetwork);
-#ifdef __BIG_ENDIAN
- /* wlan_network endian conversion */
- psecnetwork->Length = cpu_to_le32(psecnetwork->Length);
- psecnetwork->Ssid.SsidLength = cpu_to_le32(psecnetwork->Ssid.SsidLength);
- psecnetwork->Privacy = cpu_to_le32(psecnetwork->Privacy);
- psecnetwork->Rssi = cpu_to_le32(psecnetwork->Rssi);
- psecnetwork->NetworkTypeInUse = cpu_to_le32(psecnetwork->NetworkTypeInUse);
- psecnetwork->Configuration.ATIMWindow = cpu_to_le32(psecnetwork->Configuration.ATIMWindow);
- psecnetwork->Configuration.BeaconPeriod = cpu_to_le32(psecnetwork->Configuration.BeaconPeriod);
- psecnetwork->Configuration.DSConfig = cpu_to_le32(psecnetwork->Configuration.DSConfig);
- psecnetwork->Configuration.FHConfig.DwellTime = cpu_to_le32(psecnetwork->Configuration.FHConfig.DwellTime);
- psecnetwork->Configuration.FHConfig.HopPattern = cpu_to_le32(psecnetwork->Configuration.FHConfig.HopPattern);
- psecnetwork->Configuration.FHConfig.HopSet = cpu_to_le32(psecnetwork->Configuration.FHConfig.HopSet);
- psecnetwork->Configuration.FHConfig.Length = cpu_to_le32(psecnetwork->Configuration.FHConfig.Length);
- psecnetwork->Configuration.Length = cpu_to_le32(psecnetwork->Configuration.Length);
- psecnetwork->InfrastructureMode = cpu_to_le32(psecnetwork->InfrastructureMode);
- psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength);
-#endif
- INIT_LIST_HEAD(&pcmd->list);
- pcmd->cmdcode = _JoinBss_CMD_;
- pcmd->parmbuf = (unsigned char *)psecnetwork;
- pcmd->rsp = NULL;
- pcmd->rspsz = 0;
- r8712_enqueue_cmd(pcmdpriv, pcmd);
- return 0;
-}
-
-void r8712_disassoc_cmd(struct _adapter *padapter) /* for sta_mode */
-{
- struct cmd_obj *pdisconnect_cmd;
- struct disconnect_parm *pdisconnect;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- pdisconnect_cmd = kmalloc(sizeof(*pdisconnect_cmd), GFP_ATOMIC);
- if (!pdisconnect_cmd)
- return;
- pdisconnect = kmalloc(sizeof(*pdisconnect), GFP_ATOMIC);
- if (!pdisconnect) {
- kfree(pdisconnect_cmd);
- return;
- }
- init_h2fwcmd_w_parm_no_rsp(pdisconnect_cmd, pdisconnect, _DisConnect_CMD_);
- r8712_enqueue_cmd(pcmdpriv, pdisconnect_cmd);
-}
-
-void r8712_setopmode_cmd(struct _adapter *padapter,
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
-{
- struct cmd_obj *ph2c;
- struct setopmode_parm *psetop;
-
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- psetop = kmalloc(sizeof(*psetop), GFP_ATOMIC);
- if (!psetop) {
- kfree(ph2c);
- return;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
- psetop->mode = (u8)networktype;
- r8712_enqueue_cmd(pcmdpriv, ph2c);
-}
-
-void r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key)
-{
- struct cmd_obj *ph2c;
- struct set_stakey_parm *psetstakey_para;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct set_stakey_rsp *psetstakey_rsp = NULL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct sta_info *sta = (struct sta_info *)psta;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- psetstakey_para = kmalloc(sizeof(*psetstakey_para), GFP_ATOMIC);
- if (!psetstakey_para) {
- kfree(ph2c);
- return;
- }
- psetstakey_rsp = kmalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC);
- if (!psetstakey_rsp) {
- kfree(ph2c);
- kfree(psetstakey_para);
- return;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
- ph2c->rsp = (u8 *)psetstakey_rsp;
- ph2c->rspsz = sizeof(struct set_stakey_rsp);
- ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- psetstakey_para->algorithm = (unsigned char)
- psecuritypriv->PrivacyAlgrthm;
- else
- GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
- if (unicast_key)
- memcpy(&psetstakey_para->key, &sta->x_UncstKey, 16);
- else
- memcpy(&psetstakey_para->key,
- &psecuritypriv->XGrpKey[psecuritypriv->XGrpKeyid - 1].skey,
- 16);
- r8712_enqueue_cmd(pcmdpriv, ph2c);
-}
-
-void r8712_setMacAddr_cmd(struct _adapter *padapter, const u8 *mac_addr)
-{
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct cmd_obj *ph2c;
- struct SetMacAddr_param *psetMacAddr_para;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- psetMacAddr_para = kmalloc(sizeof(*psetMacAddr_para), GFP_ATOMIC);
- if (!psetMacAddr_para) {
- kfree(ph2c);
- return;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetMacAddr_para, _SetMacAddress_CMD_);
- ether_addr_copy(psetMacAddr_para->MacAddr, mac_addr);
- r8712_enqueue_cmd(pcmdpriv, ph2c);
-}
-
-void r8712_addbareq_cmd(struct _adapter *padapter, u8 tid)
-{
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct cmd_obj *ph2c;
- struct addBaReq_parm *paddbareq_parm;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- paddbareq_parm = kmalloc(sizeof(*paddbareq_parm), GFP_ATOMIC);
- if (!paddbareq_parm) {
- kfree(ph2c);
- return;
- }
- paddbareq_parm->tid = tid;
- init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
- r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
-}
-
-void r8712_wdg_wk_cmd(struct _adapter *padapter)
-{
- struct cmd_obj *ph2c;
- struct drvint_cmd_parm *pdrvintcmd_param;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- pdrvintcmd_param = kmalloc(sizeof(*pdrvintcmd_param), GFP_ATOMIC);
- if (!pdrvintcmd_param) {
- kfree(ph2c);
- return;
- }
- pdrvintcmd_param->i_cid = WDG_WK_CID;
- pdrvintcmd_param->sz = 0;
- pdrvintcmd_param->pbuf = NULL;
- init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvintcmd_param, _DRV_INT_CMD_);
- r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
-}
-
-void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (pcmd->res != H2C_SUCCESS)
- clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
- r8712_free_cmd_obj(pcmd);
-}
-
-void r8712_disassoc_cmd_callback(struct _adapter *padapter,
- struct cmd_obj *pcmd)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (pcmd->res != H2C_SUCCESS) {
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- set_fwstate(pmlmepriv, _FW_LINKED);
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- return;
- }
- r8712_free_cmd_obj(pcmd);
-}
-
-void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (pcmd->res != H2C_SUCCESS)
- mod_timer(&pmlmepriv->assoc_timer, jiffies + msecs_to_jiffies(1));
- r8712_free_cmd_obj(pcmd);
-}
-
-void r8712_createbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
-{
- unsigned long irqL;
- struct sta_info *psta = NULL;
- struct wlan_network *pwlan = NULL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
- struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
-
- if (pcmd->res != H2C_SUCCESS)
- mod_timer(&pmlmepriv->assoc_timer, jiffies + msecs_to_jiffies(1));
- del_timer(&pmlmepriv->assoc_timer);
-#ifdef __BIG_ENDIAN
- /* endian_convert */
- pnetwork->Length = le32_to_cpu(pnetwork->Length);
- pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
- pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
- pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
- pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
- pnetwork->Configuration.ATIMWindow = le32_to_cpu(pnetwork->Configuration.ATIMWindow);
- pnetwork->Configuration.DSConfig = le32_to_cpu(pnetwork->Configuration.DSConfig);
- pnetwork->Configuration.FHConfig.DwellTime = le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
- pnetwork->Configuration.FHConfig.HopPattern = le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
- pnetwork->Configuration.FHConfig.HopSet = le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
- pnetwork->Configuration.FHConfig.Length = le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
- pnetwork->Configuration.Length = le32_to_cpu(pnetwork->Configuration.Length);
- pnetwork->InfrastructureMode = le32_to_cpu(pnetwork->InfrastructureMode);
- pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
-#endif
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if ((pmlmepriv->fw_state) & WIFI_AP_STATE) {
- psta = r8712_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
- if (!psta) {
- psta = r8712_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
- if (!psta)
- goto createbss_cmd_fail;
- }
- r8712_indicate_connect(padapter);
- } else {
- pwlan = _r8712_alloc_network(pmlmepriv);
- if (!pwlan) {
- pwlan = r8712_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
- if (!pwlan)
- goto createbss_cmd_fail;
- pwlan->last_scanned = jiffies;
- } else {
- list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
- }
- pnetwork->Length = r8712_get_wlan_bssid_ex_sz(pnetwork);
- memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
- pwlan->fixed = true;
- memcpy(&tgt_network->network, pnetwork, (r8712_get_wlan_bssid_ex_sz(pnetwork)));
- if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
- pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
- /*
- * we will set _FW_LINKED when there is one more sat to
- * join us (stassoc_event_callback)
- */
- }
-createbss_cmd_fail:
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- r8712_free_cmd_obj(pcmd);
-}
-
-void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
-{
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp);
- struct sta_info *psta = r8712_get_stainfo(pstapriv, psetstakey_rsp->addr);
-
- if (!psta)
- goto exit;
- psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/
-exit:
- r8712_free_cmd_obj(pcmd);
-}
-
-void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter,
- struct cmd_obj *pcmd)
-{
- unsigned long irqL;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
- struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp);
- struct sta_info *psta = r8712_get_stainfo(pstapriv, passocsta_parm->addr);
-
- if (!psta)
- return;
- psta->aid = psta->mac_id = passocsta_rsp->cam_id;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if ((check_fwstate(pmlmepriv, WIFI_MP_STATE)) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)))
- pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
- set_fwstate(pmlmepriv, _FW_LINKED);
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- r8712_free_cmd_obj(pcmd);
-}
-
-void r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl, u32 tryPktCnt,
- u32 tryPktInterval, u32 firstStageTO)
-{
- struct cmd_obj *ph2c;
- struct DisconnectCtrlEx_param *param;
- struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- param = kzalloc(sizeof(*param), GFP_ATOMIC);
- if (!param) {
- kfree(ph2c);
- return;
- }
-
- param->EnableDrvCtrl = (unsigned char)enableDrvCtrl;
- param->TryPktCnt = (unsigned char)tryPktCnt;
- param->TryPktInterval = (unsigned char)tryPktInterval;
- param->FirstStageTO = (unsigned int)firstStageTO;
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, param, GEN_CMD_CODE(_DisconnectCtrlEx));
- r8712_enqueue_cmd(pcmdpriv, ph2c);
-}
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h
deleted file mode 100644
index 268844af57f0..000000000000
--- a/drivers/staging/rtl8712/rtl871x_cmd.h
+++ /dev/null
@@ -1,750 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_CMD_H_
-#define __RTL871X_CMD_H_
-
-#include "wlan_bssdef.h"
-#include "rtl871x_rf.h"
-#define C2H_MEM_SZ (16*1024)
-
-#include "osdep_service.h"
-#include "ieee80211.h"
-
-#define FREE_CMDOBJ_SZ 128
-#define MAX_CMDSZ 512
-#define MAX_RSPSZ 512
-#define MAX_EVTSZ 1024
-#define CMDBUFF_ALIGN_SZ 512
-
-struct cmd_obj {
- u16 cmdcode;
- u8 res;
- u8 *parmbuf;
- u32 cmdsz;
- u8 *rsp;
- u32 rspsz;
- struct list_head list;
-};
-
-struct cmd_priv {
- struct completion cmd_queue_comp;
- struct completion terminate_cmdthread_comp;
- struct __queue cmd_queue;
- u8 cmd_seq;
- u8 *cmd_buf; /*shall be non-paged, and 4 bytes aligned*/
- u8 *cmd_allocated_buf;
- u8 *rsp_buf; /*shall be non-paged, and 4 bytes aligned*/
- u8 *rsp_allocated_buf;
- u32 cmd_issued_cnt;
- u32 cmd_done_cnt;
- u32 rsp_cnt;
- struct _adapter *padapter;
-};
-
-struct evt_obj {
- u16 evtcode;
- u8 res;
- u8 *parmbuf;
- u32 evtsz;
- struct list_head list;
-};
-
-struct evt_priv {
- struct __queue evt_queue;
- u8 event_seq;
- u8 *evt_buf; /*shall be non-paged, and 4 bytes aligned*/
- u8 *evt_allocated_buf;
- u32 evt_done_cnt;
-};
-
-#define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \
-do {\
- INIT_LIST_HEAD(&pcmd->list);\
- pcmd->cmdcode = code;\
- pcmd->parmbuf = (u8 *)(pparm);\
- pcmd->cmdsz = sizeof(*pparm);\
- pcmd->rsp = NULL;\
- pcmd->rspsz = 0;\
-} while (0)
-
-void r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj);
-void r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj);
-struct cmd_obj *r8712_dequeue_cmd(struct __queue *queue);
-void r8712_free_cmd_obj(struct cmd_obj *pcmd);
-int r8712_cmd_thread(void *context);
-int r8712_init_cmd_priv(struct cmd_priv *pcmdpriv);
-void r8712_free_cmd_priv(struct cmd_priv *pcmdpriv);
-int r8712_init_evt_priv(struct evt_priv *pevtpriv);
-void r8712_free_evt_priv(struct evt_priv *pevtpriv);
-
-enum rtl871x_drvint_cid {
- NONE_WK_CID,
- WDG_WK_CID,
- MAX_WK_CID
-};
-
-enum RFINTFS {
- SWSI,
- HWSI,
- HWPI,
-};
-
-/*
- * Caller Mode: Infra, Ad-HoC(C)
- * Notes: To enter USB suspend mode
- * Command Mode
- */
-struct usb_suspend_parm {
- u32 action; /* 1: sleep, 0:resume */
-};
-
-/*
- * Caller Mode: Infra, Ad-HoC(C)
- * Notes: To disconnect the current associated BSS
- * Command Mode
- */
-struct disconnect_parm {
- u32 rsvd;
-};
-
-/*
- * Caller Mode: AP, Ad-HoC, Infra
- * Notes: To set the NIC mode of RTL8711
- * Command Mode
- * The definition of mode:
- *
- * #define IW_MODE_AUTO 0 // Let the driver decides which AP to join
- * #define IW_MODE_ADHOC 1 // Single cell network (Ad-Hoc Clients)
- * #define IW_MODE_INFRA 2 // Multi cell network, roaming, ..
- * #define IW_MODE_MASTER 3 // Synchronisation master or AP
- * #define IW_MODE_REPEAT 4 // Wireless Repeater (forwarder)
- * #define IW_MODE_SECOND 5 // Secondary master/repeater (backup)
- * #define IW_MODE_MONITOR 6 // Passive monitor (listen only)
- */
-struct setopmode_parm {
- u8 mode;
- u8 rsvd[3];
-};
-
-/*
- * Caller Mode: AP, Ad-HoC, Infra
- * Notes: To ask RTL8711 performing site-survey
- * Command-Event Mode
- */
-struct sitesurvey_parm {
- __le32 passive_mode; /*active: 1, passive: 0 */
- __le32 bsslimit; /* 1 ~ 48 */
- __le32 ss_ssidlen;
- u8 ss_ssid[IW_ESSID_MAX_SIZE + 1];
-};
-
-/*
- * Caller Mode: Any
- * Notes: To set the auth type of RTL8711. open/shared/802.1x
- * Command Mode
- */
-struct setauth_parm {
- u8 mode; /*0: legacy open, 1: legacy shared 2: 802.1x*/
- u8 _1x; /*0: PSK, 1: TLS*/
- u8 rsvd[2];
-};
-
-/*
- * Caller Mode: Infra
- * a. algorithm: wep40, wep104, tkip & aes
- * b. keytype: grp key/unicast key
- * c. key contents
- *
- * when shared key ==> keyid is the camid
- * when 802.1x ==> keyid [0:1] ==> grp key
- * when 802.1x ==> keyid > 2 ==> unicast key
- */
-struct setkey_parm {
- u8 algorithm; /* encryption algorithm, could be none, wep40,
- * TKIP, CCMP, wep104
- */
- u8 keyid;
- u8 grpkey; /* 1: this is the grpkey for 802.1x.
- * 0: this is the unicast key for 802.1x
- */
- u8 key[16]; /* this could be 40 or 104 */
-};
-
-/*
- * When in AP or Ad-Hoc mode, this is used to
- * allocate an sw/hw entry for a newly associated sta.
- * Command
- * when shared key ==> algorithm/keyid
- */
-struct set_stakey_parm {
- u8 addr[ETH_ALEN];
- u8 algorithm;
- u8 key[16];
-};
-
-struct set_stakey_rsp {
- u8 addr[ETH_ALEN];
- u8 keyid;
- u8 rsvd;
-};
-
-struct SetMacAddr_param {
- u8 MacAddr[ETH_ALEN];
-};
-
-/*
- * Caller Ad-Hoc/AP
- *
- * Command -Rsp(AID == CAMID) mode
- *
- * This is to force fw to add an sta_data entry per driver's request.
- *
- * FW will write an cam entry associated with it.
- *
- */
-struct set_assocsta_parm {
- u8 addr[ETH_ALEN];
-};
-
-struct set_assocsta_rsp {
- u8 cam_id;
- u8 rsvd[3];
-};
-
-/*
- * Caller Ad-Hoc/AP
- *
- * Command mode
- *
- * This is to force fw to del an sta_data entry per driver's request
- *
- * FW will invalidate the cam entry associated with it.
- *
- */
-struct del_assocsta_parm {
- u8 addr[ETH_ALEN];
-};
-
-/*
- * Caller Mode: AP/Ad-HoC(M)
- *
- * Notes: To notify fw that given staid has changed its power state
- *
- * Command Mode
- *
- */
-struct setstapwrstate_parm {
- u8 staid;
- u8 status;
- u8 hwaddr[6];
-};
-
-/*
- * Caller Mode: Any
- *
- * Notes: To setup the basic rate of RTL8711
- *
- * Command Mode
- *
- */
-struct setbasicrate_parm {
- u8 basicrates[NumRates];
-};
-
-/*
- * Caller Mode: Any
- *
- * Notes: To read the current basic rate
- *
- * Command-Rsp Mode
- *
- */
-struct getbasicrate_parm {
- u32 rsvd;
-};
-
-struct getbasicrate_rsp {
- u8 basicrates[NumRates];
-};
-
-/*
- * Caller Mode: Any
- *
- * Notes: To setup the data rate of RTL8711
- *
- * Command Mode
- *
- */
-struct setdatarate_parm {
- u8 mac_id;
- u8 datarates[NumRates];
-};
-
-enum _RT_CHANNEL_DOMAIN {
- RT_CHANNEL_DOMAIN_FCC = 0,
- RT_CHANNEL_DOMAIN_IC = 1,
- RT_CHANNEL_DOMAIN_ETSI = 2,
- RT_CHANNEL_DOMAIN_SPAIN = 3,
- RT_CHANNEL_DOMAIN_FRANCE = 4,
- RT_CHANNEL_DOMAIN_MKK = 5,
- RT_CHANNEL_DOMAIN_MKK1 = 6,
- RT_CHANNEL_DOMAIN_ISRAEL = 7,
- RT_CHANNEL_DOMAIN_TELEC = 8,
-
- /* Be compatible with old channel plan. No good! */
- RT_CHANNEL_DOMAIN_MIC = 9,
- RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN = 10,
- RT_CHANNEL_DOMAIN_WORLD_WIDE_13 = 11,
- RT_CHANNEL_DOMAIN_TELEC_NETGEAR = 12,
-
- RT_CHANNEL_DOMAIN_NCC = 13,
- RT_CHANNEL_DOMAIN_5G = 14,
- RT_CHANNEL_DOMAIN_5G_40M = 15,
- /*===== Add new channel plan above this line===============*/
- RT_CHANNEL_DOMAIN_MAX,
-};
-
-struct SetChannelPlan_param {
- enum _RT_CHANNEL_DOMAIN ChannelPlan;
-};
-
-/*
- * Caller Mode: Any
- *
- * Notes: To read the current data rate
- *
- * Command-Rsp Mode
- *
- */
-struct getdatarate_parm {
- u32 rsvd;
-
-};
-
-struct getdatarate_rsp {
- u8 datarates[NumRates];
-};
-
-/*
- * Caller Mode: Any
- * AP: AP can use the info for the contents of beacon frame
- * Infra: STA can use the info when sitesurveying
- * Ad-HoC(M): Like AP
- * Ad-HoC(C): Like STA
- *
- *
- * Notes: To set the phy capability of the NIC
- *
- * Command Mode
- *
- */
-
-/*
- * Caller Mode: Any
- *
- * Notes: To set the channel/modem/band
- * This command will be used when channel/modem/band is changed.
- *
- * Command Mode
- *
- */
-/*
- * Caller Mode: Any
- *
- * Notes: To get the current setting of channel/modem/band
- *
- * Command-Rsp Mode
- *
- */
-struct getphy_rsp {
- u8 rfchannel;
- u8 modem;
-};
-
-struct readBB_parm {
- u8 offset;
-};
-
-struct readBB_rsp {
- u8 value;
-};
-
-struct readTSSI_parm {
- u8 offset;
-};
-
-struct readTSSI_rsp {
- u8 value;
-};
-
-struct writeBB_parm {
- u8 offset;
- u8 value;
-};
-
-struct writePTM_parm {
- u8 type;
-};
-
-struct readRF_parm {
- u8 offset;
-};
-
-struct readRF_rsp {
- u32 value;
-};
-
-struct writeRF_parm {
- u32 offset;
- u32 value;
-};
-
-struct setrfintfs_parm {
- u8 rfintfs;
-};
-
-struct getrfintfs_parm {
- u8 rfintfs;
-};
-
-/*
- * Notes: This command is used for H2C/C2H loopback testing
- *
- * mac[0] == 0
- * ==> CMD mode, return H2C_SUCCESS.
- * The following condition must be true under CMD mode
- * mac[1] == mac[4], mac[2] == mac[3], mac[0]=mac[5]= 0;
- * s0 == 0x1234, s1 == 0xabcd, w0 == 0x78563412, w1 == 0x5aa5def7;
- * s2 == (b1 << 8 | b0);
- *
- * mac[0] == 1
- * ==> CMD_RSP mode, return H2C_SUCCESS_RSP
- *
- * The rsp layout shall be:
- * rsp: parm:
- * mac[0] = mac[5];
- * mac[1] = mac[4];
- * mac[2] = mac[3];
- * mac[3] = mac[2];
- * mac[4] = mac[1];
- * mac[5] = mac[0];
- * s0 = s1;
- * s1 = swap16(s0);
- * w0 = swap32(w1);
- * b0 = b1
- * s2 = s0 + s1
- * b1 = b0
- * w1 = w0
- *
- * mac[0] == 2
- * ==> CMD_EVENT mode, return H2C_SUCCESS
- * The event layout shall be:
- * event: parm:
- * mac[0] = mac[5];
- * mac[1] = mac[4];
- * mac[2] = event's sequence number, starting from 1 to parm's marc[3]
- * mac[3] = mac[2];
- * mac[4] = mac[1];
- * mac[5] = mac[0];
- * s0 = swap16(s0) - event.mac[2];
- * s1 = s1 + event.mac[2];
- * w0 = swap32(w0);
- * b0 = b1
- * s2 = s0 + event.mac[2]
- * b1 = b0
- * w1 = swap32(w1) - event.mac[2];
- *
- * parm->mac[3] is the total event counts that host requested.
- *
- *
- * event will be the same with the cmd's param.
- *
- */
-
-/* CMD param Formart for DRV INTERNAL CMD HDL*/
-struct drvint_cmd_parm {
- int i_cid; /*internal cmd id*/
- int sz; /* buf sz*/
- unsigned char *pbuf;
-};
-
-/*------------------- Below are used for RF/BB tuning ---------------------*/
-
-struct setantenna_parm {
- u8 tx_antset;
- u8 rx_antset;
- u8 tx_antenna;
- u8 rx_antenna;
-};
-
-struct enrateadaptive_parm {
- u32 en;
-};
-
-struct settxagctbl_parm {
- u32 txagc[MAX_RATES_LENGTH];
-};
-
-struct gettxagctbl_parm {
- u32 rsvd;
-};
-
-struct gettxagctbl_rsp {
- u32 txagc[MAX_RATES_LENGTH];
-};
-
-struct setagcctrl_parm {
- u32 agcctrl; /* 0: pure hw, 1: fw */
-};
-
-struct setssup_parm {
- u32 ss_ForceUp[MAX_RATES_LENGTH];
-};
-
-struct getssup_parm {
- u32 rsvd;
-};
-
-struct getssup_rsp {
- u8 ss_ForceUp[MAX_RATES_LENGTH];
-};
-
-struct setssdlevel_parm {
- u8 ss_DLevel[MAX_RATES_LENGTH];
-};
-
-struct getssdlevel_parm {
- u32 rsvd;
-};
-
-struct getssdlevel_rsp {
- u8 ss_DLevel[MAX_RATES_LENGTH];
-};
-
-struct setssulevel_parm {
- u8 ss_ULevel[MAX_RATES_LENGTH];
-};
-
-struct getssulevel_parm {
- u32 rsvd;
-};
-
-struct getssulevel_rsp {
- u8 ss_ULevel[MAX_RATES_LENGTH];
-};
-
-struct setcountjudge_parm {
- u8 count_judge[MAX_RATES_LENGTH];
-};
-
-struct getcountjudge_parm {
- u32 rsvd;
-};
-
-struct getcountjudge_rsp {
- u8 count_judge[MAX_RATES_LENGTH];
-};
-
-struct setpwrmode_parm {
- u8 mode;
- u8 flag_low_traffic_en;
- u8 flag_lpnav_en;
- u8 flag_rf_low_snr_en;
- u8 flag_dps_en; /* 1: dps, 0: 32k */
- u8 bcn_rx_en;
- u8 bcn_pass_cnt; /* fw report one beacon information to
- * driver when it receives bcn_pass_cnt
- * beacons.
- */
- u8 bcn_to; /* beacon TO (ms). ¡§=0¡¨ no limit.*/
- u16 bcn_itv;
- u8 app_itv; /* only for VOIP mode. */
- u8 awake_bcn_itv;
- u8 smart_ps;
- u8 bcn_pass_time; /* unit: 100ms */
-};
-
-struct setatim_parm {
- u8 op; /*0: add, 1:del*/
- u8 txid; /* id of dest station.*/
-};
-
-struct setratable_parm {
- u8 ss_ForceUp[NumRates];
- u8 ss_ULevel[NumRates];
- u8 ss_DLevel[NumRates];
- u8 count_judge[NumRates];
-};
-
-struct getratable_parm {
- uint rsvd;
-};
-
-struct getratable_rsp {
- u8 ss_ForceUp[NumRates];
- u8 ss_ULevel[NumRates];
- u8 ss_DLevel[NumRates];
- u8 count_judge[NumRates];
-};
-
-/*to get TX,RX retry count*/
-struct gettxretrycnt_parm {
- unsigned int rsvd;
-};
-
-struct gettxretrycnt_rsp {
- unsigned long tx_retrycnt;
-};
-
-struct getrxretrycnt_parm {
- unsigned int rsvd;
-};
-
-struct getrxretrycnt_rsp {
- unsigned long rx_retrycnt;
-};
-
-/*to get BCNOK,BCNERR count*/
-struct getbcnokcnt_parm {
- unsigned int rsvd;
-};
-
-struct getbcnokcnt_rsp {
- unsigned long bcnokcnt;
-};
-
-struct getbcnerrcnt_parm {
- unsigned int rsvd;
-};
-
-struct getbcnerrcnt_rsp {
- unsigned long bcnerrcnt;
-};
-
-/* to get current TX power level*/
-struct getcurtxpwrlevel_parm {
- unsigned int rsvd;
-};
-
-struct getcurtxpwrlevel_rsp {
- unsigned short tx_power;
-};
-
-/*dynamic on/off DIG*/
-struct setdig_parm {
- unsigned char dig_on; /* 1:on , 0:off */
-};
-
-/*dynamic on/off RA*/
-struct setra_parm {
- unsigned char ra_on; /* 1:on , 0:off */
-};
-
-struct setprobereqextraie_parm {
- unsigned char e_id;
- unsigned char ie_len;
- unsigned char ie[];
-};
-
-struct setassocreqextraie_parm {
- unsigned char e_id;
- unsigned char ie_len;
- unsigned char ie[];
-};
-
-struct setproberspextraie_parm {
- unsigned char e_id;
- unsigned char ie_len;
- unsigned char ie[];
-};
-
-struct setassocrspextraie_parm {
- unsigned char e_id;
- unsigned char ie_len;
- unsigned char ie[];
-};
-
-struct addBaReq_parm {
- unsigned int tid;
-};
-
-/*H2C Handler index: 46 */
-struct SetChannel_parm {
- u32 curr_ch;
-};
-
-/*H2C Handler index: 61 */
-struct DisconnectCtrlEx_param {
- /* MAXTIME = (2 * FirstStageTO) + (TryPktCnt * TryPktInterval) */
- unsigned char EnableDrvCtrl;
- unsigned char TryPktCnt;
- unsigned char TryPktInterval; /* Unit: ms */
- unsigned char rsvd;
- unsigned int FirstStageTO; /* Unit: ms */
-};
-
-#define GEN_CMD_CODE(cmd) cmd ## _CMD_
-
-/*
- * Result:
- * 0x00: success
- * 0x01: success, and check Response.
- * 0x02: cmd ignored due to duplicated sequence number
- * 0x03: cmd dropped due to invalid cmd code
- * 0x04: reserved.
- */
-
-#define H2C_RSP_OFFSET 512
-#define H2C_SUCCESS 0x00
-#define H2C_SUCCESS_RSP 0x01
-#define H2C_DUPLICATED 0x02
-#define H2C_DROPPED 0x03
-#define H2C_PARAMETERS_ERROR 0x04
-#define H2C_REJECTED 0x05
-#define H2C_CMD_OVERFLOW 0x06
-#define H2C_RESERVED 0x07
-
-void r8712_setMacAddr_cmd(struct _adapter *padapter, const u8 *mac_addr);
-u8 r8712_sitesurvey_cmd(struct _adapter *padapter, struct ndis_802_11_ssid *pssid);
-int r8712_createbss_cmd(struct _adapter *padapter);
-void r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key);
-int r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork);
-void r8712_disassoc_cmd(struct _adapter *padapter);
-void r8712_setopmode_cmd(struct _adapter *padapter, enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype);
-int r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset);
-void r8712_set_chplan_cmd(struct _adapter *padapter, int chplan);
-int r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval);
-int r8712_setrfreg_cmd(struct _adapter *padapter, u8 offset, u32 val);
-void r8712_addbareq_cmd(struct _adapter *padapter, u8 tid);
-void r8712_wdg_wk_cmd(struct _adapter *padapter);
-void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_disassoc_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_createbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl, u32 tryPktCnt,
- u32 tryPktInterval, u32 firstStageTO);
-
-struct _cmd_callback {
- u32 cmd_code;
- void (*callback)(struct _adapter *padapter, struct cmd_obj *cmd);
-};
-
-#include "rtl8712_cmd.h"
-
-#endif /* _CMD_H_ */
-
diff --git a/drivers/staging/rtl8712/rtl871x_debug.h b/drivers/staging/rtl8712/rtl871x_debug.h
deleted file mode 100644
index 69c631af2a2a..000000000000
--- a/drivers/staging/rtl8712/rtl871x_debug.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_DEBUG_H__
-#define __RTL871X_DEBUG_H__
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#define _drv_emerg_ 1
-#define _drv_alert_ 2
-#define _drv_crit_ 3
-#define _drv_err_ 4
-#define _drv_warning_ 5
-#define _drv_notice_ 6
-#define _drv_info_ 7
-#define _drv_dump_ 8
-#define _drv_debug_ 9
-
-#define _module_rtl871x_xmit_c_ BIT(0)
-#define _module_xmit_osdep_c_ BIT(1)
-#define _module_rtl871x_recv_c_ BIT(2)
-#define _module_recv_osdep_c_ BIT(3)
-#define _module_rtl871x_mlme_c_ BIT(4)
-#define _module_mlme_osdep_c_ BIT(5)
-#define _module_rtl871x_sta_mgt_c_ BIT(6)
-#define _module_rtl871x_cmd_c_ BIT(7)
-#define _module_cmd_osdep_c_ BIT(8)
-#define _module_rtl871x_io_c_ BIT(9)
-#define _module_io_osdep_c_ BIT(10)
-#define _module_os_intfs_c_ BIT(11)
-#define _module_rtl871x_security_c_ BIT(12)
-#define _module_rtl871x_eeprom_c_ BIT(13)
-#define _module_hal_init_c_ BIT(14)
-#define _module_hci_hal_init_c_ BIT(15)
-#define _module_rtl871x_ioctl_c_ BIT(16)
-#define _module_rtl871x_ioctl_set_c_ BIT(17)
-#define _module_rtl871x_pwrctrl_c_ BIT(19)
-#define _module_hci_intfs_c_ BIT(20)
-#define _module_hci_ops_c_ BIT(21)
-#define _module_osdep_service_c_ BIT(22)
-#define _module_rtl871x_mp_ioctl_c_ BIT(23)
-#define _module_hci_ops_os_c_ BIT(24)
-#define _module_rtl871x_ioctl_os_c BIT(25)
-#define _module_rtl8712_cmd_c_ BIT(26)
-#define _module_rtl871x_mp_c_ BIT(27)
-#define _module_rtl8712_xmit_c_ BIT(28)
-#define _module_rtl8712_efuse_c_ BIT(29)
-#define _module_rtl8712_recv_c_ BIT(30)
-#define _module_rtl8712_led_c_ BIT(31)
-
-#undef _MODULE_DEFINE_
-
-#if defined _RTL871X_XMIT_C_
- #define _MODULE_DEFINE_ _module_rtl871x_xmit_c_
-#elif defined _XMIT_OSDEP_C_
- #define _MODULE_DEFINE_ _module_xmit_osdep_c_
-#elif defined _RTL871X_RECV_C_
- #define _MODULE_DEFINE_ _module_rtl871x_recv_c_
-#elif defined _RECV_OSDEP_C_
- #define _MODULE_DEFINE_ _module_recv_osdep_c_
-#elif defined _RTL871X_MLME_C_
- #define _MODULE_DEFINE_ _module_rtl871x_mlme_c_
-#elif defined _MLME_OSDEP_C_
- #define _MODULE_DEFINE_ _module_mlme_osdep_c_
-#elif defined _RTL871X_STA_MGT_C_
- #define _MODULE_DEFINE_ _module_rtl871x_sta_mgt_c_
-#elif defined _RTL871X_CMD_C_
- #define _MODULE_DEFINE_ _module_rtl871x_cmd_c_
-#elif defined _CMD_OSDEP_C_
- #define _MODULE_DEFINE_ _module_cmd_osdep_c_
-#elif defined _RTL871X_IO_C_
- #define _MODULE_DEFINE_ _module_rtl871x_io_c_
-#elif defined _IO_OSDEP_C_
- #define _MODULE_DEFINE_ _module_io_osdep_c_
-#elif defined _OS_INTFS_C_
- #define _MODULE_DEFINE_ _module_os_intfs_c_
-#elif defined _RTL871X_SECURITY_C_
- #define _MODULE_DEFINE_ _module_rtl871x_security_c_
-#elif defined _RTL871X_EEPROM_C_
- #define _MODULE_DEFINE_ _module_rtl871x_eeprom_c_
-#elif defined _HAL_INIT_C_
- #define _MODULE_DEFINE_ _module_hal_init_c_
-#elif defined _HCI_HAL_INIT_C_
- #define _MODULE_DEFINE_ _module_hci_hal_init_c_
-#elif defined _RTL871X_IOCTL_C_
- #define _MODULE_DEFINE_ _module_rtl871x_ioctl_c_
-#elif defined _RTL871X_IOCTL_SET_C_
- #define _MODULE_DEFINE_ _module_rtl871x_ioctl_set_c_
-#elif defined _RTL871X_PWRCTRL_C_
- #define _MODULE_DEFINE_ _module_rtl871x_pwrctrl_c_
-#elif defined _HCI_INTF_C_
- #define _MODULE_DEFINE_ _module_hci_intfs_c_
-#elif defined _HCI_OPS_C_
- #define _MODULE_DEFINE_ _module_hci_ops_c_
-#elif defined _OSDEP_HCI_INTF_C_
- #define _MODULE_DEFINE_ _module_hci_intfs_c_
-#elif defined _OSDEP_SERVICE_C_
- #define _MODULE_DEFINE_ _module_osdep_service_c_
-#elif defined _RTL871X_MP_IOCTL_C_
- #define _MODULE_DEFINE_ _module_rtl871x_mp_ioctl_c_
-#elif defined _HCI_OPS_OS_C_
- #define _MODULE_DEFINE_ _module_hci_ops_os_c_
-#elif defined _RTL871X_IOCTL_LINUX_C_
- #define _MODULE_DEFINE_ _module_rtl871x_ioctl_os_c
-#elif defined _RTL871X_MP_C_
- #define _MODULE_DEFINE_ _module_rtl871x_mp_c_
-#elif defined _RTL8712_CMD_C_
- #define _MODULE_DEFINE_ _module_rtl8712_cmd_c_
-#elif defined _RTL8712_XMIT_C_
- #define _MODULE_DEFINE_ _module_rtl8712_xmit_c_
-#elif defined _RTL8712_EFUSE_C_
- #define _MODULE_DEFINE_ _module_rtl8712_efuse_c_
-#elif defined _RTL8712_RECV_C_
- #define _MODULE_DEFINE_ _module_rtl8712_recv_c_
-#else
- #undef _MODULE_DEFINE_
-#endif
-
-#endif /*__RTL871X_DEBUG_H__*/
diff --git a/drivers/staging/rtl8712/rtl871x_eeprom.c b/drivers/staging/rtl8712/rtl871x_eeprom.c
deleted file mode 100644
index 221bf92e1b1c..000000000000
--- a/drivers/staging/rtl8712/rtl871x_eeprom.c
+++ /dev/null
@@ -1,220 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_eeprom.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_EEPROM_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-static void up_clk(struct _adapter *padapter, u16 *x)
-{
- *x = *x | _EESK;
- r8712_write8(padapter, EE_9346CR, (u8)*x);
- udelay(CLOCK_RATE);
-}
-
-static void down_clk(struct _adapter *padapter, u16 *x)
-{
- *x = *x & ~_EESK;
- r8712_write8(padapter, EE_9346CR, (u8)*x);
- udelay(CLOCK_RATE);
-}
-
-static void shift_out_bits(struct _adapter *padapter, u16 data, u16 count)
-{
- u16 x, mask;
-
- if (padapter->surprise_removed)
- goto out;
- mask = 0x01 << (count - 1);
- x = r8712_read8(padapter, EE_9346CR);
- x &= ~(_EEDO | _EEDI);
- do {
- x &= ~_EEDI;
- if (data & mask)
- x |= _EEDI;
- if (padapter->surprise_removed)
- goto out;
- r8712_write8(padapter, EE_9346CR, (u8)x);
- udelay(CLOCK_RATE);
- up_clk(padapter, &x);
- down_clk(padapter, &x);
- mask >>= 1;
- } while (mask);
- if (padapter->surprise_removed)
- goto out;
- x &= ~_EEDI;
- r8712_write8(padapter, EE_9346CR, (u8)x);
-out:;
-}
-
-static u16 shift_in_bits(struct _adapter *padapter)
-{
- u16 x, d = 0, i;
-
- if (padapter->surprise_removed)
- goto out;
- x = r8712_read8(padapter, EE_9346CR);
- x &= ~(_EEDO | _EEDI);
- d = 0;
- for (i = 0; i < 16; i++) {
- d <<= 1;
- up_clk(padapter, &x);
- if (padapter->surprise_removed)
- goto out;
- x = r8712_read8(padapter, EE_9346CR);
- x &= ~(_EEDI);
- if (x & _EEDO)
- d |= 1;
- down_clk(padapter, &x);
- }
-out:
- return d;
-}
-
-static void standby(struct _adapter *padapter)
-{
- u8 x;
-
- x = r8712_read8(padapter, EE_9346CR);
- x &= ~(_EECS | _EESK);
- r8712_write8(padapter, EE_9346CR, x);
- udelay(CLOCK_RATE);
- x |= _EECS;
- r8712_write8(padapter, EE_9346CR, x);
- udelay(CLOCK_RATE);
-}
-
-static u16 wait_eeprom_cmd_done(struct _adapter *padapter)
-{
- u8 x;
- u16 i;
-
- standby(padapter);
- for (i = 0; i < 200; i++) {
- x = r8712_read8(padapter, EE_9346CR);
- if (x & _EEDO)
- return true;
- udelay(CLOCK_RATE);
- }
- return false;
-}
-
-static void eeprom_clean(struct _adapter *padapter)
-{
- u16 x;
-
- if (padapter->surprise_removed)
- return;
- x = r8712_read8(padapter, EE_9346CR);
- if (padapter->surprise_removed)
- return;
- x &= ~(_EECS | _EEDI);
- r8712_write8(padapter, EE_9346CR, (u8)x);
- if (padapter->surprise_removed)
- return;
- up_clk(padapter, &x);
- if (padapter->surprise_removed)
- return;
- down_clk(padapter, &x);
-}
-
-void r8712_eeprom_write16(struct _adapter *padapter, u16 reg, u16 data)
-{
- u8 x;
- u8 tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new;
-
- tmp8_ori = r8712_read8(padapter, 0x102502f1);
- tmp8_new = tmp8_ori & 0xf7;
- if (tmp8_ori != tmp8_new)
- r8712_write8(padapter, 0x102502f1, tmp8_new);
- tmp8_clk_ori = r8712_read8(padapter, 0x10250003);
- tmp8_clk_new = tmp8_clk_ori | 0x20;
- if (tmp8_clk_new != tmp8_clk_ori)
- r8712_write8(padapter, 0x10250003, tmp8_clk_new);
- x = r8712_read8(padapter, EE_9346CR);
- x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
- x |= _EEM1 | _EECS;
- r8712_write8(padapter, EE_9346CR, x);
- shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5);
- if (padapter->eeprom_address_size == 8) /*CF+ and SDIO*/
- shift_out_bits(padapter, 0, 6);
- else /* USB */
- shift_out_bits(padapter, 0, 4);
- standby(padapter);
- /* Erase this particular word. Write the erase opcode and register
- * number in that order. The opcode is 3bits in length; reg is 6
- * bits long.
- */
- standby(padapter);
- /* write the new word to the EEPROM
- * send the write opcode the EEPORM
- */
- shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3);
- /* select which word in the EEPROM that we are writing to. */
- shift_out_bits(padapter, reg, padapter->eeprom_address_size);
- /* write the data to the selected EEPROM word. */
- shift_out_bits(padapter, data, 16);
- if (wait_eeprom_cmd_done(padapter)) {
- standby(padapter);
- shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5);
- shift_out_bits(padapter, reg, 4);
- eeprom_clean(padapter);
- }
- if (tmp8_clk_new != tmp8_clk_ori)
- r8712_write8(padapter, 0x10250003, tmp8_clk_ori);
- if (tmp8_new != tmp8_ori)
- r8712_write8(padapter, 0x102502f1, tmp8_ori);
-}
-
-u16 r8712_eeprom_read16(struct _adapter *padapter, u16 reg) /*ReadEEprom*/
-{
- u16 x;
- u16 data = 0;
- u8 tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new;
-
- tmp8_ori = r8712_read8(padapter, 0x102502f1);
- tmp8_new = tmp8_ori & 0xf7;
- if (tmp8_ori != tmp8_new)
- r8712_write8(padapter, 0x102502f1, tmp8_new);
- tmp8_clk_ori = r8712_read8(padapter, 0x10250003);
- tmp8_clk_new = tmp8_clk_ori | 0x20;
- if (tmp8_clk_new != tmp8_clk_ori)
- r8712_write8(padapter, 0x10250003, tmp8_clk_new);
- if (padapter->surprise_removed)
- goto out;
- /* select EEPROM, reset bits, set _EECS */
- x = r8712_read8(padapter, EE_9346CR);
- if (padapter->surprise_removed)
- goto out;
- x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
- x |= _EEM1 | _EECS;
- r8712_write8(padapter, EE_9346CR, (unsigned char)x);
- /* write the read opcode and register number in that order
- * The opcode is 3bits in length, reg is 6 bits long
- */
- shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
- shift_out_bits(padapter, reg, padapter->eeprom_address_size);
- /* Now read the data (16 bits) in from the selected EEPROM word */
- data = shift_in_bits(padapter);
- eeprom_clean(padapter);
-out:
- if (tmp8_clk_new != tmp8_clk_ori)
- r8712_write8(padapter, 0x10250003, tmp8_clk_ori);
- if (tmp8_new != tmp8_ori)
- r8712_write8(padapter, 0x102502f1, tmp8_ori);
- return data;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_eeprom.h b/drivers/staging/rtl8712/rtl871x_eeprom.h
deleted file mode 100644
index 7bdeb2aaa025..000000000000
--- a/drivers/staging/rtl8712/rtl871x_eeprom.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL871X_EEPROM_H__
-#define __RTL871X_EEPROM_H__
-
-#include "osdep_service.h"
-
-#define RTL8712_EEPROM_ID 0x8712
-#define EEPROM_MAX_SIZE 256
-#define CLOCK_RATE 50 /*100us*/
-
-/*- EEPROM opcodes*/
-#define EEPROM_READ_OPCODE 06
-#define EEPROM_WRITE_OPCODE 05
-#define EEPROM_ERASE_OPCODE 07
-#define EEPROM_EWEN_OPCODE 19 /* Erase/write enable*/
-#define EEPROM_EWDS_OPCODE 16 /* Erase/write disable*/
-
-#define EEPROM_CID_DEFAULT 0x0
-#define EEPROM_CID_ALPHA 0x1
-#define EEPROM_CID_Senao 0x3
-#define EEPROM_CID_NetCore 0x5
-#define EEPROM_CID_CAMEO 0X8
-#define EEPROM_CID_SITECOM 0x9
-#define EEPROM_CID_COREGA 0xB
-#define EEPROM_CID_EDIMAX_BELKIN 0xC
-#define EEPROM_CID_SERCOMM_BELKIN 0xE
-#define EEPROM_CID_CAMEO1 0xF
-#define EEPROM_CID_WNC_COREGA 0x12
-#define EEPROM_CID_CLEVO 0x13
-#define EEPROM_CID_WHQL 0xFE
-
-enum RT_CUSTOMER_ID {
- RT_CID_DEFAULT = 0,
- RT_CID_8187_ALPHA0 = 1,
- RT_CID_8187_SERCOMM_PS = 2,
- RT_CID_8187_HW_LED = 3,
- RT_CID_8187_NETGEAR = 4,
- RT_CID_WHQL = 5,
- RT_CID_819x_CAMEO = 6,
- RT_CID_819x_RUNTOP = 7,
- RT_CID_819x_Senao = 8,
- RT_CID_TOSHIBA = 9,
- RT_CID_819x_Netcore = 10,
- RT_CID_Nettronix = 11,
- RT_CID_DLINK = 12,
- RT_CID_PRONET = 13,
- RT_CID_COREGA = 14,
- RT_CID_819x_ALPHA = 15,
- RT_CID_819x_Sitecom = 16,
- RT_CID_CCX = 17,
- RT_CID_819x_Lenovo = 18,
- RT_CID_819x_QMI = 19,
- RT_CID_819x_Edimax_Belkin = 20,
- RT_CID_819x_Sercomm_Belkin = 21,
- RT_CID_819x_CAMEO1 = 22,
- RT_CID_819x_MSI = 23,
- RT_CID_819x_Acer = 24,
- RT_CID_819x_AzWave_ASUS = 25,
- RT_CID_819x_AzWave = 26,
- RT_CID_819x_WNC_COREGA = 27,
- RT_CID_819x_CLEVO = 28,
-};
-
-struct eeprom_priv {
- u8 bautoload_fail_flag;
- u8 bempty;
- u8 sys_config;
- u8 mac_addr[6];
- u8 config0;
- u16 channel_plan;
- u8 country_string[3];
- u8 tx_power_b[15];
- u8 tx_power_g[15];
- u8 tx_power_a[201];
- u8 efuse_eeprom_data[EEPROM_MAX_SIZE];
- enum RT_CUSTOMER_ID CustomerID;
-};
-
-void r8712_eeprom_write16(struct _adapter *padapter, u16 reg, u16 data);
-u16 r8712_eeprom_read16(struct _adapter *padapter, u16 reg);
-
-#endif /*__RTL871X_EEPROM_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl871x_event.h b/drivers/staging/rtl8712/rtl871x_event.h
deleted file mode 100644
index 0cc780cf4341..000000000000
--- a/drivers/staging/rtl8712/rtl871x_event.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871x_EVENT_H_
-#define _RTL871x_EVENT_H_
-
-#include "osdep_service.h"
-
-#include "wlan_bssdef.h"
-#include <linux/semaphore.h>
-#include <linux/sem.h>
-
-/*
- * Used to report a bss has been scanned
- */
-struct survey_event {
- struct wlan_bssid_ex bss;
-};
-
-/*
- * Used to report that the requested site survey has been done.
- * bss_cnt indicates the number of bss that has been reported.
- */
-struct surveydone_event {
- unsigned int bss_cnt;
-
-};
-
-/*
- * Used to report the link result of joining the given bss
- * join_res:
- * -1: authentication fail
- * -2: association fail
- * > 0: TID
- */
-struct joinbss_event {
- struct wlan_network network;
-};
-
-/*
- * Used to report a given STA has joinned the created BSS.
- * It is used in AP/Ad-HoC(M) mode.
- */
-struct stassoc_event {
- unsigned char macaddr[6];
- unsigned char rsvd[2];
- __le32 cam_id;
-};
-
-struct stadel_event {
- unsigned char macaddr[6];
- unsigned char rsvd[2];
-};
-
-struct addba_event {
- unsigned int tid;
-};
-
-#define GEN_EVT_CODE(event) event ## _EVT_
-
-struct fwevent {
- u32 parmsize;
- void (*event_callback)(struct _adapter *dev, u8 *pbuf);
-};
-
-#define C2HEVENT_SZ 32
-struct event_node {
- unsigned char *node;
- unsigned char evt_code;
- unsigned short evt_sz;
- /*volatile*/ int *caller_ff_tail;
- int caller_ff_sz;
-};
-
-struct c2hevent_queue {
- /*volatile*/ int head;
- /*volatile*/ int tail;
- struct event_node nodes[C2HEVENT_SZ];
- unsigned char seq;
-};
-
-#define NETWORK_QUEUE_SZ 4
-
-struct network_queue {
- /*volatile*/ int head;
- /*volatile*/ int tail;
- struct wlan_bssid_ex networks[NETWORK_QUEUE_SZ];
-};
-
-struct ADDBA_Req_Report_parm {
- unsigned char MacAddress[ETH_ALEN];
- unsigned short StartSeqNum;
- unsigned char tid;
-};
-
-#include "rtl8712_event.h"
-
-#endif /* _WLANEVENT_H_ */
-
diff --git a/drivers/staging/rtl8712/rtl871x_ht.h b/drivers/staging/rtl8712/rtl871x_ht.h
deleted file mode 100644
index ebd78665775d..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ht.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871X_HT_H_
-#define _RTL871X_HT_H_
-
-#include "osdep_service.h"
-#include "wifi.h"
-
-struct ht_priv {
- unsigned int ht_option;
- unsigned int ampdu_enable;/*for enable Tx A-MPDU*/
- unsigned char baddbareq_issued[16];
- unsigned int tx_amsdu_enable;/*for enable Tx A-MSDU */
- unsigned int tx_amdsu_maxlen; /* 1: 8k, 0:4k ; default:8k, for tx */
- unsigned int rx_ampdu_maxlen; /* for rx reordering ctrl win_sz,
- * updated when join_callback.
- */
- struct ieee80211_ht_cap ht_cap;
-};
-
-#endif /*_RTL871X_HT_H_ */
-
diff --git a/drivers/staging/rtl8712/rtl871x_io.c b/drivers/staging/rtl8712/rtl871x_io.c
deleted file mode 100644
index 20e080e284dd..000000000000
--- a/drivers/staging/rtl8712/rtl871x_io.c
+++ /dev/null
@@ -1,147 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_io.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-/*
- *
- * The purpose of rtl871x_io.c
- *
- * a. provides the API
- * b. provides the protocol engine
- * c. provides the software interface between caller and the hardware interface
- *
- * For r8712u, both sync/async operations are provided.
- *
- * Only sync read/write_mem operations are provided.
- *
- */
-
-#define _RTL871X_IO_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "rtl871x_io.h"
-#include "osdep_intf.h"
-#include "usb_ops.h"
-
-static uint _init_intf_hdl(struct _adapter *padapter,
- struct intf_hdl *pintf_hdl)
-{
- struct intf_priv *pintf_priv;
- void (*set_intf_option)(u32 *poption) = NULL;
- void (*set_intf_funs)(struct intf_hdl *pintf_hdl);
- void (*set_intf_ops)(struct _io_ops *pops);
- uint (*init_intf_priv)(struct intf_priv *pintfpriv);
-
- set_intf_option = &(r8712_usb_set_intf_option);
- set_intf_funs = &(r8712_usb_set_intf_funs);
- set_intf_ops = &r8712_usb_set_intf_ops;
- init_intf_priv = &r8712_usb_init_intf_priv;
- pintf_priv = kmalloc(sizeof(*pintf_priv), GFP_ATOMIC);
- pintf_hdl->pintfpriv = pintf_priv;
- if (!pintf_priv)
- goto _init_intf_hdl_fail;
- pintf_hdl->adapter = (u8 *)padapter;
- set_intf_option(&pintf_hdl->intf_option);
- set_intf_funs(pintf_hdl);
- set_intf_ops(&pintf_hdl->io_ops);
- pintf_priv->intf_dev = (u8 *)&padapter->dvobjpriv;
- if (init_intf_priv(pintf_priv) == _FAIL)
- goto _init_intf_hdl_fail;
- return _SUCCESS;
-_init_intf_hdl_fail:
- kfree(pintf_priv);
- return _FAIL;
-}
-
-static void _unload_intf_hdl(struct intf_priv *pintfpriv)
-{
- void (*unload_intf_priv)(struct intf_priv *pintfpriv);
-
- unload_intf_priv = &r8712_usb_unload_intf_priv;
- unload_intf_priv(pintfpriv);
- kfree(pintfpriv);
-}
-
-static uint register_intf_hdl(u8 *dev, struct intf_hdl *pintfhdl)
-{
- struct _adapter *adapter = (struct _adapter *)dev;
-
- pintfhdl->intf_option = 0;
- pintfhdl->adapter = dev;
- pintfhdl->intf_dev = (u8 *)&adapter->dvobjpriv;
- if (!_init_intf_hdl(adapter, pintfhdl))
- goto register_intf_hdl_fail;
- return _SUCCESS;
-register_intf_hdl_fail:
- return false;
-}
-
-static void unregister_intf_hdl(struct intf_hdl *pintfhdl)
-{
- _unload_intf_hdl(pintfhdl->pintfpriv);
- memset((u8 *)pintfhdl, 0, sizeof(struct intf_hdl));
-}
-
-uint r8712_alloc_io_queue(struct _adapter *adapter)
-{
- u32 i;
- struct io_queue *pio_queue;
- struct io_req *pio_req;
-
- pio_queue = kmalloc(sizeof(*pio_queue), GFP_ATOMIC);
- if (!pio_queue)
- goto alloc_io_queue_fail;
- INIT_LIST_HEAD(&pio_queue->free_ioreqs);
- INIT_LIST_HEAD(&pio_queue->processing);
- INIT_LIST_HEAD(&pio_queue->pending);
- spin_lock_init(&pio_queue->lock);
- pio_queue->pallocated_free_ioreqs_buf = kzalloc(NUM_IOREQ *
- (sizeof(struct io_req)) + 4,
- GFP_ATOMIC);
- if ((pio_queue->pallocated_free_ioreqs_buf) == NULL)
- goto alloc_io_queue_fail;
- pio_queue->free_ioreqs_buf = pio_queue->pallocated_free_ioreqs_buf + 4
- - ((addr_t)(pio_queue->pallocated_free_ioreqs_buf)
- & 3);
- pio_req = (struct io_req *)(pio_queue->free_ioreqs_buf);
- for (i = 0; i < NUM_IOREQ; i++) {
- INIT_LIST_HEAD(&pio_req->list);
- list_add_tail(&pio_req->list, &pio_queue->free_ioreqs);
- pio_req++;
- }
- if ((register_intf_hdl((u8 *)adapter, &pio_queue->intf)) == _FAIL)
- goto alloc_io_queue_fail;
- adapter->pio_queue = pio_queue;
- return _SUCCESS;
-alloc_io_queue_fail:
- if (pio_queue) {
- kfree(pio_queue->pallocated_free_ioreqs_buf);
- kfree(pio_queue);
- }
- adapter->pio_queue = NULL;
- return _FAIL;
-}
-
-void r8712_free_io_queue(struct _adapter *adapter)
-{
- struct io_queue *pio_queue = adapter->pio_queue;
-
- if (pio_queue) {
- kfree(pio_queue->pallocated_free_ioreqs_buf);
- adapter->pio_queue = NULL;
- unregister_intf_hdl(&pio_queue->intf);
- kfree(pio_queue);
- }
-}
diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h
deleted file mode 100644
index f09d50a29b82..000000000000
--- a/drivers/staging/rtl8712/rtl871x_io.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871X_IO_H_
-#define _RTL871X_IO_H_
-
-#include "osdep_service.h"
-#include "osdep_intf.h"
-
-#define NUM_IOREQ 8
-
-#define MAX_PROT_SZ (64-16)
-
-#define _IOREADY 0
-#define _IO_WAIT_COMPLETE 1
-#define _IO_WAIT_RSP 2
-
-/* IO COMMAND TYPE */
-#define _IOSZ_MASK_ (0x7F)
-#define _IO_WRITE_ BIT(7)
-#define _IO_FIXED_ BIT(8)
-#define _IO_BURST_ BIT(9)
-#define _IO_BYTE_ BIT(10)
-#define _IO_HW_ BIT(11)
-#define _IO_WORD_ BIT(12)
-#define _IO_SYNC_ BIT(13)
-#define _IO_CMDMASK_ (0x1F80)
-
-/*
- * For prompt mode accessing, caller shall free io_req
- * Otherwise, io_handler will free io_req
- */
-/* IO STATUS TYPE */
-#define _IO_ERR_ BIT(2)
-#define _IO_SUCCESS_ BIT(1)
-#define _IO_DONE_ BIT(0)
-#define IO_RD32 (_IO_SYNC_ | _IO_WORD_)
-#define IO_RD16 (_IO_SYNC_ | _IO_HW_)
-#define IO_RD8 (_IO_SYNC_ | _IO_BYTE_)
-#define IO_RD32_ASYNC (_IO_WORD_)
-#define IO_RD16_ASYNC (_IO_HW_)
-#define IO_RD8_ASYNC (_IO_BYTE_)
-#define IO_WR32 (_IO_WRITE_ | _IO_SYNC_ | _IO_WORD_)
-#define IO_WR16 (_IO_WRITE_ | _IO_SYNC_ | _IO_HW_)
-#define IO_WR8 (_IO_WRITE_ | _IO_SYNC_ | _IO_BYTE_)
-#define IO_WR32_ASYNC (_IO_WRITE_ | _IO_WORD_)
-#define IO_WR16_ASYNC (_IO_WRITE_ | _IO_HW_)
-#define IO_WR8_ASYNC (_IO_WRITE_ | _IO_BYTE_)
-/*
- * Only Sync. burst accessing is provided.
- */
-#define IO_WR_BURST(x) (IO_WRITE_ | _IO_SYNC_ | _IO_BURST_ | \
- ((x) & _IOSZ_MASK_))
-#define IO_RD_BURST(x) (_IO_SYNC_ | _IO_BURST_ | ((x) & _IOSZ_MASK_))
-/*below is for the intf_option bit definition...*/
-#define _INTF_ASYNC_ BIT(0) /*support async io*/
-struct intf_priv;
-struct intf_hdl;
-struct io_queue;
-struct _io_ops {
- uint (*_sdbus_read_bytes_to_membuf)(struct intf_priv *pintfpriv,
- u32 addr, u32 cnt, u8 *pbuf);
- uint (*_sdbus_read_blocks_to_membuf)(struct intf_priv *pintfpriv,
- u32 addr, u32 cnt, u8 *pbuf);
- u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
- u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
- u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
- uint (*_sdbus_write_blocks_from_membuf)(struct intf_priv *pintfpriv,
- u32 addr, u32 cnt, u8 *pbuf,
- u8 async);
- uint (*_sdbus_write_bytes_from_membuf)(struct intf_priv *pintfpriv,
- u32 addr, u32 cnt, u8 *pbuf);
- u8 (*_cmd52r)(struct intf_priv *pintfpriv, u32 addr);
- void (*_cmd52w)(struct intf_priv *pintfpriv, u32 addr, u8 val8);
- u8 (*_cmdfunc152r)(struct intf_priv *pintfpriv, u32 addr);
- void (*_cmdfunc152w)(struct intf_priv *pintfpriv, u32 addr, u8 val8);
- void (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
- void (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
- void (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
- void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
- u8 *pmem);
- void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
- u8 *pmem);
- void (*_sync_irp_protocol_rw)(struct io_queue *pio_q);
- u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
- u8 *pmem);
- u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
- u8 *pmem);
-};
-
-struct io_req {
- struct list_head list;
- u32 addr;
- /*volatile*/ u32 val;
- u32 command;
- u32 status;
- u8 *pbuf;
- void (*_async_io_callback)(struct _adapter *padapter,
- struct io_req *pio_req, u8 *cnxt);
- u8 *cnxt;
-};
-
-struct intf_hdl {
- u32 intf_option;
- u8 *adapter;
- u8 *intf_dev;
- struct intf_priv *pintfpriv;
- void (*intf_hdl_init)(u8 *priv);
- void (*intf_hdl_unload)(u8 *priv);
- void (*intf_hdl_open)(u8 *priv);
- void (*intf_hdl_close)(u8 *priv);
- struct _io_ops io_ops;
-};
-
-struct reg_protocol_rd {
-#ifdef __LITTLE_ENDIAN
- /* DW1 */
- u32 NumOfTrans:4;
- u32 Reserved1:4;
- u32 Reserved2:24;
- /* DW2 */
- u32 ByteCount:7;
- u32 WriteEnable:1; /*0:read, 1:write*/
- u32 FixOrContinuous:1; /*0:continuous, 1: Fix*/
- u32 BurstMode:1;
- u32 Byte1Access:1;
- u32 Byte2Access:1;
- u32 Byte4Access:1;
- u32 Reserved3:3;
- u32 Reserved4:16;
- /*DW3*/
- u32 BusAddress;
- /*DW4*/
-#else
-/*DW1*/
- u32 Reserved1:4;
- u32 NumOfTrans:4;
- u32 Reserved2:24;
- /*DW2*/
- u32 WriteEnable:1;
- u32 ByteCount:7;
- u32 Reserved3:3;
- u32 Byte4Access:1;
- u32 Byte2Access:1;
- u32 Byte1Access:1;
- u32 BurstMode:1;
- u32 FixOrContinuous:1;
- u32 Reserved4:16;
- /*DW3*/
- u32 BusAddress;
- /*DW4*/
-#endif
-};
-
-struct reg_protocol_wt {
-#ifdef __LITTLE_ENDIAN
- /*DW1*/
- u32 NumOfTrans:4;
- u32 Reserved1:4;
- u32 Reserved2:24;
- /*DW2*/
- u32 ByteCount:7;
- u32 WriteEnable:1; /*0:read, 1:write*/
- u32 FixOrContinuous:1; /*0:continuous, 1: Fix*/
- u32 BurstMode:1;
- u32 Byte1Access:1;
- u32 Byte2Access:1;
- u32 Byte4Access:1;
- u32 Reserved3:3;
- u32 Reserved4:16;
- /*DW3*/
- u32 BusAddress;
- /*DW4*/
- u32 Value;
-#else
- /*DW1*/
- u32 Reserved1:4;
- u32 NumOfTrans:4;
- u32 Reserved2:24;
- /*DW2*/
- u32 WriteEnable:1;
- u32 ByteCount:7;
- u32 Reserved3:3;
- u32 Byte4Access:1;
- u32 Byte2Access:1;
- u32 Byte1Access:1;
- u32 BurstMode:1;
- u32 FixOrContinuous:1;
- u32 Reserved4:16;
- /*DW3*/
- u32 BusAddress;
- /*DW4*/
- u32 Value;
-#endif
-};
-
-/*
- * Below is the data structure used by _io_handler
- */
-
-struct io_queue {
- spinlock_t lock;
- struct list_head free_ioreqs;
- /*The io_req list that will be served in the single protocol r/w.*/
- struct list_head pending;
- struct list_head processing;
- u8 *free_ioreqs_buf; /* 4-byte aligned */
- u8 *pallocated_free_ioreqs_buf;
- struct intf_hdl intf;
-};
-
-u8 r8712_read8(struct _adapter *adapter, u32 addr);
-u16 r8712_read16(struct _adapter *adapter, u32 addr);
-u32 r8712_read32(struct _adapter *adapter, u32 addr);
-void r8712_read_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-void r8712_read_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-void r8712_write8(struct _adapter *adapter, u32 addr, u8 val);
-void r8712_write16(struct _adapter *adapter, u32 addr, u16 val);
-void r8712_write32(struct _adapter *adapter, u32 addr, u32 val);
-void r8712_write_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-void r8712_write_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-/*ioreq */
-uint r8712_alloc_io_queue(struct _adapter *adapter);
-void r8712_free_io_queue(struct _adapter *adapter);
-
-#endif /*_RTL871X_IO_H_*/
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl.h b/drivers/staging/rtl8712/rtl871x_ioctl.h
deleted file mode 100644
index d6332a8c7f4f..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ioctl.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __IOCTL_H
-#define __IOCTL_H
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#ifndef OID_802_11_CAPABILITY
- #define OID_802_11_CAPABILITY 0x0d010122
-#endif
-
-#ifndef OID_802_11_PMKID
- #define OID_802_11_PMKID 0x0d010123
-#endif
-
-/* For DDK-defined OIDs*/
-#define OID_NDIS_SEG1 0x00010100
-#define OID_NDIS_SEG2 0x00010200
-#define OID_NDIS_SEG3 0x00020100
-#define OID_NDIS_SEG4 0x01010100
-#define OID_NDIS_SEG5 0x01020100
-#define OID_NDIS_SEG6 0x01020200
-#define OID_NDIS_SEG7 0xFD010100
-#define OID_NDIS_SEG8 0x0D010100
-#define OID_NDIS_SEG9 0x0D010200
-#define OID_NDIS_SEG10 0x0D020200
-#define SZ_OID_NDIS_SEG1 23
-#define SZ_OID_NDIS_SEG2 3
-#define SZ_OID_NDIS_SEG3 6
-#define SZ_OID_NDIS_SEG4 6
-#define SZ_OID_NDIS_SEG5 4
-#define SZ_OID_NDIS_SEG6 8
-#define SZ_OID_NDIS_SEG7 7
-#define SZ_OID_NDIS_SEG8 36
-#define SZ_OID_NDIS_SEG9 24
-#define SZ_OID_NDIS_SEG10 19
-
-/* For Realtek-defined OIDs*/
-#define OID_MP_SEG1 0xFF871100
-#define OID_MP_SEG2 0xFF818000
-#define OID_MP_SEG3 0xFF818700
-#define OID_MP_SEG4 0xFF011100
-
-enum oid_type {
- QUERY_OID,
- SET_OID
-};
-
-struct oid_funs_node {
- unsigned int oid_start; /*the starting number for OID*/
- unsigned int oid_end; /*the ending number for OID*/
- struct oid_obj_priv *node_array;
- unsigned int array_sz; /*the size of node_array*/
- int query_counter; /*count the number of query hits for this segment*/
- int set_counter; /*count the number of set hits for this segment*/
-};
-
-struct oid_par_priv {
- void *adapter_context;
- uint oid;
- void *information_buf;
- unsigned long information_buf_len;
- unsigned long *bytes_rw;
- unsigned long *bytes_needed;
- enum oid_type type_of_oid;
- unsigned int dbg;
-};
-
-struct oid_obj_priv {
- unsigned char dbg; /* 0: without OID debug message
- * 1: with OID debug message
- */
- uint (*oidfuns)(struct oid_par_priv *poid_par_priv);
-};
-
-uint oid_null_function(struct oid_par_priv *poid_par_priv);
-
-extern struct iw_handler_def r871x_handlers_def;
-
-uint drv_query_info(struct net_device *MiniportAdapterContext,
- uint Oid,
- void *InformationBuffer,
- u32 InformationBufferLength,
- u32 *BytesWritten,
- u32 *BytesNeeded);
-
-uint drv_set_info(struct net_device *MiniportAdapterContext,
- uint Oid,
- void *InformationBuffer,
- u32 InformationBufferLength,
- u32 *BytesRead,
- u32 *BytesNeeded);
-
-#endif
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
deleted file mode 100644
index 0653aa27b1fa..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ /dev/null
@@ -1,2275 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_ioctl_linux.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_IOCTL_LINUX_C_
-#define _RTL871X_MP_IOCTL_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "wlan_bssdef.h"
-#include "rtl871x_debug.h"
-#include "wifi.h"
-#include "rtl871x_mlme.h"
-#include "rtl871x_ioctl.h"
-#include "rtl871x_ioctl_set.h"
-#include "rtl871x_mp_ioctl.h"
-#include "mlme_osdep.h"
-#include <linux/wireless.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/semaphore.h>
-#include <net/iw_handler.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-
-#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
-
-#define SCAN_ITEM_SIZE 768
-#define MAX_CUSTOM_LEN 64
-#define RATE_COUNT 4
-
-static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
- 6000000, 9000000, 12000000, 18000000,
- 24000000, 36000000, 48000000, 54000000};
-
-static const long ieee80211_wlan_frequencies[] = {
- 2412, 2417, 2422, 2427,
- 2432, 2437, 2442, 2447,
- 2452, 2457, 2462, 2467,
- 2472, 2484
-};
-
-void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
-{
- union iwreq_data wrqu;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
- wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
-}
-
-void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
-{
- union iwreq_data wrqu;
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- eth_zero_addr(wrqu.ap_addr.sa_data);
- wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
-}
-
-static inline void handle_pairwise_key(struct sta_info *psta,
- struct ieee_param *param,
- struct _adapter *padapter)
-{
- /* pairwise key */
- memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
- (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
- if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
- memcpy(psta->tkiptxmickey. skey,
- &param->u.crypt.key[16], 8);
- memcpy(psta->tkiprxmickey. skey,
- &param->u.crypt.key[24], 8);
- padapter->securitypriv. busetkipkey = false;
- mod_timer(&padapter->securitypriv.tkip_timer,
- jiffies + msecs_to_jiffies(50));
- }
- r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
-}
-
-static inline void handle_group_key(struct ieee_param *param,
- struct _adapter *padapter)
-{
- union Keytype *gk = padapter->securitypriv.XGrpKey;
- union Keytype *gtk = padapter->securitypriv.XGrptxmickey;
- union Keytype *grk = padapter->securitypriv.XGrprxmickey;
-
- if (param->u.crypt.idx > 0 &&
- param->u.crypt.idx < 3) {
- /* group key idx is 1 or 2 */
- memcpy(gk[param->u.crypt.idx - 1].skey,
- param->u.crypt.key,
- (param->u.crypt.key_len > 16 ? 16 :
- param->u.crypt.key_len));
- memcpy(gtk[param->u.crypt.idx - 1].skey,
- &param->u.crypt.key[16], 8);
- memcpy(grk[param->u.crypt.idx - 1].skey,
- &param->u.crypt.key[24], 8);
- padapter->securitypriv.binstallGrpkey = true;
- r8712_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx);
- if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
- if (padapter->registrypriv.power_mgnt != padapter->pwrctrlpriv.pwr_mode)
- mod_timer(&padapter->mlmepriv.dhcp_timer,
- jiffies + msecs_to_jiffies(60000));
- }
- }
-}
-
-static noinline_for_stack char *translate_scan_wpa(struct iw_request_info *info,
- struct wlan_network *pnetwork,
- struct iw_event *iwe,
- char *start, char *stop)
-{
- /* parsing WPA/WPA2 IE */
- u8 buf[MAX_WPA_IE_LEN];
- u8 wpa_ie[255], rsn_ie[255];
- u16 wpa_len = 0, rsn_len = 0;
- int n, i;
-
- r8712_get_sec_ie(pnetwork->network.IEs,
- pnetwork->network.IELength, rsn_ie, &rsn_len,
- wpa_ie, &wpa_len);
- if (wpa_len > 0) {
- memset(buf, 0, MAX_WPA_IE_LEN);
- n = sprintf(buf, "wpa_ie=");
- for (i = 0; i < wpa_len; i++) {
- n += scnprintf(buf + n, MAX_WPA_IE_LEN - n,
- "%02x", wpa_ie[i]);
- if (n == MAX_WPA_IE_LEN - 1)
- break;
- }
- memset(iwe, 0, sizeof(*iwe));
- iwe->cmd = IWEVCUSTOM;
- iwe->u.data.length = (u16)strlen(buf);
- start = iwe_stream_add_point(info, start, stop, iwe, buf);
- memset(iwe, 0, sizeof(*iwe));
- iwe->cmd = IWEVGENIE;
- iwe->u.data.length = (u16)wpa_len;
- start = iwe_stream_add_point(info, start, stop, iwe, wpa_ie);
- }
- if (rsn_len > 0) {
- memset(buf, 0, MAX_WPA_IE_LEN);
- n = sprintf(buf, "rsn_ie=");
- for (i = 0; i < rsn_len; i++) {
- n += scnprintf(buf + n, MAX_WPA_IE_LEN - n,
- "%02x", rsn_ie[i]);
- if (n == MAX_WPA_IE_LEN - 1)
- break;
- }
- memset(iwe, 0, sizeof(*iwe));
- iwe->cmd = IWEVCUSTOM;
- iwe->u.data.length = strlen(buf);
- start = iwe_stream_add_point(info, start, stop, iwe, buf);
- memset(iwe, 0, sizeof(*iwe));
- iwe->cmd = IWEVGENIE;
- iwe->u.data.length = rsn_len;
- start = iwe_stream_add_point(info, start, stop, iwe, rsn_ie);
- }
-
- return start;
-}
-
-static noinline_for_stack char *translate_scan_wps(struct iw_request_info *info,
- struct wlan_network *pnetwork,
- struct iw_event *iwe,
- char *start, char *stop)
-{
- /* parsing WPS IE */
- u8 wps_ie[512];
- uint wps_ielen;
-
- if (r8712_get_wps_ie(pnetwork->network.IEs, pnetwork->network.IELength, wps_ie, &wps_ielen)) {
- if (wps_ielen > 2) {
- iwe->cmd = IWEVGENIE;
- iwe->u.data.length = (u16)wps_ielen;
- start = iwe_stream_add_point(info, start, stop, iwe, wps_ie);
- }
- }
-
- return start;
-}
-
-static char *translate_scan(struct _adapter *padapter,
- struct iw_request_info *info,
- struct wlan_network *pnetwork,
- char *start, char *stop)
-{
- struct iw_event iwe;
- char *current_val;
- s8 *p;
- u32 i = 0, ht_ielen = 0;
- u16 cap, ht_cap = false;
- u8 rssi;
-
- if ((pnetwork->network.Configuration.DSConfig < 1) ||
- (pnetwork->network.Configuration.DSConfig > 14)) {
- if (pnetwork->network.Configuration.DSConfig < 1)
- pnetwork->network.Configuration.DSConfig = 1;
- else
- pnetwork->network.Configuration.DSConfig = 14;
- }
- /* AP MAC address */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
- ether_addr_copy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress);
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
- /* Add the ESSID */
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- iwe.u.data.length = min_t(u32, pnetwork->network.Ssid.SsidLength, 32);
- start = iwe_stream_add_point(info, start, stop, &iwe,
- pnetwork->network.Ssid.Ssid);
- /* parsing HT_CAP_IE */
- p = r8712_get_ie(&pnetwork->network.IEs[12], WLAN_EID_HT_CAPABILITY,
- &ht_ielen, pnetwork->network.IELength - 12);
- if (p && ht_ielen > 0)
- ht_cap = true;
- /* Add the protocol name */
- iwe.cmd = SIOCGIWNAME;
- if (r8712_is_cckratesonly_included(pnetwork->network.rates)) {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
- } else if (r8712_is_cckrates_included(pnetwork->network.rates)) {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
- } else {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
- }
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
- /* Add mode */
- iwe.cmd = SIOCGIWMODE;
- memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs), 2);
- le16_to_cpus(&cap);
- if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_ESS)) {
- if (cap & WLAN_CAPABILITY_ESS)
- iwe.u.mode = (u32)IW_MODE_MASTER;
- else
- iwe.u.mode = (u32)IW_MODE_ADHOC;
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
- }
- /* Add frequency/channel */
- iwe.cmd = SIOCGIWFREQ;
- {
- /* check legal index */
- u8 dsconfig = pnetwork->network.Configuration.DSConfig;
-
- if (dsconfig >= 1 && dsconfig <= sizeof(ieee80211_wlan_frequencies) / sizeof(long))
- iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[dsconfig - 1] * 100000);
- else
- iwe.u.freq.m = 0;
- }
- iwe.u.freq.e = (s16)1;
- iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
- start = iwe_stream_add_event(info, start, stop, &iwe,
- IW_EV_FREQ_LEN);
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (cap & WLAN_CAPABILITY_PRIVACY)
- iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED | IW_ENCODE_NOKEY);
- else
- iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
- iwe.u.data.length = (u16)0;
- start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
- /*Add basic and extended rates */
- current_val = start + iwe_stream_lcp_len(info);
- iwe.cmd = SIOCGIWRATE;
- iwe.u.bitrate.fixed = 0;
- iwe.u.bitrate.disabled = 0;
- iwe.u.bitrate.value = 0;
- i = 0;
- while (pnetwork->network.rates[i] != 0) {
- /* Bit rate given in 500 kb/s units */
- iwe.u.bitrate.value = (pnetwork->network.rates[i++] & 0x7F) * 500000;
- current_val = iwe_stream_add_value(info, start, current_val, stop, &iwe,
- IW_EV_PARAM_LEN);
- }
- /* Check if we added any event */
- if ((current_val - start) > iwe_stream_lcp_len(info))
- start = current_val;
-
- start = translate_scan_wpa(info, pnetwork, &iwe, start, stop);
-
- start = translate_scan_wps(info, pnetwork, &iwe, start, stop);
-
- /* Add quality statistics */
- iwe.cmd = IWEVQUAL;
- rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
- /* we only update signal_level (signal strength) that is rssi. */
- iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID);
- iwe.u.qual.level = rssi; /* signal strength */
- iwe.u.qual.qual = 0; /* signal quality */
- iwe.u.qual.noise = 0; /* noise level */
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
- /* how to translate rssi to ?% */
- return start;
-}
-
-static int wpa_set_auth_algs(struct net_device *dev, u32 value)
-{
- struct _adapter *padapter = netdev_priv(dev);
- int ret = 0;
-
- if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeAutoSwitch;
- padapter->securitypriv.AuthAlgrthm = 3;
- } else if (value & AUTH_ALG_SHARED_KEY) {
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
- padapter->securitypriv.AuthAlgrthm = 1;
- } else if (value & AUTH_ALG_OPEN_SYSTEM) {
- if (padapter->securitypriv.ndisauthtype <
- Ndis802_11AuthModeWPAPSK) {
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeOpen;
- padapter->securitypriv.AuthAlgrthm = 0;
- }
- } else {
- ret = -EINVAL;
- }
- return ret;
-}
-
-static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
- u32 param_len)
-{
- int ret = 0;
- u32 wep_key_idx, wep_key_len = 0;
- struct NDIS_802_11_WEP *pwep = NULL;
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- param->u.crypt.err = 0;
- param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
- if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
- param->u.crypt.key_len)
- return -EINVAL;
- if (!is_broadcast_ether_addr(param->sta_addr))
- return -EINVAL;
-
- if (param->u.crypt.idx >= WEP_KEYS) {
- /* for large key indices, set the default (0) */
- param->u.crypt.idx = 0;
- }
- if (strcmp(param->u.crypt.alg, "WEP") == 0) {
- netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.XGrpPrivacy = _WEP40_;
- wep_key_idx = param->u.crypt.idx;
- wep_key_len = param->u.crypt.key_len;
- if (wep_key_idx >= WEP_KEYS)
- wep_key_idx = 0;
- if (wep_key_len <= 0)
- return -EINVAL;
-
- wep_key_len = wep_key_len <= 5 ? 5 : 13;
- pwep = kzalloc(sizeof(*pwep), GFP_ATOMIC);
- if (!pwep)
- return -ENOMEM;
- pwep->KeyLength = wep_key_len;
- pwep->Length = wep_key_len +
- offsetof(struct NDIS_802_11_WEP, KeyMaterial);
- if (wep_key_len == 13) {
- padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
- padapter->securitypriv.XGrpPrivacy = _WEP104_;
- }
- pwep->KeyIndex = wep_key_idx;
- pwep->KeyIndex |= 0x80000000;
- memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
- if (param->u.crypt.set_tx) {
- if (r8712_set_802_11_add_wep(padapter, pwep))
- ret = -EOPNOTSUPP;
- } else {
- /* don't update "psecuritypriv->PrivacyAlgrthm" and
- * "psecuritypriv->PrivacyKeyIndex=keyid", but can
- * r8712_set_key to fw/cam
- */
- if (wep_key_idx >= WEP_KEYS) {
- ret = -EOPNOTSUPP;
- goto exit;
- }
- memcpy(&psecuritypriv->DefKey[wep_key_idx].skey[0],
- pwep->KeyMaterial,
- pwep->KeyLength);
- psecuritypriv->DefKeylen[wep_key_idx] =
- pwep->KeyLength;
- r8712_set_key(padapter, psecuritypriv, wep_key_idx);
- }
- goto exit;
- }
- if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
- struct sta_info *psta, *pbcmc_sta;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct security_priv *spriv = &padapter->securitypriv;
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
- WIFI_MP_STATE)) { /* sta mode */
- psta = r8712_get_stainfo(pstapriv,
- get_bssid(pmlmepriv));
- if (psta) {
- psta->ieee8021x_blocked = false;
- if (spriv->ndisencryptstatus ==
- Ndis802_11Encryption2Enabled ||
- spriv->ndisencryptstatus ==
- Ndis802_11Encryption3Enabled)
- psta->XPrivacy = spriv->PrivacyAlgrthm;
- if (param->u.crypt.set_tx == 1)
- handle_pairwise_key(psta, param,
- padapter);
- else /* group key */
- handle_group_key(param, padapter);
- }
- pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
- if (pbcmc_sta) {
- pbcmc_sta->ieee8021x_blocked = false;
- if (spriv->ndisencryptstatus ==
- Ndis802_11Encryption2Enabled ||
- spriv->ndisencryptstatus ==
- Ndis802_11Encryption3Enabled)
- pbcmc_sta->XPrivacy =
- spriv->PrivacyAlgrthm;
- }
- }
- }
-exit:
- kfree(pwep);
- return ret;
-}
-
-static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
- unsigned short ielen)
-{
- u8 *buf = NULL;
- int group_cipher = 0, pairwise_cipher = 0;
- int ret = 0;
-
- if (ielen > MAX_WPA_IE_LEN || !pie)
- return -EINVAL;
- if (ielen) {
- buf = kmemdup(pie, ielen, GFP_ATOMIC);
- if (!buf)
- return -ENOMEM;
- if (ielen < RSN_HEADER_LEN) {
- ret = -EINVAL;
- goto exit;
- }
- if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
- &pairwise_cipher) == 0) {
- padapter->securitypriv.AuthAlgrthm = 2;
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeWPAPSK;
- }
- if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
- &pairwise_cipher) == 0) {
- padapter->securitypriv.AuthAlgrthm = 2;
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeWPA2PSK;
- }
- switch (group_cipher) {
- case WPA_CIPHER_NONE:
- padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- break;
- case WPA_CIPHER_WEP40:
- padapter->securitypriv.XGrpPrivacy = _WEP40_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- case WPA_CIPHER_TKIP:
- padapter->securitypriv.XGrpPrivacy = _TKIP_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
- break;
- case WPA_CIPHER_CCMP:
- padapter->securitypriv.XGrpPrivacy = _AES_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
- break;
- case WPA_CIPHER_WEP104:
- padapter->securitypriv.XGrpPrivacy = _WEP104_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- }
- switch (pairwise_cipher) {
- case WPA_CIPHER_NONE:
- padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- break;
- case WPA_CIPHER_WEP40:
- padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- case WPA_CIPHER_TKIP:
- padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
- break;
- case WPA_CIPHER_CCMP:
- padapter->securitypriv.PrivacyAlgrthm = _AES_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
- break;
- case WPA_CIPHER_WEP104:
- padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- }
- padapter->securitypriv.wps_phase = false;
- {/* set wps_ie */
- u16 cnt = 0;
- u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
-
- while (cnt < ielen) {
- eid = buf[cnt];
-
- if ((eid == WLAN_EID_VENDOR_SPECIFIC) &&
- (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
- netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
- padapter->securitypriv.wps_ie_len =
- ((buf[cnt + 1] + 2) <
- (MAX_WPA_IE_LEN << 2)) ?
- (buf[cnt + 1] + 2) :
- (MAX_WPA_IE_LEN << 2);
- memcpy(padapter->securitypriv.wps_ie,
- &buf[cnt],
- padapter->securitypriv.wps_ie_len);
- padapter->securitypriv.wps_phase =
- true;
- netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
- cnt += buf[cnt + 1] + 2;
- break;
- }
-
- cnt += buf[cnt + 1] + 2;
- }
- }
- }
-exit:
- kfree(buf);
- return ret;
-}
-
-static int r8711_wx_get_name(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- u32 ht_ielen = 0;
- char *p;
- u8 ht_cap = false;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- u8 *prates;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) == true) {
- /* parsing HT_CAP_IE */
- p = r8712_get_ie(&pcur_bss->IEs[12], WLAN_EID_HT_CAPABILITY,
- &ht_ielen, pcur_bss->IELength - 12);
- if (p && ht_ielen > 0)
- ht_cap = true;
- prates = pcur_bss->rates;
- if (r8712_is_cckratesonly_included(prates)) {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11bn");
- else
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11b");
- } else if (r8712_is_cckrates_included(prates)) {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11bgn");
- else
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11bg");
- } else {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11gn");
- else
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11g");
- }
- } else {
- snprintf(wrqu->name, IFNAMSIZ, "unassociated");
- }
- return 0;
-}
-
-static const long frequency_list[] = {
- 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
- 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
- 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
- 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
- 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
- 5825
-};
-
-static int r8711_wx_set_freq(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_freq *fwrq = &wrqu->freq;
- int rc = 0;
-
-/* If setting by frequency, convert to a channel */
- if ((fwrq->e == 1) && (fwrq->m >= 241200000) && (fwrq->m <= 248700000)) {
- int f = fwrq->m / 100000;
- int c = 0;
-
- while ((c < 14) && (f != frequency_list[c]))
- c++;
- fwrq->e = 0;
- fwrq->m = c + 1;
- }
- /* Setting by channel number */
- if ((fwrq->m > 14) || (fwrq->e > 0)) {
- rc = -EOPNOTSUPP;
- } else {
- int channel = fwrq->m;
-
- if ((channel < 1) || (channel > 14)) {
- rc = -EINVAL;
- } else {
- /* Yes ! We can set it !!! */
- padapter->registrypriv.channel = channel;
- }
- }
- return rc;
-}
-
-static int r8711_wx_get_freq(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
-
- if (!check_fwstate(pmlmepriv, _FW_LINKED))
- return -ENOLINK;
-
- wrqu->freq.m = ieee80211_wlan_frequencies[
- pcur_bss->Configuration.DSConfig - 1] * 100000;
- wrqu->freq.e = 1;
- wrqu->freq.i = pcur_bss->Configuration.DSConfig;
-
- return 0;
-}
-
-static int r8711_wx_set_mode(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct _adapter *padapter = netdev_priv(dev);
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
-
- switch (wrqu->mode) {
- case IW_MODE_AUTO:
- networkType = Ndis802_11AutoUnknown;
- break;
- case IW_MODE_ADHOC:
- networkType = Ndis802_11IBSS;
- break;
- case IW_MODE_MASTER:
- networkType = Ndis802_11APMode;
- break;
- case IW_MODE_INFRA:
- networkType = Ndis802_11Infrastructure;
- break;
- default:
- return -EINVAL;
- }
- if (Ndis802_11APMode == networkType)
- r8712_setopmode_cmd(padapter, networkType);
- else
- r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
-
- r8712_set_802_11_infrastructure_mode(padapter, networkType);
- return 0;
-}
-
-static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- wrqu->mode = IW_MODE_INFRA;
- else if (check_fwstate(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE))
- wrqu->mode = IW_MODE_ADHOC;
- else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
- wrqu->mode = IW_MODE_MASTER;
- else
- wrqu->mode = IW_MODE_AUTO;
- return 0;
-}
-
-static int r871x_wx_set_pmkid(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
- struct RT_PMKID_LIST *pl = psecuritypriv->PMKIDList;
- u8 strZeroMacAddress[ETH_ALEN] = {0x00};
- u8 strIssueBssid[ETH_ALEN] = {0x00};
- u8 j, blInserted = false;
- int intReturn = false;
-
-/*
- * There are the BSSID information in the bssid.sa_data array.
- * If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
- * all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
- * wpa_supplicant wants to add a PMKID/BSSID to driver.
- * If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
- * remove a PMKID/BSSID from driver.
- */
- if (!pPMK)
- return -EINVAL;
- memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
- switch (pPMK->cmd) {
- case IW_PMKSA_ADD:
- if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
- return intReturn;
- intReturn = true;
- blInserted = false;
- /* overwrite PMKID */
- for (j = 0; j < NUM_PMKID_CACHE; j++) {
- if (!memcmp(pl[j].Bssid, strIssueBssid, ETH_ALEN)) {
- /* BSSID is matched, the same AP => rewrite
- * with new PMKID.
- */
- netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
- __func__);
- memcpy(pl[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
- pl[j].bUsed = true;
- psecuritypriv->PMKIDIndex = j + 1;
- blInserted = true;
- break;
- }
- }
- if (!blInserted) {
- /* Find a new entry */
- netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
- __func__, psecuritypriv->PMKIDIndex);
- memcpy(pl[psecuritypriv->PMKIDIndex].Bssid,
- strIssueBssid, ETH_ALEN);
- memcpy(pl[psecuritypriv->PMKIDIndex].PMKID,
- pPMK->pmkid, IW_PMKID_LEN);
- pl[psecuritypriv->PMKIDIndex].bUsed = true;
- psecuritypriv->PMKIDIndex++;
- if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
- psecuritypriv->PMKIDIndex = 0;
- }
- break;
- case IW_PMKSA_REMOVE:
- intReturn = true;
- for (j = 0; j < NUM_PMKID_CACHE; j++) {
- if (!memcmp(pl[j].Bssid, strIssueBssid, ETH_ALEN)) {
- /* BSSID is matched, the same AP => Remove
- * this PMKID information and reset it.
- */
- eth_zero_addr(pl[j].Bssid);
- pl[j].bUsed = false;
- break;
- }
- }
- break;
- case IW_PMKSA_FLUSH:
- memset(psecuritypriv->PMKIDList, 0,
- sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
- psecuritypriv->PMKIDIndex = 0;
- intReturn = true;
- break;
- default:
- netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
- intReturn = false;
- break;
- }
- return intReturn;
-}
-
-static int r8711_wx_get_sens(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- wrqu->sens.value = 0;
- wrqu->sens.fixed = 0; /* no auto select */
- wrqu->sens.disabled = 1;
- return 0;
-}
-
-static int r8711_wx_get_range(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct iw_range *range = (struct iw_range *)extra;
- u16 val;
- int i;
-
- wrqu->data.length = sizeof(*range);
- memset(range, 0, sizeof(*range));
- /* Let's try to keep this struct in the same order as in
- * linux/include/wireless.h
- */
-
- /* TODO: See what values we can set, and remove the ones we can't
- * set, or fill them with some default data.
- */
- /* ~5 Mb/s real (802.11b) */
- range->throughput = 5 * 1000 * 1000;
- /* TODO: 8711 sensitivity ? */
- /* signal level threshold range */
- /* percent values between 0 and 100. */
- range->max_qual.qual = 100;
- range->max_qual.level = 100;
- range->max_qual.noise = 100;
- range->max_qual.updated = 7; /* Updated all three */
- range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
- /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
- range->avg_qual.level = 0x100 - 78;
- range->avg_qual.noise = 0;
- range->avg_qual.updated = 7; /* Updated all three */
- range->num_bitrates = RATE_COUNT;
- for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
- range->bitrate[i] = rtl8180_rates[i];
- range->min_frag = MIN_FRAG_THRESHOLD;
- range->max_frag = MAX_FRAG_THRESHOLD;
- range->pm_capa = 0;
- range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 16;
- range->num_channels = 14;
- for (i = 0, val = 0; i < 14; i++) {
- /* Include only legal frequencies for some countries */
- range->freq[val].i = i + 1;
- range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
- range->freq[val].e = 1;
- val++;
- if (val == IW_MAX_FREQUENCIES)
- break;
- }
- range->num_frequency = val;
- range->enc_capa = IW_ENC_CAPA_WPA |
- IW_ENC_CAPA_WPA2 |
- IW_ENC_CAPA_CIPHER_TKIP |
- IW_ENC_CAPA_CIPHER_CCMP;
- return 0;
-}
-
-static int r8711_wx_get_rate(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-
-static int r871x_wx_set_priv(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *awrq,
- char *extra)
-{
- int ret = 0, len = 0;
- char *ext;
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_point *dwrq = (struct iw_point *)awrq;
-
- len = dwrq->length;
- ext = strndup_user(dwrq->pointer, len);
- if (IS_ERR(ext))
- return PTR_ERR(ext);
-
- if (!strcasecmp(ext, "RSSI")) {
- /*Return received signal strength indicator in -db for */
- /* current AP */
- /*<ssid> Rssi xx */
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct wlan_network *pcur_network = &pmlmepriv->cur_network;
- /*static u8 xxxx; */
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- sprintf(ext, "%s rssi %d",
- pcur_network->network.Ssid.Ssid,
- /*(xxxx=xxxx+10) */
- ((padapter->recvpriv.fw_rssi) >> 1) - 95
- /*pcur_network->network.Rssi */
- );
- } else {
- sprintf(ext, "OK");
- }
- } else if (!strcasecmp(ext, "LINKSPEED")) {
- /*Return link speed in MBPS */
- /*LinkSpeed xx */
- union iwreq_data wrqd;
- int ret_inner;
- int mbps;
-
- ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
- if (ret_inner != 0)
- mbps = 0;
- else
- mbps = wrqd.bitrate.value / 1000000;
- sprintf(ext, "LINKSPEED %d", mbps);
- } else if (!strcasecmp(ext, "MACADDR")) {
- /*Return mac address of the station */
- /* Macaddr = xx:xx:xx:xx:xx:xx */
- sprintf(ext, "MACADDR = %pM", dev->dev_addr);
- } else if (!strcasecmp(ext, "SCAN-ACTIVE")) {
- /*Set scan type to active */
- /*OK if successful */
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- pmlmepriv->passive_mode = 1;
- sprintf(ext, "OK");
- } else if (!strcasecmp(ext, "SCAN-PASSIVE")) {
- /*Set scan type to passive */
- /*OK if successful */
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- pmlmepriv->passive_mode = 0;
- sprintf(ext, "OK");
- } else if (!strncmp(ext, "DCE-E", 5)) {
- /*Set scan type to passive */
- /*OK if successful */
- r8712_disconnectCtrlEx_cmd(padapter
- , 1 /*u32 enableDrvCtrl */
- , 5 /*u32 tryPktCnt */
- , 100 /*u32 tryPktInterval */
- , 5000 /*u32 firstStageTO */
- );
- sprintf(ext, "OK");
- } else if (!strncmp(ext, "DCE-D", 5)) {
- /*Set scan type to passive */
- /*OK if successfu */
- r8712_disconnectCtrlEx_cmd(padapter
- , 0 /*u32 enableDrvCtrl */
- , 5 /*u32 tryPktCnt */
- , 100 /*u32 tryPktInterval */
- , 5000 /*u32 firstStageTO */
- );
- sprintf(ext, "OK");
- } else {
- netdev_info(dev, "r8712u: %s: unknown Command %s.\n", __func__, ext);
- goto FREE_EXT;
- }
- if (copy_to_user(dwrq->pointer, ext, min(dwrq->length, (__u16)(strlen(ext) + 1))))
- ret = -EFAULT;
-
-FREE_EXT:
- kfree(ext);
- return ret;
-}
-
-/* set bssid flow
- * s1. set_802_11_infrastructure_mode()
- * s2. set_802_11_authentication_mode()
- * s3. set_802_11_encryption_mode()
- * s4. set_802_11_bssid()
- *
- * This function intends to handle the Set AP command, which specifies the
- * MAC# of a preferred Access Point.
- * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
- *
- * For this operation to succeed, there is no need for the interface to be up.
- *
- */
-static int r8711_wx_set_wap(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *awrq, char *extra)
-{
- int ret = -EINPROGRESS;
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct sockaddr *temp = (struct sockaddr *)awrq;
- unsigned long irqL;
- struct list_head *phead;
- u8 *dst_bssid;
- struct wlan_network *pnetwork = NULL;
- enum NDIS_802_11_AUTHENTICATION_MODE authmode;
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
- return -EBUSY;
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- return ret;
- if (temp->sa_family != ARPHRD_ETHER)
- return -EINVAL;
- authmode = padapter->securitypriv.ndisauthtype;
- spin_lock_irqsave(&queue->lock, irqL);
- phead = &queue->queue;
- pmlmepriv->pscanned = phead->next;
- while (1) {
- if (end_of_queue_search(phead, pmlmepriv->pscanned))
- break;
- pnetwork = container_of(pmlmepriv->pscanned,
- struct wlan_network, list);
- pmlmepriv->pscanned = pmlmepriv->pscanned->next;
- dst_bssid = pnetwork->network.MacAddress;
- if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
- r8712_set_802_11_infrastructure_mode(padapter,
- pnetwork->network.InfrastructureMode);
- break;
- }
- }
- spin_unlock_irqrestore(&queue->lock, irqL);
- if (!ret) {
- if (!r8712_set_802_11_authentication_mode(padapter, authmode)) {
- ret = -ENOMEM;
- } else {
- if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
- ret = -1;
- }
- }
- return ret;
-}
-
-static int r8711_wx_get_wap(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
-
- wrqu->ap_addr.sa_family = ARPHRD_ETHER;
- if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
- ether_addr_copy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress);
- else
- eth_zero_addr(wrqu->ap_addr.sa_data);
- return 0;
-}
-
-static int r871x_wx_set_mlme(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_mlme *mlme = (struct iw_mlme *) extra;
-
- if (!mlme)
- return -1;
- switch (mlme->cmd) {
- case IW_MLME_DEAUTH:
- if (!r8712_set_802_11_disassociate(padapter))
- ret = -1;
- break;
- case IW_MLME_DISASSOC:
- if (!r8712_set_802_11_disassociate(padapter))
- ret = -1;
- break;
- default:
- return -EOPNOTSUPP;
- }
- return ret;
-}
-
-/*
- *
- * This function intends to handle the Set Scan command.
- * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
- *
- * For this operation to succeed, the interface is brought Up beforehand.
- *
- */
-static int r8711_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 status = true;
-
- if (padapter->driver_stopped) {
- netdev_info(dev, "In %s: driver_stopped=%d\n",
- __func__, padapter->driver_stopped);
- return -1;
- }
- if (!padapter->bup)
- return -ENETDOWN;
- if (!padapter->hw_init_completed)
- return -1;
- if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) ||
- (pmlmepriv->sitesurveyctrl.traffic_busy))
- return 0;
- if (wrqu->data.length == sizeof(struct iw_scan_req)) {
- struct iw_scan_req *req = (struct iw_scan_req *)extra;
-
- if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
- struct ndis_802_11_ssid ssid;
- unsigned long irqL;
- u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
-
- memset((unsigned char *)&ssid, 0, sizeof(struct ndis_802_11_ssid));
- memcpy(ssid.Ssid, req->essid, len);
- ssid.SsidLength = len;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
- _FW_UNDER_LINKING)) ||
- (pmlmepriv->sitesurveyctrl.traffic_busy)) {
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- status = false;
- } else {
- status = r8712_sitesurvey_cmd(padapter, &ssid);
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- }
- } else {
- status = r8712_set_802_11_bssid_list_scan(padapter);
- }
- if (!status)
- return -1;
- return 0;
-}
-
-static int r8711_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct wlan_network *pnetwork = NULL;
- unsigned long irqL;
- struct list_head *plist, *phead;
- char *ev = extra;
- char *stop = ev + wrqu->data.length;
- u32 ret = 0, cnt = 0;
-
- if (padapter->driver_stopped)
- return -EINVAL;
- while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) {
- msleep(30);
- cnt++;
- if (cnt > 100)
- break;
- }
- spin_lock_irqsave(&queue->lock, irqL);
- phead = &queue->queue;
- plist = phead->next;
- while (1) {
- if (end_of_queue_search(phead, plist))
- break;
- if ((stop - ev) < SCAN_ITEM_SIZE) {
- ret = -E2BIG;
- break;
- }
- pnetwork = container_of(plist, struct wlan_network, list);
- ev = translate_scan(padapter, a, pnetwork, ev, stop);
- plist = plist->next;
- }
- spin_unlock_irqrestore(&queue->lock, irqL);
- wrqu->data.length = ev - extra;
- wrqu->data.flags = 0;
- return ret;
-}
-
-/* set ssid flow
- * s1. set_802_11_infrastructure_mode()
- * s2. set_802_11_authenticaion_mode()
- * s3. set_802_11_encryption_mode()
- * s4. set_802_11_ssid()
- *
- * This function intends to handle the Set ESSID command.
- * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
- *
- * For this operation to succeed, there is no need for the interface to be Up.
- *
- */
-static int r8711_wx_set_essid(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct wlan_network *pnetwork = NULL;
- enum NDIS_802_11_AUTHENTICATION_MODE authmode;
- struct ndis_802_11_ssid ndis_ssid;
- u8 *dst_ssid, *src_ssid;
- struct list_head *phead;
- u32 len;
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
- return -EBUSY;
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- return 0;
- if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
- return -E2BIG;
- authmode = padapter->securitypriv.ndisauthtype;
- if (wrqu->essid.flags && wrqu->essid.length) {
- len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
- wrqu->essid.length : IW_ESSID_MAX_SIZE;
- memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
- ndis_ssid.SsidLength = len;
- memcpy(ndis_ssid.Ssid, extra, len);
- src_ssid = ndis_ssid.Ssid;
- phead = &queue->queue;
- pmlmepriv->pscanned = phead->next;
- while (1) {
- if (end_of_queue_search(phead, pmlmepriv->pscanned))
- break;
- pnetwork = container_of(pmlmepriv->pscanned,
- struct wlan_network, list);
- pmlmepriv->pscanned = pmlmepriv->pscanned->next;
- dst_ssid = pnetwork->network.Ssid.Ssid;
- if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
- && (pnetwork->network.Ssid.SsidLength ==
- ndis_ssid.SsidLength)) {
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
- if (pnetwork->network.
- InfrastructureMode
- !=
- padapter->mlmepriv.
- cur_network.network.
- InfrastructureMode)
- continue;
- }
-
- r8712_set_802_11_infrastructure_mode(
- padapter,
- pnetwork->network.InfrastructureMode);
- break;
- }
- }
- r8712_set_802_11_authentication_mode(padapter, authmode);
- r8712_set_802_11_ssid(padapter, &ndis_ssid);
- }
- return -EINPROGRESS;
-}
-
-static int r8711_wx_get_essid(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- u32 len, ret = 0;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
- len = pcur_bss->Ssid.SsidLength;
- wrqu->essid.length = len;
- memcpy(extra, pcur_bss->Ssid.Ssid, len);
- wrqu->essid.flags = 1;
- } else {
- ret = -ENOLINK;
- }
- return ret;
-}
-
-static int r8711_wx_set_rate(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- u32 target_rate = wrqu->bitrate.value;
- u32 fixed = wrqu->bitrate.fixed;
- u32 ratevalue = 0;
- u8 datarates[NumRates];
- u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
- int i;
-
- if (target_rate == -1) {
- ratevalue = 11;
- goto set_rate;
- }
- target_rate = target_rate / 100000;
- switch (target_rate) {
- case 10:
- ratevalue = 0;
- break;
- case 20:
- ratevalue = 1;
- break;
- case 55:
- ratevalue = 2;
- break;
- case 60:
- ratevalue = 3;
- break;
- case 90:
- ratevalue = 4;
- break;
- case 110:
- ratevalue = 5;
- break;
- case 120:
- ratevalue = 6;
- break;
- case 180:
- ratevalue = 7;
- break;
- case 240:
- ratevalue = 8;
- break;
- case 360:
- ratevalue = 9;
- break;
- case 480:
- ratevalue = 10;
- break;
- case 540:
- ratevalue = 11;
- break;
- default:
- ratevalue = 11;
- break;
- }
-set_rate:
- for (i = 0; i < NumRates; i++) {
- if (ratevalue == mpdatarate[i]) {
- datarates[i] = mpdatarate[i];
- if (fixed == 0)
- break;
- } else {
- datarates[i] = 0xff;
- }
- }
- return r8712_setdatarate_cmd(padapter, datarates);
-}
-
-static int r8711_wx_get_rate(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- struct ieee80211_ht_cap *pht_capie;
- unsigned char rf_type = padapter->registrypriv.rf_config;
- int i;
- u8 *p;
- u16 rate, max_rate = 0, ht_cap = false;
- u32 ht_ielen = 0;
- u8 bw_40MHz = 0, short_GI = 0;
- u16 mcs_rate = 0;
-
- i = 0;
- if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE))
- return -ENOLINK;
- p = r8712_get_ie(&pcur_bss->IEs[12], WLAN_EID_HT_CAPABILITY, &ht_ielen,
- pcur_bss->IELength - 12);
- if (p && ht_ielen > 0) {
- ht_cap = true;
- pht_capie = (struct ieee80211_ht_cap *)(p + 2);
- memcpy(&mcs_rate, &pht_capie->mcs, 2);
- bw_40MHz = (le16_to_cpu(pht_capie->cap_info) &
- IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0;
- short_GI = (le16_to_cpu(pht_capie->cap_info) &
- (IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
- }
- while ((pcur_bss->rates[i] != 0) &&
- (pcur_bss->rates[i] != 0xFF)) {
- rate = pcur_bss->rates[i] & 0x7F;
- if (rate > max_rate)
- max_rate = rate;
- wrqu->bitrate.fixed = 0; /* no auto select */
- wrqu->bitrate.value = rate * 500000;
- i++;
- }
- if (ht_cap) {
- if (mcs_rate & 0x8000 /* MCS15 */
- &&
- rf_type == RTL8712_RF_2T2R)
- max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) :
- ((short_GI) ? 144 : 130);
- else /* default MCS7 */
- max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) :
- ((short_GI) ? 72 : 65);
- max_rate *= 2; /* Mbps/2 */
- }
- wrqu->bitrate.value = max_rate * 500000;
- return 0;
-}
-
-static int r8711_wx_get_rts(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
-
- wrqu->rts.value = padapter->registrypriv.rts_thresh;
- wrqu->rts.fixed = 0; /* no auto select */
- return 0;
-}
-
-static int r8711_wx_set_frag(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
-
- if (wrqu->frag.disabled) {
- padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
- } else {
- if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
- wrqu->frag.value > MAX_FRAG_THRESHOLD)
- return -EINVAL;
- padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
- }
- return 0;
-}
-
-static int r8711_wx_get_frag(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
-
- wrqu->frag.value = padapter->xmitpriv.frag_len;
- wrqu->frag.fixed = 0; /* no auto select */
- return 0;
-}
-
-static int r8711_wx_get_retry(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- wrqu->retry.value = 7;
- wrqu->retry.fixed = 0; /* no auto select */
- wrqu->retry.disabled = 1;
- return 0;
-}
-
-static int r8711_wx_set_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- u32 key;
- u32 keyindex_provided;
- struct NDIS_802_11_WEP wep;
- enum NDIS_802_11_AUTHENTICATION_MODE authmode;
- struct iw_point *erq = &wrqu->encoding;
- struct _adapter *padapter = netdev_priv(dev);
-
- key = erq->flags & IW_ENCODE_INDEX;
- memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
- if (erq->flags & IW_ENCODE_DISABLED) {
- netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11EncryptionDisabled;
- padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
- padapter->securitypriv.AuthAlgrthm = 0; /* open system */
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- return 0;
- }
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- keyindex_provided = 1;
- } else {
- keyindex_provided = 0;
- key = padapter->securitypriv.PrivacyKeyIndex;
- }
- /* set authentication mode */
- if (erq->flags & IW_ENCODE_OPEN) {
- netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.AuthAlgrthm = 0; /* open system */
- padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- } else if (erq->flags & IW_ENCODE_RESTRICTED) {
- netdev_info(dev,
- "r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__);
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
- padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.XGrpPrivacy = _WEP40_;
- authmode = Ndis802_11AuthModeShared;
- padapter->securitypriv.ndisauthtype = authmode;
- } else {
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.AuthAlgrthm = 0; /* open system */
- padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- }
- wep.KeyIndex = key;
- if (erq->length > 0) {
- wep.KeyLength = erq->length <= 5 ? 5 : 13;
- wep.Length = wep.KeyLength +
- offsetof(struct NDIS_802_11_WEP, KeyMaterial);
- } else {
- wep.KeyLength = 0;
- if (keyindex_provided == 1) { /* set key_id only, no given
- * KeyMaterial(erq->length==0).
- */
- padapter->securitypriv.PrivacyKeyIndex = key;
- switch (padapter->securitypriv.DefKeylen[key]) {
- case 5:
- padapter->securitypriv.PrivacyAlgrthm =
- _WEP40_;
- break;
- case 13:
- padapter->securitypriv.PrivacyAlgrthm =
- _WEP104_;
- break;
- default:
- padapter->securitypriv.PrivacyAlgrthm =
- _NO_PRIVACY_;
- break;
- }
- return 0;
- }
- }
- wep.KeyIndex |= 0x80000000; /* transmit key */
- memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
- if (r8712_set_802_11_add_wep(padapter, &wep))
- return -EOPNOTSUPP;
- return 0;
-}
-
-static int r8711_wx_get_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- uint key;
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_point *erq = &wrqu->encoding;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- union Keytype *dk = padapter->securitypriv.DefKey;
-
- if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- return 0;
- }
- }
- key = erq->flags & IW_ENCODE_INDEX;
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- } else {
- key = padapter->securitypriv.PrivacyKeyIndex;
- }
- erq->flags = key + 1;
- switch (padapter->securitypriv.ndisencryptstatus) {
- case Ndis802_11EncryptionNotSupported:
- case Ndis802_11EncryptionDisabled:
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- break;
- case Ndis802_11Encryption1Enabled:
- erq->length = padapter->securitypriv.DefKeylen[key];
- if (erq->length) {
- memcpy(keybuf, dk[key].skey,
- padapter->securitypriv.DefKeylen[key]);
- erq->flags |= IW_ENCODE_ENABLED;
- if (padapter->securitypriv.ndisauthtype ==
- Ndis802_11AuthModeOpen)
- erq->flags |= IW_ENCODE_OPEN;
- else if (padapter->securitypriv.ndisauthtype ==
- Ndis802_11AuthModeShared)
- erq->flags |= IW_ENCODE_RESTRICTED;
- } else {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- }
- break;
- case Ndis802_11Encryption2Enabled:
- case Ndis802_11Encryption3Enabled:
- erq->length = 16;
- erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
- IW_ENCODE_NOKEY);
- break;
- default:
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- break;
- }
- return 0;
-}
-
-static int r8711_wx_get_power(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- wrqu->power.value = 0;
- wrqu->power.fixed = 0; /* no auto select */
- wrqu->power.disabled = 1;
- return 0;
-}
-
-static int r871x_wx_set_gen_ie(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
-
- return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
-}
-
-static int r871x_wx_set_auth(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_param *param = (struct iw_param *)&wrqu->param;
- int paramid;
- int paramval;
- int ret = 0;
-
- paramid = param->flags & IW_AUTH_INDEX;
- paramval = param->value;
- switch (paramid) {
- case IW_AUTH_WPA_VERSION:
- break;
- case IW_AUTH_CIPHER_PAIRWISE:
- break;
- case IW_AUTH_CIPHER_GROUP:
- break;
- case IW_AUTH_KEY_MGMT:
- /*
- * ??? does not use these parameters
- */
- break;
- case IW_AUTH_TKIP_COUNTERMEASURES:
- if (paramval) {
- /* wpa_supplicant is enabling tkip countermeasure. */
- padapter->securitypriv.btkip_countermeasure = true;
- } else {
- /* wpa_supplicant is disabling tkip countermeasure. */
- padapter->securitypriv.btkip_countermeasure = false;
- }
- break;
- case IW_AUTH_DROP_UNENCRYPTED:
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
- if (padapter->securitypriv.ndisencryptstatus ==
- Ndis802_11Encryption1Enabled) {
- /* it means init value, or using wep,
- * ndisencryptstatus =
- * Ndis802_11Encryption1Enabled,
- * then it needn't reset it;
- */
- break;
- }
-
- if (paramval) {
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11EncryptionDisabled;
- padapter->securitypriv.PrivacyAlgrthm =
- _NO_PRIVACY_;
- padapter->securitypriv.XGrpPrivacy =
- _NO_PRIVACY_;
- padapter->securitypriv.AuthAlgrthm = 0;
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeOpen;
- }
- break;
- case IW_AUTH_80211_AUTH_ALG:
- ret = wpa_set_auth_algs(dev, (u32)paramval);
- break;
- case IW_AUTH_WPA_ENABLED:
- break;
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- break;
- case IW_AUTH_PRIVACY_INVOKED:
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-static int r871x_wx_set_enc_ext(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct iw_point *pencoding = &wrqu->encoding;
- struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
- struct ieee_param *param = NULL;
- char *alg_name;
- u32 param_len;
- int ret = 0;
-
- switch (pext->alg) {
- case IW_ENCODE_ALG_NONE:
- alg_name = "none";
- break;
- case IW_ENCODE_ALG_WEP:
- alg_name = "WEP";
- break;
- case IW_ENCODE_ALG_TKIP:
- alg_name = "TKIP";
- break;
- case IW_ENCODE_ALG_CCMP:
- alg_name = "CCMP";
- break;
- default:
- return -EINVAL;
- }
-
- param_len = sizeof(struct ieee_param) + pext->key_len;
- param = kzalloc(param_len, GFP_ATOMIC);
- if (!param)
- return -ENOMEM;
- param->cmd = IEEE_CMD_SET_ENCRYPTION;
- eth_broadcast_addr(param->sta_addr);
- strscpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
- if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
- param->u.crypt.set_tx = 0;
- if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
- param->u.crypt.set_tx = 1;
- param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
- if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
- memcpy(param->u.crypt.seq, pext->rx_seq, 8);
- if (pext->key_len) {
- param->u.crypt.key_len = pext->key_len;
- memcpy(param + 1, pext + 1, pext->key_len);
- }
- ret = wpa_set_encryption(dev, param, param_len);
- kfree(param);
- return ret;
-}
-
-static int r871x_wx_get_nick(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- if (extra) {
- wrqu->data.length = 8;
- wrqu->data.flags = 1;
- memcpy(extra, "rtl_wifi", 8);
- }
- return 0;
-}
-
-static int r8711_wx_read32(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- struct _adapter *padapter = netdev_priv(dev);
- u32 addr;
- u32 data32;
-
- get_user(addr, (u32 __user *)wrqu->data.pointer);
- data32 = r8712_read32(padapter, addr);
- put_user(data32, (u32 __user *)wrqu->data.pointer);
- wrqu->data.length = (data32 & 0xffff0000) >> 16;
- wrqu->data.flags = data32 & 0xffff;
- get_user(addr, (u32 __user *)wrqu->data.pointer);
- return 0;
-}
-
-static int r8711_wx_write32(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- struct _adapter *padapter = netdev_priv(dev);
- u32 addr;
- u32 data32;
-
- get_user(addr, (u32 __user *)wrqu->data.pointer);
- data32 = ((u32)wrqu->data.length << 16) | (u32)wrqu->data.flags;
- r8712_write32(padapter, addr, data32);
- return 0;
-}
-
-static int dummy(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- return -EINVAL;
-}
-
-static int r8711_drvext_hdl(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- return 0;
-}
-
-static int r871x_mp_ioctl_hdl(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_point *p = &wrqu->data;
- struct oid_par_priv oid_par;
- struct mp_ioctl_handler *phandler;
- struct mp_ioctl_param *poidparam;
- unsigned long BytesRead, BytesWritten, BytesNeeded;
- u8 *pparmbuf, bset;
- u16 len;
- uint status;
- int ret = 0;
-
- if ((!p->length) || (!p->pointer))
- return -EINVAL;
-
- bset = (u8)(p->flags & 0xFFFF);
- len = p->length;
- pparmbuf = memdup_user(p->pointer, len);
- if (IS_ERR(pparmbuf))
- return PTR_ERR(pparmbuf);
-
- poidparam = (struct mp_ioctl_param *)pparmbuf;
- if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
- ret = -EINVAL;
- goto _r871x_mp_ioctl_hdl_exit;
- }
- phandler = mp_ioctl_hdl + poidparam->subcode;
- if ((phandler->paramsize != 0) &&
- (poidparam->len < phandler->paramsize)) {
- ret = -EINVAL;
- goto _r871x_mp_ioctl_hdl_exit;
- }
- if (phandler->oid == 0 && phandler->handler) {
- status = phandler->handler(&oid_par);
- } else if (phandler->handler) {
- oid_par.adapter_context = padapter;
- oid_par.oid = phandler->oid;
- oid_par.information_buf = poidparam->data;
- oid_par.information_buf_len = poidparam->len;
- oid_par.dbg = 0;
- BytesWritten = 0;
- BytesNeeded = 0;
- if (bset) {
- oid_par.bytes_rw = &BytesRead;
- oid_par.bytes_needed = &BytesNeeded;
- oid_par.type_of_oid = SET_OID;
- } else {
- oid_par.bytes_rw = &BytesWritten;
- oid_par.bytes_needed = &BytesNeeded;
- oid_par.type_of_oid = QUERY_OID;
- }
- status = phandler->handler(&oid_par);
- /* todo:check status, BytesNeeded, etc. */
- } else {
- netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n",
- __func__, poidparam->subcode, phandler->oid,
- phandler->handler);
- ret = -EFAULT;
- goto _r871x_mp_ioctl_hdl_exit;
- }
- if (bset == 0x00) { /* query info */
- if (copy_to_user(p->pointer, pparmbuf, len))
- ret = -EFAULT;
- }
- if (status) {
- ret = -EFAULT;
- goto _r871x_mp_ioctl_hdl_exit;
- }
-_r871x_mp_ioctl_hdl_exit:
- kfree(pparmbuf);
- return ret;
-}
-
-static int r871x_get_ap_info(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct iw_point *pdata = &wrqu->data;
- struct wlan_network *pnetwork = NULL;
- u32 cnt = 0, wpa_ielen;
- unsigned long irqL;
- struct list_head *plist, *phead;
- unsigned char *pbuf;
- u8 bssid[ETH_ALEN];
- char data[33];
-
- if (padapter->driver_stopped || !pdata)
- return -EINVAL;
- while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
- _FW_UNDER_LINKING)) {
- msleep(30);
- cnt++;
- if (cnt > 100)
- break;
- }
- pdata->flags = 0;
- if (pdata->length < 32)
- return -EINVAL;
- if (copy_from_user(data, pdata->pointer, 32))
- return -EINVAL;
- data[32] = 0;
-
- spin_lock_irqsave(&pmlmepriv->scanned_queue.lock, irqL);
- phead = &queue->queue;
- plist = phead->next;
- while (1) {
- if (end_of_queue_search(phead, plist))
- break;
- pnetwork = container_of(plist, struct wlan_network, list);
- if (!mac_pton(data, bssid)) {
- netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n",
- (u8 *)data);
- spin_unlock_irqrestore(&pmlmepriv->scanned_queue.lock,
- irqL);
- return -EINVAL;
- }
- netdev_info(dev, "r8712u: BSSID:%pM\n", bssid);
- if (ether_addr_equal(bssid, pnetwork->network.MacAddress)) {
- /* BSSID match, then check if supporting wpa/wpa2 */
- pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
- &wpa_ielen, pnetwork->network.IELength - 12);
- if (pbuf && (wpa_ielen > 0)) {
- pdata->flags = 1;
- break;
- }
- pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
- &wpa_ielen, pnetwork->network.IELength - 12);
- if (pbuf && (wpa_ielen > 0)) {
- pdata->flags = 2;
- break;
- }
- }
- plist = plist->next;
- }
- spin_unlock_irqrestore(&pmlmepriv->scanned_queue.lock, irqL);
- if (pdata->length >= 34) {
- if (copy_to_user((u8 __user *)pdata->pointer + 32,
- (u8 *)&pdata->flags, 1))
- return -EINVAL;
- }
- return 0;
-}
-
-static int r871x_set_pid(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
-
- if (padapter->driver_stopped || !pdata)
- return -EINVAL;
- if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
- return -EINVAL;
- return 0;
-}
-
-static int r871x_set_chplan(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- int ch_plan = -1;
-
- if (padapter->driver_stopped || !pdata) {
- ret = -EINVAL;
- goto exit;
- }
- ch_plan = (int)*extra;
- r8712_set_chplan_cmd(padapter, ch_plan);
-
-exit:
-
- return ret;
-}
-
-static int r871x_wps_start(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- u32 u32wps_start = 0;
-
- if (padapter->driver_stopped || !pdata)
- return -EINVAL;
- if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
- return -EFAULT;
- if (u32wps_start == 0)
- u32wps_start = *extra;
- if (u32wps_start == 1) /* WPS Start */
- padapter->ledpriv.LedControlHandler(padapter,
- LED_CTL_START_WPS);
- else if (u32wps_start == 2) /* WPS Stop because of wps success */
- padapter->ledpriv.LedControlHandler(padapter,
- LED_CTL_STOP_WPS);
- else if (u32wps_start == 3) /* WPS Stop because of wps fail */
- padapter->ledpriv.LedControlHandler(padapter,
- LED_CTL_STOP_WPS_FAIL);
- return 0;
-}
-
-static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
-{
- struct _adapter *padapter = netdev_priv(dev);
-
- switch (name) {
- case IEEE_PARAM_WPA_ENABLED:
- padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
- switch ((value) & 0xff) {
- case 1: /* WPA */
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption2Enabled;
- break;
- case 2: /* WPA2 */
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption3Enabled;
- break;
- }
- break;
- case IEEE_PARAM_TKIP_COUNTERMEASURES:
- break;
- case IEEE_PARAM_DROP_UNENCRYPTED:
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
- break;
- case IEEE_PARAM_PRIVACY_INVOKED:
- break;
- case IEEE_PARAM_AUTH_ALGS:
- return wpa_set_auth_algs(dev, value);
- case IEEE_PARAM_IEEE_802_1X:
- break;
- case IEEE_PARAM_WPAX_SELECT:
- /* added for WPA2 mixed mode */
- break;
- default:
- return -EOPNOTSUPP;
- }
- return 0;
-}
-
-static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
-{
- struct _adapter *padapter = netdev_priv(dev);
-
- switch (command) {
- case IEEE_MLME_STA_DEAUTH:
- if (!r8712_set_802_11_disassociate(padapter))
- return -1;
- break;
- case IEEE_MLME_STA_DISASSOC:
- if (!r8712_set_802_11_disassociate(padapter))
- return -1;
- break;
- default:
- return -EOPNOTSUPP;
- }
- return 0;
-}
-
-static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
-{
- struct ieee_param *param;
- int ret = 0;
- struct _adapter *padapter = netdev_priv(dev);
-
- if (p->length < sizeof(struct ieee_param) || !p->pointer)
- return -EINVAL;
- param = memdup_user(p->pointer, p->length);
- if (IS_ERR(param))
- return PTR_ERR(param);
- switch (param->cmd) {
- case IEEE_CMD_SET_WPA_PARAM:
- ret = wpa_set_param(dev, param->u.wpa_param.name,
- param->u.wpa_param.value);
- break;
- case IEEE_CMD_SET_WPA_IE:
- ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
- (u16)param->u.wpa_ie.len);
- break;
- case IEEE_CMD_SET_ENCRYPTION:
- ret = wpa_set_encryption(dev, param, p->length);
- break;
- case IEEE_CMD_MLME:
- ret = wpa_mlme(dev, param->u.mlme.command,
- param->u.mlme.reason_code);
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
- if (ret == 0 && copy_to_user(p->pointer, param, p->length))
- ret = -EFAULT;
- kfree(param);
- return ret;
-}
-
-/* based on "driver_ipw" and for hostapd */
-int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct iwreq *wrq = (struct iwreq *)rq;
-
- switch (cmd) {
- case RTL_IOCTL_WPA_SUPPLICANT:
- return wpa_supplicant_ioctl(dev, &wrq->u.data);
- default:
- return -EOPNOTSUPP;
- }
- return 0;
-}
-
-static iw_handler r8711_handlers[] = {
- NULL, /* SIOCSIWCOMMIT */
- r8711_wx_get_name, /* SIOCGIWNAME */
- dummy, /* SIOCSIWNWID */
- dummy, /* SIOCGIWNWID */
- r8711_wx_set_freq, /* SIOCSIWFREQ */
- r8711_wx_get_freq, /* SIOCGIWFREQ */
- r8711_wx_set_mode, /* SIOCSIWMODE */
- r8711_wx_get_mode, /* SIOCGIWMODE */
- dummy, /* SIOCSIWSENS */
- r8711_wx_get_sens, /* SIOCGIWSENS */
- NULL, /* SIOCSIWRANGE */
- r8711_wx_get_range, /* SIOCGIWRANGE */
- r871x_wx_set_priv, /* SIOCSIWPRIV */
- NULL, /* SIOCGIWPRIV */
- NULL, /* SIOCSIWSTATS */
- NULL, /* SIOCGIWSTATS */
- dummy, /* SIOCSIWSPY */
- dummy, /* SIOCGIWSPY */
- NULL, /* SIOCGIWTHRSPY */
- NULL, /* SIOCWIWTHRSPY */
- r8711_wx_set_wap, /* SIOCSIWAP */
- r8711_wx_get_wap, /* SIOCGIWAP */
- r871x_wx_set_mlme, /* request MLME operation;
- * uses struct iw_mlme
- */
- dummy, /* SIOCGIWAPLIST -- deprecated */
- r8711_wx_set_scan, /* SIOCSIWSCAN */
- r8711_wx_get_scan, /* SIOCGIWSCAN */
- r8711_wx_set_essid, /* SIOCSIWESSID */
- r8711_wx_get_essid, /* SIOCGIWESSID */
- dummy, /* SIOCSIWNICKN */
- r871x_wx_get_nick, /* SIOCGIWNICKN */
- NULL, /* -- hole -- */
- NULL, /* -- hole -- */
- r8711_wx_set_rate, /* SIOCSIWRATE */
- r8711_wx_get_rate, /* SIOCGIWRATE */
- dummy, /* SIOCSIWRTS */
- r8711_wx_get_rts, /* SIOCGIWRTS */
- r8711_wx_set_frag, /* SIOCSIWFRAG */
- r8711_wx_get_frag, /* SIOCGIWFRAG */
- dummy, /* SIOCSIWTXPOW */
- dummy, /* SIOCGIWTXPOW */
- dummy, /* SIOCSIWRETRY */
- r8711_wx_get_retry, /* SIOCGIWRETRY */
- r8711_wx_set_enc, /* SIOCSIWENCODE */
- r8711_wx_get_enc, /* SIOCGIWENCODE */
- dummy, /* SIOCSIWPOWER */
- r8711_wx_get_power, /* SIOCGIWPOWER */
- NULL, /*---hole---*/
- NULL, /*---hole---*/
- r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
- NULL, /* SIOCGIWGENIE */
- r871x_wx_set_auth, /* SIOCSIWAUTH */
- NULL, /* SIOCGIWAUTH */
- r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
- NULL, /* SIOCGIWENCODEEXT */
- r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
- NULL, /*---hole---*/
-};
-
-static const struct iw_priv_args r8711_private_args[] = {
- {
- SIOCIWFIRSTPRIV + 0x0,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
- },
- {
- SIOCIWFIRSTPRIV + 0x1,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
- },
- {
- SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
- },
- {
- SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
- },
- {
- SIOCIWFIRSTPRIV + 0x4,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
- },
- {
- SIOCIWFIRSTPRIV + 0x5,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
- },
- {
- SIOCIWFIRSTPRIV + 0x6,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
- },
- {
- SIOCIWFIRSTPRIV + 0x7,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
- }
-};
-
-static iw_handler r8711_private_handler[] = {
- r8711_wx_read32,
- r8711_wx_write32,
- r8711_drvext_hdl,
- r871x_mp_ioctl_hdl,
- r871x_get_ap_info, /*for MM DTV platform*/
- r871x_set_pid,
- r871x_wps_start,
- r871x_set_chplan
-};
-
-static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_statistics *piwstats = &padapter->iwstats;
- int tmp_level = 0;
- int tmp_qual = 0;
- int tmp_noise = 0;
-
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
- piwstats->qual.qual = 0;
- piwstats->qual.level = 0;
- piwstats->qual.noise = 0;
- } else {
- /* show percentage, we need transfer dbm to original value. */
- tmp_level = padapter->recvpriv.fw_rssi;
- tmp_qual = padapter->recvpriv.signal;
- tmp_noise = padapter->recvpriv.noise;
- piwstats->qual.level = tmp_level;
- piwstats->qual.qual = tmp_qual;
- piwstats->qual.noise = tmp_noise;
- }
- piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
- return &padapter->iwstats;
-}
-
-struct iw_handler_def r871x_handlers_def = {
- .standard = r8711_handlers,
- .num_standard = ARRAY_SIZE(r8711_handlers),
- .private = r8711_private_handler,
- .private_args = (struct iw_priv_args *)r8711_private_args,
- .num_private = ARRAY_SIZE(r8711_private_handler),
- .num_private_args = sizeof(r8711_private_args) /
- sizeof(struct iw_priv_args),
- .get_wireless_stats = r871x_get_wireless_stats
-};
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c b/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c
deleted file mode 100644
index 2b539335206a..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c
+++ /dev/null
@@ -1,519 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_ioctl_rtl.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_IOCTL_RTL_C_
-
-#include <linux/rndis.h>
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "wlan_bssdef.h"
-#include "wifi.h"
-#include "rtl871x_ioctl.h"
-#include "rtl871x_ioctl_set.h"
-#include "rtl871x_ioctl_rtl.h"
-#include "mp_custom_oid.h"
-#include "rtl871x_mp.h"
-#include "rtl871x_mp_ioctl.h"
-
-uint oid_rt_get_signal_quality_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_small_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- padapter->recvpriv.rx_smallpacket_crcerr;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- padapter->recvpriv.rx_middlepacket_crcerr;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_large_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- padapter->recvpriv.rx_largepacket_crcerr;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_tx_retry_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_rx_retry_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_rx_total_packet_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- padapter->recvpriv.rx_pkts +
- padapter->recvpriv.rx_drop;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_tx_beacon_ok_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_tx_beacon_err_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_rx_icv_err_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(uint *)poid_par_priv->information_buf =
- padapter->recvpriv.rx_icv_err;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_set_encryption_algorithm_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_preamble_mode_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
- u32 preamblemode = 0;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- if (padapter->registrypriv.preamble == PREAMBLE_LONG)
- preamblemode = 0;
- else if (padapter->registrypriv.preamble == PREAMBLE_AUTO)
- preamblemode = 1;
- else if (padapter->registrypriv.preamble == PREAMBLE_SHORT)
- preamblemode = 2;
- *(u32 *)poid_par_priv->information_buf = preamblemode;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_ap_ip_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_channelplan_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
- struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- *(u16 *)poid_par_priv->information_buf = peeprompriv->channel_plan;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_set_channelplan_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
- struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- peeprompriv->channel_plan = *(u16 *)poid_par_priv->information_buf;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_set_preamble_mode_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
- u32 preamblemode = 0;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- preamblemode = *(u32 *)poid_par_priv->information_buf;
- if (preamblemode == 0)
- padapter->registrypriv.preamble = PREAMBLE_LONG;
- else if (preamblemode == 1)
- padapter->registrypriv.preamble = PREAMBLE_AUTO;
- else if (preamblemode == 2)
- padapter->registrypriv.preamble = PREAMBLE_SHORT;
- *(u32 *)poid_par_priv->information_buf = preamblemode;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_set_bcn_intvl_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_dedicate_probe_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- padapter->xmitpriv.tx_bytes;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- padapter->recvpriv.rx_bytes;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_current_tx_power_level_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_enc_key_mismatch_count_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_enc_key_match_count_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_channel_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct NDIS_802_11_CONFIGURATION *pnic_Config;
- u32 channelnum;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (check_fwstate(pmlmepriv, _FW_LINKED) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
- pnic_Config = &pmlmepriv->cur_network.network.Configuration;
- else
- pnic_Config = &padapter->registrypriv.dev_network.Configuration;
- channelnum = pnic_Config->DSConfig;
- *(u32 *)poid_par_priv->information_buf = channelnum;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_hardware_radio_off_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_key_mismatch_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_supported_wireless_mode_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- u32 ulInfo = 0;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- ulInfo |= 0x0100; /* WIRELESS_MODE_B */
- ulInfo |= 0x0200; /* WIRELESS_MODE_G */
- ulInfo |= 0x0400; /* WIRELESS_MODE_A */
- *(u32 *) poid_par_priv->information_buf = ulInfo;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_channel_list_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_scan_in_progress_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_forced_data_rate_hdl(struct oid_par_priv *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_bss_wireless_mode_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv*
- poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_ap_supported_hdl(struct oid_par_priv *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_ap_set_passphrase_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv*
- poid_par_priv)
-{
- uint status = RNDIS_STATUS_SUCCESS;
- struct _adapter *Adapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len ==
- (sizeof(unsigned long) * 3)) {
- if (r8712_setrfreg_cmd(Adapter,
- *(unsigned char *)poid_par_priv->information_buf,
- (unsigned long)(*((unsigned long *)
- poid_par_priv->information_buf + 2))))
- status = RNDIS_STATUS_NOT_ACCEPTED;
- } else {
- status = RNDIS_STATUS_INVALID_LENGTH;
- }
- return status;
-}
-
-uint oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv)
-{
- uint status = RNDIS_STATUS_SUCCESS;
- struct _adapter *Adapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len == (sizeof(unsigned long) *
- 3)) {
- if (Adapter->mppriv.act_in_progress) {
- status = RNDIS_STATUS_NOT_ACCEPTED;
- } else {
- /* init workparam */
- Adapter->mppriv.act_in_progress = true;
- Adapter->mppriv.workparam.bcompleted = false;
- Adapter->mppriv.workparam.act_type = MPT_READ_RF;
- Adapter->mppriv.workparam.io_offset = *(unsigned long *)
- poid_par_priv->information_buf;
- Adapter->mppriv.workparam.io_value = 0xcccccccc;
-
- /* RegOffsetValue - The offset of RF register to read.
- * RegDataWidth - The data width of RF register to read.
- * RegDataValue - The value to read.
- * RegOffsetValue = *((unsigned long *)InformationBuffer);
- * RegDataWidth = *((unsigned long *)InformationBuffer+1);
- * RegDataValue = *((unsigned long *)InformationBuffer+2);
- */
- if (r8712_getrfreg_cmd(Adapter,
- *(unsigned char *)poid_par_priv->information_buf,
- (unsigned char *)&Adapter->mppriv.workparam.io_value
- ))
- status = RNDIS_STATUS_NOT_ACCEPTED;
- }
- } else {
- status = RNDIS_STATUS_INVALID_LENGTH;
- }
- return status;
-}
-
-enum _CONNECT_STATE_ {
- CHECKINGSTATUS,
- ASSOCIATED,
- ADHOCMODE,
- NOTASSOCIATED
-};
-
-uint oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- u32 ulInfo;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- /* nStatus==0 CheckingStatus
- * nStatus==1 Associated
- * nStatus==2 AdHocMode
- * nStatus==3 NotAssociated
- */
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- ulInfo = CHECKINGSTATUS;
- else if (check_fwstate(pmlmepriv, _FW_LINKED))
- ulInfo = ASSOCIATED;
- else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
- ulInfo = ADHOCMODE;
- else
- ulInfo = NOTASSOCIATED;
- *(u32 *)poid_par_priv->information_buf = ulInfo;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_set_default_key_id_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h b/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h
deleted file mode 100644
index 7c0b880ac686..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871X_IOCTL_RTL_H
-#define _RTL871X_IOCTL_RTL_H
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-/*************** oid_rtl_seg_01_01 **************/
-uint oid_rt_get_signal_quality_hdl(
- struct oid_par_priv *poid_par_priv);/*84*/
-uint oid_rt_get_small_packet_crc_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_middle_packet_crc_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_large_packet_crc_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_tx_retry_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_rx_retry_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_rx_total_packet_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_tx_beacon_ok_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_tx_beacon_err_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_rx_icv_err_hdl(
- struct oid_par_priv *poid_par_priv);/*93*/
-uint oid_rt_set_encryption_algorithm_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_preamble_mode_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_ap_ip_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_channelplan_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_channelplan_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_preamble_mode_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_bcn_intvl_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_dedicate_probe_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_total_tx_bytes_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_total_rx_bytes_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_current_tx_power_level_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_enc_key_mismatch_count_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_enc_key_match_count_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_channel_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_hardware_radio_off_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_key_mismatch_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_supported_wireless_mode_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_channel_list_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_scan_in_progress_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_forced_data_rate_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_wireless_mode_for_scan_list_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_bss_wireless_mode_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_scan_with_magic_packet_hdl(
- struct oid_par_priv *poid_par_priv);
-
-/************** oid_rtl_seg_01_03 section start **************/
-uint oid_rt_ap_get_associated_station_list_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_ap_switch_into_ap_mode_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_ap_supported_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_ap_set_passphrase_hdl(
- struct oid_par_priv *poid_par_priv);
-/* oid_rtl_seg_01_11 */
-uint oid_rt_pro_rf_write_registry_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_rf_read_registry_hdl(
- struct oid_par_priv *poid_par_priv);
-/*************** oid_rtl_seg_03_00 section start **************/
-uint oid_rt_get_connect_state_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_default_key_id_hdl(
- struct oid_par_priv *poid_par_priv);
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c
deleted file mode 100644
index 34c9a52b4c42..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c
+++ /dev/null
@@ -1,354 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_ioctl_set.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_IOCTL_SET_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "rtl871x_ioctl_set.h"
-#include "usb_osintf.h"
-#include "usb_ops.h"
-
-static u8 validate_ssid(struct ndis_802_11_ssid *ssid)
-{
- u8 i;
-
- if (ssid->SsidLength > 32)
- return false;
- for (i = 0; i < ssid->SsidLength; i++) {
- /* wifi, printable ascii code must be supported */
- if (!((ssid->Ssid[i] >= 0x20) && (ssid->Ssid[i] <= 0x7e)))
- return false;
- }
- return true;
-}
-
-static u8 do_join(struct _adapter *padapter)
-{
- struct list_head *plist, *phead;
- u8 *pibss = NULL;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct __queue *queue = &(pmlmepriv->scanned_queue);
- int ret;
-
- phead = &queue->queue;
- plist = phead->next;
- pmlmepriv->cur_network.join_res = -2;
- pmlmepriv->fw_state |= _FW_UNDER_LINKING;
- pmlmepriv->pscanned = plist;
- pmlmepriv->to_join = true;
-
- /* adhoc mode will start with an empty queue, but skip checking */
- if (!check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) &&
- list_empty(&queue->queue)) {
- if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
- pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
- /* when set_ssid/set_bssid for do_join(), but scanning queue
- * is empty we try to issue sitesurvey firstly
- */
- if (!pmlmepriv->sitesurveyctrl.traffic_busy)
- r8712_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid);
- return true;
- }
-
- ret = r8712_select_and_join_from_scan(pmlmepriv);
- if (!ret) {
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
- } else {
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
- /* submit r8712_createbss_cmd to change to an
- * ADHOC_MASTER pmlmepriv->lock has been
- * acquired by caller...
- */
- struct wlan_bssid_ex *pdev_network =
- &padapter->registrypriv.dev_network;
- pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
- pibss = padapter->registrypriv.dev_network.MacAddress;
- memcpy(&pdev_network->Ssid,
- &pmlmepriv->assoc_ssid,
- sizeof(struct ndis_802_11_ssid));
- r8712_update_registrypriv_dev_network(padapter);
- r8712_generate_random_ibss(pibss);
- if (r8712_createbss_cmd(padapter))
- return false;
- pmlmepriv->to_join = false;
- } else {
- /* can't associate ; reset under-linking */
- if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
- pmlmepriv->fw_state ^=
- _FW_UNDER_LINKING;
- /* when set_ssid/set_bssid for do_join(), but
- * there are no desired bss in scanning queue
- * we try to issue sitesurvey first
- */
- if (!pmlmepriv->sitesurveyctrl.traffic_busy)
- r8712_sitesurvey_cmd(padapter,
- &pmlmepriv->assoc_ssid);
- }
- }
- return true;
-}
-
-u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid)
-{
- unsigned long irqL;
- u8 status = true;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) {
- status = false;
- return status;
- }
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
- _FW_UNDER_LINKING)) {
- status = check_fwstate(pmlmepriv, _FW_UNDER_LINKING);
- goto _Abort_Set_BSSID;
- }
- if (check_fwstate(pmlmepriv,
- _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
- if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid,
- ETH_ALEN)) {
- if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- /* driver is in
- * WIFI_ADHOC_MASTER_STATE
- */
- goto _Abort_Set_BSSID;
- } else {
- r8712_disassoc_cmd(padapter);
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- r8712_ind_disconnect(padapter);
- r8712_free_assoc_resources(padapter);
- if ((check_fwstate(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE))) {
- _clr_fwstate_(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE);
- set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
- }
- }
- }
- memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
- pmlmepriv->assoc_by_bssid = true;
- status = do_join(padapter);
- goto done;
-_Abort_Set_BSSID:
-done:
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- return status;
-}
-
-void r8712_set_802_11_ssid(struct _adapter *padapter,
- struct ndis_802_11_ssid *ssid)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_network *pnetwork = &pmlmepriv->cur_network;
-
- if (!padapter->hw_init_completed)
- return;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) {
- check_fwstate(pmlmepriv, _FW_UNDER_LINKING);
- goto _Abort_Set_SSID;
- }
- if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
- if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
- (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid,
- ssid->SsidLength))) {
- if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- if (!r8712_is_same_ibss(padapter,
- pnetwork)) {
- /* if in WIFI_ADHOC_MASTER_STATE or
- * WIFI_ADHOC_STATE, create bss or
- * rejoin again
- */
- r8712_disassoc_cmd(padapter);
- if (check_fwstate(pmlmepriv,
- _FW_LINKED))
- r8712_ind_disconnect(padapter);
- r8712_free_assoc_resources(padapter);
- if (check_fwstate(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE)) {
- _clr_fwstate_(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE);
- set_fwstate(pmlmepriv,
- WIFI_ADHOC_STATE);
- }
- } else {
- /* driver is in
- * WIFI_ADHOC_MASTER_STATE
- */
- goto _Abort_Set_SSID;
- }
- }
- } else {
- r8712_disassoc_cmd(padapter);
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- r8712_ind_disconnect(padapter);
- r8712_free_assoc_resources(padapter);
- if (check_fwstate(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE)) {
- _clr_fwstate_(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE);
- set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
- }
- }
- }
- if (padapter->securitypriv.btkip_countermeasure)
- goto _Abort_Set_SSID;
- if (!validate_ssid(ssid))
- goto _Abort_Set_SSID;
- memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
- pmlmepriv->assoc_by_bssid = false;
- do_join(padapter);
- goto done;
-_Abort_Set_SSID:
-done:
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_network *cur_network = &pmlmepriv->cur_network;
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE *pold_state =
- &(cur_network->network.InfrastructureMode);
-
- if (*pold_state != networktype) {
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_LINKED) ||
- (*pold_state == Ndis802_11IBSS))
- r8712_disassoc_cmd(padapter);
- if (check_fwstate(pmlmepriv,
- _FW_LINKED | WIFI_ADHOC_MASTER_STATE))
- r8712_free_assoc_resources(padapter);
- if (check_fwstate(pmlmepriv, _FW_LINKED) ||
- (*pold_state == Ndis802_11Infrastructure) ||
- (*pold_state == Ndis802_11IBSS)) {
- /* will clr Linked_state before this function,
- * we must have checked whether issue dis-assoc_cmd or
- * not
- */
- r8712_ind_disconnect(padapter);
- }
- *pold_state = networktype;
- /* clear WIFI_STATION_STATE; WIFI_AP_STATE; WIFI_ADHOC_STATE;
- * WIFI_ADHOC_MASTER_STATE
- */
- _clr_fwstate_(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE |
- WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE);
- switch (networktype) {
- case Ndis802_11IBSS:
- set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
- break;
- case Ndis802_11Infrastructure:
- set_fwstate(pmlmepriv, WIFI_STATION_STATE);
- break;
- case Ndis802_11APMode:
- set_fwstate(pmlmepriv, WIFI_AP_STATE);
- break;
- case Ndis802_11AutoUnknown:
- case Ndis802_11InfrastructureMax:
- break;
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- }
-}
-
-u8 r8712_set_802_11_disassociate(struct _adapter *padapter)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- r8712_disassoc_cmd(padapter);
- r8712_ind_disconnect(padapter);
- r8712_free_assoc_resources(padapter);
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- return true;
-}
-
-u8 r8712_set_802_11_bssid_list_scan(struct _adapter *padapter)
-{
- struct mlme_priv *pmlmepriv = NULL;
- unsigned long irqL;
- u8 ret = true;
-
- if (!padapter)
- return false;
- pmlmepriv = &padapter->mlmepriv;
- if (!padapter->hw_init_completed)
- return false;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ||
- pmlmepriv->sitesurveyctrl.traffic_busy) {
- /* Scan or linking is in progress, do nothing. */
- ret = (u8)check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
- } else {
- r8712_free_network_queue(padapter);
- ret = r8712_sitesurvey_cmd(padapter, NULL);
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- return ret;
-}
-
-u8 r8712_set_802_11_authentication_mode(struct _adapter *padapter,
- enum NDIS_802_11_AUTHENTICATION_MODE authmode)
-{
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- u8 ret;
-
- psecuritypriv->ndisauthtype = authmode;
- if (psecuritypriv->ndisauthtype > 3)
- psecuritypriv->AuthAlgrthm = 2; /* 802.1x */
- if (r8712_set_auth(padapter, psecuritypriv))
- ret = false;
- else
- ret = true;
- return ret;
-}
-
-int r8712_set_802_11_add_wep(struct _adapter *padapter,
- struct NDIS_802_11_WEP *wep)
-{
- sint keyid;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- keyid = wep->KeyIndex & 0x3fffffff;
- if (keyid >= WEP_KEYS)
- return -EINVAL;
- switch (wep->KeyLength) {
- case 5:
- psecuritypriv->PrivacyAlgrthm = _WEP40_;
- break;
- case 13:
- psecuritypriv->PrivacyAlgrthm = _WEP104_;
- break;
- default:
- psecuritypriv->PrivacyAlgrthm = _NO_PRIVACY_;
- break;
- }
- memcpy(psecuritypriv->DefKey[keyid].skey, &wep->KeyMaterial,
- wep->KeyLength);
- psecuritypriv->DefKeylen[keyid] = wep->KeyLength;
- psecuritypriv->PrivacyKeyIndex = keyid;
- return r8712_set_key(padapter, psecuritypriv, keyid);
-}
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.h b/drivers/staging/rtl8712/rtl871x_ioctl_set.h
deleted file mode 100644
index e2de820f61d9..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ioctl_set.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __IOCTL_SET_H
-#define __IOCTL_SET_H
-
-#include "drv_types.h"
-
-typedef u8 NDIS_802_11_PMKID_VALUE[16];
-
-struct BSSIDInfo {
- unsigned char BSSID[6];
- NDIS_802_11_PMKID_VALUE PMKID;
-};
-
-u8 r8712_set_802_11_authentication_mode(struct _adapter *pdapter,
- enum NDIS_802_11_AUTHENTICATION_MODE authmode);
-
-u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid);
-
-int r8712_set_802_11_add_wep(struct _adapter *padapter,
- struct NDIS_802_11_WEP *wep);
-
-u8 r8712_set_802_11_disassociate(struct _adapter *padapter);
-
-u8 r8712_set_802_11_bssid_list_scan(struct _adapter *padapter);
-
-void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype);
-
-void r8712_set_802_11_ssid(struct _adapter *padapter,
- struct ndis_802_11_ssid *ssid);
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl871x_led.h b/drivers/staging/rtl8712/rtl871x_led.h
deleted file mode 100644
index 2f0768132ad8..000000000000
--- a/drivers/staging/rtl8712/rtl871x_led.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_LED_H
-#define __RTL8712_LED_H
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-/*===========================================================================
- * LED customization.
- *===========================================================================
- */
-enum LED_CTL_MODE {
- LED_CTL_POWER_ON = 1,
- LED_CTL_LINK = 2,
- LED_CTL_NO_LINK = 3,
- LED_CTL_TX = 4,
- LED_CTL_RX = 5,
- LED_CTL_SITE_SURVEY = 6,
- LED_CTL_POWER_OFF = 7,
- LED_CTL_START_TO_LINK = 8,
- LED_CTL_START_WPS = 9,
- LED_CTL_STOP_WPS = 10,
- LED_CTL_START_WPS_BOTTON = 11,
- LED_CTL_STOP_WPS_FAIL = 12,
- LED_CTL_STOP_WPS_FAIL_OVERLAP = 13,
-};
-
-#define IS_LED_WPS_BLINKING(_LED_871x) \
- (((struct LED_871x *)_LED_871x)->CurrLedState == LED_BLINK_WPS \
- || ((struct LED_871x *)_LED_871x)->CurrLedState == LED_BLINK_WPS_STOP \
- || ((struct LED_871x *)_LED_871x)->bLedWPSBlinkInProgress)
-
-#define IS_LED_BLINKING(_LED_871x) \
- (((struct LED_871x *)_LED_871x)->bLedWPSBlinkInProgress \
- || ((struct LED_871x *)_LED_871x)->bLedScanBlinkInProgress)
-
-enum LED_PIN_871x {
- LED_PIN_GPIO0,
- LED_PIN_LED0,
- LED_PIN_LED1
-};
-
-/*===========================================================================
- * LED customization.
- *===========================================================================
- */
-enum LED_STRATEGY_871x {
- SW_LED_MODE0, /* SW control 1 LED via GPIO0. It is default option. */
- SW_LED_MODE1, /* 2 LEDs, through LED0 and LED1. For ALPHA. */
- SW_LED_MODE2, /* SW control 1 LED via GPIO0,
- * custom for AzWave 8187 minicard.
- */
- SW_LED_MODE3, /* SW control 1 LED via GPIO0,
- * customized for Sercomm Printer Server case.
- */
- SW_LED_MODE4, /*for Edimax / Belkin*/
- SW_LED_MODE5, /*for Sercomm / Belkin*/
- SW_LED_MODE6, /*for WNC / Corega*/
- HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different
- * control modes, see MAC.CONFIG1 for details.)
- */
-};
-
-struct LED_871x {
- struct _adapter *padapter;
- enum LED_PIN_871x LedPin; /* Implementation for this SW led. */
- u32 CurrLedState; /* Current LED state. */
- u8 bLedOn; /* true if LED is ON */
- u8 bSWLedCtrl;
- u8 bLedBlinkInProgress; /*true if blinking */
- u8 bLedNoLinkBlinkInProgress;
- u8 bLedLinkBlinkInProgress;
- u8 bLedStartToLinkBlinkInProgress;
- u8 bLedScanBlinkInProgress;
- u8 bLedWPSBlinkInProgress;
- u32 BlinkTimes; /* No. times to toggle for blink.*/
- u32 BlinkingLedState; /* Next state for blinking,
- * either LED_ON or OFF.
- */
-
- struct timer_list BlinkTimer; /* Timer object for led blinking.*/
- struct work_struct BlinkWorkItem; /* Workitem used by BlinkTimer */
-};
-
-struct led_priv {
- /* add for led control */
- struct LED_871x SwLed0;
- struct LED_871x SwLed1;
- enum LED_STRATEGY_871x LedStrategy;
- u8 bRegUseLed;
- void (*LedControlHandler)(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction);
- /* add for led control */
-};
-
-/*===========================================================================
- * Interface to manipulate LED objects.
- *===========================================================================
- */
-void r8712_InitSwLeds(struct _adapter *padapter);
-void r8712_DeInitSwLeds(struct _adapter *padapter);
-void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction);
-void r8712_flush_led_works(struct _adapter *padapter);
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c
deleted file mode 100644
index 70c295e97068..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mlme.c
+++ /dev/null
@@ -1,1710 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_mlme.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_MLME_C_
-
-#include <linux/etherdevice.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "xmit_osdep.h"
-#include "mlme_osdep.h"
-#include "sta_info.h"
-#include "wifi.h"
-#include "wlan_bssdef.h"
-
-static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len);
-
-int r8712_init_mlme_priv(struct _adapter *padapter)
-{
- sint i;
- u8 *pbuf;
- struct wlan_network *pnetwork;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- memset((u8 *)pmlmepriv, 0, sizeof(struct mlme_priv));
- pmlmepriv->nic_hdl = (u8 *)padapter;
- pmlmepriv->pscanned = NULL;
- pmlmepriv->fw_state = 0;
- pmlmepriv->cur_network.network.InfrastructureMode =
- Ndis802_11AutoUnknown;
- /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/
- pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */
- spin_lock_init(&(pmlmepriv->lock));
- spin_lock_init(&(pmlmepriv->lock2));
- _init_queue(&(pmlmepriv->free_bss_pool));
- _init_queue(&(pmlmepriv->scanned_queue));
- set_scanned_network_val(pmlmepriv, 0);
- memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
- pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network),
- GFP_ATOMIC);
- if (!pbuf)
- return -ENOMEM;
- pmlmepriv->free_bss_buf = pbuf;
- pnetwork = (struct wlan_network *)pbuf;
- for (i = 0; i < MAX_BSS_CNT; i++) {
- INIT_LIST_HEAD(&(pnetwork->list));
- list_add_tail(&(pnetwork->list),
- &(pmlmepriv->free_bss_pool.queue));
- pnetwork++;
- }
- pmlmepriv->sitesurveyctrl.last_rx_pkts = 0;
- pmlmepriv->sitesurveyctrl.last_tx_pkts = 0;
- pmlmepriv->sitesurveyctrl.traffic_busy = false;
- /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
- r8712_init_mlme_timer(padapter);
- return 0;
-}
-
-struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv)
-{
- unsigned long irqL;
- struct wlan_network *pnetwork;
- struct __queue *free_queue = &pmlmepriv->free_bss_pool;
-
- spin_lock_irqsave(&free_queue->lock, irqL);
- pnetwork = list_first_entry_or_null(&free_queue->queue,
- struct wlan_network, list);
- if (pnetwork) {
- list_del_init(&pnetwork->list);
- pnetwork->last_scanned = jiffies;
- pmlmepriv->num_of_scanned++;
- }
- spin_unlock_irqrestore(&free_queue->lock, irqL);
- return pnetwork;
-}
-
-static void _free_network(struct mlme_priv *pmlmepriv,
- struct wlan_network *pnetwork)
-{
- u32 curr_time, delta_time;
- unsigned long irqL;
- struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
-
- if (!pnetwork)
- return;
- if (pnetwork->fixed)
- return;
- curr_time = jiffies;
- delta_time = (curr_time - (u32)pnetwork->last_scanned) / HZ;
- if (delta_time < SCANQUEUE_LIFETIME)
- return;
- spin_lock_irqsave(&free_queue->lock, irqL);
- list_del_init(&pnetwork->list);
- list_add_tail(&pnetwork->list, &free_queue->queue);
- pmlmepriv->num_of_scanned--;
- spin_unlock_irqrestore(&free_queue->lock, irqL);
-}
-
-static void free_network_nolock(struct mlme_priv *pmlmepriv,
- struct wlan_network *pnetwork)
-{
- struct __queue *free_queue = &pmlmepriv->free_bss_pool;
-
- if (!pnetwork)
- return;
- if (pnetwork->fixed)
- return;
- list_del_init(&pnetwork->list);
- list_add_tail(&pnetwork->list, &free_queue->queue);
- pmlmepriv->num_of_scanned--;
-}
-
-/* return the wlan_network with the matching addr
- * Shall be called under atomic context...
- * to avoid possible racing condition...
- */
-static struct wlan_network *r8712_find_network(struct __queue *scanned_queue,
- u8 *addr)
-{
- unsigned long irqL;
- struct list_head *phead, *plist;
- struct wlan_network *pnetwork = NULL;
-
- if (is_zero_ether_addr(addr))
- return NULL;
- spin_lock_irqsave(&scanned_queue->lock, irqL);
- phead = &scanned_queue->queue;
- list_for_each(plist, phead) {
- pnetwork = list_entry(plist, struct wlan_network, list);
- if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
- break;
- }
- if (plist == phead)
- pnetwork = NULL;
- spin_unlock_irqrestore(&scanned_queue->lock, irqL);
- return pnetwork;
-}
-
-void r8712_free_network_queue(struct _adapter *padapter)
-{
- unsigned long irqL;
- struct list_head *phead, *plist;
- struct wlan_network *pnetwork;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *scanned_queue = &pmlmepriv->scanned_queue;
-
- spin_lock_irqsave(&scanned_queue->lock, irqL);
- phead = &scanned_queue->queue;
- plist = phead->next;
- while (!end_of_queue_search(phead, plist)) {
- pnetwork = container_of(plist, struct wlan_network, list);
- plist = plist->next;
- _free_network(pmlmepriv, pnetwork);
- }
- spin_unlock_irqrestore(&scanned_queue->lock, irqL);
-}
-
-sint r8712_if_up(struct _adapter *padapter)
-{
- sint res;
-
- if (padapter->driver_stopped || padapter->surprise_removed ||
- !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
- res = false;
- } else {
- res = true;
- }
- return res;
-}
-
-void r8712_generate_random_ibss(u8 *pibss)
-{
- u32 curtime = jiffies;
-
- pibss[0] = 0x02; /*in ad-hoc mode bit1 must set to 1 */
- pibss[1] = 0x11;
- pibss[2] = 0x87;
- pibss[3] = (u8)(curtime & 0xff);
- pibss[4] = (u8)((curtime >> 8) & 0xff);
- pibss[5] = (u8)((curtime >> 16) & 0xff);
-}
-
-uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
-{
- return sizeof(*bss) + bss->IELength - MAX_IE_SZ;
-}
-
-u8 *r8712_get_capability_from_ie(u8 *ie)
-{
- return ie + 8 + 2;
-}
-
-void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv)
-{
- kfree(pmlmepriv->free_bss_buf);
-}
-
-static struct wlan_network *alloc_network(struct mlme_priv *pmlmepriv)
-{
- return _r8712_alloc_network(pmlmepriv);
-}
-
-int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork)
-{
- int ret = true;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
-
- if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
- (pnetwork->network.Privacy == cpu_to_le32(0)))
- ret = false;
- else if ((psecuritypriv->PrivacyAlgrthm == _NO_PRIVACY_) &&
- (pnetwork->network.Privacy == cpu_to_le32(1)))
- ret = false;
- else
- ret = true;
- return ret;
-
-}
-
-static int is_same_network(struct wlan_bssid_ex *src,
- struct wlan_bssid_ex *dst)
-{
- u16 s_cap, d_cap;
-
- memcpy((u8 *)&s_cap, r8712_get_capability_from_ie(src->IEs), 2);
- memcpy((u8 *)&d_cap, r8712_get_capability_from_ie(dst->IEs), 2);
- return (src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
- (src->Configuration.DSConfig ==
- dst->Configuration.DSConfig) &&
- ((!memcmp(src->MacAddress, dst->MacAddress,
- ETH_ALEN))) &&
- ((!memcmp(src->Ssid.Ssid,
- dst->Ssid.Ssid,
- src->Ssid.SsidLength))) &&
- ((s_cap & WLAN_CAPABILITY_IBSS) ==
- (d_cap & WLAN_CAPABILITY_IBSS)) &&
- ((s_cap & WLAN_CAPABILITY_ESS) ==
- (d_cap & WLAN_CAPABILITY_ESS));
-
-}
-
-struct wlan_network *r8712_get_oldest_wlan_network(
- struct __queue *scanned_queue)
-{
- struct list_head *plist, *phead;
- struct wlan_network *pwlan = NULL;
- struct wlan_network *oldest = NULL;
-
- phead = &scanned_queue->queue;
- plist = phead->next;
- while (1) {
- if (end_of_queue_search(phead, plist))
- break;
- pwlan = container_of(plist, struct wlan_network, list);
- if (!pwlan->fixed) {
- if (!oldest ||
- time_after((unsigned long)oldest->last_scanned,
- (unsigned long)pwlan->last_scanned))
- oldest = pwlan;
- }
- plist = plist->next;
- }
- return oldest;
-}
-
-static void update_network(struct wlan_bssid_ex *dst,
- struct wlan_bssid_ex *src,
- struct _adapter *padapter)
-{
- u32 last_evm = 0, tmpVal;
- struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data;
-
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
- is_same_network(&(padapter->mlmepriv.cur_network.network), src)) {
- if (padapter->recvpriv.signal_qual_data.total_num++ >=
- PHY_LINKQUALITY_SLID_WIN_MAX) {
- padapter->recvpriv.signal_qual_data.total_num =
- PHY_LINKQUALITY_SLID_WIN_MAX;
- last_evm = sqd->elements[sqd->index];
- padapter->recvpriv.signal_qual_data.total_val -=
- last_evm;
- }
- padapter->recvpriv.signal_qual_data.total_val += src->Rssi;
-
- sqd->elements[sqd->index++] = src->Rssi;
- if (padapter->recvpriv.signal_qual_data.index >=
- PHY_LINKQUALITY_SLID_WIN_MAX)
- padapter->recvpriv.signal_qual_data.index = 0;
- /* <1> Showed on UI for user, in percentage. */
- tmpVal = padapter->recvpriv.signal_qual_data.total_val /
- padapter->recvpriv.signal_qual_data.total_num;
- padapter->recvpriv.signal = (u8)tmpVal;
-
- src->Rssi = padapter->recvpriv.signal;
- } else {
- src->Rssi = (src->Rssi + dst->Rssi) / 2;
- }
- memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src));
-}
-
-static void update_current_network(struct _adapter *adapter,
- struct wlan_bssid_ex *pnetwork)
-{
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- if (is_same_network(&(pmlmepriv->cur_network.network), pnetwork)) {
- update_network(&(pmlmepriv->cur_network.network),
- pnetwork, adapter);
- r8712_update_protection(adapter,
- (pmlmepriv->cur_network.network.IEs) +
- sizeof(struct NDIS_802_11_FIXED_IEs),
- pmlmepriv->cur_network.network.IELength);
- }
-}
-
-/* Caller must hold pmlmepriv->lock first */
-static void update_scanned_network(struct _adapter *adapter,
- struct wlan_bssid_ex *target)
-{
- struct list_head *plist, *phead;
-
- u32 bssid_ex_sz;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct wlan_network *pnetwork = NULL;
- struct wlan_network *oldest = NULL;
-
- phead = &queue->queue;
- plist = phead->next;
-
- while (1) {
- if (end_of_queue_search(phead, plist))
- break;
-
- pnetwork = container_of(plist, struct wlan_network, list);
- if (is_same_network(&pnetwork->network, target))
- break;
- if ((oldest == ((struct wlan_network *)0)) ||
- time_after((unsigned long)oldest->last_scanned,
- (unsigned long)pnetwork->last_scanned))
- oldest = pnetwork;
-
- plist = plist->next;
- }
-
- /* If we didn't find a match, then get a new network slot to initialize
- * with this beacon's information
- */
- if (end_of_queue_search(phead, plist)) {
- if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
- /* If there are no more slots, expire the oldest */
- pnetwork = oldest;
- target->Rssi = (pnetwork->network.Rssi +
- target->Rssi) / 2;
- memcpy(&pnetwork->network, target,
- r8712_get_wlan_bssid_ex_sz(target));
- pnetwork->last_scanned = jiffies;
- } else {
- /* Otherwise just pull from the free list */
- /* update scan_time */
- pnetwork = alloc_network(pmlmepriv);
- if (!pnetwork)
- return;
- bssid_ex_sz = r8712_get_wlan_bssid_ex_sz(target);
- target->Length = bssid_ex_sz;
- memcpy(&pnetwork->network, target, bssid_ex_sz);
- list_add_tail(&pnetwork->list, &queue->queue);
- }
- } else {
- /* we have an entry and we are going to update it. But
- * this entry may be already expired. In this case we
- * do the same as we found a new net and call the new_net
- * handler
- */
- update_network(&pnetwork->network, target, adapter);
- pnetwork->last_scanned = jiffies;
- }
-}
-
-static void rtl8711_add_network(struct _adapter *adapter,
- struct wlan_bssid_ex *pnetwork)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &(((struct _adapter *)adapter)->mlmepriv);
- struct __queue *queue = &pmlmepriv->scanned_queue;
-
- spin_lock_irqsave(&queue->lock, irqL);
- update_current_network(adapter, pnetwork);
- update_scanned_network(adapter, pnetwork);
- spin_unlock_irqrestore(&queue->lock, irqL);
-}
-
-/*select the desired network based on the capability of the (i)bss.
- * check items: (1) security
- * (2) network_type
- * (3) WMM
- * (4) HT
- * (5) others
- */
-static int is_desired_network(struct _adapter *adapter,
- struct wlan_network *pnetwork)
-{
- u8 wps_ie[512];
- uint wps_ielen;
- int bselected = true;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
-
- if (psecuritypriv->wps_phase) {
- if (r8712_get_wps_ie(pnetwork->network.IEs,
- pnetwork->network.IELength, wps_ie,
- &wps_ielen))
- return true;
- return false;
- }
- if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
- (pnetwork->network.Privacy == 0))
- bselected = false;
- if (check_fwstate(&adapter->mlmepriv, WIFI_ADHOC_STATE)) {
- if (pnetwork->network.InfrastructureMode !=
- adapter->mlmepriv.cur_network.network.InfrastructureMode)
- bselected = false;
- }
- return bselected;
-}
-
-/* TODO: Perry : For Power Management */
-void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
-}
-
-void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- unsigned long flags;
- u32 len;
- struct wlan_bssid_ex *pnetwork;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- pnetwork = (struct wlan_bssid_ex *)pbuf;
-#ifdef __BIG_ENDIAN
- /* endian_convert */
- pnetwork->Length = le32_to_cpu(pnetwork->Length);
- pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
- pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
- pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
- pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
- pnetwork->Configuration.ATIMWindow =
- le32_to_cpu(pnetwork->Configuration.ATIMWindow);
- pnetwork->Configuration.BeaconPeriod =
- le32_to_cpu(pnetwork->Configuration.BeaconPeriod);
- pnetwork->Configuration.DSConfig =
- le32_to_cpu(pnetwork->Configuration.DSConfig);
- pnetwork->Configuration.FHConfig.DwellTime =
- le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
- pnetwork->Configuration.FHConfig.HopPattern =
- le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
- pnetwork->Configuration.FHConfig.HopSet =
- le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
- pnetwork->Configuration.FHConfig.Length =
- le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
- pnetwork->Configuration.Length =
- le32_to_cpu(pnetwork->Configuration.Length);
- pnetwork->InfrastructureMode =
- le32_to_cpu(pnetwork->InfrastructureMode);
- pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
-#endif
- len = r8712_get_wlan_bssid_ex_sz(pnetwork);
- if (len > sizeof(struct wlan_bssid_ex))
- return;
- spin_lock_irqsave(&pmlmepriv->lock2, flags);
- /* update IBSS_network 's timestamp */
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress),
- pnetwork->MacAddress, ETH_ALEN)) {
- struct wlan_network *ibss_wlan = NULL;
-
- memcpy(pmlmepriv->cur_network.network.IEs,
- pnetwork->IEs, 8);
- ibss_wlan = r8712_find_network(
- &pmlmepriv->scanned_queue,
- pnetwork->MacAddress);
- if (ibss_wlan) {
- memcpy(ibss_wlan->network.IEs,
- pnetwork->IEs, 8);
- goto exit;
- }
- }
- }
- /* lock pmlmepriv->lock when you accessing network_q */
- if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
- if (pnetwork->Ssid.Ssid[0] != 0) {
- rtl8711_add_network(adapter, pnetwork);
- } else {
- pnetwork->Ssid.SsidLength = 8;
- memcpy(pnetwork->Ssid.Ssid, "<hidden>", 8);
- rtl8711_add_network(adapter, pnetwork);
- }
- }
-exit:
- spin_unlock_irqrestore(&pmlmepriv->lock2, flags);
-}
-
-void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
- del_timer(&pmlmepriv->scan_to_timer);
-
- _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
- }
-
- if (pmlmepriv->to_join) {
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
- if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
-
- if (!r8712_select_and_join_from_scan(pmlmepriv)) {
- mod_timer(&pmlmepriv->assoc_timer, jiffies +
- msecs_to_jiffies(MAX_JOIN_TIMEOUT));
- } else {
- struct wlan_bssid_ex *pdev_network =
- &(adapter->registrypriv.dev_network);
- u8 *pibss =
- adapter->registrypriv.dev_network.MacAddress;
- pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;
- memcpy(&pdev_network->Ssid,
- &pmlmepriv->assoc_ssid,
- sizeof(struct
- ndis_802_11_ssid));
- r8712_update_registrypriv_dev_network
- (adapter);
- r8712_generate_random_ibss(pibss);
- pmlmepriv->fw_state =
- WIFI_ADHOC_MASTER_STATE;
- pmlmepriv->to_join = false;
- }
- }
- } else {
- pmlmepriv->to_join = false;
- set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
- if (!r8712_select_and_join_from_scan(pmlmepriv))
- mod_timer(&pmlmepriv->assoc_timer, jiffies +
- msecs_to_jiffies(MAX_JOIN_TIMEOUT));
- else
- _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
- }
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-/*
- *r8712_free_assoc_resources: the caller has to lock pmlmepriv->lock
- */
-void r8712_free_assoc_resources(struct _adapter *adapter)
-{
- unsigned long irqL;
- struct wlan_network *pwlan = NULL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct wlan_network *tgt_network = &pmlmepriv->cur_network;
-
- pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
- tgt_network->network.MacAddress);
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
- struct sta_info *psta;
-
- psta = r8712_get_stainfo(&adapter->stapriv,
- tgt_network->network.MacAddress);
-
- spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
- r8712_free_stainfo(adapter, psta);
- spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
- }
-
- if (check_fwstate(pmlmepriv,
- WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
- r8712_free_all_stainfo(adapter);
- if (pwlan)
- pwlan->fixed = false;
-
- if (((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) &&
- (adapter->stapriv.asoc_sta_count == 1)))
- free_network_nolock(pmlmepriv, pwlan);
-}
-
-/*
- * r8712_indicate_connect: the caller has to lock pmlmepriv->lock
- */
-void r8712_indicate_connect(struct _adapter *padapter)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- pmlmepriv->to_join = false;
- set_fwstate(pmlmepriv, _FW_LINKED);
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_LINK);
- r8712_os_indicate_connect(padapter);
- if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE)
- mod_timer(&pmlmepriv->dhcp_timer,
- jiffies + msecs_to_jiffies(60000));
-}
-
-/*
- * r8712_ind_disconnect: the caller has to lock pmlmepriv->lock
- */
-void r8712_ind_disconnect(struct _adapter *padapter)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- _clr_fwstate_(pmlmepriv, _FW_LINKED);
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
- r8712_os_indicate_disconnect(padapter);
- }
- if (padapter->pwrctrlpriv.pwr_mode !=
- padapter->registrypriv.power_mgnt) {
- del_timer(&pmlmepriv->dhcp_timer);
- r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
- padapter->registrypriv.smart_ps);
- }
-}
-
-/*Notes:
- *pnetwork : returns from r8712_joinbss_event_callback
- *ptarget_wlan: found from scanned_queue
- *if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if
- * "ptarget_sta" & "ptarget_wlan" exist.
- *if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check
- * if "ptarget_wlan" exist.
- *if join_res > 0, update "cur_network->network" from
- * "pnetwork->network" if (ptarget_wlan !=NULL).
- */
-void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- unsigned long irqL = 0, irqL2;
- struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct wlan_network *cur_network = &pmlmepriv->cur_network;
- struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL;
- unsigned int the_same_macaddr = false;
- struct wlan_network *pnetwork;
-
- if (sizeof(struct list_head) == 4 * sizeof(u32)) {
- pnetwork = kmalloc(sizeof(struct wlan_network), GFP_ATOMIC);
- if (!pnetwork)
- return;
- memcpy((u8 *)pnetwork + 16, (u8 *)pbuf + 8,
- sizeof(struct wlan_network) - 16);
- } else {
- pnetwork = (struct wlan_network *)pbuf;
- }
-
-#ifdef __BIG_ENDIAN
- /* endian_convert */
- pnetwork->join_res = le32_to_cpu(pnetwork->join_res);
- pnetwork->network_type = le32_to_cpu(pnetwork->network_type);
- pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length);
- pnetwork->network.Ssid.SsidLength =
- le32_to_cpu(pnetwork->network.Ssid.SsidLength);
- pnetwork->network.Privacy = le32_to_cpu(pnetwork->network.Privacy);
- pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi);
- pnetwork->network.NetworkTypeInUse =
- le32_to_cpu(pnetwork->network.NetworkTypeInUse);
- pnetwork->network.Configuration.ATIMWindow =
- le32_to_cpu(pnetwork->network.Configuration.ATIMWindow);
- pnetwork->network.Configuration.BeaconPeriod =
- le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod);
- pnetwork->network.Configuration.DSConfig =
- le32_to_cpu(pnetwork->network.Configuration.DSConfig);
- pnetwork->network.Configuration.FHConfig.DwellTime =
- le32_to_cpu(pnetwork->network.Configuration.FHConfig.DwellTime);
- pnetwork->network.Configuration.FHConfig.HopPattern =
- le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopPattern);
- pnetwork->network.Configuration.FHConfig.HopSet =
- le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet);
- pnetwork->network.Configuration.FHConfig.Length =
- le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length);
- pnetwork->network.Configuration.Length =
- le32_to_cpu(pnetwork->network.Configuration.Length);
- pnetwork->network.InfrastructureMode =
- le32_to_cpu(pnetwork->network.InfrastructureMode);
- pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength);
-#endif
-
- the_same_macaddr = !memcmp(pnetwork->network.MacAddress,
- cur_network->network.MacAddress, ETH_ALEN);
- pnetwork->network.Length =
- r8712_get_wlan_bssid_ex_sz(&pnetwork->network);
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
- goto ignore_joinbss_callback;
- if (pnetwork->join_res > 0) {
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
- /*s1. find ptarget_wlan*/
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (the_same_macaddr) {
- ptarget_wlan =
- r8712_find_network(&pmlmepriv->scanned_queue,
- cur_network->network.MacAddress);
- } else {
- pcur_wlan =
- r8712_find_network(&pmlmepriv->scanned_queue,
- cur_network->network.MacAddress);
- if (pcur_wlan)
- pcur_wlan->fixed = false;
-
- pcur_sta = r8712_get_stainfo(pstapriv,
- cur_network->network.MacAddress);
- spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL2);
- r8712_free_stainfo(adapter, pcur_sta);
- spin_unlock_irqrestore(&(pstapriv->sta_hash_lock), irqL2);
-
- ptarget_wlan =
- r8712_find_network(&pmlmepriv->scanned_queue,
- pnetwork->network.MacAddress);
- if (ptarget_wlan)
- ptarget_wlan->fixed = true;
- }
- } else {
- ptarget_wlan = r8712_find_network(&pmlmepriv->scanned_queue,
- pnetwork->network.MacAddress);
- if (ptarget_wlan)
- ptarget_wlan->fixed = true;
- }
-
- if (!ptarget_wlan) {
- if (check_fwstate(pmlmepriv,
- _FW_UNDER_LINKING))
- pmlmepriv->fw_state ^=
- _FW_UNDER_LINKING;
- goto ignore_joinbss_callback;
- }
-
- /*s2. find ptarget_sta & update ptarget_sta*/
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- if (the_same_macaddr) {
- ptarget_sta =
- r8712_get_stainfo(pstapriv,
- pnetwork->network.MacAddress);
- if (!ptarget_sta)
- ptarget_sta =
- r8712_alloc_stainfo(pstapriv,
- pnetwork->network.MacAddress);
- } else {
- ptarget_sta =
- r8712_alloc_stainfo(pstapriv,
- pnetwork->network.MacAddress);
- }
- if (ptarget_sta) /*update ptarget_sta*/ {
- ptarget_sta->aid = pnetwork->join_res;
- ptarget_sta->qos_option = 1;
- ptarget_sta->mac_id = 5;
- if (adapter->securitypriv.AuthAlgrthm == 2) {
- adapter->securitypriv.binstallGrpkey = false;
- adapter->securitypriv.busetkipkey = false;
- adapter->securitypriv.bgrpkey_handshake = false;
- ptarget_sta->ieee8021x_blocked = true;
- ptarget_sta->XPrivacy =
- adapter->securitypriv.PrivacyAlgrthm;
- memset((u8 *)&ptarget_sta->x_UncstKey,
- 0,
- sizeof(union Keytype));
- memset((u8 *)&ptarget_sta->tkiprxmickey,
- 0,
- sizeof(union Keytype));
- memset((u8 *)&ptarget_sta->tkiptxmickey,
- 0,
- sizeof(union Keytype));
- memset((u8 *)&ptarget_sta->txpn,
- 0,
- sizeof(union pn48));
- memset((u8 *)&ptarget_sta->rxpn,
- 0,
- sizeof(union pn48));
- }
- } else {
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- pmlmepriv->fw_state ^=
- _FW_UNDER_LINKING;
- goto ignore_joinbss_callback;
- }
- }
-
- /*s3. update cur_network & indicate connect*/
- memcpy(&cur_network->network, &pnetwork->network,
- pnetwork->network.Length);
- cur_network->aid = pnetwork->join_res;
- /*update fw_state will clr _FW_UNDER_LINKING*/
- switch (pnetwork->network.InfrastructureMode) {
- case Ndis802_11Infrastructure:
- pmlmepriv->fw_state = WIFI_STATION_STATE;
- break;
- case Ndis802_11IBSS:
- pmlmepriv->fw_state = WIFI_ADHOC_STATE;
- break;
- default:
- pmlmepriv->fw_state = WIFI_NULL_STATE;
- break;
- }
- r8712_update_protection(adapter,
- (cur_network->network.IEs) +
- sizeof(struct NDIS_802_11_FIXED_IEs),
- (cur_network->network.IELength));
- /*TODO: update HT_Capability*/
- update_ht_cap(adapter, cur_network->network.IEs,
- cur_network->network.IELength);
- /*indicate connect*/
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- r8712_indicate_connect(adapter);
- del_timer(&pmlmepriv->assoc_timer);
- } else {
- goto ignore_joinbss_callback;
- }
- } else {
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(1));
- _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
- }
- }
-ignore_joinbss_callback:
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- if (sizeof(struct list_head) == 4 * sizeof(u32))
- kfree(pnetwork);
-}
-
-void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- unsigned long irqL;
- struct sta_info *psta;
- struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
- struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
-
- /* to do: */
- if (!r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr))
- return;
- psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
- if (psta) {
- /*the sta have been in sta_info_queue => do nothing
- *(between drv has received this event before and
- * fw have not yet to set key to CAM_ENTRY)
- */
- return;
- }
-
- psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
- if (!psta)
- return;
- /* to do : init sta_info variable */
- psta->qos_option = 0;
- psta->mac_id = le32_to_cpu(pstassoc->cam_id);
- /* psta->aid = (uint)pstassoc->cam_id; */
-
- if (adapter->securitypriv.AuthAlgrthm == 2)
- psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm;
- psta->ieee8021x_blocked = false;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
- if (adapter->stapriv.asoc_sta_count == 2) {
- /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
- r8712_indicate_connect(adapter);
- }
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- unsigned long irqL, irqL2;
- struct sta_info *psta;
- struct wlan_network *pwlan = NULL;
- struct wlan_bssid_ex *pdev_network = NULL;
- u8 *pibss = NULL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct stadel_event *pstadel = (struct stadel_event *)pbuf;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct wlan_network *tgt_network = &pmlmepriv->cur_network;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL2);
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- r8712_ind_disconnect(adapter);
- r8712_free_assoc_resources(adapter);
- }
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE |
- WIFI_ADHOC_STATE)) {
- psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr);
- spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
- r8712_free_stainfo(adapter, psta);
- spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
- if (adapter->stapriv.asoc_sta_count == 1) {
- /*a sta + bc/mc_stainfo (not Ibss_stainfo) */
- pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
- tgt_network->network.MacAddress);
- if (pwlan) {
- pwlan->fixed = false;
- free_network_nolock(pmlmepriv, pwlan);
- }
- /*re-create ibss*/
- pdev_network = &(adapter->registrypriv.dev_network);
- pibss = adapter->registrypriv.dev_network.MacAddress;
- memcpy(pdev_network, &tgt_network->network,
- r8712_get_wlan_bssid_ex_sz(&tgt_network->network));
- memcpy(&pdev_network->Ssid,
- &pmlmepriv->assoc_ssid,
- sizeof(struct ndis_802_11_ssid));
- r8712_update_registrypriv_dev_network(adapter);
- r8712_generate_random_ibss(pibss);
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
- _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
- set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
- }
- }
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL2);
-}
-
-void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- struct reportpwrstate_parm *preportpwrstate =
- (struct reportpwrstate_parm *)pbuf;
-
- preportpwrstate->state |= (u8)(adapter->pwrctrlpriv.cpwm_tog + 0x80);
- r8712_cpwm_int_hdl(adapter, preportpwrstate);
-}
-
-/* When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send
- * the ADDBA req frame with start seq control = 0 to wifi client after
- * the WPA handshake and the sequence number of following data packet
- * will be 0. In this case, the Rx reorder sequence is not longer than 0
- * and the WiFi client will drop the data with seq number 0.
- * So, the 8712 firmware has to inform driver with receiving the
- * ADDBA-Req frame so that the driver can reset the
- * sequence value of Rx reorder control.
- */
-void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- struct ADDBA_Req_Report_parm *pAddbareq_pram =
- (struct ADDBA_Req_Report_parm *)pbuf;
- struct sta_info *psta;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct recv_reorder_ctrl *precvreorder_ctrl = NULL;
-
- psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress);
- if (psta) {
- precvreorder_ctrl =
- &psta->recvreorder_ctrl[pAddbareq_pram->tid];
- /* set the indicate_seq to 0xffff so that the rx reorder
- * can store any following data packet.
- */
- precvreorder_ctrl->indicate_seq = 0xffff;
- }
-}
-
-void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- if (!adapter->securitypriv.wps_hw_pbc_pressed)
- adapter->securitypriv.wps_hw_pbc_pressed = true;
-}
-
-void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter)
-{
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct sitesurvey_ctrl *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
- struct registry_priv *pregistrypriv = &adapter->registrypriv;
- u64 current_tx_pkts;
- uint current_rx_pkts;
-
- current_tx_pkts = (adapter->xmitpriv.tx_pkts) -
- (psitesurveyctrl->last_tx_pkts);
- current_rx_pkts = (adapter->recvpriv.rx_pkts) -
- (psitesurveyctrl->last_rx_pkts);
- psitesurveyctrl->last_tx_pkts = adapter->xmitpriv.tx_pkts;
- psitesurveyctrl->last_rx_pkts = adapter->recvpriv.rx_pkts;
- if ((current_tx_pkts > pregistrypriv->busy_thresh) ||
- (current_rx_pkts > pregistrypriv->busy_thresh))
- psitesurveyctrl->traffic_busy = true;
- else
- psitesurveyctrl->traffic_busy = false;
-}
-
-void _r8712_join_timeout_handler(struct _adapter *adapter)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- if (adapter->driver_stopped || adapter->surprise_removed)
- return;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
- pmlmepriv->to_join = false;
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- r8712_os_indicate_disconnect(adapter);
- _clr_fwstate_(pmlmepriv, _FW_LINKED);
- }
- if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) {
- r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
- adapter->registrypriv.smart_ps);
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-void r8712_scan_timeout_handler (struct _adapter *adapter)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
- pmlmepriv->to_join = false; /* scan fail, so clear to_join flag */
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-void _r8712_dhcp_timeout_handler (struct _adapter *adapter)
-{
- if (adapter->driver_stopped || adapter->surprise_removed)
- return;
- if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt)
- r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
- adapter->registrypriv.smart_ps);
-}
-
-int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
-{
- struct list_head *phead;
- unsigned char *dst_ssid, *src_ssid;
- struct _adapter *adapter;
- struct __queue *queue = NULL;
- struct wlan_network *pnetwork = NULL;
- struct wlan_network *pnetwork_max_rssi = NULL;
-
- adapter = (struct _adapter *)pmlmepriv->nic_hdl;
- queue = &pmlmepriv->scanned_queue;
- phead = &queue->queue;
- pmlmepriv->pscanned = phead->next;
- while (1) {
- if (end_of_queue_search(phead, pmlmepriv->pscanned)) {
- if (pmlmepriv->assoc_by_rssi && pnetwork_max_rssi) {
- pnetwork = pnetwork_max_rssi;
- goto ask_for_joinbss;
- }
- return -EINVAL;
- }
- pnetwork = container_of(pmlmepriv->pscanned,
- struct wlan_network, list);
- pmlmepriv->pscanned = pmlmepriv->pscanned->next;
- if (pmlmepriv->assoc_by_bssid) {
- dst_ssid = pnetwork->network.MacAddress;
- src_ssid = pmlmepriv->assoc_bssid;
- if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (is_same_network(&pmlmepriv->cur_network.network,
- &pnetwork->network)) {
- _clr_fwstate_(pmlmepriv,
- _FW_UNDER_LINKING);
- /*r8712_indicate_connect again*/
- r8712_indicate_connect(adapter);
- return 2;
- }
- r8712_disassoc_cmd(adapter);
- r8712_ind_disconnect(adapter);
- r8712_free_assoc_resources(adapter);
- }
- goto ask_for_joinbss;
- }
- } else if (pmlmepriv->assoc_ssid.SsidLength == 0) {
- goto ask_for_joinbss;
- }
- dst_ssid = pnetwork->network.Ssid.Ssid;
- src_ssid = pmlmepriv->assoc_ssid.Ssid;
- if ((pnetwork->network.Ssid.SsidLength ==
- pmlmepriv->assoc_ssid.SsidLength) &&
- (!memcmp(dst_ssid, src_ssid,
- pmlmepriv->assoc_ssid.SsidLength))) {
- if (pmlmepriv->assoc_by_rssi) {
- /* if the ssid is the same, select the bss
- * which has the max rssi
- */
- if (pnetwork_max_rssi) {
- if (pnetwork->network.Rssi >
- pnetwork_max_rssi->network.Rssi)
- pnetwork_max_rssi = pnetwork;
- } else {
- pnetwork_max_rssi = pnetwork;
- }
- } else if (is_desired_network(adapter, pnetwork)) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- r8712_disassoc_cmd(adapter);
- r8712_free_assoc_resources(adapter);
- }
- goto ask_for_joinbss;
- }
- }
- }
-
-ask_for_joinbss:
- return r8712_joinbss_cmd(adapter, pnetwork);
-}
-
-int r8712_set_auth(struct _adapter *adapter,
- struct security_priv *psecuritypriv)
-{
- struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
- struct cmd_obj *pcmd;
- struct setauth_parm *psetauthparm;
-
- pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
- if (!pcmd)
- return -ENOMEM;
-
- psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC);
- if (!psetauthparm) {
- kfree(pcmd);
- return -ENOMEM;
- }
- psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm;
- pcmd->cmdcode = _SetAuth_CMD_;
- pcmd->parmbuf = (unsigned char *)psetauthparm;
- pcmd->cmdsz = sizeof(struct setauth_parm);
- pcmd->rsp = NULL;
- pcmd->rspsz = 0;
- INIT_LIST_HEAD(&pcmd->list);
- r8712_enqueue_cmd(pcmdpriv, pcmd);
- return 0;
-}
-
-int r8712_set_key(struct _adapter *adapter,
- struct security_priv *psecuritypriv,
- sint keyid)
-{
- struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
- struct cmd_obj *pcmd;
- struct setkey_parm *psetkeyparm;
- u8 keylen;
- int ret;
-
- pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
- if (!pcmd)
- return -ENOMEM;
- psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC);
- if (!psetkeyparm) {
- ret = -ENOMEM;
- goto err_free_cmd;
- }
- if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */
- psetkeyparm->algorithm =
- (u8)psecuritypriv->XGrpPrivacy;
- } else { /* WEP */
- psetkeyparm->algorithm =
- (u8)psecuritypriv->PrivacyAlgrthm;
- }
- psetkeyparm->keyid = (u8)keyid;
-
- switch (psetkeyparm->algorithm) {
- case _WEP40_:
- keylen = 5;
- memcpy(psetkeyparm->key,
- psecuritypriv->DefKey[keyid].skey, keylen);
- break;
- case _WEP104_:
- keylen = 13;
- memcpy(psetkeyparm->key,
- psecuritypriv->DefKey[keyid].skey, keylen);
- break;
- case _TKIP_:
- if (keyid < 1 || keyid > 2) {
- ret = -EINVAL;
- goto err_free_parm;
- }
- keylen = 16;
- memcpy(psetkeyparm->key,
- &psecuritypriv->XGrpKey[keyid - 1], keylen);
- psetkeyparm->grpkey = 1;
- break;
- case _AES_:
- if (keyid < 1 || keyid > 2) {
- ret = -EINVAL;
- goto err_free_parm;
- }
- keylen = 16;
- memcpy(psetkeyparm->key,
- &psecuritypriv->XGrpKey[keyid - 1], keylen);
- psetkeyparm->grpkey = 1;
- break;
- default:
- ret = -EINVAL;
- goto err_free_parm;
- }
- pcmd->cmdcode = _SetKey_CMD_;
- pcmd->parmbuf = (u8 *)psetkeyparm;
- pcmd->cmdsz = (sizeof(struct setkey_parm));
- pcmd->rsp = NULL;
- pcmd->rspsz = 0;
- INIT_LIST_HEAD(&pcmd->list);
- r8712_enqueue_cmd(pcmdpriv, pcmd);
- return 0;
-
-err_free_parm:
- kfree(psetkeyparm);
-err_free_cmd:
- kfree(pcmd);
- return ret;
-}
-
-/* adjust IEs for r8712_joinbss_cmd in WMM */
-int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, u8 *out_ie,
- uint in_len, uint initial_out_len)
-{
- unsigned int ielength = 0;
- unsigned int i, j;
-
- i = 12; /* after the fixed IE */
- while (i < in_len) {
- ielength = initial_out_len;
- if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
- in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
- in_ie[i + 5] == 0x02 && i + 5 < in_len) {
- /*WMM element ID and OUI*/
- for (j = i; j < i + 9; j++) {
- out_ie[ielength] = in_ie[j];
- ielength++;
- }
- out_ie[initial_out_len + 1] = 0x07;
- out_ie[initial_out_len + 6] = 0x00;
- out_ie[initial_out_len + 8] = 0x00;
- break;
- }
- i += (in_ie[i + 1] + 2); /* to the next IE element */
- }
- return ielength;
-}
-
-/*
- * Ported from 8185: IsInPreAuthKeyList().
- *
- * Search by BSSID,
- * Return Value:
- * -1 :if there is no pre-auth key in the table
- * >=0 :if there is pre-auth key, and return the entry id
- */
-static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid)
-{
- struct security_priv *p = &Adapter->securitypriv;
- int i;
-
- for (i = 0; i < NUM_PMKID_CACHE; i++)
- if (p->PMKIDList[i].bUsed && !memcmp(p->PMKIDList[i].Bssid, bssid, ETH_ALEN))
- return i;
- return -1;
-}
-
-sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
- u8 *out_ie, uint in_len)
-{
- u8 authmode = 0, match;
- u8 sec_ie[IW_CUSTOM_MAX], uncst_oui[4], bkup_ie[255];
- u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
- uint ielength, cnt, remove_cnt;
- int iEntry;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
- uint ndisauthmode = psecuritypriv->ndisauthtype;
- uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
-
- if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
- (ndisauthmode == Ndis802_11AuthModeWPAPSK)) {
- authmode = _WPA_IE_ID_;
- uncst_oui[0] = 0x0;
- uncst_oui[1] = 0x50;
- uncst_oui[2] = 0xf2;
- }
- if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
- (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) {
- authmode = _WPA2_IE_ID_;
- uncst_oui[0] = 0x0;
- uncst_oui[1] = 0x0f;
- uncst_oui[2] = 0xac;
- }
- switch (ndissecuritytype) {
- case Ndis802_11Encryption1Enabled:
- case Ndis802_11Encryption1KeyAbsent:
- uncst_oui[3] = 0x1;
- break;
- case Ndis802_11Encryption2Enabled:
- case Ndis802_11Encryption2KeyAbsent:
- uncst_oui[3] = 0x2;
- break;
- case Ndis802_11Encryption3Enabled:
- case Ndis802_11Encryption3KeyAbsent:
- uncst_oui[3] = 0x4;
- break;
- default:
- break;
- }
- /*Search required WPA or WPA2 IE and copy to sec_ie[] */
- cnt = 12;
- match = false;
- while (cnt < in_len) {
- if (in_ie[cnt] == authmode) {
- if ((authmode == _WPA_IE_ID_) &&
- (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
- memcpy(&sec_ie[0], &in_ie[cnt],
- in_ie[cnt + 1] + 2);
- match = true;
- break;
- }
- if (authmode == _WPA2_IE_ID_) {
- memcpy(&sec_ie[0], &in_ie[cnt],
- in_ie[cnt + 1] + 2);
- match = true;
- break;
- }
- if (((authmode == _WPA_IE_ID_) &&
- (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) ||
- (authmode == _WPA2_IE_ID_))
- memcpy(&bkup_ie[0], &in_ie[cnt],
- in_ie[cnt + 1] + 2);
- }
- cnt += in_ie[cnt + 1] + 2; /*get next*/
- }
- /*restruct WPA IE or WPA2 IE in sec_ie[] */
- if (match) {
- if (sec_ie[0] == _WPA_IE_ID_) {
- /* parsing SSN IE to select required encryption
- * algorithm, and set the bc/mc encryption algorithm
- */
- while (true) {
- /*check wpa_oui tag*/
- if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) {
- match = false;
- break;
- }
- if ((sec_ie[6] != 0x01) || (sec_ie[7] != 0x0)) {
- /*IE Ver error*/
- match = false;
- break;
- }
- if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) {
- /* get bc/mc encryption type (group
- * key type)
- */
- switch (sec_ie[11]) {
- case 0x0: /*none*/
- psecuritypriv->XGrpPrivacy =
- _NO_PRIVACY_;
- break;
- case 0x1: /*WEP_40*/
- psecuritypriv->XGrpPrivacy =
- _WEP40_;
- break;
- case 0x2: /*TKIP*/
- psecuritypriv->XGrpPrivacy =
- _TKIP_;
- break;
- case 0x3: /*AESCCMP*/
- case 0x4:
- psecuritypriv->XGrpPrivacy =
- _AES_;
- break;
- case 0x5: /*WEP_104*/
- psecuritypriv->XGrpPrivacy =
- _WEP104_;
- break;
- }
- } else {
- match = false;
- break;
- }
- if (sec_ie[12] == 0x01) {
- /*check the unicast encryption type*/
- if (memcmp(&sec_ie[14],
- &uncst_oui[0], 4)) {
- match = false;
- break;
-
- } /*else the uncst_oui is match*/
- } else { /*mixed mode, unicast_enc_type > 1*/
- /*select the uncst_oui and remove
- * the other uncst_oui
- */
- cnt = sec_ie[12];
- remove_cnt = (cnt - 1) * 4;
- sec_ie[12] = 0x01;
- memcpy(&sec_ie[14], &uncst_oui[0], 4);
- /*remove the other unicast suit*/
- memcpy(&sec_ie[18],
- &sec_ie[18 + remove_cnt],
- sec_ie[1] - 18 + 2 -
- remove_cnt);
- sec_ie[1] = sec_ie[1] - remove_cnt;
- }
- break;
- }
- }
- if (authmode == _WPA2_IE_ID_) {
- /* parsing RSN IE to select required encryption
- * algorithm, and set the bc/mc encryption algorithm
- */
- while (true) {
- if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) {
- /*IE Ver error*/
- match = false;
- break;
- }
- if (!memcmp(&sec_ie[4], &uncst_oui[0], 3)) {
- /*get bc/mc encryption type*/
- switch (sec_ie[7]) {
- case 0x1: /*WEP_40*/
- psecuritypriv->XGrpPrivacy =
- _WEP40_;
- break;
- case 0x2: /*TKIP*/
- psecuritypriv->XGrpPrivacy =
- _TKIP_;
- break;
- case 0x4: /*AESWRAP*/
- psecuritypriv->XGrpPrivacy =
- _AES_;
- break;
- case 0x5: /*WEP_104*/
- psecuritypriv->XGrpPrivacy =
- _WEP104_;
- break;
- default: /*one*/
- psecuritypriv->XGrpPrivacy =
- _NO_PRIVACY_;
- break;
- }
- } else {
- match = false;
- break;
- }
- if (sec_ie[8] == 0x01) {
- /*check the unicast encryption type*/
- if (memcmp(&sec_ie[10],
- &uncst_oui[0], 4)) {
- match = false;
- break;
- } /*else the uncst_oui is match*/
- } else { /*mixed mode, unicast_enc_type > 1*/
- /*select the uncst_oui and remove the
- * other uncst_oui
- */
- cnt = sec_ie[8];
- remove_cnt = (cnt - 1) * 4;
- sec_ie[8] = 0x01;
- memcpy(&sec_ie[10], &uncst_oui[0], 4);
- /*remove the other unicast suit*/
- memcpy(&sec_ie[14],
- &sec_ie[14 + remove_cnt],
- (sec_ie[1] - 14 + 2 -
- remove_cnt));
- sec_ie[1] = sec_ie[1] - remove_cnt;
- }
- break;
- }
- }
- }
- if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
- /*copy fixed ie*/
- memcpy(out_ie, in_ie, 12);
- ielength = 12;
- /*copy RSN or SSN*/
- if (match) {
- memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1] + 2);
- ielength += sec_ie[1] + 2;
- if (authmode == _WPA2_IE_ID_) {
- /*the Pre-Authentication bit should be zero*/
- out_ie[ielength - 1] = 0;
- out_ie[ielength - 2] = 0;
- }
- r8712_report_sec_ie(adapter, authmode, sec_ie);
- }
- } else {
- /*copy fixed ie only*/
- memcpy(out_ie, in_ie, 12);
- ielength = 12;
- if (psecuritypriv->wps_phase) {
- memcpy(out_ie + ielength, psecuritypriv->wps_ie,
- psecuritypriv->wps_ie_len);
- ielength += psecuritypriv->wps_ie_len;
- }
- }
- iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
- if (iEntry < 0)
- return ielength;
- if (authmode == _WPA2_IE_ID_) {
- out_ie[ielength] = 1;
- ielength++;
- out_ie[ielength] = 0; /*PMKID count = 0x0100*/
- ielength++;
- memcpy(&out_ie[ielength],
- &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
- ielength += 16;
- out_ie[13] += 18;/*PMKID length = 2+16*/
- }
- return ielength;
-}
-
-void r8712_init_registrypriv_dev_network(struct _adapter *adapter)
-{
- struct registry_priv *pregistrypriv = &adapter->registrypriv;
- struct eeprom_priv *peepriv = &adapter->eeprompriv;
- struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
- u8 *myhwaddr = myid(peepriv);
-
- memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
- memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
- sizeof(struct ndis_802_11_ssid));
- pdev_network->Configuration.Length =
- sizeof(struct NDIS_802_11_CONFIGURATION);
- pdev_network->Configuration.BeaconPeriod = 100;
- pdev_network->Configuration.FHConfig.Length = 0;
- pdev_network->Configuration.FHConfig.HopPattern = 0;
- pdev_network->Configuration.FHConfig.HopSet = 0;
- pdev_network->Configuration.FHConfig.DwellTime = 0;
-}
-
-void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
-{
- int sz = 0;
- struct registry_priv *pregistrypriv = &adapter->registrypriv;
- struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
- struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
-
- pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
- > 0 ? 1 : 0); /* adhoc no 802.1x */
- pdev_network->Rssi = 0;
- switch (pregistrypriv->wireless_mode) {
- case WIRELESS_11B:
- pdev_network->NetworkTypeInUse = Ndis802_11DS;
- break;
- case WIRELESS_11G:
- case WIRELESS_11BG:
- pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
- break;
- case WIRELESS_11A:
- pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
- break;
- default:
- /* TODO */
- break;
- }
- pdev_network->Configuration.DSConfig = pregistrypriv->channel;
- if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
- pdev_network->Configuration.ATIMWindow = 3;
- pdev_network->InfrastructureMode = cur_network->network.InfrastructureMode;
- /* 1. Supported rates
- * 2. IE
- */
- sz = r8712_generate_ie(pregistrypriv);
- pdev_network->IELength = sz;
- pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network);
-}
-
-/*the function is at passive_level*/
-void r8712_joinbss_reset(struct _adapter *padapter)
-{
- int i;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-
- /* todo: if you want to do something io/reg/hw setting before join_bss,
- * please add code here
- */
- phtpriv->ampdu_enable = false;/*reset to disabled*/
- for (i = 0; i < 16; i++)
- phtpriv->baddbareq_issued[i] = false;/*reset it*/
- if (phtpriv->ht_option) {
- /* validate usb rx aggregation */
- r8712_write8(padapter, 0x102500D9, 48);/*TH = 48 pages, 6k*/
- } else {
- /* invalidate usb rx aggregation */
- /* TH=1 => means that invalidate usb rx aggregation */
- r8712_write8(padapter, 0x102500D9, 1);
- }
-}
-
-/*the function is >= passive_level*/
-unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
- u8 *out_ie, uint in_len, uint *pout_len)
-{
- u32 ielen, out_len;
- unsigned char *p;
- struct ieee80211_ht_cap ht_capie;
- unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-
- phtpriv->ht_option = 0;
- p = r8712_get_ie(in_ie + 12, WLAN_EID_HT_CAPABILITY, &ielen, in_len - 12);
- if (p && (ielen > 0)) {
- if (pqospriv->qos_option == 0) {
- out_len = *pout_len;
- r8712_set_ie(out_ie + out_len, WLAN_EID_VENDOR_SPECIFIC,
- _WMM_IE_Length_, WMM_IE, pout_len);
- pqospriv->qos_option = 1;
- }
- out_len = *pout_len;
- memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
- ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
- IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40 |
- IEEE80211_HT_CAP_TX_STBC |
- IEEE80211_HT_CAP_MAX_AMSDU |
- IEEE80211_HT_CAP_DSSSCCK40);
- ht_capie.ampdu_params_info = (IEEE80211_HT_AMPDU_PARM_FACTOR &
- 0x03) | (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
- r8712_set_ie(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
- sizeof(struct ieee80211_ht_cap),
- (unsigned char *)&ht_capie, pout_len);
- phtpriv->ht_option = 1;
- }
- return phtpriv->ht_option;
-}
-
-/* the function is > passive_level (in critical_section) */
-static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
-{
- u8 *p, max_ampdu_sz;
- int i;
- uint len;
- struct sta_info *bmc_sta, *psta;
- struct ieee80211_ht_cap *pht_capie;
- struct recv_reorder_ctrl *preorder_ctrl;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct wlan_network *pcur_network = &(pmlmepriv->cur_network);
-
- if (!phtpriv->ht_option)
- return;
- /* maybe needs check if ap supports rx ampdu. */
- if (!phtpriv->ampdu_enable &&
- (pregistrypriv->ampdu_enable == 1))
- phtpriv->ampdu_enable = true;
- /*check Max Rx A-MPDU Size*/
- len = 0;
- p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
- WLAN_EID_HT_CAPABILITY,
- &len, ie_len -
- sizeof(struct NDIS_802_11_FIXED_IEs));
- if (p && len > 0) {
- pht_capie = (struct ieee80211_ht_cap *)(p + 2);
- max_ampdu_sz = (pht_capie->ampdu_params_info &
- IEEE80211_HT_AMPDU_PARM_FACTOR);
- /* max_ampdu_sz (kbytes); */
- max_ampdu_sz = 1 << (max_ampdu_sz + 3);
- phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
- }
- /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
- * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl
- * wstart_b(indicate_seq) to default value=0xffff
- * todo: check if AP can send A-MPDU packets
- */
- bmc_sta = r8712_get_bcmc_stainfo(padapter);
- if (bmc_sta) {
- for (i = 0; i < 16; i++) {
- preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
- preorder_ctrl->indicate_seq = 0xffff;
- preorder_ctrl->wend_b = 0xffff;
- }
- }
- psta = r8712_get_stainfo(&padapter->stapriv,
- pcur_network->network.MacAddress);
- if (psta) {
- for (i = 0; i < 16; i++) {
- preorder_ctrl = &psta->recvreorder_ctrl[i];
- preorder_ctrl->indicate_seq = 0xffff;
- preorder_ctrl->wend_b = 0xffff;
- }
- }
- len = 0;
- p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
- WLAN_EID_HT_OPERATION, &len,
- ie_len - sizeof(struct NDIS_802_11_FIXED_IEs));
-}
-
-void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-
- if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable)) {
- if (!phtpriv->baddbareq_issued[priority]) {
- r8712_addbareq_cmd(padapter, (u8)priority);
- phtpriv->baddbareq_issued[priority] = true;
- }
- }
-}
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h
deleted file mode 100644
index d7d25f240111..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mlme.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_MLME_H_
-#define __RTL871X_MLME_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "wlan_bssdef.h"
-
-#define MAX_BSS_CNT 64
-#define MAX_JOIN_TIMEOUT 6000
-
-#define SCANNING_TIMEOUT 4500
-
-#define SCANQUEUE_LIFETIME 20 /* unit:sec */
-
-#define WIFI_NULL_STATE 0x00000000
-#define WIFI_ASOC_STATE 0x00000001 /* Under Linked state...*/
-#define WIFI_REASOC_STATE 0x00000002
-#define WIFI_SLEEP_STATE 0x00000004
-#define WIFI_STATION_STATE 0x00000008
-#define WIFI_AP_STATE 0x00000010
-#define WIFI_ADHOC_STATE 0x00000020
-#define WIFI_ADHOC_MASTER_STATE 0x00000040
-#define WIFI_UNDER_LINKING 0x00000080
-#define WIFI_SITE_MONITOR 0x00000800 /* to indicate the station
- * is under site surveying
- */
-#define WIFI_MP_STATE 0x00010000
-#define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in cont. tx background*/
-#define WIFI_MP_CTX_ST 0x00040000 /* in cont. tx with
- * single-tone
- */
-#define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in cont, tx
- * background due
- * to out of skb
- */
-#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continuous tx*/
-#define WIFI_MP_CTX_CCK_CS 0x00200000 /* in cont, tx with carrier
- * suppression
- */
-#define WIFI_MP_LPBK_STATE 0x00400000
-
-#define _FW_UNDER_LINKING WIFI_UNDER_LINKING
-#define _FW_LINKED WIFI_ASOC_STATE
-#define _FW_UNDER_SURVEY WIFI_SITE_MONITOR
-
-/*
- * there are several "locks" in mlme_priv,
- * since mlme_priv is a shared resource between many threads,
- * like ISR/Call-Back functions, the OID handlers, and even timer functions.
- * Each _queue has its own locks, already.
- * Other items are protected by mlme_priv.lock.
- * To avoid possible dead lock, any thread trying to modify mlme_priv
- * SHALL not lock up more than one lock at a time!
- */
-
-#define traffic_threshold 10
-#define traffic_scan_period 500
-
-struct sitesurvey_ctrl {
- u64 last_tx_pkts;
- uint last_rx_pkts;
- sint traffic_busy;
- struct timer_list sitesurvey_ctrl_timer;
-};
-
-struct mlme_priv {
- spinlock_t lock;
- spinlock_t lock2;
- sint fw_state; /*shall we protect this variable? */
- u8 to_join; /*flag*/
- u8 *nic_hdl;
- struct list_head *pscanned;
- struct __queue free_bss_pool;
- struct __queue scanned_queue;
- u8 *free_bss_buf;
- unsigned long num_of_scanned;
- u8 passive_mode; /*add for Android's SCAN-ACTIVE/SCAN-PASSIVE */
- struct ndis_802_11_ssid assoc_ssid;
- u8 assoc_bssid[6];
- struct wlan_network cur_network;
- struct sitesurvey_ctrl sitesurveyctrl;
- struct timer_list assoc_timer;
- uint assoc_by_bssid;
- uint assoc_by_rssi;
- struct timer_list scan_to_timer; /* driver handles scan_timeout.*/
- struct timer_list dhcp_timer; /* set dhcp to if driver in ps mode.*/
- struct qos_priv qospriv;
- struct ht_priv htpriv;
- struct timer_list wdg_timer; /*watchdog periodic timer*/
-};
-
-static inline u8 *get_bssid(struct mlme_priv *pmlmepriv)
-{
- return pmlmepriv->cur_network.network.MacAddress;
-}
-
-static inline u8 check_fwstate(struct mlme_priv *pmlmepriv, sint state)
-{
- if (pmlmepriv->fw_state & state)
- return true;
- return false;
-}
-
-static inline sint get_fwstate(struct mlme_priv *pmlmepriv)
-{
- return pmlmepriv->fw_state;
-}
-
-/*
- * No Limit on the calling context,
- * therefore set it to be the critical section...
- *
- * ### NOTE:#### (!!!!)
- * TAKE CARE BEFORE CALLING THIS FUNC, LOCK pmlmepriv->lock
- */
-static inline void set_fwstate(struct mlme_priv *pmlmepriv, sint state)
-{
- pmlmepriv->fw_state |= state;
-}
-
-static inline void _clr_fwstate_(struct mlme_priv *pmlmepriv, sint state)
-{
- pmlmepriv->fw_state &= ~state;
-}
-
-/*
- * No Limit on the calling context,
- * therefore set it to be the critical section...
- */
-static inline void clr_fwstate(struct mlme_priv *pmlmepriv, sint state)
-{
- unsigned long irqL;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, state))
- pmlmepriv->fw_state ^= state;
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-static inline void set_scanned_network_val(struct mlme_priv *pmlmepriv,
- sint val)
-{
- unsigned long irqL;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- pmlmepriv->num_of_scanned = val;
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_free_network_queue(struct _adapter *adapter);
-int r8712_init_mlme_priv(struct _adapter *adapter);
-void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv);
-int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv);
-int r8712_set_key(struct _adapter *adapter,
- struct security_priv *psecuritypriv, sint keyid);
-int r8712_set_auth(struct _adapter *adapter,
- struct security_priv *psecuritypriv);
-uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss);
-void r8712_generate_random_ibss(u8 *pibss);
-u8 *r8712_get_capability_from_ie(u8 *ie);
-struct wlan_network *r8712_get_oldest_wlan_network(
- struct __queue *scanned_queue);
-void r8712_free_assoc_resources(struct _adapter *adapter);
-void r8712_ind_disconnect(struct _adapter *adapter);
-void r8712_indicate_connect(struct _adapter *adapter);
-int r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
- u8 *out_ie, uint in_len);
-int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie,
- u8 *out_ie, uint in_len, uint initial_out_len);
-void r8712_init_registrypriv_dev_network(struct _adapter *adapter);
-void r8712_update_registrypriv_dev_network(struct _adapter *adapter);
-void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter);
-void _r8712_join_timeout_handler(struct _adapter *adapter);
-void r8712_scan_timeout_handler(struct _adapter *adapter);
-void _r8712_dhcp_timeout_handler(struct _adapter *adapter);
-struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv);
-sint r8712_if_up(struct _adapter *padapter);
-void r8712_joinbss_reset(struct _adapter *padapter);
-unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
- u8 *out_ie, uint in_len, uint *pout_len);
-void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority);
-int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork);
-
-#endif /*__RTL871X_MLME_H_*/
diff --git a/drivers/staging/rtl8712/rtl871x_mp.c b/drivers/staging/rtl8712/rtl871x_mp.c
deleted file mode 100644
index 099c512c8519..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mp.c
+++ /dev/null
@@ -1,724 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#define _RTL871X_MP_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "rtl871x_mp_phy_regdef.h"
-#include "rtl8712_cmd.h"
-
-static void _init_mp_priv_(struct mp_priv *pmp_priv)
-{
- pmp_priv->mode = _LOOPBOOK_MODE_;
- pmp_priv->curr_ch = 1;
- pmp_priv->curr_modem = MIXED_PHY;
- pmp_priv->curr_rateidx = 0;
- pmp_priv->curr_txpoweridx = 0x14;
- pmp_priv->antenna_tx = ANTENNA_A;
- pmp_priv->antenna_rx = ANTENNA_AB;
- pmp_priv->check_mp_pkt = 0;
- pmp_priv->tx_pktcount = 0;
- pmp_priv->rx_pktcount = 0;
- pmp_priv->rx_crcerrpktcount = 0;
-}
-
-static int init_mp_priv(struct mp_priv *pmp_priv)
-{
- int i;
- struct mp_xmit_frame *pmp_xmitframe;
-
- _init_mp_priv_(pmp_priv);
- _init_queue(&pmp_priv->free_mp_xmitqueue);
- pmp_priv->pallocated_mp_xmitframe_buf = NULL;
- pmp_priv->pallocated_mp_xmitframe_buf = kmalloc(NR_MP_XMITFRAME *
- sizeof(struct mp_xmit_frame) + 4,
- GFP_ATOMIC);
- if (!pmp_priv->pallocated_mp_xmitframe_buf)
- return -ENOMEM;
-
- pmp_priv->pmp_xmtframe_buf = pmp_priv->pallocated_mp_xmitframe_buf +
- 4 -
- ((addr_t)(pmp_priv->pallocated_mp_xmitframe_buf) & 3);
- pmp_xmitframe = (struct mp_xmit_frame *)pmp_priv->pmp_xmtframe_buf;
- for (i = 0; i < NR_MP_XMITFRAME; i++) {
- INIT_LIST_HEAD(&(pmp_xmitframe->list));
- list_add_tail(&(pmp_xmitframe->list),
- &(pmp_priv->free_mp_xmitqueue.queue));
- pmp_xmitframe->pkt = NULL;
- pmp_xmitframe->frame_tag = MP_FRAMETAG;
- pmp_xmitframe->padapter = pmp_priv->papdater;
- pmp_xmitframe++;
- }
- pmp_priv->free_mp_xmitframe_cnt = NR_MP_XMITFRAME;
- return 0;
-}
-
-static int free_mp_priv(struct mp_priv *pmp_priv)
-{
- kfree(pmp_priv->pallocated_mp_xmitframe_buf);
- return 0;
-}
-
-void mp871xinit(struct _adapter *padapter)
-{
- struct mp_priv *pmppriv = &padapter->mppriv;
-
- pmppriv->papdater = padapter;
- init_mp_priv(pmppriv);
-}
-
-void mp871xdeinit(struct _adapter *padapter)
-{
- struct mp_priv *pmppriv = &padapter->mppriv;
-
- free_mp_priv(pmppriv);
-}
-
-/*
- * Special for bb and rf reg read/write
- */
-static u32 fw_iocmd_read(struct _adapter *pAdapter, struct IOCMD_STRUCT iocmd)
-{
- u32 cmd32 = 0, val32 = 0;
- u8 iocmd_class = iocmd.cmdclass;
- u16 iocmd_value = iocmd.value;
- u8 iocmd_idx = iocmd.index;
-
- cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx;
- if (r8712_fw_cmd(pAdapter, cmd32))
- r8712_fw_cmd_data(pAdapter, &val32, 1);
- else
- val32 = 0;
- return val32;
-}
-
-static u8 fw_iocmd_write(struct _adapter *pAdapter,
- struct IOCMD_STRUCT iocmd, u32 value)
-{
- u32 cmd32 = 0;
- u8 iocmd_class = iocmd.cmdclass;
- u32 iocmd_value = iocmd.value;
- u8 iocmd_idx = iocmd.index;
-
- r8712_fw_cmd_data(pAdapter, &value, 0);
- msleep(100);
- cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx;
- return r8712_fw_cmd(pAdapter, cmd32);
-}
-
-/* offset : 0X800~0XFFF */
-u32 r8712_bb_reg_read(struct _adapter *pAdapter, u16 offset)
-{
- u8 shift = offset & 0x0003; /* 4 byte access */
- u16 bb_addr = offset & 0x0FFC; /* 4 byte access */
- u32 bb_val = 0;
- struct IOCMD_STRUCT iocmd;
-
- iocmd.cmdclass = IOCMD_CLASS_BB_RF;
- iocmd.value = bb_addr;
- iocmd.index = IOCMD_BB_READ_IDX;
- bb_val = fw_iocmd_read(pAdapter, iocmd);
- if (shift != 0) {
- u32 bb_val2 = 0;
-
- bb_val >>= (shift * 8);
- iocmd.value += 4;
- bb_val2 = fw_iocmd_read(pAdapter, iocmd);
- bb_val2 <<= ((4 - shift) * 8);
- bb_val |= bb_val2;
- }
- return bb_val;
-}
-
-/* offset : 0X800~0XFFF */
-u8 r8712_bb_reg_write(struct _adapter *pAdapter, u16 offset, u32 value)
-{
- u8 shift = offset & 0x0003; /* 4 byte access */
- u16 bb_addr = offset & 0x0FFC; /* 4 byte access */
- struct IOCMD_STRUCT iocmd;
-
- iocmd.cmdclass = IOCMD_CLASS_BB_RF;
- iocmd.value = bb_addr;
- iocmd.index = IOCMD_BB_WRITE_IDX;
- if (shift != 0) {
- u32 oldValue = 0;
- u32 newValue = value;
-
- oldValue = r8712_bb_reg_read(pAdapter, iocmd.value);
- oldValue &= (0xFFFFFFFF >> ((4 - shift) * 8));
- value = oldValue | (newValue << (shift * 8));
- if (!fw_iocmd_write(pAdapter, iocmd, value))
- return false;
- iocmd.value += 4;
- oldValue = r8712_bb_reg_read(pAdapter, iocmd.value);
- oldValue &= (0xFFFFFFFF << (shift * 8));
- value = oldValue | (newValue >> ((4 - shift) * 8));
- }
- return fw_iocmd_write(pAdapter, iocmd, value);
-}
-
-/* offset : 0x00 ~ 0xFF */
-u32 r8712_rf_reg_read(struct _adapter *pAdapter, u8 path, u8 offset)
-{
- u16 rf_addr = (path << 8) | offset;
- struct IOCMD_STRUCT iocmd;
-
- iocmd.cmdclass = IOCMD_CLASS_BB_RF;
- iocmd.value = rf_addr;
- iocmd.index = IOCMD_RF_READ_IDX;
- return fw_iocmd_read(pAdapter, iocmd);
-}
-
-u8 r8712_rf_reg_write(struct _adapter *pAdapter, u8 path, u8 offset, u32 value)
-{
- u16 rf_addr = (path << 8) | offset;
- struct IOCMD_STRUCT iocmd;
-
- iocmd.cmdclass = IOCMD_CLASS_BB_RF;
- iocmd.value = rf_addr;
- iocmd.index = IOCMD_RF_WRIT_IDX;
- return fw_iocmd_write(pAdapter, iocmd, value);
-}
-
-static u32 bitshift(u32 bitmask)
-{
- u32 i;
-
- for (i = 0; i <= 31; i++)
- if (((bitmask >> i) & 0x1) == 1)
- break;
- return i;
-}
-
-static u32 get_bb_reg(struct _adapter *pAdapter, u16 offset, u32 bitmask)
-{
- u32 org_value, bit_shift;
-
- org_value = r8712_bb_reg_read(pAdapter, offset);
- bit_shift = bitshift(bitmask);
- return (org_value & bitmask) >> bit_shift;
-}
-
-static u8 set_bb_reg(struct _adapter *pAdapter,
- u16 offset,
- u32 bitmask,
- u32 value)
-{
- u32 org_value, bit_shift, new_value;
-
- if (bitmask != bMaskDWord) {
- org_value = r8712_bb_reg_read(pAdapter, offset);
- bit_shift = bitshift(bitmask);
- new_value = (org_value & (~bitmask)) | (value << bit_shift);
- } else {
- new_value = value;
- }
- return r8712_bb_reg_write(pAdapter, offset, new_value);
-}
-
-static u32 get_rf_reg(struct _adapter *pAdapter, u8 path, u8 offset,
- u32 bitmask)
-{
- u32 org_value, bit_shift;
-
- org_value = r8712_rf_reg_read(pAdapter, path, offset);
- bit_shift = bitshift(bitmask);
- return (org_value & bitmask) >> bit_shift;
-}
-
-static u8 set_rf_reg(struct _adapter *pAdapter, u8 path, u8 offset, u32 bitmask,
- u32 value)
-{
- u32 org_value, bit_shift, new_value;
-
- if (bitmask != bMaskDWord) {
- org_value = r8712_rf_reg_read(pAdapter, path, offset);
- bit_shift = bitshift(bitmask);
- new_value = (org_value & (~bitmask)) | (value << bit_shift);
- } else {
- new_value = value;
- }
- return r8712_rf_reg_write(pAdapter, path, offset, new_value);
-}
-
-/*
- * SetChannel
- * Description
- * Use H2C command to change channel,
- * not only modify rf register, but also other setting need to be done.
- */
-void r8712_SetChannel(struct _adapter *pAdapter)
-{
- struct cmd_priv *pcmdpriv = &pAdapter->cmdpriv;
- struct cmd_obj *pcmd = NULL;
- struct SetChannel_parm *pparm = NULL;
- u16 code = GEN_CMD_CODE(_SetChannel);
-
- pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
- if (!pcmd)
- return;
- pparm = kmalloc(sizeof(*pparm), GFP_ATOMIC);
- if (!pparm) {
- kfree(pcmd);
- return;
- }
- pparm->curr_ch = pAdapter->mppriv.curr_ch;
- init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code);
- r8712_enqueue_cmd(pcmdpriv, pcmd);
-}
-
-static void SetCCKTxPower(struct _adapter *pAdapter, u8 TxPower)
-{
- u16 TxAGC = 0;
-
- TxAGC = TxPower;
- set_bb_reg(pAdapter, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
-}
-
-static void SetOFDMTxPower(struct _adapter *pAdapter, u8 TxPower)
-{
- u32 TxAGC = 0;
-
- TxAGC |= ((TxPower << 24) | (TxPower << 16) | (TxPower << 8) |
- TxPower);
- set_bb_reg(pAdapter, rTxAGC_Rate18_06, bTxAGCRate18_06, TxAGC);
- set_bb_reg(pAdapter, rTxAGC_Rate54_24, bTxAGCRate54_24, TxAGC);
- set_bb_reg(pAdapter, rTxAGC_Mcs03_Mcs00, bTxAGCRateMCS3_MCS0, TxAGC);
- set_bb_reg(pAdapter, rTxAGC_Mcs07_Mcs04, bTxAGCRateMCS7_MCS4, TxAGC);
- set_bb_reg(pAdapter, rTxAGC_Mcs11_Mcs08, bTxAGCRateMCS11_MCS8, TxAGC);
- set_bb_reg(pAdapter, rTxAGC_Mcs15_Mcs12, bTxAGCRateMCS15_MCS12, TxAGC);
-}
-
-void r8712_SetTxPower(struct _adapter *pAdapter)
-{
- u8 TxPower = pAdapter->mppriv.curr_txpoweridx;
-
- SetCCKTxPower(pAdapter, TxPower);
- SetOFDMTxPower(pAdapter, TxPower);
-}
-
-void r8712_SetTxAGCOffset(struct _adapter *pAdapter, u32 ulTxAGCOffset)
-{
- u32 TxAGCOffset_B, TxAGCOffset_C, TxAGCOffset_D, tmpAGC;
-
- TxAGCOffset_B = ulTxAGCOffset & 0x000000ff;
- TxAGCOffset_C = (ulTxAGCOffset & 0x0000ff00) >> 8;
- TxAGCOffset_D = (ulTxAGCOffset & 0x00ff0000) >> 16;
- tmpAGC = TxAGCOffset_D << 8 | TxAGCOffset_C << 4 | TxAGCOffset_B;
- set_bb_reg(pAdapter, rFPGA0_TxGainStage,
- (bXBTxAGC | bXCTxAGC | bXDTxAGC), tmpAGC);
-}
-
-void r8712_SetDataRate(struct _adapter *pAdapter)
-{
- u8 path = RF_PATH_A;
- u8 offset = RF_SYN_G2;
- u32 value;
-
- value = (pAdapter->mppriv.curr_rateidx < 4) ? 0x4440 : 0xF200;
- r8712_rf_reg_write(pAdapter, path, offset, value);
-}
-
-void r8712_SwitchBandwidth(struct _adapter *pAdapter)
-{
- /* 3 1.Set MAC register : BWOPMODE bit2:1 20MhzBW */
- u8 regBwOpMode = 0;
- u8 Bandwidth = pAdapter->mppriv.curr_bandwidth;
-
- regBwOpMode = r8712_read8(pAdapter, 0x10250203);
- if (Bandwidth == HT_CHANNEL_WIDTH_20)
- regBwOpMode |= BIT(2);
- else
- regBwOpMode &= ~(BIT(2));
- r8712_write8(pAdapter, 0x10250203, regBwOpMode);
- /* 3 2.Set PHY related register */
- switch (Bandwidth) {
- /* 20 MHz channel*/
- case HT_CHANNEL_WIDTH_20:
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bRFMOD, 0x0);
- set_bb_reg(pAdapter, rFPGA1_RFMOD, bRFMOD, 0x0);
- /* Use PHY_REG.txt default value. Do not need to change.
- * Correct the tx power for CCK rate in 40M.
- * It is set in Tx descriptor for 8192x series
- */
- set_bb_reg(pAdapter, rFPGA0_AnalogParameter2, bMaskDWord, 0x58);
- break;
- /* 40 MHz channel*/
- case HT_CHANNEL_WIDTH_40:
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bRFMOD, 0x1);
- set_bb_reg(pAdapter, rFPGA1_RFMOD, bRFMOD, 0x1);
- /* Use PHY_REG.txt default value. Do not need to change.
- * Correct the tx power for CCK rate in 40M.
- * Set Control channel to upper or lower. These settings are
- * required only for 40MHz
- */
- set_bb_reg(pAdapter, rCCK0_System, bCCKSideBand,
- (HAL_PRIME_CHNL_OFFSET_DONT_CARE >> 1));
- set_bb_reg(pAdapter, rOFDM1_LSTF, 0xC00,
- HAL_PRIME_CHNL_OFFSET_DONT_CARE);
- set_bb_reg(pAdapter, rFPGA0_AnalogParameter2, bMaskDWord, 0x18);
- break;
- default:
- break;
- }
-
- /* 3 3.Set RF related register */
- switch (Bandwidth) {
- case HT_CHANNEL_WIDTH_20:
- set_rf_reg(pAdapter, RF_PATH_A, RF_CHNLBW,
- BIT(10) | BIT(11), 0x01);
- break;
- case HT_CHANNEL_WIDTH_40:
- set_rf_reg(pAdapter, RF_PATH_A, RF_CHNLBW,
- BIT(10) | BIT(11), 0x00);
- break;
- default:
- break;
- }
-}
-
-/*------------------------------Define structure----------------------------*/
-struct R_ANTENNA_SELECT_OFDM {
- u32 r_tx_antenna:4;
- u32 r_ant_l:4;
- u32 r_ant_non_ht:4;
- u32 r_ant_ht1:4;
- u32 r_ant_ht2:4;
- u32 r_ant_ht_s1:4;
- u32 r_ant_non_ht_s1:4;
- u32 OFDM_TXSC:2;
- u32 Reserved:2;
-};
-
-struct R_ANTENNA_SELECT_CCK {
- u8 r_cckrx_enable_2:2;
- u8 r_cckrx_enable:2;
- u8 r_ccktx_enable:4;
-};
-
-void r8712_SwitchAntenna(struct _adapter *pAdapter)
-{
- u32 ofdm_tx_en_val = 0, ofdm_tx_ant_sel_val = 0;
- u8 ofdm_rx_ant_sel_val = 0;
- u8 cck_ant_select_val = 0;
- u32 cck_ant_sel_val = 0;
- struct R_ANTENNA_SELECT_CCK *p_cck_txrx;
-
- p_cck_txrx = (struct R_ANTENNA_SELECT_CCK *)&cck_ant_select_val;
-
- switch (pAdapter->mppriv.antenna_tx) {
- case ANTENNA_A:
- /* From SD3 Willis suggestion !!! Set RF A=TX and B as standby*/
- set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2);
- set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 1);
- ofdm_tx_en_val = 0x3;
- ofdm_tx_ant_sel_val = 0x11111111;/* Power save */
- p_cck_txrx->r_ccktx_enable = 0x8;
- break;
- case ANTENNA_B:
- set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 1);
- set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2);
- ofdm_tx_en_val = 0x3;
- ofdm_tx_ant_sel_val = 0x22222222;/* Power save */
- p_cck_txrx->r_ccktx_enable = 0x4;
- break;
- case ANTENNA_AB: /* For 8192S */
- set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2);
- set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2);
- ofdm_tx_en_val = 0x3;
- ofdm_tx_ant_sel_val = 0x3321333; /* Disable Power save */
- p_cck_txrx->r_ccktx_enable = 0xC;
- break;
- default:
- break;
- }
- /*OFDM Tx*/
- set_bb_reg(pAdapter, rFPGA1_TxInfo, 0xffffffff, ofdm_tx_ant_sel_val);
- /*OFDM Tx*/
- set_bb_reg(pAdapter, rFPGA0_TxInfo, 0x0000000f, ofdm_tx_en_val);
- switch (pAdapter->mppriv.antenna_rx) {
- case ANTENNA_A:
- ofdm_rx_ant_sel_val = 0x1; /* A */
- p_cck_txrx->r_cckrx_enable = 0x0; /* default: A */
- p_cck_txrx->r_cckrx_enable_2 = 0x0; /* option: A */
- break;
- case ANTENNA_B:
- ofdm_rx_ant_sel_val = 0x2; /* B */
- p_cck_txrx->r_cckrx_enable = 0x1; /* default: B */
- p_cck_txrx->r_cckrx_enable_2 = 0x1; /* option: B */
- break;
- case ANTENNA_AB:
- ofdm_rx_ant_sel_val = 0x3; /* AB */
- p_cck_txrx->r_cckrx_enable = 0x0; /* default:A */
- p_cck_txrx->r_cckrx_enable_2 = 0x1; /* option:B */
- break;
- default:
- break;
- }
- /*OFDM Rx*/
- set_bb_reg(pAdapter, rOFDM0_TRxPathEnable, 0x0000000f,
- ofdm_rx_ant_sel_val);
- /*OFDM Rx*/
- set_bb_reg(pAdapter, rOFDM1_TRxPathEnable, 0x0000000f,
- ofdm_rx_ant_sel_val);
-
- cck_ant_sel_val = cck_ant_select_val;
- /*CCK TxRx*/
- set_bb_reg(pAdapter, rCCK0_AFESetting, bMaskByte3, cck_ant_sel_val);
-}
-
-static void TriggerRFThermalMeter(struct _adapter *pAdapter)
-{
- /* 0x24: RF Reg[6:5] */
- set_rf_reg(pAdapter, RF_PATH_A, RF_T_METER, bRFRegOffsetMask, 0x60);
-}
-
-static u32 ReadRFThermalMeter(struct _adapter *pAdapter)
-{
- /* 0x24: RF Reg[4:0] */
- return get_rf_reg(pAdapter, RF_PATH_A, RF_T_METER, 0x1F);
-}
-
-void r8712_GetThermalMeter(struct _adapter *pAdapter, u32 *value)
-{
- TriggerRFThermalMeter(pAdapter);
- msleep(1000);
- *value = ReadRFThermalMeter(pAdapter);
-}
-
-void r8712_SetSingleCarrierTx(struct _adapter *pAdapter, u8 bStart)
-{
- if (bStart) { /* Start Single Carrier. */
- /* 1. if OFDM block on? */
- if (!get_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn))
- /*set OFDM block on*/
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable);
- /* 2. set CCK test mode off, set to CCK normal mode */
- set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, bDisable);
- /* 3. turn on scramble setting */
- set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
- /* 4. Turn On Single Carrier Tx and off the other test modes. */
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bEnable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
- } else { /* Stop Single Carrier.*/
- /* Turn off all test modes.*/
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier,
- bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
- msleep(20);
- /*BB Reset*/
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
- }
-}
-
-void r8712_SetSingleToneTx(struct _adapter *pAdapter, u8 bStart)
-{
- u8 rfPath;
-
- switch (pAdapter->mppriv.antenna_tx) {
- case ANTENNA_B:
- rfPath = RF_PATH_B;
- break;
- case ANTENNA_A:
- default:
- rfPath = RF_PATH_A;
- break;
- }
- if (bStart) { /* Start Single Tone.*/
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, bDisable);
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bDisable);
- set_rf_reg(pAdapter, rfPath, RF_TX_G2, bRFRegOffsetMask,
- 0xd4000);
- msleep(100);
- /* PAD all on.*/
- set_rf_reg(pAdapter, rfPath, RF_AC, bRFRegOffsetMask, 0x2001f);
- msleep(100);
- } else { /* Stop Single Tone.*/
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable);
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable);
- set_rf_reg(pAdapter, rfPath, RF_TX_G2, bRFRegOffsetMask,
- 0x54000);
- msleep(100);
- /* PAD all on.*/
- set_rf_reg(pAdapter, rfPath, RF_AC, bRFRegOffsetMask, 0x30000);
- msleep(100);
- }
-}
-
-void r8712_SetCarrierSuppressionTx(struct _adapter *pAdapter, u8 bStart)
-{
- if (bStart) { /* Start Carrier Suppression.*/
- if (pAdapter->mppriv.curr_rateidx <= MPT_RATE_11M) {
- /* 1. if CCK block on? */
- if (!get_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn)) {
- /*set CCK block on*/
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn,
- bEnable);
- }
- /* Turn Off All Test Mode */
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx,
- bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier,
- bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone,
- bDisable);
- /*transmit mode*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x2);
- /*turn off scramble setting*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKScramble,
- bDisable);
- /*Set CCK Tx Test Rate*/
- /*Set FTxRate to 1Mbps*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKTxRate, 0x0);
- }
- } else { /* Stop Carrier Suppression. */
- if (pAdapter->mppriv.curr_rateidx <= MPT_RATE_11M) {
- /*normal mode*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x0);
- /*turn on scramble setting*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKScramble,
- bEnable);
- /*BB Reset*/
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
- }
- }
-}
-
-static void SetCCKContinuousTx(struct _adapter *pAdapter, u8 bStart)
-{
- u32 cckrate;
-
- if (bStart) {
- /* 1. if CCK block on? */
- if (!get_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn)) {
- /*set CCK block on*/
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable);
- }
- /* Turn Off All Test Mode */
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
- /*Set CCK Tx Test Rate*/
- cckrate = pAdapter->mppriv.curr_rateidx;
- set_bb_reg(pAdapter, rCCK0_System, bCCKTxRate, cckrate);
- /*transmit mode*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x2);
- /*turn on scramble setting*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
- } else {
- /*normal mode*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x0);
- /*turn on scramble setting*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
- /*BB Reset*/
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
- }
-} /* mpt_StartCckContTx */
-
-static void SetOFDMContinuousTx(struct _adapter *pAdapter, u8 bStart)
-{
- if (bStart) {
- /* 1. if OFDM block on? */
- if (!get_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn)) {
- /*set OFDM block on*/
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable);
- }
- /* 2. set CCK test mode off, set to CCK normal mode*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, bDisable);
- /* 3. turn on scramble setting */
- set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
- /* 4. Turn On Continue Tx and turn off the other test modes.*/
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bEnable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
- } else {
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier,
- bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
- msleep(20);
- /*BB Reset*/
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
- }
-} /* mpt_StartOfdmContTx */
-
-void r8712_SetContinuousTx(struct _adapter *pAdapter, u8 bStart)
-{
- /* ADC turn off [bit24-21] adc port0 ~ port1 */
- if (bStart) {
- r8712_bb_reg_write(pAdapter, rRx_Wait_CCCA,
- r8712_bb_reg_read(pAdapter,
- rRx_Wait_CCCA) & 0xFE1FFFFF);
- msleep(100);
- }
- if (pAdapter->mppriv.curr_rateidx <= MPT_RATE_11M)
- SetCCKContinuousTx(pAdapter, bStart);
- else if ((pAdapter->mppriv.curr_rateidx >= MPT_RATE_6M) &&
- (pAdapter->mppriv.curr_rateidx <= MPT_RATE_MCS15))
- SetOFDMContinuousTx(pAdapter, bStart);
- /* ADC turn on [bit24-21] adc port0 ~ port1 */
- if (!bStart)
- r8712_bb_reg_write(pAdapter, rRx_Wait_CCCA,
- r8712_bb_reg_read(pAdapter,
- rRx_Wait_CCCA) | 0x01E00000);
-}
-
-void r8712_ResetPhyRxPktCount(struct _adapter *pAdapter)
-{
- u32 i, phyrx_set = 0;
-
- for (i = OFDM_PPDU_BIT; i <= HT_MPDU_FAIL_BIT; i++) {
- phyrx_set = 0;
- phyrx_set |= (i << 28); /*select*/
- phyrx_set |= 0x08000000; /* set counter to zero*/
- r8712_write32(pAdapter, RXERR_RPT, phyrx_set);
- }
-}
-
-static u32 GetPhyRxPktCounts(struct _adapter *pAdapter, u32 selbit)
-{
- /*selection*/
- u32 phyrx_set = 0;
- u32 SelectBit;
-
- SelectBit = selbit << 28;
- phyrx_set |= (SelectBit & 0xF0000000);
- r8712_write32(pAdapter, RXERR_RPT, phyrx_set);
- /*Read packet count*/
- return r8712_read32(pAdapter, RXERR_RPT) & RPTMaxCount;
-}
-
-u32 r8712_GetPhyRxPktReceived(struct _adapter *pAdapter)
-{
- u32 OFDM_cnt = GetPhyRxPktCounts(pAdapter, OFDM_MPDU_OK_BIT);
- u32 CCK_cnt = GetPhyRxPktCounts(pAdapter, CCK_MPDU_OK_BIT);
- u32 HT_cnt = GetPhyRxPktCounts(pAdapter, HT_MPDU_OK_BIT);
-
- return OFDM_cnt + CCK_cnt + HT_cnt;
-}
-
-u32 r8712_GetPhyRxPktCRC32Error(struct _adapter *pAdapter)
-{
- u32 OFDM_cnt = GetPhyRxPktCounts(pAdapter, OFDM_MPDU_FAIL_BIT);
- u32 CCK_cnt = GetPhyRxPktCounts(pAdapter, CCK_MPDU_FAIL_BIT);
- u32 HT_cnt = GetPhyRxPktCounts(pAdapter, HT_MPDU_FAIL_BIT);
-
- return OFDM_cnt + CCK_cnt + HT_cnt;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_mp.h b/drivers/staging/rtl8712/rtl871x_mp.h
deleted file mode 100644
index 0a60b1e6ccaf..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mp.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_MP_H_
-#define __RTL871X_MP_H_
-
-#define MPT_NOOP 0
-#define MPT_READ_MAC_1BYTE 1
-#define MPT_READ_MAC_2BYTE 2
-#define MPT_READ_MAC_4BYTE 3
-#define MPT_WRITE_MAC_1BYTE 4
-#define MPT_WRITE_MAC_2BYTE 5
-#define MPT_WRITE_MAC_4BYTE 6
-#define MPT_READ_BB_CCK 7
-#define MPT_WRITE_BB_CCK 8
-#define MPT_READ_BB_OFDM 9
-#define MPT_WRITE_BB_OFDM 10
-#define MPT_READ_RF 11
-#define MPT_WRITE_RF 12
-#define MPT_READ_EEPROM_1BYTE 13
-#define MPT_WRITE_EEPROM_1BYTE 14
-#define MPT_READ_EEPROM_2BYTE 15
-#define MPT_WRITE_EEPROM_2BYTE 16
-#define MPT_SET_CSTHRESHOLD 21
-#define MPT_SET_INITGAIN 22
-#define MPT_SWITCH_BAND 23
-#define MPT_SWITCH_CHANNEL 24
-#define MPT_SET_DATARATE 25
-#define MPT_SWITCH_ANTENNA 26
-#define MPT_SET_TX_POWER 27
-#define MPT_SET_CONT_TX 28
-#define MPT_SET_SINGLE_CARRIER 29
-#define MPT_SET_CARRIER_SUPPRESSION 30
-#define MPT_GET_RATE_TABLE 31
-#define MPT_READ_TSSI 32
-#define MPT_GET_THERMAL_METER 33
-#define MAX_MP_XMITBUF_SZ 2048
-#define NR_MP_XMITFRAME 8
-
-struct mp_xmit_frame {
- struct list_head list;
- struct pkt_attrib attrib;
- _pkt *pkt;
- int frame_tag;
- struct _adapter *padapter;
- u8 *mem_addr;
- u16 sz[8];
- struct urb *pxmit_urb[8];
- u8 bpending[8];
- u8 last[8];
-};
-
-struct mp_wiparam {
- u32 bcompleted;
- u32 act_type;
- u32 io_offset;
- u32 io_value;
-};
-
-struct mp_priv {
- struct _adapter *papdater;
- /*OID cmd handler*/
- struct mp_wiparam workparam;
- u8 act_in_progress;
- /*Tx Section*/
- u8 TID;
- u32 tx_pktcount;
- /*Rx Section*/
- u32 rx_pktcount;
- u32 rx_crcerrpktcount;
- u32 rx_pktloss;
- struct recv_stat rxstat;
- /*RF/BB relative*/
- u32 curr_ch;
- u32 curr_rateidx;
- u8 curr_bandwidth;
- u8 curr_modem;
- u8 curr_txpoweridx;
- u32 curr_crystalcap;
- u16 antenna_tx;
- u16 antenna_rx;
- u8 curr_rfpath;
- u8 check_mp_pkt;
- uint ForcedDataRate;
- struct wlan_network mp_network;
- unsigned char network_macaddr[6];
- /*Testing Flag*/
- u32 mode;/*0 for normal type packet,
- * 1 for loopback packet (16bytes TXCMD)
- */
- sint prev_fw_state;
- u8 *pallocated_mp_xmitframe_buf;
- u8 *pmp_xmtframe_buf;
- struct __queue free_mp_xmitqueue;
- u32 free_mp_xmitframe_cnt;
-};
-
-struct IOCMD_STRUCT {
- u8 cmdclass;
- u16 value;
- u8 index;
-};
-
-struct rf_reg_param {
- u32 path;
- u32 offset;
- u32 value;
-};
-
-struct bb_reg_param {
- u32 offset;
- u32 value;
-};
-
-/* ======================================================================= */
-
-#define LOWER true
-#define RAISE false
-#define IOCMD_CTRL_REG 0x10250370
-#define IOCMD_DATA_REG 0x10250374
-#define IOCMD_GET_THERMAL_METER 0xFD000028
-#define IOCMD_CLASS_BB_RF 0xF0
-#define IOCMD_BB_READ_IDX 0x00
-#define IOCMD_BB_WRITE_IDX 0x01
-#define IOCMD_RF_READ_IDX 0x02
-#define IOCMD_RF_WRIT_IDX 0x03
-#define BB_REG_BASE_ADDR 0x800
-#define RF_PATH_A 0
-#define RF_PATH_B 1
-#define RF_PATH_C 2
-#define RF_PATH_D 3
-#define MAX_RF_PATH_NUMS 2
-#define _2MAC_MODE_ 0
-#define _LOOPBOOK_MODE_ 1
-
-/* MP set force data rate base on the definition. */
-enum {
- /* CCK rate. */
- MPT_RATE_1M, /* 0 */
- MPT_RATE_2M,
- MPT_RATE_55M,
- MPT_RATE_11M, /* 3 */
-
- /* OFDM rate. */
- MPT_RATE_6M, /* 4 */
- MPT_RATE_9M,
- MPT_RATE_12M,
- MPT_RATE_18M,
- MPT_RATE_24M,
- MPT_RATE_36M,
- MPT_RATE_48M,
- MPT_RATE_54M, /* 11 */
-
- /* HT rate. */
- MPT_RATE_MCS0, /* 12 */
- MPT_RATE_MCS1,
- MPT_RATE_MCS2,
- MPT_RATE_MCS3,
- MPT_RATE_MCS4,
- MPT_RATE_MCS5,
- MPT_RATE_MCS6,
- MPT_RATE_MCS7, /* 19 */
- MPT_RATE_MCS8,
- MPT_RATE_MCS9,
- MPT_RATE_MCS10,
- MPT_RATE_MCS11,
- MPT_RATE_MCS12,
- MPT_RATE_MCS13,
- MPT_RATE_MCS14,
- MPT_RATE_MCS15, /* 27 */
- MPT_RATE_LAST
-};
-
-/* Represent Channel Width in HT Capabilities */
-enum HT_CHANNEL_WIDTH {
- HT_CHANNEL_WIDTH_20 = 0,
- HT_CHANNEL_WIDTH_40 = 1,
-};
-
-#define MAX_TX_PWR_INDEX_N_MODE 64 /* 0x3F */
-
-enum POWER_MODE {
- POWER_LOW = 0,
- POWER_NORMAL
-};
-
-#define RX_PKT_BROADCAST 1
-#define RX_PKT_DEST_ADDR 2
-#define RX_PKT_PHY_MATCH 3
-
-#define RPTMaxCount 0x000FFFFF
-
-/* parameter 1 : BitMask
- * bit 0 : OFDM PPDU
- * bit 1 : OFDM False Alarm
- * bit 2 : OFDM MPDU OK
- * bit 3 : OFDM MPDU Fail
- * bit 4 : CCK PPDU
- * bit 5 : CCK False Alarm
- * bit 6 : CCK MPDU ok
- * bit 7 : CCK MPDU fail
- * bit 8 : HT PPDU counter
- * bit 9 : HT false alarm
- * bit 10 : HT MPDU total
- * bit 11 : HT MPDU OK
- * bit 12 : HT MPDU fail
- * bit 15 : RX full drop
- */
-enum RXPHY_BITMASK {
- OFDM_PPDU_BIT = 0,
- OFDM_MPDU_OK_BIT,
- OFDM_MPDU_FAIL_BIT,
- CCK_PPDU_BIT,
- CCK_MPDU_OK_BIT,
- CCK_MPDU_FAIL_BIT,
- HT_PPDU_BIT,
- HT_MPDU_BIT,
- HT_MPDU_OK_BIT,
- HT_MPDU_FAIL_BIT,
-};
-
-enum ENCRY_CTRL_STATE {
- HW_CONTROL, /*hw encryption& decryption*/
- SW_CONTROL, /*sw encryption& decryption*/
- HW_ENCRY_SW_DECRY, /*hw encryption & sw decryption*/
- SW_ENCRY_HW_DECRY /*sw encryption & hw decryption*/
-};
-
-/* Bandwidth Offset */
-#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0
-#define HAL_PRIME_CHNL_OFFSET_LOWER 1
-#define HAL_PRIME_CHNL_OFFSET_UPPER 2
-/*=======================================================================*/
-void mp871xinit(struct _adapter *padapter);
-void mp871xdeinit(struct _adapter *padapter);
-u32 r8712_bb_reg_read(struct _adapter *Adapter, u16 offset);
-u8 r8712_bb_reg_write(struct _adapter *Adapter, u16 offset, u32 value);
-u32 r8712_rf_reg_read(struct _adapter *Adapter, u8 path, u8 offset);
-u8 r8712_rf_reg_write(struct _adapter *Adapter, u8 path,
- u8 offset, u32 value);
-u32 r8712_get_bb_reg(struct _adapter *Adapter, u16 offset, u32 bitmask);
-u8 r8712_set_bb_reg(struct _adapter *Adapter, u16 offset,
- u32 bitmask, u32 value);
-u32 r8712_get_rf_reg(struct _adapter *Adapter, u8 path, u8 offset,
- u32 bitmask);
-u8 r8712_set_rf_reg(struct _adapter *Adapter, u8 path, u8 offset,
- u32 bitmask, u32 value);
-
-void r8712_SetChannel(struct _adapter *pAdapter);
-void r8712_SetTxPower(struct _adapter *pAdapte);
-void r8712_SetTxAGCOffset(struct _adapter *pAdapter, u32 ulTxAGCOffset);
-void r8712_SetDataRate(struct _adapter *pAdapter);
-void r8712_SwitchBandwidth(struct _adapter *pAdapter);
-void r8712_SwitchAntenna(struct _adapter *pAdapter);
-void r8712_GetThermalMeter(struct _adapter *pAdapter, u32 *value);
-void r8712_SetContinuousTx(struct _adapter *pAdapter, u8 bStart);
-void r8712_SetSingleCarrierTx(struct _adapter *pAdapter, u8 bStart);
-void r8712_SetSingleToneTx(struct _adapter *pAdapter, u8 bStart);
-void r8712_SetCarrierSuppressionTx(struct _adapter *pAdapter, u8 bStart);
-void r8712_ResetPhyRxPktCount(struct _adapter *pAdapter);
-u32 r8712_GetPhyRxPktReceived(struct _adapter *pAdapter);
-u32 r8712_GetPhyRxPktCRC32Error(struct _adapter *pAdapter);
-
-#endif /*__RTL871X_MP_H_*/
-
diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
deleted file mode 100644
index 26fa09b45c90..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
+++ /dev/null
@@ -1,883 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_mp_ioctl.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#include <linux/rndis.h>
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "mlme_osdep.h"
-#include "rtl871x_mp.h"
-#include "rtl871x_mp_ioctl.h"
-
-uint oid_null_function(struct oid_par_priv *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv)
-{
- uint status = RNDIS_STATUS_SUCCESS;
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid == SET_OID) {
- if (poid_par_priv->information_buf_len >= sizeof(u8))
- Adapter->registrypriv.wireless_mode =
- *(u8 *)poid_par_priv->information_buf;
- else
- status = RNDIS_STATUS_INVALID_LENGTH;
- } else if (poid_par_priv->type_of_oid == QUERY_OID) {
- if (poid_par_priv->information_buf_len >= sizeof(u8)) {
- *(u8 *)poid_par_priv->information_buf =
- Adapter->registrypriv.wireless_mode;
- *poid_par_priv->bytes_rw =
- poid_par_priv->information_buf_len;
- } else {
- status = RNDIS_STATUS_INVALID_LENGTH;
- }
- } else {
- status = RNDIS_STATUS_NOT_ACCEPTED;
- }
- return status;
-}
-
-uint oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- struct bb_reg_param *pbbreg;
- u16 offset;
- u32 value;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
- return RNDIS_STATUS_INVALID_LENGTH;
- pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
- offset = (u16)(pbbreg->offset) & 0xFFF; /*0ffset :0x800~0xfff*/
- if (offset < BB_REG_BASE_ADDR)
- offset |= BB_REG_BASE_ADDR;
- value = pbbreg->value;
- r8712_bb_reg_write(Adapter, offset, value);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- struct bb_reg_param *pbbreg;
- u16 offset;
- u32 value;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
- return RNDIS_STATUS_INVALID_LENGTH;
- pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
- offset = (u16)(pbbreg->offset) & 0xFFF; /*0ffset :0x800~0xfff*/
- if (offset < BB_REG_BASE_ADDR)
- offset |= BB_REG_BASE_ADDR;
- value = r8712_bb_reg_read(Adapter, offset);
- pbbreg->value = value;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- struct rf_reg_param *pbbreg;
- u8 path;
- u8 offset;
- u32 value;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
- return RNDIS_STATUS_INVALID_LENGTH;
- pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
- path = (u8)pbbreg->path;
- if (path > RF_PATH_B)
- return RNDIS_STATUS_NOT_ACCEPTED;
- offset = (u8)pbbreg->offset;
- value = pbbreg->value;
- r8712_rf_reg_write(Adapter, path, offset, value);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- struct rf_reg_param *pbbreg;
- u8 path;
- u8 offset;
- u32 value;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
- return RNDIS_STATUS_INVALID_LENGTH;
- pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
- path = (u8)pbbreg->path;
- if (path > RF_PATH_B) /* 1T2R path_a /path_b */
- return RNDIS_STATUS_NOT_ACCEPTED;
- offset = (u8)pbbreg->offset;
- value = r8712_rf_reg_read(Adapter, path, offset);
- pbbreg->value = value;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-/*This function initializes the DUT to the MP test mode*/
-static int mp_start_test(struct _adapter *padapter)
-{
- struct mp_priv *pmppriv = &padapter->mppriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_network *tgt_network = &pmlmepriv->cur_network;
- struct wlan_bssid_ex *bssid;
- struct sta_info *psta;
- unsigned long length;
- unsigned long irqL;
- int res = 0;
-
- bssid = kzalloc(sizeof(*bssid), GFP_KERNEL);
- if (!bssid)
- return -ENOMEM;
-
- /* 3 1. initialize a new struct wlan_bssid_ex */
- memcpy(bssid->MacAddress, pmppriv->network_macaddr, ETH_ALEN);
- bssid->Ssid.SsidLength = 16;
- memcpy(bssid->Ssid.Ssid, (unsigned char *)"mp_pseudo_adhoc",
- bssid->Ssid.SsidLength);
- bssid->InfrastructureMode = Ndis802_11IBSS;
- bssid->NetworkTypeInUse = Ndis802_11DS;
- bssid->IELength = 0;
- length = r8712_get_wlan_bssid_ex_sz(bssid);
- if (length % 4) {
- /*round up to multiple of 4 bytes.*/
- bssid->Length = ((length >> 2) + 1) << 2;
- } else {
- bssid->Length = length;
- }
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
- goto end_of_mp_start_test;
- /*init mp_start_test status*/
- pmppriv->prev_fw_state = get_fwstate(pmlmepriv);
- pmlmepriv->fw_state = WIFI_MP_STATE;
- if (pmppriv->mode == _LOOPBOOK_MODE_)
- set_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE); /*append txdesc*/
- set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
- /* 3 2. create a new psta for mp driver */
- /* clear psta in the cur_network, if any */
- psta = r8712_get_stainfo(&padapter->stapriv,
- tgt_network->network.MacAddress);
- if (psta)
- r8712_free_stainfo(padapter, psta);
- psta = r8712_alloc_stainfo(&padapter->stapriv, bssid->MacAddress);
- if (!psta) {
- res = -ENOMEM;
- goto end_of_mp_start_test;
- }
- /* 3 3. join pseudo AdHoc */
- tgt_network->join_res = 1;
- tgt_network->aid = psta->aid = 1;
- memcpy(&tgt_network->network, bssid, length);
- _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
- r8712_os_indicate_connect(padapter);
- /* Set to LINKED STATE for MP TRX Testing */
- set_fwstate(pmlmepriv, _FW_LINKED);
-end_of_mp_start_test:
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- kfree(bssid);
- return res;
-}
-
-/*This function change the DUT from the MP test mode into normal mode */
-static int mp_stop_test(struct _adapter *padapter)
-{
- struct mp_priv *pmppriv = &padapter->mppriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_network *tgt_network = &pmlmepriv->cur_network;
- struct sta_info *psta;
- unsigned long irqL;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (!check_fwstate(pmlmepriv, WIFI_MP_STATE))
- goto end_of_mp_stop_test;
- /* 3 1. disconnect pseudo AdHoc */
- r8712_os_indicate_disconnect(padapter);
- /* 3 2. clear psta used in mp test mode. */
- psta = r8712_get_stainfo(&padapter->stapriv,
- tgt_network->network.MacAddress);
- if (psta)
- r8712_free_stainfo(padapter, psta);
- /* 3 3. return to normal state (default:station mode) */
- pmlmepriv->fw_state = pmppriv->prev_fw_state; /* WIFI_STATION_STATE;*/
- /*flush the cur_network*/
- memset(tgt_network, 0, sizeof(struct wlan_network));
-end_of_mp_stop_test:
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- return _SUCCESS;
-}
-
-uint oid_rt_pro_set_data_rate_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 ratevalue;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len != sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- ratevalue = *((u32 *)poid_par_priv->information_buf);
- if (ratevalue >= MPT_RATE_LAST)
- return RNDIS_STATUS_INVALID_DATA;
- Adapter->mppriv.curr_rateidx = ratevalue;
- r8712_SetDataRate(Adapter);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- uint status = RNDIS_STATUS_SUCCESS;
- u32 mode;
- u8 val8;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- mode = *((u32 *)poid_par_priv->information_buf);
- Adapter->mppriv.mode = mode;/* 1 for loopback*/
- if (mp_start_test(Adapter))
- status = RNDIS_STATUS_NOT_ACCEPTED;
- r8712_write8(Adapter, MSR, 1); /* Link in ad hoc network, 0x1025004C */
- r8712_write8(Adapter, RCR, 0); /* RCR : disable all pkt, 0x10250048 */
- /* RCR disable Check BSSID, 0x1025004a */
- r8712_write8(Adapter, RCR + 2, 0x57);
- /* disable RX filter map , mgt frames will put in RX FIFO 0 */
- r8712_write16(Adapter, RXFLTMAP0, 0x0);
- val8 = r8712_read8(Adapter, EE_9346CR);
- if (!(val8 & _9356SEL)) { /*boot from EFUSE*/
- r8712_efuse_reg_init(Adapter);
- r8712_efuse_change_max_size(Adapter);
- r8712_efuse_reg_uninit(Adapter);
- }
- return status;
-}
-
-uint oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (mp_stop_test(Adapter) == _FAIL)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 Channel;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len != sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- Channel = *((u32 *)poid_par_priv->information_buf);
- if (Channel > 14)
- return RNDIS_STATUS_NOT_ACCEPTED;
- Adapter->mppriv.curr_ch = Channel;
- r8712_SetChannel(Adapter);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_antenna_bb_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 antenna;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len != sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- antenna = *((u32 *)poid_par_priv->information_buf);
- Adapter->mppriv.antenna_tx = (u16)((antenna & 0xFFFF0000) >> 16);
- Adapter->mppriv.antenna_rx = (u16)(antenna & 0x0000FFFF);
- r8712_SwitchAntenna(Adapter);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_tx_power_control_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 tx_pwr_idx;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len != sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- tx_pwr_idx = *((u32 *)poid_par_priv->information_buf);
- if (tx_pwr_idx > MAX_TX_PWR_INDEX_N_MODE)
- return RNDIS_STATUS_NOT_ACCEPTED;
- Adapter->mppriv.curr_txpoweridx = (u8)tx_pwr_idx;
- r8712_SetTxPower(Adapter);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_query_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- if (poid_par_priv->information_buf_len == sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- Adapter->mppriv.tx_pktcount;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_query_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- if (poid_par_priv->information_buf_len == sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- Adapter->mppriv.rx_pktcount;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_query_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- if (poid_par_priv->information_buf_len == sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- Adapter->mppriv.rx_crcerrpktcount;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- Adapter->mppriv.tx_pktcount = 0;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len == sizeof(u32)) {
- Adapter->mppriv.rx_pktcount = 0;
- Adapter->mppriv.rx_crcerrpktcount = 0;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- r8712_ResetPhyRxPktCount(Adapter);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len != sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- *(u32 *)poid_par_priv->information_buf =
- r8712_GetPhyRxPktReceived(Adapter);
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len != sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- *(u32 *)poid_par_priv->information_buf =
- r8712_GetPhyRxPktCRC32Error(Adapter);
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_modulation_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- Adapter->mppriv.curr_modem = *((u8 *)poid_par_priv->information_buf);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 bStartTest;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- bStartTest = *((u32 *)poid_par_priv->information_buf);
- r8712_SetContinuousTx(Adapter, (u8)bStartTest);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 bStartTest;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- bStartTest = *((u32 *)poid_par_priv->information_buf);
- r8712_SetSingleCarrierTx(Adapter, (u8)bStartTest);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 bStartTest;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- bStartTest = *((u32 *)poid_par_priv->information_buf);
- r8712_SetCarrierSuppressionTx(Adapter, (u8)bStartTest);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 bStartTest;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- bStartTest = *((u32 *)poid_par_priv->information_buf);
- r8712_SetSingleToneTx(Adapter, (u8)bStartTest);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- uint status = RNDIS_STATUS_SUCCESS;
- struct mp_rw_reg *RegRWStruct;
- u16 offset;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf;
- if ((RegRWStruct->offset >= 0x10250800) &&
- (RegRWStruct->offset <= 0x10250FFF)) {
- /*baseband register*/
- /*0ffset :0x800~0xfff*/
- offset = (u16)(RegRWStruct->offset) & 0xFFF;
- RegRWStruct->value = r8712_bb_reg_read(Adapter, offset);
- } else {
- switch (RegRWStruct->width) {
- case 1:
- RegRWStruct->value = r8712_read8(Adapter,
- RegRWStruct->offset);
- break;
- case 2:
- RegRWStruct->value = r8712_read16(Adapter,
- RegRWStruct->offset);
- break;
- case 4:
- RegRWStruct->value = r8712_read32(Adapter,
- RegRWStruct->offset);
- break;
- default:
- status = RNDIS_STATUS_NOT_ACCEPTED;
- break;
- }
- }
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return status;
-}
-
-uint oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- uint status = RNDIS_STATUS_SUCCESS;
- struct mp_rw_reg *RegRWStruct;
- u16 offset;
- u32 value;
- u32 oldValue = 0;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf;
- if ((RegRWStruct->offset >= 0x10250800) &&
- (RegRWStruct->offset <= 0x10250FFF)) {
- /*baseband register*/
- offset = (u16)(RegRWStruct->offset) & 0xFFF;
- value = RegRWStruct->value;
- switch (RegRWStruct->width) {
- case 1:
- oldValue = r8712_bb_reg_read(Adapter, offset);
- oldValue &= 0xFFFFFF00;
- value &= 0x000000FF;
- value |= oldValue;
- break;
- case 2:
- oldValue = r8712_bb_reg_read(Adapter, offset);
- oldValue &= 0xFFFF0000;
- value &= 0x0000FFFF;
- value |= oldValue;
- break;
- }
- r8712_bb_reg_write(Adapter, offset, value);
- } else {
- switch (RegRWStruct->width) {
- case 1:
- r8712_write8(Adapter, RegRWStruct->offset,
- (unsigned char)RegRWStruct->value);
- break;
- case 2:
- r8712_write16(Adapter, RegRWStruct->offset,
- (unsigned short)RegRWStruct->value);
- break;
- case 4:
- r8712_write32(Adapter, RegRWStruct->offset,
- (unsigned int)RegRWStruct->value);
- break;
- default:
- status = RNDIS_STATUS_NOT_ACCEPTED;
- break;
- }
- }
- return status;
-}
-
-uint oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- if (Adapter->mppriv.act_in_progress)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- if (poid_par_priv->information_buf_len < sizeof(u8))
- return RNDIS_STATUS_INVALID_LENGTH;
- /*init workparam*/
- Adapter->mppriv.act_in_progress = true;
- Adapter->mppriv.workparam.bcompleted = false;
- Adapter->mppriv.workparam.act_type = MPT_GET_THERMAL_METER;
- Adapter->mppriv.workparam.io_offset = 0;
- Adapter->mppriv.workparam.io_value = 0xFFFFFFFF;
- r8712_GetThermalMeter(Adapter, &Adapter->mppriv.workparam.io_value);
- Adapter->mppriv.workparam.bcompleted = true;
- Adapter->mppriv.act_in_progress = false;
- *(u32 *)poid_par_priv->information_buf =
- Adapter->mppriv.workparam.io_value;
- *poid_par_priv->bytes_rw = sizeof(u32);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- uint status = RNDIS_STATUS_SUCCESS;
-
- struct EFUSE_ACCESS_STRUCT *pefuse;
- u8 *data;
- u16 addr = 0, cnts = 0;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len <
- sizeof(struct EFUSE_ACCESS_STRUCT))
- return RNDIS_STATUS_INVALID_LENGTH;
- pefuse = (struct EFUSE_ACCESS_STRUCT *)poid_par_priv->information_buf;
- addr = pefuse->start_addr;
- cnts = pefuse->cnts;
- data = pefuse->data;
- memset(data, 0xFF, cnts);
- if ((addr > 511) || (cnts < 1) || (cnts > 512) || (addr + cnts) >
- EFUSE_MAX_SIZE)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (!r8712_efuse_access(Adapter, true, addr, cnts, data))
- status = RNDIS_STATUS_FAILURE;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return status;
-}
-
-/*------------------------------------------------------------------------*/
-uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- uint status = RNDIS_STATUS_SUCCESS;
-
- struct EFUSE_ACCESS_STRUCT *pefuse;
- u8 *data;
- u16 addr = 0, cnts = 0;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- pefuse = (struct EFUSE_ACCESS_STRUCT *)poid_par_priv->information_buf;
- addr = pefuse->start_addr;
- cnts = pefuse->cnts;
- data = pefuse->data;
-
- if ((addr > 511) || (cnts < 1) || (cnts > 512) ||
- (addr + cnts) > r8712_efuse_get_max_size(Adapter))
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (!r8712_efuse_access(Adapter, false, addr, cnts, data))
- status = RNDIS_STATUS_FAILURE;
- return status;
-}
-
-/*----------------------------------------------------------------------*/
-
-uint oid_rt_get_efuse_current_size_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(int))
- return RNDIS_STATUS_INVALID_LENGTH;
- r8712_efuse_reg_init(Adapter);
- *(int *)poid_par_priv->information_buf =
- r8712_efuse_get_current_size(Adapter);
- r8712_efuse_reg_uninit(Adapter);
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- *(int *)poid_par_priv->information_buf =
- r8712_efuse_get_max_size(Adapter);
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv)
-{
- uint status = RNDIS_STATUS_SUCCESS;
-
- if (poid_par_priv->type_of_oid == QUERY_OID)
- status = oid_rt_pro_read_efuse_hdl(poid_par_priv);
- else
- status = oid_rt_pro_write_efuse_hdl(poid_par_priv);
- return status;
-}
-
-uint oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- uint status = RNDIS_STATUS_SUCCESS;
- u8 *data;
-
- *poid_par_priv->bytes_rw = 0;
- if (poid_par_priv->information_buf_len < EFUSE_MAP_MAX_SIZE)
- return RNDIS_STATUS_INVALID_LENGTH;
- data = (u8 *)poid_par_priv->information_buf;
- if (poid_par_priv->type_of_oid == QUERY_OID) {
- if (r8712_efuse_map_read(Adapter, 0, EFUSE_MAP_MAX_SIZE, data))
- *poid_par_priv->bytes_rw = EFUSE_MAP_MAX_SIZE;
- else
- status = RNDIS_STATUS_FAILURE;
- } else {
- /* SET_OID */
- if (r8712_efuse_reg_init(Adapter)) {
- if (r8712_efuse_map_write(Adapter, 0,
- EFUSE_MAP_MAX_SIZE, data))
- *poid_par_priv->bytes_rw = EFUSE_MAP_MAX_SIZE;
- else
- status = RNDIS_STATUS_FAILURE;
- r8712_efuse_reg_uninit(Adapter);
- } else {
- status = RNDIS_STATUS_FAILURE;
- }
- }
- return status;
-}
-
-uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 bandwidth;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- bandwidth = *((u32 *)poid_par_priv->information_buf);/*4*/
- if (bandwidth != HT_CHANNEL_WIDTH_20)
- bandwidth = HT_CHANNEL_WIDTH_40;
- Adapter->mppriv.curr_bandwidth = (u8)bandwidth;
- r8712_SwitchBandwidth(Adapter);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u8 rx_pkt_type;
- u32 rcr_val32;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(u8))
- return RNDIS_STATUS_INVALID_LENGTH;
- rx_pkt_type = *((u8 *)poid_par_priv->information_buf);/*4*/
- rcr_val32 = r8712_read32(Adapter, RCR);/*RCR = 0x10250048*/
- rcr_val32 &= ~(RCR_CBSSID | RCR_AB | RCR_AM | RCR_APM | RCR_AAP);
- switch (rx_pkt_type) {
- case RX_PKT_BROADCAST:
- rcr_val32 |= (RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_ACRC32);
- break;
- case RX_PKT_DEST_ADDR:
- rcr_val32 |= (RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_ACRC32);
- break;
- case RX_PKT_PHY_MATCH:
- rcr_val32 |= (RCR_APM | RCR_ACRC32);
- break;
- default:
- rcr_val32 &= ~(RCR_AAP |
- RCR_APM |
- RCR_AM |
- RCR_AB |
- RCR_ACRC32);
- break;
- }
- if (rx_pkt_type == RX_PKT_DEST_ADDR)
- Adapter->mppriv.check_mp_pkt = 1;
- else
- Adapter->mppriv.check_mp_pkt = 0;
- r8712_write32(Adapter, RCR, rcr_val32);
- return RNDIS_STATUS_SUCCESS;
-}
-
-/*--------------------------------------------------------------------------*/
-/*Linux*/
-unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv)
-{
- return _SUCCESS;
-}
-
-/*-------------------------------------------------------------------------*/
-uint oid_rt_set_power_down_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- /*CALL the power_down function*/
- return RNDIS_STATUS_SUCCESS;
-}
-
-/*-------------------------------------------------------------------------- */
-uint oid_rt_get_power_mode_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- *(int *)poid_par_priv->information_buf =
- Adapter->registrypriv.low_power ? POWER_LOW : POWER_NORMAL;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h
deleted file mode 100644
index aa4d5ce471f2..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h
+++ /dev/null
@@ -1,328 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871X_MP_IOCTL_H
-#define _RTL871X_MP_IOCTL_H
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "mp_custom_oid.h"
-#include "rtl871x_ioctl.h"
-#include "rtl871x_ioctl_rtl.h"
-#include "rtl8712_efuse.h"
-
-#define TESTFWCMDNUMBER 1000000
-#define TEST_H2CINT_WAIT_TIME 500
-#define TEST_C2HINT_WAIT_TIME 500
-#define HCI_TEST_SYSCFG_HWMASK 1
-#define _BUSCLK_40M (4 << 2)
-
-struct CFG_DBG_MSG_STRUCT {
- u32 DebugLevel;
- u32 DebugComponent_H32;
- u32 DebugComponent_L32;
-};
-
-struct mp_rw_reg {
- uint offset;
- uint width;
- u32 value;
-};
-
-/* for OID_RT_PRO_READ16_EEPROM & OID_RT_PRO_WRITE16_EEPROM */
-struct eeprom_rw_param {
- uint offset;
- u16 value;
-};
-
-struct EFUSE_ACCESS_STRUCT {
- u16 start_addr;
- u16 cnts;
- u8 data[];
-};
-
-struct burst_rw_reg {
- uint offset;
- uint len;
- u8 Data[256];
-};
-
-struct usb_vendor_req {
- u8 bRequest;
- u16 wValue;
- u16 wIndex;
- u16 wLength;
- u8 u8Dir;/*0:OUT, 1:IN */
- u8 u8InData;
-};
-
-struct DR_VARIABLE_STRUCT {
- u8 offset;
- u32 variable;
-};
-
-/* oid_rtl_seg_87_11_00 */
-uint oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv);
-/* oid_rtl_seg_81_80_00 */
-uint oid_rt_pro_set_data_rate_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_channel_direct_call_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_antenna_bb_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_tx_power_control_hdl(
- struct oid_par_priv *poid_par_priv);
-/* oid_rtl_seg_81_80_20 */
-uint oid_rt_pro_query_tx_packet_sent_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_query_rx_packet_received_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_query_rx_packet_crc32_error_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_reset_tx_packet_sent_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_reset_rx_packet_received_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_modulation_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_continuous_tx_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_single_carrier_tx_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_carrier_suppression_tx_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_single_tone_tx_hdl(
- struct oid_par_priv *poid_par_priv);
-/* oid_rtl_seg_81_87 */
-uint oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv);
-/* oid_rtl_seg_81_85 */
-uint oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_efuse_current_size_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_thermal_meter_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_reset_phy_rx_packet_count_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_phy_rx_packet_received_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_phy_rx_packet_crc32_error_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_power_down_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_power_mode_hdl(
- struct oid_par_priv *poid_par_priv);
-#ifdef _RTL871X_MP_IOCTL_C_ /* CAUTION!!! */
-/* This ifdef _MUST_ be left in!! */
-
-#else /* _RTL871X_MP_IOCTL_C_ */
-extern struct oid_obj_priv oid_rtl_seg_81_87[5];
-extern struct oid_obj_priv oid_rtl_seg_87_11_00[32];
-extern struct oid_obj_priv oid_rtl_seg_87_11_20[5];
-extern struct oid_obj_priv oid_rtl_seg_87_11_50[2];
-extern struct oid_obj_priv oid_rtl_seg_87_11_80[1];
-extern struct oid_obj_priv oid_rtl_seg_87_11_B0[1];
-extern struct oid_obj_priv oid_rtl_seg_87_11_F0[16];
-extern struct oid_obj_priv oid_rtl_seg_87_12_00[32];
-
-#endif /* _RTL871X_MP_IOCTL_C_ */
-
-enum MP_MODE {
- MP_START_MODE,
- MP_STOP_MODE,
- MP_ERR_MODE
-};
-
-struct rwreg_param {
- unsigned int offset;
- unsigned int width;
- unsigned int value;
-};
-
-struct bbreg_param {
- unsigned int offset;
- unsigned int phymask;
- unsigned int value;
-};
-
-struct txpower_param {
- unsigned int pwr_index;
-};
-
-struct datarate_param {
- unsigned int rate_index;
-};
-
-struct rfintfs_parm {
- unsigned int rfintfs;
-};
-
-struct mp_xmit_packet {
- unsigned int len;
-};
-
-struct psmode_param {
- unsigned int ps_mode;
- unsigned int smart_ps;
-};
-
-struct mp_ioctl_handler {
- unsigned int paramsize;
- unsigned int (*handler)(struct oid_par_priv *poid_par_priv);
- unsigned int oid;
-};
-
-struct mp_ioctl_param {
- unsigned int subcode;
- unsigned int len;
- unsigned char data[];
-};
-
-#define GEN_MP_IOCTL_SUBCODE(code) _MP_IOCTL_ ## code ## _CMD_
-
-enum RTL871X_MP_IOCTL_SUBCODE {
- GEN_MP_IOCTL_SUBCODE(MP_START), /*0*/
- GEN_MP_IOCTL_SUBCODE(MP_STOP), /*1*/
- GEN_MP_IOCTL_SUBCODE(READ_REG), /*2*/
- GEN_MP_IOCTL_SUBCODE(WRITE_REG),
- GEN_MP_IOCTL_SUBCODE(SET_CHANNEL), /*4*/
- GEN_MP_IOCTL_SUBCODE(SET_TXPOWER), /*5*/
- GEN_MP_IOCTL_SUBCODE(SET_DATARATE), /*6*/
- GEN_MP_IOCTL_SUBCODE(READ_BB_REG), /*7*/
- GEN_MP_IOCTL_SUBCODE(WRITE_BB_REG),
- GEN_MP_IOCTL_SUBCODE(READ_RF_REG), /*9*/
- GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG),
- GEN_MP_IOCTL_SUBCODE(SET_RF_INTFS),
- GEN_MP_IOCTL_SUBCODE(IOCTL_XMIT_PACKET), /*12*/
- GEN_MP_IOCTL_SUBCODE(PS_STATE), /*13*/
- GEN_MP_IOCTL_SUBCODE(READ16_EEPROM), /*14*/
- GEN_MP_IOCTL_SUBCODE(WRITE16_EEPROM), /*15*/
- GEN_MP_IOCTL_SUBCODE(SET_PTM), /*16*/
- GEN_MP_IOCTL_SUBCODE(READ_TSSI), /*17*/
- GEN_MP_IOCTL_SUBCODE(CNTU_TX), /*18*/
- GEN_MP_IOCTL_SUBCODE(SET_BANDWIDTH), /*19*/
- GEN_MP_IOCTL_SUBCODE(SET_RX_PKT_TYPE), /*20*/
- GEN_MP_IOCTL_SUBCODE(RESET_PHY_RX_PKT_CNT), /*21*/
- GEN_MP_IOCTL_SUBCODE(GET_PHY_RX_PKT_RECV), /*22*/
- GEN_MP_IOCTL_SUBCODE(GET_PHY_RX_PKT_ERROR), /*23*/
- GEN_MP_IOCTL_SUBCODE(SET_POWER_DOWN), /*24*/
- GEN_MP_IOCTL_SUBCODE(GET_THERMAL_METER), /*25*/
- GEN_MP_IOCTL_SUBCODE(GET_POWER_MODE), /*26*/
- GEN_MP_IOCTL_SUBCODE(EFUSE), /*27*/
- GEN_MP_IOCTL_SUBCODE(EFUSE_MAP), /*28*/
- GEN_MP_IOCTL_SUBCODE(GET_EFUSE_MAX_SIZE), /*29*/
- GEN_MP_IOCTL_SUBCODE(GET_EFUSE_CURRENT_SIZE), /*30*/
- GEN_MP_IOCTL_SUBCODE(SC_TX), /*31*/
- GEN_MP_IOCTL_SUBCODE(CS_TX), /*32*/
- GEN_MP_IOCTL_SUBCODE(ST_TX), /*33*/
- GEN_MP_IOCTL_SUBCODE(SET_ANTENNA), /*34*/
- MAX_MP_IOCTL_SUBCODE,
-};
-
-unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv);
-
-#ifdef _RTL871X_MP_IOCTL_C_ /* CAUTION!!! */
-/* This ifdef _MUST_ be left in!! */
-
-static struct mp_ioctl_handler mp_ioctl_hdl[] = {
- {sizeof(u32), oid_rt_pro_start_test_hdl,
- OID_RT_PRO_START_TEST},/*0*/
- {sizeof(u32), oid_rt_pro_stop_test_hdl,
- OID_RT_PRO_STOP_TEST},/*1*/
- {sizeof(struct rwreg_param),
- oid_rt_pro_read_register_hdl,
- OID_RT_PRO_READ_REGISTER},/*2*/
- {sizeof(struct rwreg_param),
- oid_rt_pro_write_register_hdl,
- OID_RT_PRO_WRITE_REGISTER},
- {sizeof(u32),
- oid_rt_pro_set_channel_direct_call_hdl,
- OID_RT_PRO_SET_CHANNEL_DIRECT_CALL},
- {sizeof(struct txpower_param),
- oid_rt_pro_set_tx_power_control_hdl,
- OID_RT_PRO_SET_TX_POWER_CONTROL},
- {sizeof(u32),
- oid_rt_pro_set_data_rate_hdl,
- OID_RT_PRO_SET_DATA_RATE},
- {sizeof(struct bb_reg_param),
- oid_rt_pro_read_bb_reg_hdl,
- OID_RT_PRO_READ_BB_REG},/*7*/
- {sizeof(struct bb_reg_param),
- oid_rt_pro_write_bb_reg_hdl,
- OID_RT_PRO_WRITE_BB_REG},
- {sizeof(struct rwreg_param),
- oid_rt_pro_read_rf_reg_hdl,
- OID_RT_PRO_RF_READ_REGISTRY},/*9*/
- {sizeof(struct rwreg_param),
- oid_rt_pro_write_rf_reg_hdl,
- OID_RT_PRO_RF_WRITE_REGISTRY},
- {sizeof(struct rfintfs_parm), NULL, 0},
- {0, mp_ioctl_xmit_packet_hdl, 0},/*12*/
- {sizeof(struct psmode_param), NULL, 0},/*13*/
- {sizeof(struct eeprom_rw_param), NULL, 0},/*14*/
- {sizeof(struct eeprom_rw_param), NULL, 0},/*15*/
- {sizeof(unsigned char), NULL, 0},/*16*/
- {sizeof(u32), NULL, 0},/*17*/
- {sizeof(u32), oid_rt_pro_set_continuous_tx_hdl,
- OID_RT_PRO_SET_CONTINUOUS_TX},/*18*/
- {sizeof(u32), oid_rt_set_bandwidth_hdl,
- OID_RT_SET_BANDWIDTH},/*19*/
- {sizeof(u32), oid_rt_set_rx_packet_type_hdl,
- OID_RT_SET_RX_PACKET_TYPE},/*20*/
- {0, oid_rt_reset_phy_rx_packet_count_hdl,
- OID_RT_RESET_PHY_RX_PACKET_COUNT},/*21*/
- {sizeof(u32), oid_rt_get_phy_rx_packet_received_hdl,
- OID_RT_GET_PHY_RX_PACKET_RECEIVED},/*22*/
- {sizeof(u32), oid_rt_get_phy_rx_packet_crc32_error_hdl,
- OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR},/*23*/
- {sizeof(unsigned char), oid_rt_set_power_down_hdl,
- OID_RT_SET_POWER_DOWN},/*24*/
- {sizeof(u32), oid_rt_get_thermal_meter_hdl,
- OID_RT_PRO_GET_THERMAL_METER},/*25*/
- {sizeof(u32), oid_rt_get_power_mode_hdl,
- OID_RT_GET_POWER_MODE},/*26*/
- {sizeof(struct EFUSE_ACCESS_STRUCT),
- oid_rt_pro_efuse_hdl, OID_RT_PRO_EFUSE},/*27*/
- {EFUSE_MAP_MAX_SIZE, oid_rt_pro_efuse_map_hdl,
- OID_RT_PRO_EFUSE_MAP},/*28*/
- {sizeof(u32), oid_rt_get_efuse_max_size_hdl,
- OID_RT_GET_EFUSE_MAX_SIZE},/*29*/
- {sizeof(u32), oid_rt_get_efuse_current_size_hdl,
- OID_RT_GET_EFUSE_CURRENT_SIZE},/*30*/
- {sizeof(u32), oid_rt_pro_set_single_carrier_tx_hdl,
- OID_RT_PRO_SET_SINGLE_CARRIER_TX},/*31*/
- {sizeof(u32), oid_rt_pro_set_carrier_suppression_tx_hdl,
- OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX},/*32*/
- {sizeof(u32), oid_rt_pro_set_single_tone_tx_hdl,
- OID_RT_PRO_SET_SINGLE_TONE_TX},/*33*/
- {sizeof(u32), oid_rt_pro_set_antenna_bb_hdl,
- OID_RT_PRO_SET_ANTENNA_BB},/*34*/
-};
-
-#else /* _RTL871X_MP_IOCTL_C_ */
-extern struct mp_ioctl_handler mp_ioctl_hdl[];
-#endif /* _RTL871X_MP_IOCTL_C_ */
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h b/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h
deleted file mode 100644
index bb9f83d58225..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h
+++ /dev/null
@@ -1,1034 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*****************************************************************************
- * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved.
- *
- * Module: __INC_HAL8192SPHYREG_H
- *
- *
- * Note: 1. Define PMAC/BB register map
- * 2. Define RF register map
- * 3. PMAC/BB register bit mask.
- * 4. RF reg bit mask.
- * 5. Other BB/RF relative definition.
- *
- *
- * Export: Constants, macro, functions(API), global variables(None).
- *
- * Abbrev:
- *
- * History:
- * Data Who Remark
- * 08/07/2007 MHC 1. Porting from 9x series PHYCFG.h.
- * 2. Reorganize code architecture.
- * 09/25/2008 MH 1. Add RL6052 register definition
- *
- *****************************************************************************/
-#ifndef __RTL871X_MP_PHY_REGDEF_H
-#define __RTL871X_MP_PHY_REGDEF_H
-
-/*--------------------------Define Parameters-------------------------------*/
-
-/*============================================================
- * 8192S Register offset definition
- *============================================================
- *
- *
- * BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF
- * 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF
- * 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00
- * 3. RF register 0x00-2E
- * 4. Bit Mask for BB/RF register
- * 5. Other definition for BB/RF R/W
- *
- * 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF
- * 1. Page1(0x100)
- */
-#define rPMAC_Reset 0x100
-#define rPMAC_TxStart 0x104
-#define rPMAC_TxLegacySIG 0x108
-#define rPMAC_TxHTSIG1 0x10c
-#define rPMAC_TxHTSIG2 0x110
-#define rPMAC_PHYDebug 0x114
-#define rPMAC_TxPacketNum 0x118
-#define rPMAC_TxIdle 0x11c
-#define rPMAC_TxMACHeader0 0x120
-#define rPMAC_TxMACHeader1 0x124
-#define rPMAC_TxMACHeader2 0x128
-#define rPMAC_TxMACHeader3 0x12c
-#define rPMAC_TxMACHeader4 0x130
-#define rPMAC_TxMACHeader5 0x134
-#define rPMAC_TxDataType 0x138
-#define rPMAC_TxRandomSeed 0x13c
-#define rPMAC_CCKPLCPPreamble 0x140
-#define rPMAC_CCKPLCPHeader 0x144
-#define rPMAC_CCKCRC16 0x148
-#define rPMAC_OFDMRxCRC32OK 0x170
-#define rPMAC_OFDMRxCRC32Er 0x174
-#define rPMAC_OFDMRxParityEr 0x178
-#define rPMAC_OFDMRxCRC8Er 0x17c
-#define rPMAC_CCKCRxRC16Er 0x180
-#define rPMAC_CCKCRxRC32Er 0x184
-#define rPMAC_CCKCRxRC32OK 0x188
-#define rPMAC_TxStatus 0x18c
-
-/*
- * 2. Page2(0x200)
- *
- * The following two definition are only used for USB interface.
- *#define RF_BB_CMD_ADDR 0x02c0 // RF/BB read/write command address.
- *#define RF_BB_CMD_DATA 0x02c4 // RF/BB read/write command data.
- *
- *
- * 3. Page8(0x800)
- */
-#define rFPGA0_RFMOD 0x800 /*RF mode & CCK TxSC RF
- * BW Setting??
- */
-#define rFPGA0_TxInfo 0x804 /* Status report?? */
-#define rFPGA0_PSDFunction 0x808
-#define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */
-#define rFPGA0_RFTiming1 0x810 /* Useless now */
-#define rFPGA0_RFTiming2 0x814
-#define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */
-#define rFPGA0_XA_HSSIParameter2 0x824
-#define rFPGA0_XB_HSSIParameter1 0x828
-#define rFPGA0_XB_HSSIParameter2 0x82c
-#define rFPGA0_XC_HSSIParameter1 0x830
-#define rFPGA0_XC_HSSIParameter2 0x834
-#define rFPGA0_XD_HSSIParameter1 0x838
-#define rFPGA0_XD_HSSIParameter2 0x83c
-#define rFPGA0_XA_LSSIParameter 0x840
-#define rFPGA0_XB_LSSIParameter 0x844
-#define rFPGA0_XC_LSSIParameter 0x848
-#define rFPGA0_XD_LSSIParameter 0x84c
-
-#define rFPGA0_RFWakeUpParameter 0x850 /* Useless now */
-#define rFPGA0_RFSleepUpParameter 0x854
-
-#define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */
-#define rFPGA0_XCD_SwitchControl 0x85c
-
-#define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */
-#define rFPGA0_XB_RFInterfaceOE 0x864
-#define rFPGA0_XC_RFInterfaceOE 0x868
-#define rFPGA0_XD_RFInterfaceOE 0x86c
-#define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Interface Software Ctrl */
-#define rFPGA0_XCD_RFInterfaceSW 0x874
-
-#define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */
-#define rFPGA0_XCD_RFParameter 0x87c
-
-#define rFPGA0_AnalogParameter1 0x880 /* Crystal cap setting
- * RF-R/W protection
- * for parameter4??
- */
-#define rFPGA0_AnalogParameter2 0x884
-#define rFPGA0_AnalogParameter3 0x888 /* Useless now */
-#define rFPGA0_AnalogParameter4 0x88c
-
-#define rFPGA0_XA_LSSIReadBack 0x8a0 /* Transceiver LSSI Readback */
-#define rFPGA0_XB_LSSIReadBack 0x8a4
-#define rFPGA0_XC_LSSIReadBack 0x8a8
-#define rFPGA0_XD_LSSIReadBack 0x8ac
-
-#define rFPGA0_PSDReport 0x8b4 /* Useless now */
-#define rFPGA0_XAB_RFInterfaceRB 0x8e0 /* Useless now */
-#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */
-
-/*
- * 4. Page9(0x900)
- */
-#define rFPGA1_RFMOD 0x900 /* RF mode & OFDM TxSC */
-
-#define rFPGA1_TxBlock 0x904 /* Useless now */
-#define rFPGA1_DebugSelect 0x908 /* Useless now */
-#define rFPGA1_TxInfo 0x90c /* Useless now */
-
-/*
- * 5. PageA(0xA00)
- *
- * Set Control channel to upper or lower.
- * These settings are required only for 40MHz
- */
-#define rCCK0_System 0xa00
-
-#define rCCK0_AFESetting 0xa04 /* Disable init gain now */
-#define rCCK0_CCA 0xa08 /* Disable init gain now */
-
-#define rCCK0_RxAGC1 0xa0c
-/* AGC default value, saturation level
- * Antenna Diversity, RX AGC, LNA Threshold, RX LNA Threshold useless now.
- * Not the same as 90 series
- */
-#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */
-
-#define rCCK0_RxHP 0xa14
-
-#define rCCK0_DSPParameter1 0xa18 /* Timing recovery & Channel
- * estimation threshold
- */
-#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */
-
-#define rCCK0_TxFilter1 0xa20
-#define rCCK0_TxFilter2 0xa24
-#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */
-#define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now 0xa30-a4f
- * channel report
- */
-#define rCCK0_TRSSIReport 0xa50
-#define rCCK0_RxReport 0xa54 /* 0xa57 */
-#define rCCK0_FACounterLower 0xa5c /* 0xa5b */
-#define rCCK0_FACounterUpper 0xa58 /* 0xa5c */
-
-/*
- * 6. PageC(0xC00)
- */
-#define rOFDM0_LSTF 0xc00
-#define rOFDM0_TRxPathEnable 0xc04
-#define rOFDM0_TRMuxPar 0xc08
-#define rOFDM0_TRSWIsolation 0xc0c
-
-/*RxIQ DC offset, Rx digital filter, DC notch filter */
-#define rOFDM0_XARxAFE 0xc10
-#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imbalance matrix */
-#define rOFDM0_XBRxAFE 0xc18
-#define rOFDM0_XBRxIQImbalance 0xc1c
-#define rOFDM0_XCRxAFE 0xc20
-#define rOFDM0_XCRxIQImbalance 0xc24
-#define rOFDM0_XDRxAFE 0xc28
-#define rOFDM0_XDRxIQImbalance 0xc2c
-
-#define rOFDM0_RxDetector1 0xc30 /* PD,BW & SBD DM tune
- * init gain
- */
-#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */
-#define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */
-#define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync &
- * Short-GI
- */
-
-#define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */
-#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */
-#define rOFDM0_CCADropThreshold 0xc48 /* CCA Drop threshold */
-#define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */
-
-#define rOFDM0_XAAGCCore1 0xc50 /* DIG */
-#define rOFDM0_XAAGCCore2 0xc54
-#define rOFDM0_XBAGCCore1 0xc58
-#define rOFDM0_XBAGCCore2 0xc5c
-#define rOFDM0_XCAGCCore1 0xc60
-#define rOFDM0_XCAGCCore2 0xc64
-#define rOFDM0_XDAGCCore1 0xc68
-#define rOFDM0_XDAGCCore2 0xc6c
-#define rOFDM0_AGCParameter1 0xc70
-#define rOFDM0_AGCParameter2 0xc74
-#define rOFDM0_AGCRSSITable 0xc78
-#define rOFDM0_HTSTFAGC 0xc7c
-
-#define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */
-#define rOFDM0_XATxAFE 0xc84
-#define rOFDM0_XBTxIQImbalance 0xc88
-#define rOFDM0_XBTxAFE 0xc8c
-#define rOFDM0_XCTxIQImbalance 0xc90
-#define rOFDM0_XCTxAFE 0xc94
-#define rOFDM0_XDTxIQImbalance 0xc98
-#define rOFDM0_XDTxAFE 0xc9c
-
-#define rOFDM0_RxHPParameter 0xce0
-#define rOFDM0_TxPseudoNoiseWgt 0xce4
-#define rOFDM0_FrameSync 0xcf0
-#define rOFDM0_DFSReport 0xcf4
-#define rOFDM0_TxCoeff1 0xca4
-#define rOFDM0_TxCoeff2 0xca8
-#define rOFDM0_TxCoeff3 0xcac
-#define rOFDM0_TxCoeff4 0xcb0
-#define rOFDM0_TxCoeff5 0xcb4
-#define rOFDM0_TxCoeff6 0xcb8
-
-/*
- * 7. PageD(0xD00)
- */
-#define rOFDM1_LSTF 0xd00
-#define rOFDM1_TRxPathEnable 0xd04
-
-#define rOFDM1_CFO 0xd08 /* No setting now */
-#define rOFDM1_CSI1 0xd10
-#define rOFDM1_SBD 0xd14
-#define rOFDM1_CSI2 0xd18
-#define rOFDM1_CFOTracking 0xd2c
-#define rOFDM1_TRxMesaure1 0xd34
-#define rOFDM1_IntfDet 0xd3c
-#define rOFDM1_PseudoNoiseStateAB 0xd50
-#define rOFDM1_PseudoNoiseStateCD 0xd54
-#define rOFDM1_RxPseudoNoiseWgt 0xd58
-
-#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */
-#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */
-#define rOFDM_PHYCounter3 0xda8 /* MCS not support */
-#define rOFDM_ShortCFOAB 0xdac /* No setting now */
-#define rOFDM_ShortCFOCD 0xdb0
-#define rOFDM_LongCFOAB 0xdb4
-#define rOFDM_LongCFOCD 0xdb8
-#define rOFDM_TailCFOAB 0xdbc
-#define rOFDM_TailCFOCD 0xdc0
-#define rOFDM_PWMeasure1 0xdc4
-#define rOFDM_PWMeasure2 0xdc8
-#define rOFDM_BWReport 0xdcc
-#define rOFDM_AGCReport 0xdd0
-#define rOFDM_RxSNR 0xdd4
-#define rOFDM_RxEVMCSI 0xdd8
-#define rOFDM_SIGReport 0xddc
-
-/*
- * 8. PageE(0xE00)
- */
-#define rTxAGC_Rate18_06 0xe00
-#define rTxAGC_Rate54_24 0xe04
-#define rTxAGC_CCK_Mcs32 0xe08
-#define rTxAGC_Mcs03_Mcs00 0xe10
-#define rTxAGC_Mcs07_Mcs04 0xe14
-#define rTxAGC_Mcs11_Mcs08 0xe18
-#define rTxAGC_Mcs15_Mcs12 0xe1c
-
-/* Analog- control in RX_WAIT_CCA : REG: EE0
- * [Analog- Power & Control Register]
- */
-#define rRx_Wait_CCCA 0xe70
-#define rAnapar_Ctrl_BB 0xee0
-
-/*
- * 7. RF Register 0x00-0x2E (RF 8256)
- * RF-0222D 0x00-3F
- *
- * Zebra1
- */
-#define rZebra1_HSSIEnable 0x0 /* Useless now */
-#define rZebra1_TRxEnable1 0x1
-#define rZebra1_TRxEnable2 0x2
-#define rZebra1_AGC 0x4
-#define rZebra1_ChargePump 0x5
-#define rZebra1_Channel 0x7 /* RF channel switch */
-#define rZebra1_TxGain 0x8 /* Useless now */
-#define rZebra1_TxLPF 0x9
-#define rZebra1_RxLPF 0xb
-#define rZebra1_RxHPFCorner 0xc
-
-/* Zebra4 */
-#define rGlobalCtrl 0 /* Useless now */
-#define rRTL8256_TxLPF 19
-#define rRTL8256_RxLPF 11
-
-/* RTL8258 */
-#define rRTL8258_TxLPF 0x11 /* Useless now */
-#define rRTL8258_RxLPF 0x13
-#define rRTL8258_RSSILPF 0xa
-
-/* RL6052 Register definition */
-#define RF_AC 0x00
-#define RF_IQADJ_G1 0x01
-#define RF_IQADJ_G2 0x02
-#define RF_POW_TRSW 0x05
-
-#define RF_GAIN_RX 0x06
-#define RF_GAIN_TX 0x07
-
-#define RF_TXM_IDAC 0x08
-#define RF_BS_IQGEN 0x0F
-
-#define RF_MODE1 0x10
-#define RF_MODE2 0x11
-
-#define RF_RX_AGC_HP 0x12
-#define RF_TX_AGC 0x13
-#define RF_BIAS 0x14
-#define RF_IPA 0x15
-#define RF_POW_ABILITY 0x17
-#define RF_MODE_AG 0x18
-#define rRfChannel 0x18 /* RF channel and BW switch */
-#define RF_CHNLBW 0x18 /* RF channel and BW switch */
-#define RF_TOP 0x19
-#define RF_RX_G1 0x1A
-#define RF_RX_G2 0x1B
-#define RF_RX_BB2 0x1C
-#define RF_RX_BB1 0x1D
-
-#define RF_RCK1 0x1E
-#define RF_RCK2 0x1F
-
-#define RF_TX_G1 0x20
-#define RF_TX_G2 0x21
-#define RF_TX_G3 0x22
-
-#define RF_TX_BB1 0x23
-#define RF_T_METER 0x24
-
-#define RF_SYN_G1 0x25 /* RF TX Power control */
-#define RF_SYN_G2 0x26 /* RF TX Power control */
-#define RF_SYN_G3 0x27 /* RF TX Power control */
-#define RF_SYN_G4 0x28 /* RF TX Power control */
-#define RF_SYN_G5 0x29 /* RF TX Power control */
-#define RF_SYN_G6 0x2A /* RF TX Power control */
-#define RF_SYN_G7 0x2B /* RF TX Power control */
-#define RF_SYN_G8 0x2C /* RF TX Power control */
-
-#define RF_RCK_OS 0x30 /* RF TX PA control */
-
-#define RF_TXPA_G1 0x31 /* RF TX PA control */
-#define RF_TXPA_G2 0x32 /* RF TX PA control */
-#define RF_TXPA_G3 0x33 /* RF TX PA control */
-
-/*
- * Bit Mask
- *
- * 1. Page1(0x100)
- */
-#define bBBResetB 0x100 /* Useless now? */
-#define bGlobalResetB 0x200
-#define bOFDMTxStart 0x4
-#define bCCKTxStart 0x8
-#define bCRC32Debug 0x100
-#define bPMACLoopback 0x10
-#define bTxLSIG 0xffffff
-#define bOFDMTxRate 0xf
-#define bOFDMTxReserved 0x10
-#define bOFDMTxLength 0x1ffe0
-#define bOFDMTxParity 0x20000
-#define bTxHTSIG1 0xffffff
-#define bTxHTMCSRate 0x7f
-#define bTxHTBW 0x80
-#define bTxHTLength 0xffff00
-#define bTxHTSIG2 0xffffff
-#define bTxHTSmoothing 0x1
-#define bTxHTSounding 0x2
-#define bTxHTReserved 0x4
-#define bTxHTAggreation 0x8
-#define bTxHTSTBC 0x30
-#define bTxHTAdvanceCoding 0x40
-#define bTxHTShortGI 0x80
-#define bTxHTNumberHT_LTF 0x300
-#define bTxHTCRC8 0x3fc00
-#define bCounterReset 0x10000
-#define bNumOfOFDMTx 0xffff
-#define bNumOfCCKTx 0xffff0000
-#define bTxIdleInterval 0xffff
-#define bOFDMService 0xffff0000
-#define bTxMACHeader 0xffffffff
-#define bTxDataInit 0xff
-#define bTxHTMode 0x100
-#define bTxDataType 0x30000
-#define bTxRandomSeed 0xffffffff
-#define bCCKTxPreamble 0x1
-#define bCCKTxSFD 0xffff0000
-#define bCCKTxSIG 0xff
-#define bCCKTxService 0xff00
-#define bCCKLengthExt 0x8000
-#define bCCKTxLength 0xffff0000
-#define bCCKTxCRC16 0xffff
-#define bCCKTxStatus 0x1
-#define bOFDMTxStatus 0x2
-#define IS_BB_REG_OFFSET_92S(_Offset) ((_Offset >= 0x800) && \
- (_Offset <= 0xfff))
-
-/* 2. Page8(0x800) */
-#define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */
-#define bJapanMode 0x2
-#define bCCKTxSC 0x30
-#define bCCKEn 0x1000000
-#define bOFDMEn 0x2000000
-
-#define bOFDMRxADCPhase 0x10000 /* Useless now */
-#define bOFDMTxDACPhase 0x40000
-#define bXATxAGC 0x3f
-#define bXBTxAGC 0xf00 /* Reg 80c rFPGA0_TxGainStage */
-#define bXCTxAGC 0xf000
-#define bXDTxAGC 0xf0000
-
-#define bPAStart 0xf0000000 /* Useless now */
-#define bTRStart 0x00f00000
-#define bRFStart 0x0000f000
-#define bBBStart 0x000000f0
-#define bBBCCKStart 0x0000000f
-#define bPAEnd 0xf /* Reg0x814 */
-#define bTREnd 0x0f000000
-#define bRFEnd 0x000f0000
-#define bCCAMask 0x000000f0 /* T2R */
-#define bR2RCCAMask 0x00000f00
-#define bHSSI_R2TDelay 0xf8000000
-#define bHSSI_T2RDelay 0xf80000
-#define bContTxHSSI 0x400 /* change gain at continue Tx */
-#define bIGFromCCK 0x200
-#define bAGCAddress 0x3f
-#define bRxHPTx 0x7000
-#define bRxHPT2R 0x38000
-#define bRxHPCCKIni 0xc0000
-#define bAGCTxCode 0xc00000
-#define bAGCRxCode 0x300000
-#define b3WireDataLength 0x800 /* Reg 0x820~84f rFPGA0_XA_HSSIParm1 */
-#define b3WireAddressLength 0x400
-#define b3WireRFPowerDown 0x1 /* Useless now */
-#define b5GPAPEPolarity 0x40000000
-#define b2GPAPEPolarity 0x80000000
-#define bRFSW_TxDefaultAnt 0x3
-#define bRFSW_TxOptionAnt 0x30
-#define bRFSW_RxDefaultAnt 0x300
-#define bRFSW_RxOptionAnt 0x3000
-#define bRFSI_3WireData 0x1
-#define bRFSI_3WireClock 0x2
-#define bRFSI_3WireLoad 0x4
-#define bRFSI_3WireRW 0x8
-#define bRFSI_3Wire 0xf
-#define bRFSI_RFENV 0x10 /* Reg 0x870 rFPGA0_XAB_RFInterfaceSW */
-#define bRFSI_TRSW 0x20 /* Useless now */
-#define bRFSI_TRSWB 0x40
-#define bRFSI_ANTSW 0x100
-#define bRFSI_ANTSWB 0x200
-#define bRFSI_PAPE 0x400
-#define bRFSI_PAPE5G 0x800
-#define bBandSelect 0x1
-#define bHTSIG2_GI 0x80
-#define bHTSIG2_Smoothing 0x01
-#define bHTSIG2_Sounding 0x02
-#define bHTSIG2_Aggreaton 0x08
-#define bHTSIG2_STBC 0x30
-#define bHTSIG2_AdvCoding 0x40
-#define bHTSIG2_NumOfHTLTF 0x300
-#define bHTSIG2_CRC8 0x3fc
-#define bHTSIG1_MCS 0x7f
-#define bHTSIG1_BandWidth 0x80
-#define bHTSIG1_HTLength 0xffff
-#define bLSIG_Rate 0xf
-#define bLSIG_Reserved 0x10
-#define bLSIG_Length 0x1fffe
-#define bLSIG_Parity 0x20
-#define bCCKRxPhase 0x4
-#define bLSSIReadAddress 0x7f800000 /* T65 RF */
-#define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */
-#define bLSSIReadBackData 0xfffff /* T65 RF */
-#define bLSSIReadOKFlag 0x1000 /* Useless now */
-#define bCCKSampleRate 0x8 /*0: 44MHz, 1:88MHz*/
-#define bRegulator0Standby 0x1
-#define bRegulatorPLLStandby 0x2
-#define bRegulator1Standby 0x4
-#define bPLLPowerUp 0x8
-#define bDPLLPowerUp 0x10
-#define bDA10PowerUp 0x20
-#define bAD7PowerUp 0x200
-#define bDA6PowerUp 0x2000
-#define bXtalPowerUp 0x4000
-#define b40MDClkPowerUP 0x8000
-#define bDA6DebugMode 0x20000
-#define bDA6Swing 0x380000
-
-/* Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */
-#define bADClkPhase 0x4000000
-
-#define b80MClkDelay 0x18000000 /* Useless */
-#define bAFEWatchDogEnable 0x20000000
-
-/* Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap */
-#define bXtalCap01 0xc0000000
-#define bXtalCap23 0x3
-#define bXtalCap92x 0x0f000000
-#define bXtalCap 0x0f000000
-#define bIntDifClkEnable 0x400 /* Useless */
-#define bExtSigClkEnable 0x800
-#define bBandgapMbiasPowerUp 0x10000
-#define bAD11SHGain 0xc0000
-#define bAD11InputRange 0x700000
-#define bAD11OPCurrent 0x3800000
-#define bIPathLoopback 0x4000000
-#define bQPathLoopback 0x8000000
-#define bAFELoopback 0x10000000
-#define bDA10Swing 0x7e0
-#define bDA10Reverse 0x800
-#define bDAClkSource 0x1000
-#define bAD7InputRange 0x6000
-#define bAD7Gain 0x38000
-#define bAD7OutputCMMode 0x40000
-#define bAD7InputCMMode 0x380000
-#define bAD7Current 0xc00000
-#define bRegulatorAdjust 0x7000000
-#define bAD11PowerUpAtTx 0x1
-#define bDA10PSAtTx 0x10
-#define bAD11PowerUpAtRx 0x100
-#define bDA10PSAtRx 0x1000
-#define bCCKRxAGCFormat 0x200
-#define bPSDFFTSamplepPoint 0xc000
-#define bPSDAverageNum 0x3000
-#define bIQPathControl 0xc00
-#define bPSDFreq 0x3ff
-#define bPSDAntennaPath 0x30
-#define bPSDIQSwitch 0x40
-#define bPSDRxTrigger 0x400000
-#define bPSDTxTrigger 0x80000000
-#define bPSDSineToneScale 0x7f000000
-#define bPSDReport 0xffff
-
-/* 3. Page9(0x900) */
-#define bOFDMTxSC 0x30000000 /* Useless */
-#define bCCKTxOn 0x1
-#define bOFDMTxOn 0x2
-#define bDebugPage 0xfff /* reset debug page and HWord, LWord */
-#define bDebugItem 0xff /* reset debug page and LWord */
-#define bAntL 0x10
-#define bAntNonHT 0x100
-#define bAntHT1 0x1000
-#define bAntHT2 0x10000
-#define bAntHT1S1 0x100000
-#define bAntNonHTS1 0x1000000
-
-/* 4. PageA(0xA00) */
-#define bCCKBBMode 0x3 /* Useless */
-#define bCCKTxPowerSaving 0x80
-#define bCCKRxPowerSaving 0x40
-
-#define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 switch*/
-#define bCCKScramble 0x8 /* Useless */
-#define bCCKAntDiversity 0x8000
-#define bCCKCarrierRecovery 0x4000
-#define bCCKTxRate 0x3000
-#define bCCKDCCancel 0x0800
-#define bCCKISICancel 0x0400
-#define bCCKMatchFilter 0x0200
-#define bCCKEqualizer 0x0100
-#define bCCKPreambleDetect 0x800000
-#define bCCKFastFalseCCA 0x400000
-#define bCCKChEstStart 0x300000
-#define bCCKCCACount 0x080000
-#define bCCKcs_lim 0x070000
-#define bCCKBistMode 0x80000000
-#define bCCKCCAMask 0x40000000
-#define bCCKTxDACPhase 0x4
-#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */
-#define bCCKr_cp_mode0 0x0100
-#define bCCKTxDCOffset 0xf0
-#define bCCKRxDCOffset 0xf
-#define bCCKCCAMode 0xc000
-#define bCCKFalseCS_lim 0x3f00
-#define bCCKCS_ratio 0xc00000
-#define bCCKCorgBit_sel 0x300000
-#define bCCKPD_lim 0x0f0000
-#define bCCKNewCCA 0x80000000
-#define bCCKRxHPofIG 0x8000
-#define bCCKRxIG 0x7f00
-#define bCCKLNAPolarity 0x800000
-#define bCCKRx1stGain 0x7f0000
-#define bCCKRFExtend 0x20000000 /* CCK Rx initial gain polarity */
-#define bCCKRxAGCSatLevel 0x1f000000
-#define bCCKRxAGCSatCount 0xe0
-#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */
-#define bCCKFixedRxAGC 0x8000
-#define bCCKAntennaPolarity 0x2000
-#define bCCKTxFilterType 0x0c00
-#define bCCKRxAGCReportType 0x0300
-#define bCCKRxDAGCEn 0x80000000
-#define bCCKRxDAGCPeriod 0x20000000
-#define bCCKRxDAGCSatLevel 0x1f000000
-#define bCCKTimingRecovery 0x800000
-#define bCCKTxC0 0x3f0000
-#define bCCKTxC1 0x3f000000
-#define bCCKTxC2 0x3f
-#define bCCKTxC3 0x3f00
-#define bCCKTxC4 0x3f0000
-#define bCCKTxC5 0x3f000000
-#define bCCKTxC6 0x3f
-#define bCCKTxC7 0x3f00
-#define bCCKDebugPort 0xff0000
-#define bCCKDACDebug 0x0f000000
-#define bCCKFalseAlarmEnable 0x8000
-#define bCCKFalseAlarmRead 0x4000
-#define bCCKTRSSI 0x7f
-#define bCCKRxAGCReport 0xfe
-#define bCCKRxReport_AntSel 0x80000000
-#define bCCKRxReport_MFOff 0x40000000
-#define bCCKRxRxReport_SQLoss 0x20000000
-#define bCCKRxReport_Pktloss 0x10000000
-#define bCCKRxReport_Lockedbit 0x08000000
-#define bCCKRxReport_RateError 0x04000000
-#define bCCKRxReport_RxRate 0x03000000
-#define bCCKRxFACounterLower 0xff
-#define bCCKRxFACounterUpper 0xff000000
-#define bCCKRxHPAGCStart 0xe000
-#define bCCKRxHPAGCFinal 0x1c00
-#define bCCKRxFalseAlarmEnable 0x8000
-#define bCCKFACounterFreeze 0x4000
-#define bCCKTxPathSel 0x10000000
-#define bCCKDefaultRxPath 0xc000000
-#define bCCKOptionRxPath 0x3000000
-
-/* 5. PageC(0xC00) */
-#define bNumOfSTF 0x3 /* Useless */
-#define bShift_L 0xc0
-#define bGI_TH 0xc
-#define bRxPathA 0x1
-#define bRxPathB 0x2
-#define bRxPathC 0x4
-#define bRxPathD 0x8
-#define bTxPathA 0x1
-#define bTxPathB 0x2
-#define bTxPathC 0x4
-#define bTxPathD 0x8
-#define bTRSSIFreq 0x200
-#define bADCBackoff 0x3000
-#define bDFIRBackoff 0xc000
-#define bTRSSILatchPhase 0x10000
-#define bRxIDCOffset 0xff
-#define bRxQDCOffset 0xff00
-#define bRxDFIRMode 0x1800000
-#define bRxDCNFType 0xe000000
-#define bRXIQImb_A 0x3ff
-#define bRXIQImb_B 0xfc00
-#define bRXIQImb_C 0x3f0000
-#define bRXIQImb_D 0xffc00000
-#define bDC_dc_Notch 0x60000
-#define bRxNBINotch 0x1f000000
-#define bPD_TH 0xf
-#define bPD_TH_Opt2 0xc000
-#define bPWED_TH 0x700
-#define bIfMF_Win_L 0x800
-#define bPD_Option 0x1000
-#define bMF_Win_L 0xe000
-#define bBW_Search_L 0x30000
-#define bwin_enh_L 0xc0000
-#define bBW_TH 0x700000
-#define bED_TH2 0x3800000
-#define bBW_option 0x4000000
-#define bRatio_TH 0x18000000
-#define bWindow_L 0xe0000000
-#define bSBD_Option 0x1
-#define bFrame_TH 0x1c
-#define bFS_Option 0x60
-#define bDC_Slope_check 0x80
-#define bFGuard_Counter_DC_L 0xe00
-#define bFrame_Weight_Short 0x7000
-#define bSub_Tune 0xe00000
-#define bFrame_DC_Length 0xe000000
-#define bSBD_start_offset 0x30000000
-#define bFrame_TH_2 0x7
-#define bFrame_GI2_TH 0x38
-#define bGI2_Sync_en 0x40
-#define bSarch_Short_Early 0x300
-#define bSarch_Short_Late 0xc00
-#define bSarch_GI2_Late 0x70000
-#define bCFOAntSum 0x1
-#define bCFOAcc 0x2
-#define bCFOStartOffset 0xc
-#define bCFOLookBack 0x70
-#define bCFOSumWeight 0x80
-#define bDAGCEnable 0x10000
-#define bTXIQImb_A 0x3ff
-#define bTXIQImb_B 0xfc00
-#define bTXIQImb_C 0x3f0000
-#define bTXIQImb_D 0xffc00000
-#define bTxIDCOffset 0xff
-#define bTxQDCOffset 0xff00
-#define bTxDFIRMode 0x10000
-#define bTxPesudoNoiseOn 0x4000000
-#define bTxPesudoNoise_A 0xff
-#define bTxPesudoNoise_B 0xff00
-#define bTxPesudoNoise_C 0xff0000
-#define bTxPesudoNoise_D 0xff000000
-#define bCCADropOption 0x20000
-#define bCCADropThres 0xfff00000
-#define bEDCCA_H 0xf
-#define bEDCCA_L 0xf0
-#define bLambda_ED 0x300
-#define bRxInitialGain 0x7f
-#define bRxAntDivEn 0x80
-#define bRxAGCAddressForLNA 0x7f00
-#define bRxHighPowerFlow 0x8000
-#define bRxAGCFreezeThres 0xc0000
-#define bRxFreezeStep_AGC1 0x300000
-#define bRxFreezeStep_AGC2 0xc00000
-#define bRxFreezeStep_AGC3 0x3000000
-#define bRxFreezeStep_AGC0 0xc000000
-#define bRxRssi_Cmp_En 0x10000000
-#define bRxQuickAGCEn 0x20000000
-#define bRxAGCFreezeThresMode 0x40000000
-#define bRxOverFlowCheckType 0x80000000
-#define bRxAGCShift 0x7f
-#define bTRSW_Tri_Only 0x80
-#define bPowerThres 0x300
-#define bRxAGCEn 0x1
-#define bRxAGCTogetherEn 0x2
-#define bRxAGCMin 0x4
-#define bRxHP_Ini 0x7
-#define bRxHP_TRLNA 0x70
-#define bRxHP_RSSI 0x700
-#define bRxHP_BBP1 0x7000
-#define bRxHP_BBP2 0x70000
-#define bRxHP_BBP3 0x700000
-#define bRSSI_H 0x7f0000 /* the threshold for high power */
-#define bRSSI_Gen 0x7f000000 /* the threshold for ant divers */
-#define bRxSettle_TRSW 0x7
-#define bRxSettle_LNA 0x38
-#define bRxSettle_RSSI 0x1c0
-#define bRxSettle_BBP 0xe00
-#define bRxSettle_RxHP 0x7000
-#define bRxSettle_AntSW_RSSI 0x38000
-#define bRxSettle_AntSW 0xc0000
-#define bRxProcessTime_DAGC 0x300000
-#define bRxSettle_HSSI 0x400000
-#define bRxProcessTime_BBPPW 0x800000
-#define bRxAntennaPowerShift 0x3000000
-#define bRSSITableSelect 0xc000000
-#define bRxHP_Final 0x7000000
-#define bRxHTSettle_BBP 0x7
-#define bRxHTSettle_HSSI 0x8
-#define bRxHTSettle_RxHP 0x70
-#define bRxHTSettle_BBPPW 0x80
-#define bRxHTSettle_Idle 0x300
-#define bRxHTSettle_Reserved 0x1c00
-#define bRxHTRxHPEn 0x8000
-#define bRxHTAGCFreezeThres 0x30000
-#define bRxHTAGCTogetherEn 0x40000
-#define bRxHTAGCMin 0x80000
-#define bRxHTAGCEn 0x100000
-#define bRxHTDAGCEn 0x200000
-#define bRxHTRxHP_BBP 0x1c00000
-#define bRxHTRxHP_Final 0xe0000000
-#define bRxPWRatioTH 0x3
-#define bRxPWRatioEn 0x4
-#define bRxMFHold 0x3800
-#define bRxPD_Delay_TH1 0x38
-#define bRxPD_Delay_TH2 0x1c0
-#define bRxPD_DC_COUNT_MAX 0x600
-#define bRxPD_Delay_TH 0x8000
-#define bRxProcess_Delay 0xf0000
-#define bRxSearchrange_GI2_Early 0x700000
-#define bRxFrame_Guard_Counter_L 0x3800000
-#define bRxSGI_Guard_L 0xc000000
-#define bRxSGI_Search_L 0x30000000
-#define bRxSGI_TH 0xc0000000
-#define bDFSCnt0 0xff
-#define bDFSCnt1 0xff00
-#define bDFSFlag 0xf0000
-#define bMFWeightSum 0x300000
-#define bMinIdxTH 0x7f000000
-#define bDAFormat 0x40000
-#define bTxChEmuEnable 0x01000000
-#define bTRSWIsolation_A 0x7f
-#define bTRSWIsolation_B 0x7f00
-#define bTRSWIsolation_C 0x7f0000
-#define bTRSWIsolation_D 0x7f000000
-#define bExtLNAGain 0x7c00
-
-/* 6. PageE(0xE00) */
-#define bSTBCEn 0x4 /* Useless */
-#define bAntennaMapping 0x10
-#define bNss 0x20
-#define bCFOAntSumD 0x200
-#define bPHYCounterReset 0x8000000
-#define bCFOReportGet 0x4000000
-#define bOFDMContinueTx 0x10000000
-#define bOFDMSingleCarrier 0x20000000
-#define bOFDMSingleTone 0x40000000
-#define bHTDetect 0x100
-#define bCFOEn 0x10000
-#define bCFOValue 0xfff00000
-#define bSigTone_Re 0x3f
-#define bSigTone_Im 0x7f00
-#define bCounter_CCA 0xffff
-#define bCounter_ParityFail 0xffff0000
-#define bCounter_RateIllegal 0xffff
-#define bCounter_CRC8Fail 0xffff0000
-#define bCounter_MCSNoSupport 0xffff
-#define bCounter_FastSync 0xffff
-#define bShortCFO 0xfff
-#define bShortCFOTLength 12 /* total */
-#define bShortCFOFLength 11 /* fraction */
-#define bLongCFO 0x7ff
-#define bLongCFOTLength 11
-#define bLongCFOFLength 11
-#define bTailCFO 0x1fff
-#define bTailCFOTLength 13
-#define bTailCFOFLength 12
-#define bmax_en_pwdB 0xffff
-#define bCC_power_dB 0xffff0000
-#define bnoise_pwdB 0xffff
-#define bPowerMeasTLength 10
-#define bPowerMeasFLength 3
-#define bRx_HT_BW 0x1
-#define bRxSC 0x6
-#define bRx_HT 0x8
-#define bNB_intf_det_on 0x1
-#define bIntf_win_len_cfg 0x30
-#define bNB_Intf_TH_cfg 0x1c0
-#define bRFGain 0x3f
-#define bTableSel 0x40
-#define bTRSW 0x80
-#define bRxSNR_A 0xff
-#define bRxSNR_B 0xff00
-#define bRxSNR_C 0xff0000
-#define bRxSNR_D 0xff000000
-#define bSNREVMTLength 8
-#define bSNREVMFLength 1
-#define bCSI1st 0xff
-#define bCSI2nd 0xff00
-#define bRxEVM1st 0xff0000
-#define bRxEVM2nd 0xff000000
-#define bSIGEVM 0xff
-#define bPWDB 0xff00
-#define bSGIEN 0x10000
-
-#define bSFactorQAM1 0xf /* Useless */
-#define bSFactorQAM2 0xf0
-#define bSFactorQAM3 0xf00
-#define bSFactorQAM4 0xf000
-#define bSFactorQAM5 0xf0000
-#define bSFactorQAM6 0xf0000
-#define bSFactorQAM7 0xf00000
-#define bSFactorQAM8 0xf000000
-#define bSFactorQAM9 0xf0000000
-#define bCSIScheme 0x100000
-
-#define bNoiseLvlTopSet 0x3 /* Useless */
-#define bChSmooth 0x4
-#define bChSmoothCfg1 0x38
-#define bChSmoothCfg2 0x1c0
-#define bChSmoothCfg3 0xe00
-#define bChSmoothCfg4 0x7000
-#define bMRCMode 0x800000
-#define bTHEVMCfg 0x7000000
-
-#define bLoopFitType 0x1 /* Useless */
-#define bUpdCFO 0x40
-#define bUpdCFOOffData 0x80
-#define bAdvUpdCFO 0x100
-#define bAdvTimeCtrl 0x800
-#define bUpdClko 0x1000
-#define bFC 0x6000
-#define bTrackingMode 0x8000
-#define bPhCmpEnable 0x10000
-#define bUpdClkoLTF 0x20000
-#define bComChCFO 0x40000
-#define bCSIEstiMode 0x80000
-#define bAdvUpdEqz 0x100000
-#define bUChCfg 0x7000000
-#define bUpdEqz 0x8000000
-
-#define bTxAGCRate18_06 0x7f7f7f7f /* Useless */
-#define bTxAGCRate54_24 0x7f7f7f7f
-#define bTxAGCRateMCS32 0x7f
-#define bTxAGCRateCCK 0x7f00
-#define bTxAGCRateMCS3_MCS0 0x7f7f7f7f
-#define bTxAGCRateMCS7_MCS4 0x7f7f7f7f
-#define bTxAGCRateMCS11_MCS8 0x7f7f7f7f
-#define bTxAGCRateMCS15_MCS12 0x7f7f7f7f
-
-/* Rx Pseduo noise */
-#define bRxPesudoNoiseOn 0x20000000 /* Useless */
-#define bRxPesudoNoise_A 0xff
-#define bRxPesudoNoise_B 0xff00
-#define bRxPesudoNoise_C 0xff0000
-#define bRxPesudoNoise_D 0xff000000
-#define bPesudoNoiseState_A 0xffff
-#define bPesudoNoiseState_B 0xffff0000
-#define bPesudoNoiseState_C 0xffff
-#define bPesudoNoiseState_D 0xffff0000
-
-/* 7. RF Register
- * Zebra1
- */
-#define bZebra1_HSSIEnable 0x8 /* Useless */
-#define bZebra1_TRxControl 0xc00
-#define bZebra1_TRxGainSetting 0x07f
-#define bZebra1_RxCorner 0xc00
-#define bZebra1_TxChargePump 0x38
-#define bZebra1_RxChargePump 0x7
-#define bZebra1_ChannelNum 0xf80
-#define bZebra1_TxLPFBW 0x400
-#define bZebra1_RxLPFBW 0x600
-
-/*Zebra4 */
-#define bRTL8256RegModeCtrl1 0x100 /* Useless */
-#define bRTL8256RegModeCtrl0 0x40
-#define bRTL8256_TxLPFBW 0x18
-#define bRTL8256_RxLPFBW 0x600
-
-/* RTL8258 */
-#define bRTL8258_TxLPFBW 0xc /* Useless */
-#define bRTL8258_RxLPFBW 0xc00
-#define bRTL8258_RSSILPFBW 0xc0
-
-/*
- * Other Definition
- */
-
-/* byte endable for sb_write */
-#define bByte0 0x1 /* Useless */
-#define bByte1 0x2
-#define bByte2 0x4
-#define bByte3 0x8
-#define bWord0 0x3
-#define bWord1 0xc
-#define bDWord 0xf
-
-/* for PutRegsetting & GetRegSetting BitMask */
-#define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */
-#define bMaskByte1 0xff00
-#define bMaskByte2 0xff0000
-#define bMaskByte3 0xff000000
-#define bMaskHWord 0xffff0000
-#define bMaskLWord 0x0000ffff
-#define bMaskDWord 0xffffffff
-
-/* for PutRFRegsetting & GetRFRegSetting BitMask */
-#define bRFRegOffsetMask 0xfffff
-#define bEnable 0x1 /* Useless */
-#define bDisable 0x0
-
-#define LeftAntenna 0x0 /* Useless */
-#define RightAntenna 0x1
-
-#define tCheckTxStatus 500 /* 500ms Useless */
-#define tUpdateRxCounter 100 /* 100ms */
-
-#define rateCCK 0 /* Useless */
-#define rateOFDM 1
-#define rateHT 2
-
-/* define Register-End */
-#define bPMAC_End 0x1ff /* Useless */
-#define bFPGAPHY0_End 0x8ff
-#define bFPGAPHY1_End 0x9ff
-#define bCCKPHY0_End 0xaff
-#define bOFDMPHY0_End 0xcff
-#define bOFDMPHY1_End 0xdff
-
-#define bPMACControl 0x0 /* Useless */
-#define bWMACControl 0x1
-#define bWNICControl 0x2
-
-#define ANTENNA_A 0x1 /* Useless */
-#define ANTENNA_B 0x2
-#define ANTENNA_AB 0x3 /* ANTENNA_A |ANTENNA_B */
-
-#define ANTENNA_C 0x4
-#define ANTENNA_D 0x8
-
-/* accept all physical address */
-#define RCR_AAP BIT(0)
-#define RCR_APM BIT(1) /* accept physical match */
-#define RCR_AM BIT(2) /* accept multicast */
-#define RCR_AB BIT(3) /* accept broadcast */
-#define RCR_ACRC32 BIT(5) /* accept error packet */
-#define RCR_9356SEL BIT(6)
-#define RCR_AICV BIT(12) /* Accept ICV error packet */
-#define RCR_RXFTH0 (BIT(13)|BIT(14)|BIT(15)) /* Rx FIFO threshold */
-#define RCR_ADF BIT(18) /* Accept Data(frame type) frame */
-#define RCR_ACF BIT(19) /* Accept control frame */
-#define RCR_AMF BIT(20) /* Accept management frame */
-#define RCR_ADD3 BIT(21)
-#define RCR_APWRMGT BIT(22) /* Accept power management packet */
-#define RCR_CBSSID BIT(23) /* Accept BSSID match packet */
-#define RCR_ENMARP BIT(28) /* enable mac auto reset phy */
-#define RCR_EnCS1 BIT(29) /* enable carrier sense method 1 */
-#define RCR_EnCS2 BIT(30) /* enable carrier sense method 2 */
-/* Rx Early mode is performed for packet size greater than 1536 */
-#define RCR_OnlyErlPkt BIT(31)
-
-/*--------------------------Define Parameters-------------------------------*/
-
-#endif /*__INC_HAL8192SPHYREG_H */
-
diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c
deleted file mode 100644
index cd6d9ff0bebc..000000000000
--- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c
+++ /dev/null
@@ -1,234 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_pwrctrl.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_PWRCTRL_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "osdep_intf.h"
-
-#define RTL8712_SDIO_LOCAL_BASE 0X10100000
-#define SDIO_HCPWM (RTL8712_SDIO_LOCAL_BASE + 0x0081)
-
-void r8712_set_rpwm(struct _adapter *padapter, u8 val8)
-{
- u8 rpwm;
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-
- if (pwrpriv->rpwm == val8) {
- if (pwrpriv->rpwm_retry == 0)
- return;
- }
- if (padapter->driver_stopped || padapter->surprise_removed)
- return;
- rpwm = val8 | pwrpriv->tog;
- switch (val8) {
- case PS_STATE_S1:
- pwrpriv->cpwm = val8;
- break;
- case PS_STATE_S2:/* only for USB normal powersave mode use,
- * temp mark some code.
- */
- case PS_STATE_S3:
- case PS_STATE_S4:
- pwrpriv->cpwm = val8;
- break;
- default:
- break;
- }
- pwrpriv->rpwm_retry = 0;
- pwrpriv->rpwm = val8;
- r8712_write8(padapter, 0x1025FE58, rpwm);
- pwrpriv->tog += 0x80;
-}
-
-void r8712_set_ps_mode(struct _adapter *padapter, uint ps_mode, uint smart_ps)
-{
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-
- if (ps_mode > PM_Card_Disable)
- return;
- /* if driver is in active state, we dont need set smart_ps.*/
- if (ps_mode == PS_MODE_ACTIVE)
- smart_ps = 0;
- if ((pwrpriv->pwr_mode != ps_mode) || (pwrpriv->smart_ps != smart_ps)) {
- if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
- pwrpriv->bSleep = true;
- else
- pwrpriv->bSleep = false;
- pwrpriv->pwr_mode = ps_mode;
- pwrpriv->smart_ps = smart_ps;
- schedule_work(&pwrpriv->SetPSModeWorkItem);
- }
-}
-
-/*
- * Caller:ISR handler...
- *
- * This will be called when CPWM interrupt is up.
- *
- * using to update cpwn of drv; and drv will make a decision to up or
- * down pwr level
- */
-void r8712_cpwm_int_hdl(struct _adapter *padapter,
- struct reportpwrstate_parm *preportpwrstate)
-{
- struct pwrctrl_priv *pwrpriv = &(padapter->pwrctrlpriv);
- struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
-
- if (pwrpriv->cpwm_tog == ((preportpwrstate->state) & 0x80))
- return;
- del_timer(&padapter->pwrctrlpriv.rpwm_check_timer);
- mutex_lock(&pwrpriv->mutex_lock);
- pwrpriv->cpwm = (preportpwrstate->state) & 0xf;
- if (pwrpriv->cpwm >= PS_STATE_S2) {
- if (pwrpriv->alives & CMD_ALIVE)
- complete(&(pcmdpriv->cmd_queue_comp));
- }
- pwrpriv->cpwm_tog = (preportpwrstate->state) & 0x80;
- mutex_unlock(&pwrpriv->mutex_lock);
-}
-
-static inline void register_task_alive(struct pwrctrl_priv *pwrctrl, uint tag)
-{
- pwrctrl->alives |= tag;
-}
-
-static inline void unregister_task_alive(struct pwrctrl_priv *pwrctrl, uint tag)
-{
- if (pwrctrl->alives & tag)
- pwrctrl->alives ^= tag;
-}
-
-static void _rpwm_check_handler (struct _adapter *padapter)
-{
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-
- if (padapter->driver_stopped || padapter->surprise_removed)
- return;
- if (pwrpriv->cpwm != pwrpriv->rpwm)
- schedule_work(&pwrpriv->rpwm_workitem);
-}
-
-static void SetPSModeWorkItemCallback(struct work_struct *work)
-{
- struct pwrctrl_priv *pwrpriv = container_of(work,
- struct pwrctrl_priv, SetPSModeWorkItem);
- struct _adapter *padapter = container_of(pwrpriv,
- struct _adapter, pwrctrlpriv);
- if (!pwrpriv->bSleep) {
- mutex_lock(&pwrpriv->mutex_lock);
- if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
- r8712_set_rpwm(padapter, PS_STATE_S4);
- mutex_unlock(&pwrpriv->mutex_lock);
- }
-}
-
-static void rpwm_workitem_callback(struct work_struct *work)
-{
- struct pwrctrl_priv *pwrpriv = container_of(work,
- struct pwrctrl_priv, rpwm_workitem);
- struct _adapter *padapter = container_of(pwrpriv,
- struct _adapter, pwrctrlpriv);
- if (pwrpriv->cpwm != pwrpriv->rpwm) {
- mutex_lock(&pwrpriv->mutex_lock);
- r8712_read8(padapter, SDIO_HCPWM);
- pwrpriv->rpwm_retry = 1;
- r8712_set_rpwm(padapter, pwrpriv->rpwm);
- mutex_unlock(&pwrpriv->mutex_lock);
- }
-}
-
-static void rpwm_check_handler (struct timer_list *t)
-{
- struct _adapter *adapter =
- from_timer(adapter, t, pwrctrlpriv.rpwm_check_timer);
-
- _rpwm_check_handler(adapter);
-}
-
-void r8712_init_pwrctrl_priv(struct _adapter *padapter)
-{
- struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
-
- memset((unsigned char *)pwrctrlpriv, 0, sizeof(struct pwrctrl_priv));
- mutex_init(&pwrctrlpriv->mutex_lock);
- pwrctrlpriv->cpwm = PS_STATE_S4;
- pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
- pwrctrlpriv->smart_ps = 0;
- pwrctrlpriv->tog = 0x80;
-/* clear RPWM to ensure driver and fw back to initial state. */
- r8712_write8(padapter, 0x1025FE58, 0);
- INIT_WORK(&pwrctrlpriv->SetPSModeWorkItem, SetPSModeWorkItemCallback);
- INIT_WORK(&pwrctrlpriv->rpwm_workitem, rpwm_workitem_callback);
- timer_setup(&pwrctrlpriv->rpwm_check_timer, rpwm_check_handler, 0);
-}
-
-/*
- * Caller: r8712_cmd_thread
- * Check if the fw_pwrstate is okay for issuing cmd.
- * If not (cpwm should be is less than P2 state), then the sub-routine
- * will raise the cpwm to be greater than or equal to P2.
- * Calling Context: Passive
- * Return Value:
- * 0: r8712_cmd_thread can issue cmds to firmware afterwards.
- * -EINVAL: r8712_cmd_thread can not do anything.
- */
-int r8712_register_cmd_alive(struct _adapter *padapter)
-{
- int res = 0;
- struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv;
-
- mutex_lock(&pwrctrl->mutex_lock);
- register_task_alive(pwrctrl, CMD_ALIVE);
- if (pwrctrl->cpwm < PS_STATE_S2) {
- r8712_set_rpwm(padapter, PS_STATE_S3);
- res = -EINVAL;
- }
- mutex_unlock(&pwrctrl->mutex_lock);
- return res;
-}
-
-/*
- * Caller: ISR
- * If ISR's txdone,
- * No more pkts for TX,
- * Then driver shall call this fun. to power down firmware again.
- */
-void r8712_unregister_cmd_alive(struct _adapter *padapter)
-{
- struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv;
-
- mutex_lock(&pwrctrl->mutex_lock);
- unregister_task_alive(pwrctrl, CMD_ALIVE);
- if ((pwrctrl->cpwm > PS_STATE_S2) &&
- (pwrctrl->pwr_mode > PS_MODE_ACTIVE)) {
- if ((pwrctrl->alives == 0) &&
- (check_fwstate(&padapter->mlmepriv,
- _FW_UNDER_LINKING) != true)) {
- r8712_set_rpwm(padapter, PS_STATE_S0);
- }
- }
- mutex_unlock(&pwrctrl->mutex_lock);
-}
-
-void r8712_flush_rwctrl_works(struct _adapter *padapter)
-{
- struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv;
-
- flush_work(&pwrctrl->SetPSModeWorkItem);
- flush_work(&pwrctrl->rpwm_workitem);
-}
diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h
deleted file mode 100644
index b35b9c7920eb..000000000000
--- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_PWRCTRL_H_
-#define __RTL871X_PWRCTRL_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#define CMD_ALIVE BIT(2)
-
-enum Power_Mgnt {
- PS_MODE_ACTIVE = 0,
- PS_MODE_MIN,
- PS_MODE_MAX,
- PS_MODE_DTIM,
- PS_MODE_VOIP,
- PS_MODE_UAPSD_WMM,
- PS_MODE_UAPSD,
- PS_MODE_IBSS,
- PS_MODE_WWLAN,
- PM_Radio_Off,
- PM_Card_Disable,
- PS_MODE_NUM
-};
-
-/*
- * BIT[2:0] = HW state
- * BIT[3] = Protocol PS state, 0: register active state,
- * 1: register sleep state
- * BIT[4] = sub-state
- */
-
-#define PS_DPS BIT(0)
-#define PS_LCLK (PS_DPS)
-#define PS_RF_OFF BIT(1)
-#define PS_ALL_ON BIT(2)
-#define PS_ST_ACTIVE BIT(3)
-#define PS_LP BIT(4) /* low performance */
-
-#define PS_STATE_MASK (0x0F)
-#define PS_STATE_HW_MASK (0x07)
-#define PS_SEQ_MASK (0xc0)
-
-#define PS_STATE(x) (PS_STATE_MASK & (x))
-#define PS_STATE_HW(x) (PS_STATE_HW_MASK & (x))
-#define PS_SEQ(x) (PS_SEQ_MASK & (x))
-
-#define PS_STATE_S0 (PS_DPS)
-#define PS_STATE_S1 (PS_LCLK)
-#define PS_STATE_S2 (PS_RF_OFF)
-#define PS_STATE_S3 (PS_ALL_ON)
-#define PS_STATE_S4 ((PS_ST_ACTIVE) | (PS_ALL_ON))
-
-#define PS_IS_RF_ON(x) ((x) & (PS_ALL_ON))
-#define PS_IS_ACTIVE(x) ((x) & (PS_ST_ACTIVE))
-#define CLR_PS_STATE(x) ((x) = ((x) & (0xF0)))
-
-struct reportpwrstate_parm {
- unsigned char mode;
- unsigned char state; /* the CPWM value */
- unsigned short rsvd;
-};
-
-struct pwrctrl_priv {
- struct mutex mutex_lock;
- /*volatile*/ u8 rpwm; /* requested power state for fw */
- /* fw current power state. updated when 1. read from HCPWM or
- * 2. driver lowers power level
- */
- /*volatile*/ u8 cpwm;
- /*volatile*/ u8 tog; /* toggling */
- /*volatile*/ u8 cpwm_tog; /* toggling */
- /*volatile*/ u8 tgt_rpwm; /* wanted power state */
- uint pwr_mode;
- uint smart_ps;
- uint alives;
- uint ImrContent; /* used to store original imr. */
- uint bSleep; /* sleep -> active is different from active -> sleep. */
-
- struct work_struct SetPSModeWorkItem;
- struct work_struct rpwm_workitem;
- struct timer_list rpwm_check_timer;
- u8 rpwm_retry;
- uint bSetPSModeWorkItemInProgress;
-
- spinlock_t pnp_pwr_mgnt_lock;
- s32 pnp_current_pwr_state;
- u8 pnp_bstop_trx;
- u8 pnp_wwirp_pending;
-};
-
-void r8712_init_pwrctrl_priv(struct _adapter *adapter);
-int r8712_register_cmd_alive(struct _adapter *padapter);
-void r8712_unregister_cmd_alive(struct _adapter *padapter);
-void r8712_cpwm_int_hdl(struct _adapter *padapter,
- struct reportpwrstate_parm *preportpwrstate);
-void r8712_set_ps_mode(struct _adapter *padapter, uint ps_mode,
- uint smart_ps);
-void r8712_set_rpwm(struct _adapter *padapter, u8 val8);
-void r8712_flush_rwctrl_works(struct _adapter *padapter);
-
-#endif /* __RTL871X_PWRCTRL_H_ */
diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c
deleted file mode 100644
index 8a3566214af7..000000000000
--- a/drivers/staging/rtl8712/rtl871x_recv.c
+++ /dev/null
@@ -1,671 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_recv.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_RECV_C_
-
-#include <linux/ip.h>
-#include <linux/if_ether.h>
-#include <linux/etherdevice.h>
-#include <linux/ieee80211.h>
-#include <net/cfg80211.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "mlme_osdep.h"
-#include "ethernet.h"
-#include "usb_ops.h"
-#include "wifi.h"
-
-static const u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37};
-
-/* Datagram Delivery Protocol */
-static const u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3};
-
-void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)
-{
- memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv));
- spin_lock_init(&psta_recvpriv->lock);
- _init_queue(&psta_recvpriv->defrag_q);
-}
-
-int _r8712_init_recv_priv(struct recv_priv *precvpriv,
- struct _adapter *padapter)
-{
- int ret;
- sint i;
- union recv_frame *precvframe;
-
- memset((unsigned char *)precvpriv, 0, sizeof(struct recv_priv));
- spin_lock_init(&precvpriv->lock);
- _init_queue(&precvpriv->free_recv_queue);
- _init_queue(&precvpriv->recv_pending_queue);
- precvpriv->adapter = padapter;
- precvpriv->free_recvframe_cnt = NR_RECVFRAME;
- precvpriv->pallocated_frame_buf = kzalloc(NR_RECVFRAME *
- sizeof(union recv_frame) + RXFRAME_ALIGN_SZ,
- GFP_ATOMIC);
- if (!precvpriv->pallocated_frame_buf)
- return -ENOMEM;
- precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf +
- RXFRAME_ALIGN_SZ -
- ((addr_t)(precvpriv->pallocated_frame_buf) &
- (RXFRAME_ALIGN_SZ - 1));
- precvframe = (union recv_frame *)precvpriv->precv_frame_buf;
- for (i = 0; i < NR_RECVFRAME; i++) {
- INIT_LIST_HEAD(&(precvframe->u.list));
- list_add_tail(&(precvframe->u.list),
- &(precvpriv->free_recv_queue.queue));
- r8712_os_recv_resource_alloc(padapter, precvframe);
- precvframe->u.hdr.adapter = padapter;
- precvframe++;
- }
- precvpriv->rx_pending_cnt = 1;
- ret = r8712_init_recv_priv(precvpriv, padapter);
- if (ret)
- kfree(precvpriv->pallocated_frame_buf);
-
- return ret;
-}
-
-void _r8712_free_recv_priv(struct recv_priv *precvpriv)
-{
- kfree(precvpriv->pallocated_frame_buf);
- r8712_free_recv_priv(precvpriv);
-}
-
-union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue)
-{
- unsigned long irqL;
- union recv_frame *precvframe;
- struct _adapter *padapter;
- struct recv_priv *precvpriv;
-
- spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
- precvframe = list_first_entry_or_null(&pfree_recv_queue->queue,
- union recv_frame, u.hdr.list);
- if (precvframe) {
- list_del_init(&precvframe->u.hdr.list);
- padapter = precvframe->u.hdr.adapter;
- if (padapter) {
- precvpriv = &padapter->recvpriv;
- if (pfree_recv_queue == &precvpriv->free_recv_queue)
- precvpriv->free_recvframe_cnt--;
- }
- }
- spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL);
- return precvframe;
-}
-
-/*
- * caller : defrag; recvframe_chk_defrag in recv_thread (passive)
- * pframequeue: defrag_queue : will be accessed in recv_thread (passive)
- * using spin_lock to protect
- */
-void r8712_free_recvframe_queue(struct __queue *pframequeue,
- struct __queue *pfree_recv_queue)
-{
- union recv_frame *precvframe;
- struct list_head *plist, *phead;
-
- spin_lock(&pframequeue->lock);
- phead = &pframequeue->queue;
- plist = phead->next;
- while (!end_of_queue_search(phead, plist)) {
- precvframe = container_of(plist, union recv_frame, u.list);
- plist = plist->next;
- r8712_free_recvframe(precvframe, pfree_recv_queue);
- }
- spin_unlock(&pframequeue->lock);
-}
-
-sint r8712_recvframe_chkmic(struct _adapter *adapter,
- union recv_frame *precvframe)
-{
- sint i, res = _SUCCESS;
- u32 datalen;
- u8 miccode[8];
- u8 bmic_err = false;
- u8 *pframe, *payload, *pframemic;
- u8 *mickey, idx, *iv;
- struct sta_info *stainfo;
- struct rx_pkt_attrib *prxattrib = &precvframe->u.hdr.attrib;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
-
- stainfo = r8712_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]);
- if (prxattrib->encrypt == _TKIP_) {
- /* calculate mic code */
- if (stainfo) {
- if (is_multicast_ether_addr(prxattrib->ra)) {
- iv = precvframe->u.hdr.rx_data +
- prxattrib->hdrlen;
- idx = iv[3];
- mickey = &psecuritypriv->XGrprxmickey[(((idx >>
- 6) & 0x3)) - 1].skey[0];
- if (!psecuritypriv->binstallGrpkey)
- return _FAIL;
- } else {
- mickey = &stainfo->tkiprxmickey.skey[0];
- }
- /*icv_len included the mic code*/
- datalen = precvframe->u.hdr.len - prxattrib->hdrlen -
- prxattrib->iv_len - prxattrib->icv_len - 8;
- pframe = precvframe->u.hdr.rx_data;
- payload = pframe + prxattrib->hdrlen +
- prxattrib->iv_len;
- seccalctkipmic(mickey, pframe, payload, datalen,
- &miccode[0],
- (unsigned char)prxattrib->priority);
- pframemic = payload + datalen;
- bmic_err = false;
- for (i = 0; i < 8; i++) {
- if (miccode[i] != *(pframemic + i))
- bmic_err = true;
- }
- if (bmic_err) {
- if (prxattrib->bdecrypted)
- r8712_handle_tkip_mic_err(adapter,
- (u8)is_multicast_ether_addr(prxattrib->ra));
- res = _FAIL;
- } else {
- /* mic checked ok */
- if (!psecuritypriv->bcheck_grpkey &&
- is_multicast_ether_addr(prxattrib->ra))
- psecuritypriv->bcheck_grpkey = true;
- }
- recvframe_pull_tail(precvframe, 8);
- }
- }
- return res;
-}
-
-/* decrypt and set the ivlen,icvlen of the recv_frame */
-union recv_frame *r8712_decryptor(struct _adapter *padapter,
- union recv_frame *precv_frame)
-{
- struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- union recv_frame *return_packet = precv_frame;
-
- if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0) ||
- psecuritypriv->sw_decrypt)) {
- psecuritypriv->hw_decrypted = false;
- switch (prxattrib->encrypt) {
- case _WEP40_:
- case _WEP104_:
- r8712_wep_decrypt(padapter, (u8 *)precv_frame);
- break;
- case _TKIP_:
- r8712_tkip_decrypt(padapter, (u8 *)precv_frame);
- break;
- case _AES_:
- r8712_aes_decrypt(padapter, (u8 *)precv_frame);
- break;
- default:
- break;
- }
- } else if (prxattrib->bdecrypted == 1) {
- psecuritypriv->hw_decrypted = true;
- }
- return return_packet;
-}
-
-/*###set the security information in the recv_frame */
-union recv_frame *r8712_portctrl(struct _adapter *adapter,
- union recv_frame *precv_frame)
-{
- u8 *psta_addr, *ptr;
- uint auth_alg;
- struct recv_frame_hdr *pfhdr;
- struct sta_info *psta;
- struct sta_priv *pstapriv;
- union recv_frame *prtnframe;
- u16 ether_type;
-
- pstapriv = &adapter->stapriv;
- ptr = precv_frame->u.hdr.rx_data;
- pfhdr = &precv_frame->u.hdr;
- psta_addr = pfhdr->attrib.ta;
- psta = r8712_get_stainfo(pstapriv, psta_addr);
- auth_alg = adapter->securitypriv.AuthAlgrthm;
- if (auth_alg == 2) {
- /* get ether_type */
- ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
- ether_type = get_unaligned_be16(ptr);
-
- if (psta && psta->ieee8021x_blocked) {
- /* blocked
- * only accept EAPOL frame
- */
- if (ether_type == 0x888e) {
- prtnframe = precv_frame;
- } else {
- /*free this frame*/
- r8712_free_recvframe(precv_frame,
- &adapter->recvpriv.free_recv_queue);
- prtnframe = NULL;
- }
- } else {
- /* allowed
- * check decryption status, and decrypt the
- * frame if needed
- */
- prtnframe = precv_frame;
- /* check is the EAPOL frame or not (Rekey) */
- if (ether_type == 0x888e) {
- /* check Rekey */
- prtnframe = precv_frame;
- }
- }
- } else {
- prtnframe = precv_frame;
- }
- return prtnframe;
-}
-
-static sint recv_decache(union recv_frame *precv_frame, u8 bretry,
- struct stainfo_rxcache *prxcache)
-{
- sint tid = precv_frame->u.hdr.attrib.priority;
- u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num & 0xffff) << 4) |
- (precv_frame->u.hdr.attrib.frag_num & 0xf);
-
- if (tid > 15)
- return _FAIL;
- if (seq_ctrl == prxcache->tid_rxseq[tid])
- return _FAIL;
- prxcache->tid_rxseq[tid] = seq_ctrl;
- return _SUCCESS;
-}
-
-static sint sta2sta_data_frame(struct _adapter *adapter,
- union recv_frame *precv_frame,
- struct sta_info **psta)
-{
- u8 *ptr = precv_frame->u.hdr.rx_data;
- sint ret = _SUCCESS;
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- u8 *mybssid = get_bssid(pmlmepriv);
- u8 *myhwaddr = myid(&adapter->eeprompriv);
- u8 *sta_addr = NULL;
- bool bmcast = is_multicast_ether_addr(pattrib->dst);
-
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- /* filter packets that SA is myself or multicast or broadcast */
- if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN))
- return _FAIL;
- if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast))
- return _FAIL;
- if (is_zero_ether_addr(pattrib->bssid) ||
- is_zero_ether_addr(mybssid) ||
- (memcmp(pattrib->bssid, mybssid, ETH_ALEN)))
- return _FAIL;
- sta_addr = pattrib->src;
- } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- /* For Station mode, sa and bssid should always be BSSID,
- * and DA is my mac-address
- */
- if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN))
- return _FAIL;
- sta_addr = pattrib->bssid;
- } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- if (bmcast) {
- /* For AP mode, if DA == MCAST, then BSSID should
- * be also MCAST
- */
- if (!is_multicast_ether_addr(pattrib->bssid))
- return _FAIL;
- } else { /* not mc-frame */
- /* For AP mode, if DA is non-MCAST, then it must be
- * BSSID, and bssid == BSSID
- */
- if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN))
- return _FAIL;
- sta_addr = pattrib->src;
- }
- } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
- memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
- sta_addr = mybssid;
- } else {
- ret = _FAIL;
- }
- if (bmcast)
- *psta = r8712_get_bcmc_stainfo(adapter);
- else
- *psta = r8712_get_stainfo(pstapriv, sta_addr); /* get ap_info */
- if (!*psta) {
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
- adapter->mppriv.rx_pktloss++;
- return _FAIL;
- }
- return ret;
-}
-
-static sint ap2sta_data_frame(struct _adapter *adapter,
- union recv_frame *precv_frame,
- struct sta_info **psta)
-{
- u8 *ptr = precv_frame->u.hdr.rx_data;
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- u8 *mybssid = get_bssid(pmlmepriv);
- u8 *myhwaddr = myid(&adapter->eeprompriv);
- bool bmcast = is_multicast_ether_addr(pattrib->dst);
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
- check_fwstate(pmlmepriv, _FW_LINKED)) {
- /* if NULL-frame, drop packet */
- if ((GetFrameSubType(ptr)) == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC))
- return _FAIL;
- /* drop QoS-SubType Data, including QoS NULL,
- * excluding QoS-Data
- */
- if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) ==
- WIFI_QOS_DATA_TYPE) {
- if (GetFrameSubType(ptr) & (BIT(4) | BIT(5) | BIT(6)))
- return _FAIL;
- }
-
- /* filter packets that SA is myself or multicast or broadcast */
- if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN))
- return _FAIL;
-
- /* da should be for me */
- if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast))
- return _FAIL;
- /* check BSSID */
- if (is_zero_ether_addr(pattrib->bssid) ||
- is_zero_ether_addr(mybssid) ||
- (memcmp(pattrib->bssid, mybssid, ETH_ALEN)))
- return _FAIL;
- if (bmcast)
- *psta = r8712_get_bcmc_stainfo(adapter);
- else
- *psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
- if (!*psta)
- return _FAIL;
- } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) &&
- check_fwstate(pmlmepriv, _FW_LINKED)) {
- memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
- memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
- memcpy(pattrib->bssid, mybssid, ETH_ALEN);
- *psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
- if (!*psta)
- return _FAIL;
- } else {
- return _FAIL;
- }
- return _SUCCESS;
-}
-
-static sint sta2ap_data_frame(struct _adapter *adapter,
- union recv_frame *precv_frame,
- struct sta_info **psta)
-{
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- unsigned char *mybssid = get_bssid(pmlmepriv);
-
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- /* For AP mode, if DA is non-MCAST, then it must be BSSID,
- * and bssid == BSSID
- * For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR
- */
- if (memcmp(pattrib->bssid, mybssid, ETH_ALEN))
- return _FAIL;
- *psta = r8712_get_stainfo(pstapriv, pattrib->src);
- if (!*psta)
- return _FAIL;
- }
- return _SUCCESS;
-}
-
-static sint validate_recv_ctrl_frame(struct _adapter *adapter,
- union recv_frame *precv_frame)
-{
- return _FAIL;
-}
-
-static sint validate_recv_mgnt_frame(struct _adapter *adapter,
- union recv_frame *precv_frame)
-{
- return _FAIL;
-}
-
-static sint validate_recv_data_frame(struct _adapter *adapter,
- union recv_frame *precv_frame)
-{
- int res;
- u8 bretry;
- u8 *psa, *pda, *pbssid;
- struct sta_info *psta = NULL;
- u8 *ptr = precv_frame->u.hdr.rx_data;
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
-
- bretry = GetRetry(ptr);
- pda = ieee80211_get_DA((struct ieee80211_hdr *)ptr);
- psa = ieee80211_get_SA((struct ieee80211_hdr *)ptr);
- pbssid = get_hdr_bssid(ptr);
- if (!pbssid)
- return _FAIL;
- memcpy(pattrib->dst, pda, ETH_ALEN);
- memcpy(pattrib->src, psa, ETH_ALEN);
- memcpy(pattrib->bssid, pbssid, ETH_ALEN);
- switch (pattrib->to_fr_ds) {
- case 0:
- memcpy(pattrib->ra, pda, ETH_ALEN);
- memcpy(pattrib->ta, psa, ETH_ALEN);
- res = sta2sta_data_frame(adapter, precv_frame, &psta);
- break;
- case 1:
- memcpy(pattrib->ra, pda, ETH_ALEN);
- memcpy(pattrib->ta, pbssid, ETH_ALEN);
- res = ap2sta_data_frame(adapter, precv_frame, &psta);
- break;
- case 2:
- memcpy(pattrib->ra, pbssid, ETH_ALEN);
- memcpy(pattrib->ta, psa, ETH_ALEN);
- res = sta2ap_data_frame(adapter, precv_frame, &psta);
- break;
- case 3:
- memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
- return _FAIL;
- default:
- return _FAIL;
- }
- if (res == _FAIL)
- return _FAIL;
- if (!psta)
- return _FAIL;
- precv_frame->u.hdr.psta = psta;
- pattrib->amsdu = 0;
- /* parsing QC field */
- if (pattrib->qos == 1) {
- pattrib->priority = GetPriority((ptr + 24));
- pattrib->ack_policy = GetAckpolicy((ptr + 24));
- pattrib->amsdu = GetAMsdu((ptr + 24));
- pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 32 : 26;
- } else {
- pattrib->priority = 0;
- pattrib->hdrlen = (pattrib->to_fr_ds == 3) ? 30 : 24;
- }
-
- if (pattrib->order)/*HT-CTRL 11n*/
- pattrib->hdrlen += 4;
- precv_frame->u.hdr.preorder_ctrl =
- &psta->recvreorder_ctrl[pattrib->priority];
-
- /* decache, drop duplicate recv packets */
- if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) ==
- _FAIL)
- return _FAIL;
-
- if (pattrib->privacy) {
- GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt,
- is_multicast_ether_addr(pattrib->ra));
- SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len,
- pattrib->encrypt);
- } else {
- pattrib->encrypt = 0;
- pattrib->iv_len = pattrib->icv_len = 0;
- }
- return _SUCCESS;
-}
-
-sint r8712_validate_recv_frame(struct _adapter *adapter,
- union recv_frame *precv_frame)
-{
- /*shall check frame subtype, to / from ds, da, bssid */
- /*then call check if rx seq/frag. duplicated.*/
-
- u8 type;
- u8 subtype;
- sint retval = _SUCCESS;
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-
- u8 *ptr = precv_frame->u.hdr.rx_data;
- u8 ver = (unsigned char)(*ptr) & 0x3;
-
- /*add version chk*/
- if (ver != 0)
- return _FAIL;
- type = GetFrameType(ptr);
- subtype = GetFrameSubType(ptr); /*bit(7)~bit(2)*/
- pattrib->to_fr_ds = get_tofr_ds(ptr);
- pattrib->frag_num = GetFragNum(ptr);
- pattrib->seq_num = GetSequence(ptr);
- pattrib->pw_save = GetPwrMgt(ptr);
- pattrib->mfrag = GetMFrag(ptr);
- pattrib->mdata = GetMData(ptr);
- pattrib->privacy = GetPrivacy(ptr);
- pattrib->order = GetOrder(ptr);
- switch (type) {
- case IEEE80211_FTYPE_MGMT:
- retval = validate_recv_mgnt_frame(adapter, precv_frame);
- break;
- case IEEE80211_FTYPE_CTL:
- retval = validate_recv_ctrl_frame(adapter, precv_frame);
- break;
- case IEEE80211_FTYPE_DATA:
- pattrib->qos = (subtype & BIT(7)) ? 1 : 0;
- retval = validate_recv_data_frame(adapter, precv_frame);
- break;
- default:
- return _FAIL;
- }
- return retval;
-}
-
-int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe)
-{
- /*remove the wlanhdr and add the eth_hdr*/
- sint rmv_len;
- u16 len;
- u8 bsnaphdr;
- u8 *psnap_type;
- struct ieee80211_snap_hdr *psnap;
- struct _adapter *adapter = precvframe->u.hdr.adapter;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- u8 *ptr = precvframe->u.hdr.rx_data; /*point to frame_ctrl field*/
- struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
-
- if (pattrib->encrypt)
- recvframe_pull_tail(precvframe, pattrib->icv_len);
- psnap = (struct ieee80211_snap_hdr *)(ptr + pattrib->hdrlen +
- pattrib->iv_len);
- psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE;
- /* convert hdr + possible LLC headers into Ethernet header */
- if ((!memcmp(psnap, (void *)rfc1042_header, SNAP_SIZE) &&
- (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_IPX, 2)) &&
- (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_APPLETALK_AARP, 2))) ||
- !memcmp(psnap, (void *)bridge_tunnel_header, SNAP_SIZE)) {
- /* remove RFC1042 or Bridge-Tunnel encapsulation and
- * replace EtherType
- */
- bsnaphdr = true;
- } else {
- /* Leave Ethernet header part of hdr and full payload */
- bsnaphdr = false;
- }
- rmv_len = pattrib->hdrlen + pattrib->iv_len +
- (bsnaphdr ? SNAP_SIZE : 0);
- len = precvframe->u.hdr.len - rmv_len;
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- ptr += rmv_len;
- *ptr = 0x87;
- *(ptr + 1) = 0x12;
- /* append rx status for mp test packets */
- ptr = recvframe_pull(precvframe, (rmv_len -
- sizeof(struct ethhdr) + 2) - 24);
- if (!ptr)
- return -ENOMEM;
- memcpy(ptr, get_rxmem(precvframe), 24);
- ptr += 24;
- } else {
- ptr = recvframe_pull(precvframe, (rmv_len -
- sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0)));
- if (!ptr)
- return -ENOMEM;
- }
-
- memcpy(ptr, pattrib->dst, ETH_ALEN);
- memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN);
- if (!bsnaphdr) {
- __be16 be_tmp = htons(len);
-
- memcpy(ptr + 12, &be_tmp, 2);
- }
- return 0;
-}
-
-void r8712_recv_entry(union recv_frame *precvframe)
-{
- struct _adapter *padapter;
- struct recv_priv *precvpriv;
-
- s32 ret = _SUCCESS;
-
- padapter = precvframe->u.hdr.adapter;
- precvpriv = &(padapter->recvpriv);
-
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_RX);
-
- ret = recv_func(padapter, precvframe);
- if (ret == _FAIL)
- goto _recv_entry_drop;
- precvpriv->rx_pkts++;
- precvpriv->rx_bytes += (uint)(precvframe->u.hdr.rx_tail -
- precvframe->u.hdr.rx_data);
- return;
-_recv_entry_drop:
- precvpriv->rx_drop++;
- padapter->mppriv.rx_pktloss = precvpriv->rx_drop;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_recv.h b/drivers/staging/rtl8712/rtl871x_recv.h
deleted file mode 100644
index 0760bccbf389..000000000000
--- a/drivers/staging/rtl8712/rtl871x_recv.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _RTL871X_RECV_H_
-#define _RTL871X_RECV_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#define NR_RECVFRAME 256
-
-#define RXFRAME_ALIGN 8
-#define RXFRAME_ALIGN_SZ (1 << RXFRAME_ALIGN)
-
-#define MAX_SUBFRAME_COUNT 64
-
-/* for Rx reordering buffer control */
-struct recv_reorder_ctrl {
- struct _adapter *padapter;
- u16 indicate_seq; /* =wstart_b, init_value=0xffff */
- u16 wend_b;
- u8 wsize_b;
- struct __queue pending_recvframe_queue;
- struct timer_list reordering_ctrl_timer;
-};
-
-struct stainfo_rxcache {
- u16 tid_rxseq[16];
-};
-
-#define PHY_RSSI_SLID_WIN_MAX 100
-#define PHY_LINKQUALITY_SLID_WIN_MAX 20
-
-struct smooth_rssi_data {
- u32 elements[100]; /* array to store values */
- u32 index; /* index to current array to store */
- u32 total_num; /* num of valid elements */
- u32 total_val; /* sum of valid elements */
-};
-
-struct rx_pkt_attrib {
- u8 amsdu;
- u8 order;
- u8 qos;
- u8 to_fr_ds;
- u8 frag_num;
- u16 seq_num;
- u8 pw_save;
- u8 mfrag;
- u8 mdata;
- u8 privacy; /* in frame_ctrl field */
- u8 bdecrypted;
- int hdrlen; /* the WLAN Header Len */
- int encrypt; /* 0 no encrypt. != 0 encrypt algorithm */
- int iv_len;
- int icv_len;
- int priority;
- int ack_policy;
- u8 crc_err;
- u8 dst[ETH_ALEN];
- u8 src[ETH_ALEN];
- u8 ta[ETH_ALEN];
- u8 ra[ETH_ALEN];
- u8 bssid[ETH_ALEN];
- u8 tcpchk_valid; /* 0: invalid, 1: valid */
- u8 ip_chkrpt; /* 0: incorrect, 1: correct */
- u8 tcp_chkrpt; /* 0: incorrect, 1: correct */
- u8 signal_qual;
- s8 rx_mimo_signal_qual[2];
- u8 mcs_rate;
- u8 htc;
- u8 signal_strength;
-};
-
-/*
- * accesser of recv_priv: recv_entry(dispatch / passive level);
- * recv_thread(passive) ; returnpkt(dispatch)
- * ; halt(passive) ;
- *
- * using enter_critical section to protect
- */
-struct recv_priv {
- spinlock_t lock;
- struct __queue free_recv_queue;
- struct __queue recv_pending_queue;
- u8 *pallocated_frame_buf;
- u8 *precv_frame_buf;
- uint free_recvframe_cnt;
- struct _adapter *adapter;
- uint rx_bytes;
- uint rx_pkts;
- uint rx_drop;
- uint rx_icv_err;
- uint rx_largepacket_crcerr;
- uint rx_smallpacket_crcerr;
- uint rx_middlepacket_crcerr;
- u8 rx_pending_cnt;
- uint ff_hwaddr;
- struct tasklet_struct recv_tasklet;
- struct sk_buff_head free_recv_skb_queue;
- struct sk_buff_head rx_skb_queue;
- u8 *pallocated_recv_buf;
- u8 *precv_buf; /* 4 alignment */
- struct __queue free_recv_buf_queue;
- u32 free_recv_buf_queue_cnt;
- /* For the phy information */
- s8 rssi;
- u8 signal;
- u8 noise;
- u8 fw_rssi;
- struct smooth_rssi_data signal_qual_data;
- struct smooth_rssi_data signal_strength_data;
-};
-
-struct sta_recv_priv {
- spinlock_t lock;
- sint option;
- struct __queue defrag_q; /* keeping the fragment frame until defrag */
- struct stainfo_rxcache rxcache;
- uint sta_rx_bytes;
- uint sta_rx_pkts;
- uint sta_rx_fail;
-};
-
-#include "rtl8712_recv.h"
-
-/* get a free recv_frame from pfree_recv_queue */
-union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue);
-void r8712_free_recvframe(union recv_frame *precvframe,
- struct __queue *pfree_recv_queue);
-void r8712_free_recvframe_queue(struct __queue *pframequeue,
- struct __queue *pfree_recv_queue);
-int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe);
-int recv_func(struct _adapter *padapter, void *pcontext);
-
-static inline u8 *get_rxmem(union recv_frame *precvframe)
-{
- /* always return rx_head... */
- if (!precvframe)
- return NULL;
- return precvframe->u.hdr.rx_head;
-}
-
-static inline u8 *recvframe_pull(union recv_frame *precvframe, sint sz)
-{
- /* used for extract sz bytes from rx_data, update rx_data and return
- * the updated rx_data to the caller
- */
- if (!precvframe)
- return NULL;
- precvframe->u.hdr.rx_data += sz;
- if (precvframe->u.hdr.rx_data > precvframe->u.hdr.rx_tail) {
- precvframe->u.hdr.rx_data -= sz;
- return NULL;
- }
- precvframe->u.hdr.len -= sz;
- return precvframe->u.hdr.rx_data;
-}
-
-static inline u8 *recvframe_put(union recv_frame *precvframe, sint sz)
-{
- /* used for append sz bytes from ptr to rx_tail, update rx_tail and
- * return the updated rx_tail to the caller
- * after putting, rx_tail must be still larger than rx_end.
- */
- if (!precvframe)
- return NULL;
- precvframe->u.hdr.rx_tail += sz;
- if (precvframe->u.hdr.rx_tail > precvframe->u.hdr.rx_end) {
- precvframe->u.hdr.rx_tail -= sz;
- return NULL;
- }
- precvframe->u.hdr.len += sz;
- return precvframe->u.hdr.rx_tail;
-}
-
-static inline u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz)
-{
- /* rmv data from rx_tail (by yitsen)
- * used for extract sz bytes from rx_end, update rx_end and return the
- * updated rx_end to the caller
- * after pulling, rx_end must be still larger than rx_data.
- */
- if (!precvframe)
- return NULL;
- precvframe->u.hdr.rx_tail -= sz;
- if (precvframe->u.hdr.rx_tail < precvframe->u.hdr.rx_data) {
- precvframe->u.hdr.rx_tail += sz;
- return NULL;
- }
- precvframe->u.hdr.len -= sz;
- return precvframe->u.hdr.rx_tail;
-}
-
-struct sta_info;
-
-void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv);
-sint r8712_recvframe_chkmic(struct _adapter *adapter,
- union recv_frame *precvframe);
-union recv_frame *r8712_decryptor(struct _adapter *adapter,
- union recv_frame *precv_frame);
-union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *adapter,
- union recv_frame *precv_frame);
-int r8712_validate_recv_frame(struct _adapter *adapter,
- union recv_frame *precv_frame);
-union recv_frame *r8712_portctrl(struct _adapter *adapter,
- union recv_frame *precv_frame);
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl871x_rf.h b/drivers/staging/rtl8712/rtl871x_rf.h
deleted file mode 100644
index 7d98921a48fa..000000000000
--- a/drivers/staging/rtl8712/rtl871x_rf.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_RF_H_
-#define __RTL871X_RF_H_
-
-#include "rtl871x_cmd.h"
-#include "rtl871x_mp_phy_regdef.h"
-
-#define OFDM_PHY 1
-#define MIXED_PHY 2
-#define CCK_PHY 3
-#define NumRates (13)
-#define RTL8711_RF_MAX_SENS 6
-#define RTL8711_RF_DEF_SENS 4
-#define NUM_CHANNELS 15
-
-struct regulatory_class {
- u32 starting_freq; /*MHz, */
- u8 channel_set[NUM_CHANNELS];
- u8 channel_cck_power[NUM_CHANNELS]; /*dbm*/
- u8 channel_ofdm_power[NUM_CHANNELS];/*dbm*/
- u8 txpower_limit; /*dbm*/
- u8 channel_spacing; /*MHz*/
- u8 modem;
-};
-
-enum _REG_PREAMBLE_MODE {
- PREAMBLE_LONG = 1,
- PREAMBLE_AUTO = 2,
- PREAMBLE_SHORT = 3,
-};
-
-enum {
- RTL8712_RFC_1T = 0x10,
- RTL8712_RFC_2T = 0x20,
- RTL8712_RFC_1R = 0x01,
- RTL8712_RFC_2R = 0x02,
- RTL8712_RFC_1T1R = 0x11,
- RTL8712_RFC_1T2R = 0x12,
- RTL8712_RFC_TURBO = 0x92,
- RTL8712_RFC_2T2R = 0x22
-};
-
-#endif /*__RTL871X_RF_H_*/
diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c
deleted file mode 100644
index e46a5dbc7b65..000000000000
--- a/drivers/staging/rtl8712/rtl871x_security.c
+++ /dev/null
@@ -1,1386 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_security.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_SECURITY_C_
-
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/circ_buf.h>
-#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-#include <linux/atomic.h>
-#include <linux/crc32poly.h>
-#include <linux/semaphore.h>
-#include <linux/ieee80211.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "osdep_intf.h"
-
-/* =====WEP related===== */
-
-struct arc4context {
- u32 x;
- u32 y;
- u8 state[256];
-};
-
-static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len)
-{
- u32 t, u;
- u32 keyindex;
- u32 stateindex;
- u8 *state;
- u32 counter;
-
- state = parc4ctx->state;
- parc4ctx->x = 0;
- parc4ctx->y = 0;
- for (counter = 0; counter < 256; counter++)
- state[counter] = (u8)counter;
- keyindex = 0;
- stateindex = 0;
- for (counter = 0; counter < 256; counter++) {
- t = state[counter];
- stateindex = (stateindex + key[keyindex] + t) & 0xff;
- u = state[stateindex];
- state[stateindex] = (u8)t;
- state[counter] = (u8)u;
- if (++keyindex >= key_len)
- keyindex = 0;
- }
-}
-
-static u32 arcfour_byte(struct arc4context *parc4ctx)
-{
- u32 x;
- u32 y;
- u32 sx, sy;
- u8 *state;
-
- state = parc4ctx->state;
- x = (parc4ctx->x + 1) & 0xff;
- sx = state[x];
- y = (sx + parc4ctx->y) & 0xff;
- sy = state[y];
- parc4ctx->x = x;
- parc4ctx->y = y;
- state[y] = (u8)sx;
- state[x] = (u8)sy;
- return state[(sx + sy) & 0xff];
-}
-
-static void arcfour_encrypt(struct arc4context *parc4ctx,
- u8 *dest, u8 *src, u32 len)
-{
- u32 i;
-
- for (i = 0; i < len; i++)
- dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx);
-}
-
-static sint bcrc32initialized;
-static u32 crc32_table[256];
-
-static u8 crc32_reverseBit(u8 data)
-{
- return ((u8)(data << 7) & 0x80) | ((data << 5) & 0x40) | ((data << 3)
- & 0x20) | ((data << 1) & 0x10) | ((data >> 1) & 0x08) |
- ((data >> 3) & 0x04) | ((data >> 5) & 0x02) | ((data >> 7) &
- 0x01);
-}
-
-static void crc32_init(void)
-{
- sint i, j;
- u32 c;
- u8 *p = (u8 *)&c, *p1;
- u8 k;
-
- if (bcrc32initialized == 1)
- return;
-
- for (i = 0; i < 256; ++i) {
- k = crc32_reverseBit((u8)i);
- for (c = ((u32)k) << 24, j = 8; j > 0; --j)
- c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY_BE : (c << 1);
- p1 = (u8 *)&crc32_table[i];
- p1[0] = crc32_reverseBit(p[3]);
- p1[1] = crc32_reverseBit(p[2]);
- p1[2] = crc32_reverseBit(p[1]);
- p1[3] = crc32_reverseBit(p[0]);
- }
- bcrc32initialized = 1;
-}
-
-static u32 getcrc32(u8 *buf, u32 len)
-{
- u8 *p;
- u32 crc;
-
- if (!bcrc32initialized)
- crc32_init();
- crc = 0xffffffff; /* preload shift register, per CRC-32 spec */
- for (p = buf; len > 0; ++p, --len)
- crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8);
- return ~crc; /* transmit complement, per CRC-32 spec */
-}
-
-/*
- * Need to consider the fragment situation
- */
-void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe)
-{ /* exclude ICV */
- unsigned char crc[4];
- struct arc4context mycontext;
- u32 curfragnum, length, keylength, pki;
- u8 *pframe, *payload, *iv; /*,*wepkey*/
- u8 wepkey[16];
- struct pkt_attrib *pattrib = &((struct xmit_frame *)
- pxmitframe)->attrib;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
- if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
- return;
- pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
- /*start to encrypt each fragment*/
- if ((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) {
- pki = psecuritypriv->PrivacyKeyIndex;
- keylength = psecuritypriv->DefKeylen[pki];
- for (curfragnum = 0; curfragnum < pattrib->nr_frags;
- curfragnum++) {
- iv = pframe + pattrib->hdrlen;
- memcpy(&wepkey[0], iv, 3);
- memcpy(&wepkey[3], &psecuritypriv->DefKey[
- psecuritypriv->PrivacyKeyIndex].skey[0],
- keylength);
- payload = pframe + pattrib->iv_len + pattrib->hdrlen;
- if ((curfragnum + 1) == pattrib->nr_frags) {
- length = pattrib->last_txcmdsz -
- pattrib->hdrlen -
- pattrib->iv_len -
- pattrib->icv_len;
- *((__le32 *)crc) = cpu_to_le32(getcrc32(
- payload, length));
- arcfour_init(&mycontext, wepkey, 3 + keylength);
- arcfour_encrypt(&mycontext, payload, payload,
- length);
- arcfour_encrypt(&mycontext, payload + length,
- crc, 4);
- } else {
- length = pxmitpriv->frag_len -
- pattrib->hdrlen - pattrib->iv_len -
- pattrib->icv_len;
- *((__le32 *)crc) = cpu_to_le32(getcrc32(
- payload, length));
- arcfour_init(&mycontext, wepkey, 3 + keylength);
- arcfour_encrypt(&mycontext, payload, payload,
- length);
- arcfour_encrypt(&mycontext, payload + length,
- crc, 4);
- pframe += pxmitpriv->frag_len;
- pframe = (u8 *)RND4((addr_t)(pframe));
- }
- }
- }
-}
-
-void r8712_wep_decrypt(struct _adapter *padapter, u8 *precvframe)
-{
- /* exclude ICV */
- u8 crc[4];
- struct arc4context mycontext;
- u32 length, keylength;
- u8 *pframe, *payload, *iv, wepkey[16];
- u8 keyindex;
- struct rx_pkt_attrib *prxattrib = &(((union recv_frame *)
- precvframe)->u.hdr.attrib);
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- pframe = (unsigned char *)((union recv_frame *)precvframe)->
- u.hdr.rx_data;
- /* start to decrypt recvframe */
- if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt ==
- _WEP104_)) {
- iv = pframe + prxattrib->hdrlen;
- keyindex = (iv[3] & 0x3);
- keylength = psecuritypriv->DefKeylen[keyindex];
- memcpy(&wepkey[0], iv, 3);
- memcpy(&wepkey[3], &psecuritypriv->DefKey[
- psecuritypriv->PrivacyKeyIndex].skey[0],
- keylength);
- length = ((union recv_frame *)precvframe)->
- u.hdr.len - prxattrib->hdrlen - prxattrib->iv_len;
- payload = pframe + prxattrib->iv_len + prxattrib->hdrlen;
- /* decrypt payload include icv */
- arcfour_init(&mycontext, wepkey, 3 + keylength);
- arcfour_encrypt(&mycontext, payload, payload, length);
- /* calculate icv and compare the icv */
- *((__le32 *)crc) = cpu_to_le32(getcrc32(payload, length - 4));
- }
-}
-
-/* 3 =====TKIP related===== */
-
-static u32 secmicgetuint32(u8 *p)
-/* Convert from Byte[] to Us4Byte32 in a portable way */
-{
- s32 i;
- u32 res = 0;
-
- for (i = 0; i < 4; i++)
- res |= ((u32)(*p++)) << (8 * i);
- return res;
-}
-
-static void secmicputuint32(u8 *p, u32 val)
-/* Convert from Us4Byte32 to Byte[] in a portable way */
-{
- long i;
-
- for (i = 0; i < 4; i++) {
- *p++ = (u8)(val & 0xff);
- val >>= 8;
- }
-}
-
-static void secmicclear(struct mic_data *pmicdata)
-{
-/* Reset the state to the empty message. */
- pmicdata->L = pmicdata->K0;
- pmicdata->R = pmicdata->K1;
- pmicdata->nBytesInM = 0;
- pmicdata->M = 0;
-}
-
-void r8712_secmicsetkey(struct mic_data *pmicdata, u8 *key)
-{
- /* Set the key */
- pmicdata->K0 = secmicgetuint32(key);
- pmicdata->K1 = secmicgetuint32(key + 4);
- /* and reset the message */
- secmicclear(pmicdata);
-}
-
-static void secmicappendbyte(struct mic_data *pmicdata, u8 b)
-{
- /* Append the byte to our word-sized buffer */
- pmicdata->M |= ((u32)b) << (8 * pmicdata->nBytesInM);
- pmicdata->nBytesInM++;
- /* Process the word if it is full. */
- if (pmicdata->nBytesInM >= 4) {
- pmicdata->L ^= pmicdata->M;
- pmicdata->R ^= ROL32(pmicdata->L, 17);
- pmicdata->L += pmicdata->R;
- pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) |
- ((pmicdata->L & 0x00ff00ff) << 8);
- pmicdata->L += pmicdata->R;
- pmicdata->R ^= ROL32(pmicdata->L, 3);
- pmicdata->L += pmicdata->R;
- pmicdata->R ^= ROR32(pmicdata->L, 2);
- pmicdata->L += pmicdata->R;
- /* Clear the buffer */
- pmicdata->M = 0;
- pmicdata->nBytesInM = 0;
- }
-}
-
-void r8712_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes)
-{
- /* This is simple */
- while (nbytes > 0) {
- secmicappendbyte(pmicdata, *src++);
- nbytes--;
- }
-}
-
-void r8712_secgetmic(struct mic_data *pmicdata, u8 *dst)
-{
- /* Append the minimum padding */
- secmicappendbyte(pmicdata, 0x5a);
- secmicappendbyte(pmicdata, 0);
- secmicappendbyte(pmicdata, 0);
- secmicappendbyte(pmicdata, 0);
- secmicappendbyte(pmicdata, 0);
- /* and then zeroes until the length is a multiple of 4 */
- while (pmicdata->nBytesInM != 0)
- secmicappendbyte(pmicdata, 0);
- /* The appendByte function has already computed the result. */
- secmicputuint32(dst, pmicdata->L);
- secmicputuint32(dst + 4, pmicdata->R);
- /* Reset to the empty message. */
- secmicclear(pmicdata);
-}
-
-void seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_code,
- u8 pri)
-{
-
- struct mic_data micdata;
- u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
-
- r8712_secmicsetkey(&micdata, key);
- priority[0] = pri;
- /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
- if (header[1] & 1) { /* ToDS==1 */
- r8712_secmicappend(&micdata, &header[16], 6); /* DA */
- if (header[1] & 2) /* From Ds==1 */
- r8712_secmicappend(&micdata, &header[24], 6);
- else
- r8712_secmicappend(&micdata, &header[10], 6);
- } else { /* ToDS==0 */
- r8712_secmicappend(&micdata, &header[4], 6); /* DA */
- if (header[1] & 2) /* From Ds==1 */
- r8712_secmicappend(&micdata, &header[16], 6);
- else
- r8712_secmicappend(&micdata, &header[10], 6);
- }
- r8712_secmicappend(&micdata, &priority[0], 4);
- r8712_secmicappend(&micdata, data, data_len);
- r8712_secgetmic(&micdata, mic_code);
-}
-
-/* macros for extraction/creation of unsigned char/unsigned short values */
-#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15))
-#define Lo8(v16) ((u8)((v16) & 0x00FF))
-#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF))
-#define Lo16(v32) ((u16)((v32) & 0xFFFF))
-#define Hi16(v32) ((u16)(((v32) >> 16) & 0xFFFF))
-#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8))
-
-/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */
-#define TK16(N) Mk16(tk[2 * (N) + 1], tk[2 * (N)])
-
-/* S-box lookup: 16 bits --> 16 bits */
-#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)])
-
-/* fixed algorithm "parameters" */
-#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */
-#define TA_SIZE 6 /* 48-bit transmitter address */
-#define TK_SIZE 16 /* 128-bit temporal key */
-#define P1K_SIZE 10 /* 80-bit Phase1 key */
-#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */
-
-/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
-static const unsigned short Sbox1[2][256] = {/* Sbox for hash (can be in ROM) */
- {
- 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
- 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
- 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
- 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
- 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
- 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
- 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
- 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
- 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
- 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
- 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
- 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
- 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
- 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
- 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
- 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
- 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
- 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
- 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
- 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
- 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
- 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
- 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
- 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
- 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
- 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
- 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
- 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
- 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
- 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
- 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
- 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
- },
- { /* second half is unsigned char-reversed version of first! */
- 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
- 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
- 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
- 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
- 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
- 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
- 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
- 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
- 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
- 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
- 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
- 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
- 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
- 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
- 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
- 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
- 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
- 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
- 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
- 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
- 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
- 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
- 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
- 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
- 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
- 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
- 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
- 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
- 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
- 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
- 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
- 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C,
- }
-};
-
-/*
- **********************************************************************
- * Routine: Phase 1 -- generate P1K, given TA, TK, IV32
- *
- * Inputs:
- * tk[] = temporal key [128 bits]
- * ta[] = transmitter's MAC address [ 48 bits]
- * iv32 = upper 32 bits of IV [ 32 bits]
- * Output:
- * p1k[] = Phase 1 key [ 80 bits]
- *
- * Note:
- * This function only needs to be called every 2**16 packets,
- * although in theory it could be called every packet.
- *
- **********************************************************************
- */
-static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
-{
- sint i;
-
- /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */
- p1k[0] = Lo16(iv32);
- p1k[1] = Hi16(iv32);
- p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */
- p1k[3] = Mk16(ta[3], ta[2]);
- p1k[4] = Mk16(ta[5], ta[4]);
- /* Now compute an unbalanced Feistel cipher with 80-bit block */
- /* size on the 80-bit block P1K[], using the 128-bit key TK[] */
- for (i = 0; i < PHASE1_LOOP_CNT; i++) { /* Each add is mod 2**16 */
- p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0));
- p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2));
- p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4));
- p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6));
- p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0));
- p1k[4] += (unsigned short)i; /* avoid "slide attacks" */
- }
-}
-
-/*
- **********************************************************************
- * Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16
- *
- * Inputs:
- * tk[] = Temporal key [128 bits]
- * p1k[] = Phase 1 output key [ 80 bits]
- * iv16 = low 16 bits of IV counter [ 16 bits]
- * Output:
- * rc4key[] = the key used to encrypt the packet [128 bits]
- *
- * Note:
- * The value {TA,IV32,IV16} for Phase1/Phase2 must be unique
- * across all packets using the same key TK value. Then, for a
- * given value of TK[], this TKIP48 construction guarantees that
- * the final RC4KEY value is unique across all packets.
- *
- * Suggested implementation optimization: if PPK[] is "overlaid"
- * appropriately on RC4KEY[], there is no need for the final
- * for loop below that copies the PPK[] result into RC4KEY[].
- *
- **********************************************************************
- */
-static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
-{
- sint i;
- u16 PPK[6]; /* temporary key for mixing */
-
- /* Note: all adds in the PPK[] equations below are mod 2**16 */
- for (i = 0; i < 5; i++)
- PPK[i] = p1k[i]; /* first, copy P1K to PPK */
- PPK[5] = p1k[4] + iv16; /* next, add in IV16 */
- /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */
- PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */
- PPK[1] += _S_(PPK[0] ^ TK16(1));
- PPK[2] += _S_(PPK[1] ^ TK16(2));
- PPK[3] += _S_(PPK[2] ^ TK16(3));
- PPK[4] += _S_(PPK[3] ^ TK16(4));
- PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */
- /* Final sweep: bijective, "linear". Rotates kill LSB correlations */
- PPK[0] += RotR1(PPK[5] ^ TK16(6));
- PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */
- PPK[2] += RotR1(PPK[1]);
- PPK[3] += RotR1(PPK[2]);
- PPK[4] += RotR1(PPK[3]);
- PPK[5] += RotR1(PPK[4]);
- /* Note: At this point, for a given key TK[0..15], the 96-bit output */
- /* value PPK[0..5] is guaranteed to be unique, as a function */
- /* of the 96-bit "input" value {TA,IV32,IV16}. That is, P1K */
- /* is now a keyed permutation of {TA,IV32,IV16}. */
- /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */
- rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */
- rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */
- rc4key[2] = Lo8(iv16);
- rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);
- /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */
- for (i = 0; i < 6; i++) {
- rc4key[4 + 2 * i] = Lo8(PPK[i]);
- rc4key[5 + 2 * i] = Hi8(PPK[i]);
- }
-}
-
-/*The hlen isn't include the IV*/
-u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe)
-{ /* exclude ICV */
- u16 pnl;
- u32 pnh;
- u8 rc4key[16];
- u8 ttkey[16];
- u8 crc[4];
- struct arc4context mycontext;
- u32 curfragnum, length;
-
- u8 *pframe, *payload, *iv, *prwskey;
- union pn48 txpn;
- struct sta_info *stainfo;
- struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- u32 res = _SUCCESS;
-
- if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
- return _FAIL;
-
- pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
- /* 4 start to encrypt each fragment */
- if (pattrib->encrypt == _TKIP_) {
- if (pattrib->psta)
- stainfo = pattrib->psta;
- else
- stainfo = r8712_get_stainfo(&padapter->stapriv,
- &pattrib->ra[0]);
- if (stainfo) {
- prwskey = &stainfo->x_UncstKey.skey[0];
- for (curfragnum = 0; curfragnum < pattrib->nr_frags;
- curfragnum++) {
- iv = pframe + pattrib->hdrlen;
- payload = pframe + pattrib->iv_len +
- pattrib->hdrlen;
- GET_TKIP_PN(iv, txpn);
- pnl = (u16)(txpn.val);
- pnh = (u32)(txpn.val >> 16);
- phase1((u16 *)&ttkey[0], prwskey,
- &pattrib->ta[0], pnh);
- phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0],
- pnl);
- if ((curfragnum + 1) == pattrib->nr_frags) {
- /* 4 the last fragment */
- length = pattrib->last_txcmdsz -
- pattrib->hdrlen -
- pattrib->iv_len -
- pattrib->icv_len;
- *((__le32 *)crc) = cpu_to_le32(
- getcrc32(payload, length));
- arcfour_init(&mycontext, rc4key, 16);
- arcfour_encrypt(&mycontext, payload,
- payload, length);
- arcfour_encrypt(&mycontext, payload +
- length, crc, 4);
- } else {
- length = pxmitpriv->frag_len -
- pattrib->hdrlen -
- pattrib->iv_len -
- pattrib->icv_len;
- *((__le32 *)crc) = cpu_to_le32(getcrc32(
- payload, length));
- arcfour_init(&mycontext, rc4key, 16);
- arcfour_encrypt(&mycontext, payload,
- payload, length);
- arcfour_encrypt(&mycontext,
- payload + length, crc,
- 4);
- pframe += pxmitpriv->frag_len;
- pframe = (u8 *)RND4((addr_t)(pframe));
- }
- }
- } else {
- res = _FAIL;
- }
- }
- return res;
-}
-
-/* The hlen doesn't include the IV */
-void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe)
-{ /* exclude ICV */
- u16 pnl;
- u32 pnh;
- u8 rc4key[16];
- u8 ttkey[16];
- u8 crc[4];
- struct arc4context mycontext;
- u32 length;
- u8 *pframe, *payload, *iv, *prwskey, idx = 0;
- union pn48 txpn;
- struct sta_info *stainfo;
- struct rx_pkt_attrib *prxattrib = &((union recv_frame *)
- precvframe)->u.hdr.attrib;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- pframe = (unsigned char *)((union recv_frame *)
- precvframe)->u.hdr.rx_data;
- /* 4 start to decrypt recvframe */
- if (prxattrib->encrypt == _TKIP_) {
- stainfo = r8712_get_stainfo(&padapter->stapriv,
- &prxattrib->ta[0]);
- if (stainfo) {
- iv = pframe + prxattrib->hdrlen;
- payload = pframe + prxattrib->iv_len +
- prxattrib->hdrlen;
- length = ((union recv_frame *)precvframe)->
- u.hdr.len - prxattrib->hdrlen -
- prxattrib->iv_len;
- if (is_multicast_ether_addr(prxattrib->ra)) {
- idx = iv[3];
- prwskey = &psecuritypriv->XGrpKey[
- ((idx >> 6) & 0x3) - 1].skey[0];
- if (!psecuritypriv->binstallGrpkey)
- return;
- } else {
- prwskey = &stainfo->x_UncstKey.skey[0];
- }
- GET_TKIP_PN(iv, txpn);
- pnl = (u16)(txpn.val);
- pnh = (u32)(txpn.val >> 16);
- phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0],
- pnh);
- phase2(&rc4key[0], prwskey, (unsigned short *)
- &ttkey[0], pnl);
- /* 4 decrypt payload include icv */
- arcfour_init(&mycontext, rc4key, 16);
- arcfour_encrypt(&mycontext, payload, payload, length);
- *((__le32 *)crc) = cpu_to_le32(getcrc32(payload,
- length - 4));
- }
- }
-}
-
-/* 3 =====AES related===== */
-
-#define MAX_MSG_SIZE 2048
-/*****************************/
-/******** SBOX Table *********/
-/*****************************/
-
-static const u8 sbox_table[256] = {
- 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
- 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
- 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
- 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
- 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
- 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
- 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
- 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
- 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
- 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
- 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
- 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
- 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
- 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
- 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
- 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
- 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
- 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
- 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
- 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
- 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
- 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
- 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
- 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
- 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
- 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
- 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
- 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
- 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
- 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
- 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
- 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
-};
-
-/****************************************/
-/* aes128k128d() */
-/* Performs a 128 bit AES encrypt with */
-/* 128 bit data. */
-/****************************************/
-static void xor_128(u8 *a, u8 *b, u8 *out)
-{
- sint i;
-
- for (i = 0; i < 16; i++)
- out[i] = a[i] ^ b[i];
-}
-
-static void xor_32(u8 *a, u8 *b, u8 *out)
-{
- sint i;
-
- for (i = 0; i < 4; i++)
- out[i] = a[i] ^ b[i];
-}
-
-static u8 sbox(u8 a)
-{
- return sbox_table[(sint)a];
-}
-
-static void next_key(u8 *key, sint round)
-{
- u8 rcon;
- u8 sbox_key[4];
- static const u8 rcon_table[12] = {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
- 0x1b, 0x36, 0x36, 0x36
- };
-
- sbox_key[0] = sbox(key[13]);
- sbox_key[1] = sbox(key[14]);
- sbox_key[2] = sbox(key[15]);
- sbox_key[3] = sbox(key[12]);
- rcon = rcon_table[round];
- xor_32(&key[0], sbox_key, &key[0]);
- key[0] = key[0] ^ rcon;
- xor_32(&key[4], &key[0], &key[4]);
- xor_32(&key[8], &key[4], &key[8]);
- xor_32(&key[12], &key[8], &key[12]);
-}
-
-static void byte_sub(u8 *in, u8 *out)
-{
- sint i;
-
- for (i = 0; i < 16; i++)
- out[i] = sbox(in[i]);
-}
-
-static void shift_row(u8 *in, u8 *out)
-{
- out[0] = in[0];
- out[1] = in[5];
- out[2] = in[10];
- out[3] = in[15];
- out[4] = in[4];
- out[5] = in[9];
- out[6] = in[14];
- out[7] = in[3];
- out[8] = in[8];
- out[9] = in[13];
- out[10] = in[2];
- out[11] = in[7];
- out[12] = in[12];
- out[13] = in[1];
- out[14] = in[6];
- out[15] = in[11];
-}
-
-static void mix_column(u8 *in, u8 *out)
-{
- sint i;
- u8 add1b[4];
- u8 add1bf7[4];
- u8 rotl[4];
- u8 swap_halves[4];
- u8 andf7[4];
- u8 rotr[4];
- u8 temp[4];
- u8 tempb[4];
-
- for (i = 0; i < 4; i++) {
- if ((in[i] & 0x80) == 0x80)
- add1b[i] = 0x1b;
- else
- add1b[i] = 0x00;
- }
- swap_halves[0] = in[2]; /* Swap halves */
- swap_halves[1] = in[3];
- swap_halves[2] = in[0];
- swap_halves[3] = in[1];
- rotl[0] = in[3]; /* Rotate left 8 bits */
- rotl[1] = in[0];
- rotl[2] = in[1];
- rotl[3] = in[2];
- andf7[0] = in[0] & 0x7f;
- andf7[1] = in[1] & 0x7f;
- andf7[2] = in[2] & 0x7f;
- andf7[3] = in[3] & 0x7f;
- for (i = 3; i > 0; i--) { /* logical shift left 1 bit */
- andf7[i] = andf7[i] << 1;
- if ((andf7[i - 1] & 0x80) == 0x80)
- andf7[i] = (andf7[i] | 0x01);
- }
- andf7[0] = andf7[0] << 1;
- andf7[0] = andf7[0] & 0xfe;
- xor_32(add1b, andf7, add1bf7);
- xor_32(in, add1bf7, rotr);
- temp[0] = rotr[0]; /* Rotate right 8 bits */
- rotr[0] = rotr[1];
- rotr[1] = rotr[2];
- rotr[2] = rotr[3];
- rotr[3] = temp[0];
- xor_32(add1bf7, rotr, temp);
- xor_32(swap_halves, rotl, tempb);
- xor_32(temp, tempb, out);
-}
-
-static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
-{
- sint round;
- sint i;
- u8 intermediatea[16];
- u8 intermediateb[16];
- u8 round_key[16];
-
- for (i = 0; i < 16; i++)
- round_key[i] = key[i];
- for (round = 0; round < 11; round++) {
- if (round == 0) {
- xor_128(round_key, data, ciphertext);
- next_key(round_key, round);
- } else if (round == 10) {
- byte_sub(ciphertext, intermediatea);
- shift_row(intermediatea, intermediateb);
- xor_128(intermediateb, round_key, ciphertext);
- } else { /* 1 - 9 */
- byte_sub(ciphertext, intermediatea);
- shift_row(intermediatea, intermediateb);
- mix_column(&intermediateb[0], &intermediatea[0]);
- mix_column(&intermediateb[4], &intermediatea[4]);
- mix_column(&intermediateb[8], &intermediatea[8]);
- mix_column(&intermediateb[12], &intermediatea[12]);
- xor_128(intermediatea, round_key, ciphertext);
- next_key(round_key, round);
- }
- }
-}
-
-/************************************************/
-/* construct_mic_iv() */
-/* Builds the MIC IV from header fields and PN */
-/************************************************/
-static void construct_mic_iv(u8 *mic_iv, sint qc_exists, sint a4_exists,
- u8 *mpdu, uint payload_length, u8 *pn_vector)
-{
- sint i;
-
- mic_iv[0] = 0x59;
- if (qc_exists && a4_exists)
- mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */
- if (qc_exists && !a4_exists)
- mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */
- if (!qc_exists)
- mic_iv[1] = 0x00;
- for (i = 2; i < 8; i++)
- mic_iv[i] = mpdu[i + 8];
- for (i = 8; i < 14; i++)
- mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */
- mic_iv[14] = (unsigned char)(payload_length / 256);
- mic_iv[15] = (unsigned char)(payload_length % 256);
-}
-
-/************************************************/
-/* construct_mic_header1() */
-/* Builds the first MIC header block from */
-/* header fields. */
-/************************************************/
-static void construct_mic_header1(u8 *mic_header1, sint header_length, u8 *mpdu)
-{
- mic_header1[0] = (u8)((header_length - 2) / 256);
- mic_header1[1] = (u8)((header_length - 2) % 256);
- mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */
- /* Mute retry, more data and pwr mgt bits */
- mic_header1[3] = mpdu[1] & 0xc7;
- mic_header1[4] = mpdu[4]; /* A1 */
- mic_header1[5] = mpdu[5];
- mic_header1[6] = mpdu[6];
- mic_header1[7] = mpdu[7];
- mic_header1[8] = mpdu[8];
- mic_header1[9] = mpdu[9];
- mic_header1[10] = mpdu[10]; /* A2 */
- mic_header1[11] = mpdu[11];
- mic_header1[12] = mpdu[12];
- mic_header1[13] = mpdu[13];
- mic_header1[14] = mpdu[14];
- mic_header1[15] = mpdu[15];
-}
-
-/************************************************/
-/* construct_mic_header2() */
-/* Builds the last MIC header block from */
-/* header fields. */
-/************************************************/
-static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, sint a4_exists,
- sint qc_exists)
-{
- sint i;
-
- for (i = 0; i < 16; i++)
- mic_header2[i] = 0x00;
- mic_header2[0] = mpdu[16]; /* A3 */
- mic_header2[1] = mpdu[17];
- mic_header2[2] = mpdu[18];
- mic_header2[3] = mpdu[19];
- mic_header2[4] = mpdu[20];
- mic_header2[5] = mpdu[21];
- mic_header2[6] = 0x00;
- mic_header2[7] = 0x00; /* mpdu[23]; */
- if (!qc_exists && a4_exists)
- for (i = 0; i < 6; i++)
- mic_header2[8 + i] = mpdu[24 + i]; /* A4 */
- if (qc_exists && !a4_exists) {
- mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
- mic_header2[9] = mpdu[25] & 0x00;
- }
- if (qc_exists && a4_exists) {
- for (i = 0; i < 6; i++)
- mic_header2[8 + i] = mpdu[24 + i]; /* A4 */
- mic_header2[14] = mpdu[30] & 0x0f;
- mic_header2[15] = mpdu[31] & 0x00;
- }
-}
-
-/************************************************/
-/* construct_mic_header2() */
-/* Builds the last MIC header block from */
-/* header fields. */
-/************************************************/
-static void construct_ctr_preload(u8 *ctr_preload,
- sint a4_exists, sint qc_exists,
- u8 *mpdu, u8 *pn_vector, sint c)
-{
- sint i;
-
- for (i = 0; i < 16; i++)
- ctr_preload[i] = 0x00;
- i = 0;
- ctr_preload[0] = 0x01; /* flag */
- if (qc_exists && a4_exists)
- ctr_preload[1] = mpdu[30] & 0x0f;
- if (qc_exists && !a4_exists)
- ctr_preload[1] = mpdu[24] & 0x0f;
- for (i = 2; i < 8; i++)
- ctr_preload[i] = mpdu[i + 8];
- for (i = 8; i < 14; i++)
- ctr_preload[i] = pn_vector[13 - i];
- ctr_preload[14] = (unsigned char)(c / 256); /* Ctr */
- ctr_preload[15] = (unsigned char)(c % 256);
-}
-
-/************************************/
-/* bitwise_xor() */
-/* A 128 bit, bitwise exclusive or */
-/************************************/
-static void bitwise_xor(u8 *ina, u8 *inb, u8 *out)
-{
- sint i;
-
- for (i = 0; i < 16; i++)
- out[i] = ina[i] ^ inb[i];
-}
-
-static void aes_cipher(u8 *key, uint hdrlen,
- u8 *pframe, uint plen)
-{
- uint qc_exists, a4_exists, i, j, payload_remainder;
- uint num_blocks, payload_index;
-
- u8 pn_vector[6];
- u8 mic_iv[16];
- u8 mic_header1[16];
- u8 mic_header2[16];
- u8 ctr_preload[16];
-
- /* Intermediate Buffers */
- u8 chain_buffer[16];
- u8 aes_out[16];
- u8 padded_buffer[16];
- u8 mic[8];
- u16 frtype = GetFrameType(pframe);
- u16 frsubtype = GetFrameSubType(pframe);
-
- frsubtype >>= 4;
- memset((void *)mic_iv, 0, 16);
- memset((void *)mic_header1, 0, 16);
- memset((void *)mic_header2, 0, 16);
- memset((void *)ctr_preload, 0, 16);
- memset((void *)chain_buffer, 0, 16);
- memset((void *)aes_out, 0, 16);
- memset((void *)padded_buffer, 0, 16);
-
- if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN))
- a4_exists = 0;
- else
- a4_exists = 1;
-
- if ((frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACK)) ||
- (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFPOLL)) ||
- (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACKPOLL))) {
- qc_exists = 1;
- if (hdrlen != WLAN_HDR_A3_QOS_LEN)
- hdrlen += 2;
- } else if ((frsubtype == 0x08) ||
- (frsubtype == 0x09) ||
- (frsubtype == 0x0a) ||
- (frsubtype == 0x0b)) {
- if (hdrlen != WLAN_HDR_A3_QOS_LEN)
- hdrlen += 2;
- qc_exists = 1;
- } else {
- qc_exists = 0;
- }
- pn_vector[0] = pframe[hdrlen];
- pn_vector[1] = pframe[hdrlen + 1];
- pn_vector[2] = pframe[hdrlen + 4];
- pn_vector[3] = pframe[hdrlen + 5];
- pn_vector[4] = pframe[hdrlen + 6];
- pn_vector[5] = pframe[hdrlen + 7];
- construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector);
- construct_mic_header1(mic_header1, hdrlen, pframe);
- construct_mic_header2(mic_header2, pframe, a4_exists, qc_exists);
- payload_remainder = plen % 16;
- num_blocks = plen / 16;
- /* Find start of payload */
- payload_index = hdrlen + 8;
- /* Calculate MIC */
- aes128k128d(key, mic_iv, aes_out);
- bitwise_xor(aes_out, mic_header1, chain_buffer);
- aes128k128d(key, chain_buffer, aes_out);
- bitwise_xor(aes_out, mic_header2, chain_buffer);
- aes128k128d(key, chain_buffer, aes_out);
- for (i = 0; i < num_blocks; i++) {
- bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
- payload_index += 16;
- aes128k128d(key, chain_buffer, aes_out);
- }
- /* Add on the final payload block if it needs padding */
- if (payload_remainder > 0) {
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < payload_remainder; j++)
- padded_buffer[j] = pframe[payload_index++];
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- aes128k128d(key, chain_buffer, aes_out);
- }
- for (j = 0; j < 8; j++)
- mic[j] = aes_out[j];
- /* Insert MIC into payload */
- for (j = 0; j < 8; j++)
- pframe[payload_index + j] = mic[j];
- payload_index = hdrlen + 8;
- for (i = 0; i < num_blocks; i++) {
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- pframe, pn_vector, i + 1);
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
- for (j = 0; j < 16; j++)
- pframe[payload_index++] = chain_buffer[j];
- }
- if (payload_remainder > 0) { /* If short final block, then pad it,*/
- /* encrypt and copy unpadded part back */
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- pframe, pn_vector, num_blocks + 1);
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < payload_remainder; j++)
- padded_buffer[j] = pframe[payload_index + j];
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- for (j = 0; j < payload_remainder; j++)
- pframe[payload_index++] = chain_buffer[j];
- }
- /* Encrypt the MIC */
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- pframe, pn_vector, 0);
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < 8; j++)
- padded_buffer[j] = pframe[j + hdrlen + 8 + plen];
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- for (j = 0; j < 8; j++)
- pframe[payload_index++] = chain_buffer[j];
-}
-
-u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe)
-{ /* exclude ICV */
- /* Intermediate Buffers */
- sint curfragnum, length;
- u8 *pframe, *prwskey;
- struct sta_info *stainfo;
- struct pkt_attrib *pattrib = &((struct xmit_frame *)
- pxmitframe)->attrib;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- u32 res = _SUCCESS;
-
- if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
- return _FAIL;
- pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
- /* 4 start to encrypt each fragment */
- if (pattrib->encrypt == _AES_) {
- if (pattrib->psta)
- stainfo = pattrib->psta;
- else
- stainfo = r8712_get_stainfo(&padapter->stapriv,
- &pattrib->ra[0]);
- if (stainfo) {
- prwskey = &stainfo->x_UncstKey.skey[0];
- for (curfragnum = 0; curfragnum < pattrib->nr_frags;
- curfragnum++) {
- if ((curfragnum + 1) == pattrib->nr_frags) {
- length = pattrib->last_txcmdsz -
- pattrib->hdrlen -
- pattrib->iv_len -
- pattrib->icv_len;
- aes_cipher(prwskey, pattrib->hdrlen,
- pframe, length);
- } else {
- length = pxmitpriv->frag_len -
- pattrib->hdrlen -
- pattrib->iv_len -
- pattrib->icv_len;
- aes_cipher(prwskey, pattrib->hdrlen,
- pframe, length);
- pframe += pxmitpriv->frag_len;
- pframe = (u8 *)RND4((addr_t)(pframe));
- }
- }
- } else {
- res = _FAIL;
- }
- }
- return res;
-}
-
-static void aes_decipher(u8 *key, uint hdrlen,
- u8 *pframe, uint plen)
-{
- static u8 message[MAX_MSG_SIZE];
- uint qc_exists, a4_exists, i, j, payload_remainder;
- uint num_blocks, payload_index;
- u8 pn_vector[6];
- u8 mic_iv[16];
- u8 mic_header1[16];
- u8 mic_header2[16];
- u8 ctr_preload[16];
- /* Intermediate Buffers */
- u8 chain_buffer[16];
- u8 aes_out[16];
- u8 padded_buffer[16];
- u8 mic[8];
- uint frtype = GetFrameType(pframe);
- uint frsubtype = GetFrameSubType(pframe);
-
- frsubtype >>= 4;
- memset((void *)mic_iv, 0, 16);
- memset((void *)mic_header1, 0, 16);
- memset((void *)mic_header2, 0, 16);
- memset((void *)ctr_preload, 0, 16);
- memset((void *)chain_buffer, 0, 16);
- memset((void *)aes_out, 0, 16);
- memset((void *)padded_buffer, 0, 16);
- /* start to decrypt the payload */
- /*(plen including llc, payload and mic) */
- num_blocks = (plen - 8) / 16;
- payload_remainder = (plen - 8) % 16;
- pn_vector[0] = pframe[hdrlen];
- pn_vector[1] = pframe[hdrlen + 1];
- pn_vector[2] = pframe[hdrlen + 4];
- pn_vector[3] = pframe[hdrlen + 5];
- pn_vector[4] = pframe[hdrlen + 6];
- pn_vector[5] = pframe[hdrlen + 7];
- if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN))
- a4_exists = 0;
- else
- a4_exists = 1;
- if ((frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACK)) ||
- (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFPOLL)) ||
- (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACKPOLL))) {
- qc_exists = 1;
- if (hdrlen != WLAN_HDR_A3_QOS_LEN)
- hdrlen += 2;
- } else if ((frsubtype == 0x08) ||
- (frsubtype == 0x09) ||
- (frsubtype == 0x0a) ||
- (frsubtype == 0x0b)) {
- if (hdrlen != WLAN_HDR_A3_QOS_LEN)
- hdrlen += 2;
- qc_exists = 1;
- } else {
- qc_exists = 0;
- }
- /* now, decrypt pframe with hdrlen offset and plen long */
- payload_index = hdrlen + 8; /* 8 is for extiv */
- for (i = 0; i < num_blocks; i++) {
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- pframe, pn_vector, i + 1);
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
- for (j = 0; j < 16; j++)
- pframe[payload_index++] = chain_buffer[j];
- }
- if (payload_remainder > 0) { /* If short final block, pad it,*/
- /* encrypt it and copy the unpadded part back */
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- pframe, pn_vector, num_blocks + 1);
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < payload_remainder; j++)
- padded_buffer[j] = pframe[payload_index + j];
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- for (j = 0; j < payload_remainder; j++)
- pframe[payload_index++] = chain_buffer[j];
- }
- /* start to calculate the mic */
- memcpy((void *)message, pframe, (hdrlen + plen + 8));
- pn_vector[0] = pframe[hdrlen];
- pn_vector[1] = pframe[hdrlen + 1];
- pn_vector[2] = pframe[hdrlen + 4];
- pn_vector[3] = pframe[hdrlen + 5];
- pn_vector[4] = pframe[hdrlen + 6];
- pn_vector[5] = pframe[hdrlen + 7];
- construct_mic_iv(mic_iv, qc_exists, a4_exists, message, plen - 8,
- pn_vector);
- construct_mic_header1(mic_header1, hdrlen, message);
- construct_mic_header2(mic_header2, message, a4_exists, qc_exists);
- payload_remainder = (plen - 8) % 16;
- num_blocks = (plen - 8) / 16;
- /* Find start of payload */
- payload_index = hdrlen + 8;
- /* Calculate MIC */
- aes128k128d(key, mic_iv, aes_out);
- bitwise_xor(aes_out, mic_header1, chain_buffer);
- aes128k128d(key, chain_buffer, aes_out);
- bitwise_xor(aes_out, mic_header2, chain_buffer);
- aes128k128d(key, chain_buffer, aes_out);
- for (i = 0; i < num_blocks; i++) {
- bitwise_xor(aes_out, &message[payload_index], chain_buffer);
- payload_index += 16;
- aes128k128d(key, chain_buffer, aes_out);
- }
- /* Add on the final payload block if it needs padding */
- if (payload_remainder > 0) {
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < payload_remainder; j++)
- padded_buffer[j] = message[payload_index++];
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- aes128k128d(key, chain_buffer, aes_out);
- }
- for (j = 0; j < 8; j++)
- mic[j] = aes_out[j];
- /* Insert MIC into payload */
- for (j = 0; j < 8; j++)
- message[payload_index + j] = mic[j];
- payload_index = hdrlen + 8;
- for (i = 0; i < num_blocks; i++) {
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- message, pn_vector, i + 1);
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, &message[payload_index], chain_buffer);
- for (j = 0; j < 16; j++)
- message[payload_index++] = chain_buffer[j];
- }
- if (payload_remainder > 0) { /* If short final block, pad it,*/
- /* encrypt and copy unpadded part back */
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- message, pn_vector, num_blocks + 1);
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < payload_remainder; j++)
- padded_buffer[j] = message[payload_index + j];
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- for (j = 0; j < payload_remainder; j++)
- message[payload_index++] = chain_buffer[j];
- }
- /* Encrypt the MIC */
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message,
- pn_vector, 0);
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < 8; j++)
- padded_buffer[j] = message[j + hdrlen + plen];
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- for (j = 0; j < 8; j++)
- message[payload_index++] = chain_buffer[j];
- /* compare the mic */
-}
-
-void r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe)
-{ /* exclude ICV */
- /* Intermediate Buffers */
- sint length;
- u8 *pframe, *prwskey, *iv, idx;
- struct sta_info *stainfo;
- struct rx_pkt_attrib *prxattrib = &((union recv_frame *)
- precvframe)->u.hdr.attrib;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- pframe = (unsigned char *)((union recv_frame *)precvframe)->
- u.hdr.rx_data;
- /* 4 start to encrypt each fragment */
- if (prxattrib->encrypt == _AES_) {
- stainfo = r8712_get_stainfo(&padapter->stapriv,
- &prxattrib->ta[0]);
- if (stainfo) {
- if (is_multicast_ether_addr(prxattrib->ra)) {
- iv = pframe + prxattrib->hdrlen;
- idx = iv[3];
- prwskey = &psecuritypriv->XGrpKey[
- ((idx >> 6) & 0x3) - 1].skey[0];
- if (!psecuritypriv->binstallGrpkey)
- return;
-
- } else {
- prwskey = &stainfo->x_UncstKey.skey[0];
- }
- length = ((union recv_frame *)precvframe)->
- u.hdr.len - prxattrib->hdrlen -
- prxattrib->iv_len;
- aes_decipher(prwskey, prxattrib->hdrlen, pframe,
- length);
- }
- }
-}
-
-void r8712_use_tkipkey_handler(struct timer_list *t)
-{
- struct _adapter *padapter =
- from_timer(padapter, t, securitypriv.tkip_timer);
-
- padapter->securitypriv.busetkipkey = true;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_security.h b/drivers/staging/rtl8712/rtl871x_security.h
deleted file mode 100644
index 8461b7f05359..000000000000
--- a/drivers/staging/rtl8712/rtl871x_security.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_SECURITY_H_
-#define __RTL871X_SECURITY_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#define _NO_PRIVACY_ 0x0
-#define _WEP40_ 0x1
-#define _TKIP_ 0x2
-#define _TKIP_WTMIC_ 0x3
-#define _AES_ 0x4
-#define _WEP104_ 0x5
-
-#define _WPA_IE_ID_ 0xdd
-#define _WPA2_IE_ID_ 0x30
-
-#ifndef Ndis802_11AuthModeWPA2
-#define Ndis802_11AuthModeWPA2 (Ndis802_11AuthModeWPANone + 1)
-#endif
-
-#ifndef Ndis802_11AuthModeWPA2PSK
-#define Ndis802_11AuthModeWPA2PSK (Ndis802_11AuthModeWPANone + 2)
-#endif
-
-union pn48 {
- u64 val;
-#if defined(__BIG_ENDIAN)
- struct {
- u8 TSC7;
- u8 TSC6;
- u8 TSC5;
- u8 TSC4;
- u8 TSC3;
- u8 TSC2;
- u8 TSC1;
- u8 TSC0;
- } _byte_;
-#else
- struct {
- u8 TSC0;
- u8 TSC1;
- u8 TSC2;
- u8 TSC3;
- u8 TSC4;
- u8 TSC5;
- u8 TSC6;
- u8 TSC7;
- } _byte_;
-#endif
-};
-
-union Keytype {
- u8 skey[16];
- u32 lkey[4];
-};
-
-struct RT_PMKID_LIST {
- u8 bUsed;
- u8 Bssid[6];
- u8 PMKID[16];
- u8 SsidBuf[33];
- u8 *ssid_octet;
- u16 ssid_length;
-};
-
-struct security_priv {
- u32 AuthAlgrthm; /* 802.11 auth, could be open, shared,
- * 8021x and authswitch
- */
- u32 PrivacyAlgrthm; /* This specify the privacy for shared
- * auth. algorithm.
- */
- u32 PrivacyKeyIndex; /* this is only valid for legendary
- * wep, 0~3 for key id.
- */
- union Keytype DefKey[4]; /* this is only valid for def. key */
- u32 DefKeylen[4];
- u32 XGrpPrivacy; /* This specify the privacy algthm.
- * used for Grp key
- */
- u32 XGrpKeyid; /* key id used for Grp Key */
- union Keytype XGrpKey[2]; /* 802.1x Group Key, for
- * inx0 and inx1
- */
- union Keytype XGrptxmickey[2];
- union Keytype XGrprxmickey[2];
- union pn48 Grptxpn; /* PN48 used for Grp Key xmit. */
- union pn48 Grprxpn; /* PN48 used for Grp Key recv. */
- u8 wps_hw_pbc_pressed;/*for hw pbc pressed*/
- u8 wps_phase;/*for wps*/
- u8 wps_ie[MAX_WPA_IE_LEN << 2];
- int wps_ie_len;
- u8 binstallGrpkey;
- u8 busetkipkey;
- struct timer_list tkip_timer;
- u8 bcheck_grpkey;
- u8 bgrpkey_handshake;
- s32 sw_encrypt; /* from registry_priv */
- s32 sw_decrypt; /* from registry_priv */
- s32 hw_decrypted; /* if the rx packets is hw_decrypted==false,
- * it means the hw has not been ready.
- */
- u32 ndisauthtype; /* keeps the auth_type & enc_status from upper
- * layer ioctl(wpa_supplicant or wzc)
- */
- u32 ndisencryptstatus;
- struct wlan_bssid_ex sec_bss; /* for joinbss (h2c buffer) usage */
- struct NDIS_802_11_WEP ndiswep;
- u8 assoc_info[600];
- u8 szofcapability[256]; /* for wpa2 usage */
- u8 oidassociation[512]; /* for wpa/wpa2 usage */
- u8 authenticator_ie[256]; /* store ap security information element */
- u8 supplicant_ie[256]; /* store sta security information element */
- /* for tkip countermeasure */
- u32 last_mic_err_time;
- u8 btkip_countermeasure;
- u8 btkip_wait_report;
- u32 btkip_countermeasure_time;
- /*-------------------------------------------------------------------
- * For WPA2 Pre-Authentication.
- *------------------------------------------------------------------
- **/
- struct RT_PMKID_LIST PMKIDList[NUM_PMKID_CACHE];
- u8 PMKIDIndex;
-};
-
-#define GET_ENCRY_ALGO(psecuritypriv, psta, encry_algo, bmcst) \
-do { \
- switch (psecuritypriv->AuthAlgrthm) { \
- case 0: \
- case 1: \
- case 3: \
- encry_algo = (u8)psecuritypriv->PrivacyAlgrthm; \
- break; \
- case 2: \
- if (bmcst) \
- encry_algo = (u8)psecuritypriv->XGrpPrivacy; \
- else \
- encry_algo = (u8)psta->XPrivacy; \
- break; \
- } \
-} while (0)
-#define SET_ICE_IV_LEN(iv_len, icv_len, encrypt)\
-do {\
- switch (encrypt) { \
- case _WEP40_: \
- case _WEP104_: \
- iv_len = 4; \
- icv_len = 4; \
- break; \
- case _TKIP_: \
- iv_len = 8; \
- icv_len = 4; \
- break; \
- case _AES_: \
- iv_len = 8; \
- icv_len = 8; \
- break; \
- default: \
- iv_len = 0; \
- icv_len = 0; \
- break; \
- } \
-} while (0)
-#define GET_TKIP_PN(iv, txpn) \
-do {\
- txpn._byte_.TSC0 = iv[2];\
- txpn._byte_.TSC1 = iv[0];\
- txpn._byte_.TSC2 = iv[4];\
- txpn._byte_.TSC3 = iv[5];\
- txpn._byte_.TSC4 = iv[6];\
- txpn._byte_.TSC5 = iv[7];\
-} while (0)
-
-#define ROL32(A, n) (((A) << (n)) | (((A) >> (32 - (n))) & ((1UL << (n)) - 1)))
-#define ROR32(A, n) ROL32((A), 32 - (n))
-
-struct mic_data {
- u32 K0, K1; /* Key */
- u32 L, R; /* Current state */
- u32 M; /* Message accumulator (single word) */
- u32 nBytesInM; /* # bytes in M */
-};
-
-void seccalctkipmic(
- u8 *key,
- u8 *header,
- u8 *data,
- u32 data_len,
- u8 *Miccode,
- u8 priority);
-
-void r8712_secmicsetkey(struct mic_data *pmicdata, u8 *key);
-void r8712_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nBytes);
-void r8712_secgetmic(struct mic_data *pmicdata, u8 *dst);
-u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe);
-u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe);
-void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe);
-void r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe);
-void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe);
-void r8712_wep_decrypt(struct _adapter *padapter, u8 *precvframe);
-void r8712_use_tkipkey_handler(struct timer_list *t);
-
-#endif /*__RTL871X_SECURITY_H_ */
-
diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
deleted file mode 100644
index 2c806a0105bf..000000000000
--- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c
+++ /dev/null
@@ -1,263 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_sta_mgt.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_STA_MGT_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "xmit_osdep.h"
-#include "sta_info.h"
-
-static void _init_stainfo(struct sta_info *psta)
-{
- memset((u8 *)psta, 0, sizeof(struct sta_info));
- spin_lock_init(&psta->lock);
- INIT_LIST_HEAD(&psta->list);
- INIT_LIST_HEAD(&psta->hash_list);
- _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
- _r8712_init_sta_recv_priv(&psta->sta_recvpriv);
- INIT_LIST_HEAD(&psta->asoc_list);
- INIT_LIST_HEAD(&psta->auth_list);
-}
-
-int _r8712_init_sta_priv(struct sta_priv *pstapriv)
-{
- struct sta_info *psta;
- s32 i;
-
- pstapriv->pallocated_stainfo_buf = kmalloc(sizeof(struct sta_info) *
- NUM_STA + 4, GFP_ATOMIC);
- if (!pstapriv->pallocated_stainfo_buf)
- return -ENOMEM;
- pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
- ((addr_t)(pstapriv->pallocated_stainfo_buf) & 3);
- _init_queue(&pstapriv->free_sta_queue);
- spin_lock_init(&pstapriv->sta_hash_lock);
- pstapriv->asoc_sta_count = 0;
- _init_queue(&pstapriv->sleep_q);
- _init_queue(&pstapriv->wakeup_q);
- psta = (struct sta_info *)(pstapriv->pstainfo_buf);
- for (i = 0; i < NUM_STA; i++) {
- _init_stainfo(psta);
- INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
- list_add_tail(&psta->list, &pstapriv->free_sta_queue.queue);
- psta++;
- }
- INIT_LIST_HEAD(&pstapriv->asoc_list);
- INIT_LIST_HEAD(&pstapriv->auth_list);
- return 0;
-}
-
-/* this function is used to free the memory of lock || sema for all stainfos */
-static void mfree_all_stainfo(struct sta_priv *pstapriv)
-{
- unsigned long irqL;
- struct list_head *plist, *phead;
-
- spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
- phead = &pstapriv->free_sta_queue.queue;
- plist = phead->next;
- while (!end_of_queue_search(phead, plist))
- plist = plist->next;
-
- spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
-}
-
-void _r8712_free_sta_priv(struct sta_priv *pstapriv)
-{
- if (pstapriv) {
- /* be done before free sta_hash_lock */
- mfree_all_stainfo(pstapriv);
- kfree(pstapriv->pallocated_stainfo_buf);
- }
-}
-
-struct sta_info *r8712_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
-{
- s32 index;
- struct list_head *phash_list;
- struct sta_info *psta;
- struct __queue *pfree_sta_queue;
- struct recv_reorder_ctrl *preorder_ctrl;
- int i = 0;
- u16 wRxSeqInitialValue = 0xffff;
- unsigned long flags;
-
- pfree_sta_queue = &pstapriv->free_sta_queue;
- spin_lock_irqsave(&pfree_sta_queue->lock, flags);
- psta = list_first_entry_or_null(&pfree_sta_queue->queue,
- struct sta_info, list);
- if (psta) {
- list_del_init(&psta->list);
- _init_stainfo(psta);
- memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
- index = wifi_mac_hash(hwaddr);
- if (index >= NUM_STA) {
- psta = NULL;
- goto exit;
- }
- phash_list = &pstapriv->sta_hash[index];
- list_add_tail(&psta->hash_list, phash_list);
- pstapriv->asoc_sta_count++;
-
-/* For the SMC router, the sequence number of first packet of WPS handshake
- * will be 0. In this case, this packet will be dropped by recv_decache function
- * if we use the 0x00 as the default value for tid_rxseq variable. So, we
- * initialize the tid_rxseq variable as the 0xffff.
- */
- for (i = 0; i < 16; i++)
- memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i],
- &wRxSeqInitialValue, 2);
- /* for A-MPDU Rx reordering buffer control */
- for (i = 0; i < 16; i++) {
- preorder_ctrl = &psta->recvreorder_ctrl[i];
- preorder_ctrl->padapter = pstapriv->padapter;
- preorder_ctrl->indicate_seq = 0xffff;
- preorder_ctrl->wend_b = 0xffff;
- preorder_ctrl->wsize_b = 64;
- _init_queue(&preorder_ctrl->pending_recvframe_queue);
- r8712_init_recv_timer(preorder_ctrl);
- }
- }
-exit:
- spin_unlock_irqrestore(&pfree_sta_queue->lock, flags);
- return psta;
-}
-
-/* using pstapriv->sta_hash_lock to protect */
-void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta)
-{
- int i;
- unsigned long irqL0;
- struct __queue *pfree_sta_queue;
- struct recv_reorder_ctrl *preorder_ctrl;
- struct sta_xmit_priv *pstaxmitpriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- if (!psta)
- return;
- pfree_sta_queue = &pstapriv->free_sta_queue;
- pstaxmitpriv = &psta->sta_xmitpriv;
- spin_lock_irqsave(&(pxmitpriv->vo_pending.lock), irqL0);
- r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
- list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
- spin_unlock_irqrestore(&(pxmitpriv->vo_pending.lock), irqL0);
- spin_lock_irqsave(&(pxmitpriv->vi_pending.lock), irqL0);
- r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
- list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
- spin_unlock_irqrestore(&(pxmitpriv->vi_pending.lock), irqL0);
- spin_lock_irqsave(&(pxmitpriv->bk_pending.lock), irqL0);
- r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
- list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
- spin_unlock_irqrestore(&(pxmitpriv->bk_pending.lock), irqL0);
- spin_lock_irqsave(&(pxmitpriv->be_pending.lock), irqL0);
- r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
- list_del_init(&(pstaxmitpriv->be_q.tx_pending));
- spin_unlock_irqrestore(&(pxmitpriv->be_pending.lock), irqL0);
- list_del_init(&psta->hash_list);
- pstapriv->asoc_sta_count--;
- /* re-init sta_info; 20061114 */
- _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
- _r8712_init_sta_recv_priv(&psta->sta_recvpriv);
- /* for A-MPDU Rx reordering buffer control,
- * cancel reordering_ctrl_timer
- */
- for (i = 0; i < 16; i++) {
- preorder_ctrl = &psta->recvreorder_ctrl[i];
- del_timer(&preorder_ctrl->reordering_ctrl_timer);
- }
- spin_lock(&(pfree_sta_queue->lock));
- /* insert into free_sta_queue; 20061114 */
- list_add_tail(&psta->list, &pfree_sta_queue->queue);
- spin_unlock(&(pfree_sta_queue->lock));
-}
-
-/* free all stainfo which in sta_hash[all] */
-void r8712_free_all_stainfo(struct _adapter *padapter)
-{
- unsigned long irqL;
- struct list_head *plist, *phead;
- s32 index;
- struct sta_info *psta = NULL;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct sta_info *pbcmc_stainfo = r8712_get_bcmc_stainfo(padapter);
-
- if (pstapriv->asoc_sta_count == 1)
- return;
- spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
- for (index = 0; index < NUM_STA; index++) {
- phead = &(pstapriv->sta_hash[index]);
- plist = phead->next;
- while (!end_of_queue_search(phead, plist)) {
- psta = container_of(plist,
- struct sta_info, hash_list);
- plist = plist->next;
- if (pbcmc_stainfo != psta)
- r8712_free_stainfo(padapter, psta);
- }
- }
- spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
-}
-
-/* any station allocated can be searched by hash list */
-struct sta_info *r8712_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
-{
- unsigned long irqL;
- struct list_head *plist, *phead;
- struct sta_info *psta = NULL;
- u32 index;
-
- if (!hwaddr)
- return NULL;
- index = wifi_mac_hash(hwaddr);
- spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
- phead = &(pstapriv->sta_hash[index]);
- plist = phead->next;
- while (!end_of_queue_search(phead, plist)) {
- psta = container_of(plist, struct sta_info, hash_list);
- if ((!memcmp(psta->hwaddr, hwaddr, ETH_ALEN))) {
- /* if found the matched address */
- break;
- }
- psta = NULL;
- plist = plist->next;
- }
- spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
- return psta;
-}
-
-void r8712_init_bcmc_stainfo(struct _adapter *padapter)
-{
- unsigned char bcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- r8712_alloc_stainfo(pstapriv, bcast_addr);
-}
-
-struct sta_info *r8712_get_bcmc_stainfo(struct _adapter *padapter)
-{
- struct sta_priv *pstapriv = &padapter->stapriv;
- u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
- return r8712_get_stainfo(pstapriv, bc_addr);
-}
-
-u8 r8712_access_ctrl(struct wlan_acl_pool *pacl_list, u8 *mac_addr)
-{
- return true;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_wlan_sme.h b/drivers/staging/rtl8712/rtl871x_wlan_sme.h
deleted file mode 100644
index 97ea1451426c..000000000000
--- a/drivers/staging/rtl8712/rtl871x_wlan_sme.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871X_WLAN_SME_H_
-#define _RTL871X_WLAN_SME_H_
-
-#define MSR_APMODE 0x0C
-#define MSR_STAMODE 0x08
-#define MSR_ADHOCMODE 0x04
-#define MSR_NOLINKMODE 0x00
-#define _1M_RATE_ 0
-#define _2M_RATE_ 1
-#define _5M_RATE_ 2
-#define _11M_RATE_ 3
-#define _6M_RATE_ 4
-#define _9M_RATE_ 5
-#define _12M_RATE_ 6
-#define _18M_RATE_ 7
-#define _24M_RATE_ 8
-#define _36M_RATE_ 9
-#define _48M_RATE_ 10
-#define _54M_RATE_ 11
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c
deleted file mode 100644
index 408616e9afcf..000000000000
--- a/drivers/staging/rtl8712/rtl871x_xmit.c
+++ /dev/null
@@ -1,1056 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_xmit.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_XMIT_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "osdep_intf.h"
-#include "usb_ops.h"
-
-#include <linux/usb.h>
-#include <linux/ieee80211.h>
-
-static const u8 P802_1H_OUI[P80211_OUI_LEN] = {0x00, 0x00, 0xf8};
-static const u8 RFC1042_OUI[P80211_OUI_LEN] = {0x00, 0x00, 0x00};
-static void init_hwxmits(struct hw_xmit *phwxmit, sint entry);
-static void alloc_hwxmits(struct _adapter *padapter);
-static void free_hwxmits(struct _adapter *padapter);
-
-static void _init_txservq(struct tx_servq *ptxservq)
-{
- INIT_LIST_HEAD(&ptxservq->tx_pending);
- _init_queue(&ptxservq->sta_pending);
- ptxservq->qcnt = 0;
-}
-
-void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)
-{
- memset((unsigned char *)psta_xmitpriv, 0,
- sizeof(struct sta_xmit_priv));
- spin_lock_init(&psta_xmitpriv->lock);
- _init_txservq(&psta_xmitpriv->be_q);
- _init_txservq(&psta_xmitpriv->bk_q);
- _init_txservq(&psta_xmitpriv->vi_q);
- _init_txservq(&psta_xmitpriv->vo_q);
- INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz);
- INIT_LIST_HEAD(&psta_xmitpriv->apsd);
-}
-
-int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
- struct _adapter *padapter)
-{
- sint i;
- struct xmit_buf *pxmitbuf;
- struct xmit_frame *pxframe;
- int j;
-
- memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv));
- spin_lock_init(&pxmitpriv->lock);
- /*
- *Please insert all the queue initialization using _init_queue below
- */
- pxmitpriv->adapter = padapter;
- _init_queue(&pxmitpriv->be_pending);
- _init_queue(&pxmitpriv->bk_pending);
- _init_queue(&pxmitpriv->vi_pending);
- _init_queue(&pxmitpriv->vo_pending);
- _init_queue(&pxmitpriv->bm_pending);
- _init_queue(&pxmitpriv->legacy_dz_queue);
- _init_queue(&pxmitpriv->apsd_queue);
- _init_queue(&pxmitpriv->free_xmit_queue);
- /*
- * Please allocate memory with sz = (struct xmit_frame) * NR_XMITFRAME,
- * and initialize free_xmit_frame below.
- * Please also apply free_txobj to link_up all the xmit_frames...
- */
- pxmitpriv->pallocated_frame_buf =
- kmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4,
- GFP_ATOMIC);
- if (!pxmitpriv->pallocated_frame_buf) {
- pxmitpriv->pxmit_frame_buf = NULL;
- return -ENOMEM;
- }
- pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 -
- ((addr_t) (pxmitpriv->pallocated_frame_buf) & 3);
- pxframe = (struct xmit_frame *) pxmitpriv->pxmit_frame_buf;
- for (i = 0; i < NR_XMITFRAME; i++) {
- INIT_LIST_HEAD(&(pxframe->list));
- pxframe->padapter = padapter;
- pxframe->frame_tag = DATA_FRAMETAG;
- pxframe->pkt = NULL;
- pxframe->buf_addr = NULL;
- pxframe->pxmitbuf = NULL;
- list_add_tail(&(pxframe->list),
- &(pxmitpriv->free_xmit_queue.queue));
- pxframe++;
- }
- pxmitpriv->free_xmitframe_cnt = NR_XMITFRAME;
- /*
- * init xmit hw_txqueue
- */
- _r8712_init_hw_txqueue(&pxmitpriv->be_txqueue, BE_QUEUE_INX);
- _r8712_init_hw_txqueue(&pxmitpriv->bk_txqueue, BK_QUEUE_INX);
- _r8712_init_hw_txqueue(&pxmitpriv->vi_txqueue, VI_QUEUE_INX);
- _r8712_init_hw_txqueue(&pxmitpriv->vo_txqueue, VO_QUEUE_INX);
- _r8712_init_hw_txqueue(&pxmitpriv->bmc_txqueue, BMC_QUEUE_INX);
- pxmitpriv->frag_len = MAX_FRAG_THRESHOLD;
- pxmitpriv->txirp_cnt = 1;
- /*per AC pending irp*/
- pxmitpriv->beq_cnt = 0;
- pxmitpriv->bkq_cnt = 0;
- pxmitpriv->viq_cnt = 0;
- pxmitpriv->voq_cnt = 0;
- /*init xmit_buf*/
- _init_queue(&pxmitpriv->free_xmitbuf_queue);
- _init_queue(&pxmitpriv->pending_xmitbuf_queue);
- pxmitpriv->pxmitbuf = kmalloc(NR_XMITBUFF * sizeof(struct xmit_buf), GFP_ATOMIC);
- if (!pxmitpriv->pxmitbuf)
- goto clean_up_frame_buf;
- pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
- for (i = 0; i < NR_XMITBUFF; i++) {
- INIT_LIST_HEAD(&pxmitbuf->list);
- pxmitbuf->pallocated_buf =
- kmalloc(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ, GFP_ATOMIC);
- if (!pxmitbuf->pallocated_buf) {
- j = 0;
- goto clean_up_alloc_buf;
- }
- pxmitbuf->pbuf = pxmitbuf->pallocated_buf + XMITBUF_ALIGN_SZ -
- ((addr_t) (pxmitbuf->pallocated_buf) &
- (XMITBUF_ALIGN_SZ - 1));
- if (r8712_xmit_resource_alloc(padapter, pxmitbuf)) {
- j = 1;
- goto clean_up_alloc_buf;
- }
- list_add_tail(&pxmitbuf->list,
- &(pxmitpriv->free_xmitbuf_queue.queue));
- pxmitbuf++;
- }
- pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;
- INIT_WORK(&padapter->wk_filter_rx_ff0, r8712_SetFilter);
- alloc_hwxmits(padapter);
- init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
- tasklet_setup(&pxmitpriv->xmit_tasklet, r8712_xmit_bh);
- return 0;
-
-clean_up_alloc_buf:
- if (j) {
- /* failure happened in r8712_xmit_resource_alloc()
- * delete extra pxmitbuf->pallocated_buf
- */
- kfree(pxmitbuf->pallocated_buf);
- }
- for (j = 0; j < i; j++) {
- int k;
-
- pxmitbuf--; /* reset pointer */
- kfree(pxmitbuf->pallocated_buf);
- for (k = 0; k < 8; k++) /* delete xmit urb's */
- usb_free_urb(pxmitbuf->pxmit_urb[k]);
- }
- kfree(pxmitpriv->pxmitbuf);
- pxmitpriv->pxmitbuf = NULL;
-clean_up_frame_buf:
- kfree(pxmitpriv->pallocated_frame_buf);
- pxmitpriv->pallocated_frame_buf = NULL;
- return -ENOMEM;
-}
-
-void _free_xmit_priv(struct xmit_priv *pxmitpriv)
-{
- int i;
- struct _adapter *padapter = pxmitpriv->adapter;
- struct xmit_frame *pxmitframe = (struct xmit_frame *)
- pxmitpriv->pxmit_frame_buf;
- struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
-
- if (!pxmitpriv->pxmit_frame_buf)
- return;
- for (i = 0; i < NR_XMITFRAME; i++) {
- r8712_xmit_complete(padapter, pxmitframe);
- pxmitframe++;
- }
- for (i = 0; i < NR_XMITBUFF; i++) {
- r8712_xmit_resource_free(padapter, pxmitbuf);
- kfree(pxmitbuf->pallocated_buf);
- pxmitbuf++;
- }
- kfree(pxmitpriv->pallocated_frame_buf);
- kfree(pxmitpriv->pxmitbuf);
- free_hwxmits(padapter);
-}
-
-int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
- struct pkt_attrib *pattrib)
-{
- struct pkt_file pktfile;
- struct sta_info *psta = NULL;
- struct ethhdr etherhdr;
-
- struct tx_cmd txdesc;
-
- bool bmcast;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
-
- _r8712_open_pktfile(pkt, &pktfile);
-
- _r8712_pktfile_read(&pktfile, (unsigned char *)&etherhdr, ETH_HLEN);
-
- pattrib->ether_type = ntohs(etherhdr.h_proto);
-
- /*
- * If driver xmit ARP packet, driver can set ps mode to initial
- * setting. It stands for getting DHCP or fix IP.
- */
- if (pattrib->ether_type == 0x0806) {
- if (padapter->pwrctrlpriv.pwr_mode !=
- padapter->registrypriv.power_mgnt) {
- del_timer_sync(&pmlmepriv->dhcp_timer);
- r8712_set_ps_mode(padapter,
- padapter->registrypriv.power_mgnt,
- padapter->registrypriv.smart_ps);
- }
- }
-
- memcpy(pattrib->dst, &etherhdr.h_dest, ETH_ALEN);
- memcpy(pattrib->src, &etherhdr.h_source, ETH_ALEN);
- pattrib->pctrl = 0;
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
- memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
- } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
- memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
- } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
- memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);
- } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- /*firstly, filter packet not belongs to mp*/
- if (pattrib->ether_type != 0x8712)
- return -EINVAL;
- /* for mp storing the txcmd per packet,
- * according to the info of txcmd to update pattrib
- */
- /*get MP_TXDESC_SIZE bytes txcmd per packet*/
- _r8712_pktfile_read(&pktfile, (u8 *)&txdesc, TXDESC_SIZE);
- memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
- memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
- pattrib->pctrl = 1;
- }
- /* r8712_xmitframe_coalesce() overwrite this!*/
- pattrib->pktlen = pktfile.pkt_len;
- if (pattrib->ether_type == ETH_P_IP) {
- /* The following is for DHCP and ARP packet, we use cck1M to
- * tx these packets and let LPS awake some time
- * to prevent DHCP protocol fail
- */
- u8 tmp[24];
-
- _r8712_pktfile_read(&pktfile, &tmp[0], 24);
- pattrib->dhcp_pkt = 0;
- if (pktfile.pkt_len > 282) {/*MINIMUM_DHCP_PACKET_SIZE)*/
- if (pattrib->ether_type == ETH_P_IP) {/* IP header*/
- if (((tmp[21] == 68) && (tmp[23] == 67)) ||
- ((tmp[21] == 67) && (tmp[23] == 68))) {
- /* 68 : UDP BOOTP client
- * 67 : UDP BOOTP server
- * Use low rate to send DHCP packet.
- */
- pattrib->dhcp_pkt = 1;
- }
- }
- }
- }
- bmcast = is_multicast_ether_addr(pattrib->ra);
- /* get sta_info*/
- if (bmcast) {
- psta = r8712_get_bcmc_stainfo(padapter);
- pattrib->mac_id = 4;
- } else {
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- psta = r8712_get_stainfo(pstapriv,
- get_bssid(pmlmepriv));
- pattrib->mac_id = 5;
- } else {
- psta = r8712_get_stainfo(pstapriv, pattrib->ra);
- if (!psta) /* drop the pkt */
- return -ENOMEM;
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- pattrib->mac_id = 5;
- else
- pattrib->mac_id = psta->mac_id;
- }
- }
-
- if (psta) {
- pattrib->psta = psta;
- } else {
- /* if we cannot get psta => drrp the pkt */
- return -ENOMEM;
- }
-
- pattrib->ack_policy = 0;
- /* get ether_hdr_len */
- pattrib->pkt_hdrlen = ETH_HLEN;
-
- if (pqospriv->qos_option) {
- r8712_set_qos(&pktfile, pattrib);
- } else {
- pattrib->hdrlen = WLAN_HDR_A3_LEN;
- pattrib->subtype = IEEE80211_FTYPE_DATA;
- pattrib->priority = 0;
- }
- if (psta->ieee8021x_blocked) {
- pattrib->encrypt = 0;
- if ((pattrib->ether_type != 0x888e) &&
- !check_fwstate(pmlmepriv, WIFI_MP_STATE))
- return -EINVAL;
- } else {
- GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
- }
- switch (pattrib->encrypt) {
- case _WEP40_:
- case _WEP104_:
- pattrib->iv_len = 4;
- pattrib->icv_len = 4;
- break;
- case _TKIP_:
- pattrib->iv_len = 8;
- pattrib->icv_len = 4;
- if (padapter->securitypriv.busetkipkey == _FAIL)
- return -EINVAL;
- break;
- case _AES_:
- pattrib->iv_len = 8;
- pattrib->icv_len = 8;
- break;
- default:
- pattrib->iv_len = 0;
- pattrib->icv_len = 0;
- break;
- }
-
- if (pattrib->encrypt &&
- (padapter->securitypriv.sw_encrypt ||
- !psecuritypriv->hw_decrypted))
- pattrib->bswenc = true;
- else
- pattrib->bswenc = false;
- /* if in MP_STATE, update pkt_attrib from mp_txcmd, and overwrite
- * some settings above.
- */
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
- pattrib->priority =
- (le32_to_cpu(txdesc.txdw1) >> QSEL_SHT) & 0x1f;
- return 0;
-}
-
-static int xmitframe_addmic(struct _adapter *padapter,
- struct xmit_frame *pxmitframe)
-{
- u32 curfragnum, length;
- u8 *pframe, *payload, mic[8];
- struct mic_data micdata;
- struct sta_info *stainfo;
- struct qos_priv *pqospriv = &(padapter->mlmepriv.qospriv);
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct security_priv *psecpriv = &padapter->securitypriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- u8 priority[4] = {};
- bool bmcst = is_multicast_ether_addr(pattrib->ra);
-
- if (pattrib->psta)
- stainfo = pattrib->psta;
- else
- stainfo = r8712_get_stainfo(&padapter->stapriv,
- &pattrib->ra[0]);
- if (pattrib->encrypt == _TKIP_) {
- /*encode mic code*/
- if (stainfo) {
- u8 null_key[16] = {};
-
- pframe = pxmitframe->buf_addr + TXDESC_OFFSET;
- if (bmcst) {
- if (!memcmp(psecpriv->XGrptxmickey
- [psecpriv->XGrpKeyid].skey,
- null_key, 16))
- return -ENOMEM;
- /*start to calculate the mic code*/
- r8712_secmicsetkey(&micdata,
- psecpriv->XGrptxmickey
- [psecpriv->XGrpKeyid].skey);
- } else {
- if (!memcmp(&stainfo->tkiptxmickey.skey[0],
- null_key, 16))
- return -ENOMEM;
- /* start to calculate the mic code */
- r8712_secmicsetkey(&micdata,
- &stainfo->tkiptxmickey.skey[0]);
- }
- if (pframe[1] & 1) { /* ToDS==1 */
- r8712_secmicappend(&micdata,
- &pframe[16], 6); /*DA*/
- if (pframe[1] & 2) /* From Ds==1 */
- r8712_secmicappend(&micdata,
- &pframe[24], 6);
- else
- r8712_secmicappend(&micdata,
- &pframe[10], 6);
- } else { /* ToDS==0 */
- r8712_secmicappend(&micdata,
- &pframe[4], 6); /* DA */
- if (pframe[1] & 2) /* From Ds==1 */
- r8712_secmicappend(&micdata,
- &pframe[16], 6);
- else
- r8712_secmicappend(&micdata,
- &pframe[10], 6);
- }
- if (pqospriv->qos_option == 1)
- priority[0] = (u8)pxmitframe->attrib.priority;
- r8712_secmicappend(&micdata, &priority[0], 4);
- payload = pframe;
- for (curfragnum = 0; curfragnum < pattrib->nr_frags;
- curfragnum++) {
- payload = (u8 *)RND4((addr_t)(payload));
- payload += pattrib->hdrlen + pattrib->iv_len;
- if ((curfragnum + 1) == pattrib->nr_frags) {
- length = pattrib->last_txcmdsz -
- pattrib->hdrlen -
- pattrib->iv_len -
- ((psecpriv->sw_encrypt)
- ? pattrib->icv_len : 0);
- r8712_secmicappend(&micdata, payload,
- length);
- payload = payload + length;
- } else {
- length = pxmitpriv->frag_len -
- pattrib->hdrlen - pattrib->iv_len -
- ((psecpriv->sw_encrypt) ?
- pattrib->icv_len : 0);
- r8712_secmicappend(&micdata, payload,
- length);
- payload = payload + length +
- pattrib->icv_len;
- }
- }
- r8712_secgetmic(&micdata, &(mic[0]));
- /* add mic code and add the mic code length in
- * last_txcmdsz
- */
- memcpy(payload, &(mic[0]), 8);
- pattrib->last_txcmdsz += 8;
- payload = payload - pattrib->last_txcmdsz + 8;
- }
- }
- return 0;
-}
-
-static sint xmitframe_swencrypt(struct _adapter *padapter,
- struct xmit_frame *pxmitframe)
-{
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
-
- if (pattrib->bswenc) {
- switch (pattrib->encrypt) {
- case _WEP40_:
- case _WEP104_:
- r8712_wep_encrypt(padapter, (u8 *)pxmitframe);
- break;
- case _TKIP_:
- r8712_tkip_encrypt(padapter, (u8 *)pxmitframe);
- break;
- case _AES_:
- r8712_aes_encrypt(padapter, (u8 *)pxmitframe);
- break;
- default:
- break;
- }
- }
- return _SUCCESS;
-}
-
-static int make_wlanhdr(struct _adapter *padapter, u8 *hdr,
- struct pkt_attrib *pattrib)
-{
- u16 *qc;
-
- struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
- __le16 *fctrl = &pwlanhdr->frame_control;
- u8 *bssid;
-
- memset(hdr, 0, WLANHDR_OFFSET);
- SetFrameSubType(fctrl, pattrib->subtype);
- if (!(pattrib->subtype & IEEE80211_FTYPE_DATA))
- return 0;
-
- bssid = get_bssid(pmlmepriv);
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- /* to_ds = 1, fr_ds = 0; */
- SetToDs(fctrl);
- ether_addr_copy(pwlanhdr->addr1, bssid);
- ether_addr_copy(pwlanhdr->addr2, pattrib->src);
- ether_addr_copy(pwlanhdr->addr3, pattrib->dst);
- } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- /* to_ds = 0, fr_ds = 1; */
- SetFrDs(fctrl);
- ether_addr_copy(pwlanhdr->addr1, pattrib->dst);
- ether_addr_copy(pwlanhdr->addr2, bssid);
- ether_addr_copy(pwlanhdr->addr3, pattrib->src);
- } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- ether_addr_copy(pwlanhdr->addr1, pattrib->dst);
- ether_addr_copy(pwlanhdr->addr2, pattrib->src);
- ether_addr_copy(pwlanhdr->addr3, bssid);
- } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- ether_addr_copy(pwlanhdr->addr1, pattrib->dst);
- ether_addr_copy(pwlanhdr->addr2, pattrib->src);
- ether_addr_copy(pwlanhdr->addr3, bssid);
- } else {
- return -EINVAL;
- }
-
- if (pattrib->encrypt)
- SetPrivacy(fctrl);
- if (pqospriv->qos_option) {
- qc = (unsigned short *)(hdr + pattrib->hdrlen - 2);
- if (pattrib->priority)
- SetPriority(qc, pattrib->priority);
- SetAckpolicy(qc, pattrib->ack_policy);
- }
- /* TODO: fill HT Control Field */
- /* Update Seq Num will be handled by f/w */
- {
- struct sta_info *psta;
- bool bmcst = is_multicast_ether_addr(pattrib->ra);
-
- if (pattrib->psta)
- psta = pattrib->psta;
- else if (bmcst)
- psta = r8712_get_bcmc_stainfo(padapter);
- else
- psta = r8712_get_stainfo(&padapter->stapriv,
- pattrib->ra);
-
- if (psta) {
- u16 *txtid = psta->sta_xmitpriv.txseq_tid;
-
- txtid[pattrib->priority]++;
- txtid[pattrib->priority] &= 0xFFF;
- pattrib->seqnum = txtid[pattrib->priority];
- SetSeqNum(hdr, pattrib->seqnum);
- }
- }
-
- return 0;
-}
-
-static sint r8712_put_snap(u8 *data, u16 h_proto)
-{
- struct ieee80211_snap_hdr *snap;
- const u8 *oui;
-
- snap = (struct ieee80211_snap_hdr *)data;
- snap->dsap = 0xaa;
- snap->ssap = 0xaa;
- snap->ctrl = 0x03;
- if (h_proto == 0x8137 || h_proto == 0x80f3)
- oui = P802_1H_OUI;
- else
- oui = RFC1042_OUI;
- snap->oui[0] = oui[0];
- snap->oui[1] = oui[1];
- snap->oui[2] = oui[2];
- *(__be16 *)(data + SNAP_SIZE) = htons(h_proto);
- return SNAP_SIZE + sizeof(u16);
-}
-
-/*
- * This sub-routine will perform all the following:
- * 1. remove 802.3 header.
- * 2. create wlan_header, based on the info in pxmitframe
- * 3. append sta's iv/ext-iv
- * 4. append LLC
- * 5. move frag chunk from pframe to pxmitframe->mem
- * 6. apply sw-encrypt, if necessary.
- */
-sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt,
- struct xmit_frame *pxmitframe)
-{
- struct pkt_file pktfile;
-
- sint frg_len, mpdu_len, llc_sz;
- u32 mem_sz;
- u8 frg_inx;
- addr_t addr;
- u8 *pframe, *mem_start, *ptxdesc;
- struct sta_info *psta;
- struct security_priv *psecpriv = &padapter->securitypriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- u8 *pbuf_start;
- bool bmcst = is_multicast_ether_addr(pattrib->ra);
-
- if (!pattrib->psta)
- return _FAIL;
- psta = pattrib->psta;
- if (!pxmitframe->buf_addr)
- return _FAIL;
- pbuf_start = pxmitframe->buf_addr;
- ptxdesc = pbuf_start;
- mem_start = pbuf_start + TXDESC_OFFSET;
- if (make_wlanhdr(padapter, mem_start, pattrib))
- return _FAIL;
- _r8712_open_pktfile(pkt, &pktfile);
- _r8712_pktfile_read(&pktfile, NULL, (uint) pattrib->pkt_hdrlen);
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- /* truncate TXDESC_SIZE bytes txcmd if at mp mode for 871x */
- if (pattrib->ether_type == 0x8712) {
- /* take care - update_txdesc overwrite this */
- _r8712_pktfile_read(&pktfile, ptxdesc, TXDESC_SIZE);
- }
- }
- pattrib->pktlen = pktfile.pkt_len;
- frg_inx = 0;
- frg_len = pxmitpriv->frag_len - 4;
- while (1) {
- llc_sz = 0;
- mpdu_len = frg_len;
- pframe = mem_start;
- SetMFrag(mem_start);
- pframe += pattrib->hdrlen;
- mpdu_len -= pattrib->hdrlen;
- /* adding icv, if necessary...*/
- if (pattrib->iv_len) {
- if (psta) {
- switch (pattrib->encrypt) {
- case _WEP40_:
- case _WEP104_:
- WEP_IV(pattrib->iv, psta->txpn,
- (u8)psecpriv->PrivacyKeyIndex);
- break;
- case _TKIP_:
- if (bmcst)
- TKIP_IV(pattrib->iv,
- psta->txpn,
- (u8)psecpriv->XGrpKeyid);
- else
- TKIP_IV(pattrib->iv, psta->txpn,
- 0);
- break;
- case _AES_:
- if (bmcst)
- AES_IV(pattrib->iv, psta->txpn,
- (u8)psecpriv->XGrpKeyid);
- else
- AES_IV(pattrib->iv, psta->txpn,
- 0);
- break;
- }
- }
- memcpy(pframe, pattrib->iv, pattrib->iv_len);
- pframe += pattrib->iv_len;
- mpdu_len -= pattrib->iv_len;
- }
- if (frg_inx == 0) {
- llc_sz = r8712_put_snap(pframe, pattrib->ether_type);
- pframe += llc_sz;
- mpdu_len -= llc_sz;
- }
- if ((pattrib->icv_len > 0) && (pattrib->bswenc))
- mpdu_len -= pattrib->icv_len;
- if (bmcst)
- mem_sz = _r8712_pktfile_read(&pktfile, pframe,
- pattrib->pktlen);
- else
- mem_sz = _r8712_pktfile_read(&pktfile, pframe,
- mpdu_len);
- pframe += mem_sz;
- if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {
- memcpy(pframe, pattrib->icv, pattrib->icv_len);
- pframe += pattrib->icv_len;
- }
- frg_inx++;
- if (bmcst || r8712_endofpktfile(&pktfile)) {
- pattrib->nr_frags = frg_inx;
- pattrib->last_txcmdsz = pattrib->hdrlen +
- pattrib->iv_len +
- ((pattrib->nr_frags == 1) ?
- llc_sz : 0) +
- ((pattrib->bswenc) ?
- pattrib->icv_len : 0) + mem_sz;
- ClearMFrag(mem_start);
- break;
- }
- addr = (addr_t)(pframe);
- mem_start = (unsigned char *)RND4(addr) + TXDESC_OFFSET;
- memcpy(mem_start, pbuf_start + TXDESC_OFFSET, pattrib->hdrlen);
- }
-
- if (xmitframe_addmic(padapter, pxmitframe))
- return _FAIL;
- xmitframe_swencrypt(padapter, pxmitframe);
- return _SUCCESS;
-}
-
-void r8712_update_protection(struct _adapter *padapter, u8 *ie, uint ie_len)
-{
- uint protection;
- u8 *perp;
- uint erp_len;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
-
- switch (pxmitpriv->vcs_setting) {
- case DISABLE_VCS:
- pxmitpriv->vcs = NONE_VCS;
- break;
- case ENABLE_VCS:
- break;
- case AUTO_VCS:
- default:
- perp = r8712_get_ie(ie, WLAN_EID_ERP_INFO, &erp_len, ie_len);
- if (!perp) {
- pxmitpriv->vcs = NONE_VCS;
- } else {
- protection = (*(perp + 2)) & BIT(1);
- if (protection) {
- if (pregistrypriv->vcs_type == RTS_CTS)
- pxmitpriv->vcs = RTS_CTS;
- else
- pxmitpriv->vcs = CTS_TO_SELF;
- } else {
- pxmitpriv->vcs = NONE_VCS;
- }
- }
- break;
- }
-}
-
-struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
-{
- unsigned long irqL;
- struct xmit_buf *pxmitbuf;
- struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
-
- spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
- pxmitbuf = list_first_entry_or_null(&pfree_xmitbuf_queue->queue,
- struct xmit_buf, list);
- if (pxmitbuf) {
- list_del_init(&pxmitbuf->list);
- pxmitpriv->free_xmitbuf_cnt--;
- }
- spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
- return pxmitbuf;
-}
-
-void r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
-{
- unsigned long irqL;
- struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
-
- if (!pxmitbuf)
- return;
- spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
- list_del_init(&pxmitbuf->list);
- list_add_tail(&(pxmitbuf->list), &pfree_xmitbuf_queue->queue);
- pxmitpriv->free_xmitbuf_cnt++;
- spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
-}
-
-/*
- * Calling context:
- * 1. OS_TXENTRY
- * 2. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
- *
- * If we turn on USE_RXTHREAD, then, no need for critical section.
- * Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
- *
- * Must be very very cautious...
- *
- */
-struct xmit_frame *r8712_alloc_xmitframe(struct xmit_priv *pxmitpriv)
-{
- /*
- * Please remember to use all the osdep_service api,
- * and lock/unlock or _enter/_exit critical to protect
- * pfree_xmit_queue
- */
- unsigned long irqL;
- struct xmit_frame *pxframe;
- struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
-
- spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
- pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue,
- struct xmit_frame, list);
- if (pxframe) {
- list_del_init(&pxframe->list);
- pxmitpriv->free_xmitframe_cnt--;
- pxframe->buf_addr = NULL;
- pxframe->pxmitbuf = NULL;
- pxframe->attrib.psta = NULL;
- pxframe->pkt = NULL;
- }
- spin_unlock_irqrestore(&pfree_xmit_queue->lock, irqL);
- return pxframe;
-}
-
-void r8712_free_xmitframe(struct xmit_priv *pxmitpriv,
- struct xmit_frame *pxmitframe)
-{
- unsigned long irqL;
- struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
- struct _adapter *padapter = pxmitpriv->adapter;
-
- if (!pxmitframe)
- return;
- spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
- list_del_init(&pxmitframe->list);
- if (pxmitframe->pkt)
- pxmitframe->pkt = NULL;
- list_add_tail(&pxmitframe->list, &pfree_xmit_queue->queue);
- pxmitpriv->free_xmitframe_cnt++;
- spin_unlock_irqrestore(&pfree_xmit_queue->lock, irqL);
- if (netif_queue_stopped(padapter->pnetdev))
- netif_wake_queue(padapter->pnetdev);
-}
-
-void r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv,
- struct xmit_frame *pxmitframe)
-{
- if (!pxmitframe)
- return;
- if (pxmitframe->frame_tag == DATA_FRAMETAG)
- r8712_free_xmitframe(pxmitpriv, pxmitframe);
-}
-
-void r8712_free_xmitframe_queue(struct xmit_priv *pxmitpriv,
- struct __queue *pframequeue)
-{
- unsigned long irqL;
- struct list_head *plist, *phead;
- struct xmit_frame *pxmitframe;
-
- spin_lock_irqsave(&(pframequeue->lock), irqL);
- phead = &pframequeue->queue;
- plist = phead->next;
- while (!end_of_queue_search(phead, plist)) {
- pxmitframe = container_of(plist, struct xmit_frame, list);
- plist = plist->next;
- r8712_free_xmitframe(pxmitpriv, pxmitframe);
- }
- spin_unlock_irqrestore(&(pframequeue->lock), irqL);
-}
-
-static inline struct tx_servq *get_sta_pending(struct _adapter *padapter,
- struct __queue **ppstapending,
- struct sta_info *psta, sint up)
-{
- struct tx_servq *ptxservq;
- struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
-
- switch (up) {
- case 1:
- case 2:
- ptxservq = &(psta->sta_xmitpriv.bk_q);
- *ppstapending = &padapter->xmitpriv.bk_pending;
- (phwxmits + 3)->accnt++;
- break;
- case 4:
- case 5:
- ptxservq = &(psta->sta_xmitpriv.vi_q);
- *ppstapending = &padapter->xmitpriv.vi_pending;
- (phwxmits + 1)->accnt++;
- break;
- case 6:
- case 7:
- ptxservq = &(psta->sta_xmitpriv.vo_q);
- *ppstapending = &padapter->xmitpriv.vo_pending;
- (phwxmits + 0)->accnt++;
- break;
- case 0:
- case 3:
- default:
- ptxservq = &(psta->sta_xmitpriv.be_q);
- *ppstapending = &padapter->xmitpriv.be_pending;
- (phwxmits + 2)->accnt++;
- break;
- }
- return ptxservq;
-}
-
-/*
- * Will enqueue pxmitframe to the proper queue, and indicate it
- * to xx_pending list.....
- */
-int r8712_xmit_classifier(struct _adapter *padapter,
- struct xmit_frame *pxmitframe)
-{
- unsigned long irqL0;
- struct __queue *pstapending;
- struct sta_info *psta;
- struct tx_servq *ptxservq;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- bool bmcst = is_multicast_ether_addr(pattrib->ra);
-
- if (pattrib->psta) {
- psta = pattrib->psta;
- } else {
- if (bmcst) {
- psta = r8712_get_bcmc_stainfo(padapter);
- } else {
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
- psta = r8712_get_stainfo(pstapriv,
- get_bssid(pmlmepriv));
- else
- psta = r8712_get_stainfo(pstapriv, pattrib->ra);
- }
- }
- if (!psta)
- return -EINVAL;
- ptxservq = get_sta_pending(padapter, &pstapending,
- psta, pattrib->priority);
- spin_lock_irqsave(&pstapending->lock, irqL0);
- if (list_empty(&ptxservq->tx_pending))
- list_add_tail(&ptxservq->tx_pending, &pstapending->queue);
- list_add_tail(&pxmitframe->list, &ptxservq->sta_pending.queue);
- ptxservq->qcnt++;
- spin_unlock_irqrestore(&pstapending->lock, irqL0);
- return 0;
-}
-
-static void alloc_hwxmits(struct _adapter *padapter)
-{
- struct hw_xmit *hwxmits;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
- pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
- pxmitpriv->hwxmits = kmalloc_array(pxmitpriv->hwxmit_entry,
- sizeof(struct hw_xmit), GFP_ATOMIC);
- if (!pxmitpriv->hwxmits)
- return;
- hwxmits = pxmitpriv->hwxmits;
- if (pxmitpriv->hwxmit_entry == 5) {
- pxmitpriv->bmc_txqueue.head = 0;
- hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue;
- hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;
- pxmitpriv->vo_txqueue.head = 0;
- hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue;
- hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
- pxmitpriv->vi_txqueue.head = 0;
- hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue;
- hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
- pxmitpriv->bk_txqueue.head = 0;
- hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue;
- hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
- pxmitpriv->be_txqueue.head = 0;
- hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue;
- hwxmits[4] .sta_queue = &pxmitpriv->be_pending;
- } else if (pxmitpriv->hwxmit_entry == 4) {
- pxmitpriv->vo_txqueue.head = 0;
- hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue;
- hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
- pxmitpriv->vi_txqueue.head = 0;
- hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue;
- hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
- pxmitpriv->be_txqueue.head = 0;
- hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue;
- hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
- pxmitpriv->bk_txqueue.head = 0;
- hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue;
- hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
- }
-}
-
-static void free_hwxmits(struct _adapter *padapter)
-{
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
- kfree(pxmitpriv->hwxmits);
-}
-
-static void init_hwxmits(struct hw_xmit *phwxmit, sint entry)
-{
- sint i;
-
- for (i = 0; i < entry; i++, phwxmit++) {
- spin_lock_init(&phwxmit->xmit_lock);
- INIT_LIST_HEAD(&phwxmit->pending);
- phwxmit->txcmdcnt = 0;
- phwxmit->accnt = 0;
- }
-}
-
-void xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe,
- struct xmit_buf *pxmitbuf)
-{
- /* pxmitbuf attach to pxmitframe */
- pxmitframe->pxmitbuf = pxmitbuf;
- /* urb and irp connection */
- pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
- /* buffer addr assoc */
- pxmitframe->buf_addr = pxmitbuf->pbuf;
- /* pxmitframe attach to pxmitbuf */
- pxmitbuf->priv_data = pxmitframe;
-}
-
-/*
- * tx_action == 0 == no frames to transmit
- * tx_action > 0 ==> we have frames to transmit
- * tx_action < 0 ==> we have frames to transmit, but TXFF is not even enough
- * to transmit 1 frame.
- */
-
-int r8712_pre_xmit(struct _adapter *padapter, struct xmit_frame *pxmitframe)
-{
- unsigned long irqL;
- int ret;
- struct xmit_buf *pxmitbuf = NULL;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
-
- r8712_do_queue_select(padapter, pattrib);
- spin_lock_irqsave(&pxmitpriv->lock, irqL);
- if (r8712_txframes_sta_ac_pending(padapter, pattrib) > 0) {
- ret = false;
- r8712_xmit_enqueue(padapter, pxmitframe);
- spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
- return ret;
- }
- pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv);
- if (!pxmitbuf) { /*enqueue packet*/
- ret = false;
- r8712_xmit_enqueue(padapter, pxmitframe);
- spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
- } else { /*dump packet directly*/
- spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
- ret = true;
- xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
- r8712_xmit_direct(padapter, pxmitframe);
- }
- return ret;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h
deleted file mode 100644
index 784172c385e3..000000000000
--- a/drivers/staging/rtl8712/rtl871x_xmit.h
+++ /dev/null
@@ -1,287 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871X_XMIT_H_
-#define _RTL871X_XMIT_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "xmit_osdep.h"
-
-#ifdef CONFIG_R8712_TX_AGGR
-#define MAX_XMITBUF_SZ (16384)
-#else
-#define MAX_XMITBUF_SZ (2048)
-#endif
-
-#define NR_XMITBUFF (4)
-
-#ifdef CONFIG_R8712_TX_AGGR
-#define AGGR_NR_HIGH_BOUND (4) /*(8) */
-#define AGGR_NR_LOW_BOUND (2)
-#endif
-
-#define XMITBUF_ALIGN_SZ 512
-#define TX_GUARD_BAND 5
-#define MAX_NUMBLKS (1)
-
-/* Fixed the Big Endian bug when using the software driver encryption.*/
-#define WEP_IV(pattrib_iv, txpn, keyidx)\
-do { \
- pattrib_iv[0] = txpn._byte_.TSC0;\
- pattrib_iv[1] = txpn._byte_.TSC1;\
- pattrib_iv[2] = txpn._byte_.TSC2;\
- pattrib_iv[3] = ((keyidx & 0x3) << 6);\
- txpn.val = (txpn.val == 0xffffff) ? 0 : (txpn.val + 1);\
-} while (0)
-
-/* Fixed the Big Endian bug when doing the Tx.
- * The Linksys WRH54G will check this.
- */
-#define TKIP_IV(pattrib_iv, txpn, keyidx)\
-do { \
- pattrib_iv[0] = txpn._byte_.TSC1;\
- pattrib_iv[1] = (txpn._byte_.TSC1 | 0x20) & 0x7f;\
- pattrib_iv[2] = txpn._byte_.TSC0;\
- pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6);\
- pattrib_iv[4] = txpn._byte_.TSC2;\
- pattrib_iv[5] = txpn._byte_.TSC3;\
- pattrib_iv[6] = txpn._byte_.TSC4;\
- pattrib_iv[7] = txpn._byte_.TSC5;\
- txpn.val = txpn.val == 0xffffffffffffULL ? 0 : \
- (txpn.val + 1);\
-} while (0)
-
-#define AES_IV(pattrib_iv, txpn, keyidx)\
-do { \
- pattrib_iv[0] = txpn._byte_.TSC0;\
- pattrib_iv[1] = txpn._byte_.TSC1;\
- pattrib_iv[2] = 0;\
- pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6);\
- pattrib_iv[4] = txpn._byte_.TSC2;\
- pattrib_iv[5] = txpn._byte_.TSC3;\
- pattrib_iv[6] = txpn._byte_.TSC4;\
- pattrib_iv[7] = txpn._byte_.TSC5;\
- txpn.val = txpn.val == 0xffffffffffffULL ? 0 : \
- (txpn.val + 1);\
-} while (0)
-
-struct hw_xmit {
- spinlock_t xmit_lock;
- struct list_head pending;
- struct __queue *sta_queue;
- struct hw_txqueue *phwtxqueue;
- sint txcmdcnt;
- int accnt;
-};
-
-struct pkt_attrib {
- u8 type;
- u8 subtype;
- u8 bswenc;
- u8 dhcp_pkt;
-
- u16 seqnum;
- u16 ether_type;
- u16 pktlen; /* the original 802.3 pkt raw_data len
- * (not include ether_hdr data)
- */
- u16 last_txcmdsz;
-
- u8 pkt_hdrlen; /*the original 802.3 pkt header len*/
- u8 hdrlen; /*the WLAN Header Len*/
- u8 nr_frags;
- u8 ack_policy;
- u8 mac_id;
- u8 vcs_mode; /*virtual carrier sense method*/
- u8 pctrl;/*per packet txdesc control enable*/
- u8 qsel;
-
- u8 priority;
- u8 encrypt; /* when 0 indicate no encrypt. when non-zero,
- * indicate the encrypt algorithm
- */
- u8 iv_len;
- u8 icv_len;
- unsigned char iv[8];
- unsigned char icv[8];
- u8 dst[ETH_ALEN] __aligned(2); /* for ether_addr_copy */
- u8 src[ETH_ALEN];
- u8 ta[ETH_ALEN];
- u8 ra[ETH_ALEN];
- struct sta_info *psta;
-};
-
-#define WLANHDR_OFFSET 64
-#define DATA_FRAMETAG 0x01
-#define L2_FRAMETAG 0x02
-#define MGNT_FRAMETAG 0x03
-#define AMSDU_FRAMETAG 0x04
-#define EII_FRAMETAG 0x05
-#define IEEE8023_FRAMETAG 0x06
-#define MP_FRAMETAG 0x07
-#define TXAGG_FRAMETAG 0x08
-
-struct xmit_buf {
- struct list_head list;
-
- u8 *pallocated_buf;
- u8 *pbuf;
- void *priv_data;
- struct urb *pxmit_urb[8];
- u32 aggr_nr;
-};
-
-struct xmit_frame {
- struct list_head list;
- struct pkt_attrib attrib;
- _pkt *pkt;
- int frame_tag;
- struct _adapter *padapter;
- u8 *buf_addr;
- struct xmit_buf *pxmitbuf;
- u8 *mem_addr;
- u16 sz[8];
- struct urb *pxmit_urb[8];
- u8 bpending[8];
- u8 last[8];
-};
-
-struct tx_servq {
- struct list_head tx_pending;
- struct __queue sta_pending;
- int qcnt;
-};
-
-struct sta_xmit_priv {
- spinlock_t lock;
- sint option;
- sint apsd_setting; /* When bit mask is on, the associated edca
- * queue supports APSD.
- */
- struct tx_servq be_q; /* priority == 0,3 */
- struct tx_servq bk_q; /* priority == 1,2*/
- struct tx_servq vi_q; /*priority == 4,5*/
- struct tx_servq vo_q; /*priority == 6,7*/
- struct list_head legacy_dz;
- struct list_head apsd;
- u16 txseq_tid[16];
- uint sta_tx_bytes;
- u64 sta_tx_pkts;
- uint sta_tx_fail;
-};
-
-struct hw_txqueue {
- sint head;
- sint tail;
- sint free_sz; /* in units of 64 bytes */
- sint free_cmdsz;
- sint txsz[8];
- uint ff_hwaddr;
- uint cmd_hwaddr;
- sint ac_tag;
-};
-
-struct xmit_priv {
- spinlock_t lock;
- struct __queue be_pending;
- struct __queue bk_pending;
- struct __queue vi_pending;
- struct __queue vo_pending;
- struct __queue bm_pending;
- struct __queue legacy_dz_queue;
- struct __queue apsd_queue;
- u8 *pallocated_frame_buf;
- u8 *pxmit_frame_buf;
- uint free_xmitframe_cnt;
- uint mapping_addr;
- uint pkt_sz;
- struct __queue free_xmit_queue;
- struct hw_txqueue be_txqueue;
- struct hw_txqueue bk_txqueue;
- struct hw_txqueue vi_txqueue;
- struct hw_txqueue vo_txqueue;
- struct hw_txqueue bmc_txqueue;
- uint frag_len;
- struct _adapter *adapter;
- u8 vcs_setting;
- u8 vcs;
- u8 vcs_type;
- u16 rts_thresh;
- uint tx_bytes;
- u64 tx_pkts;
- uint tx_drop;
- struct hw_xmit *hwxmits;
- u8 hwxmit_entry;
- u8 txirp_cnt;
- struct tasklet_struct xmit_tasklet;
- struct work_struct xmit_pipe4_reset_wi;
- struct work_struct xmit_pipe6_reset_wi;
- struct work_struct xmit_piped_reset_wi;
- /*per AC pending irp*/
- int beq_cnt;
- int bkq_cnt;
- int viq_cnt;
- int voq_cnt;
- struct __queue free_amsdu_xmit_queue;
- u8 *pallocated_amsdu_frame_buf;
- u8 *pxmit_amsdu_frame_buf;
- uint free_amsdu_xmitframe_cnt;
- struct __queue free_txagg_xmit_queue;
- u8 *pallocated_txagg_frame_buf;
- u8 *pxmit_txagg_frame_buf;
- uint free_txagg_xmitframe_cnt;
- int cmdseq;
- struct __queue free_xmitbuf_queue;
- struct __queue pending_xmitbuf_queue;
- u8 *pxmitbuf;
- uint free_xmitbuf_cnt;
-};
-
-void r8712_free_xmitbuf(struct xmit_priv *pxmitpriv,
- struct xmit_buf *pxmitbuf);
-struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv);
-void r8712_update_protection(struct _adapter *padapter, u8 *ie, uint ie_len);
-struct xmit_frame *r8712_alloc_xmitframe(struct xmit_priv *pxmitpriv);
-void r8712_free_xmitframe(struct xmit_priv *pxmitpriv,
- struct xmit_frame *pxmitframe);
-void r8712_free_xmitframe_queue(struct xmit_priv *pxmitpriv,
- struct __queue *pframequeue);
-int r8712_xmit_classifier(struct _adapter *padapter,
- struct xmit_frame *pxmitframe);
-sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt,
- struct xmit_frame *pxmitframe);
-sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag);
-void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv);
-int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
- struct pkt_attrib *pattrib);
-int r8712_txframes_sta_ac_pending(struct _adapter *padapter,
- struct pkt_attrib *pattrib);
-int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
- struct _adapter *padapter);
-void _free_xmit_priv(struct xmit_priv *pxmitpriv);
-void r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv,
- struct xmit_frame *pxmitframe);
-int r8712_pre_xmit(struct _adapter *padapter, struct xmit_frame *pxmitframe);
-int r8712_xmit_enqueue(struct _adapter *padapter,
- struct xmit_frame *pxmitframe);
-void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe);
-void r8712_xmit_bh(struct tasklet_struct *t);
-
-void xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe,
- struct xmit_buf *pxmitbuf);
-
-#include "rtl8712_xmit.h"
-
-#endif /*_RTL871X_XMIT_H_*/
-
diff --git a/drivers/staging/rtl8712/sta_info.h b/drivers/staging/rtl8712/sta_info.h
deleted file mode 100644
index 6286c622475e..000000000000
--- a/drivers/staging/rtl8712/sta_info.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __STA_INFO_H_
-#define __STA_INFO_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "wifi.h"
-
-#define NUM_STA 32
-#define NUM_ACL 64
-
-/* if mode ==0, then the sta is allowed once the addr is hit.
- * if mode ==1, then the sta is rejected once the addr is non-hit.
- */
-struct wlan_acl_node {
- struct list_head list;
- u8 addr[ETH_ALEN];
- u8 mode;
-};
-
-struct wlan_acl_pool {
- struct wlan_acl_node aclnode[NUM_ACL];
-};
-
-struct stainfo_stats {
- uint rx_pkts;
- uint rx_bytes;
- u64 tx_pkts;
- uint tx_bytes;
-};
-
-struct sta_info {
- spinlock_t lock;
- struct list_head list; /*free_sta_queue*/
- struct list_head hash_list; /*sta_hash*/
- struct sta_xmit_priv sta_xmitpriv;
- struct sta_recv_priv sta_recvpriv;
- uint state;
- uint aid;
- uint mac_id;
- uint qos_option;
- u8 hwaddr[ETH_ALEN];
- uint ieee8021x_blocked; /*0: allowed, 1:blocked */
- uint XPrivacy; /*aes, tkip...*/
- union Keytype tkiptxmickey;
- union Keytype tkiprxmickey;
- union Keytype x_UncstKey;
- union pn48 txpn; /* PN48 used for Unicast xmit.*/
- union pn48 rxpn; /* PN48 used for Unicast recv.*/
- u8 bssrateset[16];
- uint bssratelen;
- s32 rssi;
- s32 signal_quality;
- struct stainfo_stats sta_stats;
- /*for A-MPDU Rx reordering buffer control */
- struct recv_reorder_ctrl recvreorder_ctrl[16];
- struct ht_priv htpriv;
- /* Notes:
- * STA_Mode:
- * curr_network(mlme_priv/security_priv/qos/ht)
- * + sta_info: (STA & AP) CAP/INFO
- * scan_q: AP CAP/INFO
- * AP_Mode:
- * curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO
- * sta_info: (AP & STA) CAP/INFO
- */
- struct list_head asoc_list;
- struct list_head auth_list;
- unsigned int expire_to;
- unsigned int auth_seq;
- unsigned int authalg;
- unsigned char chg_txt[128];
- unsigned int tx_ra_bitmap;
-};
-
-struct sta_priv {
- u8 *pallocated_stainfo_buf;
- u8 *pstainfo_buf;
- struct __queue free_sta_queue;
- spinlock_t sta_hash_lock;
- struct list_head sta_hash[NUM_STA];
- int asoc_sta_count;
- struct __queue sleep_q;
- struct __queue wakeup_q;
- struct _adapter *padapter;
- struct list_head asoc_list;
- struct list_head auth_list;
- unsigned int auth_to; /* sec, time to expire in authenticating. */
- unsigned int assoc_to; /* sec, time to expire before associating. */
- unsigned int expire_to; /* sec , time to expire after associated. */
-};
-
-static inline u32 wifi_mac_hash(u8 *mac)
-{
- u32 x;
-
- x = mac[0];
- x = (x << 2) ^ mac[1];
- x = (x << 2) ^ mac[2];
- x = (x << 2) ^ mac[3];
- x = (x << 2) ^ mac[4];
- x = (x << 2) ^ mac[5];
- x ^= x >> 8;
- x = x & (NUM_STA - 1);
- return x;
-}
-
-int _r8712_init_sta_priv(struct sta_priv *pstapriv);
-void _r8712_free_sta_priv(struct sta_priv *pstapriv);
-struct sta_info *r8712_alloc_stainfo(struct sta_priv *pstapriv,
- u8 *hwaddr);
-void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta);
-void r8712_free_all_stainfo(struct _adapter *padapter);
-struct sta_info *r8712_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr);
-void r8712_init_bcmc_stainfo(struct _adapter *padapter);
-struct sta_info *r8712_get_bcmc_stainfo(struct _adapter *padapter);
-u8 r8712_access_ctrl(struct wlan_acl_pool *pacl_list, u8 *mac_addr);
-
-#endif /* _STA_INFO_H_ */
-
diff --git a/drivers/staging/rtl8712/usb_halinit.c b/drivers/staging/rtl8712/usb_halinit.c
deleted file mode 100644
index 313c569748e9..000000000000
--- a/drivers/staging/rtl8712/usb_halinit.c
+++ /dev/null
@@ -1,307 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * usb_halinit.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _HCI_HAL_INIT_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "usb_ops.h"
-#include "usb_osintf.h"
-
-u8 r8712_usb_hal_bus_init(struct _adapter *adapter)
-{
- u8 val8 = 0;
- u8 ret = _SUCCESS;
- int PollingCnt = 20;
- struct registry_priv *registrypriv = &adapter->registrypriv;
-
- if (registrypriv->chip_version == RTL8712_FPGA) {
- val8 = 0x01;
- /* switch to 80M clock */
- r8712_write8(adapter, SYS_CLKR, val8);
- val8 = r8712_read8(adapter, SPS1_CTRL);
- val8 = val8 | 0x01;
- /* enable VSPS12 LDO Macro block */
- r8712_write8(adapter, SPS1_CTRL, val8);
- val8 = r8712_read8(adapter, AFE_MISC);
- val8 = val8 | 0x01;
- /* Enable AFE Macro Block's Bandgap */
- r8712_write8(adapter, AFE_MISC, val8);
- val8 = r8712_read8(adapter, LDOA15_CTRL);
- val8 = val8 | 0x01;
- /* enable LDOA15 block */
- r8712_write8(adapter, LDOA15_CTRL, val8);
- val8 = r8712_read8(adapter, SPS1_CTRL);
- val8 = val8 | 0x02;
- /* Enable VSPS12_SW Macro Block */
- r8712_write8(adapter, SPS1_CTRL, val8);
- val8 = r8712_read8(adapter, AFE_MISC);
- val8 = val8 | 0x02;
- /* Enable AFE Macro Block's Mbias */
- r8712_write8(adapter, AFE_MISC, val8);
- val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1);
- val8 = val8 | 0x08;
- /* isolate PCIe Analog 1.2V to PCIe 3.3V and PCIE Digital */
- r8712_write8(adapter, SYS_ISO_CTRL + 1, val8);
- val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1);
- val8 = val8 & 0xEF;
- /* attach AFE PLL to MACTOP/BB/PCIe Digital */
- r8712_write8(adapter, SYS_ISO_CTRL + 1, val8);
- val8 = r8712_read8(adapter, AFE_XTAL_CTRL + 1);
- val8 = val8 & 0xFB;
- /* enable AFE clock */
- r8712_write8(adapter, AFE_XTAL_CTRL + 1, val8);
- val8 = r8712_read8(adapter, AFE_PLL_CTRL);
- val8 = val8 | 0x01;
- /* Enable AFE PLL Macro Block */
- r8712_write8(adapter, AFE_PLL_CTRL, val8);
- val8 = 0xEE;
- /* release isolation AFE PLL & MD */
- r8712_write8(adapter, SYS_ISO_CTRL, val8);
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- val8 = val8 | 0x08;
- /* enable MAC clock */
- r8712_write8(adapter, SYS_CLKR + 1, val8);
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- val8 = val8 | 0x08;
- /* enable Core digital and enable IOREG R/W */
- r8712_write8(adapter, SYS_FUNC_EN + 1, val8);
- val8 = val8 | 0x80;
- /* enable REG_EN */
- r8712_write8(adapter, SYS_FUNC_EN + 1, val8);
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- val8 = (val8 | 0x80) & 0xBF;
- /* switch the control path */
- r8712_write8(adapter, SYS_CLKR + 1, val8);
- val8 = 0xFC;
- r8712_write8(adapter, CR, val8);
- val8 = 0x37;
- r8712_write8(adapter, CR + 1, val8);
- /* reduce EndPoint & init it */
- r8712_write8(adapter, 0x102500ab, r8712_read8(adapter,
- 0x102500ab) | BIT(6) | BIT(7));
- /* consideration of power consumption - init */
- r8712_write8(adapter, 0x10250008, r8712_read8(adapter,
- 0x10250008) & 0xfffffffb);
- } else if (registrypriv->chip_version == RTL8712_1stCUT) {
- /* Initialization for power on sequence, */
- r8712_write8(adapter, SPS0_CTRL + 1, 0x53);
- r8712_write8(adapter, SPS0_CTRL, 0x57);
- /* Enable AFE Macro Block's Bandgap and Enable AFE Macro
- * Block's Mbias
- */
- val8 = r8712_read8(adapter, AFE_MISC);
- r8712_write8(adapter, AFE_MISC, (val8 | AFE_MISC_BGEN |
- AFE_MISC_MBEN));
- /* Enable LDOA15 block */
- val8 = r8712_read8(adapter, LDOA15_CTRL);
- r8712_write8(adapter, LDOA15_CTRL, (val8 | LDA15_EN));
- val8 = r8712_read8(adapter, SPS1_CTRL);
- r8712_write8(adapter, SPS1_CTRL, (val8 | SPS1_LDEN));
- msleep(20);
- /* Enable Switch Regulator Block */
- val8 = r8712_read8(adapter, SPS1_CTRL);
- r8712_write8(adapter, SPS1_CTRL, (val8 | SPS1_SWEN));
- r8712_write32(adapter, SPS1_CTRL, 0x00a7b267);
- val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1);
- r8712_write8(adapter, SYS_ISO_CTRL + 1, (val8 | 0x08));
- /* Engineer Packet CP test Enable */
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x20));
- val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1);
- r8712_write8(adapter, SYS_ISO_CTRL + 1, (val8 & 0x6F));
- /* Enable AFE clock */
- val8 = r8712_read8(adapter, AFE_XTAL_CTRL + 1);
- r8712_write8(adapter, AFE_XTAL_CTRL + 1, (val8 & 0xfb));
- /* Enable AFE PLL Macro Block */
- val8 = r8712_read8(adapter, AFE_PLL_CTRL);
- r8712_write8(adapter, AFE_PLL_CTRL, (val8 | 0x11));
- /* Attach AFE PLL to MACTOP/BB/PCIe Digital */
- val8 = r8712_read8(adapter, SYS_ISO_CTRL);
- r8712_write8(adapter, SYS_ISO_CTRL, (val8 & 0xEE));
- /* Switch to 40M clock */
- val8 = r8712_read8(adapter, SYS_CLKR);
- r8712_write8(adapter, SYS_CLKR, val8 & (~SYS_CLKSEL));
- /* SSC Disable */
- val8 = r8712_read8(adapter, SYS_CLKR);
- /* Enable MAC clock */
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- r8712_write8(adapter, SYS_CLKR + 1, (val8 | 0x18));
- /* Revised POS, */
- r8712_write8(adapter, PMC_FSM, 0x02);
- /* Enable Core digital and enable IOREG R/W */
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x08));
- /* Enable REG_EN */
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x80));
- /* Switch the control path to FW */
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- r8712_write8(adapter, SYS_CLKR + 1, (val8 | 0x80) & 0xBF);
- r8712_write8(adapter, CR, 0xFC);
- r8712_write8(adapter, CR + 1, 0x37);
- /* Fix the RX FIFO issue(usb error), */
- val8 = r8712_read8(adapter, 0x1025FE5c);
- r8712_write8(adapter, 0x1025FE5c, (val8 | BIT(7)));
- val8 = r8712_read8(adapter, 0x102500ab);
- r8712_write8(adapter, 0x102500ab, (val8 | BIT(6) | BIT(7)));
- /* For power save, used this in the bit file after 970621 */
- val8 = r8712_read8(adapter, SYS_CLKR);
- r8712_write8(adapter, SYS_CLKR, val8 & (~CPU_CLKSEL));
- } else if (registrypriv->chip_version == RTL8712_2ndCUT ||
- registrypriv->chip_version == RTL8712_3rdCUT) {
- /* Initialization for power on sequence,
- * E-Fuse leakage prevention sequence
- */
- r8712_write8(adapter, 0x37, 0xb0);
- msleep(20);
- r8712_write8(adapter, 0x37, 0x30);
- /* Set control path switch to HW control and reset Digital Core,
- * CPU Core and MAC I/O to solve FW download fail when system
- * from resume sate.
- */
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- if (val8 & 0x80) {
- val8 &= 0x3f;
- r8712_write8(adapter, SYS_CLKR + 1, val8);
- }
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- val8 &= 0x73;
- r8712_write8(adapter, SYS_FUNC_EN + 1, val8);
- msleep(20);
- /* Revised POS, */
- /* Enable AFE Macro Block's Bandgap and Enable AFE Macro
- * Block's Mbias
- */
- r8712_write8(adapter, SPS0_CTRL + 1, 0x53);
- r8712_write8(adapter, SPS0_CTRL, 0x57);
- val8 = r8712_read8(adapter, AFE_MISC);
- /*Bandgap*/
- r8712_write8(adapter, AFE_MISC, (val8 | AFE_MISC_BGEN));
- r8712_write8(adapter, AFE_MISC, (val8 | AFE_MISC_BGEN |
- AFE_MISC_MBEN | AFE_MISC_I32_EN));
- /* Enable PLL Power (LDOA15V) */
- val8 = r8712_read8(adapter, LDOA15_CTRL);
- r8712_write8(adapter, LDOA15_CTRL, (val8 | LDA15_EN));
- /* Enable LDOV12D block */
- val8 = r8712_read8(adapter, LDOV12D_CTRL);
- r8712_write8(adapter, LDOV12D_CTRL, (val8 | LDV12_EN));
- val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1);
- r8712_write8(adapter, SYS_ISO_CTRL + 1, (val8 | 0x08));
- /* Engineer Packet CP test Enable */
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x20));
- /* Support 64k IMEM */
- val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1);
- r8712_write8(adapter, SYS_ISO_CTRL + 1, (val8 & 0x68));
- /* Enable AFE clock */
- val8 = r8712_read8(adapter, AFE_XTAL_CTRL + 1);
- r8712_write8(adapter, AFE_XTAL_CTRL + 1, (val8 & 0xfb));
- /* Enable AFE PLL Macro Block */
- val8 = r8712_read8(adapter, AFE_PLL_CTRL);
- r8712_write8(adapter, AFE_PLL_CTRL, (val8 | 0x11));
- /* Some sample will download fw failure. The clock will be
- * stable with 500 us delay after reset the PLL
- * TODO: When usleep is added to kernel, change next 3
- * udelay(500) to usleep(500)
- */
- udelay(500);
- r8712_write8(adapter, AFE_PLL_CTRL, (val8 | 0x51));
- udelay(500);
- r8712_write8(adapter, AFE_PLL_CTRL, (val8 | 0x11));
- udelay(500);
- /* Attach AFE PLL to MACTOP/BB/PCIe Digital */
- val8 = r8712_read8(adapter, SYS_ISO_CTRL);
- r8712_write8(adapter, SYS_ISO_CTRL, (val8 & 0xEE));
- /* Switch to 40M clock */
- r8712_write8(adapter, SYS_CLKR, 0x00);
- /* CPU Clock and 80M Clock SSC Disable to overcome FW download
- * fail timing issue.
- */
- val8 = r8712_read8(adapter, SYS_CLKR);
- r8712_write8(adapter, SYS_CLKR, (val8 | 0xa0));
- /* Enable MAC clock */
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- r8712_write8(adapter, SYS_CLKR + 1, (val8 | 0x18));
- /* Revised POS, */
- r8712_write8(adapter, PMC_FSM, 0x02);
- /* Enable Core digital and enable IOREG R/W */
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x08));
- /* Enable REG_EN */
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x80));
- /* Switch the control path to FW */
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- r8712_write8(adapter, SYS_CLKR + 1, (val8 | 0x80) & 0xBF);
- r8712_write8(adapter, CR, 0xFC);
- r8712_write8(adapter, CR + 1, 0x37);
- /* Fix the RX FIFO issue(usb error), 970410 */
- val8 = r8712_read8(adapter, 0x1025FE5c);
- r8712_write8(adapter, 0x1025FE5c, (val8 | BIT(7)));
- /* For power save, used this in the bit file after 970621 */
- val8 = r8712_read8(adapter, SYS_CLKR);
- r8712_write8(adapter, SYS_CLKR, val8 & (~CPU_CLKSEL));
- /* Revised for 8051 ROM code wrong operation. */
- r8712_write8(adapter, 0x1025fe1c, 0x80);
- /* To make sure that TxDMA can ready to download FW.
- * We should reset TxDMA if IMEM RPT was not ready.
- */
- do {
- val8 = r8712_read8(adapter, TCR);
- if ((val8 & _TXDMA_INIT_VALUE) == _TXDMA_INIT_VALUE)
- break;
- udelay(5); /* PlatformStallExecution(5); */
- } while (PollingCnt--); /* Delay 1ms */
-
- if (PollingCnt <= 0) {
- val8 = r8712_read8(adapter, CR);
- r8712_write8(adapter, CR, val8 & (~_TXDMA_EN));
- udelay(2); /* PlatformStallExecution(2); */
- /* Reset TxDMA */
- r8712_write8(adapter, CR, val8 | _TXDMA_EN);
- }
- } else {
- ret = _FAIL;
- }
- return ret;
-}
-
-unsigned int r8712_usb_inirp_init(struct _adapter *adapter)
-{
- u8 i;
- struct recv_buf *recvbuf;
- struct intf_hdl *intfhdl = &adapter->pio_queue->intf;
- struct recv_priv *recvpriv = &(adapter->recvpriv);
-
- recvpriv->ff_hwaddr = RTL8712_DMA_RX0FF; /* mapping rx fifo address */
- /* issue Rx irp to receive data */
- recvbuf = (struct recv_buf *)recvpriv->precv_buf;
- for (i = 0; i < NR_RECVBUFF; i++) {
- if (r8712_usb_read_port(intfhdl, recvpriv->ff_hwaddr, 0,
- (unsigned char *)recvbuf) == false)
- return _FAIL;
- recvbuf++;
- recvpriv->free_recv_buf_queue_cnt--;
- }
- return _SUCCESS;
-}
-
-unsigned int r8712_usb_inirp_deinit(struct _adapter *adapter)
-{
- r8712_usb_read_port_cancel(adapter);
- return _SUCCESS;
-}
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
deleted file mode 100644
index df05213f922f..000000000000
--- a/drivers/staging/rtl8712/usb_intf.c
+++ /dev/null
@@ -1,638 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * usb_intf.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _HCI_INTF_C_
-
-#include <linux/usb.h>
-#include <linux/module.h>
-#include <linux/firmware.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "xmit_osdep.h"
-#include "rtl8712_efuse.h"
-#include "usb_ops.h"
-#include "usb_osintf.h"
-
-static struct usb_interface *pintf;
-
-static int r871xu_drv_init(struct usb_interface *pusb_intf,
- const struct usb_device_id *pdid);
-
-static void r871xu_dev_remove(struct usb_interface *pusb_intf);
-
-static const struct usb_device_id rtl871x_usb_id_tbl[] = {
-/* RTL8188SU */
- /* Realtek */
- {USB_DEVICE(0x0BDA, 0x8171)},
- {USB_DEVICE(0x0bda, 0x8173)},
- {USB_DEVICE(0x0bda, 0x8712)},
- {USB_DEVICE(0x0bda, 0x8713)},
- {USB_DEVICE(0x0bda, 0xC512)},
- /* Abocom */
- {USB_DEVICE(0x07B8, 0x8188)},
- /* ASUS */
- {USB_DEVICE(0x0B05, 0x1786)},
- {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */
- /* Belkin */
- {USB_DEVICE(0x050D, 0x945A)},
- /* ISY IWL - Belkin clone */
- {USB_DEVICE(0x050D, 0x11F1)},
- /* Corega */
- {USB_DEVICE(0x07AA, 0x0047)},
- /* D-Link */
- {USB_DEVICE(0x2001, 0x3306)},
- {USB_DEVICE(0x07D1, 0x3306)}, /* 11n mode disable */
- /* Edimax */
- {USB_DEVICE(0x7392, 0x7611)},
- /* EnGenius */
- {USB_DEVICE(0x1740, 0x9603)},
- /* Hawking */
- {USB_DEVICE(0x0E66, 0x0016)},
- /* Hercules */
- {USB_DEVICE(0x06F8, 0xE034)},
- {USB_DEVICE(0x06F8, 0xE032)},
- /* Logitec */
- {USB_DEVICE(0x0789, 0x0167)},
- /* PCI */
- {USB_DEVICE(0x2019, 0xAB28)},
- {USB_DEVICE(0x2019, 0xED16)},
- /* Sitecom */
- {USB_DEVICE(0x0DF6, 0x0057)},
- {USB_DEVICE(0x0DF6, 0x0045)},
- {USB_DEVICE(0x0DF6, 0x0059)}, /* 11n mode disable */
- {USB_DEVICE(0x0DF6, 0x004B)},
- {USB_DEVICE(0x0DF6, 0x005B)},
- {USB_DEVICE(0x0DF6, 0x005D)},
- {USB_DEVICE(0x0DF6, 0x0063)},
- /* Sweex */
- {USB_DEVICE(0x177F, 0x0154)},
- /* Thinkware */
- {USB_DEVICE(0x0BDA, 0x5077)},
- /* Toshiba */
- {USB_DEVICE(0x1690, 0x0752)},
- /* - */
- {USB_DEVICE(0x20F4, 0x646B)},
- {USB_DEVICE(0x083A, 0xC512)},
- {USB_DEVICE(0x25D4, 0x4CA1)},
- {USB_DEVICE(0x25D4, 0x4CAB)},
-
-/* RTL8191SU */
- /* Realtek */
- {USB_DEVICE(0x0BDA, 0x8172)},
- {USB_DEVICE(0x0BDA, 0x8192)},
- /* Amigo */
- {USB_DEVICE(0x0EB0, 0x9061)},
- /* ASUS/EKB */
- {USB_DEVICE(0x13D3, 0x3323)},
- {USB_DEVICE(0x13D3, 0x3311)}, /* 11n mode disable */
- {USB_DEVICE(0x13D3, 0x3342)},
- /* ASUS/EKBLenovo */
- {USB_DEVICE(0x13D3, 0x3333)},
- {USB_DEVICE(0x13D3, 0x3334)},
- {USB_DEVICE(0x13D3, 0x3335)}, /* 11n mode disable */
- {USB_DEVICE(0x13D3, 0x3336)}, /* 11n mode disable */
- /* ASUS/Media BOX */
- {USB_DEVICE(0x13D3, 0x3309)},
- /* Belkin */
- {USB_DEVICE(0x050D, 0x815F)},
- /* D-Link */
- {USB_DEVICE(0x07D1, 0x3302)},
- {USB_DEVICE(0x07D1, 0x3300)},
- {USB_DEVICE(0x07D1, 0x3303)},
- /* Edimax */
- {USB_DEVICE(0x7392, 0x7612)},
- /* EnGenius */
- {USB_DEVICE(0x1740, 0x9605)},
- /* Guillemot */
- {USB_DEVICE(0x06F8, 0xE031)},
- /* Hawking */
- {USB_DEVICE(0x0E66, 0x0015)},
- /* Mediao */
- {USB_DEVICE(0x13D3, 0x3306)},
- /* PCI */
- {USB_DEVICE(0x2019, 0xED18)},
- {USB_DEVICE(0x2019, 0x4901)},
- /* Sitecom */
- {USB_DEVICE(0x0DF6, 0x0058)},
- {USB_DEVICE(0x0DF6, 0x0049)},
- {USB_DEVICE(0x0DF6, 0x004C)},
- {USB_DEVICE(0x0DF6, 0x006C)},
- {USB_DEVICE(0x0DF6, 0x0064)},
- /* Skyworth */
- {USB_DEVICE(0x14b2, 0x3300)},
- {USB_DEVICE(0x14b2, 0x3301)},
- {USB_DEVICE(0x14B2, 0x3302)},
- /* - */
- {USB_DEVICE(0x04F2, 0xAFF2)},
- {USB_DEVICE(0x04F2, 0xAFF5)},
- {USB_DEVICE(0x04F2, 0xAFF6)},
- {USB_DEVICE(0x13D3, 0x3339)},
- {USB_DEVICE(0x13D3, 0x3340)}, /* 11n mode disable */
- {USB_DEVICE(0x13D3, 0x3341)}, /* 11n mode disable */
- {USB_DEVICE(0x13D3, 0x3310)},
- {USB_DEVICE(0x13D3, 0x3325)},
-
-/* RTL8192SU */
- /* Realtek */
- {USB_DEVICE(0x0BDA, 0x8174)},
- /* Belkin */
- {USB_DEVICE(0x050D, 0x845A)},
- /* Corega */
- {USB_DEVICE(0x07AA, 0x0051)},
- /* Edimax */
- {USB_DEVICE(0x7392, 0x7622)},
- /* NEC */
- {USB_DEVICE(0x0409, 0x02B6)},
- {}
-};
-
-MODULE_DEVICE_TABLE(usb, rtl871x_usb_id_tbl);
-
-static struct specific_device_id specific_device_id_tbl[] = {
- {.idVendor = 0x0b05, .idProduct = 0x1791,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x0df6, .idProduct = 0x0059,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x13d3, .idProduct = 0x3306,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x13D3, .idProduct = 0x3311,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x13d3, .idProduct = 0x3335,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x13d3, .idProduct = 0x3336,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x13d3, .idProduct = 0x3340,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x13d3, .idProduct = 0x3341,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {}
-};
-
-struct drv_priv {
- struct usb_driver r871xu_drv;
- int drv_registered;
-};
-
-#ifdef CONFIG_PM
-static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state)
-{
- struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
- struct _adapter *padapter = netdev_priv(pnetdev);
-
- netdev_info(pnetdev, "Suspending...\n");
- padapter->suspended = true;
- rtl871x_intf_stop(padapter);
- if (pnetdev->netdev_ops->ndo_stop)
- pnetdev->netdev_ops->ndo_stop(pnetdev);
- mdelay(10);
- netif_device_detach(pnetdev);
- return 0;
-}
-
-static void rtl871x_intf_resume(struct _adapter *padapter)
-{
- if (padapter->dvobjpriv.inirp_init)
- padapter->dvobjpriv.inirp_init(padapter);
-}
-
-static int r871x_resume(struct usb_interface *pusb_intf)
-{
- struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
- struct _adapter *padapter = netdev_priv(pnetdev);
-
- netdev_info(pnetdev, "Resuming...\n");
- netif_device_attach(pnetdev);
- if (pnetdev->netdev_ops->ndo_open)
- pnetdev->netdev_ops->ndo_open(pnetdev);
- padapter->suspended = false;
- rtl871x_intf_resume(padapter);
- return 0;
-}
-#endif
-
-static struct drv_priv drvpriv = {
- .r871xu_drv.name = "r8712u",
- .r871xu_drv.id_table = rtl871x_usb_id_tbl,
- .r871xu_drv.probe = r871xu_drv_init,
- .r871xu_drv.disconnect = r871xu_dev_remove,
-#ifdef CONFIG_PM
- .r871xu_drv.suspend = r871x_suspend,
- .r871xu_drv.resume = r871x_resume,
-#endif
-};
-
-static uint r8712_usb_dvobj_init(struct _adapter *padapter)
-{
- uint status = _SUCCESS;
- struct usb_host_interface *phost_iface;
- struct usb_interface_descriptor *piface_desc;
- struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
- struct usb_device *pusbd = pdvobjpriv->pusbdev;
-
- pdvobjpriv->padapter = padapter;
- padapter->eeprom_address_size = 6;
- phost_iface = pintf->cur_altsetting;
- piface_desc = &phost_iface->desc;
- pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
- if (pusbd->speed == USB_SPEED_HIGH) {
- pdvobjpriv->ishighspeed = true;
- dev_info(&pusbd->dev, "r8712u: USB_SPEED_HIGH with %d endpoints\n",
- pdvobjpriv->nr_endpoint);
- } else {
- pdvobjpriv->ishighspeed = false;
- dev_info(&pusbd->dev, "r8712u: USB_SPEED_LOW with %d endpoints\n",
- pdvobjpriv->nr_endpoint);
- }
- if ((r8712_alloc_io_queue(padapter)) == _FAIL)
- status = _FAIL;
- return status;
-}
-
-static void r8712_usb_dvobj_deinit(struct _adapter *padapter)
-{
- r8712_free_io_queue(padapter);
-}
-
-void rtl871x_intf_stop(struct _adapter *padapter)
-{
- /*disable_hw_interrupt*/
- if (!padapter->surprise_removed) {
- /*device still exists, so driver can do i/o operation
- * TODO:
- */
- }
-
- /* cancel in irp */
- if (padapter->dvobjpriv.inirp_deinit)
- padapter->dvobjpriv.inirp_deinit(padapter);
- /* cancel out irp */
- r8712_usb_write_port_cancel(padapter);
- /* TODO:cancel other irps */
-}
-
-void r871x_dev_unload(struct _adapter *padapter)
-{
- if (padapter->bup) {
- /*s1.*/
- padapter->driver_stopped = true;
-
- /*s3.*/
- rtl871x_intf_stop(padapter);
-
- /*s4.*/
- r8712_stop_drv_threads(padapter);
-
- /*s5.*/
- if (!padapter->surprise_removed) {
- padapter->hw_init_completed = false;
- rtl8712_hal_deinit(padapter);
- }
-
- padapter->bup = false;
- }
-}
-
-static void disable_ht_for_spec_devid(const struct usb_device_id *pdid,
- struct _adapter *padapter)
-{
- u16 vid, pid;
- u32 flags;
- int i;
- int num = ARRAY_SIZE(specific_device_id_tbl);
-
- for (i = 0; i < num; i++) {
- vid = specific_device_id_tbl[i].idVendor;
- pid = specific_device_id_tbl[i].idProduct;
- flags = specific_device_id_tbl[i].flags;
-
- if ((pdid->idVendor == vid) && (pdid->idProduct == pid) &&
- (flags & SPEC_DEV_ID_DISABLE_HT)) {
- padapter->registrypriv.ht_enable = 0;
- padapter->registrypriv.cbw40_enable = 0;
- padapter->registrypriv.ampdu_enable = 0;
- }
- }
-}
-
-static const struct device_type wlan_type = {
- .name = "wlan",
-};
-
-/*
- * drv_init() - a device potentially for us
- *
- * notes: drv_init() is called when the bus driver has located a card for us
- * to support. We accept the new device by returning 0.
- */
-static int r871xu_drv_init(struct usb_interface *pusb_intf,
- const struct usb_device_id *pdid)
-{
- uint status;
- struct _adapter *padapter = NULL;
- struct dvobj_priv *pdvobjpriv;
- struct net_device *pnetdev;
- struct usb_device *udev;
-
- /* In this probe function, O.S. will provide the usb interface pointer
- * to driver. We have to increase the reference count of the usb device
- * structure by using the usb_get_dev function.
- */
- udev = interface_to_usbdev(pusb_intf);
- usb_get_dev(udev);
- pintf = pusb_intf;
- /* step 1. */
- pnetdev = r8712_init_netdev();
- if (!pnetdev)
- goto put_dev;
- padapter = netdev_priv(pnetdev);
- disable_ht_for_spec_devid(pdid, padapter);
- pdvobjpriv = &padapter->dvobjpriv;
- pdvobjpriv->padapter = padapter;
- padapter->dvobjpriv.pusbdev = udev;
- padapter->pusb_intf = pusb_intf;
- usb_set_intfdata(pusb_intf, pnetdev);
- SET_NETDEV_DEV(pnetdev, &pusb_intf->dev);
- pnetdev->dev.type = &wlan_type;
- /* step 2. */
- padapter->dvobj_init = r8712_usb_dvobj_init;
- padapter->dvobj_deinit = r8712_usb_dvobj_deinit;
- padapter->halpriv.hal_bus_init = r8712_usb_hal_bus_init;
- padapter->dvobjpriv.inirp_init = r8712_usb_inirp_init;
- padapter->dvobjpriv.inirp_deinit = r8712_usb_inirp_deinit;
- /* step 3.
- * initialize the dvobj_priv
- */
-
- status = padapter->dvobj_init(padapter);
- if (status != _SUCCESS)
- goto free_netdev;
-
- /* step 4. */
- status = r8712_init_drv_sw(padapter);
- if (status)
- goto dvobj_deinit;
- /* step 5. read efuse/eeprom data and get mac_addr */
- {
- int i, offset;
- u8 mac[6];
- u8 tmpU1b, AutoloadFail, eeprom_CustomerID;
- u8 *pdata = padapter->eeprompriv.efuse_eeprom_data;
-
- tmpU1b = r8712_read8(padapter, EE_9346CR);/*CR9346*/
-
- /* To check system boot selection.*/
- dev_info(&udev->dev, "r8712u: Boot from %s: Autoload %s\n",
- (tmpU1b & _9356SEL) ? "EEPROM" : "EFUSE",
- (tmpU1b & _EEPROM_EN) ? "OK" : "Failed");
-
- /* To check autoload success or not.*/
- if (tmpU1b & _EEPROM_EN) {
- AutoloadFail = true;
- /* The following operations prevent Efuse leakage by
- * turning on 2.5V.
- */
- tmpU1b = r8712_read8(padapter, EFUSE_TEST + 3);
- r8712_write8(padapter, EFUSE_TEST + 3, tmpU1b | 0x80);
- msleep(20);
- r8712_write8(padapter, EFUSE_TEST + 3,
- (tmpU1b & (~BIT(7))));
-
- /* Retrieve Chip version.
- * Recognize IC version by Reg0x4 BIT15.
- */
- tmpU1b = (u8)((r8712_read32(padapter, PMC_FSM) >> 15) &
- 0x1F);
- if (tmpU1b == 0x3)
- padapter->registrypriv.chip_version =
- RTL8712_3rdCUT;
- else
- padapter->registrypriv.chip_version =
- (tmpU1b >> 1) + 1;
- switch (padapter->registrypriv.chip_version) {
- case RTL8712_1stCUT:
- case RTL8712_2ndCUT:
- case RTL8712_3rdCUT:
- break;
- default:
- padapter->registrypriv.chip_version =
- RTL8712_2ndCUT;
- break;
- }
-
- for (i = 0, offset = 0; i < 128; i += 8, offset++)
- r8712_efuse_pg_packet_read(padapter, offset,
- &pdata[i]);
-
- if (!r8712_initmac || !mac_pton(r8712_initmac, mac)) {
- /* Use the mac address stored in the Efuse
- * offset = 0x12 for usb in efuse
- */
- ether_addr_copy(mac, &pdata[0x12]);
- }
- eeprom_CustomerID = pdata[0x52];
- switch (eeprom_CustomerID) {
- case EEPROM_CID_ALPHA:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_ALPHA;
- break;
- case EEPROM_CID_CAMEO:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_CAMEO;
- break;
- case EEPROM_CID_SITECOM:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_Sitecom;
- break;
- case EEPROM_CID_COREGA:
- padapter->eeprompriv.CustomerID =
- RT_CID_COREGA;
- break;
- case EEPROM_CID_Senao:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_Senao;
- break;
- case EEPROM_CID_EDIMAX_BELKIN:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_Edimax_Belkin;
- break;
- case EEPROM_CID_SERCOMM_BELKIN:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_Sercomm_Belkin;
- break;
- case EEPROM_CID_WNC_COREGA:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_WNC_COREGA;
- break;
- case EEPROM_CID_WHQL:
- break;
- case EEPROM_CID_NetCore:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_Netcore;
- break;
- case EEPROM_CID_CAMEO1:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_CAMEO1;
- break;
- case EEPROM_CID_CLEVO:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_CLEVO;
- break;
- default:
- padapter->eeprompriv.CustomerID =
- RT_CID_DEFAULT;
- break;
- }
- dev_info(&udev->dev, "r8712u: CustomerID = 0x%.4x\n",
- padapter->eeprompriv.CustomerID);
- /* Led mode */
- switch (padapter->eeprompriv.CustomerID) {
- case RT_CID_DEFAULT:
- case RT_CID_819x_ALPHA:
- case RT_CID_819x_CAMEO:
- padapter->ledpriv.LedStrategy = SW_LED_MODE1;
- padapter->ledpriv.bRegUseLed = true;
- break;
- case RT_CID_819x_Sitecom:
- padapter->ledpriv.LedStrategy = SW_LED_MODE2;
- padapter->ledpriv.bRegUseLed = true;
- break;
- case RT_CID_COREGA:
- case RT_CID_819x_Senao:
- padapter->ledpriv.LedStrategy = SW_LED_MODE3;
- padapter->ledpriv.bRegUseLed = true;
- break;
- case RT_CID_819x_Edimax_Belkin:
- padapter->ledpriv.LedStrategy = SW_LED_MODE4;
- padapter->ledpriv.bRegUseLed = true;
- break;
- case RT_CID_819x_Sercomm_Belkin:
- padapter->ledpriv.LedStrategy = SW_LED_MODE5;
- padapter->ledpriv.bRegUseLed = true;
- break;
- case RT_CID_819x_WNC_COREGA:
- padapter->ledpriv.LedStrategy = SW_LED_MODE6;
- padapter->ledpriv.bRegUseLed = true;
- break;
- default:
- padapter->ledpriv.LedStrategy = SW_LED_MODE0;
- padapter->ledpriv.bRegUseLed = false;
- break;
- }
- } else {
- AutoloadFail = false;
- }
- if ((!AutoloadFail) ||
- ((mac[0] == 0xff) && (mac[1] == 0xff) &&
- (mac[2] == 0xff) && (mac[3] == 0xff) &&
- (mac[4] == 0xff) && (mac[5] == 0xff)) ||
- ((mac[0] == 0x00) && (mac[1] == 0x00) &&
- (mac[2] == 0x00) && (mac[3] == 0x00) &&
- (mac[4] == 0x00) && (mac[5] == 0x00))) {
- mac[0] = 0x00;
- mac[1] = 0xe0;
- mac[2] = 0x4c;
- mac[3] = 0x87;
- mac[4] = 0x00;
- mac[5] = 0x00;
- }
- if (r8712_initmac) {
- /* Make sure the user did not select a multicast
- * address by setting bit 1 of first octet.
- */
- mac[0] &= 0xFE;
- dev_info(&udev->dev,
- "r8712u: MAC Address from user = %pM\n", mac);
- } else {
- dev_info(&udev->dev,
- "r8712u: MAC Address from efuse = %pM\n", mac);
- }
- eth_hw_addr_set(pnetdev, mac);
- }
- /* step 6. Load the firmware asynchronously */
- if (rtl871x_load_fw(padapter))
- goto deinit_drv_sw;
- init_completion(&padapter->rx_filter_ready);
- return 0;
-
-deinit_drv_sw:
- r8712_free_drv_sw(padapter);
-dvobj_deinit:
- padapter->dvobj_deinit(padapter);
-free_netdev:
- free_netdev(pnetdev);
-put_dev:
- usb_put_dev(udev);
- usb_set_intfdata(pusb_intf, NULL);
- return -ENODEV;
-}
-
-/* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove()
- * => how to recognize both
- */
-static void r871xu_dev_remove(struct usb_interface *pusb_intf)
-{
- struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
- struct usb_device *udev = interface_to_usbdev(pusb_intf);
- struct _adapter *padapter = netdev_priv(pnetdev);
-
- /* never exit with a firmware callback pending */
- wait_for_completion(&padapter->rtl8712_fw_ready);
- if (pnetdev->reg_state != NETREG_UNINITIALIZED)
- unregister_netdev(pnetdev); /* will call netdev_close() */
- usb_set_intfdata(pusb_intf, NULL);
- release_firmware(padapter->fw);
- if (drvpriv.drv_registered)
- padapter->surprise_removed = true;
- r8712_flush_rwctrl_works(padapter);
- r8712_flush_led_works(padapter);
- udelay(1);
- /* Stop driver mlme relation timer */
- r8712_stop_drv_timers(padapter);
- r871x_dev_unload(padapter);
- if (padapter->dvobj_deinit)
- padapter->dvobj_deinit(padapter);
- r8712_free_drv_sw(padapter);
- free_netdev(pnetdev);
-
- /* decrease the reference count of the usb device structure
- * when disconnect
- */
- usb_put_dev(udev);
-
- /* If we didn't unplug usb dongle and remove/insert module, driver
- * fails on sitesurvey for the first time when device is up.
- * Reset usb port for sitesurvey fail issue.
- */
- if (udev->state != USB_STATE_NOTATTACHED)
- usb_reset_device(udev);
-}
-
-static int __init r8712u_drv_entry(void)
-{
- drvpriv.drv_registered = true;
- return usb_register(&drvpriv.r871xu_drv);
-}
-
-static void __exit r8712u_drv_halt(void)
-{
- drvpriv.drv_registered = false;
- usb_deregister(&drvpriv.r871xu_drv);
-}
-
-module_init(r8712u_drv_entry);
-module_exit(r8712u_drv_halt);
diff --git a/drivers/staging/rtl8712/usb_ops.c b/drivers/staging/rtl8712/usb_ops.c
deleted file mode 100644
index af9966d03979..000000000000
--- a/drivers/staging/rtl8712/usb_ops.c
+++ /dev/null
@@ -1,195 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * usb_ops.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _HCI_OPS_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "osdep_intf.h"
-#include "usb_ops.h"
-#include "recv_osdep.h"
-
-static u8 usb_read8(struct intf_hdl *intfhdl, u32 addr)
-{
- u8 request;
- u8 requesttype;
- u16 wvalue;
- u16 index;
- u16 len;
- int status;
- __le32 data = 0;
- struct intf_priv *intfpriv = intfhdl->pintfpriv;
-
- request = 0x05;
- requesttype = 0x01; /* read_in */
- index = 0;
- wvalue = (u16)(addr & 0x0000ffff);
- len = 1;
- status = r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index,
- &data, len, requesttype);
- if (status < 0)
- return 0;
- return (u8)(le32_to_cpu(data) & 0x0ff);
-}
-
-static u16 usb_read16(struct intf_hdl *intfhdl, u32 addr)
-{
- u8 request;
- u8 requesttype;
- u16 wvalue;
- u16 index;
- u16 len;
- int status;
- __le32 data = 0;
- struct intf_priv *intfpriv = intfhdl->pintfpriv;
-
- request = 0x05;
- requesttype = 0x01; /* read_in */
- index = 0;
- wvalue = (u16)(addr & 0x0000ffff);
- len = 2;
- status = r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index,
- &data, len, requesttype);
- if (status < 0)
- return 0;
- return (u16)(le32_to_cpu(data) & 0xffff);
-}
-
-static u32 usb_read32(struct intf_hdl *intfhdl, u32 addr)
-{
- u8 request;
- u8 requesttype;
- u16 wvalue;
- u16 index;
- u16 len;
- int status;
- __le32 data = 0;
- struct intf_priv *intfpriv = intfhdl->pintfpriv;
-
- request = 0x05;
- requesttype = 0x01; /* read_in */
- index = 0;
- wvalue = (u16)(addr & 0x0000ffff);
- len = 4;
- status = r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index,
- &data, len, requesttype);
- if (status < 0)
- return 0;
- return le32_to_cpu(data);
-}
-
-static void usb_write8(struct intf_hdl *intfhdl, u32 addr, u8 val)
-{
- u8 request;
- u8 requesttype;
- u16 wvalue;
- u16 index;
- u16 len;
- __le32 data;
- struct intf_priv *intfpriv = intfhdl->pintfpriv;
-
- request = 0x05;
- requesttype = 0x00; /* write_out */
- index = 0;
- wvalue = (u16)(addr & 0x0000ffff);
- len = 1;
- data = cpu_to_le32((u32)val & 0x000000ff);
- r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index, &data, len,
- requesttype);
-}
-
-static void usb_write16(struct intf_hdl *intfhdl, u32 addr, u16 val)
-{
- u8 request;
- u8 requesttype;
- u16 wvalue;
- u16 index;
- u16 len;
- __le32 data;
- struct intf_priv *intfpriv = intfhdl->pintfpriv;
-
- request = 0x05;
- requesttype = 0x00; /* write_out */
- index = 0;
- wvalue = (u16)(addr & 0x0000ffff);
- len = 2;
- data = cpu_to_le32((u32)val & 0x0000ffff);
- r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index, &data, len,
- requesttype);
-}
-
-static void usb_write32(struct intf_hdl *intfhdl, u32 addr, u32 val)
-{
- u8 request;
- u8 requesttype;
- u16 wvalue;
- u16 index;
- u16 len;
- __le32 data;
- struct intf_priv *intfpriv = intfhdl->pintfpriv;
-
- request = 0x05;
- requesttype = 0x00; /* write_out */
- index = 0;
- wvalue = (u16)(addr & 0x0000ffff);
- len = 4;
- data = cpu_to_le32(val);
- r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index, &data, len,
- requesttype);
-}
-
-void r8712_usb_set_intf_option(u32 *option)
-{
- *option = ((*option) | _INTF_ASYNC_);
-}
-
-static void usb_intf_hdl_init(u8 *priv)
-{
-}
-
-static void usb_intf_hdl_unload(u8 *priv)
-{
-}
-
-static void usb_intf_hdl_open(u8 *priv)
-{
-}
-
-static void usb_intf_hdl_close(u8 *priv)
-{
-}
-
-void r8712_usb_set_intf_funs(struct intf_hdl *intfhdl)
-{
- intfhdl->intf_hdl_init = usb_intf_hdl_init;
- intfhdl->intf_hdl_unload = usb_intf_hdl_unload;
- intfhdl->intf_hdl_open = usb_intf_hdl_open;
- intfhdl->intf_hdl_close = usb_intf_hdl_close;
-}
-
-void r8712_usb_set_intf_ops(struct _io_ops *ops)
-{
- memset((u8 *)ops, 0, sizeof(struct _io_ops));
- ops->_read8 = usb_read8;
- ops->_read16 = usb_read16;
- ops->_read32 = usb_read32;
- ops->_read_port = r8712_usb_read_port;
- ops->_write8 = usb_write8;
- ops->_write16 = usb_write16;
- ops->_write32 = usb_write32;
- ops->_write_mem = r8712_usb_write_mem;
- ops->_write_port = r8712_usb_write_port;
-}
diff --git a/drivers/staging/rtl8712/usb_ops.h b/drivers/staging/rtl8712/usb_ops.h
deleted file mode 100644
index 7a6b619b73fa..000000000000
--- a/drivers/staging/rtl8712/usb_ops.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __USB_OPS_H_
-#define __USB_OPS_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "osdep_intf.h"
-
-void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr,
- u32 cnt, u8 *wmem);
-u32 r8712_usb_write_port(struct intf_hdl *pintfhdl, u32 addr,
- u32 cnt, u8 *wmem);
-u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr,
- u32 cnt, u8 *rmem);
-void r8712_usb_set_intf_option(u32 *poption);
-void r8712_usb_set_intf_funs(struct intf_hdl *pintf_hdl);
-uint r8712_usb_init_intf_priv(struct intf_priv *pintfpriv);
-void r8712_usb_unload_intf_priv(struct intf_priv *pintfpriv);
-void r8712_usb_set_intf_ops(struct _io_ops *pops);
-void r8712_usb_read_port_cancel(struct _adapter *padapter);
-void r8712_usb_write_port_cancel(struct _adapter *padapter);
-int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value,
- u16 index, void *pdata, u16 len, u8 requesttype);
-
-#endif
-
diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c
deleted file mode 100644
index 4a34824830e3..000000000000
--- a/drivers/staging/rtl8712/usb_ops_linux.c
+++ /dev/null
@@ -1,508 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * usb_ops_linux.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _HCI_OPS_OS_C_
-
-#include <linux/usb.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "osdep_intf.h"
-#include "usb_ops.h"
-
-#define RTL871X_VENQT_READ 0xc0
-#define RTL871X_VENQT_WRITE 0x40
-
-uint r8712_usb_init_intf_priv(struct intf_priv *pintfpriv)
-{
- pintfpriv->piorw_urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!pintfpriv->piorw_urb)
- return _FAIL;
- init_completion(&pintfpriv->io_retevt_comp);
- return _SUCCESS;
-}
-
-void r8712_usb_unload_intf_priv(struct intf_priv *pintfpriv)
-{
- if (pintfpriv->piorw_urb) {
- usb_kill_urb(pintfpriv->piorw_urb);
- usb_free_urb(pintfpriv->piorw_urb);
- }
-}
-
-static unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
-{
- unsigned int pipe = 0;
- struct usb_device *pusbd = pdvobj->pusbdev;
-
- if (pdvobj->nr_endpoint == 11) {
- switch (addr) {
- case RTL8712_DMA_BKQ:
- pipe = usb_sndbulkpipe(pusbd, 0x07);
- break;
- case RTL8712_DMA_BEQ:
- pipe = usb_sndbulkpipe(pusbd, 0x06);
- break;
- case RTL8712_DMA_VIQ:
- pipe = usb_sndbulkpipe(pusbd, 0x05);
- break;
- case RTL8712_DMA_VOQ:
- pipe = usb_sndbulkpipe(pusbd, 0x04);
- break;
- case RTL8712_DMA_BCNQ:
- pipe = usb_sndbulkpipe(pusbd, 0x0a);
- break;
- case RTL8712_DMA_BMCQ: /* HI Queue */
- pipe = usb_sndbulkpipe(pusbd, 0x0b);
- break;
- case RTL8712_DMA_MGTQ:
- pipe = usb_sndbulkpipe(pusbd, 0x0c);
- break;
- case RTL8712_DMA_RX0FF:
- pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */
- break;
- case RTL8712_DMA_C2HCMD:
- pipe = usb_rcvbulkpipe(pusbd, 0x09); /* in */
- break;
- case RTL8712_DMA_H2CCMD:
- pipe = usb_sndbulkpipe(pusbd, 0x0d);
- break;
- }
- } else if (pdvobj->nr_endpoint == 6) {
- switch (addr) {
- case RTL8712_DMA_BKQ:
- pipe = usb_sndbulkpipe(pusbd, 0x07);
- break;
- case RTL8712_DMA_BEQ:
- pipe = usb_sndbulkpipe(pusbd, 0x06);
- break;
- case RTL8712_DMA_VIQ:
- pipe = usb_sndbulkpipe(pusbd, 0x05);
- break;
- case RTL8712_DMA_VOQ:
- pipe = usb_sndbulkpipe(pusbd, 0x04);
- break;
- case RTL8712_DMA_RX0FF:
- case RTL8712_DMA_C2HCMD:
- pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */
- break;
- case RTL8712_DMA_H2CCMD:
- case RTL8712_DMA_BCNQ:
- case RTL8712_DMA_BMCQ:
- case RTL8712_DMA_MGTQ:
- pipe = usb_sndbulkpipe(pusbd, 0x0d);
- break;
- }
- } else if (pdvobj->nr_endpoint == 4) {
- switch (addr) {
- case RTL8712_DMA_BEQ:
- pipe = usb_sndbulkpipe(pusbd, 0x06);
- break;
- case RTL8712_DMA_VOQ:
- pipe = usb_sndbulkpipe(pusbd, 0x04);
- break;
- case RTL8712_DMA_RX0FF:
- case RTL8712_DMA_C2HCMD:
- pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */
- break;
- case RTL8712_DMA_H2CCMD:
- case RTL8712_DMA_BCNQ:
- case RTL8712_DMA_BMCQ:
- case RTL8712_DMA_MGTQ:
- pipe = usb_sndbulkpipe(pusbd, 0x0d);
- break;
- }
- } else {
- pipe = 0;
- }
- return pipe;
-}
-
-static void usb_write_mem_complete(struct urb *purb)
-{
- struct io_queue *pio_q = (struct io_queue *)purb->context;
- struct intf_hdl *pintf = &(pio_q->intf);
- struct intf_priv *pintfpriv = pintf->pintfpriv;
- struct _adapter *padapter = (struct _adapter *)pintf->adapter;
-
- if (purb->status != 0) {
- if (purb->status == (-ESHUTDOWN))
- padapter->driver_stopped = true;
- else
- padapter->surprise_removed = true;
- }
- complete(&pintfpriv->io_retevt_comp);
-}
-
-void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
-{
- unsigned int pipe;
- struct _adapter *padapter = (struct _adapter *)pintfhdl->adapter;
- struct intf_priv *pintfpriv = pintfhdl->pintfpriv;
- struct io_queue *pio_queue = padapter->pio_queue;
- struct dvobj_priv *pdvobj = (struct dvobj_priv *)pintfpriv->intf_dev;
- struct usb_device *pusbd = pdvobj->pusbdev;
- struct urb *piorw_urb = pintfpriv->piorw_urb;
-
- if ((padapter->driver_stopped) || (padapter->surprise_removed) ||
- (padapter->pwrctrlpriv.pnp_bstop_trx))
- return;
- /* translate DMA FIFO addr to pipehandle */
- pipe = ffaddr2pipehdl(pdvobj, addr);
- if (pipe == 0)
- return;
- usb_fill_bulk_urb(piorw_urb, pusbd, pipe,
- wmem, cnt, usb_write_mem_complete,
- pio_queue);
- usb_submit_urb(piorw_urb, GFP_ATOMIC);
- wait_for_completion_interruptible(&pintfpriv->io_retevt_comp);
-}
-
-static void r8712_usb_read_port_complete(struct urb *purb)
-{
- uint isevt;
- __le32 *pbuf;
- struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
- struct _adapter *padapter = (struct _adapter *)precvbuf->adapter;
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- if (padapter->surprise_removed || padapter->driver_stopped)
- return;
- if (purb->status == 0) { /* SUCCESS */
- if ((purb->actual_length > (MAX_RECVBUF_SZ)) ||
- (purb->actual_length < RXDESC_SIZE)) {
- r8712_read_port(padapter, precvpriv->ff_hwaddr, 0,
- (unsigned char *)precvbuf);
- } else {
- _pkt *pskb = precvbuf->pskb;
-
- precvbuf->transfer_len = purb->actual_length;
- pbuf = (__le32 *)precvbuf->pbuf;
- isevt = le32_to_cpu(*(pbuf + 1)) & 0x1ff;
- if ((isevt & 0x1ff) == 0x1ff) {
- r8712_rxcmd_event_hdl(padapter, pbuf);
- skb_queue_tail(&precvpriv->rx_skb_queue, pskb);
- r8712_read_port(padapter, precvpriv->ff_hwaddr,
- 0, (unsigned char *)precvbuf);
- } else {
- skb_put(pskb, purb->actual_length);
- skb_queue_tail(&precvpriv->rx_skb_queue, pskb);
- tasklet_hi_schedule(&precvpriv->recv_tasklet);
- r8712_read_port(padapter, precvpriv->ff_hwaddr,
- 0, (unsigned char *)precvbuf);
- }
- }
- } else {
- switch (purb->status) {
- case -EINVAL:
- case -EPIPE:
- case -ENODEV:
- case -ESHUTDOWN:
- padapter->driver_stopped = true;
- break;
- case -ENOENT:
- if (!padapter->suspended) {
- padapter->driver_stopped = true;
- break;
- }
- fallthrough;
- case -EPROTO:
- r8712_read_port(padapter, precvpriv->ff_hwaddr, 0,
- (unsigned char *)precvbuf);
- break;
- case -EINPROGRESS:
- netdev_err(padapter->pnetdev, "ERROR: URB IS IN PROGRESS!\n");
- break;
- default:
- break;
- }
- }
-}
-
-u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
-{
- unsigned int pipe;
- int err;
- u32 tmpaddr = 0;
- int alignment = 0;
- u32 ret = _SUCCESS;
- struct urb *purb = NULL;
- struct recv_buf *precvbuf = (struct recv_buf *)rmem;
- struct intf_priv *pintfpriv = pintfhdl->pintfpriv;
- struct dvobj_priv *pdvobj = (struct dvobj_priv *)pintfpriv->intf_dev;
- struct _adapter *adapter = pdvobj->padapter;
- struct recv_priv *precvpriv = &adapter->recvpriv;
- struct usb_device *pusbd = pdvobj->pusbdev;
-
- if (adapter->driver_stopped || adapter->surprise_removed ||
- adapter->pwrctrlpriv.pnp_bstop_trx || !precvbuf)
- return _FAIL;
- r8712_init_recvbuf(adapter, precvbuf);
- /* Try to use skb from the free queue */
- precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
-
- if (!precvbuf->pskb) {
- precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev,
- MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
- if (!precvbuf->pskb)
- return _FAIL;
- tmpaddr = (addr_t)precvbuf->pskb->data;
- alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
- skb_reserve(precvbuf->pskb,
- (RECVBUFF_ALIGN_SZ - alignment));
- precvbuf->phead = precvbuf->pskb->head;
- precvbuf->pdata = precvbuf->pskb->data;
- precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
- precvbuf->pend = skb_end_pointer(precvbuf->pskb);
- precvbuf->pbuf = precvbuf->pskb->data;
- } else { /* skb is reused */
- precvbuf->phead = precvbuf->pskb->head;
- precvbuf->pdata = precvbuf->pskb->data;
- precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
- precvbuf->pend = skb_end_pointer(precvbuf->pskb);
- precvbuf->pbuf = precvbuf->pskb->data;
- }
- purb = precvbuf->purb;
- /* translate DMA FIFO addr to pipehandle */
- pipe = ffaddr2pipehdl(pdvobj, addr);
- usb_fill_bulk_urb(purb, pusbd, pipe,
- precvbuf->pbuf, MAX_RECVBUF_SZ,
- r8712_usb_read_port_complete,
- precvbuf);
- err = usb_submit_urb(purb, GFP_ATOMIC);
- if ((err) && (err != (-EPERM)))
- ret = _FAIL;
- return ret;
-}
-
-void r8712_usb_read_port_cancel(struct _adapter *padapter)
-{
- int i;
- struct recv_buf *precvbuf;
-
- precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
- for (i = 0; i < NR_RECVBUFF; i++) {
- if (precvbuf->purb)
- usb_kill_urb(precvbuf->purb);
- precvbuf++;
- }
-}
-
-void r8712_xmit_bh(struct tasklet_struct *t)
-{
- int ret = false;
- struct _adapter *padapter = from_tasklet(padapter, t,
- xmitpriv.xmit_tasklet);
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
- if (padapter->driver_stopped ||
- padapter->surprise_removed) {
- netdev_err(padapter->pnetdev, "xmit_bh => driver_stopped or surprise_removed\n");
- return;
- }
- ret = r8712_xmitframe_complete(padapter, pxmitpriv, NULL);
- if (!ret)
- return;
- tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
-}
-
-static void usb_write_port_complete(struct urb *purb)
-{
- int i;
- struct xmit_frame *pxmitframe = (struct xmit_frame *)purb->context;
- struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
- struct _adapter *padapter = pxmitframe->padapter;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
-
- switch (pattrib->priority) {
- case 1:
- case 2:
- pxmitpriv->bkq_cnt--;
- break;
- case 4:
- case 5:
- pxmitpriv->viq_cnt--;
- break;
- case 6:
- case 7:
- pxmitpriv->voq_cnt--;
- break;
- case 0:
- case 3:
- default:
- pxmitpriv->beq_cnt--;
- break;
- }
- pxmitpriv->txirp_cnt--;
- for (i = 0; i < 8; i++) {
- if (purb == pxmitframe->pxmit_urb[i]) {
- pxmitframe->bpending[i] = false;
- break;
- }
- }
- if (padapter->surprise_removed)
- return;
- switch (purb->status) {
- case 0:
- break;
- default:
- netdev_warn(padapter->pnetdev,
- "r8712u: pipe error: (%d)\n", purb->status);
- break;
- }
- /* not to consider tx fragment */
- r8712_free_xmitframe_ex(pxmitpriv, pxmitframe);
- r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
- tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
-}
-
-u32 r8712_usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
-{
- unsigned long irqL;
- int i, status;
- unsigned int pipe;
- u32 ret, bwritezero;
- struct urb *purb = NULL;
- struct _adapter *padapter = (struct _adapter *)pintfhdl->adapter;
- struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct xmit_frame *pxmitframe = (struct xmit_frame *)wmem;
- struct usb_device *pusbd = pdvobj->pusbdev;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
-
- if ((padapter->driver_stopped) || (padapter->surprise_removed) ||
- (padapter->pwrctrlpriv.pnp_bstop_trx))
- return _FAIL;
- for (i = 0; i < 8; i++) {
- if (!pxmitframe->bpending[i]) {
- spin_lock_irqsave(&pxmitpriv->lock, irqL);
- pxmitpriv->txirp_cnt++;
- pxmitframe->bpending[i] = true;
- switch (pattrib->priority) {
- case 1:
- case 2:
- pxmitpriv->bkq_cnt++;
- break;
- case 4:
- case 5:
- pxmitpriv->viq_cnt++;
- break;
- case 6:
- case 7:
- pxmitpriv->voq_cnt++;
- break;
- case 0:
- case 3:
- default:
- pxmitpriv->beq_cnt++;
- break;
- }
- spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
- pxmitframe->sz[i] = (u16)cnt;
- purb = pxmitframe->pxmit_urb[i];
- break;
- }
- }
- bwritezero = false;
- if (pdvobj->ishighspeed) {
- if (cnt > 0 && cnt % 512 == 0)
- bwritezero = true;
- } else {
- if (cnt > 0 && cnt % 64 == 0)
- bwritezero = true;
- }
- /* translate DMA FIFO addr to pipehandle */
- pipe = ffaddr2pipehdl(pdvobj, addr);
- if (pxmitpriv->free_xmitbuf_cnt % NR_XMITBUFF == 0)
- purb->transfer_flags &= (~URB_NO_INTERRUPT);
- else
- purb->transfer_flags |= URB_NO_INTERRUPT;
- if (bwritezero)
- cnt += 8;
- usb_fill_bulk_urb(purb, pusbd, pipe,
- pxmitframe->mem_addr,
- cnt, usb_write_port_complete,
- pxmitframe); /* context is xmit_frame */
- status = usb_submit_urb(purb, GFP_ATOMIC);
- if (!status)
- ret = _SUCCESS;
- else
- ret = _FAIL;
- return ret;
-}
-
-void r8712_usb_write_port_cancel(struct _adapter *padapter)
-{
- int i, j;
- struct xmit_buf *pxmitbuf = (struct xmit_buf *)
- padapter->xmitpriv.pxmitbuf;
-
- for (i = 0; i < NR_XMITBUFF; i++) {
- for (j = 0; j < 8; j++) {
- if (pxmitbuf->pxmit_urb[j])
- usb_kill_urb(pxmitbuf->pxmit_urb[j]);
- }
- pxmitbuf++;
- }
-}
-
-int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value,
- u16 index, void *pdata, u16 len, u8 requesttype)
-{
- unsigned int pipe;
- int status;
- u8 reqtype;
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)
- pintfpriv->intf_dev;
- struct usb_device *udev = pdvobjpriv->pusbdev;
- /* For mstar platform, mstar suggests the address for USB IO
- * should be 16 bytes alignment. Trying to fix it here.
- */
- u8 *palloc_buf, *pIo_buf;
-
- palloc_buf = kmalloc((u32)len + 16, GFP_ATOMIC);
- if (!palloc_buf)
- return -ENOMEM;
- pIo_buf = palloc_buf + 16 - ((addr_t)(palloc_buf) & 0x0f);
- if (requesttype == 0x01) {
- pipe = usb_rcvctrlpipe(udev, 0); /* read_in */
- reqtype = RTL871X_VENQT_READ;
- } else {
- pipe = usb_sndctrlpipe(udev, 0); /* write_out */
- reqtype = RTL871X_VENQT_WRITE;
- memcpy(pIo_buf, pdata, len);
- }
- status = usb_control_msg(udev, pipe, request, reqtype, value, index,
- pIo_buf, len, 500);
- if (status < 0)
- goto free;
- if (status != len) {
- status = -EREMOTEIO;
- goto free;
- }
- /* Success this control transfer. */
- if (requesttype == 0x01) {
- /* For Control read transfer, we have to copy the read
- * data from pIo_buf to pdata.
- */
- memcpy(pdata, pIo_buf, status);
- }
-
-free:
- kfree(palloc_buf);
- return status;
-}
diff --git a/drivers/staging/rtl8712/usb_osintf.h b/drivers/staging/rtl8712/usb_osintf.h
deleted file mode 100644
index 2e512b4a564c..000000000000
--- a/drivers/staging/rtl8712/usb_osintf.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __USB_OSINTF_H
-#define __USB_OSINTF_H
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-extern char *r8712_initmac;
-
-unsigned int r8712_usb_inirp_init(struct _adapter *padapter);
-unsigned int r8712_usb_inirp_deinit(struct _adapter *padapter);
-uint rtl871x_hal_init(struct _adapter *padapter);
-uint rtl8712_hal_deinit(struct _adapter *padapter);
-
-void rtl871x_intf_stop(struct _adapter *padapter);
-void r871x_dev_unload(struct _adapter *padapter);
-void r8712_stop_drv_threads(struct _adapter *padapter);
-void r8712_stop_drv_timers(struct _adapter *padapter);
-int r8712_init_drv_sw(struct _adapter *padapter);
-void r8712_free_drv_sw(struct _adapter *padapter);
-struct net_device *r8712_init_netdev(void);
-
-#endif
diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h
deleted file mode 100644
index 498e6dec7e67..000000000000
--- a/drivers/staging/rtl8712/wifi.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _WIFI_H_
-#define _WIFI_H_
-
-#include <linux/compiler.h>
-#include <linux/ieee80211.h>
-
-#define WLAN_HDR_A3_LEN 24
-#define WLAN_HDR_A3_QOS_LEN 26
-
-enum WIFI_FRAME_TYPE {
- WIFI_QOS_DATA_TYPE = (BIT(7) | BIT(3)), /*!< QoS Data */
-};
-
-#define SetToDs(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_TODS); \
-})
-
-#define GetToDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_TODS)) != 0)
-
-#define ClearToDs(pbuf) ({ \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_TODS)); \
-})
-
-#define SetFrDs(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_FROMDS); \
-})
-
-#define GetFrDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_FROMDS)) != 0)
-
-#define ClearFrDs(pbuf) ({ \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_FROMDS)); \
-})
-
-static inline unsigned char get_tofr_ds(unsigned char *pframe)
-{
- return ((GetToDs(pframe) << 1) | GetFrDs(pframe));
-}
-
-#define SetMFrag(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); \
-})
-
-#define GetMFrag(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) != 0)
-
-#define ClearMFrag(pbuf) ({ \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)); \
-})
-
-#define SetRetry(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_RETRY); \
-})
-
-#define GetRetry(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_RETRY)) != 0)
-
-#define ClearRetry(pbuf) ({ \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_RETRY)); \
-})
-
-#define SetPwrMgt(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PM); \
-})
-
-#define GetPwrMgt(pbuf) (((*(__le16 *)(pbuf)) & \
- cpu_to_le16(IEEE80211_FCTL_PM)) != 0)
-
-#define ClearPwrMgt(pbuf) ({ \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_PM)); \
-})
-
-#define SetMData(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); \
-})
-
-#define GetMData(pbuf) (((*(__le16 *)(pbuf)) & \
- cpu_to_le16(IEEE80211_FCTL_MOREDATA)) != 0)
-
-#define ClearMData(pbuf) ({ \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREDATA)); \
-})
-
-#define SetPrivacy(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); \
-})
-
-#define GetPrivacy(pbuf) (((*(__le16 *)(pbuf)) & \
- cpu_to_le16(IEEE80211_FCTL_PROTECTED)) != 0)
-
-#define GetOrder(pbuf) (((*(__le16 *)(pbuf)) & \
- cpu_to_le16(IEEE80211_FCTL_ORDER)) != 0)
-
-#define GetFrameType(pbuf) (le16_to_cpu(*(__le16 *)(pbuf)) & \
- (BIT(3) | BIT(2)))
-
-#define SetFrameType(pbuf, type) \
- do { \
- *(__le16 *)(pbuf) &= cpu_to_le16(~(BIT(3) | \
- BIT(2))); \
- *(__le16 *)(pbuf) |= cpu_to_le16(type); \
- } while (0)
-
-#define GetFrameSubType(pbuf) (le16_to_cpu(*(__le16 *)(pbuf)) & \
- (BIT(7) | BIT(6) | BIT(5) | BIT(4) | BIT(3) | \
- BIT(2)))
-
-#define SetFrameSubType(pbuf, type) \
- do { \
- *(__le16 *)(pbuf) &= cpu_to_le16(~(BIT(7) | BIT(6) | \
- BIT(5) | BIT(4) | BIT(3) | BIT(2))); \
- *(__le16 *)(pbuf) |= cpu_to_le16(type); \
- } while (0)
-
-#define GetSequence(pbuf) (le16_to_cpu(*(__le16 *)\
- ((addr_t)(pbuf) + 22)) >> 4)
-
-#define GetFragNum(pbuf) (le16_to_cpu(*(__le16 *)((addr_t)\
- (pbuf) + 22)) & 0x0f)
-
-#define SetSeqNum(pbuf, num) ({ \
- *(__le16 *)((addr_t)(pbuf) + 22) = \
- cpu_to_le16((le16_to_cpu(*(__le16 *)((addr_t)(pbuf) + 22)) & \
- 0x000f) | (0xfff0 & (num << 4))); \
-})
-
-#define SetPriority(pbuf, tid) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(tid & 0xf); \
-})
-
-#define GetPriority(pbuf) ((le16_to_cpu(*(__le16 *)(pbuf))) & 0xf)
-
-#define SetAckpolicy(pbuf, ack) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16((ack & 3) << 5); \
-})
-
-#define GetAckpolicy(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 5) & 0x3)
-
-#define GetAMsdu(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 7) & 0x1)
-
-#define GetAddr1Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 4))
-
-#define GetAddr2Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 10))
-
-#define GetAddr3Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 16))
-
-#define GetAddr4Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 24))
-
-static inline unsigned char *get_hdr_bssid(unsigned char *pframe)
-{
- unsigned char *sa;
- unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe);
-
- switch (to_fr_ds) {
- case 0x00: /* ToDs=0, FromDs=0 */
- sa = GetAddr3Ptr(pframe);
- break;
- case 0x01: /* ToDs=0, FromDs=1 */
- sa = GetAddr2Ptr(pframe);
- break;
- case 0x02: /* ToDs=1, FromDs=0 */
- sa = GetAddr1Ptr(pframe);
- break;
- default: /* ToDs=1, FromDs=1 */
- sa = NULL;
- break;
- }
- return sa;
-}
-
-/* ---------------------------------------------------------------------------
- * Below is the fixed elements...
- * ---------------------------------------------------------------------------
- */
-#define _BEACON_ITERVAL_ 2
-#define _CAPABILITY_ 2
-#define _TIMESTAMP_ 8
-
-/*-----------------------------------------------------------------------------
- * Below is the definition for WMM
- *------------------------------------------------------------------------------
- */
-#define _WMM_IE_Length_ 7 /* for WMM STA */
-
-#endif /* _WIFI_H_ */
-
diff --git a/drivers/staging/rtl8712/wlan_bssdef.h b/drivers/staging/rtl8712/wlan_bssdef.h
deleted file mode 100644
index ec3749813728..000000000000
--- a/drivers/staging/rtl8712/wlan_bssdef.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __WLAN_BSSDEF_H__
-#define __WLAN_BSSDEF_H__
-
-#define MAX_IE_SZ 768
-
-#define NDIS_802_11_LENGTH_SSID 32
-#define NDIS_802_11_LENGTH_RATES 8
-#define NDIS_802_11_LENGTH_RATES_EX 16
-
-struct ndis_802_11_ssid {
- u32 SsidLength;
- u8 Ssid[32];
-};
-
-enum NDIS_802_11_NETWORK_TYPE {
- Ndis802_11FH,
- Ndis802_11DS,
- Ndis802_11OFDM5,
- Ndis802_11OFDM24,
- Ndis802_11NetworkTypeMax /* not a real type, defined as an upper bound*/
-};
-
-struct NDIS_802_11_CONFIGURATION_FH {
- u32 Length; /* Length of structure */
- u32 HopPattern; /* As defined by 802.11, MSB set */
- u32 HopSet; /* to one if non-802.11 */
- u32 DwellTime; /* units are Kusec */
-};
-
-/*
- * FW will only save the channel number in DSConfig.
- * ODI Handler will convert the channel number to freq. number.
- */
-struct NDIS_802_11_CONFIGURATION {
- u32 Length; /* Length of structure */
- u32 BeaconPeriod; /* units are Kusec */
- u32 ATIMWindow; /* units are Kusec */
- u32 DSConfig; /* Frequency, units are kHz */
- struct NDIS_802_11_CONFIGURATION_FH FHConfig;
-};
-
-enum NDIS_802_11_NETWORK_INFRASTRUCTURE {
- Ndis802_11IBSS,
- Ndis802_11Infrastructure,
- Ndis802_11AutoUnknown,
- Ndis802_11InfrastructureMax, /*Not a real value,defined as upper bound*/
- Ndis802_11APMode
-};
-
-struct NDIS_802_11_FIXED_IEs {
- u8 Timestamp[8];
- u16 BeaconInterval;
- u16 Capabilities;
-};
-
-struct wlan_bssid_ex {
- u32 Length;
- unsigned char MacAddress[6];
- u8 Reserved[2];
- struct ndis_802_11_ssid Ssid;
- __le32 Privacy;
- s32 Rssi;
- enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
- struct NDIS_802_11_CONFIGURATION Configuration;
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
- u8 rates[NDIS_802_11_LENGTH_RATES_EX];
- /* number of content bytes in EIs, which varies */
- u32 IELength;
- /*(timestamp, beacon interval, and capability information) */
- u8 IEs[MAX_IE_SZ];
-};
-
-enum NDIS_802_11_AUTHENTICATION_MODE {
- Ndis802_11AuthModeOpen,
- Ndis802_11AuthModeShared,
- Ndis802_11AuthModeAutoSwitch,
- Ndis802_11AuthModeWPA,
- Ndis802_11AuthModeWPAPSK,
- Ndis802_11AuthModeWPANone,
- Ndis802_11AuthModeMax /* Not a real mode, defined as upper bound */
-};
-
-enum {
- Ndis802_11WEPEnabled,
- Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
- Ndis802_11WEPDisabled,
- Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
- Ndis802_11WEPKeyAbsent,
- Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
- Ndis802_11WEPNotSupported,
- Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
- Ndis802_11Encryption2Enabled,
- Ndis802_11Encryption2KeyAbsent,
- Ndis802_11Encryption3Enabled,
- Ndis802_11Encryption3KeyAbsent
-};
-
-#define NDIS_802_11_AI_REQFI_CAPABILITIES 1
-#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2
-#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4
-
-#define NDIS_802_11_AI_RESFI_CAPABILITIES 1
-#define NDIS_802_11_AI_RESFI_STATUSCODE 2
-#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4
-
-struct NDIS_802_11_AI_REQFI {
- u16 Capabilities;
- u16 ListenInterval;
- unsigned char CurrentAPAddress[6];
-};
-
-struct NDIS_802_11_AI_RESFI {
- u16 Capabilities;
- u16 StatusCode;
- u16 AssociationId;
-};
-
-struct NDIS_802_11_ASSOCIATION_INFORMATION {
- u32 Length;
- u16 AvailableRequestFixedIEs;
- struct NDIS_802_11_AI_REQFI RequestFixedIEs;
- u32 RequestIELength;
- u32 OffsetRequestIEs;
- u16 AvailableResponseFixedIEs;
- struct NDIS_802_11_AI_RESFI ResponseFixedIEs;
- u32 ResponseIELength;
- u32 OffsetResponseIEs;
-};
-
-/* Key mapping keys require a BSSID*/
-struct NDIS_802_11_KEY {
- u32 Length; /* Length of this structure */
- u32 KeyIndex;
- u32 KeyLength; /* length of key in bytes */
- unsigned char BSSID[6];
- unsigned long long KeyRSC;
- u8 KeyMaterial[32]; /* variable length */
-};
-
-struct NDIS_802_11_REMOVE_KEY {
- u32 Length; /* Length of this structure */
- u32 KeyIndex;
- unsigned char BSSID[6];
-};
-
-struct NDIS_802_11_WEP {
- u32 Length; /* Length of this structure */
- u32 KeyIndex; /* 0 is the per-client key,
- * 1-N are the global keys
- */
- u32 KeyLength; /* length of key in bytes */
- u8 KeyMaterial[16]; /* variable length depending on above field */
-};
-
-/* mask for authentication/integrity fields */
-#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f
-#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01
-#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02
-#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06
-#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E
-
-/* MIC check time, 60 seconds. */
-#define MIC_CHECK_TIME 60000000
-
-#ifndef Ndis802_11APMode
-#define Ndis802_11APMode (Ndis802_11InfrastructureMax + 1)
-#endif
-
-struct wlan_network {
- struct list_head list;
- int network_type; /*refer to ieee80211.h for WIRELESS_11A/B/G */
- int fixed; /* set to fixed when not to be removed asi
- * site-surveying
- */
- unsigned int last_scanned; /*timestamp for the network */
- int aid; /*will only be valid when a BSS is joined. */
- int join_res;
- struct wlan_bssid_ex network; /*must be the last item */
-};
-
-enum VRTL_CARRIER_SENSE {
- DISABLE_VCS,
- ENABLE_VCS,
- AUTO_VCS
-};
-
-enum VCS_TYPE {
- NONE_VCS,
- RTS_CTS,
- CTS_TO_SELF
-};
-
-#define PWR_CAM 0
-#define PWR_MINPS 1
-#define PWR_MAXPS 2
-#define PWR_UAPSD 3
-#define PWR_VOIP 4
-
-enum UAPSD_MAX_SP {
- NO_LIMIT,
- TWO_MSDU,
- FOUR_MSDU,
- SIX_MSDU
-};
-
-#define NUM_PRE_AUTH_KEY 16
-#define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY
-
-#endif /* #ifndef WLAN_BSSDEF_H_ */
-
diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c
deleted file mode 100644
index ceb6b590b310..000000000000
--- a/drivers/staging/rtl8712/xmit_linux.c
+++ /dev/null
@@ -1,181 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * xmit_linux.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _XMIT_OSDEP_C_
-
-#include <linux/usb.h>
-#include <linux/ip.h>
-#include <linux/if_ether.h>
-#include <linux/kmemleak.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#include "wifi.h"
-#include "mlme_osdep.h"
-#include "xmit_osdep.h"
-#include "osdep_intf.h"
-
-static uint remainder_len(struct pkt_file *pfile)
-{
- return (uint)(pfile->buf_len - ((addr_t)(pfile->cur_addr) -
- (addr_t)(pfile->buf_start)));
-}
-
-void _r8712_open_pktfile(_pkt *pktptr, struct pkt_file *pfile)
-{
- pfile->pkt = pktptr;
- pfile->cur_addr = pfile->buf_start = pktptr->data;
- pfile->pkt_len = pfile->buf_len = pktptr->len;
- pfile->cur_buffer = pfile->buf_start;
-}
-
-uint _r8712_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen)
-{
- uint len;
-
- len = remainder_len(pfile);
- len = (rlen > len) ? len : rlen;
- if (rmem)
- skb_copy_bits(pfile->pkt, pfile->buf_len - pfile->pkt_len,
- rmem, len);
- pfile->cur_addr += len;
- pfile->pkt_len -= len;
- return len;
-}
-
-sint r8712_endofpktfile(struct pkt_file *pfile)
-{
- return (pfile->pkt_len == 0);
-}
-
-void r8712_set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib)
-{
- struct ethhdr etherhdr;
- struct iphdr ip_hdr;
- u16 user_priority = 0;
-
- _r8712_open_pktfile(ppktfile->pkt, ppktfile);
- _r8712_pktfile_read(ppktfile, (unsigned char *)&etherhdr, ETH_HLEN);
-
- /* get user_priority from IP hdr*/
- if (pattrib->ether_type == 0x0800) {
- _r8712_pktfile_read(ppktfile, (u8 *)&ip_hdr, sizeof(ip_hdr));
- /*user_priority = (ntohs(ip_hdr.tos) >> 5) & 0x3 ;*/
- user_priority = ip_hdr.tos >> 5;
- } else {
- /* "When priority processing of data frames is supported,
- * a STA's SME should send EAPOL-Key frames at the highest
- * priority."
- */
-
- if (pattrib->ether_type == 0x888e)
- user_priority = 7;
- }
- pattrib->priority = user_priority;
- pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
- pattrib->subtype = WIFI_QOS_DATA_TYPE;
-}
-
-void r8712_SetFilter(struct work_struct *work)
-{
- struct _adapter *adapter = container_of(work, struct _adapter,
- wk_filter_rx_ff0);
- u8 oldvalue = 0x00, newvalue = 0x00;
-
- oldvalue = r8712_read8(adapter, 0x117);
- newvalue = oldvalue & 0xfe;
- r8712_write8(adapter, 0x117, newvalue);
-
- wait_for_completion(&adapter->rx_filter_ready);
- r8712_write8(adapter, 0x117, oldvalue);
-}
-
-int r8712_xmit_resource_alloc(struct _adapter *padapter,
- struct xmit_buf *pxmitbuf)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
- if (!pxmitbuf->pxmit_urb[i]) {
- int k;
-
- for (k = i - 1; k >= 0; k--) {
- /* handle allocation errors part way through loop */
- usb_free_urb(pxmitbuf->pxmit_urb[k]);
- }
- netdev_err(padapter->pnetdev, "pxmitbuf->pxmit_urb[i] == NULL\n");
- return -ENOMEM;
- }
- kmemleak_not_leak(pxmitbuf->pxmit_urb[i]);
- }
- return 0;
-}
-
-void r8712_xmit_resource_free(struct _adapter *padapter,
- struct xmit_buf *pxmitbuf)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- if (pxmitbuf->pxmit_urb[i]) {
- usb_kill_urb(pxmitbuf->pxmit_urb[i]);
- usb_free_urb(pxmitbuf->pxmit_urb[i]);
- }
- }
-}
-
-void r8712_xmit_complete(struct _adapter *padapter, struct xmit_frame *pxframe)
-{
- if (pxframe->pkt)
- dev_kfree_skb_any(pxframe->pkt);
- pxframe->pkt = NULL;
-}
-
-netdev_tx_t r8712_xmit_entry(_pkt *pkt, struct net_device *netdev)
-{
- struct xmit_frame *xmitframe = NULL;
- struct _adapter *adapter = netdev_priv(netdev);
- struct xmit_priv *xmitpriv = &(adapter->xmitpriv);
-
- if (!r8712_if_up(adapter))
- goto _xmit_entry_drop;
-
- xmitframe = r8712_alloc_xmitframe(xmitpriv);
- if (!xmitframe)
- goto _xmit_entry_drop;
-
- if (r8712_update_attrib(adapter, pkt, &xmitframe->attrib))
- goto _xmit_entry_drop;
-
- adapter->ledpriv.LedControlHandler(adapter, LED_CTL_TX);
- xmitframe->pkt = pkt;
- if (r8712_pre_xmit(adapter, xmitframe)) {
- /*dump xmitframe directly or drop xframe*/
- dev_kfree_skb_any(pkt);
- xmitframe->pkt = NULL;
- }
- xmitpriv->tx_pkts++;
- xmitpriv->tx_bytes += xmitframe->attrib.last_txcmdsz;
- return NETDEV_TX_OK;
-_xmit_entry_drop:
- if (xmitframe)
- r8712_free_xmitframe(xmitpriv, xmitframe);
- xmitpriv->tx_drop++;
- dev_kfree_skb_any(pkt);
- return NETDEV_TX_OK;
-}
diff --git a/drivers/staging/rtl8712/xmit_osdep.h b/drivers/staging/rtl8712/xmit_osdep.h
deleted file mode 100644
index 1ad42658c883..000000000000
--- a/drivers/staging/rtl8712/xmit_osdep.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __XMIT_OSDEP_H_
-#define __XMIT_OSDEP_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-struct pkt_file {
- _pkt *pkt;
- u32 pkt_len; /*the remainder length of the open_file*/
- _buffer *cur_buffer;
- u8 *buf_start;
- u8 *cur_addr;
- u32 buf_len;
-};
-
-#define NR_XMITFRAME 256
-
-struct xmit_priv;
-struct pkt_attrib;
-struct sta_xmit_priv;
-struct xmit_frame;
-struct xmit_buf;
-
-netdev_tx_t r8712_xmit_entry(_pkt *pkt, struct net_device *pnetdev);
-void r8712_SetFilter(struct work_struct *work);
-int r8712_xmit_resource_alloc(struct _adapter *padapter,
- struct xmit_buf *pxmitbuf);
-void r8712_xmit_resource_free(struct _adapter *padapter,
- struct xmit_buf *pxmitbuf);
-
-void r8712_set_qos(struct pkt_file *ppktfile,
- struct pkt_attrib *pattrib);
-void _r8712_open_pktfile(_pkt *pktptr, struct pkt_file *pfile);
-uint _r8712_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen);
-sint r8712_endofpktfile(struct pkt_file *pfile);
-void r8712_xmit_complete(struct _adapter *padapter,
- struct xmit_frame *pxframe);
-
-#endif
diff --git a/drivers/staging/rtl8723bs/TODO b/drivers/staging/rtl8723bs/TODO
index 4c413f9d3df0..050dcd0bffab 100644
--- a/drivers/staging/rtl8723bs/TODO
+++ b/drivers/staging/rtl8723bs/TODO
@@ -6,6 +6,3 @@ TODO:
of them will require refactoring
- merge Realtek's bugfixes and new features into the driver
- switch to use MAC80211
-
-Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
-Hans de Goede <hdegoede@redhat.com> and Larry Finger <Larry.Finger@lwfinger.net>.
diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c
index 84ce7307d8f3..64ce33c6fba1 100644
--- a/drivers/staging/rtl8723bs/core/rtw_cmd.c
+++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c
@@ -382,7 +382,7 @@ int rtw_cmd_thread(void *context)
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
struct drvextra_cmd_parm *extra_parm = NULL;
- thread_enter("RTW_CMD_THREAD");
+ allow_signal(SIGTERM);
pcmdbuf = pcmdpriv->cmd_buf;
@@ -1258,8 +1258,7 @@ static void dynamic_chk_wk_hdl(struct adapter *padapter)
/* always call rtw_ps_processor() at last one. */
- if (is_primary_adapter(padapter))
- rtw_ps_processor(padapter);
+ rtw_ps_processor(padapter);
}
void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type);
@@ -1465,6 +1464,7 @@ u8 rtw_ps_cmd(struct adapter *padapter)
struct drvextra_cmd_parm *pdrvextra_cmd_parm;
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
u8 res = _SUCCESS;
+
ppscmd = rtw_zmalloc(sizeof(struct cmd_obj));
if (!ppscmd) {
res = _FAIL;
diff --git a/drivers/staging/rtl8723bs/core/rtw_efuse.c b/drivers/staging/rtl8723bs/core/rtw_efuse.c
index 8b671f8a7965..7a74b011dedc 100644
--- a/drivers/staging/rtl8723bs/core/rtw_efuse.c
+++ b/drivers/staging/rtl8723bs/core/rtw_efuse.c
@@ -77,33 +77,7 @@ struct adapter *padapter,
u8 bWrite,
u8 PwrState)
{
- padapter->HalFunc.EfusePowerSwitch(padapter, bWrite, PwrState);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: Efuse_GetCurrentSize
- *
- * Overview: Get current efuse size!!!
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 11/16/2008 MHC Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-u16
-Efuse_GetCurrentSize(
- struct adapter *padapter,
- u8 efuseType,
- bool bPseudoTest)
-{
- return padapter->HalFunc.EfuseGetCurrentSize(padapter, efuseType,
- bPseudoTest);
+ Hal_EfusePowerSwitch(padapter, bWrite, PwrState);
}
/* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
@@ -159,7 +133,7 @@ efuse_ReadEFuse(
bool bPseudoTest
)
{
- Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
+ Hal_ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
}
void
@@ -171,7 +145,7 @@ EFUSE_GetEfuseDefinition(
bool bPseudoTest
)
{
- padapter->HalFunc.EFUSEGetEfuseDefinition(padapter, efuseType, type, pOut, bPseudoTest);
+ Hal_GetEfuseDefinition(padapter, efuseType, type, pOut, bPseudoTest);
}
/*-----------------------------------------------------------------------------
@@ -312,68 +286,6 @@ u8 efuse_OneByteWrite(struct adapter *padapter, u16 addr, u8 data, bool bPseudoT
return bResult;
}
-int
-Efuse_PgPacketRead(struct adapter *padapter,
- u8 offset,
- u8 *data,
- bool bPseudoTest)
-{
- return padapter->HalFunc.Efuse_PgPacketRead(padapter, offset, data,
- bPseudoTest);
-}
-
-int
-Efuse_PgPacketWrite(struct adapter *padapter,
- u8 offset,
- u8 word_en,
- u8 *data,
- bool bPseudoTest)
-{
- return padapter->HalFunc.Efuse_PgPacketWrite(padapter, offset, word_en,
- data, bPseudoTest);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: efuse_WordEnableDataRead
- *
- * Overview: Read allowed word in current efuse section data.
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 11/16/2008 MHC Create Version 0.
- * 11/21/2008 MHC Fix Write bug when we only enable late word.
- *
- *---------------------------------------------------------------------------*/
-void
-efuse_WordEnableDataRead(u8 word_en,
- u8 *sourdata,
- u8 *targetdata)
-{
- if (!(word_en & BIT(0))) {
- targetdata[0] = sourdata[0];
- targetdata[1] = sourdata[1];
- }
- if (!(word_en & BIT(1))) {
- targetdata[2] = sourdata[2];
- targetdata[3] = sourdata[3];
- }
- if (!(word_en & BIT(2))) {
- targetdata[4] = sourdata[4];
- targetdata[5] = sourdata[5];
- }
- if (!(word_en & BIT(3))) {
- targetdata[6] = sourdata[6];
- targetdata[7] = sourdata[7];
- }
-}
-
-
u8
Efuse_WordEnableDataWrite(struct adapter *padapter,
u16 efuse_addr,
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c
index cbdb134278d3..5ded183aa08c 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c
@@ -911,8 +911,7 @@ inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted)
{
rtw_os_indicate_scan_done(padapter, aborted);
- if (is_primary_adapter(padapter) &&
- (!adapter_to_pwrctl(padapter)->bInSuspend) &&
+ if ((!adapter_to_pwrctl(padapter)->bInSuspend) &&
(!check_fwstate(&padapter->mlmepriv,
WIFI_ASOC_STATE|WIFI_UNDER_LINKING))) {
rtw_set_ips_deny(padapter, 0);
@@ -1589,8 +1588,7 @@ void rtw_dynamic_check_timer_handler(struct adapter *adapter)
}
} else {
- if (is_primary_adapter(adapter))
- rtw_dynamic_chk_wk_cmd(adapter);
+ rtw_dynamic_chk_wk_cmd(adapter);
}
/* auto site survey */
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
index 4d4bec47d187..317f3db19397 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
@@ -1870,10 +1870,10 @@ unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv
if (0) {
int pp;
- printk("pattrib->pktlen = %d =>", pattrib->pkt_len);
+ netdev_dbg(padapter->pnetdev, "pattrib->pktlen = %d =>", pattrib->pkt_len);
for (pp = 0; pp < pattrib->pkt_len; pp++)
- printk(" %02x ", pframe[pp]);
- printk("\n");
+ pr_cont(" %02x ", pframe[pp]);
+ pr_cont("\n");
}
return _SUCCESS;
@@ -4872,8 +4872,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
/* set_link_timer(pmlmeext, DISCONNECT_TO); */
}
- if (get_iface_type(padapter) == IFACE_PORT0)
- rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
}
/* currently only adhoc mode will go here */
@@ -5638,7 +5637,7 @@ u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true);
/* allow multicast packets to driver */
- padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
+ SetHwReg8723BS(padapter, HW_VAR_ON_RCR_AM, null_addr);
return H2C_SUCCESS;
}
diff --git a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c
index dbfcbac3d855..c60e179bb2e1 100644
--- a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c
+++ b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c
@@ -73,9 +73,6 @@ int ips_leave(struct adapter *padapter)
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
int ret;
- if (!is_primary_adapter(padapter))
- return _SUCCESS;
-
mutex_lock(&pwrpriv->lock);
ret = _ips_leave(padapter);
mutex_unlock(&pwrpriv->lock);
@@ -455,10 +452,6 @@ void LPS_Enter(struct adapter *padapter, const char *msg)
if (n_assoc_iface != 1)
return;
- /* Skip lps enter request for adapter not port0 */
- if (get_iface_type(padapter) != IFACE_PORT0)
- return;
-
if (!PS_RDY_CHECK(dvobj->padapters))
return;
diff --git a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
index f37fec1efaf9..73c70b016f00 100644
--- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
@@ -290,21 +290,11 @@ inline void rtw_set_oper_ch(struct adapter *adapter, u8 ch)
dvobj->oper_channel = ch;
}
-inline u8 rtw_get_oper_bw(struct adapter *adapter)
-{
- return adapter_to_dvobj(adapter)->oper_bwmode;
-}
-
inline void rtw_set_oper_bw(struct adapter *adapter, u8 bw)
{
adapter_to_dvobj(adapter)->oper_bwmode = bw;
}
-inline u8 rtw_get_oper_choffset(struct adapter *adapter)
-{
- return adapter_to_dvobj(adapter)->oper_ch_offset;
-}
-
inline void rtw_set_oper_choffset(struct adapter *adapter, u8 offset)
{
adapter_to_dvobj(adapter)->oper_ch_offset = offset;
@@ -445,34 +435,6 @@ void invalidate_cam_all(struct adapter *padapter)
spin_unlock_bh(&cam_ctl->lock);
}
-static u32 _ReadCAM(struct adapter *padapter, u32 addr)
-{
- u32 count = 0, cmd;
-
- cmd = CAM_POLLINIG | addr;
- rtw_write32(padapter, RWCAM, cmd);
-
- do {
- if (0 == (rtw_read32(padapter, REG_CAMCMD) & CAM_POLLINIG))
- break;
- } while (count++ < 100);
-
- return rtw_read32(padapter, REG_CAMREAD);
-}
-
-void read_cam(struct adapter *padapter, u8 entry, u8 *get_key)
-{
- u32 j, addr, cmd;
-
- addr = entry << 3;
-
- for (j = 0; j < 6; j++) {
- cmd = _ReadCAM(padapter, addr+j);
- if (j > 1) /* get key from cam */
- memcpy(get_key+(j-2)*4, &cmd, 4);
- }
-}
-
void _write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
{
unsigned int i, val, addr;
@@ -1613,9 +1575,9 @@ void update_wireless_mode(struct adapter *padapter)
SIFS_Timer = 0x0a0a0808; /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
/* change this value if having IOT issues. */
- padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer);
+ SetHwReg8723BS(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer);
- padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_WIRELESS_MODE, (u8 *)&(pmlmeext->cur_wireless_mode));
+ SetHwReg8723BS(padapter, HW_VAR_WIRELESS_MODE, (u8 *)&(pmlmeext->cur_wireless_mode));
if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB);
@@ -1822,29 +1784,3 @@ void rtw_release_macid(struct adapter *padapter, struct sta_info *psta)
}
spin_unlock_bh(&pdvobj->lock);
}
-
-/* For 8188E RA */
-u8 rtw_search_max_mac_id(struct adapter *padapter)
-{
- u8 max_mac_id = 0;
- struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
- int i;
-
- spin_lock_bh(&pdvobj->lock);
- for (i = (NUM_STA-1); i >= 0 ; i--) {
- if (pdvobj->macid[i] == true)
- break;
- }
- max_mac_id = i;
- spin_unlock_bh(&pdvobj->lock);
-
- return max_mac_id;
-}
-
-struct adapter *dvobj_get_port0_adapter(struct dvobj_priv *dvobj)
-{
- if (get_iface_type(dvobj->padapters[i]) != IFACE_PORT0)
- return NULL;
-
- return dvobj->padapters;
-}
diff --git a/drivers/staging/rtl8723bs/core/rtw_xmit.c b/drivers/staging/rtl8723bs/core/rtw_xmit.c
index 3e88f14e3bf7..699cff7b0ac9 100644
--- a/drivers/staging/rtl8723bs/core/rtw_xmit.c
+++ b/drivers/staging/rtl8723bs/core/rtw_xmit.c
@@ -2489,7 +2489,7 @@ int rtw_xmit_thread(void *context)
err = _SUCCESS;
padapter = context;
- thread_enter("RTW_XMIT_THREAD");
+ allow_signal(SIGTERM);
do {
err = rtw_hal_xmit_thread_handler(padapter);
diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c
index 719dd116d807..95fb38283c58 100644
--- a/drivers/staging/rtl8723bs/hal/hal_com.c
+++ b/drivers/staging/rtl8723bs/hal/hal_com.c
@@ -13,23 +13,20 @@
u8 rtw_hal_data_init(struct adapter *padapter)
{
- if (is_primary_adapter(padapter)) { /* if (padapter->isprimary) */
- padapter->hal_data_sz = sizeof(struct hal_com_data);
- padapter->HalData = vzalloc(padapter->hal_data_sz);
- if (!padapter->HalData)
- return _FAIL;
- }
+ padapter->hal_data_sz = sizeof(struct hal_com_data);
+ padapter->HalData = vzalloc(padapter->hal_data_sz);
+ if (!padapter->HalData)
+ return _FAIL;
+
return _SUCCESS;
}
void rtw_hal_data_deinit(struct adapter *padapter)
{
- if (is_primary_adapter(padapter)) { /* if (padapter->isprimary) */
- if (padapter->HalData) {
- vfree(padapter->HalData);
- padapter->HalData = NULL;
- padapter->hal_data_sz = 0;
- }
+ if (padapter->HalData) {
+ vfree(padapter->HalData);
+ padapter->HalData = NULL;
+ padapter->hal_data_sz = 0;
}
}
@@ -796,19 +793,6 @@ u8 GetHalDefVar(
return bResult;
}
-void GetHalODMVar(
- struct adapter *Adapter,
- enum hal_odm_variable eVariable,
- void *pValue1,
- void *pValue2
-)
-{
- switch (eVariable) {
- default:
- break;
- }
-}
-
void SetHalODMVar(
struct adapter *Adapter,
enum hal_odm_variable eVariable,
@@ -883,7 +867,6 @@ void rtw_hal_check_rxfifo_full(struct adapter *adapter)
int save_cnt = false;
/* switch counter to RX fifo */
- /* printk("8723b or 8192e , MAC_667 set 0xf0\n"); */
rtw_write8(adapter, REG_RXERR_RPT+3, rtw_read8(adapter, REG_RXERR_RPT+3)|0xf0);
save_cnt = true;
/* todo: other chips */
@@ -910,10 +893,9 @@ void rtw_dump_raw_rssi_info(struct adapter *padapter)
for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++) {
if (!isCCKrate) {
- printk(", rx_ofdm_pwr:%d(dBm), rx_ofdm_snr:%d(dB)\n",
- psample_pkt_rssi->ofdm_pwr[rf_path], psample_pkt_rssi->ofdm_snr[rf_path]);
- } else {
- printk("\n");
+ netdev_dbg(padapter->pnetdev, ", rx_ofdm_pwr:%d(dBm), rx_ofdm_snr:%d(dB)\n",
+ psample_pkt_rssi->ofdm_pwr[rf_path],
+ psample_pkt_rssi->ofdm_snr[rf_path]);
}
}
}
diff --git a/drivers/staging/rtl8723bs/hal/hal_intf.c b/drivers/staging/rtl8723bs/hal/hal_intf.c
index 0a3900548fd2..0db8f623b805 100644
--- a/drivers/staging/rtl8723bs/hal/hal_intf.c
+++ b/drivers/staging/rtl8723bs/hal/hal_intf.c
@@ -9,52 +9,37 @@
void rtw_hal_chip_configure(struct adapter *padapter)
{
- if (padapter->HalFunc.intf_chip_configure)
- padapter->HalFunc.intf_chip_configure(padapter);
+ rtl8723bs_interface_configure(padapter);
}
void rtw_hal_read_chip_info(struct adapter *padapter)
{
- if (padapter->HalFunc.read_adapter_info)
- padapter->HalFunc.read_adapter_info(padapter);
+ ReadAdapterInfo8723BS(padapter);
}
void rtw_hal_read_chip_version(struct adapter *padapter)
{
- if (padapter->HalFunc.read_chip_version)
- padapter->HalFunc.read_chip_version(padapter);
+ rtl8723b_read_chip_version(padapter);
}
void rtw_hal_def_value_init(struct adapter *padapter)
{
- if (is_primary_adapter(padapter))
- if (padapter->HalFunc.init_default_value)
- padapter->HalFunc.init_default_value(padapter);
+ rtl8723bs_init_default_value(padapter);
}
void rtw_hal_free_data(struct adapter *padapter)
{
/* free HAL Data */
rtw_hal_data_deinit(padapter);
-
- if (is_primary_adapter(padapter))
- if (padapter->HalFunc.free_hal_data)
- padapter->HalFunc.free_hal_data(padapter);
}
void rtw_hal_dm_init(struct adapter *padapter)
{
- if (is_primary_adapter(padapter))
- if (padapter->HalFunc.dm_init)
- padapter->HalFunc.dm_init(padapter);
+ rtl8723b_init_dm_priv(padapter);
}
void rtw_hal_dm_deinit(struct adapter *padapter)
{
- /* cancel dm timer */
- if (is_primary_adapter(padapter))
- if (padapter->HalFunc.dm_deinit)
- padapter->HalFunc.dm_deinit(padapter);
}
static void rtw_hal_init_opmode(struct adapter *padapter)
@@ -82,7 +67,7 @@ uint rtw_hal_init(struct adapter *padapter)
uint status;
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
- status = padapter->HalFunc.hal_init(padapter);
+ status = rtl8723bs_hal_init(padapter);
if (status == _SUCCESS) {
rtw_hal_init_opmode(padapter);
@@ -111,7 +96,7 @@ uint rtw_hal_deinit(struct adapter *padapter)
uint status = _SUCCESS;
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
- status = padapter->HalFunc.hal_deinit(padapter);
+ status = rtl8723bs_hal_deinit(padapter);
if (status == _SUCCESS) {
padapter = dvobj->padapters;
@@ -123,34 +108,27 @@ uint rtw_hal_deinit(struct adapter *padapter)
void rtw_hal_set_hwreg(struct adapter *padapter, u8 variable, u8 *val)
{
- if (padapter->HalFunc.SetHwRegHandler)
- padapter->HalFunc.SetHwRegHandler(padapter, variable, val);
+ SetHwReg8723BS(padapter, variable, val);
}
void rtw_hal_get_hwreg(struct adapter *padapter, u8 variable, u8 *val)
{
- if (padapter->HalFunc.GetHwRegHandler)
- padapter->HalFunc.GetHwRegHandler(padapter, variable, val);
+ GetHwReg8723BS(padapter, variable, val);
}
void rtw_hal_set_hwreg_with_buf(struct adapter *padapter, u8 variable, u8 *pbuf, int len)
{
- if (padapter->HalFunc.SetHwRegHandlerWithBuf)
- padapter->HalFunc.SetHwRegHandlerWithBuf(padapter, variable, pbuf, len);
+ SetHwRegWithBuf8723B(padapter, variable, pbuf, len);
}
u8 rtw_hal_set_def_var(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue)
{
- if (padapter->HalFunc.SetHalDefVarHandler)
- return padapter->HalFunc.SetHalDefVarHandler(padapter, eVariable, pValue);
- return _FAIL;
+ return SetHalDefVar8723BSDIO(padapter, eVariable, pValue);
}
u8 rtw_hal_get_def_var(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue)
{
- if (padapter->HalFunc.GetHalDefVarHandler)
- return padapter->HalFunc.GetHalDefVarHandler(padapter, eVariable, pValue);
- return _FAIL;
+ return GetHalDefVar8723BSDIO(padapter, eVariable, pValue);
}
void rtw_hal_set_odm_var(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
@@ -161,40 +139,27 @@ void rtw_hal_set_odm_var(struct adapter *padapter, enum hal_odm_variable eVariab
void rtw_hal_enable_interrupt(struct adapter *padapter)
{
- if (padapter->HalFunc.enable_interrupt)
- padapter->HalFunc.enable_interrupt(padapter);
+ EnableInterrupt8723BSdio(padapter);
}
void rtw_hal_disable_interrupt(struct adapter *padapter)
{
- if (padapter->HalFunc.disable_interrupt)
- padapter->HalFunc.disable_interrupt(padapter);
+ DisableInterrupt8723BSdio(padapter);
}
u8 rtw_hal_check_ips_status(struct adapter *padapter)
{
- u8 val = false;
-
- if (padapter->HalFunc.check_ips_status)
- val = padapter->HalFunc.check_ips_status(padapter);
-
- return val;
+ return CheckIPSStatus(padapter);
}
s32 rtw_hal_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe)
{
- if (padapter->HalFunc.hal_xmitframe_enqueue)
- return padapter->HalFunc.hal_xmitframe_enqueue(padapter, pxmitframe);
-
- return false;
+ return rtl8723bs_hal_xmitframe_enqueue(padapter, pxmitframe);
}
s32 rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe)
{
- if (padapter->HalFunc.hal_xmit)
- return padapter->HalFunc.hal_xmit(padapter, pxmitframe);
-
- return false;
+ return rtl8723bs_hal_xmit(padapter, pxmitframe);
}
/*
@@ -202,8 +167,6 @@ s32 rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe)
*/
s32 rtw_hal_mgnt_xmit(struct adapter *padapter, struct xmit_frame *pmgntframe)
{
- s32 ret = _FAIL;
-
update_mgntframe_attrib_addr(padapter, pmgntframe);
/* pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; */
/* pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; */
@@ -220,36 +183,27 @@ s32 rtw_hal_mgnt_xmit(struct adapter *padapter, struct xmit_frame *pmgntframe)
rtw_mgmt_xmitframe_coalesce(padapter, pmgntframe->pkt, pmgntframe);
}
- if (padapter->HalFunc.mgnt_xmit)
- ret = padapter->HalFunc.mgnt_xmit(padapter, pmgntframe);
- return ret;
+ return rtl8723bs_mgnt_xmit(padapter, pmgntframe);
}
s32 rtw_hal_init_xmit_priv(struct adapter *padapter)
{
- if (padapter->HalFunc.init_xmit_priv)
- return padapter->HalFunc.init_xmit_priv(padapter);
- return _FAIL;
+ return rtl8723bs_init_xmit_priv(padapter);
}
void rtw_hal_free_xmit_priv(struct adapter *padapter)
{
- if (padapter->HalFunc.free_xmit_priv)
- padapter->HalFunc.free_xmit_priv(padapter);
+ rtl8723bs_free_xmit_priv(padapter);
}
s32 rtw_hal_init_recv_priv(struct adapter *padapter)
{
- if (padapter->HalFunc.init_recv_priv)
- return padapter->HalFunc.init_recv_priv(padapter);
-
- return _FAIL;
+ return rtl8723bs_init_recv_priv(padapter);
}
void rtw_hal_free_recv_priv(struct adapter *padapter)
{
- if (padapter->HalFunc.free_recv_priv)
- padapter->HalFunc.free_recv_priv(padapter);
+ rtl8723bs_free_recv_priv(padapter);
}
void rtw_hal_update_ra_mask(struct sta_info *psta, u8 rssi_level)
@@ -267,91 +221,70 @@ void rtw_hal_update_ra_mask(struct sta_info *psta, u8 rssi_level)
if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
add_RATid(padapter, psta, rssi_level);
else {
- if (padapter->HalFunc.UpdateRAMaskHandler)
- padapter->HalFunc.UpdateRAMaskHandler(padapter, psta->mac_id, rssi_level);
+ UpdateHalRAMask8723B(padapter, psta->mac_id, rssi_level);
}
}
void rtw_hal_add_ra_tid(struct adapter *padapter, u32 bitmap, u8 *arg, u8 rssi_level)
{
- if (padapter->HalFunc.Add_RateATid)
- padapter->HalFunc.Add_RateATid(padapter, bitmap, arg, rssi_level);
+ rtl8723b_Add_RateATid(padapter, bitmap, arg, rssi_level);
}
/*Start specifical interface thread */
void rtw_hal_start_thread(struct adapter *padapter)
{
- if (padapter->HalFunc.run_thread)
- padapter->HalFunc.run_thread(padapter);
+ rtl8723b_start_thread(padapter);
}
/*Start specifical interface thread */
void rtw_hal_stop_thread(struct adapter *padapter)
{
- if (padapter->HalFunc.cancel_thread)
- padapter->HalFunc.cancel_thread(padapter);
+ rtl8723b_stop_thread(padapter);
}
u32 rtw_hal_read_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask)
{
- u32 data = 0;
-
- if (padapter->HalFunc.read_bbreg)
- data = padapter->HalFunc.read_bbreg(padapter, RegAddr, BitMask);
- return data;
+ return PHY_QueryBBReg_8723B(padapter, RegAddr, BitMask);
}
void rtw_hal_write_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data)
{
- if (padapter->HalFunc.write_bbreg)
- padapter->HalFunc.write_bbreg(padapter, RegAddr, BitMask, Data);
+ PHY_SetBBReg_8723B(padapter, RegAddr, BitMask, Data);
}
u32 rtw_hal_read_rfreg(struct adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask)
{
- u32 data = 0;
-
- if (padapter->HalFunc.read_rfreg)
- data = padapter->HalFunc.read_rfreg(padapter, eRFPath, RegAddr, BitMask);
- return data;
+ return PHY_QueryRFReg_8723B(padapter, eRFPath, RegAddr, BitMask);
}
void rtw_hal_write_rfreg(struct adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask, u32 Data)
{
- if (padapter->HalFunc.write_rfreg)
- padapter->HalFunc.write_rfreg(padapter, eRFPath, RegAddr, BitMask, Data);
+ PHY_SetRFReg_8723B(padapter, eRFPath, RegAddr, BitMask, Data);
}
void rtw_hal_set_chan(struct adapter *padapter, u8 channel)
{
- if (padapter->HalFunc.set_channel_handler)
- padapter->HalFunc.set_channel_handler(padapter, channel);
+ PHY_SwChnl8723B(padapter, channel);
}
void rtw_hal_set_chnl_bw(struct adapter *padapter, u8 channel,
enum channel_width Bandwidth, u8 Offset40, u8 Offset80)
{
- if (padapter->HalFunc.set_chnl_bw_handler)
- padapter->HalFunc.set_chnl_bw_handler(padapter, channel,
- Bandwidth, Offset40,
- Offset80);
+ PHY_SetSwChnlBWMode8723B(padapter, channel, Bandwidth, Offset40, Offset80);
}
void rtw_hal_dm_watchdog(struct adapter *padapter)
{
- if (padapter->HalFunc.hal_dm_watchdog)
- padapter->HalFunc.hal_dm_watchdog(padapter);
+ rtl8723b_HalDmWatchDog(padapter);
}
void rtw_hal_dm_watchdog_in_lps(struct adapter *padapter)
{
if (adapter_to_pwrctl(padapter)->fw_current_in_ps_mode) {
- if (padapter->HalFunc.hal_dm_watchdog_in_lps)
- padapter->HalFunc.hal_dm_watchdog_in_lps(padapter); /* this function caller is in interrupt context */
+ rtl8723b_HalDmWatchDog_in_LPS(padapter); /* this function caller is in interrupt context */
}
}
void beacon_timing_control(struct adapter *padapter)
{
- if (padapter->HalFunc.SetBeaconRelatedRegistersHandler)
- padapter->HalFunc.SetBeaconRelatedRegistersHandler(padapter);
+ rtl8723b_SetBeaconRelatedRegisters(padapter);
}
diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c
index ea3b4cd32360..8d6131f0ad47 100644
--- a/drivers/staging/rtl8723bs/hal/odm.c
+++ b/drivers/staging/rtl8723bs/hal/odm.c
@@ -417,13 +417,11 @@ static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm)
u8 i;
struct adapter *padapter = pDM_Odm->Adapter;
- if (padapter->bDriverStopped) {
+ if (padapter->bDriverStopped)
return;
- }
- if (!pDM_Odm->bUseRAMask) {
+ if (!pDM_Odm->bUseRAMask)
return;
- }
for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
PSTA_INFO_T pstat = pDM_Odm->pODM_StaInfo[i];
@@ -433,7 +431,6 @@ static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm)
continue;
if (true == ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) {
- /* printk("RSSI:%d, RSSI_LEVEL:%d\n", pstat->rssi_stat.UndecoratedSmoothedPWDB, pstat->rssi_level); */
rtw_hal_update_ra_mask(pstat, pstat->rssi_level);
}
@@ -461,9 +458,9 @@ static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm)
static void odm_RefreshRateAdaptiveMask(struct dm_odm_t *pDM_Odm)
{
- if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK)) {
+ if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK))
return;
- }
+
odm_RefreshRateAdaptiveMaskCE(pDM_Odm);
}
@@ -512,7 +509,6 @@ bool ODM_RAStateCheck(
RATRState = DM_RATR_STA_MIDDLE;
else
RATRState = DM_RATR_STA_LOW;
- /* printk("==>%s, RATRState:0x%02x , RSSI:%d\n", __func__, RATRState, RSSI); */
if (*pRATRState != RATRState || bForceUpdate) {
*pRATRState = RATRState;
@@ -593,8 +589,6 @@ static void odm_RSSIMonitorCheckCE(struct dm_odm_t *pDM_Odm)
}
}
- /* printk("%s ==> sta_cnt(%d)\n", __func__, sta_cnt); */
-
for (i = 0; i < sta_cnt; i++) {
if (PWDB_rssi[i] != (0)) {
if (pHalData->fw_ractrl == true)/* Report every sta's RSSI to FW */
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
index 37ebbbf408ec..e15ec6452fd0 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
@@ -53,8 +53,6 @@ static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize)
u8 *bufferPtr = buffer;
u32 i = 0, offset = 0;
-/* printk("====>%s %d\n", __func__, __LINE__); */
-
/* 3 Phase #1 */
blockCount_p1 = buffSize / blockSize_p1;
remainSize_p1 = buffSize % blockSize_p1;
@@ -62,7 +60,8 @@ static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize)
for (i = 0; i < blockCount_p1; i++) {
ret = rtw_write32(padapter, (FW_8723B_START_ADDRESS + i * blockSize_p1), *((u32 *)(bufferPtr + i * blockSize_p1)));
if (ret == _FAIL) {
- printk("====>%s %d i:%d\n", __func__, __LINE__, i);
+ netdev_dbg(padapter->pnetdev, "write failed at %s %d, block:%d\n",
+ __func__, __LINE__, i);
goto exit;
}
}
@@ -85,7 +84,8 @@ static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize)
ret = rtw_write8(padapter, (FW_8723B_START_ADDRESS + offset + i), *(bufferPtr + offset + i));
if (ret == _FAIL) {
- printk("====>%s %d i:%d\n", __func__, __LINE__, i);
+ netdev_dbg(padapter->pnetdev, "write failed at %s %d, block:%d\n",
+ __func__, __LINE__, i);
goto exit;
}
}
@@ -127,7 +127,8 @@ static int _WriteFW(struct adapter *padapter, void *buffer, u32 size)
ret = _PageWrite(padapter, page, bufferPtr+offset, MAX_DLFW_PAGE_SIZE);
if (ret == _FAIL) {
- printk("====>%s %d\n", __func__, __LINE__);
+ netdev_dbg(padapter->pnetdev, "page write failed at %s %d\n",
+ __func__, __LINE__);
goto exit;
}
}
@@ -138,7 +139,8 @@ static int _WriteFW(struct adapter *padapter, void *buffer, u32 size)
ret = _PageWrite(padapter, page, bufferPtr+offset, remainSize);
if (ret == _FAIL) {
- printk("====>%s %d\n", __func__, __LINE__);
+ netdev_dbg(padapter->pnetdev, "remaining page write failed at %s %d\n",
+ __func__, __LINE__);
goto exit;
}
}
@@ -439,10 +441,6 @@ void rtl8723b_InitializeFirmwareVars(struct adapter *padapter)
/* pHalData->H2CStopInsertQueue = false; */
}
-static void rtl8723b_free_hal_data(struct adapter *padapter)
-{
-}
-
/* */
/* Efuse related code */
/* */
@@ -492,7 +490,7 @@ static u8 hal_EfuseSwitchToBank(
return bRet;
}
-static void Hal_GetEfuseDefinition(
+void Hal_GetEfuseDefinition(
struct adapter *padapter,
u8 efuseType,
u8 type,
@@ -604,46 +602,7 @@ static void Hal_GetEfuseDefinition(
#define EFUSE_ACCESS_ON_8723 0x69 /* For RTL8723 only. */
#define REG_EFUSE_ACCESS_8723 0x00CF /* Efuse access protection for RTL8723 */
-/* */
-static void Hal_BT_EfusePowerSwitch(
- struct adapter *padapter, u8 bWrite, u8 PwrState
-)
-{
- u8 tempval;
- if (PwrState) {
- /* enable BT power cut */
- /* 0x6A[14] = 1 */
- tempval = rtw_read8(padapter, 0x6B);
- tempval |= BIT(6);
- rtw_write8(padapter, 0x6B, tempval);
-
- /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */
- /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */
- msleep(1);
- /* disable BT output isolation */
- /* 0x6A[15] = 0 */
- tempval = rtw_read8(padapter, 0x6B);
- tempval &= ~BIT(7);
- rtw_write8(padapter, 0x6B, tempval);
- } else {
- /* enable BT output isolation */
- /* 0x6A[15] = 1 */
- tempval = rtw_read8(padapter, 0x6B);
- tempval |= BIT(7);
- rtw_write8(padapter, 0x6B, tempval);
-
- /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */
- /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */
-
- /* disable BT power cut */
- /* 0x6A[14] = 1 */
- tempval = rtw_read8(padapter, 0x6B);
- tempval &= ~BIT(6);
- rtw_write8(padapter, 0x6B, tempval);
- }
-
-}
-static void Hal_EfusePowerSwitch(
+void Hal_EfusePowerSwitch(
struct adapter *padapter, u8 bWrite, u8 PwrState
)
{
@@ -928,7 +887,7 @@ exit:
kfree(efuseTbl);
}
-static void Hal_ReadEFuse(
+void Hal_ReadEFuse(
struct adapter *padapter,
u8 efuseType,
u16 _offset,
@@ -1069,7 +1028,6 @@ static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest)
/* only when bank is switched we have to reset the efuse_addr. */
if (bank != startBank)
efuse_addr = 0;
-#if 1
while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
if (efuse_OneByteRead(padapter, efuse_addr,
@@ -1098,33 +1056,6 @@ static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest)
/* read next header */
efuse_addr += (word_cnts*2)+1;
}
-#else
- while (
- bContinual &&
- efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest) &&
- AVAILABLE_EFUSE_ADDR(efuse_addr)
- ) {
- if (efuse_data != 0xFF) {
- if ((efuse_data&0x1F) == 0x0F) { /* extended header */
- efuse_addr++;
- efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest);
- if ((efuse_data & 0x0F) == 0x0F) {
- efuse_addr++;
- continue;
- } else {
- hworden = efuse_data & 0x0F;
- }
- } else {
- hworden = efuse_data & 0x0F;
- }
- word_cnts = Efuse_CalculateWordCnts(hworden);
- /* read next header */
- efuse_addr = efuse_addr + (word_cnts*2)+1;
- } else
- bContinual = false;
- }
-#endif
-
/* Check if we need to check next bank efuse */
if (efuse_addr < retU2)
@@ -1141,7 +1072,7 @@ static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest)
return retU2;
}
-static u16 Hal_EfuseGetCurrentSize(
+u16 Hal_EfuseGetCurrentSize(
struct adapter *padapter, u8 efuseType, bool bPseudoTest
)
{
@@ -1220,403 +1151,6 @@ static u8 Hal_EfuseWordEnableDataWrite(
return badworden;
}
-static s32 Hal_EfusePgPacketRead(
- struct adapter *padapter,
- u8 offset,
- u8 *data,
- bool bPseudoTest
-)
-{
- u8 efuse_data, word_cnts = 0;
- u16 efuse_addr = 0;
- u8 hoffset = 0, hworden = 0;
- u8 i;
- u8 max_section = 0;
- s32 ret;
-
-
- if (!data)
- return false;
-
- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, &max_section, bPseudoTest);
- if (offset > max_section)
- return false;
-
- memset(data, 0xFF, PGPKT_DATA_SIZE);
- ret = true;
-
- /* */
- /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
- /* Skip dummy parts to prevent unexpected data read from Efuse. */
- /* By pass right now. 2009.02.19. */
- /* */
- while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
- if (efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest) == false) {
- ret = false;
- break;
- }
-
- if (efuse_data == 0xFF)
- break;
-
- if (EXT_HEADER(efuse_data)) {
- hoffset = GET_HDR_OFFSET_2_0(efuse_data);
- efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest);
- if (ALL_WORDS_DISABLED(efuse_data))
- continue;
-
- hoffset |= ((efuse_data & 0xF0) >> 1);
- hworden = efuse_data & 0x0F;
- } else {
- hoffset = (efuse_data>>4) & 0x0F;
- hworden = efuse_data & 0x0F;
- }
-
- if (hoffset == offset) {
- for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
- /* Check word enable condition in the section */
- if (!(hworden & (0x01<<i))) {
- efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest);
- data[i*2] = efuse_data;
-
- efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest);
- data[(i*2)+1] = efuse_data;
- }
- }
- } else {
- word_cnts = Efuse_CalculateWordCnts(hworden);
- efuse_addr += word_cnts*2;
- }
- }
-
- return ret;
-}
-
-static u8 hal_EfusePgCheckAvailableAddr(
- struct adapter *padapter, u8 efuseType, u8 bPseudoTest
-)
-{
- u16 max_available = 0;
- u16 current_size;
-
-
- EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &max_available, bPseudoTest);
-
- current_size = Efuse_GetCurrentSize(padapter, efuseType, bPseudoTest);
- if (current_size >= max_available)
- return false;
-
- return true;
-}
-
-static void hal_EfuseConstructPGPkt(
- u8 offset,
- u8 word_en,
- u8 *pData,
- struct pgpkt_struct *pTargetPkt
-)
-{
- memset(pTargetPkt->data, 0xFF, PGPKT_DATA_SIZE);
- pTargetPkt->offset = offset;
- pTargetPkt->word_en = word_en;
- efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
- pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
-}
-
-static u8 hal_EfusePartialWriteCheck(
- struct adapter *padapter,
- u8 efuseType,
- u16 *pAddr,
- struct pgpkt_struct *pTargetPkt,
- u8 bPseudoTest
-)
-{
- struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
- struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
- u8 bRet = false;
- u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
- u8 efuse_data = 0;
-
- EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &efuse_max_available_len, bPseudoTest);
- EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_CONTENT_LEN_BANK, &efuse_max, bPseudoTest);
-
- if (efuseType == EFUSE_WIFI) {
- if (bPseudoTest) {
-#ifdef HAL_EFUSE_MEMORY
- startAddr = (u16)pEfuseHal->fakeEfuseUsedBytes;
-#else
- startAddr = (u16)fakeEfuseUsedBytes;
-#endif
- } else
- rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
- } else {
- if (bPseudoTest) {
-#ifdef HAL_EFUSE_MEMORY
- startAddr = (u16)pEfuseHal->fakeBTEfuseUsedBytes;
-#else
- startAddr = (u16)fakeBTEfuseUsedBytes;
-#endif
- } else
- rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&startAddr);
- }
- startAddr %= efuse_max;
-
- while (1) {
- if (startAddr >= efuse_max_available_len) {
- bRet = false;
- break;
- }
-
- if (efuse_OneByteRead(padapter, startAddr, &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) {
-#if 1
- bRet = false;
- break;
-#else
- if (EXT_HEADER(efuse_data)) {
- cur_header = efuse_data;
- startAddr++;
- efuse_OneByteRead(padapter, startAddr, &efuse_data, bPseudoTest);
- if (ALL_WORDS_DISABLED(efuse_data)) {
- bRet = false;
- break;
- } else {
- curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
- curPkt.word_en = efuse_data & 0x0F;
- }
- } else {
- cur_header = efuse_data;
- curPkt.offset = (cur_header>>4) & 0x0F;
- curPkt.word_en = cur_header & 0x0F;
- }
-
- curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
- /* if same header is found but no data followed */
- /* write some part of data followed by the header. */
- if (
- (curPkt.offset == pTargetPkt->offset) &&
- (hal_EfuseCheckIfDatafollowed(padapter, curPkt.word_cnts, startAddr+1, bPseudoTest) == false) &&
- wordEnMatched(pTargetPkt, &curPkt, &matched_wden) == true
- ) {
- /* Here to write partial data */
- badworden = Efuse_WordEnableDataWrite(padapter, startAddr+1, matched_wden, pTargetPkt->data, bPseudoTest);
- if (badworden != 0x0F) {
- u32 PgWriteSuccess = 0;
- /* if write fail on some words, write these bad words again */
- if (efuseType == EFUSE_WIFI)
- PgWriteSuccess = Efuse_PgPacketWrite(padapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
- else
- PgWriteSuccess = Efuse_PgPacketWrite_BT(padapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
-
- if (!PgWriteSuccess) {
- bRet = false; /* write fail, return */
- break;
- }
- }
- /* partial write ok, update the target packet for later use */
- for (i = 0; i < 4; i++) {
- if ((matched_wden & (0x1<<i)) == 0) { /* this word has been written */
- pTargetPkt->word_en |= (0x1<<i); /* disable the word */
- }
- }
- pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
- }
- /* read from next header */
- startAddr = startAddr + (curPkt.word_cnts*2) + 1;
-#endif
- } else {
- /* not used header, 0xff */
- *pAddr = startAddr;
- bRet = true;
- break;
- }
- }
-
- return bRet;
-}
-
-static u8 hal_EfusePgPacketWrite1ByteHeader(
- struct adapter *padapter,
- u8 efuseType,
- u16 *pAddr,
- struct pgpkt_struct *pTargetPkt,
- u8 bPseudoTest
-)
-{
- u8 pg_header = 0, tmp_header = 0;
- u16 efuse_addr = *pAddr;
- u8 repeatcnt = 0;
-
- pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
-
- do {
- efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest);
- efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest);
- if (tmp_header != 0xFF)
- break;
- if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
- return false;
-
- } while (1);
-
- if (tmp_header != pg_header)
- return false;
-
- *pAddr = efuse_addr;
-
- return true;
-}
-
-static u8 hal_EfusePgPacketWrite2ByteHeader(
- struct adapter *padapter,
- u8 efuseType,
- u16 *pAddr,
- struct pgpkt_struct *pTargetPkt,
- u8 bPseudoTest
-)
-{
- u16 efuse_addr, efuse_max_available_len = 0;
- u8 pg_header = 0, tmp_header = 0;
- u8 repeatcnt = 0;
-
- EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, &efuse_max_available_len, bPseudoTest);
-
- efuse_addr = *pAddr;
- if (efuse_addr >= efuse_max_available_len)
- return false;
-
- pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
-
- do {
- efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest);
- efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest);
- if (tmp_header != 0xFF)
- break;
- if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
- return false;
-
- } while (1);
-
- if (tmp_header != pg_header)
- return false;
-
- /* to write ext_header */
- efuse_addr++;
- pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
-
- do {
- efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest);
- efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest);
- if (tmp_header != 0xFF)
- break;
- if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
- return false;
-
- } while (1);
-
- if (tmp_header != pg_header) /* offset PG fail */
- return false;
-
- *pAddr = efuse_addr;
-
- return true;
-}
-
-static u8 hal_EfusePgPacketWriteHeader(
- struct adapter *padapter,
- u8 efuseType,
- u16 *pAddr,
- struct pgpkt_struct *pTargetPkt,
- u8 bPseudoTest
-)
-{
- u8 bRet = false;
-
- if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
- bRet = hal_EfusePgPacketWrite2ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
- else
- bRet = hal_EfusePgPacketWrite1ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
-
- return bRet;
-}
-
-static u8 hal_EfusePgPacketWriteData(
- struct adapter *padapter,
- u8 efuseType,
- u16 *pAddr,
- struct pgpkt_struct *pTargetPkt,
- u8 bPseudoTest
-)
-{
- u16 efuse_addr;
- u8 badworden;
-
-
- efuse_addr = *pAddr;
- badworden = Efuse_WordEnableDataWrite(padapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data, bPseudoTest);
- if (badworden != 0x0F)
- return false;
-
- return true;
-}
-
-static s32 Hal_EfusePgPacketWrite(
- struct adapter *padapter,
- u8 offset,
- u8 word_en,
- u8 *pData,
- bool bPseudoTest
-)
-{
- struct pgpkt_struct targetPkt;
- u16 startAddr = 0;
- u8 efuseType = EFUSE_WIFI;
-
- if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType, bPseudoTest))
- return false;
-
- hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
-
- if (!hal_EfusePartialWriteCheck(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
- return false;
-
- if (!hal_EfusePgPacketWriteHeader(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
- return false;
-
- if (!hal_EfusePgPacketWriteData(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
- return false;
-
- return true;
-}
-
-static bool Hal_EfusePgPacketWrite_BT(
- struct adapter *padapter,
- u8 offset,
- u8 word_en,
- u8 *pData,
- bool bPseudoTest
-)
-{
- struct pgpkt_struct targetPkt;
- u16 startAddr = 0;
- u8 efuseType = EFUSE_BT;
-
- if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType, bPseudoTest))
- return false;
-
- hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
-
- if (!hal_EfusePartialWriteCheck(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
- return false;
-
- if (!hal_EfusePgPacketWriteHeader(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
- return false;
-
- if (!hal_EfusePgPacketWriteData(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
- return false;
-
- return true;
-}
-
static struct hal_version ReadChipVersion8723B(struct adapter *padapter)
{
u32 value32;
@@ -1645,15 +1179,15 @@ static struct hal_version ReadChipVersion8723B(struct adapter *padapter)
pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0);
pHalData->MultiFunc |= ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0);
pHalData->PolarityCtl = ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT : RT_POLARITY_LOW_ACT);
-#if 1
+
dump_chip_info(ChipVersion);
-#endif
+
pHalData->VersionID = ChipVersion;
return ChipVersion;
}
-static void rtl8723b_read_chip_version(struct adapter *padapter)
+void rtl8723b_read_chip_version(struct adapter *padapter)
{
ReadChipVersion8723B(padapter);
}
@@ -1747,7 +1281,7 @@ static void _BeaconFunctionEnable(struct adapter *padapter, u8 Enable, u8 Linked
rtw_write8(padapter, REG_RD_CTRL+1, 0x6F);
}
-static void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter)
+void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter)
{
u8 val8;
u32 value32;
@@ -1808,16 +1342,6 @@ static void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter)
rtw_write8(padapter, bcn_ctrl_reg, val8);
}
-static void rtl8723b_GetHalODMVar(
- struct adapter *Adapter,
- enum hal_odm_variable eVariable,
- void *pValue1,
- void *pValue2
-)
-{
- GetHalODMVar(Adapter, eVariable, pValue1, pValue2);
-}
-
static void rtl8723b_SetHalODMVar(
struct adapter *Adapter,
enum hal_odm_variable eVariable,
@@ -1836,7 +1360,7 @@ static void hal_notch_filter_8723b(struct adapter *adapter, bool enable)
rtw_write8(adapter, rOFDM0_RxDSP+1, rtw_read8(adapter, rOFDM0_RxDSP+1) & ~BIT1);
}
-static void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level)
+void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level)
{
u32 mask, rate_bitmap;
u8 shortGIrate = false;
@@ -1876,49 +1400,9 @@ static void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_l
void rtl8723b_set_hal_ops(struct hal_ops *pHalFunc)
{
- pHalFunc->free_hal_data = &rtl8723b_free_hal_data;
-
- pHalFunc->dm_init = &rtl8723b_init_dm_priv;
-
- pHalFunc->read_chip_version = &rtl8723b_read_chip_version;
-
- pHalFunc->UpdateRAMaskHandler = &UpdateHalRAMask8723B;
-
- pHalFunc->set_bwmode_handler = &PHY_SetBWMode8723B;
- pHalFunc->set_channel_handler = &PHY_SwChnl8723B;
- pHalFunc->set_chnl_bw_handler = &PHY_SetSwChnlBWMode8723B;
-
- pHalFunc->set_tx_power_level_handler = &PHY_SetTxPowerLevel8723B;
- pHalFunc->get_tx_power_level_handler = &PHY_GetTxPowerLevel8723B;
-
- pHalFunc->hal_dm_watchdog = &rtl8723b_HalDmWatchDog;
- pHalFunc->hal_dm_watchdog_in_lps = &rtl8723b_HalDmWatchDog_in_LPS;
-
-
- pHalFunc->SetBeaconRelatedRegistersHandler = &rtl8723b_SetBeaconRelatedRegisters;
-
- pHalFunc->Add_RateATid = &rtl8723b_Add_RateATid;
-
- pHalFunc->run_thread = &rtl8723b_start_thread;
- pHalFunc->cancel_thread = &rtl8723b_stop_thread;
-
- pHalFunc->read_bbreg = &PHY_QueryBBReg_8723B;
- pHalFunc->write_bbreg = &PHY_SetBBReg_8723B;
- pHalFunc->read_rfreg = &PHY_QueryRFReg_8723B;
- pHalFunc->write_rfreg = &PHY_SetRFReg_8723B;
-
/* Efuse related function */
- pHalFunc->BTEfusePowerSwitch = &Hal_BT_EfusePowerSwitch;
- pHalFunc->EfusePowerSwitch = &Hal_EfusePowerSwitch;
- pHalFunc->ReadEFuse = &Hal_ReadEFuse;
- pHalFunc->EFUSEGetEfuseDefinition = &Hal_GetEfuseDefinition;
- pHalFunc->EfuseGetCurrentSize = &Hal_EfuseGetCurrentSize;
- pHalFunc->Efuse_PgPacketRead = &Hal_EfusePgPacketRead;
- pHalFunc->Efuse_PgPacketWrite = &Hal_EfusePgPacketWrite;
pHalFunc->Efuse_WordEnableDataWrite = &Hal_EfuseWordEnableDataWrite;
- pHalFunc->Efuse_PgPacketWrite_BT = &Hal_EfusePgPacketWrite_BT;
- pHalFunc->GetHalODMVarHandler = &rtl8723b_GetHalODMVar;
pHalFunc->SetHalODMVarHandler = &rtl8723b_SetHalODMVar;
pHalFunc->xmit_thread_handler = &hal_xmit_handler;
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
index 4ff092b7c9c9..d8709d40cb33 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
@@ -575,10 +575,6 @@ void PHY_SetTxPowerLevel8723B(struct adapter *Adapter, u8 Channel)
PHY_SetTxPowerLevelByPath(Adapter, Channel, RFPath);
}
-void PHY_GetTxPowerLevel8723B(struct adapter *Adapter, s32 *powerlevel)
-{
-}
-
static void phy_SetRegBW_8723B(
struct adapter *Adapter, enum channel_width CurrentBW
)
@@ -764,17 +760,6 @@ static void PHY_HandleSwChnlAndSetBW8723B(
}
}
-void PHY_SetBWMode8723B(
- struct adapter *Adapter,
- enum channel_width Bandwidth, /* 20M or 40M */
- unsigned char Offset /* Upper, Lower, or Don't care */
-)
-{
- struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
-
- PHY_HandleSwChnlAndSetBW8723B(Adapter, false, true, pHalData->CurrentChannel, Bandwidth, Offset, Offset, pHalData->CurrentChannel);
-}
-
/* Call after initialization */
void PHY_SwChnl8723B(struct adapter *Adapter, u8 channel)
{
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
index 78298e63edce..5dc1c12fe03e 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
@@ -411,14 +411,12 @@ int rtl8723bs_xmit_thread(void *context)
s32 ret;
struct adapter *padapter;
struct xmit_priv *pxmitpriv;
- u8 thread_name[20];
ret = _SUCCESS;
padapter = context;
pxmitpriv = &padapter->xmitpriv;
- rtw_sprintf(thread_name, 20, "RTWHALXT-%s", ADPT_ARG(padapter));
- thread_enter(thread_name);
+ allow_signal(SIGTERM);
do {
ret = rtl8723bs_xmit_handler(padapter);
diff --git a/drivers/staging/rtl8723bs/hal/sdio_halinit.c b/drivers/staging/rtl8723bs/hal/sdio_halinit.c
index d3aae413fc0f..af9a2b068796 100644
--- a/drivers/staging/rtl8723bs/hal/sdio_halinit.c
+++ b/drivers/staging/rtl8723bs/hal/sdio_halinit.c
@@ -583,7 +583,7 @@ static bool HalDetectPwrDownMode(struct adapter *Adapter)
return pHalData->pwrdown;
} /* HalDetectPwrDownMode */
-static u32 rtl8723bs_hal_init(struct adapter *padapter)
+u32 rtl8723bs_hal_init(struct adapter *padapter)
{
s32 ret;
struct hal_com_data *pHalData;
@@ -884,7 +884,7 @@ static void CardDisableRTL8723BSdio(struct adapter *padapter)
HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, rtl8723B_card_disable_flow);
}
-static u32 rtl8723bs_hal_deinit(struct adapter *padapter)
+u32 rtl8723bs_hal_deinit(struct adapter *padapter)
{
struct dvobj_priv *psdpriv = padapter->dvobj;
struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
@@ -937,17 +937,7 @@ static u32 rtl8723bs_hal_deinit(struct adapter *padapter)
return _SUCCESS;
}
-static u32 rtl8723bs_inirp_init(struct adapter *padapter)
-{
- return _SUCCESS;
-}
-
-static u32 rtl8723bs_inirp_deinit(struct adapter *padapter)
-{
- return _SUCCESS;
-}
-
-static void rtl8723bs_init_default_value(struct adapter *padapter)
+void rtl8723bs_init_default_value(struct adapter *padapter)
{
struct hal_com_data *pHalData;
@@ -960,7 +950,7 @@ static void rtl8723bs_init_default_value(struct adapter *padapter)
pHalData->SdioRxFIFOCnt = 0;
}
-static void rtl8723bs_interface_configure(struct adapter *padapter)
+void rtl8723bs_interface_configure(struct adapter *padapter)
{
struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
@@ -1142,7 +1132,7 @@ static s32 _ReadAdapterInfo8723BS(struct adapter *padapter)
return _SUCCESS;
}
-static void ReadAdapterInfo8723BS(struct adapter *padapter)
+void ReadAdapterInfo8723BS(struct adapter *padapter)
{
/* Read EEPROM size before call any EEPROM function */
padapter->EepromAddressSize = GetEEPROMSize8723B(padapter);
@@ -1154,7 +1144,7 @@ static void ReadAdapterInfo8723BS(struct adapter *padapter)
* If variable not handled here,
* some variables will be processed in SetHwReg8723B()
*/
-static void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
+void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
{
u8 val8;
@@ -1195,7 +1185,7 @@ static void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
* If variable not handled here,
* some variables will be processed in GetHwReg8723B()
*/
-static void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
+void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
{
switch (variable) {
case HW_VAR_CPWM:
@@ -1214,7 +1204,7 @@ static void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
}
}
-static void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf, int len)
+void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf, int len)
{
switch (variable) {
case HW_VAR_C2H_HANDLE:
@@ -1229,7 +1219,7 @@ static void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf
/* Description: */
/* Query setting of specified variable. */
/* */
-static u8 GetHalDefVar8723BSDIO(
+u8 GetHalDefVar8723BSDIO(
struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue
)
{
@@ -1257,8 +1247,7 @@ static u8 GetHalDefVar8723BSDIO(
/* Description: */
/* Change default setting of specified variable. */
/* */
-static u8 SetHalDefVar8723BSDIO(struct adapter *Adapter,
- enum hal_def_variable eVariable, void *pValue)
+u8 SetHalDefVar8723BSDIO(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue)
{
return SetHalDefVar8723B(Adapter, eVariable, pValue);
}
@@ -1269,32 +1258,4 @@ void rtl8723bs_set_hal_ops(struct adapter *padapter)
rtl8723b_set_hal_ops(pHalFunc);
- pHalFunc->hal_init = &rtl8723bs_hal_init;
- pHalFunc->hal_deinit = &rtl8723bs_hal_deinit;
-
- pHalFunc->inirp_init = &rtl8723bs_inirp_init;
- pHalFunc->inirp_deinit = &rtl8723bs_inirp_deinit;
-
- pHalFunc->init_xmit_priv = &rtl8723bs_init_xmit_priv;
- pHalFunc->free_xmit_priv = &rtl8723bs_free_xmit_priv;
-
- pHalFunc->init_recv_priv = &rtl8723bs_init_recv_priv;
- pHalFunc->free_recv_priv = &rtl8723bs_free_recv_priv;
-
- pHalFunc->init_default_value = &rtl8723bs_init_default_value;
- pHalFunc->intf_chip_configure = &rtl8723bs_interface_configure;
- pHalFunc->read_adapter_info = &ReadAdapterInfo8723BS;
-
- pHalFunc->enable_interrupt = &EnableInterrupt8723BSdio;
- pHalFunc->disable_interrupt = &DisableInterrupt8723BSdio;
- pHalFunc->check_ips_status = &CheckIPSStatus;
- pHalFunc->SetHwRegHandler = &SetHwReg8723BS;
- pHalFunc->GetHwRegHandler = &GetHwReg8723BS;
- pHalFunc->SetHwRegHandlerWithBuf = &SetHwRegWithBuf8723B;
- pHalFunc->GetHalDefVarHandler = &GetHalDefVar8723BSDIO;
- pHalFunc->SetHalDefVarHandler = &SetHalDefVar8723BSDIO;
-
- pHalFunc->hal_xmit = &rtl8723bs_hal_xmit;
- pHalFunc->mgnt_xmit = &rtl8723bs_mgnt_xmit;
- pHalFunc->hal_xmitframe_enqueue = &rtl8723bs_hal_xmitframe_enqueue;
}
diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h
index 0b35c97843cc..7b0e824e05a9 100644
--- a/drivers/staging/rtl8723bs/include/drv_types.h
+++ b/drivers/staging/rtl8723bs/include/drv_types.h
@@ -182,8 +182,6 @@ struct registry_priv {
#include <drv_types_sdio.h>
-#define is_primary_adapter(adapter) (1)
-#define get_iface_type(adapter) (IFACE_PORT0)
#define GET_PRIMARY_ADAPTER(padapter) (((struct adapter *)padapter)->dvobj->if1)
#define GET_IFACE_NUMS(padapter) (((struct adapter *)padapter)->dvobj->iface_nums)
#define GET_ADAPTER(padapter, iface_id) (((struct adapter *)padapter)->dvobj->padapters[iface_id])
@@ -320,14 +318,6 @@ static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj)
return &dvobj->intf_data.func->dev;
}
-struct adapter *dvobj_get_port0_adapter(struct dvobj_priv *dvobj);
-
-enum {
- IFACE_PORT0, /* mapping to port0 for C/D series chips */
- IFACE_PORT1, /* mapping to port1 for C/D series chip */
- MAX_IFACE_PORT,
-};
-
enum {
DRIVER_NORMAL = 0,
DRIVER_DISAPPEAR = 1,
diff --git a/drivers/staging/rtl8723bs/include/hal_com.h b/drivers/staging/rtl8723bs/include/hal_com.h
index 17d5cfb66a36..4db93484725f 100644
--- a/drivers/staging/rtl8723bs/include/hal_com.h
+++ b/drivers/staging/rtl8723bs/include/hal_com.h
@@ -158,10 +158,6 @@ void rtw_dump_raw_rssi_info(struct adapter *padapter);
void rtw_bb_rf_gain_offset(struct adapter *padapter);
-void GetHalODMVar(struct adapter *Adapter,
- enum hal_odm_variable eVariable,
- void *pValue1,
- void *pValue2);
void SetHalODMVar(
struct adapter *Adapter,
enum hal_odm_variable eVariable,
diff --git a/drivers/staging/rtl8723bs/include/hal_intf.h b/drivers/staging/rtl8723bs/include/hal_intf.h
index efdd1f912b5d..282e141616b0 100644
--- a/drivers/staging/rtl8723bs/include/hal_intf.h
+++ b/drivers/staging/rtl8723bs/include/hal_intf.h
@@ -162,91 +162,9 @@ enum hal_intf_ps_func {
typedef s32 (*c2h_id_filter)(u8 *c2h_evt);
struct hal_ops {
- u32 (*hal_power_on)(struct adapter *padapter);
- void (*hal_power_off)(struct adapter *padapter);
- u32 (*hal_init)(struct adapter *padapter);
- u32 (*hal_deinit)(struct adapter *padapter);
-
- void (*free_hal_data)(struct adapter *padapter);
-
- u32 (*inirp_init)(struct adapter *padapter);
- u32 (*inirp_deinit)(struct adapter *padapter);
- void (*irp_reset)(struct adapter *padapter);
-
- s32 (*init_xmit_priv)(struct adapter *padapter);
- void (*free_xmit_priv)(struct adapter *padapter);
-
- s32 (*init_recv_priv)(struct adapter *padapter);
- void (*free_recv_priv)(struct adapter *padapter);
-
- void (*dm_init)(struct adapter *padapter);
- void (*dm_deinit)(struct adapter *padapter);
- void (*read_chip_version)(struct adapter *padapter);
-
- void (*init_default_value)(struct adapter *padapter);
-
- void (*intf_chip_configure)(struct adapter *padapter);
-
- void (*read_adapter_info)(struct adapter *padapter);
-
- void (*enable_interrupt)(struct adapter *padapter);
- void (*disable_interrupt)(struct adapter *padapter);
- u8 (*check_ips_status)(struct adapter *padapter);
- s32 (*interrupt_handler)(struct adapter *padapter);
- void (*clear_interrupt)(struct adapter *padapter);
- void (*set_bwmode_handler)(struct adapter *padapter, enum channel_width Bandwidth, u8 Offset);
- void (*set_channel_handler)(struct adapter *padapter, u8 channel);
- void (*set_chnl_bw_handler)(struct adapter *padapter, u8 channel, enum channel_width Bandwidth, u8 Offset40, u8 Offset80);
-
- void (*set_tx_power_level_handler)(struct adapter *padapter, u8 channel);
- void (*get_tx_power_level_handler)(struct adapter *padapter, s32 *powerlevel);
-
- void (*hal_dm_watchdog)(struct adapter *padapter);
- void (*hal_dm_watchdog_in_lps)(struct adapter *padapter);
-
-
- void (*SetHwRegHandler)(struct adapter *padapter, u8 variable, u8 *val);
- void (*GetHwRegHandler)(struct adapter *padapter, u8 variable, u8 *val);
-
- void (*SetHwRegHandlerWithBuf)(struct adapter *padapter, u8 variable, u8 *pbuf, int len);
-
- u8 (*GetHalDefVarHandler)(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue);
- u8 (*SetHalDefVarHandler)(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue);
-
- void (*GetHalODMVarHandler)(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, void *pValue2);
void (*SetHalODMVarHandler)(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet);
- void (*UpdateRAMaskHandler)(struct adapter *padapter, u32 mac_id, u8 rssi_level);
- void (*SetBeaconRelatedRegistersHandler)(struct adapter *padapter);
-
- void (*Add_RateATid)(struct adapter *padapter, u32 bitmap, u8 *arg, u8 rssi_level);
-
- void (*run_thread)(struct adapter *padapter);
- void (*cancel_thread)(struct adapter *padapter);
-
- u8 (*interface_ps_func)(struct adapter *padapter, enum hal_intf_ps_func efunc_id, u8 *val);
-
- s32 (*hal_xmit)(struct adapter *padapter, struct xmit_frame *pxmitframe);
- /*
- * mgnt_xmit should be implemented to run in interrupt context
- */
- s32 (*mgnt_xmit)(struct adapter *padapter, struct xmit_frame *pmgntframe);
- s32 (*hal_xmitframe_enqueue)(struct adapter *padapter, struct xmit_frame *pxmitframe);
-
- u32 (*read_bbreg)(struct adapter *padapter, u32 RegAddr, u32 BitMask);
- void (*write_bbreg)(struct adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data);
- u32 (*read_rfreg)(struct adapter *padapter, u8 eRFPath, u32 RegAddr, u32 BitMask);
- void (*write_rfreg)(struct adapter *padapter, u8 eRFPath, u32 RegAddr, u32 BitMask, u32 Data);
-
- void (*EfusePowerSwitch)(struct adapter *padapter, u8 bWrite, u8 PwrState);
- void (*BTEfusePowerSwitch)(struct adapter *padapter, u8 bWrite, u8 PwrState);
- void (*ReadEFuse)(struct adapter *padapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool bPseudoTest);
- void (*EFUSEGetEfuseDefinition)(struct adapter *padapter, u8 efuseType, u8 type, void *pOut, bool bPseudoTest);
- u16 (*EfuseGetCurrentSize)(struct adapter *padapter, u8 efuseType, bool bPseudoTest);
- int (*Efuse_PgPacketRead)(struct adapter *padapter, u8 offset, u8 *data, bool bPseudoTest);
- int (*Efuse_PgPacketWrite)(struct adapter *padapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest);
u8 (*Efuse_WordEnableDataWrite)(struct adapter *padapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest);
- bool (*Efuse_PgPacketWrite_BT)(struct adapter *padapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest);
s32 (*xmit_thread_handler)(struct adapter *padapter);
void (*hal_notch_filter)(struct adapter *adapter, bool enable);
@@ -357,4 +275,17 @@ s32 rtw_hal_macid_wakeup(struct adapter *padapter, u32 macid);
s32 rtw_hal_fill_h2c_cmd(struct adapter *, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer);
+void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val);
+void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val);
+void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf, int len);
+u8 GetHalDefVar8723BSDIO(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue);
+u8 SetHalDefVar8723BSDIO(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue);
+void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level);
+void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter);
+void Hal_EfusePowerSwitch(struct adapter *padapter, u8 bWrite, u8 PwrState);
+void Hal_ReadEFuse(struct adapter *padapter, u8 efuseType, u16 _offset,
+ u16 _size_byte, u8 *pbuf, bool bPseudoTest);
+void Hal_GetEfuseDefinition(struct adapter *padapter, u8 efuseType, u8 type,
+ void *pOut, bool bPseudoTest);
+u16 Hal_EfuseGetCurrentSize(struct adapter *padapter, u8 efuseType, bool bPseudoTest);
#endif /* __HAL_INTF_H__ */
diff --git a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h
index ea494bcf830b..07bf0a8d019a 100644
--- a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h
+++ b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h
@@ -49,13 +49,8 @@ void PHY_SetTxPowerIndex(struct adapter *Adapter, u32 PowerIndex,
u8 PHY_GetTxPowerIndex(struct adapter *padapter, u8 RFPath, u8 Rate,
enum channel_width BandWidth, u8 Channel);
-void PHY_GetTxPowerLevel8723B(struct adapter *Adapter, s32 *powerlevel);
-
void PHY_SetTxPowerLevel8723B(struct adapter *Adapter, u8 channel);
-void PHY_SetBWMode8723B(struct adapter *Adapter, enum channel_width Bandwidth,
- unsigned char Offset);
-
/* Call after initialization */
void PHY_SwChnl8723B(struct adapter *Adapter, u8 channel);
diff --git a/drivers/staging/rtl8723bs/include/osdep_intf.h b/drivers/staging/rtl8723bs/include/osdep_intf.h
index 111e0179712a..215ece612f71 100644
--- a/drivers/staging/rtl8723bs/include/osdep_intf.h
+++ b/drivers/staging/rtl8723bs/include/osdep_intf.h
@@ -55,9 +55,6 @@ void rtw_unregister_netdevs(struct dvobj_priv *dvobj);
u16 rtw_recv_select_queue(struct sk_buff *skb);
-int rtw_ndev_notifier_register(void);
-void rtw_ndev_notifier_unregister(void);
-
void rtw_ips_dev_unload(struct adapter *padapter);
int rtw_ips_pwr_up(struct adapter *padapter);
diff --git a/drivers/staging/rtl8723bs/include/osdep_service.h b/drivers/staging/rtl8723bs/include/osdep_service.h
index b21267d7ef72..8b1634f4091e 100644
--- a/drivers/staging/rtl8723bs/include/osdep_service.h
+++ b/drivers/staging/rtl8723bs/include/osdep_service.h
@@ -73,11 +73,6 @@ int _rtw_netif_rx(struct net_device *ndev, struct sk_buff *skb);
extern void _rtw_init_queue(struct __queue *pqueue);
-static inline void thread_enter(char *name)
-{
- allow_signal(SIGTERM);
-}
-
static inline void flush_signals_thread(void)
{
if (signal_pending(current))
diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_recv.h b/drivers/staging/rtl8723bs/include/rtl8723b_recv.h
index a108ce89bce4..783f64de0aec 100644
--- a/drivers/staging/rtl8723bs/include/rtl8723b_recv.h
+++ b/drivers/staging/rtl8723bs/include/rtl8723b_recv.h
@@ -87,4 +87,9 @@ void rtl8723bs_free_recv_priv(struct adapter *padapter);
void rtl8723b_query_rx_phy_status(union recv_frame *prframe, struct phy_stat *pphy_stat);
void rtl8723b_process_phy_info(struct adapter *padapter, void *prframe);
+void rtl8723b_read_chip_version(struct adapter *padapter);
+void rtl8723bs_init_default_value(struct adapter *padapter);
+void rtl8723bs_interface_configure(struct adapter *padapter);
+void ReadAdapterInfo8723BS(struct adapter *padapter);
+
#endif
diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h b/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h
index ad2542d0cabe..ac4ca7e05b9b 100644
--- a/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h
+++ b/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h
@@ -405,6 +405,8 @@ struct txdesc_8723b {
void rtl8723b_update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem);
void rtl8723b_fill_fake_txdesc(struct adapter *padapter, u8 *pDesc, u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull, u8 bDataFrame);
+u32 rtl8723bs_hal_init(struct adapter *padapter);
+u32 rtl8723bs_hal_deinit(struct adapter *padapter);
s32 rtl8723bs_init_xmit_priv(struct adapter *padapter);
void rtl8723bs_free_xmit_priv(struct adapter *padapter);
s32 rtl8723bs_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe);
diff --git a/drivers/staging/rtl8723bs/include/rtw_efuse.h b/drivers/staging/rtl8723bs/include/rtw_efuse.h
index 0cb8c6f6d34d..d6ea8a4a856f 100644
--- a/drivers/staging/rtl8723bs/include/rtw_efuse.h
+++ b/drivers/staging/rtl8723bs/include/rtw_efuse.h
@@ -90,16 +90,12 @@ extern u8 fakeBTEfuseInitMap[];
extern u8 fakeBTEfuseModifiedMap[];
/*------------------------Export global variable----------------------------*/
-u16 Efuse_GetCurrentSize(struct adapter *padapter, u8 efuseType, bool bPseudoTest);
u8 Efuse_CalculateWordCnts(u8 word_en);
void EFUSE_GetEfuseDefinition(struct adapter *padapter, u8 efuseType, u8 type, void *pOut, bool bPseudoTest);
u8 efuse_OneByteRead(struct adapter *padapter, u16 addr, u8 *data, bool bPseudoTest);
u8 efuse_OneByteWrite(struct adapter *padapter, u16 addr, u8 data, bool bPseudoTest);
void Efuse_PowerSwitch(struct adapter *padapter, u8 bWrite, u8 PwrState);
-int Efuse_PgPacketRead(struct adapter *padapter, u8 offset, u8 *data, bool bPseudoTest);
-int Efuse_PgPacketWrite(struct adapter *padapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest);
-void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata);
u8 Efuse_WordEnableDataWrite(struct adapter *padapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest);
u8 EFUSE_Read1Byte(struct adapter *padapter, u16 Address);
diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h
index 8315399b64fd..2080408743ef 100644
--- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h
+++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h
@@ -447,9 +447,7 @@ void Set_MSR(struct adapter *padapter, u8 type);
u8 rtw_get_oper_ch(struct adapter *adapter);
void rtw_set_oper_ch(struct adapter *adapter, u8 ch);
-u8 rtw_get_oper_bw(struct adapter *adapter);
void rtw_set_oper_bw(struct adapter *adapter, u8 bw);
-u8 rtw_get_oper_choffset(struct adapter *adapter);
void rtw_set_oper_choffset(struct adapter *adapter, u8 offset);
u8 rtw_get_center_ch(u8 channel, u8 chnl_bw, u8 chnl_offset);
unsigned long rtw_get_on_cur_ch_time(struct adapter *adapter);
@@ -459,8 +457,6 @@ void r8723bs_select_channel(struct adapter *padapter, unsigned char channel);
unsigned int decide_wait_for_beacon_timeout(unsigned int bcn_interval);
-void read_cam(struct adapter *padapter, u8 entry, u8 *get_key);
-
/* modify HW only */
void _write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key);
void _clear_cam_entry(struct adapter *padapter, u8 entry);
@@ -528,7 +524,6 @@ void rtw_camid_free(struct adapter *adapter, u8 cam_id);
extern void rtw_alloc_macid(struct adapter *padapter, struct sta_info *psta);
extern void rtw_release_macid(struct adapter *padapter, struct sta_info *psta);
-extern u8 rtw_search_max_mac_id(struct adapter *padapter);
void report_join_res(struct adapter *padapter, int res);
void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame);
diff --git a/drivers/staging/rtl8723bs/include/rtw_mp.h b/drivers/staging/rtl8723bs/include/rtw_mp.h
index f94bb18479da..5a1cbd2ed851 100644
--- a/drivers/staging/rtl8723bs/include/rtw_mp.h
+++ b/drivers/staging/rtl8723bs/include/rtw_mp.h
@@ -276,10 +276,6 @@ void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u3
u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz);
void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz);
-u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask);
-void write_bbreg(struct adapter *padapter, u32 addr, u32 bitmask, u32 val);
-u32 read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr);
-void write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 val);
void SetChannel(struct adapter *padapter);
void SetBandwidth(struct adapter *padapter);
diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
index b63a74e669bc..c053ee9c1361 100644
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
@@ -581,7 +581,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
- /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
/* set mic key */
memcpy(txkey, &(param->u.crypt.key[16]), 8);
memcpy(rxkey, &(param->u.crypt.key[24]), 8);
@@ -626,7 +625,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
psta->dot118021XPrivacy = _TKIP_;
- /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
/* set mic key */
memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
@@ -657,7 +655,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
- /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
/* set mic key */
memcpy(txkey, &(param->u.crypt.key[16]), 8);
memcpy(rxkey, &(param->u.crypt.key[24]), 8);
@@ -785,7 +782,6 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
- /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
@@ -806,10 +802,6 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
} else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
/* save the IGTK key, length 16 bytes */
memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
- /*
- for (no = 0;no<16;no++)
- printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
- */
padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
padapter->securitypriv.binstallBIPkey = true;
}
@@ -817,9 +809,7 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
}
pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
- if (!pbcmc_sta) {
- /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
- } else {
+ if (pbcmc_sta) {
/* Jeff: don't disable ieee8021x_blocked while clearing key */
if (strcmp(param->u.crypt.alg, "none") != 0)
pbcmc_sta->ieee8021x_blocked = false;
diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
index a9e481e182ad..793b051536f3 100644
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
@@ -138,9 +138,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) { /* sta mode */
psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
- if (!psta) {
- /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
- } else {
+ if (psta) {
/* Jeff: don't disable ieee8021x_blocked while clearing key */
if (strcmp(param->u.crypt.alg, "none") != 0)
psta->ieee8021x_blocked = false;
@@ -154,7 +152,6 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
- /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
memcpy(psta->dot11tkiptxmickey.skey, &param->u.crypt.key[16], 8);
memcpy(psta->dot11tkiprxmickey.skey, &param->u.crypt.key[24], 8);
@@ -177,13 +174,8 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, true);
} else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
- /* printk("BIP key_len =%d , index =%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */
/* save the IGTK key, length 16 bytes */
memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
- /*printk("IGTK key below:\n");
- for (no = 0;no<16;no++)
- printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
- printk("\n");*/
padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
padapter->securitypriv.binstallBIPkey = true;
}
@@ -191,9 +183,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
}
pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
- if (!pbcmc_sta) {
- /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
- } else {
+ if (pbcmc_sta) {
/* Jeff: don't disable ieee8021x_blocked while clearing key */
if (strcmp(param->u.crypt.alg, "none") != 0)
pbcmc_sta->ieee8021x_blocked = false;
@@ -629,7 +619,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
- /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
/* set mic key */
memcpy(txkey, &param->u.crypt.key[16], 8);
memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[24], 8);
@@ -674,7 +663,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
psta->dot118021XPrivacy = _TKIP_;
- /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
/* set mic key */
memcpy(psta->dot11tkiptxmickey.skey, &param->u.crypt.key[16], 8);
memcpy(psta->dot11tkiprxmickey.skey, &param->u.crypt.key[24], 8);
@@ -703,7 +691,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
- /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
/* set mic key */
memcpy(txkey, &param->u.crypt.key[16], 8);
memcpy(rxkey, &param->u.crypt.key[24], 8);
diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
index fc9b9c5efb50..4e1917c05402 100644
--- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
@@ -381,34 +381,6 @@ u16 rtw_recv_select_queue(struct sk_buff *skb)
return rtw_1d_to_queue[priority];
}
-static int rtw_ndev_notifier_call(struct notifier_block *nb, unsigned long state, void *ptr)
-{
- struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-
- if (dev->netdev_ops->ndo_do_ioctl != rtw_ioctl)
- return NOTIFY_DONE;
-
- netdev_dbg(dev, FUNC_NDEV_FMT " state:%lu\n", FUNC_NDEV_ARG(dev),
- state);
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block rtw_ndev_notifier = {
- .notifier_call = rtw_ndev_notifier_call,
-};
-
-int rtw_ndev_notifier_register(void)
-{
- return register_netdevice_notifier(&rtw_ndev_notifier);
-}
-
-void rtw_ndev_notifier_unregister(void)
-{
- unregister_netdevice_notifier(&rtw_ndev_notifier);
-}
-
-
static int rtw_ndev_init(struct net_device *dev)
{
struct adapter *adapter = rtw_netdev_priv(dev);
@@ -633,8 +605,7 @@ void rtw_reset_drv_sw(struct adapter *padapter)
struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
/* hal_priv */
- if (is_primary_adapter(padapter))
- rtw_hal_def_value_init(padapter);
+ rtw_hal_def_value_init(padapter);
RTW_ENABLE_FUNC(padapter, DF_RX_BIT);
RTW_ENABLE_FUNC(padapter, DF_TX_BIT);
diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c
index d18fde4e5d6c..5a7238e661ff 100644
--- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c
+++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c
@@ -72,7 +72,7 @@ static int sdio_alloc_irq(struct dvobj_priv *dvobj)
err = sdio_claim_irq(func, &sd_sync_int_hdl);
if (err) {
dvobj->drv_dbg.dbg_sdio_alloc_irq_error_cnt++;
- printk(KERN_CRIT "%s: sdio_claim_irq FAIL(%d)!\n", __func__, err);
+ netdev_crit(dvobj->if1->pnetdev, "%s: sdio_claim_irq FAIL(%d)!\n", __func__, err);
} else {
dvobj->drv_dbg.dbg_sdio_alloc_irq_cnt++;
dvobj->irq_alloc = 1;
@@ -382,7 +382,6 @@ static int rtw_drv_init(
if (sdio_alloc_irq(dvobj) != _SUCCESS)
goto free_if1;
- rtw_ndev_notifier_register();
status = _SUCCESS;
free_if1:
@@ -484,22 +483,12 @@ static int rtw_sdio_resume(struct device *dev)
static int __init rtw_drv_entry(void)
{
- int ret;
-
- ret = sdio_register_driver(&rtl8723bs_sdio_driver);
- if (ret != 0)
- rtw_ndev_notifier_unregister();
-
- return ret;
+ return sdio_register_driver(&rtl8723bs_sdio_driver);
}
+module_init(rtw_drv_entry);
static void __exit rtw_drv_halt(void)
{
sdio_unregister_driver(&rtl8723bs_sdio_driver);
-
- rtw_ndev_notifier_unregister();
}
-
-
-module_init(rtw_drv_entry);
module_exit(rtw_drv_halt);
diff --git a/drivers/staging/rts5208/Kconfig b/drivers/staging/rts5208/Kconfig
deleted file mode 100644
index b864023d3ccb..000000000000
--- a/drivers/staging/rts5208/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config RTS5208
- tristate "Realtek PCI-E Card Reader RTS5208/5288 support"
- depends on PCI && SCSI
- help
- Say Y here to include driver code to support the Realtek
- PCI-E card reader rts5208/rts5288.
-
- If this driver is compiled as a module, it will be named rts5208.
diff --git a/drivers/staging/rts5208/Makefile b/drivers/staging/rts5208/Makefile
deleted file mode 100644
index 3c9e9797d3d9..000000000000
--- a/drivers/staging/rts5208/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_RTS5208) := rts5208.o
-
-rts5208-y := rtsx.o rtsx_chip.o rtsx_transport.o rtsx_scsi.o \
- rtsx_card.o general.o sd.o xd.o ms.o spi.o
diff --git a/drivers/staging/rts5208/TODO b/drivers/staging/rts5208/TODO
deleted file mode 100644
index 9cec0d8dd0b6..000000000000
--- a/drivers/staging/rts5208/TODO
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO:
-- use kernel coding style
-- checkpatch.pl fixes
-- We will use the stack in drivers/mmc to implement
- rts5208/5288 in the future
-
-Micky Ching <micky_ching@realsil.com.cn>
diff --git a/drivers/staging/rts5208/general.c b/drivers/staging/rts5208/general.c
deleted file mode 100644
index 0f912b011064..000000000000
--- a/drivers/staging/rts5208/general.c
+++ /dev/null
@@ -1,25 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include "general.h"
-
-int bit1cnt_long(u32 data)
-{
- int i, cnt = 0;
-
- for (i = 0; i < 32; i++) {
- if (data & 0x01)
- cnt++;
- data >>= 1;
- }
- return cnt;
-}
-
diff --git a/drivers/staging/rts5208/general.h b/drivers/staging/rts5208/general.h
deleted file mode 100644
index 53e2dbabf04b..000000000000
--- a/drivers/staging/rts5208/general.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __RTSX_GENERAL_H
-#define __RTSX_GENERAL_H
-
-#include "rtsx.h"
-
-int bit1cnt_long(u32 data);
-
-#endif /* __RTSX_GENERAL_H */
diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c
deleted file mode 100644
index bfeb5873bf3b..000000000000
--- a/drivers/staging/rts5208/ms.c
+++ /dev/null
@@ -1,4311 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-
-#include "rtsx.h"
-#include "ms.h"
-
-static inline void ms_set_err_code(struct rtsx_chip *chip, u8 err_code)
-{
- struct ms_info *ms_card = &chip->ms_card;
-
- ms_card->err_code = err_code;
-}
-
-static inline int ms_check_err_code(struct rtsx_chip *chip, u8 err_code)
-{
- struct ms_info *ms_card = &chip->ms_card;
-
- return (ms_card->err_code == err_code);
-}
-
-static int ms_parse_err_code(struct rtsx_chip *chip)
-{
- return STATUS_FAIL;
-}
-
-static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode,
- u8 tpc, u8 cnt, u8 cfg)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- u8 *ptr;
-
- dev_dbg(rtsx_dev(chip), "%s: tpc = 0x%x\n", __func__, tpc);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER,
- 0xFF, MS_TRANSFER_START | trans_mode);
- rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
-
- rtsx_add_cmd(chip, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
-
- retval = rtsx_send_cmd(chip, MS_CARD, 5000);
- if (retval < 0) {
- rtsx_clear_ms_error(chip);
- ms_set_err_code(chip, MS_TO_ERROR);
- return ms_parse_err_code(chip);
- }
-
- ptr = rtsx_get_cmd_data(chip) + 1;
-
- if (!(tpc & 0x08)) { /* Read Packet */
- if (*ptr & MS_CRC16_ERR) {
- ms_set_err_code(chip, MS_CRC16_ERROR);
- return ms_parse_err_code(chip);
- }
- } else { /* Write Packet */
- if (CHK_MSPRO(ms_card) && !(*ptr & 0x80)) {
- if (*ptr & (MS_INT_ERR | MS_INT_CMDNK)) {
- ms_set_err_code(chip, MS_CMD_NK);
- return ms_parse_err_code(chip);
- }
- }
- }
-
- if (*ptr & MS_RDY_TIMEOUT) {
- rtsx_clear_ms_error(chip);
- ms_set_err_code(chip, MS_TO_ERROR);
- return ms_parse_err_code(chip);
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode,
- u8 tpc, u16 sec_cnt, u8 cfg, bool mode_2k,
- int use_sg, void *buf, int buf_len)
-{
- int retval;
- u8 val, err_code = 0;
- enum dma_data_direction dir;
-
- if (!buf || !buf_len)
- return STATUS_FAIL;
-
- if (trans_mode == MS_TM_AUTO_READ) {
- dir = DMA_FROM_DEVICE;
- err_code = MS_FLASH_READ_ERROR;
- } else if (trans_mode == MS_TM_AUTO_WRITE) {
- dir = DMA_TO_DEVICE;
- err_code = MS_FLASH_WRITE_ERROR;
- } else {
- return STATUS_FAIL;
- }
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- MS_SECTOR_CNT_H, 0xFF, (u8)(sec_cnt >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_L, 0xFF, (u8)sec_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
-
- if (mode_2k) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- MS_CFG, MS_2K_SECTOR_MODE, MS_2K_SECTOR_MODE);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_CFG, MS_2K_SECTOR_MODE, 0);
- }
-
- trans_dma_enable(dir, chip, sec_cnt * 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- MS_TRANSFER, 0xFF, MS_TRANSFER_START | trans_mode);
- rtsx_add_cmd(chip, CHECK_REG_CMD,
- MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data(chip, MS_CARD, buf, buf_len,
- use_sg, dir, chip->mspro_timeout);
- if (retval < 0) {
- ms_set_err_code(chip, err_code);
- if (retval == -ETIMEDOUT)
- retval = STATUS_TIMEDOUT;
- else
- retval = STATUS_FAIL;
-
- return retval;
- }
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
- if (retval)
- return retval;
-
- if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT))
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_write_bytes(struct rtsx_chip *chip,
- u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
-
- if (!data || data_len < cnt)
- return STATUS_ERROR;
-
- rtsx_init_cmd(chip);
-
- for (i = 0; i < cnt; i++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- PPBUF_BASE2 + i, 0xFF, data[i]);
- }
- if (cnt % 2)
- rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2 + i, 0xFF, 0xFF);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- MS_TRANSFER, 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES);
- rtsx_add_cmd(chip, CHECK_REG_CMD,
- MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, MS_CARD, 5000);
- if (retval < 0) {
- u8 val = 0;
-
- rtsx_read_register(chip, MS_TRANS_CFG, &val);
- dev_dbg(rtsx_dev(chip), "MS_TRANS_CFG: 0x%02x\n", val);
-
- rtsx_clear_ms_error(chip);
-
- if (!(tpc & 0x08)) {
- if (val & MS_CRC16_ERR) {
- ms_set_err_code(chip, MS_CRC16_ERROR);
- return ms_parse_err_code(chip);
- }
- } else {
- if (CHK_MSPRO(ms_card) && !(val & 0x80)) {
- if (val & (MS_INT_ERR | MS_INT_CMDNK)) {
- ms_set_err_code(chip, MS_CMD_NK);
- return ms_parse_err_code(chip);
- }
- }
- }
-
- if (val & MS_RDY_TIMEOUT) {
- ms_set_err_code(chip, MS_TO_ERROR);
- return ms_parse_err_code(chip);
- }
-
- ms_set_err_code(chip, MS_TO_ERROR);
- return ms_parse_err_code(chip);
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_read_bytes(struct rtsx_chip *chip,
- u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 *ptr;
-
- if (!data)
- return STATUS_ERROR;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
- MS_TRANSFER_START | MS_TM_READ_BYTES);
- rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
-
- for (i = 0; i < data_len - 1; i++)
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
-
- if (data_len % 2)
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, 0);
- else
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len - 1,
- 0, 0);
-
- retval = rtsx_send_cmd(chip, MS_CARD, 5000);
- if (retval < 0) {
- u8 val = 0;
-
- rtsx_read_register(chip, MS_TRANS_CFG, &val);
- rtsx_clear_ms_error(chip);
-
- if (!(tpc & 0x08)) {
- if (val & MS_CRC16_ERR) {
- ms_set_err_code(chip, MS_CRC16_ERROR);
- return ms_parse_err_code(chip);
- }
- } else {
- if (CHK_MSPRO(ms_card) && !(val & 0x80)) {
- if (val & (MS_INT_ERR | MS_INT_CMDNK)) {
- ms_set_err_code(chip, MS_CMD_NK);
- return ms_parse_err_code(chip);
- }
- }
- }
-
- if (val & MS_RDY_TIMEOUT) {
- ms_set_err_code(chip, MS_TO_ERROR);
- return ms_parse_err_code(chip);
- }
-
- ms_set_err_code(chip, MS_TO_ERROR);
- return ms_parse_err_code(chip);
- }
-
- ptr = rtsx_get_cmd_data(chip) + 1;
-
- for (i = 0; i < data_len; i++)
- data[i] = ptr[i];
-
- if (tpc == PRO_READ_SHORT_DATA && data_len == 8) {
- dev_dbg(rtsx_dev(chip), "Read format progress:\n");
- print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, ptr,
- cnt);
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_set_rw_reg_addr(struct rtsx_chip *chip, u8 read_start,
- u8 read_cnt, u8 write_start, u8 write_cnt)
-{
- int retval, i;
- u8 data[4];
-
- data[0] = read_start;
- data[1] = read_cnt;
- data[2] = write_start;
- data[3] = write_cnt;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, SET_RW_REG_ADRS, 4,
- NO_WAIT_INT, data, 4);
- if (retval == STATUS_SUCCESS)
- return STATUS_SUCCESS;
- rtsx_clear_ms_error(chip);
- }
-
- return STATUS_FAIL;
-}
-
-static int ms_send_cmd(struct rtsx_chip *chip, u8 cmd, u8 cfg)
-{
- u8 data[2];
-
- data[0] = cmd;
- data[1] = 0;
-
- return ms_write_bytes(chip, PRO_SET_CMD, 1, cfg, data, 1);
-}
-
-static int ms_set_init_para(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-
- if (CHK_HG8BIT(ms_card)) {
- if (chip->asic_code)
- ms_card->ms_clock = chip->asic_ms_hg_clk;
- else
- ms_card->ms_clock = chip->fpga_ms_hg_clk;
-
- } else if (CHK_MSPRO(ms_card) || CHK_MS4BIT(ms_card)) {
- if (chip->asic_code)
- ms_card->ms_clock = chip->asic_ms_4bit_clk;
- else
- ms_card->ms_clock = chip->fpga_ms_4bit_clk;
-
- } else {
- if (chip->asic_code)
- ms_card->ms_clock = chip->asic_ms_1bit_clk;
- else
- ms_card->ms_clock = chip->fpga_ms_1bit_clk;
- }
-
- retval = switch_clock(chip, ms_card->ms_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = select_card(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_switch_clock(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-
- retval = select_card(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = switch_clock(chip, ms_card->ms_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_pull_ctl_disable(struct rtsx_chip *chip)
-{
- int retval;
-
- if (CHECK_PID(chip, 0x5208)) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF,
- MS_D1_PD | MS_D2_PD | MS_CLK_PD |
- MS_D6_PD);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF,
- MS_D3_PD | MS_D0_PD | MS_BS_PD |
- XD_D4_PD);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF,
- MS_D7_PD | XD_CE_PD | XD_CLE_PD |
- XD_CD_PU);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PD | SD_D3_PD | SD_D2_PD |
- XD_ALE_PD);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU | SD_WP_PD | SD_CD_PU |
- SD_CMD_PD);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- if (retval)
- return retval;
-
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL1,
- 0xFF, 0x55);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL2,
- 0xFF, 0x55);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL3,
- 0xFF, 0x4B);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL4,
- 0xFF, 0x69);
- if (retval)
- return retval;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_pull_ctl_enable(struct rtsx_chip *chip)
-{
- int retval;
-
- rtsx_init_cmd(chip);
-
- if (CHECK_PID(chip, 0x5208)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
- MS_D1_PD | MS_D2_PD | MS_CLK_NP | MS_D6_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
- MS_D3_PD | MS_D0_PD | MS_BS_NP | XD_D4_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
- MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- CARD_PULL_CTL1, 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- CARD_PULL_CTL2, 0xFF, 0x45);
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- CARD_PULL_CTL3, 0xFF, 0x4B);
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- CARD_PULL_CTL4, 0xFF, 0x29);
- }
- }
-
- retval = rtsx_send_cmd(chip, MS_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_prepare_reset(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- u8 oc_mask = 0;
-
- ms_card->ms_type = 0;
- ms_card->check_ms_flow = 0;
- ms_card->switch_8bit_fail = 0;
- ms_card->delay_write.delay_write_flag = 0;
-
- ms_card->pro_under_formatting = 0;
-
- retval = ms_power_off_card3v3(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!chip->ft2_fast_mode)
- wait_timeout(250);
-
- retval = enable_card_clock(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (chip->asic_code) {
- retval = ms_pull_ctl_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL,
- FPGA_MS_PULL_CTL_BIT | 0x20, 0);
- if (retval)
- return retval;
- }
-
- if (!chip->ft2_fast_mode) {
- retval = card_power_on(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- wait_timeout(150);
-
-#ifdef SUPPORT_OCP
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
- oc_mask = MS_OC_NOW | MS_OC_EVER;
- else
- oc_mask = SD_OC_NOW | SD_OC_EVER;
-
- if (chip->ocp_stat & oc_mask) {
- dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
- chip->ocp_stat);
- return STATUS_FAIL;
- }
-#endif
- }
-
- retval = rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN,
- MS_OUTPUT_EN);
- if (retval)
- return retval;
-
- if (chip->asic_code) {
- retval = rtsx_write_register(chip, MS_CFG, 0xFF,
- SAMPLE_TIME_RISING |
- PUSH_TIME_DEFAULT |
- NO_EXTEND_TOGGLE |
- MS_BUS_WIDTH_1);
- if (retval)
- return retval;
-
- } else {
- retval = rtsx_write_register(chip, MS_CFG, 0xFF,
- SAMPLE_TIME_FALLING |
- PUSH_TIME_DEFAULT |
- NO_EXTEND_TOGGLE |
- MS_BUS_WIDTH_1);
- if (retval)
- return retval;
- }
- retval = rtsx_write_register(chip, MS_TRANS_CFG, 0xFF,
- NO_WAIT_INT | NO_AUTO_READ_INT_REG);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR,
- MS_STOP | MS_CLR_ERR);
- if (retval)
- return retval;
-
- retval = ms_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 val;
-
- retval = ms_set_rw_reg_addr(chip, PRO_STATUS_REG, 6, SYSTEM_PARAM, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, READ_REG,
- 6, NO_WAIT_INT);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- retval = rtsx_read_register(chip, PPBUF_BASE2 + 2, &val);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "Type register: 0x%x\n", val);
- if (val != 0x01) {
- if (val != 0x02)
- ms_card->check_ms_flow = 1;
-
- return STATUS_FAIL;
- }
-
- retval = rtsx_read_register(chip, PPBUF_BASE2 + 4, &val);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "Category register: 0x%x\n", val);
- if (val != 0) {
- ms_card->check_ms_flow = 1;
- return STATUS_FAIL;
- }
-
- retval = rtsx_read_register(chip, PPBUF_BASE2 + 5, &val);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "Class register: 0x%x\n", val);
- if (val == 0) {
- retval = rtsx_read_register(chip, PPBUF_BASE2, &val);
- if (retval)
- return retval;
-
- if (val & WRT_PRTCT)
- chip->card_wp |= MS_CARD;
- else
- chip->card_wp &= ~MS_CARD;
-
- } else if ((val == 0x01) || (val == 0x02) || (val == 0x03)) {
- chip->card_wp |= MS_CARD;
- } else {
- ms_card->check_ms_flow = 1;
- return STATUS_FAIL;
- }
-
- ms_card->ms_type |= TYPE_MSPRO;
-
- retval = rtsx_read_register(chip, PPBUF_BASE2 + 3, &val);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "IF Mode register: 0x%x\n", val);
- if (val == 0) {
- ms_card->ms_type &= 0x0F;
- } else if (val == 7) {
- if (switch_8bit_bus)
- ms_card->ms_type |= MS_HG;
- else
- ms_card->ms_type &= 0x0F;
-
- } else {
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_confirm_cpu_startup(struct rtsx_chip *chip)
-{
- int retval, i, k;
- u8 val;
-
- /* Confirm CPU StartUp */
- k = 0;
- do {
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_read_bytes(chip, GET_INT, 1,
- NO_WAIT_INT, &val, 1);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- if (k > 100)
- return STATUS_FAIL;
-
- k++;
- wait_timeout(100);
- } while (!(val & INT_REG_CED));
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- if (val & INT_REG_ERR) {
- if (val & INT_REG_CMDNK)
- chip->card_wp |= (MS_CARD);
- else
- return STATUS_FAIL;
- }
- /* -- end confirm CPU startup */
-
- return STATUS_SUCCESS;
-}
-
-static int ms_switch_parallel_bus(struct rtsx_chip *chip)
-{
- int retval, i;
- u8 data[2];
-
- data[0] = PARALLEL_4BIT_IF;
- data[1] = 0;
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, WRITE_REG, 1, NO_WAIT_INT,
- data, 2);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_switch_8bit_bus(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 data[2];
-
- data[0] = PARALLEL_8BIT_IF;
- data[1] = 0;
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, WRITE_REG, 1,
- NO_WAIT_INT, data, 2);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, MS_CFG, 0x98,
- MS_BUS_WIDTH_8 | SAMPLE_TIME_FALLING);
- if (retval)
- return retval;
-
- ms_card->ms_type |= MS_8BIT;
- retval = ms_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT,
- 1, NO_WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_pro_reset_flow(struct rtsx_chip *chip, int switch_8bit_bus)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
-
- for (i = 0; i < 3; i++) {
- retval = ms_prepare_reset(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_identify_media_type(chip, switch_8bit_bus);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_confirm_cpu_startup(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_switch_parallel_bus(chip);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
- continue;
- } else {
- break;
- }
- }
-
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- /* Switch MS-PRO into Parallel mode */
- retval = rtsx_write_register(chip, MS_CFG, 0x18, MS_BUS_WIDTH_4);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, MS_CFG, PUSH_TIME_ODD,
- PUSH_TIME_ODD);
- if (retval)
- return retval;
-
- retval = ms_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- /* If MSPro HG Card, We shall try to switch to 8-bit bus */
- if (CHK_MSHG(ms_card) && chip->support_ms_8bit && switch_8bit_bus) {
- retval = ms_switch_8bit_bus(chip);
- if (retval != STATUS_SUCCESS) {
- ms_card->switch_8bit_fail = 1;
- return STATUS_FAIL;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-#ifdef XC_POWERCLASS
-static int msxc_change_power(struct rtsx_chip *chip, u8 mode)
-{
- int retval;
- u8 buf[6];
-
- ms_cleanup_work(chip);
-
- retval = ms_set_rw_reg_addr(chip, 0, 0, PRO_DATA_COUNT1, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf[0] = 0;
- buf[1] = mode;
- buf[2] = 0;
- buf[3] = 0;
- buf[4] = 0;
- buf[5] = 0;
-
- retval = ms_write_bytes(chip, PRO_WRITE_REG, 6, NO_WAIT_INT, buf, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, XC_CHG_POWER, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, buf);
- if (retval)
- return retval;
-
- if (buf[0] & (MS_INT_CMDNK | MS_INT_ERR))
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-#endif
-
-static int ms_read_attribute_info(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 val, *buf, class_code, device_type, sub_class, data[16];
- u16 total_blk = 0, blk_size = 0;
-#ifdef SUPPORT_MSXC
- u32 xc_total_blk = 0, xc_blk_size = 0;
-#endif
- u32 sys_info_addr = 0, sys_info_size;
-#ifdef SUPPORT_PCGL_1P18
- u32 model_name_addr = 0, model_name_size;
- int found_sys_info = 0, found_model_name = 0;
-#endif
-
- retval = ms_set_rw_reg_addr(chip, PRO_INT_REG, 2, PRO_SYSTEM_PARAM, 7);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_MS8BIT(ms_card))
- data[0] = PARALLEL_8BIT_IF;
- else
- data[0] = PARALLEL_4BIT_IF;
-
- data[1] = 0;
-
- data[2] = 0x40;
- data[3] = 0;
- data[4] = 0;
- data[5] = 0;
- data[6] = 0;
- data[7] = 0;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, PRO_WRITE_REG, 7, NO_WAIT_INT,
- data, 8);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf = kmalloc(64 * 512, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_send_cmd(chip, PRO_READ_ATRB, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- continue;
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
- if (!(val & MS_INT_BREQ)) {
- kfree(buf);
- return STATUS_FAIL;
- }
- retval = ms_transfer_data(chip, MS_TM_AUTO_READ,
- PRO_READ_LONG_DATA, 0x40, WAIT_INT,
- 0, 0, buf, 64 * 512);
- if (retval == STATUS_SUCCESS)
- break;
-
- rtsx_clear_ms_error(chip);
- }
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- i = 0;
- do {
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- if ((val & MS_INT_CED) || !(val & MS_INT_BREQ))
- break;
-
- retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ,
- PRO_READ_LONG_DATA, 0, WAIT_INT);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- i++;
- } while (i < 1024);
-
- if (buf[0] != 0xa5 && buf[1] != 0xc3) {
- /* Signature code is wrong */
- kfree(buf);
- return STATUS_FAIL;
- }
-
- if (buf[4] < 1 || buf[4] > 12) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- for (i = 0; i < buf[4]; i++) {
- int cur_addr_off = 16 + i * 12;
-
-#ifdef SUPPORT_MSXC
- if (buf[cur_addr_off + 8] == 0x10 ||
- buf[cur_addr_off + 8] == 0x13) {
-#else
- if (buf[cur_addr_off + 8] == 0x10) {
-#endif
- sys_info_addr = ((u32)buf[cur_addr_off + 0] << 24) |
- ((u32)buf[cur_addr_off + 1] << 16) |
- ((u32)buf[cur_addr_off + 2] << 8) |
- buf[cur_addr_off + 3];
- sys_info_size = ((u32)buf[cur_addr_off + 4] << 24) |
- ((u32)buf[cur_addr_off + 5] << 16) |
- ((u32)buf[cur_addr_off + 6] << 8) |
- buf[cur_addr_off + 7];
- dev_dbg(rtsx_dev(chip), "sys_info_addr = 0x%x, sys_info_size = 0x%x\n",
- sys_info_addr, sys_info_size);
- if (sys_info_size != 96) {
- kfree(buf);
- return STATUS_FAIL;
- }
- if (sys_info_addr < 0x1A0) {
- kfree(buf);
- return STATUS_FAIL;
- }
- if ((sys_info_size + sys_info_addr) > 0x8000) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
-#ifdef SUPPORT_MSXC
- if (buf[cur_addr_off + 8] == 0x13)
- ms_card->ms_type |= MS_XC;
-#endif
-#ifdef SUPPORT_PCGL_1P18
- found_sys_info = 1;
-#else
- break;
-#endif
- }
-#ifdef SUPPORT_PCGL_1P18
- if (buf[cur_addr_off + 8] == 0x15) {
- model_name_addr = ((u32)buf[cur_addr_off + 0] << 24) |
- ((u32)buf[cur_addr_off + 1] << 16) |
- ((u32)buf[cur_addr_off + 2] << 8) |
- buf[cur_addr_off + 3];
- model_name_size = ((u32)buf[cur_addr_off + 4] << 24) |
- ((u32)buf[cur_addr_off + 5] << 16) |
- ((u32)buf[cur_addr_off + 6] << 8) |
- buf[cur_addr_off + 7];
- dev_dbg(rtsx_dev(chip), "model_name_addr = 0x%x, model_name_size = 0x%x\n",
- model_name_addr, model_name_size);
- if (model_name_size != 48) {
- kfree(buf);
- return STATUS_FAIL;
- }
- if (model_name_addr < 0x1A0) {
- kfree(buf);
- return STATUS_FAIL;
- }
- if ((model_name_size + model_name_addr) > 0x8000) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- found_model_name = 1;
- }
-
- if (found_sys_info && found_model_name)
- break;
-#endif
- }
-
- if (i == buf[4]) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- class_code = buf[sys_info_addr + 0];
- device_type = buf[sys_info_addr + 56];
- sub_class = buf[sys_info_addr + 46];
-#ifdef SUPPORT_MSXC
- if (CHK_MSXC(ms_card)) {
- xc_total_blk = ((u32)buf[sys_info_addr + 6] << 24) |
- ((u32)buf[sys_info_addr + 7] << 16) |
- ((u32)buf[sys_info_addr + 8] << 8) |
- buf[sys_info_addr + 9];
- xc_blk_size = ((u32)buf[sys_info_addr + 32] << 24) |
- ((u32)buf[sys_info_addr + 33] << 16) |
- ((u32)buf[sys_info_addr + 34] << 8) |
- buf[sys_info_addr + 35];
- dev_dbg(rtsx_dev(chip), "xc_total_blk = 0x%x, xc_blk_size = 0x%x\n",
- xc_total_blk, xc_blk_size);
- } else {
- total_blk = ((u16)buf[sys_info_addr + 6] << 8) |
- buf[sys_info_addr + 7];
- blk_size = ((u16)buf[sys_info_addr + 2] << 8) |
- buf[sys_info_addr + 3];
- dev_dbg(rtsx_dev(chip), "total_blk = 0x%x, blk_size = 0x%x\n",
- total_blk, blk_size);
- }
-#else
- total_blk = ((u16)buf[sys_info_addr + 6] << 8) | buf[sys_info_addr + 7];
- blk_size = ((u16)buf[sys_info_addr + 2] << 8) | buf[sys_info_addr + 3];
- dev_dbg(rtsx_dev(chip), "total_blk = 0x%x, blk_size = 0x%x\n",
- total_blk, blk_size);
-#endif
-
- dev_dbg(rtsx_dev(chip), "class_code = 0x%x, device_type = 0x%x, sub_class = 0x%x\n",
- class_code, device_type, sub_class);
-
- memcpy(ms_card->raw_sys_info, buf + sys_info_addr, 96);
-#ifdef SUPPORT_PCGL_1P18
- memcpy(ms_card->raw_model_name, buf + model_name_addr, 48);
-#endif
-
- kfree(buf);
-
-#ifdef SUPPORT_MSXC
- if (CHK_MSXC(ms_card)) {
- if (class_code != 0x03)
- return STATUS_FAIL;
- } else {
- if (class_code != 0x02)
- return STATUS_FAIL;
- }
-#else
- if (class_code != 0x02)
- return STATUS_FAIL;
-#endif
-
- if (device_type != 0x00) {
- if (device_type == 0x01 || device_type == 0x02 ||
- device_type == 0x03) {
- chip->card_wp |= MS_CARD;
- } else {
- return STATUS_FAIL;
- }
- }
-
- if (sub_class & 0xC0)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "class_code: 0x%x, device_type: 0x%x, sub_class: 0x%x\n",
- class_code, device_type, sub_class);
-
-#ifdef SUPPORT_MSXC
- if (CHK_MSXC(ms_card)) {
- chip->capacity[chip->card2lun[MS_CARD]] =
- ms_card->capacity = xc_total_blk * xc_blk_size;
- } else {
- chip->capacity[chip->card2lun[MS_CARD]] =
- ms_card->capacity = total_blk * blk_size;
- }
-#else
- ms_card->capacity = total_blk * blk_size;
- chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity;
-#endif
-
- return STATUS_SUCCESS;
-}
-
-#ifdef SUPPORT_MAGIC_GATE
-static int mg_set_tpc_para_sub(struct rtsx_chip *chip,
- int type, u8 mg_entry_num);
-#endif
-
-static int reset_ms_pro(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-#ifdef XC_POWERCLASS
- u8 change_power_class;
-
- if (chip->ms_power_class_en & 0x02)
- change_power_class = 2;
- else if (chip->ms_power_class_en & 0x01)
- change_power_class = 1;
- else
- change_power_class = 0;
-#endif
-
-#ifdef XC_POWERCLASS
-retry:
-#endif
- retval = ms_pro_reset_flow(chip, 1);
- if (retval != STATUS_SUCCESS) {
- if (ms_card->switch_8bit_fail) {
- retval = ms_pro_reset_flow(chip, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- return STATUS_FAIL;
- }
- }
-
- retval = ms_read_attribute_info(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
-#ifdef XC_POWERCLASS
- if (CHK_HG8BIT(ms_card))
- change_power_class = 0;
-
- if (change_power_class && CHK_MSXC(ms_card)) {
- u8 power_class_en = chip->ms_power_class_en;
-
- dev_dbg(rtsx_dev(chip), "power_class_en = 0x%x\n",
- power_class_en);
- dev_dbg(rtsx_dev(chip), "change_power_class = %d\n",
- change_power_class);
-
- if (change_power_class)
- power_class_en &= (1 << (change_power_class - 1));
- else
- power_class_en = 0;
-
- if (power_class_en) {
- u8 power_class_mode =
- (ms_card->raw_sys_info[46] & 0x18) >> 3;
- dev_dbg(rtsx_dev(chip), "power_class_mode = 0x%x",
- power_class_mode);
- if (change_power_class > power_class_mode)
- change_power_class = power_class_mode;
- if (change_power_class) {
- retval = msxc_change_power(chip,
- change_power_class);
- if (retval != STATUS_SUCCESS) {
- change_power_class--;
- goto retry;
- }
- }
- }
- }
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
- retval = mg_set_tpc_para_sub(chip, 0, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-#endif
-
- if (CHK_HG8BIT(ms_card))
- chip->card_bus_width[chip->card2lun[MS_CARD]] = 8;
- else
- chip->card_bus_width[chip->card2lun[MS_CARD]] = 4;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_read_status_reg(struct rtsx_chip *chip)
-{
- int retval;
- u8 val[2];
-
- retval = ms_set_rw_reg_addr(chip, STATUS_REG0, 2, 0, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_read_bytes(chip, READ_REG, 2, NO_WAIT_INT, val, 2);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val[1] & (STS_UCDT | STS_UCEX | STS_UCFG)) {
- ms_set_err_code(chip, MS_FLASH_READ_ERROR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_read_extra_data(struct rtsx_chip *chip,
- u16 block_addr, u8 page_num, u8 *buf, int buf_len)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 val, data[10];
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_MS4BIT(ms_card)) {
- /* Parallel interface */
- data[0] = 0x88;
- } else {
- /* Serial interface */
- data[0] = 0x80;
- }
- data[1] = 0;
- data[2] = (u8)(block_addr >> 8);
- data[3] = (u8)block_addr;
- data[4] = 0x40;
- data[5] = page_num;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT,
- data, 6);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- retval = ms_read_status_reg(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG,
- MS_EXTRA_SIZE, SYSTEM_PARAM,
- 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
- }
-
- retval = ms_read_bytes(chip, READ_REG, MS_EXTRA_SIZE, NO_WAIT_INT,
- data, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (buf && buf_len) {
- if (buf_len > MS_EXTRA_SIZE)
- buf_len = MS_EXTRA_SIZE;
- memcpy(buf, data, buf_len);
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_write_extra_data(struct rtsx_chip *chip, u16 block_addr,
- u8 page_num, u8 *buf, int buf_len)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 val, data[16];
-
- if (!buf || buf_len < MS_EXTRA_SIZE)
- return STATUS_FAIL;
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 6 + MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(block_addr >> 8);
- data[3] = (u8)block_addr;
- data[4] = 0x40;
- data[5] = page_num;
-
- for (i = 6; i < MS_EXTRA_SIZE + 6; i++)
- data[i] = buf[i - 6];
-
- retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE),
- NO_WAIT_INT, data, 16);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- u8 val, data[6];
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(block_addr >> 8);
- data[3] = (u8)block_addr;
- data[4] = 0x20;
- data[5] = page_num;
-
- retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- if (!(val & INT_REG_BREQ)) {
- ms_set_err_code(chip, MS_FLASH_READ_ERROR);
- return STATUS_FAIL;
- }
- retval = ms_read_status_reg(chip);
- if (retval != STATUS_SUCCESS)
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-
- } else {
- if (!(val & INT_REG_BREQ)) {
- ms_set_err_code(chip, MS_BREQ_ERROR);
- return STATUS_FAIL;
- }
- }
- }
-
- retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA,
- 0, NO_WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR))
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- u8 val, data[8], extra[MS_EXTRA_SIZE];
-
- retval = ms_read_extra_data(chip, phy_blk, 0, extra, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 7);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(phy_blk >> 8);
- data[3] = (u8)phy_blk;
- data[4] = 0x80;
- data[5] = 0;
- data[6] = extra[0] & 0x7F;
- data[7] = 0xFF;
-
- retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, data, 7);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i = 0;
- u8 val, data[6];
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(phy_blk >> 8);
- data[3] = (u8)phy_blk;
- data[4] = 0;
- data[5] = 0;
-
- retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
-ERASE_RTY:
- retval = ms_send_cmd(chip, BLOCK_ERASE, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- if (i < 3) {
- i++;
- goto ERASE_RTY;
- }
-
- ms_set_err_code(chip, MS_CMD_NK);
- ms_set_bad_block(chip, phy_blk);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static void ms_set_page_status(u16 log_blk, u8 type, u8 *extra, int extra_len)
-{
- if (!extra || extra_len < MS_EXTRA_SIZE)
- return;
-
- memset(extra, 0xFF, MS_EXTRA_SIZE);
-
- if (type == set_PS_NG) {
- /* set page status as 1:NG,and block status keep 1:OK */
- extra[0] = 0xB8;
- } else {
- /* set page status as 0:Data Error,and block status keep 1:OK */
- extra[0] = 0x98;
- }
-
- extra[2] = (u8)(log_blk >> 8);
- extra[3] = (u8)log_blk;
-}
-
-static int ms_init_page(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk,
- u8 start_page, u8 end_page)
-{
- int retval;
- u8 extra[MS_EXTRA_SIZE], i;
-
- memset(extra, 0xff, MS_EXTRA_SIZE);
-
- extra[0] = 0xf8; /* Block, page OK, data erased */
- extra[1] = 0xff;
- extra[2] = (u8)(log_blk >> 8);
- extra[3] = (u8)log_blk;
-
- for (i = start_page; i < end_page; i++) {
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = ms_write_extra_data(chip, phy_blk, i,
- extra, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
- u16 log_blk, u8 start_page, u8 end_page)
-{
- struct ms_info *ms_card = &chip->ms_card;
- bool uncorrect_flag = false;
- int retval, rty_cnt;
- u8 extra[MS_EXTRA_SIZE], val, i, j, data[16];
-
- dev_dbg(rtsx_dev(chip), "Copy page from 0x%x to 0x%x, logical block is 0x%x\n",
- old_blk, new_blk, log_blk);
- dev_dbg(rtsx_dev(chip), "start_page = %d, end_page = %d\n",
- start_page, end_page);
-
- retval = ms_read_extra_data(chip, new_blk, 0, extra, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_read_status_reg(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_read_register(chip, PPBUF_BASE2, &val);
- if (retval)
- return retval;
-
- if (val & BUF_FULL) {
- retval = ms_send_cmd(chip, CLEAR_BUF, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!(val & INT_REG_CED)) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
-
- for (i = start_page; i < end_page; i++) {
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = ms_read_extra_data(chip, old_blk, i, extra,
- MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG,
- MS_EXTRA_SIZE, SYSTEM_PARAM, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(old_blk >> 8);
- data[3] = (u8)old_blk;
- data[4] = 0x20;
- data[5] = i;
-
- retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT,
- data, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- retval = ms_read_status_reg(chip);
- if (retval != STATUS_SUCCESS) {
- uncorrect_flag = true;
- dev_dbg(rtsx_dev(chip), "Uncorrectable error\n");
- } else {
- uncorrect_flag = false;
- }
-
- retval = ms_transfer_tpc(chip,
- MS_TM_NORMAL_READ,
- READ_PAGE_DATA,
- 0, NO_WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (uncorrect_flag) {
- ms_set_page_status(log_blk, set_PS_NG,
- extra,
- MS_EXTRA_SIZE);
- if (i == 0)
- extra[0] &= 0xEF;
-
- ms_write_extra_data(chip, old_blk, i,
- extra,
- MS_EXTRA_SIZE);
- dev_dbg(rtsx_dev(chip), "page %d : extra[0] = 0x%x\n",
- i, extra[0]);
- MS_SET_BAD_BLOCK_FLG(ms_card);
-
- ms_set_page_status(log_blk,
- set_PS_error, extra,
- MS_EXTRA_SIZE);
- ms_write_extra_data(chip, new_blk, i,
- extra,
- MS_EXTRA_SIZE);
- continue;
- }
-
- for (rty_cnt = 0; rty_cnt < MS_MAX_RETRY_COUNT;
- rty_cnt++) {
- retval = ms_transfer_tpc(chip,
- MS_TM_NORMAL_WRITE,
- WRITE_PAGE_DATA,
- 0, NO_WAIT_INT);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (rty_cnt == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
- }
-
- if (!(val & INT_REG_BREQ)) {
- ms_set_err_code(chip, MS_BREQ_ERROR);
- return STATUS_FAIL;
- }
- }
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, (6 + MS_EXTRA_SIZE));
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(new_blk >> 8);
- data[3] = (u8)new_blk;
- data[4] = 0x20;
- data[5] = i;
-
- if ((extra[0] & 0x60) != 0x60)
- data[6] = extra[0];
- else
- data[6] = 0xF8;
-
- data[6 + 1] = 0xFF;
- data[6 + 2] = (u8)(log_blk >> 8);
- data[6 + 3] = (u8)log_blk;
-
- for (j = 4; j <= MS_EXTRA_SIZE; j++)
- data[6 + j] = 0xFF;
-
- retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE),
- NO_WAIT_INT, data, 16);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
-
- if (i == 0) {
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG,
- MS_EXTRA_SIZE, SYSTEM_PARAM,
- 7);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(old_blk >> 8);
- data[3] = (u8)old_blk;
- data[4] = 0x80;
- data[5] = 0;
- data[6] = 0xEF;
- data[7] = 0xFF;
-
- retval = ms_write_bytes(chip, WRITE_REG, 7,
- NO_WAIT_INT, data, 8);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1,
- NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- ms_set_err_code(chip,
- MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static int reset_ms(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- u16 i, reg_addr, block_size;
- u8 val, extra[MS_EXTRA_SIZE], j, *ptr;
-#ifndef SUPPORT_MAGIC_GATE
- u16 eblock_cnt;
-#endif
-
- retval = ms_prepare_reset(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_card->ms_type |= TYPE_MS;
-
- retval = ms_send_cmd(chip, MS_RESET, NO_WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_read_status_reg(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_read_register(chip, PPBUF_BASE2, &val);
- if (retval)
- return retval;
-
- if (val & WRT_PRTCT)
- chip->card_wp |= MS_CARD;
- else
- chip->card_wp &= ~MS_CARD;
-
- i = 0;
-
-RE_SEARCH:
- /* Search Boot Block */
- while (i < (MAX_DEFECTIVE_BLOCK + 2)) {
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = ms_read_extra_data(chip, i, 0, extra, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS) {
- i++;
- continue;
- }
-
- if (extra[0] & BLOCK_OK) {
- if (!(extra[1] & NOT_BOOT_BLOCK)) {
- ms_card->boot_block = i;
- break;
- }
- }
- i++;
- }
-
- if (i == (MAX_DEFECTIVE_BLOCK + 2)) {
- dev_dbg(rtsx_dev(chip), "No boot block found!");
- return STATUS_FAIL;
- }
-
- for (j = 0; j < 3; j++) {
- retval = ms_read_page(chip, ms_card->boot_block, j);
- if (retval != STATUS_SUCCESS) {
- if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) {
- i = ms_card->boot_block + 1;
- ms_set_err_code(chip, MS_NO_ERROR);
- goto RE_SEARCH;
- }
- }
- }
-
- retval = ms_read_page(chip, ms_card->boot_block, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- /* Read MS system information as sys_info */
- rtsx_init_cmd(chip);
-
- for (i = 0; i < 96; i++)
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 0x1A0 + i, 0, 0);
-
- retval = rtsx_send_cmd(chip, MS_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- ptr = rtsx_get_cmd_data(chip);
- memcpy(ms_card->raw_sys_info, ptr, 96);
-
- /* Read useful block contents */
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID0, 0, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID1, 0, 0);
-
- for (reg_addr = DISABLED_BLOCK0; reg_addr <= DISABLED_BLOCK3;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
- for (reg_addr = BLOCK_SIZE_0; reg_addr <= PAGE_SIZE_1; reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
- rtsx_add_cmd(chip, READ_REG_CMD, MS_device_type, 0, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, MS_4bit_support, 0, 0);
-
- retval = rtsx_send_cmd(chip, MS_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- ptr = rtsx_get_cmd_data(chip);
-
- dev_dbg(rtsx_dev(chip), "Boot block data:\n");
- dev_dbg(rtsx_dev(chip), "%*ph\n", 16, ptr);
-
- /* Block ID error
- * HEADER_ID0, HEADER_ID1
- */
- if (ptr[0] != 0x00 || ptr[1] != 0x01) {
- i = ms_card->boot_block + 1;
- goto RE_SEARCH;
- }
-
- /* Page size error
- * PAGE_SIZE_0, PAGE_SIZE_1
- */
- if (ptr[12] != 0x02 || ptr[13] != 0x00) {
- i = ms_card->boot_block + 1;
- goto RE_SEARCH;
- }
-
- if (ptr[14] == 1 || ptr[14] == 3)
- chip->card_wp |= MS_CARD;
-
- /* BLOCK_SIZE_0, BLOCK_SIZE_1 */
- block_size = ((u16)ptr[6] << 8) | ptr[7];
- if (block_size == 0x0010) {
- /* Block size 16KB */
- ms_card->block_shift = 5;
- ms_card->page_off = 0x1F;
- } else if (block_size == 0x0008) {
- /* Block size 8KB */
- ms_card->block_shift = 4;
- ms_card->page_off = 0x0F;
- }
-
- /* BLOCK_COUNT_0, BLOCK_COUNT_1 */
- ms_card->total_block = ((u16)ptr[8] << 8) | ptr[9];
-
-#ifdef SUPPORT_MAGIC_GATE
- j = ptr[10];
-
- if (ms_card->block_shift == 4) { /* 4MB or 8MB */
- if (j < 2) { /* Effective block for 4MB: 0x1F0 */
- ms_card->capacity = 0x1EE0;
- } else { /* Effective block for 8MB: 0x3E0 */
- ms_card->capacity = 0x3DE0;
- }
- } else { /* 16MB, 32MB, 64MB or 128MB */
- if (j < 5) { /* Effective block for 16MB: 0x3E0 */
- ms_card->capacity = 0x7BC0;
- } else if (j < 0xA) { /* Effective block for 32MB: 0x7C0 */
- ms_card->capacity = 0xF7C0;
- } else if (j < 0x11) { /* Effective block for 64MB: 0xF80 */
- ms_card->capacity = 0x1EF80;
- } else { /* Effective block for 128MB: 0x1F00 */
- ms_card->capacity = 0x3DF00;
- }
- }
-#else
- /* EBLOCK_COUNT_0, EBLOCK_COUNT_1 */
- eblock_cnt = ((u16)ptr[10] << 8) | ptr[11];
-
- ms_card->capacity = ((u32)eblock_cnt - 2) << ms_card->block_shift;
-#endif
-
- chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity;
-
- /* Switch I/F Mode */
- if (ptr[15]) {
- retval = ms_set_rw_reg_addr(chip, 0, 0, SYSTEM_PARAM, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, PPBUF_BASE2, 0xFF, 0x88);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, PPBUF_BASE2 + 1, 0xFF, 0);
- if (retval)
- return retval;
-
- retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG, 1,
- NO_WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, MS_CFG,
- 0x58 | MS_NO_CHECK_INT,
- MS_BUS_WIDTH_4 |
- PUSH_TIME_ODD |
- MS_NO_CHECK_INT);
- if (retval)
- return retval;
-
- ms_card->ms_type |= MS_4BIT;
- }
-
- if (CHK_MS4BIT(ms_card))
- chip->card_bus_width[chip->card2lun[MS_CARD]] = 4;
- else
- chip->card_bus_width[chip->card2lun[MS_CARD]] = 1;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_init_l2p_tbl(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int size, i, seg_no, retval;
- u16 defect_block, reg_addr;
- u8 val1, val2;
-
- ms_card->segment_cnt = ms_card->total_block >> 9;
- dev_dbg(rtsx_dev(chip), "ms_card->segment_cnt = %d\n",
- ms_card->segment_cnt);
-
- size = ms_card->segment_cnt * sizeof(struct zone_entry);
- ms_card->segment = vzalloc(size);
- if (!ms_card->segment)
- return STATUS_FAIL;
-
- retval = ms_read_page(chip, ms_card->boot_block, 1);
- if (retval != STATUS_SUCCESS)
- goto INIT_FAIL;
-
- reg_addr = PPBUF_BASE2;
- for (i = 0; i < (((ms_card->total_block >> 9) * 10) + 1); i++) {
- int block_no;
-
- retval = rtsx_read_register(chip, reg_addr++, &val1);
- if (retval != STATUS_SUCCESS)
- goto INIT_FAIL;
-
- retval = rtsx_read_register(chip, reg_addr++, &val2);
- if (retval != STATUS_SUCCESS)
- goto INIT_FAIL;
-
- defect_block = ((u16)val1 << 8) | val2;
- if (defect_block == 0xFFFF)
- break;
-
- seg_no = defect_block / 512;
-
- block_no = ms_card->segment[seg_no].disable_count++;
- ms_card->segment[seg_no].defect_list[block_no] = defect_block;
- }
-
- for (i = 0; i < ms_card->segment_cnt; i++) {
- ms_card->segment[i].build_flag = 0;
- ms_card->segment[i].l2p_table = NULL;
- ms_card->segment[i].free_table = NULL;
- ms_card->segment[i].get_index = 0;
- ms_card->segment[i].set_index = 0;
- ms_card->segment[i].unused_blk_cnt = 0;
-
- dev_dbg(rtsx_dev(chip), "defective block count of segment %d is %d\n",
- i, ms_card->segment[i].disable_count);
- }
-
- return STATUS_SUCCESS;
-
-INIT_FAIL:
- vfree(ms_card->segment);
- ms_card->segment = NULL;
-
- return STATUS_FAIL;
-}
-
-static u16 ms_get_l2p_tbl(struct rtsx_chip *chip, int seg_no, u16 log_off)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct zone_entry *segment;
-
- if (!ms_card->segment)
- return 0xFFFF;
-
- segment = &ms_card->segment[seg_no];
-
- if (segment->l2p_table)
- return segment->l2p_table[log_off];
-
- return 0xFFFF;
-}
-
-static void ms_set_l2p_tbl(struct rtsx_chip *chip,
- int seg_no, u16 log_off, u16 phy_blk)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct zone_entry *segment;
-
- if (!ms_card->segment)
- return;
-
- segment = &ms_card->segment[seg_no];
- if (segment->l2p_table)
- segment->l2p_table[log_off] = phy_blk;
-}
-
-static void ms_set_unused_block(struct rtsx_chip *chip, u16 phy_blk)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct zone_entry *segment;
- int seg_no;
-
- seg_no = (int)phy_blk >> 9;
- segment = &ms_card->segment[seg_no];
-
- segment->free_table[segment->set_index++] = phy_blk;
- if (segment->set_index >= MS_FREE_TABLE_CNT)
- segment->set_index = 0;
-
- segment->unused_blk_cnt++;
-}
-
-static u16 ms_get_unused_block(struct rtsx_chip *chip, int seg_no)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct zone_entry *segment;
- u16 phy_blk;
-
- segment = &ms_card->segment[seg_no];
-
- if (segment->unused_blk_cnt <= 0)
- return 0xFFFF;
-
- phy_blk = segment->free_table[segment->get_index];
- segment->free_table[segment->get_index++] = 0xFFFF;
- if (segment->get_index >= MS_FREE_TABLE_CNT)
- segment->get_index = 0;
-
- segment->unused_blk_cnt--;
-
- return phy_blk;
-}
-
-static const unsigned short ms_start_idx[] = {0, 494, 990, 1486, 1982, 2478,
- 2974, 3470, 3966, 4462, 4958,
- 5454, 5950, 6446, 6942, 7438,
- 7934};
-
-static int ms_arbitrate_l2p(struct rtsx_chip *chip, u16 phy_blk,
- u16 log_off, u8 us1, u8 us2)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct zone_entry *segment;
- int seg_no;
- u16 tmp_blk;
-
- seg_no = (int)phy_blk >> 9;
- segment = &ms_card->segment[seg_no];
- tmp_blk = segment->l2p_table[log_off];
-
- if (us1 != us2) {
- if (us1 == 0) {
- if (!(chip->card_wp & MS_CARD))
- ms_erase_block(chip, tmp_blk);
-
- ms_set_unused_block(chip, tmp_blk);
- segment->l2p_table[log_off] = phy_blk;
- } else {
- if (!(chip->card_wp & MS_CARD))
- ms_erase_block(chip, phy_blk);
-
- ms_set_unused_block(chip, phy_blk);
- }
- } else {
- if (phy_blk < tmp_blk) {
- if (!(chip->card_wp & MS_CARD))
- ms_erase_block(chip, phy_blk);
-
- ms_set_unused_block(chip, phy_blk);
- } else {
- if (!(chip->card_wp & MS_CARD))
- ms_erase_block(chip, tmp_blk);
-
- ms_set_unused_block(chip, tmp_blk);
- segment->l2p_table[log_off] = phy_blk;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct zone_entry *segment;
- bool defect_flag;
- int retval, table_size, disable_cnt, i;
- u16 start, end, phy_blk, log_blk, tmp_blk, idx;
- u8 extra[MS_EXTRA_SIZE], us1, us2;
-
- dev_dbg(rtsx_dev(chip), "%s: %d\n", __func__, seg_no);
-
- if (!ms_card->segment) {
- retval = ms_init_l2p_tbl(chip);
- if (retval != STATUS_SUCCESS)
- return retval;
- }
-
- if (ms_card->segment[seg_no].build_flag) {
- dev_dbg(rtsx_dev(chip), "l2p table of segment %d has been built\n",
- seg_no);
- return STATUS_SUCCESS;
- }
-
- if (seg_no == 0)
- table_size = 494;
- else
- table_size = 496;
-
- segment = &ms_card->segment[seg_no];
-
- if (!segment->l2p_table) {
- segment->l2p_table = vmalloc(array_size(table_size, 2));
- if (!segment->l2p_table)
- goto BUILD_FAIL;
- }
- memset((u8 *)(segment->l2p_table), 0xff, array_size(table_size, 2));
-
- if (!segment->free_table) {
- segment->free_table = vmalloc(array_size(MS_FREE_TABLE_CNT, 2));
- if (!segment->free_table)
- goto BUILD_FAIL;
- }
- memset((u8 *)(segment->free_table), 0xff, array_size(MS_FREE_TABLE_CNT, 2));
-
- start = (u16)seg_no << 9;
- end = (u16)(seg_no + 1) << 9;
-
- disable_cnt = segment->disable_count;
-
- segment->get_index = 0;
- segment->set_index = 0;
- segment->unused_blk_cnt = 0;
-
- for (phy_blk = start; phy_blk < end; phy_blk++) {
- if (disable_cnt) {
- defect_flag = false;
- for (i = 0; i < segment->disable_count; i++) {
- if (phy_blk == segment->defect_list[i]) {
- defect_flag = true;
- break;
- }
- }
- if (defect_flag) {
- disable_cnt--;
- continue;
- }
- }
-
- retval = ms_read_extra_data(chip, phy_blk, 0,
- extra, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS) {
- dev_dbg(rtsx_dev(chip), "read extra data fail\n");
- ms_set_bad_block(chip, phy_blk);
- continue;
- }
-
- if (seg_no == ms_card->segment_cnt - 1) {
- if (!(extra[1] & NOT_TRANSLATION_TABLE)) {
- if (!(chip->card_wp & MS_CARD)) {
- retval = ms_erase_block(chip, phy_blk);
- if (retval != STATUS_SUCCESS)
- continue;
- extra[2] = 0xff;
- extra[3] = 0xff;
- }
- }
- }
-
- if (!(extra[0] & BLOCK_OK))
- continue;
- if (!(extra[1] & NOT_BOOT_BLOCK))
- continue;
- if ((extra[0] & PAGE_OK) != PAGE_OK)
- continue;
-
- log_blk = ((u16)extra[2] << 8) | extra[3];
-
- if (log_blk == 0xFFFF) {
- if (!(chip->card_wp & MS_CARD)) {
- retval = ms_erase_block(chip, phy_blk);
- if (retval != STATUS_SUCCESS)
- continue;
- }
- ms_set_unused_block(chip, phy_blk);
- continue;
- }
-
- if (log_blk < ms_start_idx[seg_no] ||
- log_blk >= ms_start_idx[seg_no + 1]) {
- if (!(chip->card_wp & MS_CARD)) {
- retval = ms_erase_block(chip, phy_blk);
- if (retval != STATUS_SUCCESS)
- continue;
- }
- ms_set_unused_block(chip, phy_blk);
- continue;
- }
-
- idx = log_blk - ms_start_idx[seg_no];
-
- if (segment->l2p_table[idx] == 0xFFFF) {
- segment->l2p_table[idx] = phy_blk;
- continue;
- }
-
- us1 = extra[0] & 0x10;
- tmp_blk = segment->l2p_table[idx];
- retval = ms_read_extra_data(chip, tmp_blk, 0,
- extra, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- continue;
- us2 = extra[0] & 0x10;
-
- (void)ms_arbitrate_l2p(chip, phy_blk,
- log_blk - ms_start_idx[seg_no], us1, us2);
- }
-
- segment->build_flag = 1;
-
- dev_dbg(rtsx_dev(chip), "unused block count: %d\n",
- segment->unused_blk_cnt);
-
- /* Logical Address Confirmation Process */
- if (seg_no == ms_card->segment_cnt - 1) {
- if (segment->unused_blk_cnt < 2)
- chip->card_wp |= MS_CARD;
- } else {
- if (segment->unused_blk_cnt < 1)
- chip->card_wp |= MS_CARD;
- }
-
- if (chip->card_wp & MS_CARD)
- return STATUS_SUCCESS;
-
- for (log_blk = ms_start_idx[seg_no];
- log_blk < ms_start_idx[seg_no + 1]; log_blk++) {
- idx = log_blk - ms_start_idx[seg_no];
- if (segment->l2p_table[idx] == 0xFFFF) {
- phy_blk = ms_get_unused_block(chip, seg_no);
- if (phy_blk == 0xFFFF) {
- chip->card_wp |= MS_CARD;
- return STATUS_SUCCESS;
- }
- retval = ms_init_page(chip, phy_blk, log_blk, 0, 1);
- if (retval != STATUS_SUCCESS)
- goto BUILD_FAIL;
-
- segment->l2p_table[idx] = phy_blk;
- if (seg_no == ms_card->segment_cnt - 1) {
- if (segment->unused_blk_cnt < 2) {
- chip->card_wp |= MS_CARD;
- return STATUS_SUCCESS;
- }
- } else {
- if (segment->unused_blk_cnt < 1) {
- chip->card_wp |= MS_CARD;
- return STATUS_SUCCESS;
- }
- }
- }
- }
-
- /* Make boot block be the first normal block */
- if (seg_no == 0) {
- for (log_blk = 0; log_blk < 494; log_blk++) {
- tmp_blk = segment->l2p_table[log_blk];
- if (tmp_blk < ms_card->boot_block) {
- dev_dbg(rtsx_dev(chip), "Boot block is not the first normal block.\n");
-
- if (chip->card_wp & MS_CARD)
- break;
-
- phy_blk = ms_get_unused_block(chip, 0);
- retval = ms_copy_page(chip, tmp_blk, phy_blk,
- log_blk, 0,
- ms_card->page_off + 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- segment->l2p_table[log_blk] = phy_blk;
-
- retval = ms_set_bad_block(chip, tmp_blk);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
- }
- }
-
- return STATUS_SUCCESS;
-
-BUILD_FAIL:
- segment->build_flag = 0;
- vfree(segment->l2p_table);
- segment->l2p_table = NULL;
- vfree(segment->free_table);
- segment->free_table = NULL;
-
- return STATUS_FAIL;
-}
-
-int reset_ms_card(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int seg_no = ms_card->total_block / 512 - 1;
- int retval;
-
- memset(ms_card, 0, sizeof(struct ms_info));
-
- retval = enable_card_clock(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = select_card(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_card->ms_type = 0;
-
- retval = reset_ms_pro(chip);
- if (retval != STATUS_SUCCESS) {
- if (ms_card->check_ms_flow) {
- retval = reset_ms(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- return STATUS_FAIL;
- }
- }
-
- retval = ms_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!CHK_MSPRO(ms_card)) {
- /* Build table for the last segment,
- * to check if L2P table block exists, erasing it
- */
- retval = ms_build_l2p_tbl(chip, seg_no);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- dev_dbg(rtsx_dev(chip), "ms_card->ms_type = 0x%x\n", ms_card->ms_type);
-
- return STATUS_SUCCESS;
-}
-
-static int mspro_set_rw_cmd(struct rtsx_chip *chip,
- u32 start_sec, u16 sec_cnt, u8 cmd)
-{
- int retval, i;
- u8 data[8];
-
- data[0] = cmd;
- data[1] = (u8)(sec_cnt >> 8);
- data[2] = (u8)sec_cnt;
- data[3] = (u8)(start_sec >> 24);
- data[4] = (u8)(start_sec >> 16);
- data[5] = (u8)(start_sec >> 8);
- data[6] = (u8)start_sec;
- data[7] = 0;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7,
- WAIT_INT, data, 8);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-void mspro_stop_seq_mode(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-
- if (ms_card->seq_mode) {
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return;
-
- ms_card->seq_mode = 0;
- ms_card->total_sec_cnt = 0;
- ms_send_cmd(chip, PRO_STOP, WAIT_INT);
-
- rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
- }
-}
-
-static inline int ms_auto_tune_clock(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-
- if (chip->asic_code) {
- if (ms_card->ms_clock > 30)
- ms_card->ms_clock -= 20;
- } else {
- if (ms_card->ms_clock == CLK_80)
- ms_card->ms_clock = CLK_60;
- else if (ms_card->ms_clock == CLK_60)
- ms_card->ms_clock = CLK_40;
- }
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int mspro_rw_multi_sector(struct scsi_cmnd *srb,
- struct rtsx_chip *chip, u32 start_sector,
- u16 sector_cnt)
-{
- struct ms_info *ms_card = &chip->ms_card;
- bool mode_2k = false;
- int retval;
- u16 count;
- u8 val, trans_mode, rw_tpc, rw_cmd;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- ms_card->cleanup_counter = 0;
-
- if (CHK_MSHG(ms_card)) {
- if ((start_sector % 4) || (sector_cnt % 4)) {
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- rw_tpc = PRO_READ_LONG_DATA;
- rw_cmd = PRO_READ_DATA;
- } else {
- rw_tpc = PRO_WRITE_LONG_DATA;
- rw_cmd = PRO_WRITE_DATA;
- }
- } else {
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- rw_tpc = PRO_READ_QUAD_DATA;
- rw_cmd = PRO_READ_2K_DATA;
- } else {
- rw_tpc = PRO_WRITE_QUAD_DATA;
- rw_cmd = PRO_WRITE_2K_DATA;
- }
- mode_2k = true;
- }
- } else {
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- rw_tpc = PRO_READ_LONG_DATA;
- rw_cmd = PRO_READ_DATA;
- } else {
- rw_tpc = PRO_WRITE_LONG_DATA;
- rw_cmd = PRO_WRITE_DATA;
- }
- }
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- trans_mode = MS_TM_AUTO_READ;
- else
- trans_mode = MS_TM_AUTO_WRITE;
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
- if (retval)
- return retval;
-
- if (ms_card->seq_mode) {
- if (ms_card->pre_dir != srb->sc_data_direction ||
- ((ms_card->pre_sec_addr + ms_card->pre_sec_cnt) !=
- start_sector) ||
- (mode_2k && (ms_card->seq_mode & MODE_512_SEQ)) ||
- (!mode_2k && (ms_card->seq_mode & MODE_2K_SEQ)) ||
- !(val & MS_INT_BREQ) ||
- ((ms_card->total_sec_cnt + sector_cnt) > 0xFE00)) {
- ms_card->seq_mode = 0;
- ms_card->total_sec_cnt = 0;
- if (val & MS_INT_BREQ) {
- retval = ms_send_cmd(chip, PRO_STOP, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_write_register(chip, RBCTL, RB_FLUSH,
- RB_FLUSH);
- }
- }
- }
-
- if (!ms_card->seq_mode) {
- ms_card->total_sec_cnt = 0;
- if (sector_cnt >= SEQ_START_CRITERIA) {
- if ((ms_card->capacity - start_sector) > 0xFE00)
- count = 0xFE00;
- else
- count = (u16)(ms_card->capacity - start_sector);
-
- if (count > sector_cnt) {
- if (mode_2k)
- ms_card->seq_mode = MODE_2K_SEQ;
- else
- ms_card->seq_mode = MODE_512_SEQ;
- }
- } else {
- count = sector_cnt;
- }
- retval = mspro_set_rw_cmd(chip, start_sector, count, rw_cmd);
- if (retval != STATUS_SUCCESS) {
- ms_card->seq_mode = 0;
- return STATUS_FAIL;
- }
- }
-
- retval = ms_transfer_data(chip, trans_mode, rw_tpc, sector_cnt,
- WAIT_INT, mode_2k, scsi_sg_count(srb),
- scsi_sglist(srb), scsi_bufflen(srb));
- if (retval != STATUS_SUCCESS) {
- ms_card->seq_mode = 0;
- rtsx_read_register(chip, MS_TRANS_CFG, &val);
- rtsx_clear_ms_error(chip);
-
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- chip->rw_need_retry = 0;
- dev_dbg(rtsx_dev(chip), "No card exist, exit %s\n",
- __func__);
- return STATUS_FAIL;
- }
-
- if (val & MS_INT_BREQ)
- ms_send_cmd(chip, PRO_STOP, WAIT_INT);
-
- if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) {
- dev_dbg(rtsx_dev(chip), "MSPro CRC error, tune clock!\n");
- chip->rw_need_retry = 1;
- ms_auto_tune_clock(chip);
- }
-
- return retval;
- }
-
- if (ms_card->seq_mode) {
- ms_card->pre_sec_addr = start_sector;
- ms_card->pre_sec_cnt = sector_cnt;
- ms_card->pre_dir = srb->sc_data_direction;
- ms_card->total_sec_cnt += sector_cnt;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int mspro_read_format_progress(struct rtsx_chip *chip,
- const int short_data_len)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u32 total_progress, cur_progress;
- u8 cnt, tmp;
- u8 data[8];
-
- dev_dbg(rtsx_dev(chip), "%s, short_data_len = %d\n", __func__,
- short_data_len);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
- if (retval != STATUS_SUCCESS) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- if (!(tmp & MS_INT_BREQ)) {
- if ((tmp & (MS_INT_CED | MS_INT_BREQ | MS_INT_CMDNK |
- MS_INT_ERR)) == MS_INT_CED) {
- ms_card->format_status = FORMAT_SUCCESS;
- return STATUS_SUCCESS;
- }
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- if (short_data_len >= 256)
- cnt = 0;
- else
- cnt = (u8)short_data_len;
-
- retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT,
- MS_NO_CHECK_INT);
- if (retval != STATUS_SUCCESS) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, cnt, WAIT_INT,
- data, 8);
- if (retval != STATUS_SUCCESS) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- total_progress = (data[0] << 24) | (data[1] << 16) |
- (data[2] << 8) | data[3];
- cur_progress = (data[4] << 24) | (data[5] << 16) |
- (data[6] << 8) | data[7];
-
- dev_dbg(rtsx_dev(chip), "total_progress = %d, cur_progress = %d\n",
- total_progress, cur_progress);
-
- if (total_progress == 0) {
- ms_card->progress = 0;
- } else {
- u64 ulltmp = (u64)cur_progress * (u64)65535;
-
- do_div(ulltmp, total_progress);
- ms_card->progress = (u16)ulltmp;
- }
- dev_dbg(rtsx_dev(chip), "progress = %d\n", ms_card->progress);
-
- for (i = 0; i < 5000; i++) {
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
- if (retval != STATUS_SUCCESS) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
- if (tmp & (MS_INT_CED | MS_INT_CMDNK |
- MS_INT_BREQ | MS_INT_ERR))
- break;
-
- wait_timeout(1);
- }
-
- retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, 0);
- if (retval != STATUS_SUCCESS) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- if (i == 5000) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- if (tmp & MS_INT_CED) {
- ms_card->format_status = FORMAT_SUCCESS;
- ms_card->pro_under_formatting = 0;
- } else if (tmp & MS_INT_BREQ) {
- ms_card->format_status = FORMAT_IN_PROGRESS;
- } else {
- ms_card->format_status = FORMAT_FAIL;
- ms_card->pro_under_formatting = 0;
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-void mspro_polling_format_status(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int i;
-
- if (ms_card->pro_under_formatting &&
- (rtsx_get_stat(chip) != RTSX_STAT_SS)) {
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- for (i = 0; i < 65535; i++) {
- mspro_read_format_progress(chip, MS_SHORT_DATA_LEN);
- if (ms_card->format_status != FORMAT_IN_PROGRESS)
- break;
- }
- }
-}
-
-int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- int short_data_len, bool quick_format)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 buf[8], tmp;
- u16 para;
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_set_rw_reg_addr(chip, 0x00, 0x00, PRO_TPC_PARM, 0x01);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- memset(buf, 0, 2);
- switch (short_data_len) {
- case 32:
- buf[0] = 0;
- break;
- case 64:
- buf[0] = 1;
- break;
- case 128:
- buf[0] = 2;
- break;
- case 256:
- default:
- buf[0] = 3;
- break;
- }
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, PRO_WRITE_REG, 1,
- NO_WAIT_INT, buf, 2);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- if (quick_format)
- para = 0x0000;
- else
- para = 0x0001;
-
- retval = mspro_set_rw_cmd(chip, 0, para, PRO_FORMAT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
- if (retval)
- return retval;
-
- if (tmp & (MS_INT_CMDNK | MS_INT_ERR))
- return STATUS_FAIL;
-
- if ((tmp & (MS_INT_BREQ | MS_INT_CED)) == MS_INT_BREQ) {
- ms_card->pro_under_formatting = 1;
- ms_card->progress = 0;
- ms_card->format_status = FORMAT_IN_PROGRESS;
- return STATUS_SUCCESS;
- }
-
- if (tmp & MS_INT_CED) {
- ms_card->pro_under_formatting = 0;
- ms_card->progress = 0;
- ms_card->format_status = FORMAT_SUCCESS;
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_NO_SENSE);
- return STATUS_SUCCESS;
- }
-
- return STATUS_FAIL;
-}
-
-static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk,
- u16 log_blk, u8 start_page, u8 end_page,
- u8 *buf, unsigned int *index,
- unsigned int *offset)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 extra[MS_EXTRA_SIZE], page_addr, val, trans_cfg, data[6];
- u8 *ptr;
-
- retval = ms_read_extra_data(chip, phy_blk, start_page,
- extra, MS_EXTRA_SIZE);
- if (retval == STATUS_SUCCESS) {
- if ((extra[1] & 0x30) != 0x30) {
- ms_set_err_code(chip, MS_FLASH_READ_ERROR);
- return STATUS_FAIL;
- }
- }
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(phy_blk >> 8);
- data[3] = (u8)phy_blk;
- data[4] = 0;
- data[5] = start_page;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT,
- data, 6);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ptr = buf;
-
- for (page_addr = start_page; page_addr < end_page; page_addr++) {
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
- if (val & INT_REG_ERR) {
- if (val & INT_REG_BREQ) {
- retval = ms_read_status_reg(chip);
- if (retval != STATUS_SUCCESS) {
- if (!(chip->card_wp & MS_CARD)) {
- reset_ms(chip);
- ms_set_page_status
- (log_blk, set_PS_NG,
- extra,
- MS_EXTRA_SIZE);
- ms_write_extra_data
- (chip, phy_blk,
- page_addr, extra,
- MS_EXTRA_SIZE);
- }
- ms_set_err_code(chip,
- MS_FLASH_READ_ERROR);
- return STATUS_FAIL;
- }
- } else {
- ms_set_err_code(chip, MS_FLASH_READ_ERROR);
- return STATUS_FAIL;
- }
- } else {
- if (!(val & INT_REG_BREQ)) {
- ms_set_err_code(chip, MS_BREQ_ERROR);
- return STATUS_FAIL;
- }
- }
-
- if (page_addr == (end_page - 1)) {
- if (!(val & INT_REG_CED)) {
- retval = ms_send_cmd(chip, BLOCK_END, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT,
- &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!(val & INT_REG_CED)) {
- ms_set_err_code(chip, MS_FLASH_READ_ERROR);
- return STATUS_FAIL;
- }
-
- trans_cfg = NO_WAIT_INT;
- } else {
- trans_cfg = WAIT_INT;
- }
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, READ_PAGE_DATA);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG,
- 0xFF, trans_cfg);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, RING_BUFFER);
-
- trans_dma_enable(DMA_FROM_DEVICE, chip, 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
- MS_TRANSFER_START | MS_TM_NORMAL_READ);
- rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, 512,
- scsi_sg_count(chip->srb),
- index, offset,
- DMA_FROM_DEVICE,
- chip->ms_timeout);
- if (retval < 0) {
- if (retval == -ETIMEDOUT) {
- ms_set_err_code(chip, MS_TO_ERROR);
- rtsx_clear_ms_error(chip);
- return STATUS_TIMEDOUT;
- }
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
- if (retval != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_TO_ERROR);
- rtsx_clear_ms_error(chip);
- return STATUS_TIMEDOUT;
- }
- if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) {
- ms_set_err_code(chip, MS_CRC16_ERROR);
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
- }
-
- if (scsi_sg_count(chip->srb) == 0)
- ptr += 512;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk,
- u16 new_blk, u16 log_blk, u8 start_page,
- u8 end_page, u8 *buf, unsigned int *index,
- unsigned int *offset)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 page_addr, val, data[16];
- u8 *ptr;
-
- if (!start_page) {
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 7);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(old_blk >> 8);
- data[3] = (u8)old_blk;
- data[4] = 0x80;
- data[5] = 0;
- data[6] = 0xEF;
- data[7] = 0xFF;
-
- retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT,
- data, 8);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1,
- NO_WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, (6 + MS_EXTRA_SIZE));
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(new_blk >> 8);
- data[3] = (u8)new_blk;
- if ((end_page - start_page) == 1)
- data[4] = 0x20;
- else
- data[4] = 0;
-
- data[5] = start_page;
- data[6] = 0xF8;
- data[7] = 0xFF;
- data[8] = (u8)(log_blk >> 8);
- data[9] = (u8)log_blk;
-
- for (i = 0x0A; i < 0x10; i++)
- data[i] = 0xFF;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, WRITE_REG, 6 + MS_EXTRA_SIZE,
- NO_WAIT_INT, data, 16);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ptr = buf;
- for (page_addr = start_page; page_addr < end_page; page_addr++) {
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
- if (val & INT_REG_ERR) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- if (!(val & INT_REG_BREQ)) {
- ms_set_err_code(chip, MS_BREQ_ERROR);
- return STATUS_FAIL;
- }
-
- udelay(30);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC,
- 0xFF, WRITE_PAGE_DATA);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG,
- 0xFF, WAIT_INT);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, RING_BUFFER);
-
- trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
- MS_TRANSFER_START | MS_TM_NORMAL_WRITE);
- rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, 512,
- scsi_sg_count(chip->srb),
- index, offset,
- DMA_TO_DEVICE,
- chip->ms_timeout);
- if (retval < 0) {
- ms_set_err_code(chip, MS_TO_ERROR);
- rtsx_clear_ms_error(chip);
-
- if (retval == -ETIMEDOUT)
- return STATUS_TIMEDOUT;
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if ((end_page - start_page) == 1) {
- if (!(val & INT_REG_CED)) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- } else {
- if (page_addr == (end_page - 1)) {
- if (!(val & INT_REG_CED)) {
- retval = ms_send_cmd(chip, BLOCK_END,
- WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, GET_INT, 1,
- NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- if (page_addr == (end_page - 1) ||
- page_addr == ms_card->page_off) {
- if (!(val & INT_REG_CED)) {
- ms_set_err_code(chip,
- MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
- }
-
- if (scsi_sg_count(chip->srb) == 0)
- ptr += 512;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
- u16 log_blk, u8 page_off)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, seg_no;
-
- retval = ms_copy_page(chip, old_blk, new_blk, log_blk,
- page_off, ms_card->page_off + 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- seg_no = old_blk >> 9;
-
- if (MS_TST_BAD_BLOCK_FLG(ms_card)) {
- MS_CLR_BAD_BLOCK_FLG(ms_card);
- ms_set_bad_block(chip, old_blk);
- } else {
- retval = ms_erase_block(chip, old_blk);
- if (retval == STATUS_SUCCESS)
- ms_set_unused_block(chip, old_blk);
- }
-
- ms_set_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no], new_blk);
-
- return STATUS_SUCCESS;
-}
-
-static int ms_prepare_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
- u16 log_blk, u8 start_page)
-{
- int retval;
-
- if (start_page) {
- retval = ms_copy_page(chip, old_blk, new_blk, log_blk,
- 0, start_page);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-#ifdef MS_DELAY_WRITE
-int ms_delay_write(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct ms_delay_write_tag *delay_write = &ms_card->delay_write;
- int retval;
-
- if (delay_write->delay_write_flag) {
- retval = ms_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- delay_write->delay_write_flag = 0;
- retval = ms_finish_write(chip,
- delay_write->old_phyblock,
- delay_write->new_phyblock,
- delay_write->logblock,
- delay_write->pageoff);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-#endif
-
-static inline void ms_rw_fail(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- else
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-}
-
-static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 start_sector, u16 sector_cnt)
-{
- struct ms_info *ms_card = &chip->ms_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval, seg_no;
- unsigned int index = 0, offset = 0;
- u16 old_blk = 0, new_blk = 0, log_blk, total_sec_cnt = sector_cnt;
- u8 start_page, end_page = 0, page_cnt;
- u8 *ptr;
-#ifdef MS_DELAY_WRITE
- struct ms_delay_write_tag *delay_write = &ms_card->delay_write;
-#endif
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- ms_card->cleanup_counter = 0;
-
- ptr = (u8 *)scsi_sglist(srb);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS) {
- ms_rw_fail(srb, chip);
- return STATUS_FAIL;
- }
-
- log_blk = (u16)(start_sector >> ms_card->block_shift);
- start_page = (u8)(start_sector & ms_card->page_off);
-
- for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; seg_no++) {
- if (log_blk < ms_start_idx[seg_no + 1])
- break;
- }
-
- if (ms_card->segment[seg_no].build_flag == 0) {
- retval = ms_build_l2p_tbl(chip, seg_no);
- if (retval != STATUS_SUCCESS) {
- chip->card_fail |= MS_CARD;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
-#ifdef MS_DELAY_WRITE
- if (delay_write->delay_write_flag &&
- delay_write->logblock == log_blk &&
- start_page > delay_write->pageoff) {
- delay_write->delay_write_flag = 0;
- retval = ms_copy_page(chip,
- delay_write->old_phyblock,
- delay_write->new_phyblock,
- log_blk,
- delay_write->pageoff, start_page);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
- old_blk = delay_write->old_phyblock;
- new_blk = delay_write->new_phyblock;
- } else if (delay_write->delay_write_flag &&
- (delay_write->logblock == log_blk) &&
- (start_page == delay_write->pageoff)) {
- delay_write->delay_write_flag = 0;
- old_blk = delay_write->old_phyblock;
- new_blk = delay_write->new_phyblock;
- } else {
- retval = ms_delay_write(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-#endif
- old_blk = ms_get_l2p_tbl
- (chip, seg_no,
- log_blk - ms_start_idx[seg_no]);
- new_blk = ms_get_unused_block(chip, seg_no);
- if (old_blk == 0xFFFF || new_blk == 0xFFFF) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-
- retval = ms_prepare_write(chip, old_blk, new_blk,
- log_blk, start_page);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, MS_CARD) !=
- STATUS_SUCCESS) {
- set_sense_type
- (chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-#ifdef MS_DELAY_WRITE
- }
-#endif
- } else {
-#ifdef MS_DELAY_WRITE
- retval = ms_delay_write(chip);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return STATUS_FAIL;
- }
-#endif
- old_blk = ms_get_l2p_tbl(chip, seg_no,
- log_blk - ms_start_idx[seg_no]);
- if (old_blk == 0xFFFF) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return STATUS_FAIL;
- }
- }
-
- dev_dbg(rtsx_dev(chip), "seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n",
- seg_no, old_blk, new_blk);
-
- while (total_sec_cnt) {
- if ((start_page + total_sec_cnt) > (ms_card->page_off + 1))
- end_page = ms_card->page_off + 1;
- else
- end_page = start_page + (u8)total_sec_cnt;
-
- page_cnt = end_page - start_page;
-
- dev_dbg(rtsx_dev(chip), "start_page = %d, end_page = %d, page_cnt = %d\n",
- start_page, end_page, page_cnt);
-
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- retval = ms_read_multiple_pages(chip,
- old_blk, log_blk,
- start_page, end_page,
- ptr, &index, &offset);
- } else {
- retval = ms_write_multiple_pages(chip, old_blk, new_blk,
- log_blk, start_page,
- end_page, ptr, &index,
- &offset);
- }
-
- if (retval != STATUS_SUCCESS) {
- toggle_gpio(chip, 1);
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- ms_rw_fail(srb, chip);
- return STATUS_FAIL;
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
- if (end_page == (ms_card->page_off + 1)) {
- retval = ms_erase_block(chip, old_blk);
- if (retval == STATUS_SUCCESS)
- ms_set_unused_block(chip, old_blk);
-
- ms_set_l2p_tbl(chip, seg_no,
- log_blk - ms_start_idx[seg_no],
- new_blk);
- }
- }
-
- total_sec_cnt -= page_cnt;
- if (scsi_sg_count(srb) == 0)
- ptr += page_cnt * 512;
-
- if (total_sec_cnt == 0)
- break;
-
- log_blk++;
-
- for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1;
- seg_no++) {
- if (log_blk < ms_start_idx[seg_no + 1])
- break;
- }
-
- if (ms_card->segment[seg_no].build_flag == 0) {
- retval = ms_build_l2p_tbl(chip, seg_no);
- if (retval != STATUS_SUCCESS) {
- chip->card_fail |= MS_CARD;
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- }
-
- old_blk = ms_get_l2p_tbl(chip, seg_no,
- log_blk - ms_start_idx[seg_no]);
- if (old_blk == 0xFFFF) {
- ms_rw_fail(srb, chip);
- return STATUS_FAIL;
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
- new_blk = ms_get_unused_block(chip, seg_no);
- if (new_blk == 0xFFFF) {
- ms_rw_fail(srb, chip);
- return STATUS_FAIL;
- }
- }
-
- dev_dbg(rtsx_dev(chip), "seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n",
- seg_no, old_blk, new_blk);
-
- start_page = 0;
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
- if (end_page < (ms_card->page_off + 1)) {
-#ifdef MS_DELAY_WRITE
- delay_write->delay_write_flag = 1;
- delay_write->old_phyblock = old_blk;
- delay_write->new_phyblock = new_blk;
- delay_write->logblock = log_blk;
- delay_write->pageoff = end_page;
-#else
- retval = ms_finish_write(chip, old_blk, new_blk,
- log_blk, end_page);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, MS_CARD) !=
- STATUS_SUCCESS) {
- set_sense_type
- (chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
-
- ms_rw_fail(srb, chip);
- return STATUS_FAIL;
- }
-#endif
- }
- }
-
- scsi_set_resid(srb, 0);
-
- return STATUS_SUCCESS;
-}
-
-int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 start_sector, u16 sector_cnt)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-
- if (CHK_MSPRO(ms_card))
- retval = mspro_rw_multi_sector(srb, chip, start_sector,
- sector_cnt);
- else
- retval = ms_rw_multi_sector(srb, chip, start_sector,
- sector_cnt);
-
- return retval;
-}
-
-void ms_free_l2p_tbl(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int i = 0;
-
- if (ms_card->segment) {
- for (i = 0; i < ms_card->segment_cnt; i++) {
- vfree(ms_card->segment[i].l2p_table);
- ms_card->segment[i].l2p_table = NULL;
- vfree(ms_card->segment[i].free_table);
- ms_card->segment[i].free_table = NULL;
- }
- vfree(ms_card->segment);
- ms_card->segment = NULL;
- }
-}
-
-#ifdef SUPPORT_MAGIC_GATE
-
-#ifdef READ_BYTES_WAIT_INT
-static int ms_poll_int(struct rtsx_chip *chip)
-{
- int retval;
- u8 val;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANS_CFG, MS_INT_CED, MS_INT_CED);
-
- retval = rtsx_send_cmd(chip, MS_CARD, 5000);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- val = *rtsx_get_cmd_data(chip);
- if (val & MS_INT_ERR)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-#endif
-
-#ifdef MS_SAMPLE_INT_ERR
-static int check_ms_err(struct rtsx_chip *chip)
-{
- int retval;
- u8 val;
-
- retval = rtsx_read_register(chip, MS_TRANSFER, &val);
- if (retval != STATUS_SUCCESS)
- return 1;
- if (val & MS_TRANSFER_ERR)
- return 1;
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
- if (retval != STATUS_SUCCESS)
- return 1;
-
- if (val & (MS_INT_ERR | MS_INT_CMDNK))
- return 1;
-
- return 0;
-}
-#else
-static int check_ms_err(struct rtsx_chip *chip)
-{
- int retval;
- u8 val;
-
- retval = rtsx_read_register(chip, MS_TRANSFER, &val);
- if (retval != STATUS_SUCCESS)
- return 1;
- if (val & MS_TRANSFER_ERR)
- return 1;
-
- return 0;
-}
-#endif
-
-static int mg_send_ex_cmd(struct rtsx_chip *chip, u8 cmd, u8 entry_num)
-{
- int retval, i;
- u8 data[8];
-
- data[0] = cmd;
- data[1] = 0;
- data[2] = 0;
- data[3] = 0;
- data[4] = 0;
- data[5] = 0;
- data[6] = entry_num;
- data[7] = 0;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7, WAIT_INT,
- data, 8);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- if (check_ms_err(chip)) {
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type,
- u8 mg_entry_num)
-{
- int retval;
- u8 buf[6];
-
- if (type == 0)
- retval = ms_set_rw_reg_addr(chip, 0, 0, PRO_TPC_PARM, 1);
- else
- retval = ms_set_rw_reg_addr(chip, 0, 0, PRO_DATA_COUNT1, 6);
-
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf[0] = 0;
- buf[1] = 0;
- if (type == 1) {
- buf[2] = 0;
- buf[3] = 0;
- buf[4] = 0;
- buf[5] = mg_entry_num;
- }
- retval = ms_write_bytes(chip, PRO_WRITE_REG, (type == 0) ? 1 : 6,
- NO_WAIT_INT, buf, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- int i;
- unsigned int lun = SCSI_LUN(srb);
- u8 buf1[32], buf2[12];
-
- if (scsi_bufflen(srb) < 12) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return STATUS_FAIL;
- }
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = mg_send_ex_cmd(chip, MG_SET_LID, 0);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
- return STATUS_FAIL;
- }
-
- memset(buf1, 0, 32);
- rtsx_stor_get_xfer_buf(buf2, min_t(int, 12, scsi_bufflen(srb)), srb);
- for (i = 0; i < 8; i++)
- buf1[8 + i] = buf2[4 + i];
-
- retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT,
- buf1, 32);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
- return STATUS_FAIL;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- int bufflen;
- unsigned int lun = SCSI_LUN(srb);
- u8 *buf = NULL;
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf = kmalloc(1540, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- buf[0] = 0x04;
- buf[1] = 0x1A;
- buf[2] = 0x00;
- buf[3] = 0x00;
-
- retval = mg_send_ex_cmd(chip, MG_GET_LEKB, 0);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- goto free_buffer;
- }
-
- retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
- 3, WAIT_INT, 0, 0, buf + 4, 1536);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- rtsx_clear_ms_error(chip);
- goto free_buffer;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- rtsx_clear_ms_error(chip);
- retval = STATUS_FAIL;
- goto free_buffer;
- }
-
- bufflen = min_t(int, 1052, scsi_bufflen(srb));
- rtsx_stor_set_xfer_buf(buf, bufflen, srb);
-
-free_buffer:
- kfree(buf);
- return retval;
-}
-
-int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- int bufflen;
- int i;
- unsigned int lun = SCSI_LUN(srb);
- u8 buf[32];
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = mg_send_ex_cmd(chip, MG_GET_ID, 0);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT,
- buf, 32);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return STATUS_FAIL;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
-
- memcpy(ms_card->magic_gate_id, buf, 16);
-
-#ifdef READ_BYTES_WAIT_INT
- retval = ms_poll_int(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return STATUS_FAIL;
- }
-#endif
-
- retval = mg_send_ex_cmd(chip, MG_SET_RD, 0);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return STATUS_FAIL;
- }
-
- bufflen = min_t(int, 12, scsi_bufflen(srb));
- rtsx_stor_get_xfer_buf(buf, bufflen, srb);
-
- for (i = 0; i < 8; i++)
- buf[i] = buf[4 + i];
-
- for (i = 0; i < 24; i++)
- buf[8 + i] = 0;
-
- retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA,
- 32, WAIT_INT, buf, 32);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return STATUS_FAIL;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
-
- ms_card->mg_auth = 0;
-
- return STATUS_SUCCESS;
-}
-
-int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- int bufflen;
- unsigned int lun = SCSI_LUN(srb);
- u8 buf1[32], buf2[36];
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT,
- buf1, 32);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- return STATUS_FAIL;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
-
- buf2[0] = 0x00;
- buf2[1] = 0x22;
- buf2[2] = 0x00;
- buf2[3] = 0x00;
-
- memcpy(buf2 + 4, ms_card->magic_gate_id, 16);
- memcpy(buf2 + 20, buf1, 16);
-
- bufflen = min_t(int, 36, scsi_bufflen(srb));
- rtsx_stor_set_xfer_buf(buf2, bufflen, srb);
-
-#ifdef READ_BYTES_WAIT_INT
- retval = ms_poll_int(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- return STATUS_FAIL;
- }
-#endif
-
- return STATUS_SUCCESS;
-}
-
-int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- int i;
- int bufflen;
- unsigned int lun = SCSI_LUN(srb);
- u8 buf[32];
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- return STATUS_FAIL;
- }
-
- bufflen = min_t(int, 12, scsi_bufflen(srb));
- rtsx_stor_get_xfer_buf(buf, bufflen, srb);
-
- for (i = 0; i < 8; i++)
- buf[i] = buf[4 + i];
-
- for (i = 0; i < 24; i++)
- buf[8 + i] = 0;
-
- retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT,
- buf, 32);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- return STATUS_FAIL;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
-
- ms_card->mg_auth = 1;
-
- return STATUS_SUCCESS;
-}
-
-int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- int bufflen;
- unsigned int lun = SCSI_LUN(srb);
- u8 *buf = NULL;
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf = kmalloc(1028, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- buf[0] = 0x04;
- buf[1] = 0x02;
- buf[2] = 0x00;
- buf[3] = 0x00;
-
- retval = mg_send_ex_cmd(chip, MG_GET_IBD, ms_card->mg_entry_num);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- goto free_buffer;
- }
-
- retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
- 2, WAIT_INT, 0, 0, buf + 4, 1024);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- rtsx_clear_ms_error(chip);
- goto free_buffer;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- rtsx_clear_ms_error(chip);
- retval = STATUS_FAIL;
- goto free_buffer;
- }
-
- bufflen = min_t(int, 1028, scsi_bufflen(srb));
- rtsx_stor_set_xfer_buf(buf, bufflen, srb);
-
-free_buffer:
- kfree(buf);
- return retval;
-}
-
-int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- int bufflen;
-#ifdef MG_SET_ICV_SLOW
- int i;
-#endif
- unsigned int lun = SCSI_LUN(srb);
- u8 *buf = NULL;
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf = kmalloc(1028, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- bufflen = min_t(int, 1028, scsi_bufflen(srb));
- rtsx_stor_get_xfer_buf(buf, bufflen, srb);
-
- retval = mg_send_ex_cmd(chip, MG_SET_IBD, ms_card->mg_entry_num);
- if (retval != STATUS_SUCCESS) {
- if (ms_card->mg_auth == 0) {
- if ((buf[5] & 0xC0) != 0)
- set_sense_type
- (chip, lun,
- SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
- else
- set_sense_type(chip, lun,
- SENSE_TYPE_MG_WRITE_ERR);
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
- }
- goto set_ICV_finish;
- }
-
-#ifdef MG_SET_ICV_SLOW
- for (i = 0; i < 2; i++) {
- udelay(50);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC,
- 0xFF, PRO_WRITE_LONG_DATA);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, WAIT_INT);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, RING_BUFFER);
-
- trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
- MS_TRANSFER_START | MS_TM_NORMAL_WRITE);
- rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data(chip, MS_CARD, buf + 4 + i * 512,
- 512, 0, DMA_TO_DEVICE, 3000);
- if (retval < 0 || check_ms_err(chip)) {
- rtsx_clear_ms_error(chip);
- if (ms_card->mg_auth == 0) {
- if ((buf[5] & 0xC0) != 0)
- set_sense_type
- (chip, lun,
- SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
- else
- set_sense_type(chip, lun,
- SENSE_TYPE_MG_WRITE_ERR);
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MG_WRITE_ERR);
- }
- retval = STATUS_FAIL;
- goto set_ICV_finish;
- }
- }
-#else
- retval = ms_transfer_data(chip, MS_TM_AUTO_WRITE, PRO_WRITE_LONG_DATA,
- 2, WAIT_INT, 0, 0, buf + 4, 1024);
- if (retval != STATUS_SUCCESS || check_ms_err(chip)) {
- rtsx_clear_ms_error(chip);
- if (ms_card->mg_auth == 0) {
- if ((buf[5] & 0xC0) != 0)
- set_sense_type
- (chip, lun,
- SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
- else
- set_sense_type(chip, lun,
- SENSE_TYPE_MG_WRITE_ERR);
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
- }
- goto set_ICV_finish;
- }
-#endif
-
-set_ICV_finish:
- kfree(buf);
- return retval;
-}
-
-#endif /* SUPPORT_MAGIC_GATE */
-
-void ms_cleanup_work(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
-
- if (CHK_MSPRO(ms_card)) {
- if (ms_card->seq_mode) {
- dev_dbg(rtsx_dev(chip), "MS Pro: stop transmission\n");
- mspro_stop_seq_mode(chip);
- ms_card->cleanup_counter = 0;
- }
- if (CHK_MSHG(ms_card)) {
- rtsx_write_register(chip, MS_CFG,
- MS_2K_SECTOR_MODE, 0x00);
- }
- }
-#ifdef MS_DELAY_WRITE
- else if ((!CHK_MSPRO(ms_card)) &&
- ms_card->delay_write.delay_write_flag) {
- dev_dbg(rtsx_dev(chip), "MS: delay write\n");
- ms_delay_write(chip);
- ms_card->cleanup_counter = 0;
- }
-#endif
-}
-
-int ms_power_off_card3v3(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = disable_card_clock(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (chip->asic_code) {
- retval = ms_pull_ctl_disable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL,
- FPGA_MS_PULL_CTL_BIT | 0x20,
- FPGA_MS_PULL_CTL_BIT);
- if (retval)
- return retval;
- }
- retval = rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
- if (retval)
- return retval;
-
- if (!chip->ft2_fast_mode) {
- retval = card_power_off(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int release_ms_card(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-
-#ifdef MS_DELAY_WRITE
- ms_card->delay_write.delay_write_flag = 0;
-#endif
- ms_card->pro_under_formatting = 0;
-
- chip->card_ready &= ~MS_CARD;
- chip->card_fail &= ~MS_CARD;
- chip->card_wp &= ~MS_CARD;
-
- ms_free_l2p_tbl(chip);
-
- memset(ms_card->raw_sys_info, 0, 96);
-#ifdef SUPPORT_PCGL_1P18
- memset(ms_card->raw_model_name, 0, 48);
-#endif
-
- retval = ms_power_off_card3v3(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts5208/ms.h b/drivers/staging/rts5208/ms.h
deleted file mode 100644
index 33bda9ce36b6..000000000000
--- a/drivers/staging/rts5208/ms.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_MS_H
-#define __REALTEK_RTSX_MS_H
-
-#define MS_DELAY_WRITE
-
-#define MS_MAX_RETRY_COUNT 3
-
-#define MS_EXTRA_SIZE 0x9
-
-#define WRT_PRTCT 0x01
-
-/* Error Code */
-#define MS_NO_ERROR 0x00
-#define MS_CRC16_ERROR 0x80
-#define MS_TO_ERROR 0x40
-#define MS_NO_CARD 0x20
-#define MS_NO_MEMORY 0x10
-#define MS_CMD_NK 0x08
-#define MS_FLASH_READ_ERROR 0x04
-#define MS_FLASH_WRITE_ERROR 0x02
-#define MS_BREQ_ERROR 0x01
-#define MS_NOT_FOUND 0x03
-
-/* Transfer Protocol Command */
-#define READ_PAGE_DATA 0x02
-#define READ_REG 0x04
-#define GET_INT 0x07
-#define WRITE_PAGE_DATA 0x0D
-#define WRITE_REG 0x0B
-#define SET_RW_REG_ADRS 0x08
-#define SET_CMD 0x0E
-
-#define PRO_READ_LONG_DATA 0x02
-#define PRO_READ_SHORT_DATA 0x03
-#define PRO_READ_REG 0x04
-#define PRO_READ_QUAD_DATA 0x05
-#define PRO_GET_INT 0x07
-#define PRO_WRITE_LONG_DATA 0x0D
-#define PRO_WRITE_SHORT_DATA 0x0C
-#define PRO_WRITE_QUAD_DATA 0x0A
-#define PRO_WRITE_REG 0x0B
-#define PRO_SET_RW_REG_ADRS 0x08
-#define PRO_SET_CMD 0x0E
-#define PRO_EX_SET_CMD 0x09
-
-#ifdef SUPPORT_MAGIC_GATE
-
-#define MG_GET_ID 0x40
-#define MG_SET_LID 0x41
-#define MG_GET_LEKB 0x42
-#define MG_SET_RD 0x43
-#define MG_MAKE_RMS 0x44
-#define MG_MAKE_KSE 0x45
-#define MG_SET_IBD 0x46
-#define MG_GET_IBD 0x47
-
-#endif
-
-#ifdef XC_POWERCLASS
-#define XC_CHG_POWER 0x16
-#endif
-
-#define BLOCK_READ 0xAA
-#define BLOCK_WRITE 0x55
-#define BLOCK_END 0x33
-#define BLOCK_ERASE 0x99
-#define FLASH_STOP 0xCC
-
-#define SLEEP 0x5A
-#define CLEAR_BUF 0xC3
-#define MS_RESET 0x3C
-
-#define PRO_READ_DATA 0x20
-#define PRO_WRITE_DATA 0x21
-#define PRO_READ_ATRB 0x24
-#define PRO_STOP 0x25
-#define PRO_ERASE 0x26
-#define PRO_READ_2K_DATA 0x27
-#define PRO_WRITE_2K_DATA 0x28
-
-#define PRO_FORMAT 0x10
-#define PRO_SLEEP 0x11
-
-#define INT_REG 0x01
-#define STATUS_REG0 0x02
-#define STATUS_REG1 0x03
-
-#define SYSTEM_PARAM 0x10
-#define BLOCK_ADRS 0x11
-#define CMD_PARM 0x14
-#define PAGE_ADRS 0x15
-
-#define OVERWRITE_FLAG 0x16
-#define MANAGEMEN_FLAG 0x17
-#define LOGICAL_ADRS 0x18
-#define RESERVE_AREA 0x1A
-
-#define PRO_INT_REG 0x01
-#define PRO_STATUS_REG 0x02
-#define PRO_TYPE_REG 0x04
-#define PRO_IF_mode_REG 0x05
-#define PRO_CATEGORY_REG 0x06
-#define PRO_CLASS_REG 0x07
-
-#define PRO_SYSTEM_PARAM 0x10
-#define PRO_DATA_COUNT1 0x11
-#define PRO_DATA_COUNT0 0x12
-#define PRO_DATA_ADDR3 0x13
-#define PRO_DATA_ADDR2 0x14
-#define PRO_DATA_ADDR1 0x15
-#define PRO_DATA_ADDR0 0x16
-
-#define PRO_TPC_PARM 0x17
-#define PRO_CMD_PARM 0x18
-
-#define INT_REG_CED 0x80
-#define INT_REG_ERR 0x40
-#define INT_REG_BREQ 0x20
-#define INT_REG_CMDNK 0x01
-
-#define BLOCK_BOOT 0xC0
-#define BLOCK_OK 0x80
-#define PAGE_OK 0x60
-#define DATA_COMPL 0x10
-
-#define NOT_BOOT_BLOCK 0x4
-#define NOT_TRANSLATION_TABLE 0x8
-
-#define HEADER_ID0 PPBUF_BASE2
-#define HEADER_ID1 (PPBUF_BASE2 + 1)
-#define DISABLED_BLOCK0 (PPBUF_BASE2 + 0x170 + 4)
-#define DISABLED_BLOCK1 (PPBUF_BASE2 + 0x170 + 5)
-#define DISABLED_BLOCK2 (PPBUF_BASE2 + 0x170 + 6)
-#define DISABLED_BLOCK3 (PPBUF_BASE2 + 0x170 + 7)
-#define BLOCK_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 2)
-#define BLOCK_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 3)
-#define BLOCK_COUNT_0 (PPBUF_BASE2 + 0x1a0 + 4)
-#define BLOCK_COUNT_1 (PPBUF_BASE2 + 0x1a0 + 5)
-#define EBLOCK_COUNT_0 (PPBUF_BASE2 + 0x1a0 + 6)
-#define EBLOCK_COUNT_1 (PPBUF_BASE2 + 0x1a0 + 7)
-#define PAGE_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 8)
-#define PAGE_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 9)
-
-#define MS_device_type (PPBUF_BASE2 + 0x1D8)
-
-#define MS_4bit_support (PPBUF_BASE2 + 0x1D3)
-
-#define set_PS_NG 1
-#define set_PS_error 0
-
-#define PARALLEL_8BIT_IF 0x40
-#define PARALLEL_4BIT_IF 0x00
-#define SERIAL_IF 0x80
-
-#define BUF_FULL 0x10
-#define BUF_EMPTY 0x20
-
-#define MEDIA_BUSY 0x80
-#define FLASH_BUSY 0x40
-#define DATA_ERROR 0x20
-#define STS_UCDT 0x10
-#define EXTRA_ERROR 0x08
-#define STS_UCEX 0x04
-#define FLAG_ERROR 0x02
-#define STS_UCFG 0x01
-
-#define MS_SHORT_DATA_LEN 32
-
-#define FORMAT_SUCCESS 0
-#define FORMAT_FAIL 1
-#define FORMAT_IN_PROGRESS 2
-
-#define MS_SET_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag |= 0x80)
-#define MS_CLR_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag &= 0x7F)
-#define MS_TST_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag & 0x80)
-
-void mspro_polling_format_status(struct rtsx_chip *chip);
-
-void mspro_stop_seq_mode(struct rtsx_chip *chip);
-int reset_ms_card(struct rtsx_chip *chip);
-int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 start_sector, u16 sector_cnt);
-int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- int short_data_len, bool quick_format);
-void ms_free_l2p_tbl(struct rtsx_chip *chip);
-void ms_cleanup_work(struct rtsx_chip *chip);
-int ms_power_off_card3v3(struct rtsx_chip *chip);
-int release_ms_card(struct rtsx_chip *chip);
-#ifdef MS_DELAY_WRITE
-int ms_delay_write(struct rtsx_chip *chip);
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
-int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-#endif
-
-#endif /* __REALTEK_RTSX_MS_H */
diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c
deleted file mode 100644
index c4f54c311d05..000000000000
--- a/drivers/staging/rts5208/rtsx.c
+++ /dev/null
@@ -1,987 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-
-#include "rtsx.h"
-#include "ms.h"
-#include "sd.h"
-#include "xd.h"
-
-MODULE_DESCRIPTION("Realtek PCI-Express card reader rts5208/rts5288 driver");
-MODULE_LICENSE("GPL");
-
-static unsigned int delay_use = 1;
-module_param(delay_use, uint, 0644);
-MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
-
-static int ss_en;
-module_param(ss_en, int, 0644);
-MODULE_PARM_DESC(ss_en, "enable selective suspend");
-
-static int ss_interval = 50;
-module_param(ss_interval, int, 0644);
-MODULE_PARM_DESC(ss_interval, "Interval to enter ss state in seconds");
-
-static int auto_delink_en;
-module_param(auto_delink_en, int, 0644);
-MODULE_PARM_DESC(auto_delink_en, "enable auto delink");
-
-static unsigned char aspm_l0s_l1_en;
-module_param(aspm_l0s_l1_en, byte, 0644);
-MODULE_PARM_DESC(aspm_l0s_l1_en, "enable device aspm");
-
-static int msi_en;
-module_param(msi_en, int, 0644);
-MODULE_PARM_DESC(msi_en, "enable msi");
-
-static irqreturn_t rtsx_interrupt(int irq, void *dev_id);
-
-/***********************************************************************
- * Host functions
- ***********************************************************************/
-
-static const char *host_info(struct Scsi_Host *host)
-{
- return "SCSI emulation for PCI-Express Mass Storage devices";
-}
-
-static int slave_alloc(struct scsi_device *sdev)
-{
- /*
- * Set the INQUIRY transfer length to 36. We don't use any of
- * the extra data and many devices choke if asked for more or
- * less than 36 bytes.
- */
- sdev->inquiry_len = 36;
- return 0;
-}
-
-static int slave_configure(struct scsi_device *sdev)
-{
- /* Set the SCSI level to at least 2. We'll leave it at 3 if that's
- * what is originally reported. We need this to avoid confusing
- * the SCSI layer with devices that report 0 or 1, but need 10-byte
- * commands (ala ATAPI devices behind certain bridges, or devices
- * which simply have broken INQUIRY data).
- *
- * NOTE: This means /dev/sg programs (ala cdrecord) will get the
- * actual information. This seems to be the preference for
- * programs like that.
- *
- * NOTE: This also means that /proc/scsi/scsi and sysfs may report
- * the actual value or the modified one, depending on where the
- * data comes from.
- */
- if (sdev->scsi_level < SCSI_2) {
- sdev->scsi_level = SCSI_2;
- sdev->sdev_target->scsi_level = SCSI_2;
- }
-
- return 0;
-}
-
-/***********************************************************************
- * /proc/scsi/ functions
- ***********************************************************************/
-
-/* we use this macro to help us write into the buffer */
-#undef SPRINTF
-#define SPRINTF(args...) \
- do { \
- if (pos < buffer + length) \
- pos += sprintf(pos, ## args); \
- } while (0)
-
-/* queue a command */
-/* This is always called with spin_lock_irq(host->host_lock) held */
-static int queuecommand_lck(struct scsi_cmnd *srb)
-{
- void (*done)(struct scsi_cmnd *) = scsi_done;
- struct rtsx_dev *dev = host_to_rtsx(srb->device->host);
- struct rtsx_chip *chip = dev->chip;
-
- /* check for state-transition errors */
- if (chip->srb) {
- dev_err(&dev->pci->dev, "Error: chip->srb = %p\n",
- chip->srb);
- return SCSI_MLQUEUE_HOST_BUSY;
- }
-
- /* fail the command if we are disconnecting */
- if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
- dev_info(&dev->pci->dev, "Fail command during disconnect\n");
- srb->result = DID_NO_CONNECT << 16;
- done(srb);
- return 0;
- }
-
- /* enqueue the command and wake up the control thread */
- chip->srb = srb;
- complete(&dev->cmnd_ready);
-
- return 0;
-}
-
-static DEF_SCSI_QCMD(queuecommand)
-
-/***********************************************************************
- * Error handling functions
- ***********************************************************************/
-
-/* Command timeout and abort */
-static int command_abort(struct scsi_cmnd *srb)
-{
- struct Scsi_Host *host = srb->device->host;
- struct rtsx_dev *dev = host_to_rtsx(host);
- struct rtsx_chip *chip = dev->chip;
-
- spin_lock_irq(host->host_lock);
-
- /* Is this command still active? */
- if (chip->srb != srb) {
- spin_unlock_irq(host->host_lock);
- dev_info(&dev->pci->dev, "-- nothing to abort\n");
- return FAILED;
- }
-
- rtsx_set_stat(chip, RTSX_STAT_ABORT);
-
- spin_unlock_irq(host->host_lock);
-
- /* Wait for the aborted command to finish */
- wait_for_completion(&dev->notify);
-
- return SUCCESS;
-}
-
-/*
- * This invokes the transport reset mechanism to reset the state of the
- * device
- */
-static int device_reset(struct scsi_cmnd *srb)
-{
- return SUCCESS;
-}
-
-/*
- * this defines our host template, with which we'll allocate hosts
- */
-
-static const struct scsi_host_template rtsx_host_template = {
- /* basic userland interface stuff */
- .name = CR_DRIVER_NAME,
- .proc_name = CR_DRIVER_NAME,
- .info = host_info,
-
- /* command interface -- queued only */
- .queuecommand = queuecommand,
-
- /* error and abort handlers */
- .eh_abort_handler = command_abort,
- .eh_device_reset_handler = device_reset,
-
- /* queue commands only, only one command per LUN */
- .can_queue = 1,
-
- /* unknown initiator id */
- .this_id = -1,
-
- .slave_alloc = slave_alloc,
- .slave_configure = slave_configure,
-
- /* lots of sg segments can be handled */
- .sg_tablesize = SG_ALL,
-
- /* limit the total size of a transfer to 120 KB */
- .max_sectors = 240,
-
- /*
- * Scatter-gather buffers (all but the last) must have a length
- * divisible by the bulk maxpacket size. Otherwise a data packet
- * would end up being short, causing a premature end to the data
- * transfer. Since high-speed bulk pipes have a maxpacket size
- * of 512, we'll use that as the scsi device queue's DMA alignment
- * mask. Guaranteeing proper alignment of the first buffer will
- * have the desired effect because, except at the beginning and
- * the end, scatter-gather buffers follow page boundaries.
- */
- .dma_alignment = 511,
-
- /* emulated HBA */
- .emulated = 1,
-
- /* we do our own delay after a device or bus reset */
- .skip_settle_delay = 1,
-
- /* module management */
- .module = THIS_MODULE
-};
-
-static int rtsx_acquire_irq(struct rtsx_dev *dev)
-{
- struct rtsx_chip *chip = dev->chip;
-
- dev_info(&dev->pci->dev, "%s: chip->msi_en = %d, pci->irq = %d\n",
- __func__, chip->msi_en, dev->pci->irq);
-
- if (request_irq(dev->pci->irq, rtsx_interrupt,
- chip->msi_en ? 0 : IRQF_SHARED,
- CR_DRIVER_NAME, dev)) {
- dev_err(&dev->pci->dev,
- "rtsx: unable to grab IRQ %d, disabling device\n",
- dev->pci->irq);
- return -1;
- }
-
- dev->irq = dev->pci->irq;
- pci_intx(dev->pci, !chip->msi_en);
-
- return 0;
-}
-
-/*
- * power management
- */
-static int __maybe_unused rtsx_suspend(struct device *dev_d)
-{
- struct pci_dev *pci = to_pci_dev(dev_d);
- struct rtsx_dev *dev = pci_get_drvdata(pci);
- struct rtsx_chip *chip;
-
- if (!dev)
- return 0;
-
- /* lock the device pointers */
- mutex_lock(&dev->dev_mutex);
-
- chip = dev->chip;
-
- rtsx_do_before_power_down(chip, PM_S3);
-
- if (dev->irq >= 0) {
- free_irq(dev->irq, (void *)dev);
- dev->irq = -1;
- }
-
- if (chip->msi_en)
- pci_free_irq_vectors(pci);
-
- device_wakeup_enable(dev_d);
-
- /* unlock the device pointers */
- mutex_unlock(&dev->dev_mutex);
-
- return 0;
-}
-
-static int __maybe_unused rtsx_resume(struct device *dev_d)
-{
- struct pci_dev *pci = to_pci_dev(dev_d);
- struct rtsx_dev *dev = pci_get_drvdata(pci);
- struct rtsx_chip *chip;
-
- if (!dev)
- return 0;
-
- chip = dev->chip;
-
- /* lock the device pointers */
- mutex_lock(&dev->dev_mutex);
-
- pci_set_master(pci);
-
- if (chip->msi_en) {
- if (pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) < 0)
- chip->msi_en = 0;
- }
-
- if (rtsx_acquire_irq(dev) < 0) {
- /* unlock the device pointers */
- mutex_unlock(&dev->dev_mutex);
- return -EIO;
- }
-
- rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 0x00);
- rtsx_init_chip(chip);
-
- /* unlock the device pointers */
- mutex_unlock(&dev->dev_mutex);
-
- return 0;
-}
-
-static void rtsx_shutdown(struct pci_dev *pci)
-{
- struct rtsx_dev *dev = pci_get_drvdata(pci);
- struct rtsx_chip *chip;
-
- if (!dev)
- return;
-
- chip = dev->chip;
-
- rtsx_do_before_power_down(chip, PM_S1);
-
- if (dev->irq >= 0) {
- free_irq(dev->irq, (void *)dev);
- dev->irq = -1;
- }
-
- if (chip->msi_en)
- pci_free_irq_vectors(pci);
-
- pci_disable_device(pci);
-}
-
-static int rtsx_control_thread(void *__dev)
-{
- struct rtsx_dev *dev = __dev;
- struct rtsx_chip *chip = dev->chip;
- struct Scsi_Host *host = rtsx_to_host(dev);
-
- for (;;) {
- if (wait_for_completion_interruptible(&dev->cmnd_ready))
- break;
-
- /* lock the device pointers */
- mutex_lock(&dev->dev_mutex);
-
- /* if the device has disconnected, we are free to exit */
- if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
- dev_info(&dev->pci->dev, "-- rtsx-control exiting\n");
- mutex_unlock(&dev->dev_mutex);
- break;
- }
-
- /* lock access to the state */
- spin_lock_irq(host->host_lock);
-
- /* has the command aborted ? */
- if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
- chip->srb->result = DID_ABORT << 16;
- goto skip_for_abort;
- }
-
- spin_unlock_irq(host->host_lock);
-
- /* reject the command if the direction indicator
- * is UNKNOWN
- */
- if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
- dev_err(&dev->pci->dev, "UNKNOWN data direction\n");
- chip->srb->result = DID_ERROR << 16;
- } else if (chip->srb->device->id) {
- /* reject if target != 0 or if LUN is higher than
- * the maximum known LUN
- */
- dev_err(&dev->pci->dev, "Bad target number (%d:%d)\n",
- chip->srb->device->id,
- (u8)chip->srb->device->lun);
- chip->srb->result = DID_BAD_TARGET << 16;
- } else if (chip->srb->device->lun > chip->max_lun) {
- dev_err(&dev->pci->dev, "Bad LUN (%d:%d)\n",
- chip->srb->device->id,
- (u8)chip->srb->device->lun);
- chip->srb->result = DID_BAD_TARGET << 16;
- } else {
- /* we've got a command, let's do it! */
- scsi_show_command(chip);
- rtsx_invoke_transport(chip->srb, chip);
- }
-
- /* lock access to the state */
- spin_lock_irq(host->host_lock);
-
- /* did the command already complete because of a disconnect? */
- if (!chip->srb)
- ; /* nothing to do */
-
- /* indicate that the command is done */
- else if (chip->srb->result != DID_ABORT << 16) {
- scsi_done(chip->srb);
- } else {
-skip_for_abort:
- dev_err(&dev->pci->dev, "scsi command aborted\n");
- }
-
- if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
- complete(&dev->notify);
-
- rtsx_set_stat(chip, RTSX_STAT_IDLE);
- }
-
- /* finished working on this command */
- chip->srb = NULL;
- spin_unlock_irq(host->host_lock);
-
- /* unlock the device pointers */
- mutex_unlock(&dev->dev_mutex);
- } /* for (;;) */
-
- /* notify the exit routine that we're actually exiting now
- *
- * complete()/wait_for_completion() is similar to up()/down(),
- * except that complete() is safe in the case where the structure
- * is getting deleted in a parallel mode of execution (i.e. just
- * after the down() -- that's necessary for the thread-shutdown
- * case.
- *
- * kthread_complete_and_exit() goes even further than this --
- * it is safe in the case that the thread of the caller is going away
- * (not just the structure) -- this is necessary for the module-remove
- * case. This is important in preemption kernels, which transfer the
- * flow of execution immediately upon a complete().
- */
- kthread_complete_and_exit(&dev->control_exit, 0);
-}
-
-static int rtsx_polling_thread(void *__dev)
-{
- struct rtsx_dev *dev = __dev;
- struct rtsx_chip *chip = dev->chip;
- struct sd_info *sd_card = &chip->sd_card;
- struct xd_info *xd_card = &chip->xd_card;
- struct ms_info *ms_card = &chip->ms_card;
-
- sd_card->cleanup_counter = 0;
- xd_card->cleanup_counter = 0;
- ms_card->cleanup_counter = 0;
-
- /* Wait until SCSI scan finished */
- wait_timeout((delay_use + 5) * 1000);
-
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(POLLING_INTERVAL));
-
- /* lock the device pointers */
- mutex_lock(&dev->dev_mutex);
-
- /* if the device has disconnected, we are free to exit */
- if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
- dev_info(&dev->pci->dev, "-- rtsx-polling exiting\n");
- mutex_unlock(&dev->dev_mutex);
- break;
- }
-
- mutex_unlock(&dev->dev_mutex);
-
- mspro_polling_format_status(chip);
-
- /* lock the device pointers */
- mutex_lock(&dev->dev_mutex);
-
- rtsx_polling_func(chip);
-
- /* unlock the device pointers */
- mutex_unlock(&dev->dev_mutex);
- }
-
- kthread_complete_and_exit(&dev->polling_exit, 0);
-}
-
-/*
- * interrupt handler
- */
-static irqreturn_t rtsx_interrupt(int irq, void *dev_id)
-{
- struct rtsx_dev *dev = dev_id;
- struct rtsx_chip *chip;
- int retval;
- u32 status;
-
- if (dev)
- chip = dev->chip;
- else
- return IRQ_NONE;
-
- if (!chip)
- return IRQ_NONE;
-
- spin_lock(&dev->reg_lock);
-
- retval = rtsx_pre_handle_interrupt(chip);
- if (retval == STATUS_FAIL) {
- spin_unlock(&dev->reg_lock);
- if (chip->int_reg == 0xFFFFFFFF)
- return IRQ_HANDLED;
- return IRQ_NONE;
- }
-
- status = chip->int_reg;
-
- if (dev->check_card_cd) {
- if (!(dev->check_card_cd & status)) {
- /* card not exist, return TRANS_RESULT_FAIL */
- dev->trans_result = TRANS_RESULT_FAIL;
- if (dev->done)
- complete(dev->done);
- goto exit;
- }
- }
-
- if (status & (NEED_COMPLETE_INT | DELINK_INT)) {
- if (status & (TRANS_FAIL_INT | DELINK_INT)) {
- if (status & DELINK_INT)
- RTSX_SET_DELINK(chip);
- dev->trans_result = TRANS_RESULT_FAIL;
- if (dev->done)
- complete(dev->done);
- } else if (status & TRANS_OK_INT) {
- dev->trans_result = TRANS_RESULT_OK;
- if (dev->done)
- complete(dev->done);
- } else if (status & DATA_DONE_INT) {
- dev->trans_result = TRANS_NOT_READY;
- if (dev->done && dev->trans_state == STATE_TRANS_SG)
- complete(dev->done);
- }
- }
-
-exit:
- spin_unlock(&dev->reg_lock);
- return IRQ_HANDLED;
-}
-
-/* Release all our dynamic resources */
-static void rtsx_release_resources(struct rtsx_dev *dev)
-{
- dev_info(&dev->pci->dev, "-- %s\n", __func__);
-
- /* Tell the control thread to exit. The SCSI host must
- * already have been removed so it won't try to queue
- * any more commands.
- */
- dev_info(&dev->pci->dev, "-- sending exit command to thread\n");
- complete(&dev->cmnd_ready);
- if (dev->ctl_thread)
- wait_for_completion(&dev->control_exit);
- if (dev->polling_thread)
- wait_for_completion(&dev->polling_exit);
-
- wait_timeout(200);
-
- if (dev->rtsx_resv_buf) {
- dev->chip->host_cmds_ptr = NULL;
- dev->chip->host_sg_tbl_ptr = NULL;
- }
-
- if (dev->irq > 0)
- free_irq(dev->irq, (void *)dev);
- if (dev->chip->msi_en)
- pci_free_irq_vectors(dev->pci);
- if (dev->remap_addr)
- iounmap(dev->remap_addr);
-
- rtsx_release_chip(dev->chip);
- kfree(dev->chip);
-}
-
-/*
- * First stage of disconnect processing: stop all commands and remove
- * the host
- */
-static void quiesce_and_remove_host(struct rtsx_dev *dev)
-{
- struct Scsi_Host *host = rtsx_to_host(dev);
- struct rtsx_chip *chip = dev->chip;
-
- /*
- * Prevent new transfers, stop the current command, and
- * interrupt a SCSI-scan or device-reset delay
- */
- mutex_lock(&dev->dev_mutex);
- spin_lock_irq(host->host_lock);
- rtsx_set_stat(chip, RTSX_STAT_DISCONNECT);
- spin_unlock_irq(host->host_lock);
- mutex_unlock(&dev->dev_mutex);
- wake_up(&dev->delay_wait);
- wait_for_completion(&dev->scanning_done);
-
- /* Wait some time to let other threads exist */
- wait_timeout(100);
-
- /*
- * queuecommand won't accept any new commands and the control
- * thread won't execute a previously-queued command. If there
- * is such a command pending, complete it with an error.
- */
- mutex_lock(&dev->dev_mutex);
- if (chip->srb) {
- chip->srb->result = DID_NO_CONNECT << 16;
- spin_lock_irq(host->host_lock);
- scsi_done(dev->chip->srb);
- chip->srb = NULL;
- spin_unlock_irq(host->host_lock);
- }
- mutex_unlock(&dev->dev_mutex);
-
- /* Now we own no commands so it's safe to remove the SCSI host */
- scsi_remove_host(host);
-}
-
-/* Second stage of disconnect processing: deallocate all resources */
-static void release_everything(struct rtsx_dev *dev)
-{
- rtsx_release_resources(dev);
-
- /*
- * Drop our reference to the host; the SCSI core will free it
- * when the refcount becomes 0.
- */
- scsi_host_put(rtsx_to_host(dev));
-}
-
-/* Thread to carry out delayed SCSI-device scanning */
-static int rtsx_scan_thread(void *__dev)
-{
- struct rtsx_dev *dev = __dev;
- struct rtsx_chip *chip = dev->chip;
-
- /* Wait for the timeout to expire or for a disconnect */
- if (delay_use > 0) {
- dev_info(&dev->pci->dev,
- "%s: waiting for device to settle before scanning\n",
- CR_DRIVER_NAME);
- wait_event_interruptible_timeout
- (dev->delay_wait,
- rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT),
- delay_use * HZ);
- }
-
- /* If the device is still connected, perform the scanning */
- if (!rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
- scsi_scan_host(rtsx_to_host(dev));
- dev_info(&dev->pci->dev, "%s: device scan complete\n",
- CR_DRIVER_NAME);
-
- /* Should we unbind if no devices were detected? */
- }
-
- kthread_complete_and_exit(&dev->scanning_done, 0);
-}
-
-static void rtsx_init_options(struct rtsx_chip *chip)
-{
- chip->vendor_id = chip->rtsx->pci->vendor;
- chip->product_id = chip->rtsx->pci->device;
- chip->adma_mode = 1;
- chip->lun_mc = 0;
- chip->driver_first_load = 1;
-#ifdef HW_AUTO_SWITCH_SD_BUS
- chip->sdio_in_charge = 0;
-#endif
-
- chip->mspro_formatter_enable = 1;
- chip->ignore_sd = 0;
- chip->use_hw_setting = 0;
- chip->lun_mode = DEFAULT_SINGLE;
- chip->auto_delink_en = auto_delink_en;
- chip->ss_en = ss_en;
- chip->ss_idle_period = ss_interval * 1000;
- chip->remote_wakeup_en = 0;
- chip->aspm_l0s_l1_en = aspm_l0s_l1_en;
- chip->dynamic_aspm = 1;
- chip->fpga_sd_sdr104_clk = CLK_200;
- chip->fpga_sd_ddr50_clk = CLK_100;
- chip->fpga_sd_sdr50_clk = CLK_100;
- chip->fpga_sd_hs_clk = CLK_100;
- chip->fpga_mmc_52m_clk = CLK_80;
- chip->fpga_ms_hg_clk = CLK_80;
- chip->fpga_ms_4bit_clk = CLK_80;
- chip->fpga_ms_1bit_clk = CLK_40;
- chip->asic_sd_sdr104_clk = 203;
- chip->asic_sd_sdr50_clk = 98;
- chip->asic_sd_ddr50_clk = 98;
- chip->asic_sd_hs_clk = 98;
- chip->asic_mmc_52m_clk = 98;
- chip->asic_ms_hg_clk = 117;
- chip->asic_ms_4bit_clk = 78;
- chip->asic_ms_1bit_clk = 39;
- chip->ssc_depth_sd_sdr104 = SSC_DEPTH_2M;
- chip->ssc_depth_sd_sdr50 = SSC_DEPTH_2M;
- chip->ssc_depth_sd_ddr50 = SSC_DEPTH_1M;
- chip->ssc_depth_sd_hs = SSC_DEPTH_1M;
- chip->ssc_depth_mmc_52m = SSC_DEPTH_1M;
- chip->ssc_depth_ms_hg = SSC_DEPTH_1M;
- chip->ssc_depth_ms_4bit = SSC_DEPTH_512K;
- chip->ssc_depth_low_speed = SSC_DEPTH_512K;
- chip->ssc_en = 1;
- chip->sd_speed_prior = 0x01040203;
- chip->sd_current_prior = 0x00010203;
- chip->sd_ctl = SD_PUSH_POINT_AUTO |
- SD_SAMPLE_POINT_AUTO |
- SUPPORT_MMC_DDR_MODE;
- chip->sd_ddr_tx_phase = 0;
- chip->mmc_ddr_tx_phase = 1;
- chip->sd_default_tx_phase = 15;
- chip->sd_default_rx_phase = 15;
- chip->pmos_pwr_on_interval = 200;
- chip->sd_voltage_switch_delay = 1000;
- chip->ms_power_class_en = 3;
-
- chip->sd_400mA_ocp_thd = 1;
- chip->sd_800mA_ocp_thd = 5;
- chip->ms_ocp_thd = 2;
-
- chip->card_drive_sel = 0x55;
- chip->sd30_drive_sel_1v8 = 0x03;
- chip->sd30_drive_sel_3v3 = 0x01;
-
- chip->do_delink_before_power_down = 1;
- chip->auto_power_down = 1;
- chip->polling_config = 0;
-
- chip->force_clkreq_0 = 1;
- chip->ft2_fast_mode = 0;
-
- chip->sdio_retry_cnt = 1;
-
- chip->xd_timeout = 2000;
- chip->sd_timeout = 10000;
- chip->ms_timeout = 2000;
- chip->mspro_timeout = 15000;
-
- chip->power_down_in_ss = 1;
-
- chip->sdr104_en = 1;
- chip->sdr50_en = 1;
- chip->ddr50_en = 1;
-
- chip->delink_stage1_step = 100;
- chip->delink_stage2_step = 40;
- chip->delink_stage3_step = 20;
-
- chip->auto_delink_in_L1 = 1;
- chip->blink_led = 1;
- chip->msi_en = msi_en;
- chip->hp_watch_bios_hotplug = 0;
- chip->max_payload = 0;
- chip->phy_voltage = 0;
-
- chip->support_ms_8bit = 1;
- chip->s3_pwr_off_delay = 1000;
-}
-
-static int rtsx_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
-{
- struct Scsi_Host *host;
- struct rtsx_dev *dev;
- int err = 0;
- struct task_struct *th;
-
- dev_dbg(&pci->dev, "Realtek PCI-E card reader detected\n");
-
- err = pcim_enable_device(pci);
- if (err < 0) {
- dev_err(&pci->dev, "PCI enable device failed!\n");
- return err;
- }
-
- err = pci_request_regions(pci, CR_DRIVER_NAME);
- if (err < 0) {
- dev_err(&pci->dev, "PCI request regions for %s failed!\n",
- CR_DRIVER_NAME);
- return err;
- }
-
- /*
- * Ask the SCSI layer to allocate a host structure, with extra
- * space at the end for our private rtsx_dev structure.
- */
- host = scsi_host_alloc(&rtsx_host_template, sizeof(*dev));
- if (!host) {
- dev_err(&pci->dev, "Unable to allocate the scsi host\n");
- err = -ENOMEM;
- goto scsi_host_alloc_fail;
- }
-
- dev = host_to_rtsx(host);
- memset(dev, 0, sizeof(struct rtsx_dev));
-
- dev->chip = kzalloc(sizeof(*dev->chip), GFP_KERNEL);
- if (!dev->chip) {
- err = -ENOMEM;
- goto chip_alloc_fail;
- }
-
- spin_lock_init(&dev->reg_lock);
- mutex_init(&dev->dev_mutex);
- init_completion(&dev->cmnd_ready);
- init_completion(&dev->control_exit);
- init_completion(&dev->polling_exit);
- init_completion(&dev->notify);
- init_completion(&dev->scanning_done);
- init_waitqueue_head(&dev->delay_wait);
-
- dev->pci = pci;
- dev->irq = -1;
-
- dev_info(&pci->dev, "Resource length: 0x%x\n",
- (unsigned int)pci_resource_len(pci, 0));
- dev->addr = pci_resource_start(pci, 0);
- dev->remap_addr = ioremap(dev->addr, pci_resource_len(pci, 0));
- if (!dev->remap_addr) {
- dev_err(&pci->dev, "ioremap error\n");
- err = -ENXIO;
- goto ioremap_fail;
- }
-
- /*
- * Using "unsigned long" cast here to eliminate gcc warning in
- * 64-bit system
- */
- dev_info(&pci->dev, "Original address: 0x%lx, remapped address: 0x%lx\n",
- (unsigned long)(dev->addr), (unsigned long)(dev->remap_addr));
-
- dev->rtsx_resv_buf = dmam_alloc_coherent(&pci->dev, RTSX_RESV_BUF_LEN,
- &dev->rtsx_resv_buf_addr,
- GFP_KERNEL);
- if (!dev->rtsx_resv_buf) {
- dev_err(&pci->dev, "alloc dma buffer fail\n");
- err = -ENXIO;
- goto dma_alloc_fail;
- }
- dev->chip->host_cmds_ptr = dev->rtsx_resv_buf;
- dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr;
- dev->chip->host_sg_tbl_ptr = dev->rtsx_resv_buf + HOST_CMDS_BUF_LEN;
- dev->chip->host_sg_tbl_addr = dev->rtsx_resv_buf_addr +
- HOST_CMDS_BUF_LEN;
-
- dev->chip->rtsx = dev;
-
- rtsx_init_options(dev->chip);
-
- dev_info(&pci->dev, "pci->irq = %d\n", pci->irq);
-
- if (dev->chip->msi_en) {
- if (pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) < 0)
- dev->chip->msi_en = 0;
- }
-
- if (rtsx_acquire_irq(dev) < 0) {
- err = -EBUSY;
- goto irq_acquire_fail;
- }
-
- pci_set_master(pci);
- synchronize_irq(dev->irq);
-
- rtsx_init_chip(dev->chip);
-
- /*
- * set the supported max_lun and max_id for the scsi host
- * NOTE: the minimal value of max_id is 1
- */
- host->max_id = 1;
- host->max_lun = dev->chip->max_lun;
-
- /* Start up our control thread */
- th = kthread_run(rtsx_control_thread, dev, CR_DRIVER_NAME);
- if (IS_ERR(th)) {
- dev_err(&pci->dev, "Unable to start control thread\n");
- err = PTR_ERR(th);
- goto control_thread_fail;
- }
- dev->ctl_thread = th;
-
- err = scsi_add_host(host, &pci->dev);
- if (err) {
- dev_err(&pci->dev, "Unable to add the scsi host\n");
- goto scsi_add_host_fail;
- }
-
- /* Start up the thread for delayed SCSI-device scanning */
- th = kthread_run(rtsx_scan_thread, dev, "rtsx-scan");
- if (IS_ERR(th)) {
- dev_err(&pci->dev, "Unable to start the device-scanning thread\n");
- complete(&dev->scanning_done);
- err = PTR_ERR(th);
- goto scan_thread_fail;
- }
-
- /* Start up the thread for polling thread */
- th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling");
- if (IS_ERR(th)) {
- dev_err(&pci->dev, "Unable to start the device-polling thread\n");
- err = PTR_ERR(th);
- goto scan_thread_fail;
- }
- dev->polling_thread = th;
-
- pci_set_drvdata(pci, dev);
-
- return 0;
-
- /* We come here if there are any problems */
-scan_thread_fail:
- quiesce_and_remove_host(dev);
-scsi_add_host_fail:
- complete(&dev->cmnd_ready);
- wait_for_completion(&dev->control_exit);
-control_thread_fail:
- free_irq(dev->irq, (void *)dev);
- rtsx_release_chip(dev->chip);
-irq_acquire_fail:
- dev->chip->host_cmds_ptr = NULL;
- dev->chip->host_sg_tbl_ptr = NULL;
- if (dev->chip->msi_en)
- pci_free_irq_vectors(dev->pci);
-dma_alloc_fail:
- iounmap(dev->remap_addr);
-ioremap_fail:
- kfree(dev->chip);
-chip_alloc_fail:
- dev_err(&pci->dev, "%s failed\n", __func__);
- scsi_host_put(host);
-scsi_host_alloc_fail:
- pci_release_regions(pci);
- return err;
-}
-
-static void rtsx_remove(struct pci_dev *pci)
-{
- struct rtsx_dev *dev = pci_get_drvdata(pci);
-
- quiesce_and_remove_host(dev);
- release_everything(dev);
- pci_release_regions(pci);
-}
-
-/* PCI IDs */
-static const struct pci_device_id rtsx_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5208),
- PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5288),
- PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, rtsx_ids);
-
-static SIMPLE_DEV_PM_OPS(rtsx_pm_ops, rtsx_suspend, rtsx_resume);
-
-/* pci_driver definition */
-static struct pci_driver rtsx_driver = {
- .name = CR_DRIVER_NAME,
- .id_table = rtsx_ids,
- .probe = rtsx_probe,
- .remove = rtsx_remove,
- .driver.pm = &rtsx_pm_ops,
- .shutdown = rtsx_shutdown,
-};
-
-module_pci_driver(rtsx_driver);
diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h
deleted file mode 100644
index ec6f5b07390b..000000000000
--- a/drivers/staging/rts5208/rtsx.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_H
-#define __REALTEK_RTSX_H
-
-#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/mutex.h>
-#include <linux/cdrom.h>
-#include <linux/workqueue.h>
-#include <linux/timer.h>
-#include <linux/time64.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_devinfo.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_host.h>
-
-#define CR_DRIVER_NAME "rts5208"
-
-/*
- * macros for easy use
- */
-#define wait_timeout_x(task_state, msecs) \
-do { \
- set_current_state((task_state)); \
- schedule_timeout((msecs) * HZ / 1000); \
-} while (0)
-#define wait_timeout(msecs) wait_timeout_x(TASK_INTERRUPTIBLE, (msecs))
-
-#define STATE_TRANS_NONE 0
-#define STATE_TRANS_CMD 1
-#define STATE_TRANS_BUF 2
-#define STATE_TRANS_SG 3
-
-#define TRANS_NOT_READY 0
-#define TRANS_RESULT_OK 1
-#define TRANS_RESULT_FAIL 2
-
-#define SCSI_LUN(srb) ((srb)->device->lun)
-
-struct rtsx_chip;
-
-struct rtsx_dev {
- struct pci_dev *pci;
-
- /* pci resources */
- unsigned long addr;
- void __iomem *remap_addr;
- int irq;
-
- /* locks */
- spinlock_t reg_lock;
-
- struct task_struct *ctl_thread; /* the control thread */
- struct task_struct *polling_thread; /* the polling thread */
-
- /* mutual exclusion and synchronization structures */
- struct completion cmnd_ready; /* to sleep thread on */
- struct completion control_exit; /* control thread exit */
- struct completion polling_exit; /* polling thread exit */
- struct completion notify; /* thread begin/end */
- struct completion scanning_done; /* wait for scan thread */
-
- wait_queue_head_t delay_wait; /* wait during scan, reset */
- struct mutex dev_mutex;
-
- /* host reserved buffer */
- void *rtsx_resv_buf;
- dma_addr_t rtsx_resv_buf_addr;
-
- char trans_result;
- char trans_state;
-
- struct completion *done;
- /* Whether interrupt handler should care card cd info */
- u32 check_card_cd;
-
- struct rtsx_chip *chip;
-};
-
-/* Convert between rtsx_dev and the corresponding Scsi_Host */
-static inline struct Scsi_Host *rtsx_to_host(struct rtsx_dev *dev)
-{
- return container_of((void *)dev, struct Scsi_Host, hostdata);
-}
-
-static inline struct rtsx_dev *host_to_rtsx(struct Scsi_Host *host)
-{
- return (struct rtsx_dev *)host->hostdata;
-}
-
-#define lock_state(chip) spin_lock_irq(&((chip)->rtsx->reg_lock))
-#define unlock_state(chip) spin_unlock_irq(&((chip)->rtsx->reg_lock))
-
-/* struct scsi_cmnd transfer buffer access utilities */
-enum xfer_buf_dir {TO_XFER_BUF, FROM_XFER_BUF};
-
-#include "rtsx_chip.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-#include "rtsx_sys.h"
-#include "general.h"
-
-static inline void rtsx_writel(struct rtsx_chip *chip, u32 reg, u32 value)
-{
- iowrite32(value, chip->rtsx->remap_addr + reg);
-}
-
-static inline u32 rtsx_readl(struct rtsx_chip *chip, u32 reg)
-{
- return ioread32(chip->rtsx->remap_addr + reg);
-}
-
-static inline void rtsx_writew(struct rtsx_chip *chip, u32 reg, u16 value)
-{
- iowrite16(value, chip->rtsx->remap_addr + reg);
-}
-
-static inline u16 rtsx_readw(struct rtsx_chip *chip, u32 reg)
-{
- return ioread16(chip->rtsx->remap_addr + reg);
-}
-
-static inline void rtsx_writeb(struct rtsx_chip *chip, u32 reg, u8 value)
-{
- iowrite8(value, chip->rtsx->remap_addr + reg);
-}
-
-static inline u8 rtsx_readb(struct rtsx_chip *chip, u32 reg)
-{
- return ioread8((chip)->rtsx->remap_addr + reg);
-}
-
-static inline int rtsx_read_config_byte(struct rtsx_chip *chip, int where, u8 *val)
-{
- return pci_read_config_byte(chip->rtsx->pci, where, val);
-}
-
-static inline int rtsx_write_config_byte(struct rtsx_chip *chip, int where, u8 val)
-{
- return pci_write_config_byte(chip->rtsx->pci, where, val);
-}
-
-#endif /* __REALTEK_RTSX_H */
diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c
deleted file mode 100644
index 326b04756f62..000000000000
--- a/drivers/staging/rts5208/rtsx_card.c
+++ /dev/null
@@ -1,1151 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/kernel.h>
-
-#include "rtsx.h"
-#include "sd.h"
-#include "xd.h"
-#include "ms.h"
-
-void do_remaining_work(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
-#ifdef XD_DELAY_WRITE
- struct xd_info *xd_card = &chip->xd_card;
-#endif
- struct ms_info *ms_card = &chip->ms_card;
-
- if (chip->card_ready & SD_CARD) {
- if (sd_card->seq_mode) {
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- sd_card->cleanup_counter++;
- } else {
- sd_card->cleanup_counter = 0;
- }
- }
-
-#ifdef XD_DELAY_WRITE
- if (chip->card_ready & XD_CARD) {
- if (xd_card->delay_write.delay_write_flag) {
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- xd_card->cleanup_counter++;
- } else {
- xd_card->cleanup_counter = 0;
- }
- }
-#endif
-
- if (chip->card_ready & MS_CARD) {
- if (CHK_MSPRO(ms_card)) {
- if (ms_card->seq_mode) {
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- ms_card->cleanup_counter++;
- } else {
- ms_card->cleanup_counter = 0;
- }
- } else {
-#ifdef MS_DELAY_WRITE
- if (ms_card->delay_write.delay_write_flag) {
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- ms_card->cleanup_counter++;
- } else {
- ms_card->cleanup_counter = 0;
- }
-#endif
- }
- }
-
- if (sd_card->cleanup_counter > POLLING_WAIT_CNT)
- sd_cleanup_work(chip);
-
- if (xd_card->cleanup_counter > POLLING_WAIT_CNT)
- xd_cleanup_work(chip);
-
- if (ms_card->cleanup_counter > POLLING_WAIT_CNT)
- ms_cleanup_work(chip);
-}
-
-void try_to_switch_sdio_ctrl(struct rtsx_chip *chip)
-{
- u8 reg1 = 0, reg2 = 0;
-
- rtsx_read_register(chip, 0xFF34, &reg1);
- rtsx_read_register(chip, 0xFF38, &reg2);
- dev_dbg(rtsx_dev(chip), "reg 0xFF34: 0x%x, reg 0xFF38: 0x%x\n",
- reg1, reg2);
- if ((reg1 & 0xC0) && (reg2 & 0xC0)) {
- chip->sd_int = 1;
- rtsx_write_register(chip, SDIO_CTRL, 0xFF,
- SDIO_BUS_CTRL | SDIO_CD_CTRL);
- rtsx_write_register(chip, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, LDO_ON);
- }
-}
-
-#ifdef SUPPORT_SDIO_ASPM
-void dynamic_configure_sdio_aspm(struct rtsx_chip *chip)
-{
- u8 buf[12], reg;
- int i;
-
- for (i = 0; i < 12; i++)
- rtsx_read_register(chip, 0xFF08 + i, &buf[i]);
- rtsx_read_register(chip, 0xFF25, &reg);
- if ((memcmp(buf, chip->sdio_raw_data, 12) != 0) || (reg & 0x03)) {
- chip->sdio_counter = 0;
- chip->sdio_idle = 0;
- } else {
- if (!chip->sdio_idle) {
- chip->sdio_counter++;
- if (chip->sdio_counter >= SDIO_IDLE_COUNT) {
- chip->sdio_counter = 0;
- chip->sdio_idle = 1;
- }
- }
- }
- memcpy(chip->sdio_raw_data, buf, 12);
-
- if (chip->sdio_idle) {
- if (!chip->sdio_aspm) {
- dev_dbg(rtsx_dev(chip), "SDIO enter ASPM!\n");
- rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC,
- 0x30 | (chip->aspm_level[1] << 2));
- chip->sdio_aspm = 1;
- }
- } else {
- if (chip->sdio_aspm) {
- dev_dbg(rtsx_dev(chip), "SDIO exit ASPM!\n");
- rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, 0x30);
- chip->sdio_aspm = 0;
- }
- }
-}
-#endif
-
-void do_reset_sd_card(struct rtsx_chip *chip)
-{
- int retval;
-
- dev_dbg(rtsx_dev(chip), "%s: %d, card2lun = 0x%x\n", __func__,
- chip->sd_reset_counter, chip->card2lun[SD_CARD]);
-
- if (chip->card2lun[SD_CARD] >= MAX_ALLOWED_LUN_CNT) {
- clear_bit(SD_NR, &chip->need_reset);
- chip->sd_reset_counter = 0;
- chip->sd_show_cnt = 0;
- return;
- }
-
- chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0;
-
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
-
- retval = reset_sd_card(chip);
- if (chip->need_release & SD_CARD)
- return;
- if (retval == STATUS_SUCCESS) {
- clear_bit(SD_NR, &chip->need_reset);
- chip->sd_reset_counter = 0;
- chip->sd_show_cnt = 0;
- chip->card_ready |= SD_CARD;
- chip->card_fail &= ~SD_CARD;
- chip->rw_card[chip->card2lun[SD_CARD]] = sd_rw;
- } else {
- if (chip->sd_io || chip->sd_reset_counter >= MAX_RESET_CNT) {
- clear_bit(SD_NR, &chip->need_reset);
- chip->sd_reset_counter = 0;
- chip->sd_show_cnt = 0;
- } else {
- chip->sd_reset_counter++;
- }
- chip->card_ready &= ~SD_CARD;
- chip->card_fail |= SD_CARD;
- chip->capacity[chip->card2lun[SD_CARD]] = 0;
- chip->rw_card[chip->card2lun[SD_CARD]] = NULL;
-
- rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
- if (!chip->ft2_fast_mode)
- card_power_off(chip, SD_CARD);
- if (chip->sd_io) {
- chip->sd_int = 0;
- try_to_switch_sdio_ctrl(chip);
- } else {
- disable_card_clock(chip, SD_CARD);
- }
- }
-}
-
-void do_reset_xd_card(struct rtsx_chip *chip)
-{
- int retval;
-
- dev_dbg(rtsx_dev(chip), "%s: %d, card2lun = 0x%x\n", __func__,
- chip->xd_reset_counter, chip->card2lun[XD_CARD]);
-
- if (chip->card2lun[XD_CARD] >= MAX_ALLOWED_LUN_CNT) {
- clear_bit(XD_NR, &chip->need_reset);
- chip->xd_reset_counter = 0;
- chip->xd_show_cnt = 0;
- return;
- }
-
- chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0;
-
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
-
- retval = reset_xd_card(chip);
- if (chip->need_release & XD_CARD)
- return;
- if (retval == STATUS_SUCCESS) {
- clear_bit(XD_NR, &chip->need_reset);
- chip->xd_reset_counter = 0;
- chip->card_ready |= XD_CARD;
- chip->card_fail &= ~XD_CARD;
- chip->rw_card[chip->card2lun[XD_CARD]] = xd_rw;
- } else {
- if (chip->xd_reset_counter >= MAX_RESET_CNT) {
- clear_bit(XD_NR, &chip->need_reset);
- chip->xd_reset_counter = 0;
- chip->xd_show_cnt = 0;
- } else {
- chip->xd_reset_counter++;
- }
- chip->card_ready &= ~XD_CARD;
- chip->card_fail |= XD_CARD;
- chip->capacity[chip->card2lun[XD_CARD]] = 0;
- chip->rw_card[chip->card2lun[XD_CARD]] = NULL;
-
- rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
- if (!chip->ft2_fast_mode)
- card_power_off(chip, XD_CARD);
- disable_card_clock(chip, XD_CARD);
- }
-}
-
-void do_reset_ms_card(struct rtsx_chip *chip)
-{
- int retval;
-
- dev_dbg(rtsx_dev(chip), "%s: %d, card2lun = 0x%x\n", __func__,
- chip->ms_reset_counter, chip->card2lun[MS_CARD]);
-
- if (chip->card2lun[MS_CARD] >= MAX_ALLOWED_LUN_CNT) {
- clear_bit(MS_NR, &chip->need_reset);
- chip->ms_reset_counter = 0;
- chip->ms_show_cnt = 0;
- return;
- }
-
- chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0;
-
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
-
- retval = reset_ms_card(chip);
- if (chip->need_release & MS_CARD)
- return;
- if (retval == STATUS_SUCCESS) {
- clear_bit(MS_NR, &chip->need_reset);
- chip->ms_reset_counter = 0;
- chip->card_ready |= MS_CARD;
- chip->card_fail &= ~MS_CARD;
- chip->rw_card[chip->card2lun[MS_CARD]] = ms_rw;
- } else {
- if (chip->ms_reset_counter >= MAX_RESET_CNT) {
- clear_bit(MS_NR, &chip->need_reset);
- chip->ms_reset_counter = 0;
- chip->ms_show_cnt = 0;
- } else {
- chip->ms_reset_counter++;
- }
- chip->card_ready &= ~MS_CARD;
- chip->card_fail |= MS_CARD;
- chip->capacity[chip->card2lun[MS_CARD]] = 0;
- chip->rw_card[chip->card2lun[MS_CARD]] = NULL;
-
- rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
- if (!chip->ft2_fast_mode)
- card_power_off(chip, MS_CARD);
- disable_card_clock(chip, MS_CARD);
- }
-}
-
-static void release_sdio(struct rtsx_chip *chip)
-{
- if (chip->sd_io) {
- rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
- SD_STOP | SD_CLR_ERR);
-
- if (chip->chip_insert_with_sdio) {
- chip->chip_insert_with_sdio = 0;
-
- if (CHECK_PID(chip, 0x5288))
- rtsx_write_register(chip, 0xFE5A, 0x08, 0x00);
- else
- rtsx_write_register(chip, 0xFE70, 0x80, 0x00);
- }
-
- rtsx_write_register(chip, SDIO_CTRL, SDIO_CD_CTRL, 0);
- chip->sd_io = 0;
- }
-}
-
-void rtsx_power_off_card(struct rtsx_chip *chip)
-{
- if ((chip->card_ready & SD_CARD) || chip->sd_io) {
- sd_cleanup_work(chip);
- sd_power_off_card3v3(chip);
- }
-
- if (chip->card_ready & XD_CARD) {
- xd_cleanup_work(chip);
- xd_power_off_card3v3(chip);
- }
-
- if (chip->card_ready & MS_CARD) {
- ms_cleanup_work(chip);
- ms_power_off_card3v3(chip);
- }
-}
-
-void rtsx_release_cards(struct rtsx_chip *chip)
-{
- chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
- if ((chip->card_ready & SD_CARD) || chip->sd_io) {
- if (chip->int_reg & SD_EXIST)
- sd_cleanup_work(chip);
- release_sd_card(chip);
- }
-
- if (chip->card_ready & XD_CARD) {
- if (chip->int_reg & XD_EXIST)
- xd_cleanup_work(chip);
- release_xd_card(chip);
- }
-
- if (chip->card_ready & MS_CARD) {
- if (chip->int_reg & MS_EXIST)
- ms_cleanup_work(chip);
- release_ms_card(chip);
- }
-}
-
-void rtsx_reset_cards(struct rtsx_chip *chip)
-{
- if (!chip->need_reset)
- return;
-
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
-
- rtsx_disable_aspm(chip);
-
- if ((chip->need_reset & SD_CARD) && chip->chip_insert_with_sdio)
- clear_bit(SD_NR, &chip->need_reset);
-
- if (chip->need_reset & XD_CARD) {
- chip->card_exist |= XD_CARD;
-
- if (chip->xd_show_cnt >= MAX_SHOW_CNT)
- do_reset_xd_card(chip);
- else
- chip->xd_show_cnt++;
- }
- if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) {
- if (chip->card_exist & XD_CARD) {
- clear_bit(SD_NR, &chip->need_reset);
- clear_bit(MS_NR, &chip->need_reset);
- }
- }
- if (chip->need_reset & SD_CARD) {
- chip->card_exist |= SD_CARD;
-
- if (chip->sd_show_cnt >= MAX_SHOW_CNT) {
- rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
- do_reset_sd_card(chip);
- } else {
- chip->sd_show_cnt++;
- }
- }
- if (chip->need_reset & MS_CARD) {
- chip->card_exist |= MS_CARD;
-
- if (chip->ms_show_cnt >= MAX_SHOW_CNT)
- do_reset_ms_card(chip);
- else
- chip->ms_show_cnt++;
- }
-}
-
-void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip)
-{
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
-
- if (reset_chip)
- rtsx_reset_chip(chip);
-
- chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
- if ((chip->int_reg & SD_EXIST) && (chip->need_reinit & SD_CARD)) {
- release_sdio(chip);
- release_sd_card(chip);
-
- wait_timeout(100);
-
- chip->card_exist |= SD_CARD;
- do_reset_sd_card(chip);
- }
-
- if ((chip->int_reg & XD_EXIST) && (chip->need_reinit & XD_CARD)) {
- release_xd_card(chip);
-
- wait_timeout(100);
-
- chip->card_exist |= XD_CARD;
- do_reset_xd_card(chip);
- }
-
- if ((chip->int_reg & MS_EXIST) && (chip->need_reinit & MS_CARD)) {
- release_ms_card(chip);
-
- wait_timeout(100);
-
- chip->card_exist |= MS_CARD;
- do_reset_ms_card(chip);
- }
-
- chip->need_reinit = 0;
-}
-
-#ifdef DISABLE_CARD_INT
-void card_cd_debounce(struct rtsx_chip *chip, unsigned long *need_reset,
- unsigned long *need_release)
-{
- u8 release_map = 0, reset_map = 0;
-
- chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
- if (chip->card_exist) {
- if (chip->card_exist & XD_CARD) {
- if (!(chip->int_reg & XD_EXIST))
- release_map |= XD_CARD;
- } else if (chip->card_exist & SD_CARD) {
- if (!(chip->int_reg & SD_EXIST))
- release_map |= SD_CARD;
- } else if (chip->card_exist & MS_CARD) {
- if (!(chip->int_reg & MS_EXIST))
- release_map |= MS_CARD;
- }
- } else {
- if (chip->int_reg & XD_EXIST)
- reset_map |= XD_CARD;
- else if (chip->int_reg & SD_EXIST)
- reset_map |= SD_CARD;
- else if (chip->int_reg & MS_EXIST)
- reset_map |= MS_CARD;
- }
-
- if (reset_map) {
- int xd_cnt = 0, sd_cnt = 0, ms_cnt = 0;
- int i;
-
- for (i = 0; i < (DEBOUNCE_CNT); i++) {
- chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
- if (chip->int_reg & XD_EXIST)
- xd_cnt++;
- else
- xd_cnt = 0;
-
- if (chip->int_reg & SD_EXIST)
- sd_cnt++;
- else
- sd_cnt = 0;
-
- if (chip->int_reg & MS_EXIST)
- ms_cnt++;
- else
- ms_cnt = 0;
-
- wait_timeout(30);
- }
-
- reset_map = 0;
- if (!(chip->card_exist & XD_CARD) &&
- (xd_cnt > (DEBOUNCE_CNT - 1)))
- reset_map |= XD_CARD;
- if (!(chip->card_exist & SD_CARD) &&
- (sd_cnt > (DEBOUNCE_CNT - 1)))
- reset_map |= SD_CARD;
- if (!(chip->card_exist & MS_CARD) &&
- (ms_cnt > (DEBOUNCE_CNT - 1)))
- reset_map |= MS_CARD;
- }
-
- if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN))
- rtsx_write_register(chip, HOST_SLEEP_STATE, 0xC0, 0x00);
-
- if (need_reset)
- *need_reset = reset_map;
- if (need_release)
- *need_release = release_map;
-}
-#endif
-
-void rtsx_init_cards(struct rtsx_chip *chip)
-{
- if (RTSX_TST_DELINK(chip) && (rtsx_get_stat(chip) != RTSX_STAT_SS)) {
- dev_dbg(rtsx_dev(chip), "Reset chip in polling thread!\n");
- rtsx_reset_chip(chip);
- RTSX_CLR_DELINK(chip);
- }
-
-#ifdef DISABLE_CARD_INT
- card_cd_debounce(chip, &chip->need_reset, &chip->need_release);
-#endif
-
- if (chip->need_release) {
- if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) {
- if (chip->int_reg & XD_EXIST) {
- clear_bit(SD_NR, &chip->need_release);
- clear_bit(MS_NR, &chip->need_release);
- }
- }
-
- if (!(chip->card_exist & SD_CARD) && !chip->sd_io)
- clear_bit(SD_NR, &chip->need_release);
- if (!(chip->card_exist & XD_CARD))
- clear_bit(XD_NR, &chip->need_release);
- if (!(chip->card_exist & MS_CARD))
- clear_bit(MS_NR, &chip->need_release);
-
- dev_dbg(rtsx_dev(chip), "chip->need_release = 0x%x\n",
- (unsigned int)(chip->need_release));
-
-#ifdef SUPPORT_OCP
- if (chip->need_release) {
- if (chip->ocp_stat & (CARD_OC_NOW | CARD_OC_EVER))
- rtsx_write_register(chip, OCPCLR,
- CARD_OC_INT_CLR |
- CARD_OC_CLR,
- CARD_OC_INT_CLR |
- CARD_OC_CLR);
- chip->ocp_stat = 0;
- }
-#endif
- if (chip->need_release) {
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
- }
-
- if (chip->need_release & SD_CARD) {
- clear_bit(SD_NR, &chip->need_release);
- chip->card_exist &= ~SD_CARD;
- chip->card_ejected &= ~SD_CARD;
- chip->card_fail &= ~SD_CARD;
- CLR_BIT(chip->lun_mc, chip->card2lun[SD_CARD]);
- chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0;
- rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
-
- release_sdio(chip);
- release_sd_card(chip);
- }
-
- if (chip->need_release & XD_CARD) {
- clear_bit(XD_NR, &chip->need_release);
- chip->card_exist &= ~XD_CARD;
- chip->card_ejected &= ~XD_CARD;
- chip->card_fail &= ~XD_CARD;
- CLR_BIT(chip->lun_mc, chip->card2lun[XD_CARD]);
- chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0;
-
- release_xd_card(chip);
-
- if (CHECK_PID(chip, 0x5288) &&
- CHECK_BARO_PKG(chip, QFN))
- rtsx_write_register(chip, HOST_SLEEP_STATE,
- 0xC0, 0xC0);
- }
-
- if (chip->need_release & MS_CARD) {
- clear_bit(MS_NR, &chip->need_release);
- chip->card_exist &= ~MS_CARD;
- chip->card_ejected &= ~MS_CARD;
- chip->card_fail &= ~MS_CARD;
- CLR_BIT(chip->lun_mc, chip->card2lun[MS_CARD]);
- chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0;
-
- release_ms_card(chip);
- }
-
- dev_dbg(rtsx_dev(chip), "chip->card_exist = 0x%x\n",
- chip->card_exist);
-
- if (!chip->card_exist)
- turn_off_led(chip, LED_GPIO);
- }
-
- if (chip->need_reset) {
- dev_dbg(rtsx_dev(chip), "chip->need_reset = 0x%x\n",
- (unsigned int)(chip->need_reset));
-
- rtsx_reset_cards(chip);
- }
-
- if (chip->need_reinit) {
- dev_dbg(rtsx_dev(chip), "chip->need_reinit = 0x%x\n",
- (unsigned int)(chip->need_reinit));
-
- rtsx_reinit_cards(chip, 0);
- }
-}
-
-int switch_ssc_clock(struct rtsx_chip *chip, int clk)
-{
- int retval;
- u8 n = (u8)(clk - 2), min_n, max_n;
- u8 mcu_cnt, div, max_div, ssc_depth, ssc_depth_mask;
- int sd_vpclk_phase_reset = 0;
-
- if (chip->cur_clk == clk)
- return STATUS_SUCCESS;
-
- min_n = 60;
- max_n = 120;
- max_div = CLK_DIV_4;
-
- dev_dbg(rtsx_dev(chip), "Switch SSC clock to %dMHz (cur_clk = %d)\n",
- clk, chip->cur_clk);
-
- if (clk <= 2 || n > max_n)
- return STATUS_FAIL;
-
- mcu_cnt = (u8)(125 / clk + 3);
- if (mcu_cnt > 7)
- mcu_cnt = 7;
-
- div = CLK_DIV_1;
- while ((n < min_n) && (div < max_div)) {
- n = (n + 2) * 2 - 2;
- div++;
- }
- dev_dbg(rtsx_dev(chip), "n = %d, div = %d\n", n, div);
-
- if (chip->ssc_en) {
- ssc_depth = 0x01;
- n -= 2;
- } else {
- ssc_depth = 0;
- }
-
- ssc_depth_mask = 0x03;
-
- dev_dbg(rtsx_dev(chip), "ssc_depth = %d\n", ssc_depth);
-
- rtsx_init_cmd(chip);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0xFF, (div << 4) | mcu_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL2, ssc_depth_mask, ssc_depth);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
- if (sd_vpclk_phase_reset) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, PHASE_NOT_RESET);
- }
-
- retval = rtsx_send_cmd(chip, 0, WAIT_TIME);
- if (retval < 0)
- return STATUS_ERROR;
-
- udelay(10);
- retval = rtsx_write_register(chip, CLK_CTL, CLK_LOW_FREQ, 0);
- if (retval)
- return retval;
-
- chip->cur_clk = clk;
-
- return STATUS_SUCCESS;
-}
-
-int switch_normal_clock(struct rtsx_chip *chip, int clk)
-{
- int retval;
- u8 sel, div, mcu_cnt;
- int sd_vpclk_phase_reset = 0;
-
- if (chip->cur_clk == clk)
- return STATUS_SUCCESS;
-
- switch (clk) {
- case CLK_20:
- dev_dbg(rtsx_dev(chip), "Switch clock to 20MHz\n");
- sel = SSC_80;
- div = CLK_DIV_4;
- mcu_cnt = 7;
- break;
-
- case CLK_30:
- dev_dbg(rtsx_dev(chip), "Switch clock to 30MHz\n");
- sel = SSC_120;
- div = CLK_DIV_4;
- mcu_cnt = 7;
- break;
-
- case CLK_40:
- dev_dbg(rtsx_dev(chip), "Switch clock to 40MHz\n");
- sel = SSC_80;
- div = CLK_DIV_2;
- mcu_cnt = 7;
- break;
-
- case CLK_50:
- dev_dbg(rtsx_dev(chip), "Switch clock to 50MHz\n");
- sel = SSC_100;
- div = CLK_DIV_2;
- mcu_cnt = 6;
- break;
-
- case CLK_60:
- dev_dbg(rtsx_dev(chip), "Switch clock to 60MHz\n");
- sel = SSC_120;
- div = CLK_DIV_2;
- mcu_cnt = 6;
- break;
-
- case CLK_80:
- dev_dbg(rtsx_dev(chip), "Switch clock to 80MHz\n");
- sel = SSC_80;
- div = CLK_DIV_1;
- mcu_cnt = 5;
- break;
-
- case CLK_100:
- dev_dbg(rtsx_dev(chip), "Switch clock to 100MHz\n");
- sel = SSC_100;
- div = CLK_DIV_1;
- mcu_cnt = 5;
- break;
-
- case CLK_120:
- dev_dbg(rtsx_dev(chip), "Switch clock to 120MHz\n");
- sel = SSC_120;
- div = CLK_DIV_1;
- mcu_cnt = 5;
- break;
-
- case CLK_150:
- dev_dbg(rtsx_dev(chip), "Switch clock to 150MHz\n");
- sel = SSC_150;
- div = CLK_DIV_1;
- mcu_cnt = 4;
- break;
-
- case CLK_200:
- dev_dbg(rtsx_dev(chip), "Switch clock to 200MHz\n");
- sel = SSC_200;
- div = CLK_DIV_1;
- mcu_cnt = 4;
- break;
-
- default:
- dev_dbg(rtsx_dev(chip), "Try to switch to an illegal clock (%d)\n",
- clk);
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_register(chip, CLK_CTL, 0xFF, CLK_LOW_FREQ);
- if (retval)
- return retval;
- if (sd_vpclk_phase_reset) {
- retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, 0);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SD_VPCLK1_CTL,
- PHASE_NOT_RESET, 0);
- if (retval)
- return retval;
- }
- retval = rtsx_write_register(chip, CLK_DIV, 0xFF,
- (div << 4) | mcu_cnt);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CLK_SEL, 0xFF, sel);
- if (retval)
- return retval;
-
- if (sd_vpclk_phase_reset) {
- udelay(200);
- retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, PHASE_NOT_RESET);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SD_VPCLK1_CTL,
- PHASE_NOT_RESET, PHASE_NOT_RESET);
- if (retval)
- return retval;
- udelay(200);
- }
- retval = rtsx_write_register(chip, CLK_CTL, 0xFF, 0);
- if (retval)
- return retval;
-
- chip->cur_clk = clk;
-
- return STATUS_SUCCESS;
-}
-
-void trans_dma_enable(enum dma_data_direction dir, struct rtsx_chip *chip,
- u32 byte_cnt, u8 pack_size)
-{
- if (pack_size > DMA_1024)
- pack_size = DMA_512;
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, IRQSTAT0, DMA_DONE_INT, DMA_DONE_INT);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(byte_cnt >> 24));
- rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(byte_cnt >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(byte_cnt >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC0, 0xFF, (u8)byte_cnt);
-
- if (dir == DMA_FROM_DEVICE) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL,
- 0x03 | DMA_PACK_SIZE_MASK,
- DMA_DIR_FROM_CARD | DMA_EN | pack_size);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL,
- 0x03 | DMA_PACK_SIZE_MASK,
- DMA_DIR_TO_CARD | DMA_EN | pack_size);
- }
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-}
-
-int enable_card_clock(struct rtsx_chip *chip, u8 card)
-{
- int retval;
- u8 clk_en = 0;
-
- if (card & XD_CARD)
- clk_en |= XD_CLK_EN;
- if (card & SD_CARD)
- clk_en |= SD_CLK_EN;
- if (card & MS_CARD)
- clk_en |= MS_CLK_EN;
-
- retval = rtsx_write_register(chip, CARD_CLK_EN, clk_en, clk_en);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int disable_card_clock(struct rtsx_chip *chip, u8 card)
-{
- int retval;
- u8 clk_en = 0;
-
- if (card & XD_CARD)
- clk_en |= XD_CLK_EN;
- if (card & SD_CARD)
- clk_en |= SD_CLK_EN;
- if (card & MS_CARD)
- clk_en |= MS_CLK_EN;
-
- retval = rtsx_write_register(chip, CARD_CLK_EN, clk_en, 0);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int card_power_on(struct rtsx_chip *chip, u8 card)
-{
- int retval;
- u8 mask, val1, val2;
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && card == MS_CARD) {
- mask = MS_POWER_MASK;
- val1 = MS_PARTIAL_POWER_ON;
- val2 = MS_POWER_ON;
- } else {
- mask = SD_POWER_MASK;
- val1 = SD_PARTIAL_POWER_ON;
- val2 = SD_POWER_ON;
- }
-
- rtsx_init_cmd(chip);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val1);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- udelay(chip->pmos_pwr_on_interval);
-
- rtsx_init_cmd(chip);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val2);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int card_power_off(struct rtsx_chip *chip, u8 card)
-{
- int retval;
- u8 mask, val;
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && card == MS_CARD) {
- mask = MS_POWER_MASK;
- val = MS_POWER_OFF;
- } else {
- mask = SD_POWER_MASK;
- val = SD_POWER_OFF;
- }
-
- retval = rtsx_write_register(chip, CARD_PWR_CTL, mask, val);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 sec_addr, u16 sec_cnt)
-{
- int retval;
- unsigned int lun = SCSI_LUN(srb);
- int i;
-
- if (!chip->rw_card[lun])
- return STATUS_FAIL;
-
- for (i = 0; i < 3; i++) {
- chip->rw_need_retry = 0;
-
- retval = chip->rw_card[lun](srb, chip, sec_addr, sec_cnt);
- if (retval != STATUS_SUCCESS) {
- if (rtsx_check_chip_exist(chip) != STATUS_SUCCESS) {
- rtsx_release_chip(chip);
- return STATUS_FAIL;
- }
- if (detect_card_cd(chip, chip->cur_card) !=
- STATUS_SUCCESS) {
- return STATUS_FAIL;
- }
-
- if (!chip->rw_need_retry) {
- dev_dbg(rtsx_dev(chip), "RW fail, but no need to retry\n");
- break;
- }
- } else {
- chip->rw_need_retry = 0;
- break;
- }
-
- dev_dbg(rtsx_dev(chip), "Retry RW, (i = %d)\n", i);
- }
-
- return retval;
-}
-
-int card_share_mode(struct rtsx_chip *chip, int card)
-{
- int retval;
- u8 mask, value;
-
- if (CHECK_PID(chip, 0x5208)) {
- mask = CARD_SHARE_MASK;
- if (card == SD_CARD)
- value = CARD_SHARE_48_SD;
- else if (card == MS_CARD)
- value = CARD_SHARE_48_MS;
- else if (card == XD_CARD)
- value = CARD_SHARE_48_XD;
- else
- return STATUS_FAIL;
-
- } else if (CHECK_PID(chip, 0x5288)) {
- mask = 0x03;
- if (card == SD_CARD)
- value = CARD_SHARE_BAROSSA_SD;
- else if (card == MS_CARD)
- value = CARD_SHARE_BAROSSA_MS;
- else if (card == XD_CARD)
- value = CARD_SHARE_BAROSSA_XD;
- else
- return STATUS_FAIL;
-
- } else {
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_register(chip, CARD_SHARE_MODE, mask, value);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int select_card(struct rtsx_chip *chip, int card)
-{
- int retval;
-
- if (chip->cur_card != card) {
- u8 mod;
-
- if (card == SD_CARD)
- mod = SD_MOD_SEL;
- else if (card == MS_CARD)
- mod = MS_MOD_SEL;
- else if (card == XD_CARD)
- mod = XD_MOD_SEL;
- else if (card == SPI_CARD)
- mod = SPI_MOD_SEL;
- else
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_SELECT, 0x07, mod);
- if (retval)
- return retval;
- chip->cur_card = card;
-
- retval = card_share_mode(chip, card);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-void toggle_gpio(struct rtsx_chip *chip, u8 gpio)
-{
- u8 temp_reg;
-
- rtsx_read_register(chip, CARD_GPIO, &temp_reg);
- temp_reg ^= (0x01 << gpio);
- rtsx_write_register(chip, CARD_GPIO, 0xFF, temp_reg);
-}
-
-void turn_on_led(struct rtsx_chip *chip, u8 gpio)
-{
- if (CHECK_PID(chip, 0x5288))
- rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio),
- (u8)(1 << gpio));
- else
- rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0);
-}
-
-void turn_off_led(struct rtsx_chip *chip, u8 gpio)
-{
- if (CHECK_PID(chip, 0x5288))
- rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0);
- else
- rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio),
- (u8)(1 << gpio));
-}
-
-int detect_card_cd(struct rtsx_chip *chip, int card)
-{
- u32 card_cd, status;
-
- if (card == SD_CARD) {
- card_cd = SD_EXIST;
- } else if (card == MS_CARD) {
- card_cd = MS_EXIST;
- } else if (card == XD_CARD) {
- card_cd = XD_EXIST;
- } else {
- dev_dbg(rtsx_dev(chip), "Wrong card type: 0x%x\n", card);
- return STATUS_FAIL;
- }
-
- status = rtsx_readl(chip, RTSX_BIPR);
- if (!(status & card_cd))
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int check_card_exist(struct rtsx_chip *chip, unsigned int lun)
-{
- if (chip->card_exist & chip->lun2card[lun])
- return 1;
-
- return 0;
-}
-
-int check_card_ready(struct rtsx_chip *chip, unsigned int lun)
-{
- if (chip->card_ready & chip->lun2card[lun])
- return 1;
-
- return 0;
-}
-
-int check_card_wp(struct rtsx_chip *chip, unsigned int lun)
-{
- if (chip->card_wp & chip->lun2card[lun])
- return 1;
-
- return 0;
-}
-
-u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun)
-{
- if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD)
- return (u8)XD_CARD;
- else if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD)
- return (u8)SD_CARD;
- else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD)
- return (u8)MS_CARD;
-
- return 0;
-}
-
-void eject_card(struct rtsx_chip *chip, unsigned int lun)
-{
- do_remaining_work(chip);
-
- if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) {
- release_sd_card(chip);
- chip->card_ejected |= SD_CARD;
- chip->card_ready &= ~SD_CARD;
- chip->capacity[lun] = 0;
- } else if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) {
- release_xd_card(chip);
- chip->card_ejected |= XD_CARD;
- chip->card_ready &= ~XD_CARD;
- chip->capacity[lun] = 0;
- } else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) {
- release_ms_card(chip);
- chip->card_ejected |= MS_CARD;
- chip->card_ready &= ~MS_CARD;
- chip->capacity[lun] = 0;
- }
-}
diff --git a/drivers/staging/rts5208/rtsx_card.h b/drivers/staging/rts5208/rtsx_card.h
deleted file mode 100644
index 39727371cd7a..000000000000
--- a/drivers/staging/rts5208/rtsx_card.h
+++ /dev/null
@@ -1,1087 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_CARD_H
-#define __REALTEK_RTSX_CARD_H
-
-#include "rtsx.h"
-#include "rtsx_chip.h"
-#include "rtsx_transport.h"
-#include "sd.h"
-
-#define SSC_POWER_DOWN 0x01
-#define SD_OC_POWER_DOWN 0x02
-#define MS_OC_POWER_DOWN 0x04
-#define ALL_POWER_DOWN 0x07
-#define OC_POWER_DOWN 0x06
-
-#define PMOS_STRG_MASK 0x10
-#define PMOS_STRG_800mA 0x10
-#define PMOS_STRG_400mA 0x00
-
-#define POWER_OFF 0x03
-#define PARTIAL_POWER_ON 0x01
-#define POWER_ON 0x00
-
-#define MS_POWER_OFF 0x0C
-#define MS_PARTIAL_POWER_ON 0x04
-#define MS_POWER_ON 0x00
-#define MS_POWER_MASK 0x0C
-
-#define SD_POWER_OFF 0x03
-#define SD_PARTIAL_POWER_ON 0x01
-#define SD_POWER_ON 0x00
-#define SD_POWER_MASK 0x03
-
-#define XD_OUTPUT_EN 0x02
-#define SD_OUTPUT_EN 0x04
-#define MS_OUTPUT_EN 0x08
-#define SPI_OUTPUT_EN 0x10
-
-#define CLK_LOW_FREQ 0x01
-
-#define CLK_DIV_1 0x01
-#define CLK_DIV_2 0x02
-#define CLK_DIV_4 0x03
-#define CLK_DIV_8 0x04
-
-#define SSC_80 0
-#define SSC_100 1
-#define SSC_120 2
-#define SSC_150 3
-#define SSC_200 4
-
-#define XD_CLK_EN 0x02
-#define SD_CLK_EN 0x04
-#define MS_CLK_EN 0x08
-#define SPI_CLK_EN 0x10
-
-#define XD_MOD_SEL 1
-#define SD_MOD_SEL 2
-#define MS_MOD_SEL 3
-#define SPI_MOD_SEL 4
-
-#define CHANGE_CLK 0x01
-
-#define SD_CRC7_ERR 0x80
-#define SD_CRC16_ERR 0x40
-#define SD_CRC_WRITE_ERR 0x20
-#define SD_CRC_WRITE_ERR_MASK 0x1C
-#define GET_CRC_TIME_OUT 0x02
-#define SD_TUNING_COMPARE_ERR 0x01
-
-#define SD_RSP_80CLK_TIMEOUT 0x01
-
-#define SD_CLK_TOGGLE_EN 0x80
-#define SD_CLK_FORCE_STOP 0x40
-#define SD_DAT3_STATUS 0x10
-#define SD_DAT2_STATUS 0x08
-#define SD_DAT1_STATUS 0x04
-#define SD_DAT0_STATUS 0x02
-#define SD_CMD_STATUS 0x01
-
-#define SD_IO_USING_1V8 0x80
-#define SD_IO_USING_3V3 0x7F
-#define TYPE_A_DRIVING 0x00
-#define TYPE_B_DRIVING 0x01
-#define TYPE_C_DRIVING 0x02
-#define TYPE_D_DRIVING 0x03
-
-#define DDR_FIX_RX_DAT 0x00
-#define DDR_VAR_RX_DAT 0x80
-#define DDR_FIX_RX_DAT_EDGE 0x00
-#define DDR_FIX_RX_DAT_14_DELAY 0x40
-#define DDR_FIX_RX_CMD 0x00
-#define DDR_VAR_RX_CMD 0x20
-#define DDR_FIX_RX_CMD_POS_EDGE 0x00
-#define DDR_FIX_RX_CMD_14_DELAY 0x10
-#define SD20_RX_POS_EDGE 0x00
-#define SD20_RX_14_DELAY 0x08
-#define SD20_RX_SEL_MASK 0x08
-
-#define DDR_FIX_TX_CMD_DAT 0x00
-#define DDR_VAR_TX_CMD_DAT 0x80
-#define DDR_FIX_TX_DAT_14_TSU 0x00
-#define DDR_FIX_TX_DAT_12_TSU 0x40
-#define DDR_FIX_TX_CMD_NEG_EDGE 0x00
-#define DDR_FIX_TX_CMD_14_AHEAD 0x20
-#define SD20_TX_NEG_EDGE 0x00
-#define SD20_TX_14_AHEAD 0x10
-#define SD20_TX_SEL_MASK 0x10
-#define DDR_VAR_SDCLK_POL_SWAP 0x01
-
-#define SD_TRANSFER_START 0x80
-#define SD_TRANSFER_END 0x40
-#define SD_STAT_IDLE 0x20
-#define SD_TRANSFER_ERR 0x10
-#define SD_TM_NORMAL_WRITE 0x00
-#define SD_TM_AUTO_WRITE_3 0x01
-#define SD_TM_AUTO_WRITE_4 0x02
-#define SD_TM_AUTO_READ_3 0x05
-#define SD_TM_AUTO_READ_4 0x06
-#define SD_TM_CMD_RSP 0x08
-#define SD_TM_AUTO_WRITE_1 0x09
-#define SD_TM_AUTO_WRITE_2 0x0A
-#define SD_TM_NORMAL_READ 0x0C
-#define SD_TM_AUTO_READ_1 0x0D
-#define SD_TM_AUTO_READ_2 0x0E
-#define SD_TM_AUTO_TUNING 0x0F
-
-#define PHASE_CHANGE 0x80
-#define PHASE_NOT_RESET 0x40
-
-#define DCMPS_CHANGE 0x80
-#define DCMPS_CHANGE_DONE 0x40
-#define DCMPS_ERROR 0x20
-#define DCMPS_CURRENT_PHASE 0x1F
-
-#define SD_CLK_DIVIDE_0 0x00
-#define SD_CLK_DIVIDE_256 0xC0
-#define SD_CLK_DIVIDE_128 0x80
-#define SD_BUS_WIDTH_1 0x00
-#define SD_BUS_WIDTH_4 0x01
-#define SD_BUS_WIDTH_8 0x02
-#define SD_ASYNC_FIFO_NOT_RST 0x10
-#define SD_20_MODE 0x00
-#define SD_DDR_MODE 0x04
-#define SD_30_MODE 0x08
-
-#define SD_CLK_DIVIDE_MASK 0xC0
-
-#define SD_CMD_IDLE 0x80
-
-#define SD_DATA_IDLE 0x80
-
-#define DCM_RESET 0x08
-#define DCM_LOCKED 0x04
-#define DCM_208M 0x00
-#define DCM_TX 0x01
-#define DCM_RX 0x02
-
-#define DRP_START 0x80
-#define DRP_DONE 0x40
-
-#define DRP_WRITE 0x80
-#define DRP_READ 0x00
-#define DCM_WRITE_ADDRESS_50 0x50
-#define DCM_WRITE_ADDRESS_51 0x51
-#define DCM_READ_ADDRESS_00 0x00
-#define DCM_READ_ADDRESS_51 0x51
-
-#define SD_CALCULATE_CRC7 0x00
-#define SD_NO_CALCULATE_CRC7 0x80
-#define SD_CHECK_CRC16 0x00
-#define SD_NO_CHECK_CRC16 0x40
-#define SD_NO_CHECK_WAIT_CRC_TO 0x20
-#define SD_WAIT_BUSY_END 0x08
-#define SD_NO_WAIT_BUSY_END 0x00
-#define SD_CHECK_CRC7 0x00
-#define SD_NO_CHECK_CRC7 0x04
-#define SD_RSP_LEN_0 0x00
-#define SD_RSP_LEN_6 0x01
-#define SD_RSP_LEN_17 0x02
-#define SD_RSP_TYPE_R0 0x04
-#define SD_RSP_TYPE_R1 0x01
-#define SD_RSP_TYPE_R1b 0x09
-#define SD_RSP_TYPE_R2 0x02
-#define SD_RSP_TYPE_R3 0x05
-#define SD_RSP_TYPE_R4 0x05
-#define SD_RSP_TYPE_R5 0x01
-#define SD_RSP_TYPE_R6 0x01
-#define SD_RSP_TYPE_R7 0x01
-
-#define SD_RSP_80CLK_TIMEOUT_EN 0x01
-
-#define SAMPLE_TIME_RISING 0x00
-#define SAMPLE_TIME_FALLING 0x80
-#define PUSH_TIME_DEFAULT 0x00
-#define PUSH_TIME_ODD 0x40
-#define NO_EXTEND_TOGGLE 0x00
-#define EXTEND_TOGGLE_CHK 0x20
-#define MS_BUS_WIDTH_1 0x00
-#define MS_BUS_WIDTH_4 0x10
-#define MS_BUS_WIDTH_8 0x18
-#define MS_2K_SECTOR_MODE 0x04
-#define MS_512_SECTOR_MODE 0x00
-#define MS_TOGGLE_TIMEOUT_EN 0x00
-#define MS_TOGGLE_TIMEOUT_DISEN 0x01
-#define MS_NO_CHECK_INT 0x02
-
-#define WAIT_INT 0x80
-#define NO_WAIT_INT 0x00
-#define NO_AUTO_READ_INT_REG 0x00
-#define AUTO_READ_INT_REG 0x40
-#define MS_CRC16_ERR 0x20
-#define MS_RDY_TIMEOUT 0x10
-#define MS_INT_CMDNK 0x08
-#define MS_INT_BREQ 0x04
-#define MS_INT_ERR 0x02
-#define MS_INT_CED 0x01
-
-#define MS_TRANSFER_START 0x80
-#define MS_TRANSFER_END 0x40
-#define MS_TRANSFER_ERR 0x20
-#define MS_BS_STATE 0x10
-#define MS_TM_READ_BYTES 0x00
-#define MS_TM_NORMAL_READ 0x01
-#define MS_TM_WRITE_BYTES 0x04
-#define MS_TM_NORMAL_WRITE 0x05
-#define MS_TM_AUTO_READ 0x08
-#define MS_TM_AUTO_WRITE 0x0C
-
-#define CARD_SHARE_MASK 0x0F
-#define CARD_SHARE_MULTI_LUN 0x00
-#define CARD_SHARE_NORMAL 0x00
-#define CARD_SHARE_48_XD 0x02
-#define CARD_SHARE_48_SD 0x04
-#define CARD_SHARE_48_MS 0x08
-#define CARD_SHARE_BAROSSA_XD 0x00
-#define CARD_SHARE_BAROSSA_SD 0x01
-#define CARD_SHARE_BAROSSA_MS 0x02
-
-#define MS_DRIVE_8 0x00
-#define MS_DRIVE_4 0x40
-#define MS_DRIVE_12 0x80
-#define SD_DRIVE_8 0x00
-#define SD_DRIVE_4 0x10
-#define SD_DRIVE_12 0x20
-#define XD_DRIVE_8 0x00
-#define XD_DRIVE_4 0x04
-#define XD_DRIVE_12 0x08
-
-#define SPI_STOP 0x01
-#define XD_STOP 0x02
-#define SD_STOP 0x04
-#define MS_STOP 0x08
-#define SPI_CLR_ERR 0x10
-#define XD_CLR_ERR 0x20
-#define SD_CLR_ERR 0x40
-#define MS_CLR_ERR 0x80
-
-#define CRC_FIX_CLK (0x00 << 0)
-#define CRC_VAR_CLK0 (0x01 << 0)
-#define CRC_VAR_CLK1 (0x02 << 0)
-#define SD30_FIX_CLK (0x00 << 2)
-#define SD30_VAR_CLK0 (0x01 << 2)
-#define SD30_VAR_CLK1 (0x02 << 2)
-#define SAMPLE_FIX_CLK (0x00 << 4)
-#define SAMPLE_VAR_CLK0 (0x01 << 4)
-#define SAMPLE_VAR_CLK1 (0x02 << 4)
-
-#define SDIO_VER_20 0x80
-#define SDIO_VER_10 0x00
-#define SDIO_VER_CHG 0x40
-#define SDIO_BUS_AUTO_SWITCH 0x10
-
-#define PINGPONG_BUFFER 0x01
-#define RING_BUFFER 0x00
-
-#define RB_FLUSH 0x80
-
-#define DMA_DONE_INT_EN 0x80
-#define SUSPEND_INT_EN 0x40
-#define LINK_RDY_INT_EN 0x20
-#define LINK_DOWN_INT_EN 0x10
-
-#define DMA_DONE_INT 0x80
-#define SUSPEND_INT 0x40
-#define LINK_RDY_INT 0x20
-#define LINK_DOWN_INT 0x10
-
-#define MRD_ERR_INT_EN 0x40
-#define MWR_ERR_INT_EN 0x20
-#define SCSI_CMD_INT_EN 0x10
-#define TLP_RCV_INT_EN 0x08
-#define TLP_TRSMT_INT_EN 0x04
-#define MRD_COMPLETE_INT_EN 0x02
-#define MWR_COMPLETE_INT_EN 0x01
-
-#define MRD_ERR_INT 0x40
-#define MWR_ERR_INT 0x20
-#define SCSI_CMD_INT 0x10
-#define TLP_RX_INT 0x08
-#define TLP_TX_INT 0x04
-#define MRD_COMPLETE_INT 0x02
-#define MWR_COMPLETE_INT 0x01
-
-#define MSG_RX_INT_EN 0x08
-#define MRD_RX_INT_EN 0x04
-#define MWR_RX_INT_EN 0x02
-#define CPLD_RX_INT_EN 0x01
-
-#define MSG_RX_INT 0x08
-#define MRD_RX_INT 0x04
-#define MWR_RX_INT 0x02
-#define CPLD_RX_INT 0x01
-
-#define MSG_TX_INT_EN 0x08
-#define MRD_TX_INT_EN 0x04
-#define MWR_TX_INT_EN 0x02
-#define CPLD_TX_INT_EN 0x01
-
-#define MSG_TX_INT 0x08
-#define MRD_TX_INT 0x04
-#define MWR_TX_INT 0x02
-#define CPLD_TX_INT 0x01
-
-#define DMA_RST 0x80
-#define DMA_BUSY 0x04
-#define DMA_DIR_TO_CARD 0x00
-#define DMA_DIR_FROM_CARD 0x02
-#define DMA_EN 0x01
-#define DMA_128 (0 << 4)
-#define DMA_256 (1 << 4)
-#define DMA_512 (2 << 4)
-#define DMA_1024 (3 << 4)
-#define DMA_PACK_SIZE_MASK 0x30
-
-#define XD_PWR_OFF_DELAY0 0x00
-#define XD_PWR_OFF_DELAY1 0x02
-#define XD_PWR_OFF_DELAY2 0x04
-#define XD_PWR_OFF_DELAY3 0x06
-#define XD_AUTO_PWR_OFF_EN 0xF7
-#define XD_NO_AUTO_PWR_OFF 0x08
-
-#define XD_TIME_RWN_1 0x00
-#define XD_TIME_RWN_STEP 0x20
-#define XD_TIME_RW_1 0x00
-#define XD_TIME_RW_STEP 0x04
-#define XD_TIME_SETUP_1 0x00
-#define XD_TIME_SETUP_STEP 0x01
-
-#define XD_ECC2_UNCORRECTABLE 0x80
-#define XD_ECC2_ERROR 0x40
-#define XD_ECC1_UNCORRECTABLE 0x20
-#define XD_ECC1_ERROR 0x10
-#define XD_RDY 0x04
-#define XD_CE_EN 0xFD
-#define XD_CE_DISEN 0x02
-#define XD_WP_EN 0xFE
-#define XD_WP_DISEN 0x01
-
-#define XD_TRANSFER_START 0x80
-#define XD_TRANSFER_END 0x40
-#define XD_PPB_EMPTY 0x20
-#define XD_RESET 0x00
-#define XD_ERASE 0x01
-#define XD_READ_STATUS 0x02
-#define XD_READ_ID 0x03
-#define XD_READ_REDUNDANT 0x04
-#define XD_READ_PAGES 0x05
-#define XD_SET_CMD 0x06
-#define XD_NORMAL_READ 0x07
-#define XD_WRITE_PAGES 0x08
-#define XD_NORMAL_WRITE 0x09
-#define XD_WRITE_REDUNDANT 0x0A
-#define XD_SET_ADDR 0x0B
-
-#define XD_PPB_TO_SIE 0x80
-#define XD_TO_PPB_ONLY 0x00
-#define XD_BA_TRANSFORM 0x40
-#define XD_BA_NO_TRANSFORM 0x00
-#define XD_NO_CALC_ECC 0x20
-#define XD_CALC_ECC 0x00
-#define XD_IGNORE_ECC 0x10
-#define XD_CHECK_ECC 0x00
-#define XD_DIRECT_TO_RB 0x08
-#define XD_ADDR_LENGTH_0 0x00
-#define XD_ADDR_LENGTH_1 0x01
-#define XD_ADDR_LENGTH_2 0x02
-#define XD_ADDR_LENGTH_3 0x03
-#define XD_ADDR_LENGTH_4 0x04
-
-#define XD_GPG 0xFF
-#define XD_BPG 0x00
-
-#define XD_GBLK 0xFF
-#define XD_LATER_BBLK 0xF0
-
-#define XD_ECC2_ALL1 0x80
-#define XD_ECC1_ALL1 0x40
-#define XD_BA2_ALL0 0x20
-#define XD_BA1_ALL0 0x10
-#define XD_BA1_BA2_EQL 0x04
-#define XD_BA2_VALID 0x02
-#define XD_BA1_VALID 0x01
-
-#define XD_PGSTS_ZEROBIT_OVER4 0x00
-#define XD_PGSTS_NOT_FF 0x02
-#define XD_AUTO_CHK_DATA_STATUS 0x01
-
-#define RSTB_MODE_DETECT 0x80
-#define MODE_OUT_VLD 0x40
-#define MODE_OUT_0_NONE 0x00
-#define MODE_OUT_10_NONE 0x04
-#define MODE_OUT_10_47 0x05
-#define MODE_OUT_10_180 0x06
-#define MODE_OUT_10_680 0x07
-#define MODE_OUT_16_NONE 0x08
-#define MODE_OUT_16_47 0x09
-#define MODE_OUT_16_180 0x0A
-#define MODE_OUT_16_680 0x0B
-#define MODE_OUT_NONE_NONE 0x0C
-#define MODE_OUT_NONE_47 0x0D
-#define MODE_OUT_NONE_180 0x0E
-#define MODE_OUT_NONE_680 0x0F
-
-#define CARD_OC_INT_EN 0x20
-#define CARD_DETECT_EN 0x08
-
-#define MS_DETECT_EN 0x80
-#define MS_OCP_INT_EN 0x40
-#define MS_OCP_INT_CLR 0x20
-#define MS_OC_CLR 0x10
-#define SD_DETECT_EN 0x08
-#define SD_OCP_INT_EN 0x04
-#define SD_OCP_INT_CLR 0x02
-#define SD_OC_CLR 0x01
-
-#define CARD_OCP_DETECT 0x80
-#define CARD_OC_NOW 0x08
-#define CARD_OC_EVER 0x04
-
-#define MS_OCP_DETECT 0x80
-#define MS_OC_NOW 0x40
-#define MS_OC_EVER 0x20
-#define SD_OCP_DETECT 0x08
-#define SD_OC_NOW 0x04
-#define SD_OC_EVER 0x02
-
-#define CARD_OC_INT_CLR 0x08
-#define CARD_OC_CLR 0x02
-
-#define SD_OCP_GLITCH_MASK 0x07
-#define SD_OCP_GLITCH_6_4 0x00
-#define SD_OCP_GLITCH_64 0x01
-#define SD_OCP_GLITCH_640 0x02
-#define SD_OCP_GLITCH_1000 0x03
-#define SD_OCP_GLITCH_2000 0x04
-#define SD_OCP_GLITCH_4000 0x05
-#define SD_OCP_GLITCH_8000 0x06
-#define SD_OCP_GLITCH_10000 0x07
-
-#define MS_OCP_GLITCH_MASK 0x70
-#define MS_OCP_GLITCH_6_4 (0x00 << 4)
-#define MS_OCP_GLITCH_64 (0x01 << 4)
-#define MS_OCP_GLITCH_640 (0x02 << 4)
-#define MS_OCP_GLITCH_1000 (0x03 << 4)
-#define MS_OCP_GLITCH_2000 (0x04 << 4)
-#define MS_OCP_GLITCH_4000 (0x05 << 4)
-#define MS_OCP_GLITCH_8000 (0x06 << 4)
-#define MS_OCP_GLITCH_10000 (0x07 << 4)
-
-#define OCP_TIME_60 0x00
-#define OCP_TIME_100 (0x01 << 3)
-#define OCP_TIME_200 (0x02 << 3)
-#define OCP_TIME_400 (0x03 << 3)
-#define OCP_TIME_600 (0x04 << 3)
-#define OCP_TIME_800 (0x05 << 3)
-#define OCP_TIME_1100 (0x06 << 3)
-#define OCP_TIME_MASK 0x38
-
-#define MS_OCP_TIME_60 0x00
-#define MS_OCP_TIME_100 (0x01 << 4)
-#define MS_OCP_TIME_200 (0x02 << 4)
-#define MS_OCP_TIME_400 (0x03 << 4)
-#define MS_OCP_TIME_600 (0x04 << 4)
-#define MS_OCP_TIME_800 (0x05 << 4)
-#define MS_OCP_TIME_1100 (0x06 << 4)
-#define MS_OCP_TIME_MASK 0x70
-
-#define SD_OCP_TIME_60 0x00
-#define SD_OCP_TIME_100 0x01
-#define SD_OCP_TIME_200 0x02
-#define SD_OCP_TIME_400 0x03
-#define SD_OCP_TIME_600 0x04
-#define SD_OCP_TIME_800 0x05
-#define SD_OCP_TIME_1100 0x06
-#define SD_OCP_TIME_MASK 0x07
-
-#define OCP_THD_315_417 0x00
-#define OCP_THD_283_783 (0x01 << 6)
-#define OCP_THD_244_946 (0x02 << 6)
-#define OCP_THD_191_1080 (0x03 << 6)
-#define OCP_THD_MASK 0xC0
-
-#define MS_OCP_THD_450 0x00
-#define MS_OCP_THD_550 (0x01 << 4)
-#define MS_OCP_THD_650 (0x02 << 4)
-#define MS_OCP_THD_750 (0x03 << 4)
-#define MS_OCP_THD_850 (0x04 << 4)
-#define MS_OCP_THD_950 (0x05 << 4)
-#define MS_OCP_THD_1050 (0x06 << 4)
-#define MS_OCP_THD_1150 (0x07 << 4)
-#define MS_OCP_THD_MASK 0x70
-
-#define SD_OCP_THD_450 0x00
-#define SD_OCP_THD_550 0x01
-#define SD_OCP_THD_650 0x02
-#define SD_OCP_THD_750 0x03
-#define SD_OCP_THD_850 0x04
-#define SD_OCP_THD_950 0x05
-#define SD_OCP_THD_1050 0x06
-#define SD_OCP_THD_1150 0x07
-#define SD_OCP_THD_MASK 0x07
-
-#define FPGA_MS_PULL_CTL_EN 0xEF
-#define FPGA_SD_PULL_CTL_EN 0xF7
-#define FPGA_XD_PULL_CTL_EN1 0xFE
-#define FPGA_XD_PULL_CTL_EN2 0xFD
-#define FPGA_XD_PULL_CTL_EN3 0xFB
-
-#define FPGA_MS_PULL_CTL_BIT 0x10
-#define FPGA_SD_PULL_CTL_BIT 0x08
-
-#define BLINK_EN 0x08
-#define LED_GPIO0 (0 << 4)
-#define LED_GPIO1 (1 << 4)
-#define LED_GPIO2 (2 << 4)
-
-#define SDIO_BUS_CTRL 0x01
-#define SDIO_CD_CTRL 0x02
-
-#define SSC_RSTB 0x80
-#define SSC_8X_EN 0x40
-#define SSC_FIX_FRAC 0x20
-#define SSC_SEL_1M 0x00
-#define SSC_SEL_2M 0x08
-#define SSC_SEL_4M 0x10
-#define SSC_SEL_8M 0x18
-
-#define SSC_DEPTH_MASK 0x07
-#define SSC_DEPTH_DISALBE 0x00
-#define SSC_DEPTH_4M 0x01
-#define SSC_DEPTH_2M 0x02
-#define SSC_DEPTH_1M 0x03
-#define SSC_DEPTH_512K 0x04
-#define SSC_DEPTH_256K 0x05
-#define SSC_DEPTH_128K 0x06
-#define SSC_DEPTH_64K 0x07
-
-#define XD_D3_NP 0x00
-#define XD_D3_PD (0x01 << 6)
-#define XD_D3_PU (0x02 << 6)
-#define XD_D2_NP 0x00
-#define XD_D2_PD (0x01 << 4)
-#define XD_D2_PU (0x02 << 4)
-#define XD_D1_NP 0x00
-#define XD_D1_PD (0x01 << 2)
-#define XD_D1_PU (0x02 << 2)
-#define XD_D0_NP 0x00
-#define XD_D0_PD 0x01
-#define XD_D0_PU 0x02
-
-#define SD_D7_NP 0x00
-#define SD_D7_PD (0x01 << 4)
-#define SD_DAT7_PU (0x02 << 4)
-#define SD_CLK_NP 0x00
-#define SD_CLK_PD (0x01 << 2)
-#define SD_CLK_PU (0x02 << 2)
-#define SD_D5_NP 0x00
-#define SD_D5_PD 0x01
-#define SD_D5_PU 0x02
-
-#define MS_D1_NP 0x00
-#define MS_D1_PD (0x01 << 6)
-#define MS_D1_PU (0x02 << 6)
-#define MS_D2_NP 0x00
-#define MS_D2_PD (0x01 << 4)
-#define MS_D2_PU (0x02 << 4)
-#define MS_CLK_NP 0x00
-#define MS_CLK_PD (0x01 << 2)
-#define MS_CLK_PU (0x02 << 2)
-#define MS_D6_NP 0x00
-#define MS_D6_PD 0x01
-#define MS_D6_PU 0x02
-
-#define XD_D7_NP 0x00
-#define XD_D7_PD (0x01 << 6)
-#define XD_D7_PU (0x02 << 6)
-#define XD_D6_NP 0x00
-#define XD_D6_PD (0x01 << 4)
-#define XD_D6_PU (0x02 << 4)
-#define XD_D5_NP 0x00
-#define XD_D5_PD (0x01 << 2)
-#define XD_D5_PU (0x02 << 2)
-#define XD_D4_NP 0x00
-#define XD_D4_PD 0x01
-#define XD_D4_PU 0x02
-
-#define SD_D6_NP 0x00
-#define SD_D6_PD (0x01 << 6)
-#define SD_D6_PU (0x02 << 6)
-#define SD_D0_NP 0x00
-#define SD_D0_PD (0x01 << 4)
-#define SD_D0_PU (0x02 << 4)
-#define SD_D1_NP 0x00
-#define SD_D1_PD 0x01
-#define SD_D1_PU 0x02
-
-#define MS_D3_NP 0x00
-#define MS_D3_PD (0x01 << 6)
-#define MS_D3_PU (0x02 << 6)
-#define MS_D0_NP 0x00
-#define MS_D0_PD (0x01 << 4)
-#define MS_D0_PU (0x02 << 4)
-#define MS_BS_NP 0x00
-#define MS_BS_PD (0x01 << 2)
-#define MS_BS_PU (0x02 << 2)
-
-#define XD_WP_NP 0x00
-#define XD_WP_PD (0x01 << 6)
-#define XD_WP_PU (0x02 << 6)
-#define XD_CE_NP 0x00
-#define XD_CE_PD (0x01 << 3)
-#define XD_CE_PU (0x02 << 3)
-#define XD_CLE_NP 0x00
-#define XD_CLE_PD (0x01 << 1)
-#define XD_CLE_PU (0x02 << 1)
-#define XD_CD_PD 0x00
-#define XD_CD_PU 0x01
-
-#define SD_D4_NP 0x00
-#define SD_D4_PD (0x01 << 6)
-#define SD_D4_PU (0x02 << 6)
-
-#define MS_D7_NP 0x00
-#define MS_D7_PD (0x01 << 6)
-#define MS_D7_PU (0x02 << 6)
-
-#define XD_RDY_NP 0x00
-#define XD_RDY_PD (0x01 << 6)
-#define XD_RDY_PU (0x02 << 6)
-#define XD_WE_NP 0x00
-#define XD_WE_PD (0x01 << 4)
-#define XD_WE_PU (0x02 << 4)
-#define XD_RE_NP 0x00
-#define XD_RE_PD (0x01 << 2)
-#define XD_RE_PU (0x02 << 2)
-#define XD_ALE_NP 0x00
-#define XD_ALE_PD 0x01
-#define XD_ALE_PU 0x02
-
-#define SD_D3_NP 0x00
-#define SD_D3_PD (0x01 << 4)
-#define SD_D3_PU (0x02 << 4)
-#define SD_D2_NP 0x00
-#define SD_D2_PD (0x01 << 2)
-#define SD_D2_PU (0x02 << 2)
-
-#define MS_INS_PD 0x00
-#define MS_INS_PU (0x01 << 7)
-#define SD_WP_NP 0x00
-#define SD_WP_PD (0x01 << 5)
-#define SD_WP_PU (0x02 << 5)
-#define SD_CD_PD 0x00
-#define SD_CD_PU (0x01 << 4)
-#define SD_CMD_NP 0x00
-#define SD_CMD_PD (0x01 << 2)
-#define SD_CMD_PU (0x02 << 2)
-
-#define MS_D5_NP 0x00
-#define MS_D5_PD (0x01 << 2)
-#define MS_D5_PU (0x02 << 2)
-#define MS_D4_NP 0x00
-#define MS_D4_PD 0x01
-#define MS_D4_PU 0x02
-
-#define FORCE_PM_CLOCK 0x10
-#define EN_CLOCK_PM 0x01
-
-#define HOST_ENTER_S3 0x02
-#define HOST_ENTER_S1 0x01
-
-#define AUX_PWR_DETECTED 0x01
-
-#define PHY_DEBUG_MODE 0x01
-
-#define SPI_COMMAND_BIT_8 0xE0
-#define SPI_ADDRESS_BIT_24 0x17
-#define SPI_ADDRESS_BIT_32 0x1F
-
-#define SPI_TRANSFER0_START 0x80
-#define SPI_TRANSFER0_END 0x40
-#define SPI_C_MODE0 0x00
-#define SPI_CA_MODE0 0x01
-#define SPI_CDO_MODE0 0x02
-#define SPI_CDI_MODE0 0x03
-#define SPI_CADO_MODE0 0x04
-#define SPI_CADI_MODE0 0x05
-#define SPI_POLLING_MODE0 0x06
-
-#define SPI_TRANSFER1_START 0x80
-#define SPI_TRANSFER1_END 0x40
-#define SPI_DO_MODE1 0x00
-#define SPI_DI_MODE1 0x01
-
-#define CS_POLARITY_HIGH 0x40
-#define CS_POLARITY_LOW 0x00
-#define DTO_MSB_FIRST 0x00
-#define DTO_LSB_FIRST 0x20
-#define SPI_MASTER 0x00
-#define SPI_SLAVE 0x10
-#define SPI_MODE0 0x00
-#define SPI_MODE1 0x04
-#define SPI_MODE2 0x08
-#define SPI_MODE3 0x0C
-#define SPI_MANUAL 0x00
-#define SPI_HALF_AUTO 0x01
-#define SPI_AUTO 0x02
-#define SPI_EEPROM_AUTO 0x03
-
-#define EDO_TIMING_MASK 0x03
-#define SAMPLE_RISING 0x00
-#define SAMPLE_DELAY_HALF 0x01
-#define SAMPLE_DELAY_ONE 0x02
-#define SAPMLE_DELAY_ONE_HALF 0x03
-#define TCS_MASK 0x0C
-
-#define NOT_BYPASS_SD 0x02
-#define DISABLE_SDIO_FUNC 0x04
-#define SELECT_1LUN 0x08
-
-#define PWR_GATE_EN 0x01
-#define LDO3318_PWR_MASK 0x06
-#define LDO_ON 0x00
-#define LDO_SUSPEND 0x04
-#define LDO_OFF 0x06
-
-#define SD_CFG1 0xFDA0
-#define SD_CFG2 0xFDA1
-#define SD_CFG3 0xFDA2
-#define SD_STAT1 0xFDA3
-#define SD_STAT2 0xFDA4
-#define SD_BUS_STAT 0xFDA5
-#define SD_PAD_CTL 0xFDA6
-#define SD_SAMPLE_POINT_CTL 0xFDA7
-#define SD_PUSH_POINT_CTL 0xFDA8
-#define SD_CMD0 0xFDA9
-#define SD_CMD1 0xFDAA
-#define SD_CMD2 0xFDAB
-#define SD_CMD3 0xFDAC
-#define SD_CMD4 0xFDAD
-#define SD_CMD5 0xFDAE
-#define SD_BYTE_CNT_L 0xFDAF
-#define SD_BYTE_CNT_H 0xFDB0
-#define SD_BLOCK_CNT_L 0xFDB1
-#define SD_BLOCK_CNT_H 0xFDB2
-#define SD_TRANSFER 0xFDB3
-#define SD_CMD_STATE 0xFDB5
-#define SD_DATA_STATE 0xFDB6
-
-#define DCM_DRP_CTL 0xFC23
-#define DCM_DRP_TRIG 0xFC24
-#define DCM_DRP_CFG 0xFC25
-#define DCM_DRP_WR_DATA_L 0xFC26
-#define DCM_DRP_WR_DATA_H 0xFC27
-#define DCM_DRP_RD_DATA_L 0xFC28
-#define DCM_DRP_RD_DATA_H 0xFC29
-#define SD_VPCLK0_CTL 0xFC2A
-#define SD_VPCLK1_CTL 0xFC2B
-#define SD_DCMPS0_CTL 0xFC2C
-#define SD_DCMPS1_CTL 0xFC2D
-#define SD_VPTX_CTL SD_VPCLK0_CTL
-#define SD_VPRX_CTL SD_VPCLK1_CTL
-#define SD_DCMPS_TX_CTL SD_DCMPS0_CTL
-#define SD_DCMPS_RX_CTL SD_DCMPS1_CTL
-
-#define CARD_CLK_SOURCE 0xFC2E
-
-#define CARD_PWR_CTL 0xFD50
-#define CARD_CLK_SWITCH 0xFD51
-#define CARD_SHARE_MODE 0xFD52
-#define CARD_DRIVE_SEL 0xFD53
-#define CARD_STOP 0xFD54
-#define CARD_OE 0xFD55
-#define CARD_AUTO_BLINK 0xFD56
-#define CARD_GPIO_DIR 0xFD57
-#define CARD_GPIO 0xFD58
-
-#define CARD_DATA_SOURCE 0xFD5B
-#define CARD_SELECT 0xFD5C
-#define SD30_DRIVE_SEL 0xFD5E
-
-#define CARD_CLK_EN 0xFD69
-
-#define SDIO_CTRL 0xFD6B
-
-#define FPDCTL 0xFC00
-#define PDINFO 0xFC01
-
-#define CLK_CTL 0xFC02
-#define CLK_DIV 0xFC03
-#define CLK_SEL 0xFC04
-
-#define SSC_DIV_N_0 0xFC0F
-#define SSC_DIV_N_1 0xFC10
-
-#define RCCTL 0xFC14
-
-#define FPGA_PULL_CTL 0xFC1D
-
-#define CARD_PULL_CTL1 0xFD60
-#define CARD_PULL_CTL2 0xFD61
-#define CARD_PULL_CTL3 0xFD62
-#define CARD_PULL_CTL4 0xFD63
-#define CARD_PULL_CTL5 0xFD64
-#define CARD_PULL_CTL6 0xFD65
-
-#define IRQEN0 0xFE20
-#define IRQSTAT0 0xFE21
-#define IRQEN1 0xFE22
-#define IRQSTAT1 0xFE23
-#define TLPRIEN 0xFE24
-#define TLPRISTAT 0xFE25
-#define TLPTIEN 0xFE26
-#define TLPTISTAT 0xFE27
-#define DMATC0 0xFE28
-#define DMATC1 0xFE29
-#define DMATC2 0xFE2A
-#define DMATC3 0xFE2B
-#define DMACTL 0xFE2C
-#define BCTL 0xFE2D
-#define RBBC0 0xFE2E
-#define RBBC1 0xFE2F
-#define RBDAT 0xFE30
-#define RBCTL 0xFE34
-#define CFGADDR0 0xFE35
-#define CFGADDR1 0xFE36
-#define CFGDATA0 0xFE37
-#define CFGDATA1 0xFE38
-#define CFGDATA2 0xFE39
-#define CFGDATA3 0xFE3A
-#define CFGRWCTL 0xFE3B
-#define PHYRWCTL 0xFE3C
-#define PHYDATA0 0xFE3D
-#define PHYDATA1 0xFE3E
-#define PHYADDR 0xFE3F
-#define MSGRXDATA0 0xFE40
-#define MSGRXDATA1 0xFE41
-#define MSGRXDATA2 0xFE42
-#define MSGRXDATA3 0xFE43
-#define MSGTXDATA0 0xFE44
-#define MSGTXDATA1 0xFE45
-#define MSGTXDATA2 0xFE46
-#define MSGTXDATA3 0xFE47
-#define MSGTXCTL 0xFE48
-#define PETXCFG 0xFE49
-
-#define CDRESUMECTL 0xFE52
-#define WAKE_SEL_CTL 0xFE54
-#define PME_FORCE_CTL 0xFE56
-#define ASPM_FORCE_CTL 0xFE57
-#define PM_CLK_FORCE_CTL 0xFE58
-#define PERST_GLITCH_WIDTH 0xFE5C
-#define CHANGE_LINK_STATE 0xFE5B
-#define RESET_LOAD_REG 0xFE5E
-#define HOST_SLEEP_STATE 0xFE60
-#define MAIN_PWR_OFF_CTL 0xFE70 /* RTS5208 */
-
-#define NFTS_TX_CTRL 0xFE72
-
-#define PWR_GATE_CTRL 0xFE75
-#define PWD_SUSPEND_EN 0xFE76
-
-#define EFUSE_CONTENT 0xFE5F
-
-#define XD_INIT 0xFD10
-#define XD_DTCTL 0xFD11
-#define XD_CTL 0xFD12
-#define XD_TRANSFER 0xFD13
-#define XD_CFG 0xFD14
-#define XD_ADDRESS0 0xFD15
-#define XD_ADDRESS1 0xFD16
-#define XD_ADDRESS2 0xFD17
-#define XD_ADDRESS3 0xFD18
-#define XD_ADDRESS4 0xFD19
-#define XD_DAT 0xFD1A
-#define XD_PAGE_CNT 0xFD1B
-#define XD_PAGE_STATUS 0xFD1C
-#define XD_BLOCK_STATUS 0xFD1D
-#define XD_BLOCK_ADDR1_L 0xFD1E
-#define XD_BLOCK_ADDR1_H 0xFD1F
-#define XD_BLOCK_ADDR2_L 0xFD20
-#define XD_BLOCK_ADDR2_H 0xFD21
-#define XD_BYTE_CNT_L 0xFD22
-#define XD_BYTE_CNT_H 0xFD23
-#define XD_PARITY 0xFD24
-#define XD_ECC_BIT1 0xFD25
-#define XD_ECC_BYTE1 0xFD26
-#define XD_ECC_BIT2 0xFD27
-#define XD_ECC_BYTE2 0xFD28
-#define XD_RESERVED0 0xFD29
-#define XD_RESERVED1 0xFD2A
-#define XD_RESERVED2 0xFD2B
-#define XD_RESERVED3 0xFD2C
-#define XD_CHK_DATA_STATUS 0xFD2D
-#define XD_CATCTL 0xFD2E
-
-#define MS_CFG 0xFD40
-#define MS_TPC 0xFD41
-#define MS_TRANS_CFG 0xFD42
-#define MS_TRANSFER 0xFD43
-#define MS_INT_REG 0xFD44
-#define MS_BYTE_CNT 0xFD45
-#define MS_SECTOR_CNT_L 0xFD46
-#define MS_SECTOR_CNT_H 0xFD47
-#define MS_DBUS_H 0xFD48
-
-#define SSC_CTL1 0xFC11
-#define SSC_CTL2 0xFC12
-
-#define OCPCTL 0xFC15
-#define OCPSTAT 0xFC16
-#define OCPCLR 0xFC17 /* 5208 */
-#define OCPPARA1 0xFC18
-#define OCPPARA2 0xFC19
-
-#define EFUSE_OP 0xFC20
-#define EFUSE_CTRL 0xFC21
-#define EFUSE_DATA 0xFC22
-
-#define SPI_COMMAND 0xFD80
-#define SPI_ADDR0 0xFD81
-#define SPI_ADDR1 0xFD82
-#define SPI_ADDR2 0xFD83
-#define SPI_ADDR3 0xFD84
-#define SPI_CA_NUMBER 0xFD85
-#define SPI_LENGTH0 0xFD86
-#define SPI_LENGTH1 0xFD87
-#define SPI_DATA 0xFD88
-#define SPI_DATA_NUMBER 0xFD89
-#define SPI_TRANSFER0 0xFD90
-#define SPI_TRANSFER1 0xFD91
-#define SPI_CONTROL 0xFD92
-#define SPI_SIG 0xFD93
-#define SPI_TCTL 0xFD94
-#define SPI_SLAVE_NUM 0xFD95
-#define SPI_CLK_DIVIDER0 0xFD96
-#define SPI_CLK_DIVIDER1 0xFD97
-
-#define SRAM_BASE 0xE600
-#define RBUF_BASE 0xF400
-#define PPBUF_BASE1 0xF800
-#define PPBUF_BASE2 0xFA00
-#define IMAGE_FLAG_ADDR0 0xCE80
-#define IMAGE_FLAG_ADDR1 0xCE81
-
-#define READ_OP 1
-#define WRITE_OP 2
-
-#define LCTLR 0x80
-
-#define POLLING_WAIT_CNT 1
-#define IDLE_MAX_COUNT 10
-#define SDIO_IDLE_COUNT 10
-
-#define DEBOUNCE_CNT 5
-
-void do_remaining_work(struct rtsx_chip *chip);
-void try_to_switch_sdio_ctrl(struct rtsx_chip *chip);
-void do_reset_sd_card(struct rtsx_chip *chip);
-void do_reset_xd_card(struct rtsx_chip *chip);
-void do_reset_ms_card(struct rtsx_chip *chip);
-void rtsx_power_off_card(struct rtsx_chip *chip);
-void rtsx_release_cards(struct rtsx_chip *chip);
-void rtsx_reset_cards(struct rtsx_chip *chip);
-void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip);
-void rtsx_init_cards(struct rtsx_chip *chip);
-int switch_ssc_clock(struct rtsx_chip *chip, int clk);
-int switch_normal_clock(struct rtsx_chip *chip, int clk);
-int enable_card_clock(struct rtsx_chip *chip, u8 card);
-int disable_card_clock(struct rtsx_chip *chip, u8 card);
-int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 sec_addr, u16 sec_cnt);
-void trans_dma_enable(enum dma_data_direction dir,
- struct rtsx_chip *chip, u32 byte_cnt, u8 pack_size);
-void toggle_gpio(struct rtsx_chip *chip, u8 gpio);
-void turn_on_led(struct rtsx_chip *chip, u8 gpio);
-void turn_off_led(struct rtsx_chip *chip, u8 gpio);
-
-int card_share_mode(struct rtsx_chip *chip, int card);
-int select_card(struct rtsx_chip *chip, int card);
-int detect_card_cd(struct rtsx_chip *chip, int card);
-int check_card_exist(struct rtsx_chip *chip, unsigned int lun);
-int check_card_ready(struct rtsx_chip *chip, unsigned int lun);
-int check_card_wp(struct rtsx_chip *chip, unsigned int lun);
-void eject_card(struct rtsx_chip *chip, unsigned int lun);
-u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun);
-
-static inline u32 get_card_size(struct rtsx_chip *chip, unsigned int lun)
-{
-#ifdef SUPPORT_SD_LOCK
- struct sd_info *sd_card = &chip->sd_card;
-
- if ((get_lun_card(chip, lun) == SD_CARD) &&
- (sd_card->sd_lock_status & SD_LOCKED))
- return 0;
-
- return chip->capacity[lun];
-#else
- return chip->capacity[lun];
-#endif
-}
-
-static inline int switch_clock(struct rtsx_chip *chip, int clk)
-{
- int retval = 0;
-
- if (chip->asic_code)
- retval = switch_ssc_clock(chip, clk);
- else
- retval = switch_normal_clock(chip, clk);
-
- return retval;
-}
-
-int card_power_on(struct rtsx_chip *chip, u8 card);
-int card_power_off(struct rtsx_chip *chip, u8 card);
-
-static inline int card_power_off_all(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = rtsx_write_register(chip, CARD_PWR_CTL, 0x0F, 0x0F);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static inline void rtsx_clear_xd_error(struct rtsx_chip *chip)
-{
- rtsx_write_register(chip, CARD_STOP, XD_STOP | XD_CLR_ERR,
- XD_STOP | XD_CLR_ERR);
-}
-
-static inline void rtsx_clear_sd_error(struct rtsx_chip *chip)
-{
- rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
- SD_STOP | SD_CLR_ERR);
-}
-
-static inline void rtsx_clear_ms_error(struct rtsx_chip *chip)
-{
- rtsx_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR,
- MS_STOP | MS_CLR_ERR);
-}
-
-static inline void rtsx_clear_spi_error(struct rtsx_chip *chip)
-{
- rtsx_write_register(chip, CARD_STOP, SPI_STOP | SPI_CLR_ERR,
- SPI_STOP | SPI_CLR_ERR);
-}
-
-#ifdef SUPPORT_SDIO_ASPM
-void dynamic_configure_sdio_aspm(struct rtsx_chip *chip);
-#endif
-
-#endif /* __REALTEK_RTSX_CARD_H */
diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c
deleted file mode 100644
index 6375032918d4..000000000000
--- a/drivers/staging/rts5208/rtsx_chip.c
+++ /dev/null
@@ -1,2161 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/vmalloc.h>
-
-#include "rtsx.h"
-#include "sd.h"
-#include "xd.h"
-#include "ms.h"
-
-static void rtsx_calibration(struct rtsx_chip *chip)
-{
- rtsx_write_phy_register(chip, 0x1B, 0x135E);
- wait_timeout(10);
- rtsx_write_phy_register(chip, 0x00, 0x0280);
- rtsx_write_phy_register(chip, 0x01, 0x7112);
- rtsx_write_phy_register(chip, 0x01, 0x7110);
- rtsx_write_phy_register(chip, 0x01, 0x7112);
- rtsx_write_phy_register(chip, 0x01, 0x7113);
- rtsx_write_phy_register(chip, 0x00, 0x0288);
-}
-
-void rtsx_enable_card_int(struct rtsx_chip *chip)
-{
- u32 reg = rtsx_readl(chip, RTSX_BIER);
- int i;
-
- for (i = 0; i <= chip->max_lun; i++) {
- if (chip->lun2card[i] & XD_CARD)
- reg |= XD_INT_EN;
- if (chip->lun2card[i] & SD_CARD)
- reg |= SD_INT_EN;
- if (chip->lun2card[i] & MS_CARD)
- reg |= MS_INT_EN;
- }
- if (chip->hw_bypass_sd)
- reg &= ~((u32)SD_INT_EN);
-
- rtsx_writel(chip, RTSX_BIER, reg);
-}
-
-void rtsx_enable_bus_int(struct rtsx_chip *chip)
-{
- u32 reg = 0;
-#ifndef DISABLE_CARD_INT
- int i;
-#endif
-
- reg = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN;
-
-#ifndef DISABLE_CARD_INT
- for (i = 0; i <= chip->max_lun; i++) {
- dev_dbg(rtsx_dev(chip), "lun2card[%d] = 0x%02x\n",
- i, chip->lun2card[i]);
-
- if (chip->lun2card[i] & XD_CARD)
- reg |= XD_INT_EN;
- if (chip->lun2card[i] & SD_CARD)
- reg |= SD_INT_EN;
- if (chip->lun2card[i] & MS_CARD)
- reg |= MS_INT_EN;
- }
- if (chip->hw_bypass_sd)
- reg &= ~((u32)SD_INT_EN);
-#endif
-
- if (chip->ic_version >= IC_VER_C)
- reg |= DELINK_INT_EN;
-#ifdef SUPPORT_OCP
- reg |= OC_INT_EN;
-#endif
- if (!chip->adma_mode)
- reg |= DATA_DONE_INT_EN;
-
- /* Enable Bus Interrupt */
- rtsx_writel(chip, RTSX_BIER, reg);
-
- dev_dbg(rtsx_dev(chip), "RTSX_BIER: 0x%08x\n", reg);
-}
-
-void rtsx_disable_bus_int(struct rtsx_chip *chip)
-{
- rtsx_writel(chip, RTSX_BIER, 0);
-}
-
-static int rtsx_pre_handle_sdio_old(struct rtsx_chip *chip)
-{
- int retval;
-
- if (chip->ignore_sd && CHK_SDIO_EXIST(chip)) {
- if (chip->asic_code) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL5,
- 0xFF,
- MS_INS_PU | SD_WP_PU |
- SD_CD_PU | SD_CMD_PU);
- if (retval)
- return retval;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL,
- 0xFF,
- FPGA_SD_PULL_CTL_EN);
- if (retval)
- return retval;
- }
- retval = rtsx_write_register(chip, CARD_SHARE_MODE, 0xFF,
- CARD_SHARE_48_SD);
- if (retval)
- return retval;
-
- /* Enable SDIO internal clock */
- retval = rtsx_write_register(chip, 0xFF2C, 0x01, 0x01);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, SDIO_CTRL, 0xFF,
- SDIO_BUS_CTRL | SDIO_CD_CTRL);
- if (retval)
- return retval;
-
- chip->sd_int = 1;
- chip->sd_io = 1;
- } else {
- chip->need_reset |= SD_CARD;
- }
-
- return STATUS_SUCCESS;
-}
-
-#ifdef HW_AUTO_SWITCH_SD_BUS
-static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip)
-{
- u8 tmp;
- bool sw_bypass_sd = false;
- int retval;
-
- if (chip->driver_first_load) {
- if (CHECK_PID(chip, 0x5288)) {
- retval = rtsx_read_register(chip, 0xFE5A, &tmp);
- if (retval)
- return retval;
- if (tmp & 0x08)
- sw_bypass_sd = true;
- } else if (CHECK_PID(chip, 0x5208)) {
- retval = rtsx_read_register(chip, 0xFE70, &tmp);
- if (retval)
- return retval;
- if (tmp & 0x80)
- sw_bypass_sd = true;
- }
- } else {
- if (chip->sdio_in_charge)
- sw_bypass_sd = true;
- }
- dev_dbg(rtsx_dev(chip), "chip->sdio_in_charge = %d\n",
- chip->sdio_in_charge);
- dev_dbg(rtsx_dev(chip), "chip->driver_first_load = %d\n",
- chip->driver_first_load);
- dev_dbg(rtsx_dev(chip), "sw_bypass_sd = %d\n",
- sw_bypass_sd);
-
- if (sw_bypass_sd) {
- u8 cd_toggle_mask = 0;
-
- retval = rtsx_read_register(chip, TLPTISTAT, &tmp);
- if (retval)
- return retval;
- cd_toggle_mask = 0x08;
-
- if (tmp & cd_toggle_mask) {
- /* Disable sdio_bus_auto_switch */
- if (CHECK_PID(chip, 0x5288)) {
- retval = rtsx_write_register(chip, 0xFE5A,
- 0x08, 0x00);
- if (retval)
- return retval;
- } else if (CHECK_PID(chip, 0x5208)) {
- retval = rtsx_write_register(chip, 0xFE70,
- 0x80, 0x00);
- if (retval)
- return retval;
- }
-
- retval = rtsx_write_register(chip, TLPTISTAT, 0xFF,
- tmp);
- if (retval)
- return retval;
-
- chip->need_reset |= SD_CARD;
- } else {
- dev_dbg(rtsx_dev(chip), "Chip inserted with SDIO!\n");
-
- if (chip->asic_code) {
- retval = sd_pull_ctl_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register
- (chip, FPGA_PULL_CTL,
- FPGA_SD_PULL_CTL_BIT | 0x20,
- 0);
- if (retval)
- return retval;
- }
- retval = card_share_mode(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- /* Enable sdio_bus_auto_switch */
- if (CHECK_PID(chip, 0x5288)) {
- retval = rtsx_write_register(chip, 0xFE5A,
- 0x08, 0x08);
- if (retval)
- return retval;
- } else if (CHECK_PID(chip, 0x5208)) {
- retval = rtsx_write_register(chip, 0xFE70,
- 0x80, 0x80);
- if (retval)
- return retval;
- }
-
- chip->chip_insert_with_sdio = 1;
- chip->sd_io = 1;
- }
- } else {
- retval = rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
- if (retval)
- return retval;
-
- chip->need_reset |= SD_CARD;
- }
-
- return STATUS_SUCCESS;
-}
-#endif
-
-static int rtsx_reset_aspm(struct rtsx_chip *chip)
-{
- int ret;
-
- if (chip->dynamic_aspm) {
- if (!CHK_SDIO_EXIST(chip) || !CHECK_PID(chip, 0x5288))
- return STATUS_SUCCESS;
-
- ret = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF,
- chip->aspm_l0s_l1_en);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
- }
-
- if (CHECK_PID(chip, 0x5208)) {
- ret = rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF, 0x3F);
- if (ret)
- return ret;
- }
- ret = rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- chip->aspm_level[0] = chip->aspm_l0s_l1_en;
- if (CHK_SDIO_EXIST(chip)) {
- chip->aspm_level[1] = chip->aspm_l0s_l1_en;
- ret = rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1,
- 0xC0, 0xFF, chip->aspm_l0s_l1_en);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- chip->aspm_enabled = 1;
-
- return STATUS_SUCCESS;
-}
-
-static int rtsx_enable_pcie_intr(struct rtsx_chip *chip)
-{
- int ret;
-
- if (!chip->asic_code || !CHECK_PID(chip, 0x5208)) {
- rtsx_enable_bus_int(chip);
- return STATUS_SUCCESS;
- }
-
- if (chip->phy_debug_mode) {
- ret = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0);
- if (ret)
- return ret;
- rtsx_disable_bus_int(chip);
- } else {
- rtsx_enable_bus_int(chip);
- }
-
- if (chip->ic_version >= IC_VER_D) {
- u16 reg;
-
- ret = rtsx_read_phy_register(chip, 0x00, &reg);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- reg &= 0xFE7F;
- reg |= 0x80;
- ret = rtsx_write_phy_register(chip, 0x00, reg);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ret = rtsx_read_phy_register(chip, 0x1C, &reg);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- reg &= 0xFFF7;
- ret = rtsx_write_phy_register(chip, 0x1C, reg);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- if (chip->driver_first_load && chip->ic_version < IC_VER_C)
- rtsx_calibration(chip);
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_reset_chip(struct rtsx_chip *chip)
-{
- int retval;
-
- rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
-
- rtsx_disable_aspm(chip);
-
- retval = rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 0x00);
- if (retval)
- return retval;
-
- /* Disable card clock */
- retval = rtsx_write_register(chip, CARD_CLK_EN, 0x1E, 0);
- if (retval)
- return retval;
-
-#ifdef SUPPORT_OCP
- /* SSC power on, OCD power on */
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
- retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN, 0);
- if (retval)
- return retval;
- } else {
- retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN,
- MS_OC_POWER_DOWN);
- if (retval)
- return retval;
- }
-
- retval = rtsx_write_register(chip, OCPPARA1, OCP_TIME_MASK,
- OCP_TIME_800);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, OCPPARA2, OCP_THD_MASK,
- OCP_THD_244_946);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, OCPCTL, 0xFF,
- CARD_OC_INT_EN | CARD_DETECT_EN);
- if (retval)
- return retval;
-#else
- /* OC power down */
- retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN,
- OC_POWER_DOWN);
- if (retval)
- return retval;
-#endif
-
- if (!CHECK_PID(chip, 0x5288)) {
- retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0xFF, 0x03);
- if (retval)
- return retval;
- }
-
- /* Turn off LED */
- retval = rtsx_write_register(chip, CARD_GPIO, 0xFF, 0x03);
- if (retval)
- return retval;
-
- /* Reset delink mode */
- retval = rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0);
- if (retval)
- return retval;
-
- /* Card driving select */
- retval = rtsx_write_register(chip, CARD_DRIVE_SEL, 0xFF,
- chip->card_drive_sel);
- if (retval)
- return retval;
-
-#ifdef LED_AUTO_BLINK
- retval = rtsx_write_register(chip, CARD_AUTO_BLINK, 0xFF,
- LED_BLINK_SPEED | BLINK_EN | LED_GPIO0);
- if (retval)
- return retval;
-#endif
-
- if (chip->asic_code) {
- /* Enable SSC Clock */
- retval = rtsx_write_register(chip, SSC_CTL1, 0xFF,
- SSC_8X_EN | SSC_SEL_4M);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SSC_CTL2, 0xFF, 0x12);
- if (retval)
- return retval;
- }
-
- /*
- * Disable cd_pwr_save (u_force_rst_core_en=0, u_cd_rst_core_en=0)
- * 0xFE5B
- * bit[1] u_cd_rst_core_en rst_value = 0
- * bit[2] u_force_rst_core_en rst_value = 0
- * bit[5] u_mac_phy_rst_n_dbg rst_value = 1
- * bit[4] u_non_sticky_rst_n_dbg rst_value = 0
- */
- retval = rtsx_write_register(chip, CHANGE_LINK_STATE, 0x16, 0x10);
- if (retval)
- return retval;
-
- /* Enable ASPM */
- if (chip->aspm_l0s_l1_en) {
- retval = rtsx_reset_aspm(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
- retval = rtsx_write_phy_register(chip, 0x07, 0x0129);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
- retval = rtsx_write_config_byte(chip, LCTLR,
- chip->aspm_l0s_l1_en);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_config_byte(chip, 0x81, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_SDIO_EXIST(chip)) {
- retval = rtsx_write_cfg_dw(chip,
- CHECK_PID(chip, 0x5288) ? 2 : 1,
- 0xC0, 0xFF00, 0x0100);
-
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- if (CHECK_PID(chip, 0x5288) && !CHK_SDIO_EXIST(chip)) {
- retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, 0x0103);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_cfg_dw(chip, 2, 0x84, 0xFF, 0x03);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT,
- LINK_RDY_INT);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, PERST_GLITCH_WIDTH, 0xFF, 0x80);
- if (retval)
- return retval;
-
- retval = rtsx_enable_pcie_intr(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- chip->need_reset = 0;
-
- chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
- if (chip->hw_bypass_sd)
- goto nextcard;
- dev_dbg(rtsx_dev(chip), "In %s, chip->int_reg = 0x%x\n", __func__,
- chip->int_reg);
- if (chip->int_reg & SD_EXIST) {
-#ifdef HW_AUTO_SWITCH_SD_BUS
- if (CHECK_PID(chip, 0x5208) && chip->ic_version < IC_VER_C)
- retval = rtsx_pre_handle_sdio_old(chip);
- else
- retval = rtsx_pre_handle_sdio_new(chip);
-
- dev_dbg(rtsx_dev(chip), "chip->need_reset = 0x%x (%s)\n",
- (unsigned int)(chip->need_reset), __func__);
-#else /* HW_AUTO_SWITCH_SD_BUS */
- retval = rtsx_pre_handle_sdio_old(chip);
-#endif /* HW_AUTO_SWITCH_SD_BUS */
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- } else {
- chip->sd_io = 0;
- retval = rtsx_write_register(chip, SDIO_CTRL,
- SDIO_BUS_CTRL | SDIO_CD_CTRL, 0);
- if (retval)
- return retval;
- }
-
-nextcard:
- if (chip->int_reg & XD_EXIST)
- chip->need_reset |= XD_CARD;
- if (chip->int_reg & MS_EXIST)
- chip->need_reset |= MS_CARD;
- if (chip->int_reg & CARD_EXIST) {
- retval = rtsx_write_register(chip, SSC_CTL1, SSC_RSTB,
- SSC_RSTB);
- if (retval)
- return retval;
- }
-
- dev_dbg(rtsx_dev(chip), "In %s, chip->need_reset = 0x%x\n", __func__,
- (unsigned int)(chip->need_reset));
-
- retval = rtsx_write_register(chip, RCCTL, 0x01, 0x00);
- if (retval)
- return retval;
-
- if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) {
- /* Turn off main power when entering S3/S4 state */
- retval = rtsx_write_register(chip, MAIN_PWR_OFF_CTL, 0x03,
- 0x03);
- if (retval)
- return retval;
- }
-
- if (chip->remote_wakeup_en && !chip->auto_delink_en) {
- retval = rtsx_write_register(chip, WAKE_SEL_CTL, 0x07, 0x07);
- if (retval)
- return retval;
- if (chip->aux_pwr_exist) {
- retval = rtsx_write_register(chip, PME_FORCE_CTL,
- 0xFF, 0x33);
- if (retval)
- return retval;
- }
- } else {
- retval = rtsx_write_register(chip, WAKE_SEL_CTL, 0x07, 0x04);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, PME_FORCE_CTL, 0xFF, 0x30);
- if (retval)
- return retval;
- }
-
- if (CHECK_PID(chip, 0x5208) && chip->ic_version >= IC_VER_D) {
- retval = rtsx_write_register(chip, PETXCFG, 0x1C, 0x14);
- if (retval)
- return retval;
- }
-
- if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
- retval = rtsx_clr_phy_reg_bit(chip, 0x1C, 2);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- if (chip->ft2_fast_mode) {
- retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF,
- MS_PARTIAL_POWER_ON |
- SD_PARTIAL_POWER_ON);
- if (retval)
- return retval;
- udelay(chip->pmos_pwr_on_interval);
- retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF,
- MS_POWER_ON | SD_POWER_ON);
- if (retval)
- return retval;
-
- wait_timeout(200);
- }
-
- /* Reset card */
- rtsx_reset_detected_cards(chip, 0);
-
- chip->driver_first_load = 0;
-
- return STATUS_SUCCESS;
-}
-
-static inline int valid_sd_speed_prior(u32 sd_speed_prior)
-{
- bool valid_para = true;
- int i;
-
- for (i = 0; i < 4; i++) {
- u8 tmp = (u8)(sd_speed_prior >> (i * 8));
-
- if (tmp < 0x01 || tmp > 0x04) {
- valid_para = false;
- break;
- }
- }
-
- return valid_para;
-}
-
-static inline int valid_sd_current_prior(u32 sd_current_prior)
-{
- bool valid_para = true;
- int i;
-
- for (i = 0; i < 4; i++) {
- u8 tmp = (u8)(sd_current_prior >> (i * 8));
-
- if (tmp > 0x03) {
- valid_para = false;
- break;
- }
- }
-
- return valid_para;
-}
-
-static int rts5208_init(struct rtsx_chip *chip)
-{
- int retval;
- u16 reg = 0;
- u8 val = 0;
-
- retval = rtsx_write_register(chip, CLK_SEL, 0x03, 0x03);
- if (retval)
- return retval;
- retval = rtsx_read_register(chip, CLK_SEL, &val);
- if (retval)
- return retval;
- chip->asic_code = val == 0 ? 1 : 0;
-
- if (chip->asic_code) {
- retval = rtsx_read_phy_register(chip, 0x1C, &reg);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "Value of phy register 0x1C is 0x%x\n",
- reg);
- chip->ic_version = (reg >> 4) & 0x07;
- chip->phy_debug_mode = reg & PHY_DEBUG_MODE ? 1 : 0;
-
- } else {
- retval = rtsx_read_register(chip, 0xFE80, &val);
- if (retval)
- return retval;
- chip->ic_version = val;
- chip->phy_debug_mode = 0;
- }
-
- retval = rtsx_read_register(chip, PDINFO, &val);
- if (retval)
- return retval;
- dev_dbg(rtsx_dev(chip), "PDINFO: 0x%x\n", val);
- chip->aux_pwr_exist = val & AUX_PWR_DETECTED ? 1 : 0;
-
- retval = rtsx_read_register(chip, 0xFE50, &val);
- if (retval)
- return retval;
- chip->hw_bypass_sd = val & 0x01 ? 1 : 0;
-
- rtsx_read_config_byte(chip, 0x0E, &val);
- if (val & 0x80)
- SET_SDIO_EXIST(chip);
- else
- CLR_SDIO_EXIST(chip);
-
- if (chip->use_hw_setting) {
- retval = rtsx_read_register(chip, CHANGE_LINK_STATE, &val);
- if (retval)
- return retval;
- chip->auto_delink_en = val & 0x80 ? 1 : 0;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int rts5288_init(struct rtsx_chip *chip)
-{
- int retval;
- u8 val = 0, max_func;
- u32 lval = 0;
-
- retval = rtsx_write_register(chip, CLK_SEL, 0x03, 0x03);
- if (retval)
- return retval;
- retval = rtsx_read_register(chip, CLK_SEL, &val);
- if (retval)
- return retval;
- chip->asic_code = val == 0 ? 1 : 0;
-
- chip->ic_version = 0;
- chip->phy_debug_mode = 0;
-
- retval = rtsx_read_register(chip, PDINFO, &val);
- if (retval)
- return retval;
- dev_dbg(rtsx_dev(chip), "PDINFO: 0x%x\n", val);
- chip->aux_pwr_exist = val & AUX_PWR_DETECTED ? 1 : 0;
-
- retval = rtsx_read_register(chip, CARD_SHARE_MODE, &val);
- if (retval)
- return retval;
- dev_dbg(rtsx_dev(chip), "CARD_SHARE_MODE: 0x%x\n", val);
- chip->baro_pkg = val & 0x04 ? QFN : LQFP;
-
- retval = rtsx_read_register(chip, 0xFE5A, &val);
- if (retval)
- return retval;
- chip->hw_bypass_sd = val & 0x10 ? 1 : 0;
-
- retval = rtsx_read_cfg_dw(chip, 0, 0x718, &lval);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- max_func = (u8)((lval >> 29) & 0x07);
- dev_dbg(rtsx_dev(chip), "Max function number: %d\n", max_func);
- if (max_func == 0x02)
- SET_SDIO_EXIST(chip);
- else
- CLR_SDIO_EXIST(chip);
-
- if (chip->use_hw_setting) {
- retval = rtsx_read_register(chip, CHANGE_LINK_STATE, &val);
- if (retval)
- return retval;
- chip->auto_delink_en = val & 0x80 ? 1 : 0;
-
- if (CHECK_BARO_PKG(chip, LQFP))
- chip->lun_mode = SD_MS_1LUN;
- else
- chip->lun_mode = DEFAULT_SINGLE;
- }
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_init_chip(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- struct xd_info *xd_card = &chip->xd_card;
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- unsigned int i;
-
- dev_dbg(rtsx_dev(chip), "Vendor ID: 0x%04x, Product ID: 0x%04x\n",
- chip->vendor_id, chip->product_id);
-
- chip->ic_version = 0;
-
- memset(xd_card, 0, sizeof(struct xd_info));
- memset(sd_card, 0, sizeof(struct sd_info));
- memset(ms_card, 0, sizeof(struct ms_info));
-
- chip->xd_reset_counter = 0;
- chip->sd_reset_counter = 0;
- chip->ms_reset_counter = 0;
-
- chip->xd_show_cnt = MAX_SHOW_CNT;
- chip->sd_show_cnt = MAX_SHOW_CNT;
- chip->ms_show_cnt = MAX_SHOW_CNT;
-
- chip->sd_io = 0;
- chip->auto_delink_cnt = 0;
- chip->auto_delink_allowed = 1;
- rtsx_set_stat(chip, RTSX_STAT_INIT);
-
- chip->aspm_enabled = 0;
- chip->chip_insert_with_sdio = 0;
- chip->sdio_aspm = 0;
- chip->sdio_idle = 0;
- chip->sdio_counter = 0;
- chip->cur_card = 0;
- chip->phy_debug_mode = 0;
- chip->sdio_func_exist = 0;
- memset(chip->sdio_raw_data, 0, 12);
-
- for (i = 0; i < MAX_ALLOWED_LUN_CNT; i++) {
- set_sense_type(chip, i, SENSE_TYPE_NO_SENSE);
- chip->rw_fail_cnt[i] = 0;
- }
-
- if (!valid_sd_speed_prior(chip->sd_speed_prior))
- chip->sd_speed_prior = 0x01040203;
-
- dev_dbg(rtsx_dev(chip), "sd_speed_prior = 0x%08x\n",
- chip->sd_speed_prior);
-
- if (!valid_sd_current_prior(chip->sd_current_prior))
- chip->sd_current_prior = 0x00010203;
-
- dev_dbg(rtsx_dev(chip), "sd_current_prior = 0x%08x\n",
- chip->sd_current_prior);
-
- if (chip->sd_ddr_tx_phase > 31 || chip->sd_ddr_tx_phase < 0)
- chip->sd_ddr_tx_phase = 0;
-
- if (chip->mmc_ddr_tx_phase > 31 || chip->mmc_ddr_tx_phase < 0)
- chip->mmc_ddr_tx_phase = 0;
-
- retval = rtsx_write_register(chip, FPDCTL, SSC_POWER_DOWN, 0);
- if (retval)
- return retval;
- wait_timeout(200);
- retval = rtsx_write_register(chip, CLK_DIV, 0x07, 0x07);
- if (retval)
- return retval;
- dev_dbg(rtsx_dev(chip), "chip->use_hw_setting = %d\n",
- chip->use_hw_setting);
-
- if (CHECK_PID(chip, 0x5208)) {
- retval = rts5208_init(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- } else if (CHECK_PID(chip, 0x5288)) {
- retval = rts5288_init(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- if (chip->ss_en == 2)
- chip->ss_en = 0;
-
- dev_dbg(rtsx_dev(chip), "chip->asic_code = %d\n", chip->asic_code);
- dev_dbg(rtsx_dev(chip), "chip->ic_version = 0x%x\n", chip->ic_version);
- dev_dbg(rtsx_dev(chip), "chip->phy_debug_mode = %d\n",
- chip->phy_debug_mode);
- dev_dbg(rtsx_dev(chip), "chip->aux_pwr_exist = %d\n",
- chip->aux_pwr_exist);
- dev_dbg(rtsx_dev(chip), "chip->sdio_func_exist = %d\n",
- chip->sdio_func_exist);
- dev_dbg(rtsx_dev(chip), "chip->hw_bypass_sd = %d\n",
- chip->hw_bypass_sd);
- dev_dbg(rtsx_dev(chip), "chip->aspm_l0s_l1_en = %d\n",
- chip->aspm_l0s_l1_en);
- dev_dbg(rtsx_dev(chip), "chip->lun_mode = %d\n", chip->lun_mode);
- dev_dbg(rtsx_dev(chip), "chip->auto_delink_en = %d\n",
- chip->auto_delink_en);
- dev_dbg(rtsx_dev(chip), "chip->ss_en = %d\n", chip->ss_en);
- dev_dbg(rtsx_dev(chip), "chip->baro_pkg = %d\n", chip->baro_pkg);
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
- chip->card2lun[SD_CARD] = 0;
- chip->card2lun[MS_CARD] = 1;
- chip->card2lun[XD_CARD] = 0xFF;
- chip->lun2card[0] = SD_CARD;
- chip->lun2card[1] = MS_CARD;
- chip->max_lun = 1;
- SET_SDIO_IGNORED(chip);
- } else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) {
- chip->card2lun[SD_CARD] = 0;
- chip->card2lun[MS_CARD] = 0;
- chip->card2lun[XD_CARD] = 0xFF;
- chip->lun2card[0] = SD_CARD | MS_CARD;
- chip->max_lun = 0;
- } else {
- chip->card2lun[XD_CARD] = 0;
- chip->card2lun[SD_CARD] = 0;
- chip->card2lun[MS_CARD] = 0;
- chip->lun2card[0] = XD_CARD | SD_CARD | MS_CARD;
- chip->max_lun = 0;
- }
-
- retval = rtsx_reset_chip(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-void rtsx_release_chip(struct rtsx_chip *chip)
-{
- xd_free_l2p_tbl(chip);
- ms_free_l2p_tbl(chip);
- chip->card_exist = 0;
- chip->card_ready = 0;
-}
-
-#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
-static inline void rtsx_blink_led(struct rtsx_chip *chip)
-{
- if (chip->card_exist && chip->blink_led) {
- if (chip->led_toggle_counter < LED_TOGGLE_INTERVAL) {
- chip->led_toggle_counter++;
- } else {
- chip->led_toggle_counter = 0;
- toggle_gpio(chip, LED_GPIO);
- }
- }
-}
-#endif
-
-static void rtsx_monitor_aspm_config(struct rtsx_chip *chip)
-{
- bool reg_changed, maybe_support_aspm;
- u32 tmp = 0;
- u8 reg0 = 0, reg1 = 0;
-
- maybe_support_aspm = false;
- reg_changed = false;
- rtsx_read_config_byte(chip, LCTLR, &reg0);
- if (chip->aspm_level[0] != reg0) {
- reg_changed = true;
- chip->aspm_level[0] = reg0;
- }
- if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
- rtsx_read_cfg_dw(chip, 1, 0xC0, &tmp);
- reg1 = (u8)tmp;
- if (chip->aspm_level[1] != reg1) {
- reg_changed = true;
- chip->aspm_level[1] = reg1;
- }
-
- if ((reg0 & 0x03) && (reg1 & 0x03))
- maybe_support_aspm = true;
-
- } else {
- if (reg0 & 0x03)
- maybe_support_aspm = true;
- }
-
- if (reg_changed) {
- if (maybe_support_aspm)
- chip->aspm_l0s_l1_en = 0x03;
-
- dev_dbg(rtsx_dev(chip),
- "aspm_level[0] = 0x%02x, aspm_level[1] = 0x%02x\n",
- chip->aspm_level[0], chip->aspm_level[1]);
-
- if (chip->aspm_l0s_l1_en) {
- chip->aspm_enabled = 1;
- } else {
- chip->aspm_enabled = 0;
- chip->sdio_aspm = 0;
- }
- rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF,
- 0x30 | chip->aspm_level[0] |
- (chip->aspm_level[1] << 2));
- }
-}
-
-static void rtsx_manage_ocp(struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_OCP
- if (!chip->ocp_int)
- return;
-
- rtsx_read_register(chip, OCPSTAT, &chip->ocp_stat);
-
- if (chip->card_exist & SD_CARD)
- sd_power_off_card3v3(chip);
- else if (chip->card_exist & MS_CARD)
- ms_power_off_card3v3(chip);
- else if (chip->card_exist & XD_CARD)
- xd_power_off_card3v3(chip);
-
- chip->ocp_int = 0;
-#endif
-}
-
-static void rtsx_manage_sd_lock(struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_SD_LOCK
- struct sd_info *sd_card = &chip->sd_card;
- u8 val;
-
- if (!sd_card->sd_erase_status)
- return;
-
- if (chip->card_exist & SD_CARD) {
- rtsx_read_register(chip, 0xFD30, &val);
- if (val & 0x02) {
- sd_card->sd_erase_status = SD_NOT_ERASE;
- sd_card->sd_lock_notify = 1;
- chip->need_reinit |= SD_CARD;
- }
- } else {
- sd_card->sd_erase_status = SD_NOT_ERASE;
- }
-#endif
-}
-
-static bool rtsx_is_ss_allowed(struct rtsx_chip *chip)
-{
- u32 val;
-
- if (!chip->ss_en || CHECK_PID(chip, 0x5288))
- return false;
-
- if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
- rtsx_read_cfg_dw(chip, 1, 0x04, &val);
- if (val & 0x07)
- return false;
- }
-
- return true;
-}
-
-static void rtsx_manage_ss(struct rtsx_chip *chip)
-{
- if (!rtsx_is_ss_allowed(chip) || chip->sd_io)
- return;
-
- if (rtsx_get_stat(chip) != RTSX_STAT_IDLE) {
- chip->ss_counter = 0;
- return;
- }
-
- if (chip->ss_counter < (chip->ss_idle_period / POLLING_INTERVAL))
- chip->ss_counter++;
- else
- rtsx_exclusive_enter_ss(chip);
-}
-
-static void rtsx_manage_aspm(struct rtsx_chip *chip)
-{
- u8 data;
-
- if (!CHECK_PID(chip, 0x5208))
- return;
-
- rtsx_monitor_aspm_config(chip);
-
-#ifdef SUPPORT_SDIO_ASPM
- if (!CHK_SDIO_EXIST(chip) || CHK_SDIO_IGNORED(chip) ||
- !chip->aspm_l0s_l1_en || !chip->dynamic_aspm)
- return;
-
- if (chip->sd_io) {
- dynamic_configure_sdio_aspm(chip);
- return;
- }
-
- if (chip->sdio_aspm)
- return;
-
- dev_dbg(rtsx_dev(chip), "SDIO enter ASPM!\n");
- data = 0x30 | (chip->aspm_level[1] << 2);
- rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, data);
- chip->sdio_aspm = 1;
-#endif
-}
-
-static void rtsx_manage_idle(struct rtsx_chip *chip)
-{
- if (chip->idle_counter < IDLE_MAX_COUNT) {
- chip->idle_counter++;
- return;
- }
-
- if (rtsx_get_stat(chip) == RTSX_STAT_IDLE)
- return;
-
- dev_dbg(rtsx_dev(chip), "Idle state!\n");
- rtsx_set_stat(chip, RTSX_STAT_IDLE);
-
-#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
- chip->led_toggle_counter = 0;
-#endif
- rtsx_force_power_on(chip, SSC_PDCTL);
-
- turn_off_led(chip, LED_GPIO);
-
- if (chip->auto_power_down && !chip->card_ready && !chip->sd_io)
- rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
-}
-
-static void rtsx_manage_2lun_mode(struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_OCP
- u8 sd_oc, ms_oc;
-
- sd_oc = chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER);
- ms_oc = chip->ocp_stat & (MS_OC_NOW | MS_OC_EVER);
-
- if (sd_oc || ms_oc)
- dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
- chip->ocp_stat);
-
- if (sd_oc && (chip->card_exist & SD_CARD)) {
- rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
- card_power_off(chip, SD_CARD);
- chip->card_fail |= SD_CARD;
- }
-
- if (ms_oc && (chip->card_exist & MS_CARD)) {
- rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
- card_power_off(chip, MS_CARD);
- chip->card_fail |= MS_CARD;
- }
-#endif
-}
-
-static void rtsx_manage_1lun_mode(struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_OCP
- if (!(chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)))
- return;
-
- dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
- chip->ocp_stat);
-
- if (chip->card_exist & SD_CARD) {
- rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
- chip->card_fail |= SD_CARD;
- } else if (chip->card_exist & MS_CARD) {
- rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
- chip->card_fail |= MS_CARD;
- } else if (chip->card_exist & XD_CARD) {
- rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
- chip->card_fail |= XD_CARD;
- }
- card_power_off(chip, SD_CARD);
-#endif
-}
-
-static void rtsx_delink_stage1(struct rtsx_chip *chip, int enter_L1,
- int stage3_cnt)
-{
- u8 val;
-
- rtsx_set_stat(chip, RTSX_STAT_DELINK);
-
- if (chip->asic_code && CHECK_PID(chip, 0x5208))
- rtsx_set_phy_reg_bit(chip, 0x1C, 2);
-
- if (chip->card_exist)
- dev_dbg(rtsx_dev(chip), "False card inserted, do force delink\n");
- else
- dev_dbg(rtsx_dev(chip), "No card inserted, do delink\n");
-
- if (enter_L1)
- rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 1);
-
- if (chip->card_exist)
- val = 0x02;
- else
- val = 0x0A;
-
- rtsx_write_register(chip, CHANGE_LINK_STATE, val, val);
-
- if (enter_L1)
- rtsx_enter_L1(chip);
-
- if (chip->card_exist)
- chip->auto_delink_cnt = stage3_cnt + 1;
-}
-
-static void rtsx_delink_stage(struct rtsx_chip *chip)
-{
- int delink_stage1_cnt, delink_stage2_cnt, delink_stage3_cnt;
- int enter_L1;
-
- if (!chip->auto_delink_en || !chip->auto_delink_allowed ||
- chip->card_ready || chip->card_ejected || chip->sd_io) {
- chip->auto_delink_cnt = 0;
- return;
- }
-
- enter_L1 = chip->auto_delink_in_L1 &&
- (chip->aspm_l0s_l1_en || chip->ss_en);
-
- delink_stage1_cnt = chip->delink_stage1_step;
- delink_stage2_cnt = delink_stage1_cnt + chip->delink_stage2_step;
- delink_stage3_cnt = delink_stage2_cnt + chip->delink_stage3_step;
-
- if (chip->auto_delink_cnt > delink_stage3_cnt)
- return;
-
- if (chip->auto_delink_cnt == delink_stage1_cnt)
- rtsx_delink_stage1(chip, enter_L1, delink_stage3_cnt);
-
- if (chip->auto_delink_cnt == delink_stage2_cnt) {
- dev_dbg(rtsx_dev(chip), "Try to do force delink\n");
-
- if (enter_L1)
- rtsx_exit_L1(chip);
-
- if (chip->asic_code && CHECK_PID(chip, 0x5208))
- rtsx_set_phy_reg_bit(chip, 0x1C, 2);
-
- rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x0A);
- }
-
- chip->auto_delink_cnt++;
-}
-
-void rtsx_polling_func(struct rtsx_chip *chip)
-{
- if (rtsx_chk_stat(chip, RTSX_STAT_SUSPEND))
- return;
-
- if (rtsx_chk_stat(chip, RTSX_STAT_DELINK))
- goto delink_stage;
-
- if (chip->polling_config) {
- u8 val;
-
- rtsx_read_config_byte(chip, 0, &val);
- }
-
- if (rtsx_chk_stat(chip, RTSX_STAT_SS))
- return;
-
- rtsx_manage_ocp(chip);
-
- rtsx_manage_sd_lock(chip);
-
- rtsx_init_cards(chip);
-
- rtsx_manage_ss(chip);
-
- rtsx_manage_aspm(chip);
-
- rtsx_manage_idle(chip);
-
- switch (rtsx_get_stat(chip)) {
- case RTSX_STAT_RUN:
-#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
- rtsx_blink_led(chip);
-#endif
- do_remaining_work(chip);
- break;
-
- case RTSX_STAT_IDLE:
- if (chip->sd_io && !chip->sd_int)
- try_to_switch_sdio_ctrl(chip);
-
- rtsx_enable_aspm(chip);
- break;
-
- default:
- break;
- }
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
- rtsx_manage_2lun_mode(chip);
- else
- rtsx_manage_1lun_mode(chip);
-
-delink_stage:
- rtsx_delink_stage(chip);
-}
-
-/**
- * rtsx_stop_cmd - stop command transfer and DMA transfer
- * @chip: Realtek's card reader chip
- * @card: flash card type
- *
- * Stop command transfer and DMA transfer.
- * This function is called in error handler.
- */
-void rtsx_stop_cmd(struct rtsx_chip *chip, int card)
-{
- int i;
-
- for (i = 0; i <= 8; i++) {
- int addr = RTSX_HCBAR + i * 4;
- u32 reg;
-
- reg = rtsx_readl(chip, addr);
- dev_dbg(rtsx_dev(chip), "BAR (0x%02x): 0x%08x\n", addr, reg);
- }
- rtsx_writel(chip, RTSX_HCBCTLR, STOP_CMD);
- rtsx_writel(chip, RTSX_HDBCTLR, STOP_DMA);
-
- for (i = 0; i < 16; i++) {
- u16 addr = 0xFE20 + (u16)i;
- u8 val;
-
- rtsx_read_register(chip, addr, &val);
- dev_dbg(rtsx_dev(chip), "0x%04X: 0x%02x\n", addr, val);
- }
-
- rtsx_write_register(chip, DMACTL, 0x80, 0x80);
- rtsx_write_register(chip, RBCTL, 0x80, 0x80);
-}
-
-#define MAX_RW_REG_CNT 1024
-
-int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data)
-{
- int i;
- u32 val = 3 << 30;
-
- val |= (u32)(addr & 0x3FFF) << 16;
- val |= (u32)mask << 8;
- val |= (u32)data;
-
- rtsx_writel(chip, RTSX_HAIMR, val);
-
- for (i = 0; i < MAX_RW_REG_CNT; i++) {
- val = rtsx_readl(chip, RTSX_HAIMR);
- if ((val & BIT(31)) == 0) {
- if (data != (u8)val)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
- }
- }
-
- return STATUS_TIMEDOUT;
-}
-
-int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data)
-{
- u32 val = 2 << 30;
- int i;
-
- if (data)
- *data = 0;
-
- val |= (u32)(addr & 0x3FFF) << 16;
-
- rtsx_writel(chip, RTSX_HAIMR, val);
-
- for (i = 0; i < MAX_RW_REG_CNT; i++) {
- val = rtsx_readl(chip, RTSX_HAIMR);
- if ((val & BIT(31)) == 0)
- break;
- }
-
- if (i >= MAX_RW_REG_CNT)
- return STATUS_TIMEDOUT;
-
- if (data)
- *data = (u8)(val & 0xFF);
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask,
- u32 val)
-{
- int retval;
- u8 mode = 0, tmp;
- int i;
-
- for (i = 0; i < 4; i++) {
- if (mask & 0xFF) {
- retval = rtsx_write_register(chip, CFGDATA0 + i,
- 0xFF,
- (u8)(val & mask & 0xFF));
- if (retval)
- return retval;
- mode |= (1 << i);
- }
- mask >>= 8;
- val >>= 8;
- }
-
- if (mode) {
- retval = rtsx_write_register(chip, CFGADDR0, 0xFF, (u8)addr);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CFGADDR1, 0xFF,
- (u8)(addr >> 8));
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CFGRWCTL, 0xFF,
- 0x80 | mode |
- ((func_no & 0x03) << 4));
- if (retval)
- return retval;
-
- for (i = 0; i < MAX_RW_REG_CNT; i++) {
- retval = rtsx_read_register(chip, CFGRWCTL, &tmp);
- if (retval)
- return retval;
- if ((tmp & 0x80) == 0)
- break;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val)
-{
- int retval;
- int i;
- u8 tmp;
- u32 data = 0;
-
- retval = rtsx_write_register(chip, CFGADDR0, 0xFF, (u8)addr);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CFGADDR1, 0xFF, (u8)(addr >> 8));
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CFGRWCTL, 0xFF,
- 0x80 | ((func_no & 0x03) << 4));
- if (retval)
- return retval;
-
- for (i = 0; i < MAX_RW_REG_CNT; i++) {
- retval = rtsx_read_register(chip, CFGRWCTL, &tmp);
- if (retval)
- return retval;
- if ((tmp & 0x80) == 0)
- break;
- }
-
- for (i = 0; i < 4; i++) {
- retval = rtsx_read_register(chip, CFGDATA0 + i, &tmp);
- if (retval)
- return retval;
- data |= (u32)tmp << (i * 8);
- }
-
- if (val)
- *val = data;
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
- int len)
-{
- u32 *data, *mask;
- u16 offset = addr % 4;
- u16 aligned_addr = addr - offset;
- int dw_len, i, j;
- int retval;
- size_t size;
-
- if (!buf)
- return STATUS_NOMEM;
-
- if ((len + offset) % 4)
- dw_len = (len + offset) / 4 + 1;
- else
- dw_len = (len + offset) / 4;
-
- dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len);
-
- size = array_size(dw_len, 4);
- data = vzalloc(size);
- if (!data)
- return STATUS_NOMEM;
-
- mask = vzalloc(size);
- if (!mask) {
- vfree(data);
- return STATUS_NOMEM;
- }
-
- j = 0;
- for (i = 0; i < len; i++) {
- mask[j] |= 0xFF << (offset * 8);
- data[j] |= buf[i] << (offset * 8);
- if (++offset == 4) {
- j++;
- offset = 0;
- }
- }
-
- print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, mask, size);
- print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, data, size);
-
- for (i = 0; i < dw_len; i++) {
- retval = rtsx_write_cfg_dw(chip, func, aligned_addr + i * 4,
- mask[i], data[i]);
- if (retval != STATUS_SUCCESS) {
- vfree(data);
- vfree(mask);
- return STATUS_FAIL;
- }
- }
-
- vfree(data);
- vfree(mask);
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
- int len)
-{
- u32 *data;
- u16 offset = addr % 4;
- u16 aligned_addr = addr - offset;
- int dw_len, i, j;
- int retval;
-
- if ((len + offset) % 4)
- dw_len = (len + offset) / 4 + 1;
- else
- dw_len = (len + offset) / 4;
-
- dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len);
-
- data = vmalloc(array_size(dw_len, 4));
- if (!data)
- return STATUS_NOMEM;
-
- for (i = 0; i < dw_len; i++) {
- retval = rtsx_read_cfg_dw(chip, func, aligned_addr + i * 4,
- data + i);
- if (retval != STATUS_SUCCESS) {
- vfree(data);
- return STATUS_FAIL;
- }
- }
-
- if (buf) {
- j = 0;
-
- for (i = 0; i < len; i++) {
- buf[i] = (u8)(data[j] >> (offset * 8));
- if (++offset == 4) {
- j++;
- offset = 0;
- }
- }
- }
-
- vfree(data);
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val)
-{
- int retval;
- bool finished = false;
- int i;
- u8 tmp;
-
- retval = rtsx_write_register(chip, PHYDATA0, 0xFF, (u8)val);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, PHYDATA1, 0xFF, (u8)(val >> 8));
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, PHYADDR, 0xFF, addr);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, PHYRWCTL, 0xFF, 0x81);
- if (retval)
- return retval;
-
- for (i = 0; i < 100000; i++) {
- retval = rtsx_read_register(chip, PHYRWCTL, &tmp);
- if (retval)
- return retval;
- if (!(tmp & 0x80)) {
- finished = true;
- break;
- }
- }
-
- if (!finished)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val)
-{
- int retval;
- bool finished = false;
- int i;
- u16 data = 0;
- u8 tmp;
-
- retval = rtsx_write_register(chip, PHYADDR, 0xFF, addr);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, PHYRWCTL, 0xFF, 0x80);
- if (retval)
- return retval;
-
- for (i = 0; i < 100000; i++) {
- retval = rtsx_read_register(chip, PHYRWCTL, &tmp);
- if (retval)
- return retval;
- if (!(tmp & 0x80)) {
- finished = true;
- break;
- }
- }
-
- if (!finished)
- return STATUS_FAIL;
-
- retval = rtsx_read_register(chip, PHYDATA0, &tmp);
- if (retval)
- return retval;
- data = tmp;
- retval = rtsx_read_register(chip, PHYDATA1, &tmp);
- if (retval)
- return retval;
- data |= (u16)tmp << 8;
-
- if (val)
- *val = data;
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val)
-{
- int retval;
- int i;
- u8 data = 0;
-
- retval = rtsx_write_register(chip, EFUSE_CTRL, 0xFF, 0x80 | addr);
- if (retval)
- return retval;
-
- for (i = 0; i < 100; i++) {
- retval = rtsx_read_register(chip, EFUSE_CTRL, &data);
- if (retval)
- return retval;
- if (!(data & 0x80))
- break;
- udelay(1);
- }
-
- if (data & 0x80)
- return STATUS_TIMEDOUT;
-
- retval = rtsx_read_register(chip, EFUSE_DATA, &data);
- if (retval)
- return retval;
- if (val)
- *val = data;
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val)
-{
- int retval;
- int i, j;
- u8 data = 0, tmp = 0xFF;
-
- for (i = 0; i < 8; i++) {
- if (val & (u8)(1 << i))
- continue;
-
- tmp &= (~(u8)(1 << i));
- dev_dbg(rtsx_dev(chip), "Write 0x%x to 0x%x\n", tmp, addr);
-
- retval = rtsx_write_register(chip, EFUSE_DATA, 0xFF, tmp);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, EFUSE_CTRL, 0xFF,
- 0xA0 | addr);
- if (retval)
- return retval;
-
- for (j = 0; j < 100; j++) {
- retval = rtsx_read_register(chip, EFUSE_CTRL, &data);
- if (retval)
- return retval;
- if (!(data & 0x80))
- break;
- wait_timeout(3);
- }
-
- if (data & 0x80)
- return STATUS_TIMEDOUT;
-
- wait_timeout(5);
- }
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
-{
- int retval;
- u16 value;
-
- retval = rtsx_read_phy_register(chip, reg, &value);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (value & (1 << bit)) {
- value &= ~(1 << bit);
- retval = rtsx_write_phy_register(chip, reg, value);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
-{
- int retval;
- u16 value;
-
- retval = rtsx_read_phy_register(chip, reg, &value);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if ((value & (1 << bit)) == 0) {
- value |= (1 << bit);
- retval = rtsx_write_phy_register(chip, reg, value);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static void rtsx_handle_pm_dstate(struct rtsx_chip *chip, u8 dstate)
-{
- u32 ultmp;
-
- dev_dbg(rtsx_dev(chip), "%04x set pm_dstate to %d\n",
- chip->product_id, dstate);
-
- if (CHK_SDIO_EXIST(chip)) {
- u8 func_no;
-
- if (CHECK_PID(chip, 0x5288))
- func_no = 2;
- else
- func_no = 1;
-
- rtsx_read_cfg_dw(chip, func_no, 0x84, &ultmp);
- dev_dbg(rtsx_dev(chip), "pm_dstate of function %d: 0x%x\n",
- (int)func_no, ultmp);
- rtsx_write_cfg_dw(chip, func_no, 0x84, 0xFF, dstate);
- }
-
- rtsx_write_config_byte(chip, 0x44, dstate);
- rtsx_write_config_byte(chip, 0x45, 0);
-}
-
-void rtsx_enter_L1(struct rtsx_chip *chip)
-{
- rtsx_handle_pm_dstate(chip, 2);
-}
-
-void rtsx_exit_L1(struct rtsx_chip *chip)
-{
- rtsx_write_config_byte(chip, 0x44, 0);
- rtsx_write_config_byte(chip, 0x45, 0);
-}
-
-void rtsx_enter_ss(struct rtsx_chip *chip)
-{
- dev_dbg(rtsx_dev(chip), "Enter Selective Suspend State!\n");
-
- rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
-
- if (chip->power_down_in_ss) {
- rtsx_power_off_card(chip);
- rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
- }
-
- if (CHK_SDIO_EXIST(chip))
- rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1,
- 0xC0, 0xFF00, 0x0100);
-
- if (chip->auto_delink_en) {
- rtsx_write_register(chip, HOST_SLEEP_STATE, 0x01, 0x01);
- } else {
- if (!chip->phy_debug_mode) {
- u32 tmp;
-
- tmp = rtsx_readl(chip, RTSX_BIER);
- tmp |= CARD_INT;
- rtsx_writel(chip, RTSX_BIER, tmp);
- }
-
- rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 0);
- }
-
- rtsx_enter_L1(chip);
-
- RTSX_CLR_DELINK(chip);
- rtsx_set_stat(chip, RTSX_STAT_SS);
-}
-
-void rtsx_exit_ss(struct rtsx_chip *chip)
-{
- dev_dbg(rtsx_dev(chip), "Exit Selective Suspend State!\n");
-
- rtsx_exit_L1(chip);
-
- if (chip->power_down_in_ss) {
- rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
- udelay(1000);
- }
-
- if (RTSX_TST_DELINK(chip)) {
- chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
- rtsx_reinit_cards(chip, 1);
- RTSX_CLR_DELINK(chip);
- } else if (chip->power_down_in_ss) {
- chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
- rtsx_reinit_cards(chip, 0);
- }
-}
-
-int rtsx_pre_handle_interrupt(struct rtsx_chip *chip)
-{
- u32 status, int_enable;
- bool exit_ss = false;
-#ifdef SUPPORT_OCP
- u32 ocp_int = 0;
-
- ocp_int = OC_INT;
-#endif
-
- if (chip->ss_en) {
- chip->ss_counter = 0;
- if (rtsx_get_stat(chip) == RTSX_STAT_SS) {
- exit_ss = true;
- rtsx_exit_L1(chip);
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- }
- }
-
- int_enable = rtsx_readl(chip, RTSX_BIER);
- chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
- if (((chip->int_reg & int_enable) == 0) ||
- chip->int_reg == 0xFFFFFFFF)
- return STATUS_FAIL;
-
- status = chip->int_reg &= (int_enable | 0x7FFFFF);
-
- if (status & CARD_INT) {
- chip->auto_delink_cnt = 0;
-
- if (status & SD_INT) {
- if (status & SD_EXIST) {
- set_bit(SD_NR, &chip->need_reset);
- } else {
- set_bit(SD_NR, &chip->need_release);
- chip->sd_reset_counter = 0;
- chip->sd_show_cnt = 0;
- clear_bit(SD_NR, &chip->need_reset);
- }
- } else {
- /*
- * If multi-luns, it's possible that
- * when plugging/unplugging one card
- * there is another card which still
- * exists in the slot. In this case,
- * all existed cards should be reset.
- */
- if (exit_ss && (status & SD_EXIST))
- set_bit(SD_NR, &chip->need_reinit);
- }
- if (!CHECK_PID(chip, 0x5288) || CHECK_BARO_PKG(chip, QFN)) {
- if (status & XD_INT) {
- if (status & XD_EXIST) {
- set_bit(XD_NR, &chip->need_reset);
- } else {
- set_bit(XD_NR, &chip->need_release);
- chip->xd_reset_counter = 0;
- chip->xd_show_cnt = 0;
- clear_bit(XD_NR, &chip->need_reset);
- }
- } else {
- if (exit_ss && (status & XD_EXIST))
- set_bit(XD_NR, &chip->need_reinit);
- }
- }
- if (status & MS_INT) {
- if (status & MS_EXIST) {
- set_bit(MS_NR, &chip->need_reset);
- } else {
- set_bit(MS_NR, &chip->need_release);
- chip->ms_reset_counter = 0;
- chip->ms_show_cnt = 0;
- clear_bit(MS_NR, &chip->need_reset);
- }
- } else {
- if (exit_ss && (status & MS_EXIST))
- set_bit(MS_NR, &chip->need_reinit);
- }
- }
-
-#ifdef SUPPORT_OCP
- chip->ocp_int = ocp_int & status;
-#endif
-
- if (chip->sd_io && (chip->int_reg & DATA_DONE_INT))
- chip->int_reg &= ~(u32)DATA_DONE_INT;
-
- return STATUS_SUCCESS;
-}
-
-void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat)
-{
- int retval;
-
- dev_dbg(rtsx_dev(chip), "%s, pm_stat = %d\n", __func__, pm_stat);
-
- rtsx_set_stat(chip, RTSX_STAT_SUSPEND);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS)
- return;
-
- rtsx_release_cards(chip);
- rtsx_disable_bus_int(chip);
- turn_off_led(chip, LED_GPIO);
-
-#ifdef HW_AUTO_SWITCH_SD_BUS
- if (chip->sd_io) {
- chip->sdio_in_charge = 1;
- if (CHECK_PID(chip, 0x5208)) {
- rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
- /* Enable sdio_bus_auto_switch */
- rtsx_write_register(chip, 0xFE70, 0x80, 0x80);
- } else if (CHECK_PID(chip, 0x5288)) {
- rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
- /* Enable sdio_bus_auto_switch */
- rtsx_write_register(chip, 0xFE5A, 0x08, 0x08);
- }
- }
-#endif
-
- if (CHECK_PID(chip, 0x5208) && chip->ic_version >= IC_VER_D) {
- /* u_force_clkreq_0 */
- rtsx_write_register(chip, PETXCFG, 0x08, 0x08);
- }
-
- if (pm_stat == PM_S1) {
- dev_dbg(rtsx_dev(chip), "Host enter S1\n");
- rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03,
- HOST_ENTER_S1);
- } else if (pm_stat == PM_S3) {
- if (chip->s3_pwr_off_delay > 0)
- wait_timeout(chip->s3_pwr_off_delay);
-
- dev_dbg(rtsx_dev(chip), "Host enter S3\n");
- rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03,
- HOST_ENTER_S3);
- }
-
- if (chip->do_delink_before_power_down && chip->auto_delink_en)
- rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 2);
-
- rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
-
- chip->cur_clk = 0;
- chip->cur_card = 0;
- chip->card_exist = 0;
-}
-
-void rtsx_enable_aspm(struct rtsx_chip *chip)
-{
- if (chip->aspm_l0s_l1_en && chip->dynamic_aspm && !chip->aspm_enabled) {
- dev_dbg(rtsx_dev(chip), "Try to enable ASPM\n");
- chip->aspm_enabled = 1;
-
- if (chip->asic_code && CHECK_PID(chip, 0x5208))
- rtsx_write_phy_register(chip, 0x07, 0);
- if (CHECK_PID(chip, 0x5208)) {
- rtsx_write_register(chip, ASPM_FORCE_CTL, 0xF3,
- 0x30 | chip->aspm_level[0]);
- } else {
- rtsx_write_config_byte(chip, LCTLR,
- chip->aspm_l0s_l1_en);
- }
-
- if (CHK_SDIO_EXIST(chip)) {
- u16 val = chip->aspm_l0s_l1_en | 0x0100;
-
- rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1,
- 0xC0, 0xFFF, val);
- }
- }
-}
-
-void rtsx_disable_aspm(struct rtsx_chip *chip)
-{
- if (CHECK_PID(chip, 0x5208))
- rtsx_monitor_aspm_config(chip);
-
- if (chip->aspm_l0s_l1_en && chip->dynamic_aspm && chip->aspm_enabled) {
- dev_dbg(rtsx_dev(chip), "Try to disable ASPM\n");
- chip->aspm_enabled = 0;
-
- if (chip->asic_code && CHECK_PID(chip, 0x5208))
- rtsx_write_phy_register(chip, 0x07, 0x0129);
- if (CHECK_PID(chip, 0x5208))
- rtsx_write_register(chip, ASPM_FORCE_CTL,
- 0xF3, 0x30);
- else
- rtsx_write_config_byte(chip, LCTLR, 0x00);
-
- wait_timeout(1);
- }
-}
-
-int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
-{
- int retval;
- int i, j;
- u16 reg_addr;
- u8 *ptr;
-
- if (!buf)
- return STATUS_ERROR;
-
- ptr = buf;
- reg_addr = PPBUF_BASE2;
- for (i = 0; i < buf_len / 256; i++) {
- rtsx_init_cmd(chip);
-
- for (j = 0; j < 256; j++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
-
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval < 0)
- return STATUS_FAIL;
-
- memcpy(ptr, rtsx_get_cmd_data(chip), 256);
- ptr += 256;
- }
-
- if (buf_len % 256) {
- rtsx_init_cmd(chip);
-
- for (j = 0; j < buf_len % 256; j++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
-
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval < 0)
- return STATUS_FAIL;
- }
-
- memcpy(ptr, rtsx_get_cmd_data(chip), buf_len % 256);
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
-{
- int retval;
- int i, j;
- u16 reg_addr;
- u8 *ptr;
-
- if (!buf)
- return STATUS_ERROR;
-
- ptr = buf;
- reg_addr = PPBUF_BASE2;
- for (i = 0; i < buf_len / 256; i++) {
- rtsx_init_cmd(chip);
-
- for (j = 0; j < 256; j++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF,
- *ptr);
- ptr++;
- }
-
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval < 0)
- return STATUS_FAIL;
- }
-
- if (buf_len % 256) {
- rtsx_init_cmd(chip);
-
- for (j = 0; j < buf_len % 256; j++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF,
- *ptr);
- ptr++;
- }
-
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval < 0)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_check_chip_exist(struct rtsx_chip *chip)
-{
- if (rtsx_readl(chip, 0) == 0xFFFFFFFF)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl)
-{
- int retval;
- u8 mask = 0;
-
- if (ctl & SSC_PDCTL)
- mask |= SSC_POWER_DOWN;
-
-#ifdef SUPPORT_OCP
- if (ctl & OC_PDCTL) {
- mask |= SD_OC_POWER_DOWN;
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
- mask |= MS_OC_POWER_DOWN;
- }
-#endif
-
- if (mask) {
- retval = rtsx_write_register(chip, FPDCTL, mask, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHECK_PID(chip, 0x5288))
- wait_timeout(200);
- }
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl)
-{
- int retval;
- u8 mask = 0, val = 0;
-
- if (ctl & SSC_PDCTL)
- mask |= SSC_POWER_DOWN;
-
-#ifdef SUPPORT_OCP
- if (ctl & OC_PDCTL) {
- mask |= SD_OC_POWER_DOWN;
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
- mask |= MS_OC_POWER_DOWN;
- }
-#endif
-
- if (mask) {
- val = mask;
- retval = rtsx_write_register(chip, FPDCTL, mask, val);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h
deleted file mode 100644
index bac65784d4a1..000000000000
--- a/drivers/staging/rts5208/rtsx_chip.h
+++ /dev/null
@@ -1,987 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_CHIP_H
-#define __REALTEK_RTSX_CHIP_H
-
-#include "rtsx.h"
-
-#define SUPPORT_CPRM
-#define SUPPORT_OCP
-#define SUPPORT_SDIO_ASPM
-#define SUPPORT_MAGIC_GATE
-#define SUPPORT_MSXC
-#define SUPPORT_SD_LOCK
-/* Hardware switch bus_ctl and cd_ctl automatically */
-#define HW_AUTO_SWITCH_SD_BUS
-/* Enable hardware interrupt write clear */
-#define HW_INT_WRITE_CLR
-/* #define LED_AUTO_BLINK */
-/* #define DISABLE_CARD_INT */
-
-#ifdef SUPPORT_MAGIC_GATE
- /* Using NORMAL_WRITE instead of AUTO_WRITE to set ICV */
- #define MG_SET_ICV_SLOW
- /* HW may miss ERR/CMDNK signal when sampling INT status. */
- #define MS_SAMPLE_INT_ERR
- /*
- * HW DO NOT support Wait_INT function
- * during READ_BYTES transfer mode
- */
- #define READ_BYTES_WAIT_INT
-#endif
-
-#ifdef SUPPORT_MSXC
-#define XC_POWERCLASS
-#define SUPPORT_PCGL_1P18
-#endif
-
-#ifndef LED_AUTO_BLINK
-#define REGULAR_BLINK
-#endif
-
-#define LED_BLINK_SPEED 5
-#define LED_TOGGLE_INTERVAL 6
-#define GPIO_TOGGLE_THRESHOLD 1024
-#define LED_GPIO 0
-
-#define POLLING_INTERVAL 30
-
-#define TRACE_ITEM_CNT 64
-
-#ifndef STATUS_SUCCESS
-#define STATUS_SUCCESS 0
-#endif
-#ifndef STATUS_FAIL
-#define STATUS_FAIL 1
-#endif
-#ifndef STATUS_TIMEDOUT
-#define STATUS_TIMEDOUT 2
-#endif
-#ifndef STATUS_NOMEM
-#define STATUS_NOMEM 3
-#endif
-#ifndef STATUS_READ_FAIL
-#define STATUS_READ_FAIL 4
-#endif
-#ifndef STATUS_WRITE_FAIL
-#define STATUS_WRITE_FAIL 5
-#endif
-#ifndef STATUS_ERROR
-#define STATUS_ERROR 10
-#endif
-
-#define PM_S1 1
-#define PM_S3 3
-
-/*
- * Transport return codes
- */
-
-#define TRANSPORT_GOOD 0 /* Transport good, command good */
-#define TRANSPORT_FAILED 1 /* Transport good, command failed */
-#define TRANSPORT_NO_SENSE 2 /* Command failed, no auto-sense */
-#define TRANSPORT_ERROR 3 /* Transport bad (i.e. device dead) */
-
-/*
- * Start-Stop-Unit
- */
-#define STOP_MEDIUM 0x00 /* access disable */
-#define MAKE_MEDIUM_READY 0x01 /* access enable */
-#define UNLOAD_MEDIUM 0x02 /* unload */
-#define LOAD_MEDIUM 0x03 /* load */
-
-/*
- * STANDARD_INQUIRY
- */
-#define QULIFIRE 0x00
-#define AENC_FNC 0x00
-#define TRML_IOP 0x00
-#define REL_ADR 0x00
-#define WBUS_32 0x00
-#define WBUS_16 0x00
-#define SYNC 0x00
-#define LINKED 0x00
-#define CMD_QUE 0x00
-#define SFT_RE 0x00
-
-#define VEN_ID_LEN 8 /* Vendor ID Length */
-#define PRDCT_ID_LEN 16 /* Product ID Length */
-#define PRDCT_REV_LEN 4 /* Product LOT Length */
-
-/* Dynamic flag definitions: used in set_bit() etc. */
-/* 0x00040000 transfer is active */
-#define RTSX_FLIDX_TRANS_ACTIVE 18
-/* 0x00100000 abort is in progress */
-#define RTSX_FLIDX_ABORTING 20
-/* 0x00200000 disconnect in progress */
-#define RTSX_FLIDX_DISCONNECTING 21
-
-#define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \
- (1UL << US_FLIDX_DISCONNECTING))
-
-/* 0x00400000 device reset in progress */
-#define RTSX_FLIDX_RESETTING 22
-/* 0x00800000 SCSI midlayer timed out */
-#define RTSX_FLIDX_TIMED_OUT 23
-#define DRCT_ACCESS_DEV 0x00 /* Direct Access Device */
-#define RMB_DISC 0x80 /* The Device is Removable */
-#define ANSI_SCSI2 0x02 /* Based on ANSI-SCSI2 */
-
-#define SCSI 0x00 /* Interface ID */
-
-#define WRITE_PROTECTED_MEDIA 0x07
-
-/*---- sense key ----*/
-#define ILI 0x20 /* ILI bit is on */
-
-#define NO_SENSE 0x00 /* not exist sense key */
-#define RECOVER_ERR 0x01 /* Target/Logical unit is recoverd */
-#define NOT_READY 0x02 /* Logical unit is not ready */
-#define MEDIA_ERR 0x03 /* medium/data error */
-#define HARDWARE_ERR 0x04 /* hardware error */
-#define ILGAL_REQ 0x05 /* CDB/parameter/identify msg error */
-#define UNIT_ATTENTION 0x06 /* unit attention condition occur */
-#define DAT_PRTCT 0x07 /* read/write is desable */
-#define BLNC_CHK 0x08 /* find blank/DOF in read */
- /* write to unblank area */
-#define CPY_ABRT 0x0a /* Copy/Compare/Copy&Verify illegal */
-#define ABRT_CMD 0x0b /* Target make the command in error */
-#define EQUAL 0x0c /* Search Data end with Equal */
-#define VLM_OVRFLW 0x0d /* Some data are left in buffer */
-#define MISCMP 0x0e /* find inequality */
-
-#define READ_ERR -1
-#define WRITE_ERR -2
-
-#define FIRST_RESET 0x01
-#define USED_EXIST 0x02
-
-/*
- * SENSE_DATA
- */
-/*---- valid ----*/
-#define SENSE_VALID 0x80 /* Sense data is valid as SCSI2 */
-#define SENSE_INVALID 0x00 /* Sense data is invalid as SCSI2 */
-
-/*---- error code ----*/
-#define CUR_ERR 0x70 /* current error */
-#define DEF_ERR 0x71 /* specific command error */
-
-/*---- sense key Information ----*/
-#define SNSKEYINFO_LEN 3 /* length of sense key information */
-
-#define SKSV 0x80
-#define CDB_ILLEGAL 0x40
-#define DAT_ILLEGAL 0x00
-#define BPV 0x08
-#define BIT_ILLEGAL0 0 /* bit0 is illegal */
-#define BIT_ILLEGAL1 1 /* bit1 is illegal */
-#define BIT_ILLEGAL2 2 /* bit2 is illegal */
-#define BIT_ILLEGAL3 3 /* bit3 is illegal */
-#define BIT_ILLEGAL4 4 /* bit4 is illegal */
-#define BIT_ILLEGAL5 5 /* bit5 is illegal */
-#define BIT_ILLEGAL6 6 /* bit6 is illegal */
-#define BIT_ILLEGAL7 7 /* bit7 is illegal */
-
-/*---- ASC ----*/
-#define ASC_NO_INFO 0x00
-#define ASC_MISCMP 0x1d
-#define ASC_INVLD_CDB 0x24
-#define ASC_INVLD_PARA 0x26
-#define ASC_LU_NOT_READY 0x04
-#define ASC_WRITE_ERR 0x0c
-#define ASC_READ_ERR 0x11
-#define ASC_LOAD_EJCT_ERR 0x53
-#define ASC_MEDIA_NOT_PRESENT 0x3A
-#define ASC_MEDIA_CHANGED 0x28
-#define ASC_MEDIA_IN_PROCESS 0x04
-#define ASC_WRITE_PROTECT 0x27
-#define ASC_LUN_NOT_SUPPORTED 0x25
-
-/*---- ASQC ----*/
-#define ASCQ_NO_INFO 0x00
-#define ASCQ_MEDIA_IN_PROCESS 0x01
-#define ASCQ_MISCMP 0x00
-#define ASCQ_INVLD_CDB 0x00
-#define ASCQ_INVLD_PARA 0x02
-#define ASCQ_LU_NOT_READY 0x02
-#define ASCQ_WRITE_ERR 0x02
-#define ASCQ_READ_ERR 0x00
-#define ASCQ_LOAD_EJCT_ERR 0x00
-#define ASCQ_WRITE_PROTECT 0x00
-
-struct sense_data_t {
- unsigned char err_code; /* error code */
- /* bit7 : valid */
- /* (1 : SCSI2) */
- /* (0 : Vendor * specific) */
- /* bit6-0 : error * code */
- /* (0x70 : current * error) */
- /* (0x71 : specific command error) */
- unsigned char seg_no; /* segment No. */
- unsigned char sense_key; /* byte5 : ILI */
- /* bit3-0 : sense key */
- unsigned char info[4]; /* information */
- unsigned char ad_sense_len; /* additional sense data length */
- unsigned char cmd_info[4]; /* command specific information */
- unsigned char asc; /* ASC */
- unsigned char ascq; /* ASCQ */
- unsigned char rfu; /* FRU */
- unsigned char sns_key_info[3];/* sense key specific information */
-};
-
-/* PCI Operation Register Address */
-#define RTSX_HCBAR 0x00
-#define RTSX_HCBCTLR 0x04
-#define RTSX_HDBAR 0x08
-#define RTSX_HDBCTLR 0x0C
-#define RTSX_HAIMR 0x10
-#define RTSX_BIPR 0x14
-#define RTSX_BIER 0x18
-
-/* Host command buffer control register */
-#define STOP_CMD (0x01 << 28)
-
-/* Host data buffer control register */
-#define SDMA_MODE 0x00
-#define ADMA_MODE (0x02 << 26)
-#define STOP_DMA (0x01 << 28)
-#define TRIG_DMA (0x01 << 31)
-
-/* Bus interrupt pending register */
-#define CMD_DONE_INT BIT(31)
-#define DATA_DONE_INT BIT(30)
-#define TRANS_OK_INT BIT(29)
-#define TRANS_FAIL_INT BIT(28)
-#define XD_INT BIT(27)
-#define MS_INT BIT(26)
-#define SD_INT BIT(25)
-#define GPIO0_INT BIT(24)
-#define OC_INT BIT(23)
-#define SD_WRITE_PROTECT BIT(19)
-#define XD_EXIST BIT(18)
-#define MS_EXIST BIT(17)
-#define SD_EXIST BIT(16)
-#define DELINK_INT GPIO0_INT
-#define MS_OC_INT BIT(23)
-#define SD_OC_INT BIT(22)
-
-#define CARD_INT (XD_INT | MS_INT | SD_INT)
-#define NEED_COMPLETE_INT (DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT)
-#define RTSX_INT (CMD_DONE_INT | NEED_COMPLETE_INT | CARD_INT | \
- GPIO0_INT | OC_INT)
-
-#define CARD_EXIST (XD_EXIST | MS_EXIST | SD_EXIST)
-
-/* Bus interrupt enable register */
-#define CMD_DONE_INT_EN BIT(31)
-#define DATA_DONE_INT_EN BIT(30)
-#define TRANS_OK_INT_EN BIT(29)
-#define TRANS_FAIL_INT_EN BIT(28)
-#define XD_INT_EN BIT(27)
-#define MS_INT_EN BIT(26)
-#define SD_INT_EN BIT(25)
-#define GPIO0_INT_EN BIT(24)
-#define OC_INT_EN BIT(23)
-#define DELINK_INT_EN GPIO0_INT_EN
-#define MS_OC_INT_EN BIT(23)
-#define SD_OC_INT_EN BIT(22)
-
-#define READ_REG_CMD 0
-#define WRITE_REG_CMD 1
-#define CHECK_REG_CMD 2
-
-#define HOST_TO_DEVICE 0
-#define DEVICE_TO_HOST 1
-
-#define RTSX_RESV_BUF_LEN 4096
-#define HOST_CMDS_BUF_LEN 1024
-#define HOST_SG_TBL_BUF_LEN (RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN)
-
-#define SD_NR 2
-#define MS_NR 3
-#define XD_NR 4
-#define SPI_NR 7
-#define SD_CARD BIT(SD_NR)
-#define MS_CARD BIT(MS_NR)
-#define XD_CARD BIT(XD_NR)
-#define SPI_CARD BIT(SPI_NR)
-
-#define MAX_ALLOWED_LUN_CNT 8
-
-#define XD_FREE_TABLE_CNT 1200
-#define MS_FREE_TABLE_CNT 512
-
-/* Bit Operation */
-#define SET_BIT(data, idx) ((data) |= 1 << (idx))
-#define CLR_BIT(data, idx) ((data) &= ~(1 << (idx)))
-#define CHK_BIT(data, idx) ((data) & (1 << (idx)))
-
-/* SG descriptor */
-#define RTSX_SG_INT 0x04
-#define RTSX_SG_END 0x02
-#define RTSX_SG_VALID 0x01
-
-#define RTSX_SG_NO_OP 0x00
-#define RTSX_SG_TRANS_DATA (0x02 << 4)
-#define RTSX_SG_LINK_DESC (0x03 << 4)
-
-struct rtsx_chip;
-
-typedef int (*card_rw_func)(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 sec_addr, u16 sec_cnt);
-
-/* Supported Clock */
-enum card_clock {CLK_20 = 1, CLK_30, CLK_40, CLK_50, CLK_60,
- CLK_80, CLK_100, CLK_120, CLK_150, CLK_200};
-
-enum RTSX_STAT {RTSX_STAT_INIT, RTSX_STAT_IDLE, RTSX_STAT_RUN, RTSX_STAT_SS,
- RTSX_STAT_DELINK, RTSX_STAT_SUSPEND,
- RTSX_STAT_ABORT, RTSX_STAT_DISCONNECT};
-enum IC_VER {IC_VER_AB, IC_VER_C = 2, IC_VER_D = 3};
-
-#define MAX_RESET_CNT 3
-
-/* For MS Card */
-#define MAX_DEFECTIVE_BLOCK 10
-
-struct zone_entry {
- u16 *l2p_table;
- u16 *free_table;
- u16 defect_list[MAX_DEFECTIVE_BLOCK]; /* For MS card only */
- int set_index;
- int get_index;
- int unused_blk_cnt;
- int disable_count;
- /* To indicate whether the L2P table of this zone has been built. */
- int build_flag;
-};
-
-#define TYPE_SD 0x0000
-#define TYPE_MMC 0x0001
-
-/* TYPE_SD */
-#define SD_HS 0x0100
-#define SD_SDR50 0x0200
-#define SD_DDR50 0x0400
-#define SD_SDR104 0x0800
-#define SD_HCXC 0x1000
-
-/* TYPE_MMC */
-#define MMC_26M 0x0100
-#define MMC_52M 0x0200
-#define MMC_4BIT 0x0400
-#define MMC_8BIT 0x0800
-#define MMC_SECTOR_MODE 0x1000
-#define MMC_DDR52 0x2000
-
-/* SD card */
-#define CHK_SD(sd_card) (((sd_card)->sd_type & 0xFF) == TYPE_SD)
-#define CHK_SD_HS(sd_card) (CHK_SD(sd_card) && \
- ((sd_card)->sd_type & SD_HS))
-#define CHK_SD_SDR50(sd_card) (CHK_SD(sd_card) && \
- ((sd_card)->sd_type & SD_SDR50))
-#define CHK_SD_DDR50(sd_card) (CHK_SD(sd_card) && \
- ((sd_card)->sd_type & SD_DDR50))
-#define CHK_SD_SDR104(sd_card) (CHK_SD(sd_card) && \
- ((sd_card)->sd_type & SD_SDR104))
-#define CHK_SD_HCXC(sd_card) (CHK_SD(sd_card) && \
- ((sd_card)->sd_type & SD_HCXC))
-#define CHK_SD_HC(sd_card) (CHK_SD_HCXC(sd_card) && \
- ((sd_card)->capacity <= 0x4000000))
-#define CHK_SD_XC(sd_card) (CHK_SD_HCXC(sd_card) && \
- ((sd_card)->capacity > 0x4000000))
-#define CHK_SD30_SPEED(sd_card) (CHK_SD_SDR50(sd_card) || \
- CHK_SD_DDR50(sd_card) || \
- CHK_SD_SDR104(sd_card))
-
-#define SET_SD(sd_card) ((sd_card)->sd_type = TYPE_SD)
-#define SET_SD_HS(sd_card) ((sd_card)->sd_type |= SD_HS)
-#define SET_SD_SDR50(sd_card) ((sd_card)->sd_type |= SD_SDR50)
-#define SET_SD_DDR50(sd_card) ((sd_card)->sd_type |= SD_DDR50)
-#define SET_SD_SDR104(sd_card) ((sd_card)->sd_type |= SD_SDR104)
-#define SET_SD_HCXC(sd_card) ((sd_card)->sd_type |= SD_HCXC)
-
-#define CLR_SD_HS(sd_card) ((sd_card)->sd_type &= ~SD_HS)
-#define CLR_SD_SDR50(sd_card) ((sd_card)->sd_type &= ~SD_SDR50)
-#define CLR_SD_DDR50(sd_card) ((sd_card)->sd_type &= ~SD_DDR50)
-#define CLR_SD_SDR104(sd_card) ((sd_card)->sd_type &= ~SD_SDR104)
-#define CLR_SD_HCXC(sd_card) ((sd_card)->sd_type &= ~SD_HCXC)
-
-/* MMC card */
-#define CHK_MMC(sd_card) (((sd_card)->sd_type & 0xFF) == \
- TYPE_MMC)
-#define CHK_MMC_26M(sd_card) (CHK_MMC(sd_card) && \
- ((sd_card)->sd_type & MMC_26M))
-#define CHK_MMC_52M(sd_card) (CHK_MMC(sd_card) && \
- ((sd_card)->sd_type & MMC_52M))
-#define CHK_MMC_4BIT(sd_card) (CHK_MMC(sd_card) && \
- ((sd_card)->sd_type & MMC_4BIT))
-#define CHK_MMC_8BIT(sd_card) (CHK_MMC(sd_card) && \
- ((sd_card)->sd_type & MMC_8BIT))
-#define CHK_MMC_SECTOR_MODE(sd_card) (CHK_MMC(sd_card) && \
- ((sd_card)->sd_type & MMC_SECTOR_MODE))
-#define CHK_MMC_DDR52(sd_card) (CHK_MMC(sd_card) && \
- ((sd_card)->sd_type & MMC_DDR52))
-
-#define SET_MMC(sd_card) ((sd_card)->sd_type = TYPE_MMC)
-#define SET_MMC_26M(sd_card) ((sd_card)->sd_type |= MMC_26M)
-#define SET_MMC_52M(sd_card) ((sd_card)->sd_type |= MMC_52M)
-#define SET_MMC_4BIT(sd_card) ((sd_card)->sd_type |= MMC_4BIT)
-#define SET_MMC_8BIT(sd_card) ((sd_card)->sd_type |= MMC_8BIT)
-#define SET_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type |= MMC_SECTOR_MODE)
-#define SET_MMC_DDR52(sd_card) ((sd_card)->sd_type |= MMC_DDR52)
-
-#define CLR_MMC_26M(sd_card) ((sd_card)->sd_type &= ~MMC_26M)
-#define CLR_MMC_52M(sd_card) ((sd_card)->sd_type &= ~MMC_52M)
-#define CLR_MMC_4BIT(sd_card) ((sd_card)->sd_type &= ~MMC_4BIT)
-#define CLR_MMC_8BIT(sd_card) ((sd_card)->sd_type &= ~MMC_8BIT)
-#define CLR_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type &= ~MMC_SECTOR_MODE)
-#define CLR_MMC_DDR52(sd_card) ((sd_card)->sd_type &= ~MMC_DDR52)
-
-#define CHK_MMC_HS(sd_card) (CHK_MMC_52M(sd_card) && \
- CHK_MMC_26M(sd_card))
-#define CLR_MMC_HS(sd_card) \
-do { \
- CLR_MMC_DDR52(sd_card); \
- CLR_MMC_52M(sd_card); \
- CLR_MMC_26M(sd_card); \
-} while (0)
-
-#define SD_SUPPORT_CLASS_TEN 0x01
-#define SD_SUPPORT_1V8 0x02
-
-#define SD_SET_CLASS_TEN(sd_card) ((sd_card)->sd_setting |= \
- SD_SUPPORT_CLASS_TEN)
-#define SD_CHK_CLASS_TEN(sd_card) ((sd_card)->sd_setting & \
- SD_SUPPORT_CLASS_TEN)
-#define SD_CLR_CLASS_TEN(sd_card) ((sd_card)->sd_setting &= \
- ~SD_SUPPORT_CLASS_TEN)
-#define SD_SET_1V8(sd_card) ((sd_card)->sd_setting |= \
- SD_SUPPORT_1V8)
-#define SD_CHK_1V8(sd_card) ((sd_card)->sd_setting & \
- SD_SUPPORT_1V8)
-#define SD_CLR_1V8(sd_card) ((sd_card)->sd_setting &= \
- ~SD_SUPPORT_1V8)
-
-struct sd_info {
- u16 sd_type;
- u8 err_code;
- u8 sd_data_buf_ready;
- u32 sd_addr;
- u32 capacity;
-
- u8 raw_csd[16];
- u8 raw_scr[8];
-
- /* Sequential RW */
- int seq_mode;
- enum dma_data_direction pre_dir;
- u32 pre_sec_addr;
- u16 pre_sec_cnt;
-
- int cleanup_counter;
-
- int sd_clock;
-
- int mmc_dont_switch_bus;
-
-#ifdef SUPPORT_CPRM
- int sd_pass_thru_en;
- int pre_cmd_err;
- u8 last_rsp_type;
- u8 rsp[17];
-#endif
-
- u8 func_group1_mask;
- u8 func_group2_mask;
- u8 func_group3_mask;
- u8 func_group4_mask;
-
- u8 sd_switch_fail;
- u8 sd_read_phase;
-
-#ifdef SUPPORT_SD_LOCK
- u8 sd_lock_status;
- u8 sd_erase_status;
- u8 sd_lock_notify;
-#endif
- int need_retune;
-};
-
-struct xd_delay_write_tag {
- u32 old_phyblock;
- u32 new_phyblock;
- u32 logblock;
- u8 pageoff;
- u8 delay_write_flag;
-};
-
-struct xd_info {
- u8 maker_code;
- u8 device_code;
- u8 block_shift;
- u8 page_off;
- u8 addr_cycle;
- u16 cis_block;
- u8 multi_flag;
- u8 err_code;
- u32 capacity;
-
- struct zone_entry *zone;
- int zone_cnt;
-
- struct xd_delay_write_tag delay_write;
- int cleanup_counter;
-
- int xd_clock;
-};
-
-#define MODE_512_SEQ 0x01
-#define MODE_2K_SEQ 0x02
-
-#define TYPE_MS 0x0000
-#define TYPE_MSPRO 0x0001
-
-#define MS_4BIT 0x0100
-#define MS_8BIT 0x0200
-#define MS_HG 0x0400
-#define MS_XC 0x0800
-
-#define HG8BIT (MS_HG | MS_8BIT)
-
-#define CHK_MSPRO(ms_card) (((ms_card)->ms_type & 0xFF) == TYPE_MSPRO)
-#define CHK_HG8BIT(ms_card) (CHK_MSPRO(ms_card) && \
- (((ms_card)->ms_type & HG8BIT) == HG8BIT))
-#define CHK_MSXC(ms_card) (CHK_MSPRO(ms_card) && \
- ((ms_card)->ms_type & MS_XC))
-#define CHK_MSHG(ms_card) (CHK_MSPRO(ms_card) && \
- ((ms_card)->ms_type & MS_HG))
-
-#define CHK_MS8BIT(ms_card) (((ms_card)->ms_type & MS_8BIT))
-#define CHK_MS4BIT(ms_card) (((ms_card)->ms_type & MS_4BIT))
-
-struct ms_delay_write_tag {
- u16 old_phyblock;
- u16 new_phyblock;
- u16 logblock;
- u8 pageoff;
- u8 delay_write_flag;
-};
-
-struct ms_info {
- u16 ms_type;
- u8 block_shift;
- u8 page_off;
- u16 total_block;
- u16 boot_block;
- u32 capacity;
-
- u8 check_ms_flow;
- u8 switch_8bit_fail;
- u8 err_code;
-
- struct zone_entry *segment;
- int segment_cnt;
-
- int pro_under_formatting;
- int format_status;
- u16 progress;
- u8 raw_sys_info[96];
-#ifdef SUPPORT_PCGL_1P18
- u8 raw_model_name[48];
-#endif
-
- u8 multi_flag;
-
- /* Sequential RW */
- u8 seq_mode;
- enum dma_data_direction pre_dir;
- u32 pre_sec_addr;
- u16 pre_sec_cnt;
- u32 total_sec_cnt;
-
- struct ms_delay_write_tag delay_write;
-
- int cleanup_counter;
-
- int ms_clock;
-
-#ifdef SUPPORT_MAGIC_GATE
- u8 magic_gate_id[16];
- u8 mg_entry_num;
- int mg_auth; /* flag to indicate authentication process */
-#endif
-};
-
-struct spi_info {
- u8 use_clk;
- u8 write_en;
- u16 clk_div;
- u8 err_code;
-
- int spi_clock;
-};
-
-/************/
-/* LUN mode */
-/************/
-/* Single LUN, support xD/SD/MS */
-#define DEFAULT_SINGLE 0
-/* 2 LUN mode, support SD/MS */
-#define SD_MS_2LUN 1
-/* Single LUN, but only support SD/MS, for Barossa LQFP */
-#define SD_MS_1LUN 2
-
-#define LAST_LUN_MODE 2
-
-/* Barossa package */
-#define QFN 0
-#define LQFP 1
-
-/******************/
-/* sd_ctl bit map */
-/******************/
-/* SD push point control, bit 0, 1 */
-#define SD_PUSH_POINT_CTL_MASK 0x03
-#define SD_PUSH_POINT_DELAY 0x01
-#define SD_PUSH_POINT_AUTO 0x02
-/* SD sample point control, bit 2, 3 */
-#define SD_SAMPLE_POINT_CTL_MASK 0x0C
-#define SD_SAMPLE_POINT_DELAY 0x04
-#define SD_SAMPLE_POINT_AUTO 0x08
-/* SD DDR Tx phase set by user, bit 4 */
-#define SD_DDR_TX_PHASE_SET_BY_USER 0x10
-/* MMC DDR Tx phase set by user, bit 5 */
-#define MMC_DDR_TX_PHASE_SET_BY_USER 0x20
-/* Support MMC DDR mode, bit 6 */
-#define SUPPORT_MMC_DDR_MODE 0x40
-/* Reset MMC at first */
-#define RESET_MMC_FIRST 0x80
-
-#define SEQ_START_CRITERIA 0x20
-
-/* MS Power Class En */
-#define POWER_CLASS_2_EN 0x02
-#define POWER_CLASS_1_EN 0x01
-
-#define MAX_SHOW_CNT 10
-#define MAX_RESET_CNT 3
-
-#define SDIO_EXIST 0x01
-#define SDIO_IGNORED 0x02
-
-#define CHK_SDIO_EXIST(chip) ((chip)->sdio_func_exist & SDIO_EXIST)
-#define SET_SDIO_EXIST(chip) ((chip)->sdio_func_exist |= SDIO_EXIST)
-#define CLR_SDIO_EXIST(chip) ((chip)->sdio_func_exist &= ~SDIO_EXIST)
-
-#define CHK_SDIO_IGNORED(chip) ((chip)->sdio_func_exist & SDIO_IGNORED)
-#define SET_SDIO_IGNORED(chip) ((chip)->sdio_func_exist |= \
- SDIO_IGNORED)
-#define CLR_SDIO_IGNORED(chip) ((chip)->sdio_func_exist &= \
- ~SDIO_IGNORED)
-
-struct rtsx_chip {
- struct rtsx_dev *rtsx;
-
- u32 int_reg; /* Bus interrupt pending register */
- char max_lun;
- void *context;
-
- void *host_cmds_ptr; /* host commands buffer pointer */
- dma_addr_t host_cmds_addr;
- int ci; /* Command Index */
-
- void *host_sg_tbl_ptr; /* SG descriptor table */
- dma_addr_t host_sg_tbl_addr;
- int sgi; /* SG entry index */
-
- struct scsi_cmnd *srb; /* current srb */
- struct sense_data_t sense_buffer[MAX_ALLOWED_LUN_CNT];
-
- int cur_clk; /* current card clock */
-
- /* Current accessed card */
- int cur_card;
-
- unsigned long need_release; /* need release bit map */
- unsigned long need_reset; /* need reset bit map */
- /*
- * Flag to indicate that this card is just resumed from SS state,
- * and need released before being resetted
- */
- unsigned long need_reinit;
-
- int rw_need_retry;
-
-#ifdef SUPPORT_OCP
- u32 ocp_int;
- u8 ocp_stat;
-#endif
-
- u8 card_exist; /* card exist bit map (physical exist) */
- u8 card_ready; /* card ready bit map (reset successfully) */
- u8 card_fail; /* card reset fail bit map */
- u8 card_ejected; /* card ejected bit map */
- u8 card_wp; /* card write protected bit map */
-
- u8 lun_mc; /*
- * flag to indicate whether to answer
- * MediaChange
- */
-
-#ifndef LED_AUTO_BLINK
- int led_toggle_counter;
-#endif
-
- int sd_reset_counter;
- int xd_reset_counter;
- int ms_reset_counter;
-
- /* card bus width */
- u8 card_bus_width[MAX_ALLOWED_LUN_CNT];
- /* card capacity */
- u32 capacity[MAX_ALLOWED_LUN_CNT];
- /* read/write card function pointer */
- card_rw_func rw_card[MAX_ALLOWED_LUN_CNT];
- /* read/write capacity, used for GPIO Toggle */
- u32 rw_cap[MAX_ALLOWED_LUN_CNT];
- /* card to lun mapping table */
- u8 card2lun[32];
- /* lun to card mapping table */
- u8 lun2card[MAX_ALLOWED_LUN_CNT];
-
- int rw_fail_cnt[MAX_ALLOWED_LUN_CNT];
-
- int sd_show_cnt;
- int xd_show_cnt;
- int ms_show_cnt;
-
- /* card information */
- struct sd_info sd_card;
- struct xd_info xd_card;
- struct ms_info ms_card;
-
- struct spi_info spi;
-
- int auto_delink_cnt;
- int auto_delink_allowed;
-
- int aspm_enabled;
-
- int sdio_aspm;
- int sdio_idle;
- int sdio_counter;
- u8 sdio_raw_data[12];
-
- u8 sd_io;
- u8 sd_int;
-
- u8 rtsx_flag;
-
- int ss_counter;
- int idle_counter;
- enum RTSX_STAT rtsx_stat;
-
- u16 vendor_id;
- u16 product_id;
- u8 ic_version;
-
- int driver_first_load;
-
-#ifdef HW_AUTO_SWITCH_SD_BUS
- int sdio_in_charge;
-#endif
-
- u8 aspm_level[2];
-
- int chip_insert_with_sdio;
-
- /* Options */
-
- int adma_mode;
-
- int auto_delink_en;
- int ss_en;
- u8 lun_mode;
- u8 aspm_l0s_l1_en;
-
- int power_down_in_ss;
-
- int sdr104_en;
- int ddr50_en;
- int sdr50_en;
-
- int baro_pkg;
-
- int asic_code;
- int phy_debug_mode;
- int hw_bypass_sd;
- int sdio_func_exist;
- int aux_pwr_exist;
- u8 ms_power_class_en;
-
- int mspro_formatter_enable;
-
- int remote_wakeup_en;
-
- int ignore_sd;
- int use_hw_setting;
-
- int ss_idle_period;
-
- int dynamic_aspm;
-
- int fpga_sd_sdr104_clk;
- int fpga_sd_ddr50_clk;
- int fpga_sd_sdr50_clk;
- int fpga_sd_hs_clk;
- int fpga_mmc_52m_clk;
- int fpga_ms_hg_clk;
- int fpga_ms_4bit_clk;
- int fpga_ms_1bit_clk;
-
- int asic_sd_sdr104_clk;
- int asic_sd_ddr50_clk;
- int asic_sd_sdr50_clk;
- int asic_sd_hs_clk;
- int asic_mmc_52m_clk;
- int asic_ms_hg_clk;
- int asic_ms_4bit_clk;
- int asic_ms_1bit_clk;
-
- u8 ssc_depth_sd_sdr104;
- u8 ssc_depth_sd_ddr50;
- u8 ssc_depth_sd_sdr50;
- u8 ssc_depth_sd_hs;
- u8 ssc_depth_mmc_52m;
- u8 ssc_depth_ms_hg;
- u8 ssc_depth_ms_4bit;
- u8 ssc_depth_low_speed;
-
- u8 card_drive_sel;
- u8 sd30_drive_sel_1v8;
- u8 sd30_drive_sel_3v3;
-
- u8 sd_400mA_ocp_thd;
- u8 sd_800mA_ocp_thd;
- u8 ms_ocp_thd;
-
- int ssc_en;
- int msi_en;
-
- int xd_timeout;
- int sd_timeout;
- int ms_timeout;
- int mspro_timeout;
-
- int auto_power_down;
-
- int sd_ddr_tx_phase;
- int mmc_ddr_tx_phase;
- int sd_default_tx_phase;
- int sd_default_rx_phase;
-
- int pmos_pwr_on_interval;
- int sd_voltage_switch_delay;
- int s3_pwr_off_delay;
-
- int force_clkreq_0;
- int ft2_fast_mode;
-
- int do_delink_before_power_down;
- int polling_config;
- int sdio_retry_cnt;
-
- int delink_stage1_step;
- int delink_stage2_step;
- int delink_stage3_step;
-
- int auto_delink_in_L1;
- int hp_watch_bios_hotplug;
- int support_ms_8bit;
-
- u8 blink_led;
- u8 phy_voltage;
- u8 max_payload;
-
- u32 sd_speed_prior;
- u32 sd_current_prior;
- u32 sd_ctl;
-};
-
-static inline struct device *rtsx_dev(const struct rtsx_chip *chip)
-{
- return &chip->rtsx->pci->dev;
-}
-
-#define rtsx_set_stat(chip, stat) \
-do { \
- if ((stat) != RTSX_STAT_IDLE) { \
- (chip)->idle_counter = 0; \
- } \
- (chip)->rtsx_stat = (enum RTSX_STAT)(stat); \
-} while (0)
-#define rtsx_get_stat(chip) ((chip)->rtsx_stat)
-#define rtsx_chk_stat(chip, stat) ((chip)->rtsx_stat == (stat))
-
-#define RTSX_SET_DELINK(chip) ((chip)->rtsx_flag |= 0x01)
-#define RTSX_CLR_DELINK(chip) ((chip)->rtsx_flag &= 0xFE)
-#define RTSX_TST_DELINK(chip) ((chip)->rtsx_flag & 0x01)
-
-#define CHECK_PID(chip, pid) ((chip)->product_id == (pid))
-#define CHECK_BARO_PKG(chip, pkg) ((chip)->baro_pkg == (pkg))
-#define CHECK_LUN_MODE(chip, mode) ((chip)->lun_mode == (mode))
-
-/* Power down control */
-#define SSC_PDCTL 0x01
-#define OC_PDCTL 0x02
-
-int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl);
-int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl);
-
-void rtsx_enable_card_int(struct rtsx_chip *chip);
-void rtsx_enable_bus_int(struct rtsx_chip *chip);
-void rtsx_disable_bus_int(struct rtsx_chip *chip);
-int rtsx_reset_chip(struct rtsx_chip *chip);
-int rtsx_init_chip(struct rtsx_chip *chip);
-void rtsx_release_chip(struct rtsx_chip *chip);
-void rtsx_polling_func(struct rtsx_chip *chip);
-void rtsx_stop_cmd(struct rtsx_chip *chip, int card);
-int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data);
-int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data);
-int rtsx_write_cfg_dw(struct rtsx_chip *chip,
- u8 func_no, u16 addr, u32 mask, u32 val);
-int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val);
-int rtsx_write_cfg_seq(struct rtsx_chip *chip,
- u8 func, u16 addr, u8 *buf, int len);
-int rtsx_read_cfg_seq(struct rtsx_chip *chip,
- u8 func, u16 addr, u8 *buf, int len);
-int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val);
-int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val);
-int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val);
-int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val);
-int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit);
-int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit);
-void rtsx_enter_ss(struct rtsx_chip *chip);
-void rtsx_exit_ss(struct rtsx_chip *chip);
-int rtsx_pre_handle_interrupt(struct rtsx_chip *chip);
-void rtsx_enter_L1(struct rtsx_chip *chip);
-void rtsx_exit_L1(struct rtsx_chip *chip);
-void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat);
-void rtsx_enable_aspm(struct rtsx_chip *chip);
-void rtsx_disable_aspm(struct rtsx_chip *chip);
-int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len);
-int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len);
-int rtsx_check_chip_exist(struct rtsx_chip *chip);
-
-#endif /* __REALTEK_RTSX_CHIP_H */
diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c
deleted file mode 100644
index c27cffb9ad8f..000000000000
--- a/drivers/staging/rts5208/rtsx_scsi.c
+++ /dev/null
@@ -1,3279 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-
-#include "rtsx.h"
-#include "sd.h"
-#include "ms.h"
-#include "spi.h"
-
-void scsi_show_command(struct rtsx_chip *chip)
-{
- struct scsi_cmnd *srb = chip->srb;
- char *what = NULL;
- bool unknown_cmd = false;
- int len;
-
- switch (srb->cmnd[0]) {
- case TEST_UNIT_READY:
- what = "TEST_UNIT_READY";
- break;
- case REZERO_UNIT:
- what = "REZERO_UNIT";
- break;
- case REQUEST_SENSE:
- what = "REQUEST_SENSE";
- break;
- case FORMAT_UNIT:
- what = "FORMAT_UNIT";
- break;
- case READ_BLOCK_LIMITS:
- what = "READ_BLOCK_LIMITS";
- break;
- case REASSIGN_BLOCKS:
- what = "REASSIGN_BLOCKS";
- break;
- case READ_6:
- what = "READ_6";
- break;
- case WRITE_6:
- what = "WRITE_6";
- break;
- case SEEK_6:
- what = "SEEK_6";
- break;
- case READ_REVERSE:
- what = "READ_REVERSE";
- break;
- case WRITE_FILEMARKS:
- what = "WRITE_FILEMARKS";
- break;
- case SPACE:
- what = "SPACE";
- break;
- case INQUIRY:
- what = "INQUIRY";
- break;
- case RECOVER_BUFFERED_DATA:
- what = "RECOVER_BUFFERED_DATA";
- break;
- case MODE_SELECT:
- what = "MODE_SELECT";
- break;
- case RESERVE:
- what = "RESERVE";
- break;
- case RELEASE:
- what = "RELEASE";
- break;
- case COPY:
- what = "COPY";
- break;
- case ERASE:
- what = "ERASE";
- break;
- case MODE_SENSE:
- what = "MODE_SENSE";
- break;
- case START_STOP:
- what = "START_STOP";
- break;
- case RECEIVE_DIAGNOSTIC:
- what = "RECEIVE_DIAGNOSTIC";
- break;
- case SEND_DIAGNOSTIC:
- what = "SEND_DIAGNOSTIC";
- break;
- case ALLOW_MEDIUM_REMOVAL:
- what = "ALLOW_MEDIUM_REMOVAL";
- break;
- case SET_WINDOW:
- what = "SET_WINDOW";
- break;
- case READ_CAPACITY:
- what = "READ_CAPACITY";
- break;
- case READ_10:
- what = "READ_10";
- break;
- case WRITE_10:
- what = "WRITE_10";
- break;
- case SEEK_10:
- what = "SEEK_10";
- break;
- case WRITE_VERIFY:
- what = "WRITE_VERIFY";
- break;
- case VERIFY:
- what = "VERIFY";
- break;
- case SEARCH_HIGH:
- what = "SEARCH_HIGH";
- break;
- case SEARCH_EQUAL:
- what = "SEARCH_EQUAL";
- break;
- case SEARCH_LOW:
- what = "SEARCH_LOW";
- break;
- case SET_LIMITS:
- what = "SET_LIMITS";
- break;
- case READ_POSITION:
- what = "READ_POSITION";
- break;
- case SYNCHRONIZE_CACHE:
- what = "SYNCHRONIZE_CACHE";
- break;
- case LOCK_UNLOCK_CACHE:
- what = "LOCK_UNLOCK_CACHE";
- break;
- case READ_DEFECT_DATA:
- what = "READ_DEFECT_DATA";
- break;
- case MEDIUM_SCAN:
- what = "MEDIUM_SCAN";
- break;
- case COMPARE:
- what = "COMPARE";
- break;
- case COPY_VERIFY:
- what = "COPY_VERIFY";
- break;
- case WRITE_BUFFER:
- what = "WRITE_BUFFER";
- break;
- case READ_BUFFER:
- what = "READ_BUFFER";
- break;
- case UPDATE_BLOCK:
- what = "UPDATE_BLOCK";
- break;
- case READ_LONG:
- what = "READ_LONG";
- break;
- case WRITE_LONG:
- what = "WRITE_LONG";
- break;
- case CHANGE_DEFINITION:
- what = "CHANGE_DEFINITION";
- break;
- case WRITE_SAME:
- what = "WRITE_SAME";
- break;
- case GPCMD_READ_SUBCHANNEL:
- what = "READ SUBCHANNEL";
- break;
- case READ_TOC:
- what = "READ_TOC";
- break;
- case GPCMD_READ_HEADER:
- what = "READ HEADER";
- break;
- case GPCMD_PLAY_AUDIO_10:
- what = "PLAY AUDIO (10)";
- break;
- case GPCMD_PLAY_AUDIO_MSF:
- what = "PLAY AUDIO MSF";
- break;
- case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
- what = "GET EVENT/STATUS NOTIFICATION";
- break;
- case GPCMD_PAUSE_RESUME:
- what = "PAUSE/RESUME";
- break;
- case LOG_SELECT:
- what = "LOG_SELECT";
- break;
- case LOG_SENSE:
- what = "LOG_SENSE";
- break;
- case GPCMD_STOP_PLAY_SCAN:
- what = "STOP PLAY/SCAN";
- break;
- case GPCMD_READ_DISC_INFO:
- what = "READ DISC INFORMATION";
- break;
- case GPCMD_READ_TRACK_RZONE_INFO:
- what = "READ TRACK INFORMATION";
- break;
- case GPCMD_RESERVE_RZONE_TRACK:
- what = "RESERVE TRACK";
- break;
- case GPCMD_SEND_OPC:
- what = "SEND OPC";
- break;
- case MODE_SELECT_10:
- what = "MODE_SELECT_10";
- break;
- case GPCMD_REPAIR_RZONE_TRACK:
- what = "REPAIR TRACK";
- break;
- case 0x59:
- what = "READ MASTER CUE";
- break;
- case MODE_SENSE_10:
- what = "MODE_SENSE_10";
- break;
- case GPCMD_CLOSE_TRACK:
- what = "CLOSE TRACK/SESSION";
- break;
- case 0x5C:
- what = "READ BUFFER CAPACITY";
- break;
- case 0x5D:
- what = "SEND CUE SHEET";
- break;
- case GPCMD_BLANK:
- what = "BLANK";
- break;
- case REPORT_LUNS:
- what = "REPORT LUNS";
- break;
- case MOVE_MEDIUM:
- what = "MOVE_MEDIUM or PLAY AUDIO (12)";
- break;
- case READ_12:
- what = "READ_12";
- break;
- case WRITE_12:
- what = "WRITE_12";
- break;
- case WRITE_VERIFY_12:
- what = "WRITE_VERIFY_12";
- break;
- case SEARCH_HIGH_12:
- what = "SEARCH_HIGH_12";
- break;
- case SEARCH_EQUAL_12:
- what = "SEARCH_EQUAL_12";
- break;
- case SEARCH_LOW_12:
- what = "SEARCH_LOW_12";
- break;
- case SEND_VOLUME_TAG:
- what = "SEND_VOLUME_TAG";
- break;
- case READ_ELEMENT_STATUS:
- what = "READ_ELEMENT_STATUS";
- break;
- case GPCMD_READ_CD_MSF:
- what = "READ CD MSF";
- break;
- case GPCMD_SCAN:
- what = "SCAN";
- break;
- case GPCMD_SET_SPEED:
- what = "SET CD SPEED";
- break;
- case GPCMD_MECHANISM_STATUS:
- what = "MECHANISM STATUS";
- break;
- case GPCMD_READ_CD:
- what = "READ CD";
- break;
- case 0xE1:
- what = "WRITE CONTINUE";
- break;
- case WRITE_LONG_2:
- what = "WRITE_LONG_2";
- break;
- case VENDOR_CMND:
- what = "Realtek's vendor command";
- break;
- default:
- what = "(unknown command)";
- unknown_cmd = true;
- break;
- }
-
- if (srb->cmnd[0] != TEST_UNIT_READY)
- dev_dbg(rtsx_dev(chip), "Command %s (%d bytes)\n",
- what, srb->cmd_len);
-
- if (unknown_cmd) {
- len = min_t(unsigned short, srb->cmd_len, 16);
- dev_dbg(rtsx_dev(chip), "%*ph\n", len, srb->cmnd);
- }
-}
-
-void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type)
-{
- switch (sense_type) {
- case SENSE_TYPE_MEDIA_CHANGE:
- set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_NOT_PRESENT:
- set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_LBA_OVER_RANGE:
- set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT:
- set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_WRITE_PROTECT:
- set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR:
- set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_WRITE_ERR:
- set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD:
- set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0,
- ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1);
- break;
-
- case SENSE_TYPE_FORMAT_IN_PROGRESS:
- set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, 0, 0);
- break;
-
- case SENSE_TYPE_FORMAT_CMD_FAILED:
- set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0);
- break;
-
-#ifdef SUPPORT_MAGIC_GATE
- case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB:
- set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0);
- break;
-
- case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN:
- set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0);
- break;
-
- case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM:
- set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0);
- break;
-
- case SENSE_TYPE_MG_WRITE_ERR:
- set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0);
- break;
-#endif
-
-#ifdef SUPPORT_SD_LOCK
- case SENSE_TYPE_MEDIA_READ_FORBIDDEN:
- set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x11, 0x13, 0, 0);
- break;
-#endif
-
- case SENSE_TYPE_NO_SENSE:
- default:
- set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0);
- break;
- }
-}
-
-void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code,
- u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0,
- u16 sns_key_info1)
-{
- struct sense_data_t *sense = &chip->sense_buffer[lun];
-
- sense->err_code = err_code;
- sense->sense_key = sense_key;
- sense->info[0] = (u8)(info >> 24);
- sense->info[1] = (u8)(info >> 16);
- sense->info[2] = (u8)(info >> 8);
- sense->info[3] = (u8)info;
-
- sense->ad_sense_len = sizeof(struct sense_data_t) - 8;
- sense->asc = asc;
- sense->ascq = ascq;
- if (sns_key_info0 != 0) {
- sense->sns_key_info[0] = SKSV | sns_key_info0;
- sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 4;
- sense->sns_key_info[2] = sns_key_info1 & 0x0f;
- }
-}
-
-static int test_unit_ready(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
-
- if (!(CHK_BIT(chip->lun_mc, lun))) {
- SET_BIT(chip->lun_mc, lun);
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
-#ifdef SUPPORT_SD_LOCK
- if (get_lun_card(chip, SCSI_LUN(srb)) == SD_CARD) {
- struct sd_info *sd_card = &chip->sd_card;
-
- if (sd_card->sd_lock_notify) {
- sd_card->sd_lock_notify = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- } else if (sd_card->sd_lock_status & SD_LOCKED) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_READ_FORBIDDEN);
- return TRANSPORT_FAILED;
- }
- }
-#endif
-
- return TRANSPORT_GOOD;
-}
-
-static unsigned char formatter_inquiry_str[20] = {
- 'M', 'E', 'M', 'O', 'R', 'Y', 'S', 'T', 'I', 'C', 'K',
-#ifdef SUPPORT_MAGIC_GATE
- '-', 'M', 'G', /* Byte[47:49] */
-#else
- 0x20, 0x20, 0x20, /* Byte[47:49] */
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
- 0x0B, /* Byte[50]: MG, MS, MSPro, MSXC */
-#else
- 0x09, /* Byte[50]: MS, MSPro, MSXC */
-#endif
- 0x00, /* Byte[51]: Category Specific Commands */
- 0x00, /* Byte[52]: Access Control and feature */
- 0x20, 0x20, 0x20, /* Byte[53:55] */
-};
-
-static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
- char *inquiry_default = (char *)"Generic-xD/SD/M.S. 1.00";
- char *inquiry_sdms = (char *)"Generic-SD/MemoryStick 1.00";
- char *inquiry_sd = (char *)"Generic-SD/MMC 1.00";
- char *inquiry_ms = (char *)"Generic-MemoryStick 1.00";
- char *inquiry_string;
- unsigned char sendbytes;
- unsigned char *buf;
- u8 card = get_lun_card(chip, lun);
- bool pro_formatter_flag = false;
- unsigned char inquiry_buf[] = {
- QULIFIRE | DRCT_ACCESS_DEV,
- RMB_DISC | 0x0D,
- 0x00,
- 0x01,
- 0x1f,
- 0x02,
- 0,
- REL_ADR | WBUS_32 | WBUS_16 | SYNC | LINKED | CMD_QUE | SFT_RE,
- };
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
- if (chip->lun2card[lun] == SD_CARD)
- inquiry_string = inquiry_sd;
- else
- inquiry_string = inquiry_ms;
-
- } else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) {
- inquiry_string = inquiry_sdms;
- } else {
- inquiry_string = inquiry_default;
- }
-
- buf = vmalloc(scsi_bufflen(srb));
- if (!buf)
- return TRANSPORT_ERROR;
-
-#ifdef SUPPORT_MAGIC_GATE
- if (chip->mspro_formatter_enable &&
- (chip->lun2card[lun] & MS_CARD))
-#else
- if (chip->mspro_formatter_enable)
-#endif
- if (!card || card == MS_CARD)
- pro_formatter_flag = true;
-
- if (pro_formatter_flag) {
- if (scsi_bufflen(srb) < 56)
- sendbytes = (unsigned char)(scsi_bufflen(srb));
- else
- sendbytes = 56;
-
- } else {
- if (scsi_bufflen(srb) < 36)
- sendbytes = (unsigned char)(scsi_bufflen(srb));
- else
- sendbytes = 36;
- }
-
- if (sendbytes > 8) {
- memcpy(buf, inquiry_buf, 8);
- memcpy(buf + 8, inquiry_string, min(sendbytes, 36) - 8);
- if (pro_formatter_flag) {
- /* Additional Length */
- buf[4] = 0x33;
- }
- } else {
- memcpy(buf, inquiry_buf, sendbytes);
- }
-
- if (pro_formatter_flag) {
- if (sendbytes > 36)
- memcpy(buf + 36, formatter_inquiry_str, sendbytes - 36);
- }
-
- scsi_set_resid(srb, 0);
-
- rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
-
- scsi_set_resid(srb, scsi_bufflen(srb));
-
- if (srb->cmnd[1] == 1)
- return TRANSPORT_GOOD;
-
- switch (srb->cmnd[0x4]) {
- case STOP_MEDIUM:
- /* Media disabled */
- return TRANSPORT_GOOD;
-
- case UNLOAD_MEDIUM:
- /* Media shall be unload */
- if (check_card_ready(chip, lun))
- eject_card(chip, lun);
- return TRANSPORT_GOOD;
-
- case MAKE_MEDIUM_READY:
- case LOAD_MEDIUM:
- if (check_card_ready(chip, lun))
- return TRANSPORT_GOOD;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
-
- break;
- }
-
- return TRANSPORT_ERROR;
-}
-
-static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int prevent;
-
- prevent = srb->cmnd[4] & 0x1;
-
- scsi_set_resid(srb, 0);
-
- if (prevent) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sense_data_t *sense;
- unsigned int lun = SCSI_LUN(srb);
- struct ms_info *ms_card = &chip->ms_card;
- unsigned char *tmp, *buf;
-
- sense = &chip->sense_buffer[lun];
-
- if ((get_lun_card(chip, lun) == MS_CARD) &&
- ms_card->pro_under_formatting) {
- if (ms_card->format_status == FORMAT_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- ms_card->pro_under_formatting = 0;
- ms_card->progress = 0;
- } else if (ms_card->format_status == FORMAT_IN_PROGRESS) {
- /* Logical Unit Not Ready Format in Progress */
- set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
- 0, (u16)(ms_card->progress));
- } else {
- /* Format Command Failed */
- set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
- ms_card->pro_under_formatting = 0;
- ms_card->progress = 0;
- }
-
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- }
-
- buf = vmalloc(scsi_bufflen(srb));
- if (!buf)
- return TRANSPORT_ERROR;
-
- tmp = (unsigned char *)sense;
- memcpy(buf, tmp, scsi_bufflen(srb));
-
- rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
- vfree(buf);
-
- scsi_set_resid(srb, 0);
- /* Reset Sense Data */
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- return TRANSPORT_GOOD;
-}
-
-static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd,
- int lun, u8 *buf, int buf_len)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int sys_info_offset;
- int data_size = buf_len;
- bool support_format = false;
- int i = 0;
-
- if (cmd == MODE_SENSE) {
- sys_info_offset = 8;
- if (data_size > 0x68)
- data_size = 0x68;
-
- buf[i++] = 0x67; /* Mode Data Length */
- } else {
- sys_info_offset = 12;
- if (data_size > 0x6C)
- data_size = 0x6C;
-
- buf[i++] = 0x00; /* Mode Data Length (MSB) */
- buf[i++] = 0x6A; /* Mode Data Length (LSB) */
- }
-
- /* Medium Type Code */
- if (check_card_ready(chip, lun)) {
- if (CHK_MSXC(ms_card)) {
- support_format = true;
- buf[i++] = 0x40;
- } else if (CHK_MSPRO(ms_card)) {
- support_format = true;
- buf[i++] = 0x20;
- } else {
- buf[i++] = 0x10;
- }
-
- /* WP */
- if (check_card_wp(chip, lun))
- buf[i++] = 0x80;
- else
- buf[i++] = 0x00;
-
- } else {
- buf[i++] = 0x00; /* MediaType */
- buf[i++] = 0x00; /* WP */
- }
-
- buf[i++] = 0x00; /* Reserved */
-
- if (cmd == MODE_SENSE_10) {
- buf[i++] = 0x00; /* Reserved */
- buf[i++] = 0x00; /* Block descriptor length(MSB) */
- buf[i++] = 0x00; /* Block descriptor length(LSB) */
-
- /* The Following Data is the content of "Page 0x20" */
- if (data_size >= 9)
- buf[i++] = 0x20; /* Page Code */
- if (data_size >= 10)
- buf[i++] = 0x62; /* Page Length */
- if (data_size >= 11)
- buf[i++] = 0x00; /* No Access Control */
- if (data_size >= 12) {
- if (support_format)
- buf[i++] = 0xC0; /* SF, SGM */
- else
- buf[i++] = 0x00;
- }
- } else {
- /* The Following Data is the content of "Page 0x20" */
- if (data_size >= 5)
- buf[i++] = 0x20; /* Page Code */
- if (data_size >= 6)
- buf[i++] = 0x62; /* Page Length */
- if (data_size >= 7)
- buf[i++] = 0x00; /* No Access Control */
- if (data_size >= 8) {
- if (support_format)
- buf[i++] = 0xC0; /* SF, SGM */
- else
- buf[i++] = 0x00;
- }
- }
-
- if (data_size > sys_info_offset) {
- /* 96 Bytes Attribute Data */
- int len = data_size - sys_info_offset;
-
- len = (len < 96) ? len : 96;
-
- memcpy(buf + sys_info_offset, ms_card->raw_sys_info, len);
- }
-}
-
-static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
- unsigned int data_size;
- int status;
- bool pro_formatter_flag;
- unsigned char page_code, *buf;
- u8 card = get_lun_card(chip, lun);
-
-#ifndef SUPPORT_MAGIC_GATE
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- scsi_set_resid(srb, scsi_bufflen(srb));
- return TRANSPORT_FAILED;
- }
-#endif
-
- pro_formatter_flag = false;
- data_size = 8;
-#ifdef SUPPORT_MAGIC_GATE
- if ((chip->lun2card[lun] & MS_CARD)) {
- if (!card || card == MS_CARD) {
- data_size = 108;
- if (chip->mspro_formatter_enable)
- pro_formatter_flag = true;
- }
- }
-#else
- if (card == MS_CARD) {
- if (chip->mspro_formatter_enable) {
- pro_formatter_flag = true;
- data_size = 108;
- }
- }
-#endif
-
- buf = kmalloc(data_size, GFP_KERNEL);
- if (!buf)
- return TRANSPORT_ERROR;
-
- page_code = srb->cmnd[2] & 0x3f;
-
- if (page_code == 0x3F || page_code == 0x1C ||
- page_code == 0x00 ||
- (pro_formatter_flag && page_code == 0x20)) {
- if (srb->cmnd[0] == MODE_SENSE) {
- if (page_code == 0x3F || page_code == 0x20) {
- ms_mode_sense(chip, srb->cmnd[0],
- lun, buf, data_size);
- } else {
- data_size = 4;
- buf[0] = 0x03;
- buf[1] = 0x00;
- if (check_card_wp(chip, lun))
- buf[2] = 0x80;
- else
- buf[2] = 0x00;
-
- buf[3] = 0x00;
- }
- } else {
- if (page_code == 0x3F || page_code == 0x20) {
- ms_mode_sense(chip, srb->cmnd[0],
- lun, buf, data_size);
- } else {
- data_size = 8;
- buf[0] = 0x00;
- buf[1] = 0x06;
- buf[2] = 0x00;
- if (check_card_wp(chip, lun))
- buf[3] = 0x80;
- else
- buf[3] = 0x00;
- buf[4] = 0x00;
- buf[5] = 0x00;
- buf[6] = 0x00;
- buf[7] = 0x00;
- }
- }
- status = TRANSPORT_GOOD;
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- scsi_set_resid(srb, scsi_bufflen(srb));
- status = TRANSPORT_FAILED;
- }
-
- if (status == TRANSPORT_GOOD) {
- unsigned int len = min_t(unsigned int, scsi_bufflen(srb),
- data_size);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
- }
- kfree(buf);
-
- return status;
-}
-
-static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_SD_LOCK
- struct sd_info *sd_card = &chip->sd_card;
-#endif
- unsigned int lun = SCSI_LUN(srb);
- int retval;
- u32 start_sec;
- u16 sec_cnt;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- if (!check_card_ready(chip, lun) || (get_card_size(chip, lun) == 0)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
-
- if (!(CHK_BIT(chip->lun_mc, lun))) {
- SET_BIT(chip->lun_mc, lun);
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_erase_status) {
- /* Accessing to any card is forbidden
- * until the erase procedure of SD is completed
- */
- dev_dbg(rtsx_dev(chip), "SD card being erased!\n");
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
- return TRANSPORT_FAILED;
- }
-
- if (get_lun_card(chip, lun) == SD_CARD) {
- if (sd_card->sd_lock_status & SD_LOCKED) {
- dev_dbg(rtsx_dev(chip), "SD card locked!\n");
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_READ_FORBIDDEN);
- return TRANSPORT_FAILED;
- }
- }
-#endif
-
- if (srb->cmnd[0] == READ_10 || srb->cmnd[0] == WRITE_10) {
- start_sec = ((u32)srb->cmnd[2] << 24) |
- ((u32)srb->cmnd[3] << 16) |
- ((u32)srb->cmnd[4] << 8) | ((u32)srb->cmnd[5]);
- sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
- } else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) {
- start_sec = ((u32)(srb->cmnd[1] & 0x1F) << 16) |
- ((u32)srb->cmnd[2] << 8) | ((u32)srb->cmnd[3]);
- sec_cnt = srb->cmnd[4];
- if (sec_cnt == 0)
- sec_cnt = 256;
- } else if ((srb->cmnd[0] == VENDOR_CMND) &&
- (srb->cmnd[1] == SCSI_APP_CMD) &&
- ((srb->cmnd[2] == PP_READ10) || (srb->cmnd[2] == PP_WRITE10))) {
- start_sec = ((u32)srb->cmnd[4] << 24) |
- ((u32)srb->cmnd[5] << 16) |
- ((u32)srb->cmnd[6] << 8) | ((u32)srb->cmnd[7]);
- sec_cnt = ((u16)(srb->cmnd[9]) << 8) | srb->cmnd[10];
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- /* In some test, we will receive a start_sec like 0xFFFFFFFF.
- * In this situation, start_sec + sec_cnt will overflow, so we
- * need to judge start_sec at first
- */
- if (start_sec > get_card_size(chip, lun) ||
- ((start_sec + sec_cnt) > get_card_size(chip, lun))) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE);
- return TRANSPORT_FAILED;
- }
-
- if (sec_cnt == 0) {
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
- }
-
- if (chip->rw_fail_cnt[lun] == 3) {
- dev_dbg(rtsx_dev(chip), "read/write fail three times in succession\n");
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- else
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-
- return TRANSPORT_FAILED;
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
- if (check_card_wp(chip, lun)) {
- dev_dbg(rtsx_dev(chip), "Write protected card!\n");
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_PROTECT);
- return TRANSPORT_FAILED;
- }
- }
-
- retval = card_rw(srb, chip, start_sec, sec_cnt);
- if (retval != STATUS_SUCCESS) {
- if (chip->need_release & chip->lun2card[lun]) {
- chip->rw_fail_cnt[lun] = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- } else {
- chip->rw_fail_cnt[lun]++;
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- set_sense_type
- (chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- else
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- }
- retval = TRANSPORT_FAILED;
- goto exit;
- } else {
- chip->rw_fail_cnt[lun] = 0;
- retval = TRANSPORT_GOOD;
- }
-
- scsi_set_resid(srb, 0);
-
-exit:
- return retval;
-}
-
-static int read_format_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned char *buf;
- unsigned int lun = SCSI_LUN(srb);
- unsigned int buf_len;
- u8 card = get_lun_card(chip, lun);
- u32 card_size;
- int desc_cnt;
- int i = 0;
-
- if (!check_card_ready(chip, lun)) {
- if (!chip->mspro_formatter_enable) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
- }
-
- buf_len = (scsi_bufflen(srb) > 12) ? 0x14 : 12;
-
- buf = kmalloc(buf_len, GFP_KERNEL);
- if (!buf)
- return TRANSPORT_ERROR;
-
- buf[i++] = 0;
- buf[i++] = 0;
- buf[i++] = 0;
-
- /* Capacity List Length */
- if (buf_len > 12 && chip->mspro_formatter_enable &&
- (chip->lun2card[lun] & MS_CARD) &&
- (!card || card == MS_CARD)) {
- buf[i++] = 0x10;
- desc_cnt = 2;
- } else {
- buf[i++] = 0x08;
- desc_cnt = 1;
- }
-
- while (desc_cnt) {
- if (check_card_ready(chip, lun)) {
- card_size = get_card_size(chip, lun);
- buf[i++] = (unsigned char)(card_size >> 24);
- buf[i++] = (unsigned char)(card_size >> 16);
- buf[i++] = (unsigned char)(card_size >> 8);
- buf[i++] = (unsigned char)card_size;
-
- if (desc_cnt == 2)
- buf[i++] = 2;
- else
- buf[i++] = 0;
- } else {
- buf[i++] = 0xFF;
- buf[i++] = 0xFF;
- buf[i++] = 0xFF;
- buf[i++] = 0xFF;
-
- if (desc_cnt == 2)
- buf[i++] = 3;
- else
- buf[i++] = 0;
- }
-
- buf[i++] = 0x00;
- buf[i++] = 0x02;
- buf[i++] = 0x00;
-
- desc_cnt--;
- }
-
- buf_len = min_t(unsigned int, scsi_bufflen(srb), buf_len);
- rtsx_stor_set_xfer_buf(buf, buf_len, srb);
- kfree(buf);
-
- scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
-
- return TRANSPORT_GOOD;
-}
-
-static int read_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned char *buf;
- unsigned int lun = SCSI_LUN(srb);
- u32 card_size;
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
-
- if (!(CHK_BIT(chip->lun_mc, lun))) {
- SET_BIT(chip->lun_mc, lun);
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- buf = kmalloc(8, GFP_KERNEL);
- if (!buf)
- return TRANSPORT_ERROR;
-
- card_size = get_card_size(chip, lun);
- buf[0] = (unsigned char)((card_size - 1) >> 24);
- buf[1] = (unsigned char)((card_size - 1) >> 16);
- buf[2] = (unsigned char)((card_size - 1) >> 8);
- buf[3] = (unsigned char)(card_size - 1);
-
- buf[4] = 0x00;
- buf[5] = 0x00;
- buf[6] = 0x02;
- buf[7] = 0x00;
-
- rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
- kfree(buf);
-
- scsi_set_resid(srb, 0);
-
- return TRANSPORT_GOOD;
-}
-
-static int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short len, i;
- int retval;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len; i++) {
- retval = spi_read_eeprom(chip, i, buf + i);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short len, i;
- int retval;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- if (len == 511) {
- retval = spi_erase_eeprom_chip(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- } else {
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb),
- len);
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- for (i = 0; i < len; i++) {
- retval = spi_write_eeprom(chip, i, buf[i]);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- vfree(buf);
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr, len, i;
- int retval;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3];
- len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
- if (addr < 0xFC00) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len; i++) {
- retval = rtsx_read_register(chip, addr + i, buf + i);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr, len, i;
- int retval;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3];
- len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
- if (addr < 0xFC00) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len; i++) {
- retval = rtsx_write_register(chip, addr + i, 0xFF, buf[i]);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int get_sd_csd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
-
- if (get_lun_card(chip, lun) != SD_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- scsi_set_resid(srb, 0);
- rtsx_stor_set_xfer_buf(sd_card->raw_csd, scsi_bufflen(srb), srb);
-
- return TRANSPORT_GOOD;
-}
-
-static int toggle_gpio_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- u8 gpio = srb->cmnd[2];
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- if (gpio > 3)
- gpio = 1;
- toggle_gpio(chip, gpio);
-
- return TRANSPORT_GOOD;
-}
-
-static int read_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- u8 addr, buf[4];
- u32 val;
- unsigned int len;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = srb->cmnd[4];
-
- val = rtsx_readl(chip, addr);
- dev_dbg(rtsx_dev(chip), "Host register (0x%x): 0x%x\n", addr, val);
-
- buf[0] = (u8)(val >> 24);
- buf[1] = (u8)(val >> 16);
- buf[2] = (u8)(val >> 8);
- buf[3] = (u8)val;
-
- len = min_t(unsigned int, scsi_bufflen(srb), 4);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- return TRANSPORT_GOOD;
-}
-
-static int write_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- u8 addr, buf[4];
- u32 val;
- unsigned int len;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = srb->cmnd[4];
-
- len = min_t(unsigned int, scsi_bufflen(srb), 4);
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- val = ((u32)buf[0] << 24) | ((u32)buf[1] << 16) | ((u32)buf[2]
- << 8) | buf[3];
-
- rtsx_writel(chip, addr, val);
-
- return TRANSPORT_GOOD;
-}
-
-static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
-
- if (srb->cmnd[3] == 1) {
- /* Variable Clock */
- struct xd_info *xd_card = &chip->xd_card;
- struct sd_info *sd_card = &chip->sd_card;
- struct ms_info *ms_card = &chip->ms_card;
-
- switch (srb->cmnd[4]) {
- case XD_CARD:
- xd_card->xd_clock = srb->cmnd[5];
- break;
-
- case SD_CARD:
- sd_card->sd_clock = srb->cmnd[5];
- break;
-
- case MS_CARD:
- ms_card->ms_clock = srb->cmnd[5];
- break;
-
- default:
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- } else if (srb->cmnd[3] == 2) {
- if (srb->cmnd[4]) {
- chip->blink_led = 1;
- } else {
- int retval;
-
- chip->blink_led = 0;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en &&
- (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- turn_off_led(chip, LED_GPIO);
- }
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int get_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
-
- if (srb->cmnd[3] == 1) {
- struct xd_info *xd_card = &chip->xd_card;
- struct sd_info *sd_card = &chip->sd_card;
- struct ms_info *ms_card = &chip->ms_card;
- u8 tmp;
-
- switch (srb->cmnd[4]) {
- case XD_CARD:
- tmp = (u8)(xd_card->xd_clock);
- break;
-
- case SD_CARD:
- tmp = (u8)(sd_card->sd_clock);
- break;
-
- case MS_CARD:
- tmp = (u8)(ms_card->ms_clock);
- break;
-
- default:
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- rtsx_stor_set_xfer_buf(&tmp, 1, srb);
- } else if (srb->cmnd[3] == 2) {
- u8 tmp = chip->blink_led;
-
- rtsx_stor_set_xfer_buf(&tmp, 1, srb);
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int dma_access_ring_buffer(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- unsigned int lun = SCSI_LUN(srb);
- u16 len;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- len = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
- len = min_t(u16, len, scsi_bufflen(srb));
-
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- dev_dbg(rtsx_dev(chip), "Read from device\n");
- else
- dev_dbg(rtsx_dev(chip), "Write to device\n");
-
- retval = rtsx_transfer_data(chip, 0, scsi_sglist(srb), len,
- scsi_sg_count(srb), srb->sc_data_direction,
- 1000);
- if (retval < 0) {
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- else
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
-
- return TRANSPORT_FAILED;
- }
- scsi_set_resid(srb, 0);
-
- return TRANSPORT_GOOD;
-}
-
-static int get_dev_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- struct ms_info *ms_card = &chip->ms_card;
- int buf_len;
- unsigned int lun = SCSI_LUN(srb);
- u8 card = get_lun_card(chip, lun);
- u8 status[32];
-#ifdef SUPPORT_OCP
- u8 oc_now_mask = 0, oc_ever_mask = 0;
-#endif
-
- memset(status, 0, 32);
-
- status[0] = (u8)(chip->product_id);
- status[1] = chip->ic_version;
-
- if (chip->auto_delink_en)
- status[2] = 0x10;
- else
- status[2] = 0x00;
-
- status[3] = 20;
- status[4] = 10;
- status[5] = 05;
- status[6] = 21;
-
- if (chip->card_wp)
- status[7] = 0x20;
- else
- status[7] = 0x00;
-
-#ifdef SUPPORT_OCP
- status[8] = 0;
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN) &&
- chip->lun2card[lun] == MS_CARD) {
- oc_now_mask = MS_OC_NOW;
- oc_ever_mask = MS_OC_EVER;
- } else {
- oc_now_mask = SD_OC_NOW;
- oc_ever_mask = SD_OC_EVER;
- }
-
- if (chip->ocp_stat & oc_now_mask)
- status[8] |= 0x02;
-
- if (chip->ocp_stat & oc_ever_mask)
- status[8] |= 0x01;
-#endif
-
- if (card == SD_CARD) {
- if (CHK_SD(sd_card)) {
- if (CHK_SD_HCXC(sd_card)) {
- if (sd_card->capacity > 0x4000000)
- status[0x0E] = 0x02;
- else
- status[0x0E] = 0x01;
- } else {
- status[0x0E] = 0x00;
- }
-
- if (CHK_SD_SDR104(sd_card))
- status[0x0F] = 0x03;
- else if (CHK_SD_DDR50(sd_card))
- status[0x0F] = 0x04;
- else if (CHK_SD_SDR50(sd_card))
- status[0x0F] = 0x02;
- else if (CHK_SD_HS(sd_card))
- status[0x0F] = 0x01;
- else
- status[0x0F] = 0x00;
- } else {
- if (CHK_MMC_SECTOR_MODE(sd_card))
- status[0x0E] = 0x01;
- else
- status[0x0E] = 0x00;
-
- if (CHK_MMC_DDR52(sd_card))
- status[0x0F] = 0x03;
- else if (CHK_MMC_52M(sd_card))
- status[0x0F] = 0x02;
- else if (CHK_MMC_26M(sd_card))
- status[0x0F] = 0x01;
- else
- status[0x0F] = 0x00;
- }
- } else if (card == MS_CARD) {
- if (CHK_MSPRO(ms_card)) {
- if (CHK_MSXC(ms_card))
- status[0x0E] = 0x01;
- else
- status[0x0E] = 0x00;
-
- if (CHK_HG8BIT(ms_card))
- status[0x0F] = 0x01;
- else
- status[0x0F] = 0x00;
- }
- }
-
-#ifdef SUPPORT_SD_LOCK
- if (card == SD_CARD) {
- status[0x17] = 0x80;
- if (sd_card->sd_erase_status)
- status[0x17] |= 0x01;
- if (sd_card->sd_lock_status & SD_LOCKED) {
- status[0x17] |= 0x02;
- status[0x07] |= 0x40;
- }
- if (sd_card->sd_lock_status & SD_PWD_EXIST)
- status[0x17] |= 0x04;
- } else {
- status[0x17] = 0x00;
- }
-
- dev_dbg(rtsx_dev(chip), "status[0x17] = 0x%x\n", status[0x17]);
-#endif
-
- status[0x18] = 0x8A;
- status[0x1A] = 0x28;
-#ifdef SUPPORT_SD_LOCK
- status[0x1F] = 0x01;
-#endif
-
- buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(status));
- rtsx_stor_set_xfer_buf(status, buf_len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
-
- return TRANSPORT_GOOD;
-}
-
-static int set_chip_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int phy_debug_mode;
- int retval;
- u16 reg;
-
- if (!CHECK_PID(chip, 0x5208)) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- phy_debug_mode = (int)(srb->cmnd[3]);
-
- if (phy_debug_mode) {
- chip->phy_debug_mode = 1;
- retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- rtsx_disable_bus_int(chip);
-
- retval = rtsx_read_phy_register(chip, 0x1C, &reg);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- reg |= 0x0001;
- retval = rtsx_write_phy_register(chip, 0x1C, reg);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
- } else {
- chip->phy_debug_mode = 0;
- retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0x77);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- rtsx_enable_bus_int(chip);
-
- retval = rtsx_read_phy_register(chip, 0x1C, &reg);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- reg &= 0xFFFE;
- retval = rtsx_write_phy_register(chip, 0x1C, reg);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval = STATUS_SUCCESS;
- unsigned int lun = SCSI_LUN(srb);
- u8 cmd_type, mask, value, idx;
- u16 addr;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- switch (srb->cmnd[3]) {
- case INIT_BATCHCMD:
- rtsx_init_cmd(chip);
- break;
-
- case ADD_BATCHCMD:
- cmd_type = srb->cmnd[4];
- if (cmd_type > 2) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- addr = (srb->cmnd[5] << 8) | srb->cmnd[6];
- mask = srb->cmnd[7];
- value = srb->cmnd[8];
- rtsx_add_cmd(chip, cmd_type, addr, mask, value);
- break;
-
- case SEND_BATCHCMD:
- retval = rtsx_send_cmd(chip, 0, 1000);
- break;
-
- case GET_BATCHRSP:
- idx = srb->cmnd[4];
- value = *(rtsx_get_cmd_data(chip) + idx);
- if (scsi_bufflen(srb) < 1) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- rtsx_stor_set_xfer_buf(&value, 1, srb);
- scsi_set_resid(srb, 0);
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int suit_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- switch (srb->cmnd[3]) {
- case INIT_BATCHCMD:
- case ADD_BATCHCMD:
- case SEND_BATCHCMD:
- case GET_BATCHRSP:
- return rw_mem_cmd_buf(srb, chip);
- default:
- return TRANSPORT_ERROR;
- }
-}
-
-static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr, len, i;
- int retval;
- u8 *buf;
- u16 val;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
- len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
-
- if (len % 2)
- len -= len % 2;
-
- if (len) {
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len / 2; i++) {
- retval = rtsx_read_phy_register(chip, addr + i, &val);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type
- (chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- buf[2 * i] = (u8)(val >> 8);
- buf[2 * i + 1] = (u8)val;
- }
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb),
- len);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- vfree(buf);
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr, len, i;
- int retval;
- u8 *buf;
- u16 val;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
- len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
-
- if (len % 2)
- len -= len % 2;
-
- if (len) {
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb),
- len);
-
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len / 2; i++) {
- val = ((u16)buf[2 * i] << 8) | buf[2 * i + 1];
- retval = rtsx_write_phy_register(chip, addr + i, val);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- vfree(buf);
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int erase_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr;
- int retval;
- u8 mode;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- mode = srb->cmnd[3];
- addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
- if (mode == 0) {
- retval = spi_erase_eeprom_chip(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- } else if (mode == 1) {
- retval = spi_erase_eeprom_byte(chip, addr);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- } else {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr, len, i;
- int retval;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
- len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
-
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len; i++) {
- retval = spi_read_eeprom(chip, addr + i, buf + i);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr, len, i;
- int retval;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
- len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len; i++) {
- retval = spi_write_eeprom(chip, addr + i, buf[i]);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- u8 addr, len, i;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = srb->cmnd[4];
- len = srb->cmnd[5];
-
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len; i++) {
- retval = rtsx_read_efuse(chip, addr + i, buf + i);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- len = (u8)min_t(unsigned int, scsi_bufflen(srb), len);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval, result = TRANSPORT_GOOD;
- u16 val;
- u8 addr, len, i;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = srb->cmnd[4];
- len = srb->cmnd[5];
-
- len = (u8)min_t(unsigned int, scsi_bufflen(srb), len);
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- return TRANSPORT_ERROR;
- }
-
- if (chip->asic_code) {
- retval = rtsx_read_phy_register(chip, 0x08, &val);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- return TRANSPORT_ERROR;
- }
-
- retval = rtsx_write_register(chip, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, LDO_OFF);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- return TRANSPORT_ERROR;
- }
-
- wait_timeout(600);
-
- retval = rtsx_write_phy_register(chip, 0x08,
- 0x4C00 | chip->phy_voltage);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- return TRANSPORT_ERROR;
- }
-
- retval = rtsx_write_register(chip, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, LDO_ON);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- return TRANSPORT_ERROR;
- }
-
- wait_timeout(600);
- }
-
- retval = card_power_on(chip, SPI_CARD);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- return TRANSPORT_ERROR;
- }
-
- wait_timeout(50);
-
- for (i = 0; i < len; i++) {
- retval = rtsx_write_efuse(chip, addr + i, buf[i]);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- result = TRANSPORT_FAILED;
- goto exit;
- }
- }
-
-exit:
- vfree(buf);
-
- retval = card_power_off(chip, SPI_CARD);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_ERROR;
-
- if (chip->asic_code) {
- retval = rtsx_write_register(chip, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, LDO_OFF);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_ERROR;
-
- wait_timeout(600);
-
- retval = rtsx_write_phy_register(chip, 0x08, val);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_ERROR;
-
- retval = rtsx_write_register(chip, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, LDO_ON);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_ERROR;
- }
-
- return result;
-}
-
-static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- bool func_max;
- u8 func;
- u16 addr, len;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- func = srb->cmnd[3];
- addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
- len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7];
-
- dev_dbg(rtsx_dev(chip), "%s: func = %d, addr = 0x%x, len = %d\n",
- __func__, func, addr, len);
-
- if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
- func_max = true;
- else
- func_max = false;
-
- if (func > func_max) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = rtsx_read_cfg_seq(chip, func, addr, buf, len);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- vfree(buf);
- return TRANSPORT_FAILED;
- }
-
- len = (u16)min_t(unsigned int, scsi_bufflen(srb), len);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- bool func_max;
- u8 func;
- u16 addr, len;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- func = srb->cmnd[3];
- addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
- len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7];
-
- dev_dbg(rtsx_dev(chip), "%s: func = %d, addr = 0x%x\n",
- __func__, func, addr);
-
- if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
- func_max = true;
- else
- func_max = false;
-
- if (func > func_max) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- retval = rtsx_write_cfg_seq(chip, func, addr, buf, len);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
- vfree(buf);
- return TRANSPORT_FAILED;
- }
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int app_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int result;
-
- switch (srb->cmnd[2]) {
- case PP_READ10:
- case PP_WRITE10:
- result = read_write(srb, chip);
- break;
-
- case READ_HOST_REG:
- result = read_host_reg(srb, chip);
- break;
-
- case WRITE_HOST_REG:
- result = write_host_reg(srb, chip);
- break;
-
- case GET_VAR:
- result = get_variable(srb, chip);
- break;
-
- case SET_VAR:
- result = set_variable(srb, chip);
- break;
-
- case DMA_READ:
- case DMA_WRITE:
- result = dma_access_ring_buffer(srb, chip);
- break;
-
- case READ_PHY:
- result = read_phy_register(srb, chip);
- break;
-
- case WRITE_PHY:
- result = write_phy_register(srb, chip);
- break;
-
- case ERASE_EEPROM2:
- result = erase_eeprom2(srb, chip);
- break;
-
- case READ_EEPROM2:
- result = read_eeprom2(srb, chip);
- break;
-
- case WRITE_EEPROM2:
- result = write_eeprom2(srb, chip);
- break;
-
- case READ_EFUSE:
- result = read_efuse(srb, chip);
- break;
-
- case WRITE_EFUSE:
- result = write_efuse(srb, chip);
- break;
-
- case READ_CFG:
- result = read_cfg_byte(srb, chip);
- break;
-
- case WRITE_CFG:
- result = write_cfg_byte(srb, chip);
- break;
-
- case SET_CHIP_MODE:
- result = set_chip_mode(srb, chip);
- break;
-
- case SUIT_CMD:
- result = suit_cmd(srb, chip);
- break;
-
- case GET_DEV_STATUS:
- result = get_dev_status(srb, chip);
- break;
-
- default:
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return result;
-}
-
-static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- u8 rtsx_status[16];
- int buf_len;
- unsigned int lun = SCSI_LUN(srb);
-
- rtsx_status[0] = (u8)(chip->vendor_id >> 8);
- rtsx_status[1] = (u8)(chip->vendor_id);
-
- rtsx_status[2] = (u8)(chip->product_id >> 8);
- rtsx_status[3] = (u8)(chip->product_id);
-
- rtsx_status[4] = (u8)lun;
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
- if (chip->lun2card[lun] == SD_CARD)
- rtsx_status[5] = 2;
- else
- rtsx_status[5] = 3;
- } else {
- if (chip->card_exist) {
- if (chip->card_exist & XD_CARD)
- rtsx_status[5] = 4;
- else if (chip->card_exist & SD_CARD)
- rtsx_status[5] = 2;
- else if (chip->card_exist & MS_CARD)
- rtsx_status[5] = 3;
- else
- rtsx_status[5] = 7;
- } else {
- rtsx_status[5] = 7;
- }
- }
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
- rtsx_status[6] = 2;
- else
- rtsx_status[6] = 1;
-
- rtsx_status[7] = (u8)(chip->product_id);
- rtsx_status[8] = chip->ic_version;
-
- if (check_card_exist(chip, lun))
- rtsx_status[9] = 1;
- else
- rtsx_status[9] = 0;
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
- rtsx_status[10] = 0;
- else
- rtsx_status[10] = 1;
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
- if (chip->lun2card[lun] == SD_CARD)
- rtsx_status[11] = SD_CARD;
- else
- rtsx_status[11] = MS_CARD;
- } else {
- rtsx_status[11] = XD_CARD | SD_CARD | MS_CARD;
- }
-
- if (check_card_ready(chip, lun))
- rtsx_status[12] = 1;
- else
- rtsx_status[12] = 0;
-
- if (get_lun_card(chip, lun) == XD_CARD) {
- rtsx_status[13] = 0x40;
- } else if (get_lun_card(chip, lun) == SD_CARD) {
- struct sd_info *sd_card = &chip->sd_card;
-
- rtsx_status[13] = 0x20;
- if (CHK_SD(sd_card)) {
- if (CHK_SD_HCXC(sd_card))
- rtsx_status[13] |= 0x04;
- if (CHK_SD_HS(sd_card))
- rtsx_status[13] |= 0x02;
- } else {
- rtsx_status[13] |= 0x08;
- if (CHK_MMC_52M(sd_card))
- rtsx_status[13] |= 0x02;
- if (CHK_MMC_SECTOR_MODE(sd_card))
- rtsx_status[13] |= 0x04;
- }
- } else if (get_lun_card(chip, lun) == MS_CARD) {
- struct ms_info *ms_card = &chip->ms_card;
-
- if (CHK_MSPRO(ms_card)) {
- rtsx_status[13] = 0x38;
- if (CHK_HG8BIT(ms_card))
- rtsx_status[13] |= 0x04;
-#ifdef SUPPORT_MSXC
- if (CHK_MSXC(ms_card))
- rtsx_status[13] |= 0x01;
-#endif
- } else {
- rtsx_status[13] = 0x30;
- }
- } else {
- if (CHECK_LUN_MODE(chip, DEFAULT_SINGLE)) {
-#ifdef SUPPORT_SDIO
- if (chip->sd_io && chip->sd_int)
- rtsx_status[13] = 0x60;
- else
- rtsx_status[13] = 0x70;
-#else
- rtsx_status[13] = 0x70;
-#endif
- } else {
- if (chip->lun2card[lun] == SD_CARD)
- rtsx_status[13] = 0x20;
- else
- rtsx_status[13] = 0x30;
- }
- }
-
- rtsx_status[14] = 0x78;
- if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
- rtsx_status[15] = 0x83;
- else
- rtsx_status[15] = 0x82;
-
- buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(rtsx_status));
- rtsx_stor_set_xfer_buf(rtsx_status, buf_len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
-
- return TRANSPORT_GOOD;
-}
-
-static int get_card_bus_width(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
- u8 card, bus_width;
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
-
- card = get_lun_card(chip, lun);
- if (card == SD_CARD || card == MS_CARD) {
- bus_width = chip->card_bus_width[lun];
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- scsi_set_resid(srb, 0);
- rtsx_stor_set_xfer_buf(&bus_width, scsi_bufflen(srb), srb);
-
- return TRANSPORT_GOOD;
-}
-
-static int spi_vendor_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int result;
- unsigned int lun = SCSI_LUN(srb);
- u8 gpio_dir;
-
- if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- rtsx_force_power_on(chip, SSC_PDCTL);
-
- rtsx_read_register(chip, CARD_GPIO_DIR, &gpio_dir);
- rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir & 0x06);
-
- switch (srb->cmnd[2]) {
- case SCSI_SPI_GETSTATUS:
- result = spi_get_status(srb, chip);
- break;
-
- case SCSI_SPI_SETPARAMETER:
- result = spi_set_parameter(srb, chip);
- break;
-
- case SCSI_SPI_READFALSHID:
- result = spi_read_flash_id(srb, chip);
- break;
-
- case SCSI_SPI_READFLASH:
- result = spi_read_flash(srb, chip);
- break;
-
- case SCSI_SPI_WRITEFLASH:
- result = spi_write_flash(srb, chip);
- break;
-
- case SCSI_SPI_WRITEFLASHSTATUS:
- result = spi_write_flash_status(srb, chip);
- break;
-
- case SCSI_SPI_ERASEFLASH:
- result = spi_erase_flash(srb, chip);
- break;
-
- default:
- rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
-
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
-
- if (result != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- return TRANSPORT_GOOD;
-}
-
-static int vendor_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int result;
-
- switch (srb->cmnd[1]) {
- case READ_STATUS:
- result = read_status(srb, chip);
- break;
-
- case READ_MEM:
- result = read_mem(srb, chip);
- break;
-
- case WRITE_MEM:
- result = write_mem(srb, chip);
- break;
-
- case READ_EEPROM:
- result = read_eeprom(srb, chip);
- break;
-
- case WRITE_EEPROM:
- result = write_eeprom(srb, chip);
- break;
-
- case TOGGLE_GPIO:
- result = toggle_gpio_cmd(srb, chip);
- break;
-
- case GET_SD_CSD:
- result = get_sd_csd(srb, chip);
- break;
-
- case GET_BUS_WIDTH:
- result = get_card_bus_width(srb, chip);
- break;
-
- case SCSI_APP_CMD:
- result = app_cmd(srb, chip);
- break;
-
- case SPI_VENDOR_COMMAND:
- result = spi_vendor_cmd(srb, chip);
- break;
-
- default:
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return result;
-}
-
-#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK)
-void led_shine(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
- u16 sec_cnt;
-
- if (srb->cmnd[0] == READ_10 || srb->cmnd[0] == WRITE_10) {
- sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
- } else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) {
- sec_cnt = srb->cmnd[4];
- if (sec_cnt == 0)
- sec_cnt = 256;
- } else {
- return;
- }
-
- if (chip->rw_cap[lun] >= GPIO_TOGGLE_THRESHOLD) {
- toggle_gpio(chip, LED_GPIO);
- chip->rw_cap[lun] = 0;
- } else {
- chip->rw_cap[lun] += sec_cnt;
- }
-}
-#endif
-
-static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- unsigned int lun = SCSI_LUN(srb);
- bool quick_format;
- int retval;
-
- if (get_lun_card(chip, lun) != MS_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
- return TRANSPORT_FAILED;
- }
-
- if (srb->cmnd[3] != 0x4D || srb->cmnd[4] != 0x47 ||
- srb->cmnd[5] != 0x66 || srb->cmnd[6] != 0x6D ||
- srb->cmnd[7] != 0x74) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
-
- if (!check_card_ready(chip, lun) ||
- (get_card_size(chip, lun) == 0)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- if (srb->cmnd[8] & 0x01)
- quick_format = false;
- else
- quick_format = true;
-
- if (!(chip->card_ready & MS_CARD)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
-
- if (chip->card_wp & MS_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
- return TRANSPORT_FAILED;
- }
-
- if (!CHK_MSPRO(ms_card)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
- return TRANSPORT_FAILED;
- }
-
- retval = mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
- return TRANSPORT_FAILED;
- }
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-}
-
-#ifdef SUPPORT_PCGL_1P18
-static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- unsigned int lun = SCSI_LUN(srb);
- u8 dev_info_id, data_len;
- u8 *buf;
- unsigned int buf_len;
- int i;
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
- if (get_lun_card(chip, lun) != MS_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
- return TRANSPORT_FAILED;
- }
-
- if (srb->cmnd[2] != 0xB0 || srb->cmnd[4] != 0x4D ||
- srb->cmnd[5] != 0x53 || srb->cmnd[6] != 0x49 ||
- srb->cmnd[7] != 0x44) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- dev_info_id = srb->cmnd[3];
- if ((CHK_MSXC(ms_card) && dev_info_id == 0x10) ||
- (!CHK_MSXC(ms_card) && dev_info_id == 0x13) ||
- !CHK_MSPRO(ms_card)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (dev_info_id == 0x15) {
- buf_len = 0x3C;
- data_len = 0x3A;
- } else {
- buf_len = 0x6C;
- data_len = 0x6A;
- }
-
- buf = kmalloc(buf_len, GFP_KERNEL);
- if (!buf)
- return TRANSPORT_ERROR;
-
- i = 0;
- /* GET Memory Stick Media Information Response Header */
- buf[i++] = 0x00; /* Data length MSB */
- buf[i++] = data_len; /* Data length LSB */
- /* Device Information Type Code */
- if (CHK_MSXC(ms_card))
- buf[i++] = 0x03;
- else
- buf[i++] = 0x02;
-
- /* SGM bit */
- buf[i++] = 0x01;
- /* Reserved */
- buf[i++] = 0x00;
- buf[i++] = 0x00;
- buf[i++] = 0x00;
- /* Number of Device Information */
- buf[i++] = 0x01;
-
- /* Device Information Body */
-
- /* Device Information ID Number */
- buf[i++] = dev_info_id;
- /* Device Information Length */
- if (dev_info_id == 0x15)
- data_len = 0x31;
- else
- data_len = 0x61;
-
- buf[i++] = 0x00; /* Data length MSB */
- buf[i++] = data_len; /* Data length LSB */
- /* Valid Bit */
- buf[i++] = 0x80;
- if (dev_info_id == 0x10 || dev_info_id == 0x13) {
- /* System Information */
- memcpy(buf + i, ms_card->raw_sys_info, 96);
- } else {
- /* Model Name */
- memcpy(buf + i, ms_card->raw_model_name, 48);
- }
-
- rtsx_stor_set_xfer_buf(buf, buf_len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
-
- kfree(buf);
- return STATUS_SUCCESS;
-}
-#endif
-
-static int ms_sp_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval = TRANSPORT_ERROR;
-
- if (srb->cmnd[2] == MS_FORMAT)
- retval = ms_format_cmnd(srb, chip);
-#ifdef SUPPORT_PCGL_1P18
- else if (srb->cmnd[2] == GET_MS_INFORMATION)
- retval = get_ms_information(srb, chip);
-#endif
-
- return retval;
-}
-
-#ifdef SUPPORT_CPRM
-static int sd_extension_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
- int result;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- sd_cleanup_work(chip);
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
- if (get_lun_card(chip, lun) != SD_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
- return TRANSPORT_FAILED;
- }
-
- switch (srb->cmnd[0]) {
- case SD_PASS_THRU_MODE:
- result = sd_pass_thru_mode(srb, chip);
- break;
-
- case SD_EXECUTE_NO_DATA:
- result = sd_execute_no_data(srb, chip);
- break;
-
- case SD_EXECUTE_READ:
- result = sd_execute_read_data(srb, chip);
- break;
-
- case SD_EXECUTE_WRITE:
- result = sd_execute_write_data(srb, chip);
- break;
-
- case SD_GET_RSP:
- result = sd_get_cmd_rsp(srb, chip);
- break;
-
- case SD_HW_RST:
- result = sd_hw_rst(srb, chip);
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return result;
-}
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
-static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval;
- u8 key_format;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- ms_cleanup_work(chip);
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
- if (get_lun_card(chip, lun) != MS_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
- return TRANSPORT_FAILED;
- }
-
- if (srb->cmnd[7] != KC_MG_R_PRO) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (!CHK_MSPRO(ms_card)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return TRANSPORT_FAILED;
- }
-
- key_format = srb->cmnd[10] & 0x3F;
- dev_dbg(rtsx_dev(chip), "key_format = 0x%x\n", key_format);
-
- switch (key_format) {
- case KF_GET_LOC_EKB:
- if ((scsi_bufflen(srb) == 0x41C) &&
- srb->cmnd[8] == 0x04 &&
- srb->cmnd[9] == 0x1C) {
- retval = mg_get_local_EKB(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- case KF_RSP_CHG:
- if ((scsi_bufflen(srb) == 0x24) &&
- srb->cmnd[8] == 0x00 &&
- srb->cmnd[9] == 0x24) {
- retval = mg_get_rsp_chg(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- case KF_GET_ICV:
- ms_card->mg_entry_num = srb->cmnd[5];
- if ((scsi_bufflen(srb) == 0x404) &&
- srb->cmnd[8] == 0x04 &&
- srb->cmnd[9] == 0x04 &&
- srb->cmnd[2] == 0x00 &&
- srb->cmnd[3] == 0x00 &&
- srb->cmnd[4] == 0x00 &&
- srb->cmnd[5] < 32) {
- retval = mg_get_ICV(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-}
-
-static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval;
- u8 key_format;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- ms_cleanup_work(chip);
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
- if (check_card_wp(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
- return TRANSPORT_FAILED;
- }
- if (get_lun_card(chip, lun) != MS_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
- return TRANSPORT_FAILED;
- }
-
- if (srb->cmnd[7] != KC_MG_R_PRO) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (!CHK_MSPRO(ms_card)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return TRANSPORT_FAILED;
- }
-
- key_format = srb->cmnd[10] & 0x3F;
- dev_dbg(rtsx_dev(chip), "key_format = 0x%x\n", key_format);
-
- switch (key_format) {
- case KF_SET_LEAF_ID:
- if ((scsi_bufflen(srb) == 0x0C) &&
- srb->cmnd[8] == 0x00 &&
- srb->cmnd[9] == 0x0C) {
- retval = mg_set_leaf_id(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- case KF_CHG_HOST:
- if ((scsi_bufflen(srb) == 0x0C) &&
- srb->cmnd[8] == 0x00 &&
- srb->cmnd[9] == 0x0C) {
- retval = mg_chg(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- case KF_RSP_HOST:
- if ((scsi_bufflen(srb) == 0x0C) &&
- srb->cmnd[8] == 0x00 &&
- srb->cmnd[9] == 0x0C) {
- retval = mg_rsp(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- case KF_SET_ICV:
- ms_card->mg_entry_num = srb->cmnd[5];
- if ((scsi_bufflen(srb) == 0x404) &&
- srb->cmnd[8] == 0x04 &&
- srb->cmnd[9] == 0x04 &&
- srb->cmnd[2] == 0x00 &&
- srb->cmnd[3] == 0x00 &&
- srb->cmnd[4] == 0x00 &&
- srb->cmnd[5] < 32) {
- retval = mg_set_ICV(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-}
-#endif
-
-int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_SD_LOCK
- struct sd_info *sd_card = &chip->sd_card;
-#endif
- struct ms_info *ms_card = &chip->ms_card;
- unsigned int lun = SCSI_LUN(srb);
- int result;
-
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_erase_status) {
- /* Block all SCSI command except for
- * REQUEST_SENSE and rs_ppstatus
- */
- if (!(srb->cmnd[0] == VENDOR_CMND &&
- srb->cmnd[1] == SCSI_APP_CMD &&
- srb->cmnd[2] == GET_DEV_STATUS) &&
- srb->cmnd[0] != REQUEST_SENSE) {
- /* Logical Unit Not Ready Format in Progress */
- set_sense_data(chip, lun, CUR_ERR,
- 0x02, 0, 0x04, 0x04, 0, 0);
- return TRANSPORT_FAILED;
- }
- }
-#endif
-
- if ((get_lun_card(chip, lun) == MS_CARD) &&
- ms_card->format_status == FORMAT_IN_PROGRESS) {
- if (srb->cmnd[0] != REQUEST_SENSE &&
- srb->cmnd[0] != INQUIRY) {
- /* Logical Unit Not Ready Format in Progress */
- set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
- 0, (u16)(ms_card->progress));
- return TRANSPORT_FAILED;
- }
- }
-
- switch (srb->cmnd[0]) {
- case READ_10:
- case WRITE_10:
- case READ_6:
- case WRITE_6:
- result = read_write(srb, chip);
-#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK)
- led_shine(srb, chip);
-#endif
- break;
-
- case TEST_UNIT_READY:
- result = test_unit_ready(srb, chip);
- break;
-
- case INQUIRY:
- result = inquiry(srb, chip);
- break;
-
- case READ_CAPACITY:
- result = read_capacity(srb, chip);
- break;
-
- case START_STOP:
- result = start_stop_unit(srb, chip);
- break;
-
- case ALLOW_MEDIUM_REMOVAL:
- result = allow_medium_removal(srb, chip);
- break;
-
- case REQUEST_SENSE:
- result = request_sense(srb, chip);
- break;
-
- case MODE_SENSE:
- case MODE_SENSE_10:
- result = mode_sense(srb, chip);
- break;
-
- case 0x23:
- result = read_format_capacity(srb, chip);
- break;
-
- case VENDOR_CMND:
- result = vendor_cmnd(srb, chip);
- break;
-
- case MS_SP_CMND:
- result = ms_sp_cmnd(srb, chip);
- break;
-
-#ifdef SUPPORT_CPRM
- case SD_PASS_THRU_MODE:
- case SD_EXECUTE_NO_DATA:
- case SD_EXECUTE_READ:
- case SD_EXECUTE_WRITE:
- case SD_GET_RSP:
- case SD_HW_RST:
- result = sd_extension_cmnd(srb, chip);
- break;
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
- case CMD_MSPRO_MG_RKEY:
- result = mg_report_key(srb, chip);
- break;
-
- case CMD_MSPRO_MG_SKEY:
- result = mg_send_key(srb, chip);
- break;
-#endif
-
- case FORMAT_UNIT:
- case MODE_SELECT:
- case VERIFY:
- result = TRANSPORT_GOOD;
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- result = TRANSPORT_FAILED;
- }
-
- return result;
-}
diff --git a/drivers/staging/rts5208/rtsx_scsi.h b/drivers/staging/rts5208/rtsx_scsi.h
deleted file mode 100644
index df6138c97aaa..000000000000
--- a/drivers/staging/rts5208/rtsx_scsi.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_SCSI_H
-#define __REALTEK_RTSX_SCSI_H
-
-#include "rtsx.h"
-#include "rtsx_chip.h"
-
-#define MS_SP_CMND 0xFA
-#define MS_FORMAT 0xA0
-#define GET_MS_INFORMATION 0xB0
-
-#define VENDOR_CMND 0xF0
-
-#define READ_STATUS 0x09
-
-#define READ_EEPROM 0x04
-#define WRITE_EEPROM 0x05
-#define READ_MEM 0x0D
-#define WRITE_MEM 0x0E
-#define GET_BUS_WIDTH 0x13
-#define GET_SD_CSD 0x14
-#define TOGGLE_GPIO 0x15
-#define TRACE_MSG 0x18
-
-#define SCSI_APP_CMD 0x10
-
-#define PP_READ10 0x1A
-#define PP_WRITE10 0x0A
-#define READ_HOST_REG 0x1D
-#define WRITE_HOST_REG 0x0D
-#define SET_VAR 0x05
-#define GET_VAR 0x15
-#define DMA_READ 0x16
-#define DMA_WRITE 0x06
-#define GET_DEV_STATUS 0x10
-#define SET_CHIP_MODE 0x27
-#define SUIT_CMD 0xE0
-#define WRITE_PHY 0x07
-#define READ_PHY 0x17
-#define WRITE_EEPROM2 0x03
-#define READ_EEPROM2 0x13
-#define ERASE_EEPROM2 0x23
-#define WRITE_EFUSE 0x04
-#define READ_EFUSE 0x14
-#define WRITE_CFG 0x0E
-#define READ_CFG 0x1E
-
-#define SPI_VENDOR_COMMAND 0x1C
-
-#define SCSI_SPI_GETSTATUS 0x00
-#define SCSI_SPI_SETPARAMETER 0x01
-#define SCSI_SPI_READFALSHID 0x02
-#define SCSI_SPI_READFLASH 0x03
-#define SCSI_SPI_WRITEFLASH 0x04
-#define SCSI_SPI_WRITEFLASHSTATUS 0x05
-#define SCSI_SPI_ERASEFLASH 0x06
-
-#define INIT_BATCHCMD 0x41
-#define ADD_BATCHCMD 0x42
-#define SEND_BATCHCMD 0x43
-#define GET_BATCHRSP 0x44
-
-#define CHIP_NORMALMODE 0x00
-#define CHIP_DEBUGMODE 0x01
-
-/* SD Pass Through Command Extension */
-#define SD_PASS_THRU_MODE 0xD0
-#define SD_EXECUTE_NO_DATA 0xD1
-#define SD_EXECUTE_READ 0xD2
-#define SD_EXECUTE_WRITE 0xD3
-#define SD_GET_RSP 0xD4
-#define SD_HW_RST 0xD6
-
-#ifdef SUPPORT_MAGIC_GATE
-#define CMD_MSPRO_MG_RKEY 0xA4 /* Report Key Command */
-#define CMD_MSPRO_MG_SKEY 0xA3 /* Send Key Command */
-
-/* CBWCB field: key class */
-#define KC_MG_R_PRO 0xBE /* MG-R PRO*/
-
-/* CBWCB field: key format */
-#define KF_SET_LEAF_ID 0x31 /* Set Leaf ID */
-#define KF_GET_LOC_EKB 0x32 /* Get Local EKB */
-#define KF_CHG_HOST 0x33 /* Challenge (host) */
-#define KF_RSP_CHG 0x34 /* Response and Challenge (device) */
-#define KF_RSP_HOST 0x35 /* Response (host) */
-#define KF_GET_ICV 0x36 /* Get ICV */
-#define KF_SET_ICV 0x37 /* SSet ICV */
-#endif
-
-/* Sense type */
-#define SENSE_TYPE_NO_SENSE 0
-#define SENSE_TYPE_MEDIA_CHANGE 1
-#define SENSE_TYPE_MEDIA_NOT_PRESENT 2
-#define SENSE_TYPE_MEDIA_LBA_OVER_RANGE 3
-#define SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT 4
-#define SENSE_TYPE_MEDIA_WRITE_PROTECT 5
-#define SENSE_TYPE_MEDIA_INVALID_CMD_FIELD 6
-#define SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR 7
-#define SENSE_TYPE_MEDIA_WRITE_ERR 8
-#define SENSE_TYPE_FORMAT_IN_PROGRESS 9
-#define SENSE_TYPE_FORMAT_CMD_FAILED 10
-#ifdef SUPPORT_MAGIC_GATE
-#define SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB 0x0b
-#define SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN 0x0c
-#define SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM 0x0d
-#define SENSE_TYPE_MG_WRITE_ERR 0x0e
-#endif
-#ifdef SUPPORT_SD_LOCK
-/* FOR Locked SD card*/
-#define SENSE_TYPE_MEDIA_READ_FORBIDDEN 0x10
-#endif
-
-void scsi_show_command(struct rtsx_chip *chip);
-void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type);
-void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code,
- u8 sense_key, u32 info, u8 asc, u8 ascq,
- u8 sns_key_info0, u16 sns_key_info1);
-int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-
-#endif /* __REALTEK_RTSX_SCSI_H */
diff --git a/drivers/staging/rts5208/rtsx_sys.h b/drivers/staging/rts5208/rtsx_sys.h
deleted file mode 100644
index 77094809c814..000000000000
--- a/drivers/staging/rts5208/rtsx_sys.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __RTSX_SYS_H
-#define __RTSX_SYS_H
-
-#include "rtsx.h"
-#include "rtsx_chip.h"
-#include "rtsx_card.h"
-
-static inline void rtsx_exclusive_enter_ss(struct rtsx_chip *chip)
-{
- struct rtsx_dev *dev = chip->rtsx;
-
- spin_lock(&dev->reg_lock);
- rtsx_enter_ss(chip);
- spin_unlock(&dev->reg_lock);
-}
-
-static inline void rtsx_reset_detected_cards(struct rtsx_chip *chip, int flag)
-{
- rtsx_reset_cards(chip);
-}
-
-#define RTSX_MSG_IN_INT(x)
-
-#endif /* __RTSX_SYS_H */
-
diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c
deleted file mode 100644
index d5ad49de4c56..000000000000
--- a/drivers/staging/rts5208/rtsx_transport.c
+++ /dev/null
@@ -1,768 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-
-#include "rtsx.h"
-
-/***********************************************************************
- * Scatter-gather transfer buffer access routines
- ***********************************************************************/
-
-/*
- * Copy a buffer of length buflen to/from the srb's transfer buffer.
- * (Note: for scatter-gather transfers (srb->use_sg > 0), srb->request_buffer
- * points to a list of s-g entries and we ignore srb->request_bufflen.
- * For non-scatter-gather transfers, srb->request_buffer points to the
- * transfer buffer itself and srb->request_bufflen is the buffer's length.)
- * Update the *index and *offset variables so that the next copy will
- * pick up from where this one left off.
- */
-
-unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer,
- unsigned int buflen,
- struct scsi_cmnd *srb,
- unsigned int *index,
- unsigned int *offset,
- enum xfer_buf_dir dir)
-{
- unsigned int cnt;
-
- /* If not using scatter-gather, just transfer the data directly. */
- if (scsi_sg_count(srb) == 0) {
- unsigned char *sgbuffer;
-
- if (*offset >= scsi_bufflen(srb))
- return 0;
- cnt = min(buflen, scsi_bufflen(srb) - *offset);
-
- sgbuffer = (unsigned char *)scsi_sglist(srb) + *offset;
-
- if (dir == TO_XFER_BUF)
- memcpy(sgbuffer, buffer, cnt);
- else
- memcpy(buffer, sgbuffer, cnt);
- *offset += cnt;
-
- /*
- * Using scatter-gather. We have to go through the list one entry
- * at a time. Each s-g entry contains some number of pages which
- * have to be copied one at a time.
- */
- } else {
- struct scatterlist *sg =
- (struct scatterlist *)scsi_sglist(srb)
- + *index;
-
- /*
- * This loop handles a single s-g list entry, which may
- * include multiple pages. Find the initial page structure
- * and the starting offset within the page, and update
- * the *offset and *index values for the next loop.
- */
- cnt = 0;
- while (cnt < buflen && *index < scsi_sg_count(srb)) {
- struct page *page = sg_page(sg) +
- ((sg->offset + *offset) >> PAGE_SHIFT);
- unsigned int poff = (sg->offset + *offset) &
- (PAGE_SIZE - 1);
- unsigned int sglen = sg->length - *offset;
-
- if (sglen > buflen - cnt) {
- /* Transfer ends within this s-g entry */
- sglen = buflen - cnt;
- *offset += sglen;
- } else {
- /* Transfer continues to next s-g entry */
- *offset = 0;
- ++*index;
- ++sg;
- }
-
- while (sglen > 0) {
- unsigned int plen = min(sglen, (unsigned int)
- PAGE_SIZE - poff);
-
- if (dir == TO_XFER_BUF)
- memcpy_to_page(page, poff, buffer + cnt, plen);
- else
- memcpy_from_page(buffer + cnt, page, poff, plen);
-
- /* Start at the beginning of the next page */
- poff = 0;
- ++page;
- cnt += plen;
- sglen -= plen;
- }
- }
- }
-
- /* Return the amount actually transferred */
- return cnt;
-}
-
-/*
- * Store the contents of buffer into srb's transfer buffer and set the
- * SCSI residue.
- */
-void rtsx_stor_set_xfer_buf(unsigned char *buffer,
- unsigned int buflen, struct scsi_cmnd *srb)
-{
- unsigned int index = 0, offset = 0;
-
- rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
- TO_XFER_BUF);
- if (buflen < scsi_bufflen(srb))
- scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
-}
-
-void rtsx_stor_get_xfer_buf(unsigned char *buffer,
- unsigned int buflen, struct scsi_cmnd *srb)
-{
- unsigned int index = 0, offset = 0;
-
- rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
- FROM_XFER_BUF);
- if (buflen < scsi_bufflen(srb))
- scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
-}
-
-/***********************************************************************
- * Transport routines
- ***********************************************************************/
-
-/*
- * Invoke the transport and basic error-handling/recovery methods
- *
- * This is used to send the message to the device and receive the response.
- */
-void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int result;
-
- result = rtsx_scsi_handler(srb, chip);
-
- /*
- * if the command gets aborted by the higher layers, we need to
- * short-circuit all other processing.
- */
- if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
- dev_dbg(rtsx_dev(chip), "-- command was aborted\n");
- srb->result = DID_ABORT << 16;
- goto handle_errors;
- }
-
- /* if there is a transport error, reset and don't auto-sense */
- if (result == TRANSPORT_ERROR) {
- dev_dbg(rtsx_dev(chip), "-- transport indicates error, resetting\n");
- srb->result = DID_ERROR << 16;
- goto handle_errors;
- }
-
- srb->result = SAM_STAT_GOOD;
-
- /*
- * If we have a failure, we're going to do a REQUEST_SENSE
- * automatically. Note that we differentiate between a command
- * "failure" and an "error" in the transport mechanism.
- */
- if (result == TRANSPORT_FAILED) {
- /* set the result so the higher layers expect this data */
- srb->result = SAM_STAT_CHECK_CONDITION;
- memcpy(srb->sense_buffer,
- (unsigned char *)&chip->sense_buffer[SCSI_LUN(srb)],
- sizeof(struct sense_data_t));
- }
-
- return;
-
-handle_errors:
- return;
-}
-
-void rtsx_add_cmd(struct rtsx_chip *chip,
- u8 cmd_type, u16 reg_addr, u8 mask, u8 data)
-{
- __le32 *cb = (__le32 *)(chip->host_cmds_ptr);
- u32 val = 0;
-
- val |= (u32)(cmd_type & 0x03) << 30;
- val |= (u32)(reg_addr & 0x3FFF) << 16;
- val |= (u32)mask << 8;
- val |= (u32)data;
-
- spin_lock_irq(&chip->rtsx->reg_lock);
- if (chip->ci < (HOST_CMDS_BUF_LEN / 4))
- cb[(chip->ci)++] = cpu_to_le32(val);
-
- spin_unlock_irq(&chip->rtsx->reg_lock);
-}
-
-void rtsx_send_cmd_no_wait(struct rtsx_chip *chip)
-{
- u32 val = BIT(31);
-
- rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
-
- val |= (u32)(chip->ci * 4) & 0x00FFFFFF;
- /* Hardware Auto Response */
- val |= 0x40000000;
- rtsx_writel(chip, RTSX_HCBCTLR, val);
-}
-
-int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout)
-{
- struct rtsx_dev *rtsx = chip->rtsx;
- struct completion trans_done;
- u32 val = BIT(31);
- long timeleft;
- int err = 0;
-
- if (card == SD_CARD)
- rtsx->check_card_cd = SD_EXIST;
- else if (card == MS_CARD)
- rtsx->check_card_cd = MS_EXIST;
- else if (card == XD_CARD)
- rtsx->check_card_cd = XD_EXIST;
- else
- rtsx->check_card_cd = 0;
-
- spin_lock_irq(&rtsx->reg_lock);
-
- /* set up data structures for the wakeup system */
- rtsx->done = &trans_done;
- rtsx->trans_result = TRANS_NOT_READY;
- init_completion(&trans_done);
- rtsx->trans_state = STATE_TRANS_CMD;
-
- rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
-
- val |= (u32)(chip->ci * 4) & 0x00FFFFFF;
- /* Hardware Auto Response */
- val |= 0x40000000;
- rtsx_writel(chip, RTSX_HCBCTLR, val);
-
- spin_unlock_irq(&rtsx->reg_lock);
-
- /* Wait for TRANS_OK_INT */
- timeleft = wait_for_completion_interruptible_timeout(&trans_done,
- msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
- chip->int_reg);
- err = -ETIMEDOUT;
- goto finish_send_cmd;
- }
-
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_RESULT_FAIL)
- err = -EIO;
- else if (rtsx->trans_result == TRANS_RESULT_OK)
- err = 0;
-
- spin_unlock_irq(&rtsx->reg_lock);
-
-finish_send_cmd:
- rtsx->done = NULL;
- rtsx->trans_state = STATE_TRANS_NONE;
-
- if (err < 0)
- rtsx_stop_cmd(chip, card);
-
- return err;
-}
-
-static inline void rtsx_add_sg_tbl(struct rtsx_chip *chip,
- u32 addr, u32 len, u8 option)
-{
- __le64 *sgb = (__le64 *)(chip->host_sg_tbl_ptr);
- u64 val = 0;
- u32 temp_len = 0;
- u8 temp_opt = 0;
-
- do {
- if (len > 0x80000) {
- temp_len = 0x80000;
- temp_opt = option & (~RTSX_SG_END);
- } else {
- temp_len = len;
- temp_opt = option;
- }
- val = ((u64)addr << 32) | ((u64)temp_len << 12) | temp_opt;
-
- if (chip->sgi < (HOST_SG_TBL_BUF_LEN / 8))
- sgb[(chip->sgi)++] = cpu_to_le64(val);
-
- len -= temp_len;
- addr += temp_len;
- } while (len);
-}
-
-static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
- struct scatterlist *sg, int num_sg,
- unsigned int *index,
- unsigned int *offset, int size,
- enum dma_data_direction dma_dir,
- int timeout)
-{
- struct rtsx_dev *rtsx = chip->rtsx;
- struct completion trans_done;
- u8 dir;
- int sg_cnt, i, resid;
- int err = 0;
- long timeleft;
- struct scatterlist *sg_ptr;
- u32 val = TRIG_DMA;
-
- if (!sg || num_sg <= 0 || !offset || !index)
- return -EIO;
-
- if (dma_dir == DMA_TO_DEVICE)
- dir = HOST_TO_DEVICE;
- else if (dma_dir == DMA_FROM_DEVICE)
- dir = DEVICE_TO_HOST;
- else
- return -ENXIO;
-
- if (card == SD_CARD)
- rtsx->check_card_cd = SD_EXIST;
- else if (card == MS_CARD)
- rtsx->check_card_cd = MS_EXIST;
- else if (card == XD_CARD)
- rtsx->check_card_cd = XD_EXIST;
- else
- rtsx->check_card_cd = 0;
-
- spin_lock_irq(&rtsx->reg_lock);
-
- /* set up data structures for the wakeup system */
- rtsx->done = &trans_done;
-
- rtsx->trans_state = STATE_TRANS_SG;
- rtsx->trans_result = TRANS_NOT_READY;
-
- spin_unlock_irq(&rtsx->reg_lock);
-
- sg_cnt = dma_map_sg(&rtsx->pci->dev, sg, num_sg, dma_dir);
-
- resid = size;
- sg_ptr = sg;
- chip->sgi = 0;
- /*
- * Usually the next entry will be @sg@ + 1, but if this sg element
- * is part of a chained scatterlist, it could jump to the start of
- * a new scatterlist array. So here we use sg_next to move to
- * the proper sg.
- */
- for (i = 0; i < *index; i++)
- sg_ptr = sg_next(sg_ptr);
- for (i = *index; i < sg_cnt; i++) {
- dma_addr_t addr;
- unsigned int len;
- u8 option;
-
- addr = sg_dma_address(sg_ptr);
- len = sg_dma_len(sg_ptr);
-
- dev_dbg(rtsx_dev(chip), "DMA addr: 0x%x, Len: 0x%x\n",
- (unsigned int)addr, len);
- dev_dbg(rtsx_dev(chip), "*index = %d, *offset = %d\n",
- *index, *offset);
-
- addr += *offset;
-
- if ((len - *offset) > resid) {
- *offset += resid;
- len = resid;
- resid = 0;
- } else {
- resid -= (len - *offset);
- len -= *offset;
- *offset = 0;
- *index = *index + 1;
- }
- option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA;
- if ((i == sg_cnt - 1) || !resid)
- option |= RTSX_SG_END;
-
- rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option);
-
- if (!resid)
- break;
-
- sg_ptr = sg_next(sg_ptr);
- }
-
- dev_dbg(rtsx_dev(chip), "SG table count = %d\n", chip->sgi);
-
- val |= (u32)(dir & 0x01) << 29;
- val |= ADMA_MODE;
-
- spin_lock_irq(&rtsx->reg_lock);
-
- init_completion(&trans_done);
-
- rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr);
- rtsx_writel(chip, RTSX_HDBCTLR, val);
-
- spin_unlock_irq(&rtsx->reg_lock);
-
- timeleft = wait_for_completion_interruptible_timeout(&trans_done,
- msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n",
- __func__, __LINE__);
- dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
- chip->int_reg);
- err = -ETIMEDOUT;
- goto out;
- }
-
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_RESULT_FAIL) {
- err = -EIO;
- spin_unlock_irq(&rtsx->reg_lock);
- goto out;
- }
- spin_unlock_irq(&rtsx->reg_lock);
-
- /* Wait for TRANS_OK_INT */
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_NOT_READY) {
- init_completion(&trans_done);
- spin_unlock_irq(&rtsx->reg_lock);
- timeleft = wait_for_completion_interruptible_timeout(&trans_done,
- msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n",
- __func__, __LINE__);
- dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
- chip->int_reg);
- err = -ETIMEDOUT;
- goto out;
- }
- } else {
- spin_unlock_irq(&rtsx->reg_lock);
- }
-
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_RESULT_FAIL)
- err = -EIO;
- else if (rtsx->trans_result == TRANS_RESULT_OK)
- err = 0;
-
- spin_unlock_irq(&rtsx->reg_lock);
-
-out:
- rtsx->done = NULL;
- rtsx->trans_state = STATE_TRANS_NONE;
- dma_unmap_sg(&rtsx->pci->dev, sg, num_sg, dma_dir);
-
- if (err < 0)
- rtsx_stop_cmd(chip, card);
-
- return err;
-}
-
-static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card,
- struct scatterlist *sg, int num_sg,
- enum dma_data_direction dma_dir,
- int timeout)
-{
- struct rtsx_dev *rtsx = chip->rtsx;
- struct completion trans_done;
- u8 dir;
- int buf_cnt, i;
- int err = 0;
- long timeleft;
- struct scatterlist *sg_ptr;
-
- if (!sg || num_sg <= 0)
- return -EIO;
-
- if (dma_dir == DMA_TO_DEVICE)
- dir = HOST_TO_DEVICE;
- else if (dma_dir == DMA_FROM_DEVICE)
- dir = DEVICE_TO_HOST;
- else
- return -ENXIO;
-
- if (card == SD_CARD)
- rtsx->check_card_cd = SD_EXIST;
- else if (card == MS_CARD)
- rtsx->check_card_cd = MS_EXIST;
- else if (card == XD_CARD)
- rtsx->check_card_cd = XD_EXIST;
- else
- rtsx->check_card_cd = 0;
-
- spin_lock_irq(&rtsx->reg_lock);
-
- /* set up data structures for the wakeup system */
- rtsx->done = &trans_done;
-
- rtsx->trans_state = STATE_TRANS_SG;
- rtsx->trans_result = TRANS_NOT_READY;
-
- spin_unlock_irq(&rtsx->reg_lock);
-
- buf_cnt = dma_map_sg(&rtsx->pci->dev, sg, num_sg, dma_dir);
-
- sg_ptr = sg;
-
- for (i = 0; i <= buf_cnt / (HOST_SG_TBL_BUF_LEN / 8); i++) {
- u32 val = TRIG_DMA;
- int sg_cnt, j;
-
- if (i == buf_cnt / (HOST_SG_TBL_BUF_LEN / 8))
- sg_cnt = buf_cnt % (HOST_SG_TBL_BUF_LEN / 8);
- else
- sg_cnt = HOST_SG_TBL_BUF_LEN / 8;
-
- chip->sgi = 0;
- for (j = 0; j < sg_cnt; j++) {
- dma_addr_t addr = sg_dma_address(sg_ptr);
- unsigned int len = sg_dma_len(sg_ptr);
- u8 option;
-
- dev_dbg(rtsx_dev(chip), "DMA addr: 0x%x, Len: 0x%x\n",
- (unsigned int)addr, len);
-
- option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA;
- if (j == (sg_cnt - 1))
- option |= RTSX_SG_END;
-
- rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option);
-
- sg_ptr = sg_next(sg_ptr);
- }
-
- dev_dbg(rtsx_dev(chip), "SG table count = %d\n", chip->sgi);
-
- val |= (u32)(dir & 0x01) << 29;
- val |= ADMA_MODE;
-
- spin_lock_irq(&rtsx->reg_lock);
-
- init_completion(&trans_done);
-
- rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr);
- rtsx_writel(chip, RTSX_HDBCTLR, val);
-
- spin_unlock_irq(&rtsx->reg_lock);
-
- timeleft = wait_for_completion_interruptible_timeout(&trans_done,
- msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n",
- __func__, __LINE__);
- dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
- chip->int_reg);
- err = -ETIMEDOUT;
- goto out;
- }
-
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_RESULT_FAIL) {
- err = -EIO;
- spin_unlock_irq(&rtsx->reg_lock);
- goto out;
- }
- spin_unlock_irq(&rtsx->reg_lock);
-
- sg_ptr += sg_cnt;
- }
-
- /* Wait for TRANS_OK_INT */
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_NOT_READY) {
- init_completion(&trans_done);
- spin_unlock_irq(&rtsx->reg_lock);
- timeleft = wait_for_completion_interruptible_timeout(&trans_done,
- msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n",
- __func__, __LINE__);
- dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
- chip->int_reg);
- err = -ETIMEDOUT;
- goto out;
- }
- } else {
- spin_unlock_irq(&rtsx->reg_lock);
- }
-
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_RESULT_FAIL)
- err = -EIO;
- else if (rtsx->trans_result == TRANS_RESULT_OK)
- err = 0;
-
- spin_unlock_irq(&rtsx->reg_lock);
-
-out:
- rtsx->done = NULL;
- rtsx->trans_state = STATE_TRANS_NONE;
- dma_unmap_sg(&rtsx->pci->dev, sg, num_sg, dma_dir);
-
- if (err < 0)
- rtsx_stop_cmd(chip, card);
-
- return err;
-}
-
-static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf,
- size_t len, enum dma_data_direction dma_dir,
- int timeout)
-{
- struct rtsx_dev *rtsx = chip->rtsx;
- struct completion trans_done;
- dma_addr_t addr;
- u8 dir;
- int err = 0;
- u32 val = BIT(31);
- long timeleft;
-
- if (!buf || len <= 0)
- return -EIO;
-
- if (dma_dir == DMA_TO_DEVICE)
- dir = HOST_TO_DEVICE;
- else if (dma_dir == DMA_FROM_DEVICE)
- dir = DEVICE_TO_HOST;
- else
- return -ENXIO;
-
- addr = dma_map_single(&rtsx->pci->dev, buf, len, dma_dir);
- if (dma_mapping_error(&rtsx->pci->dev, addr))
- return -ENOMEM;
-
- if (card == SD_CARD)
- rtsx->check_card_cd = SD_EXIST;
- else if (card == MS_CARD)
- rtsx->check_card_cd = MS_EXIST;
- else if (card == XD_CARD)
- rtsx->check_card_cd = XD_EXIST;
- else
- rtsx->check_card_cd = 0;
-
- val |= (u32)(dir & 0x01) << 29;
- val |= (u32)(len & 0x00FFFFFF);
-
- spin_lock_irq(&rtsx->reg_lock);
-
- /* set up data structures for the wakeup system */
- rtsx->done = &trans_done;
-
- init_completion(&trans_done);
-
- rtsx->trans_state = STATE_TRANS_BUF;
- rtsx->trans_result = TRANS_NOT_READY;
-
- rtsx_writel(chip, RTSX_HDBAR, addr);
- rtsx_writel(chip, RTSX_HDBCTLR, val);
-
- spin_unlock_irq(&rtsx->reg_lock);
-
- /* Wait for TRANS_OK_INT */
- timeleft = wait_for_completion_interruptible_timeout(&trans_done,
- msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n",
- __func__, __LINE__);
- dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
- chip->int_reg);
- err = -ETIMEDOUT;
- goto out;
- }
-
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_RESULT_FAIL)
- err = -EIO;
- else if (rtsx->trans_result == TRANS_RESULT_OK)
- err = 0;
-
- spin_unlock_irq(&rtsx->reg_lock);
-
-out:
- rtsx->done = NULL;
- rtsx->trans_state = STATE_TRANS_NONE;
- dma_unmap_single(&rtsx->pci->dev, addr, len, dma_dir);
-
- if (err < 0)
- rtsx_stop_cmd(chip, card);
-
- return err;
-}
-
-int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card,
- void *buf, size_t len, int use_sg,
- unsigned int *index, unsigned int *offset,
- enum dma_data_direction dma_dir, int timeout)
-{
- int err = 0;
-
- /* don't transfer data during abort processing */
- if (rtsx_chk_stat(chip, RTSX_STAT_ABORT))
- return -EIO;
-
- if (use_sg) {
- struct scatterlist *sg = buf;
-
- err = rtsx_transfer_sglist_adma_partial(chip, card, sg, use_sg,
- index, offset, (int)len,
- dma_dir, timeout);
- } else {
- err = rtsx_transfer_buf(chip, card,
- buf, len, dma_dir, timeout);
- }
- if (err < 0) {
- if (RTSX_TST_DELINK(chip)) {
- RTSX_CLR_DELINK(chip);
- chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
- rtsx_reinit_cards(chip, 1);
- }
- }
-
- return err;
-}
-
-int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
- int use_sg, enum dma_data_direction dma_dir, int timeout)
-{
- int err = 0;
-
- dev_dbg(rtsx_dev(chip), "use_sg = %d\n", use_sg);
-
- /* don't transfer data during abort processing */
- if (rtsx_chk_stat(chip, RTSX_STAT_ABORT))
- return -EIO;
-
- if (use_sg) {
- err = rtsx_transfer_sglist_adma(chip, card, buf,
- use_sg, dma_dir, timeout);
- } else {
- err = rtsx_transfer_buf(chip, card, buf, len, dma_dir, timeout);
- }
-
- if (err < 0) {
- if (RTSX_TST_DELINK(chip)) {
- RTSX_CLR_DELINK(chip);
- chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
- rtsx_reinit_cards(chip, 1);
- }
- }
-
- return err;
-}
-
diff --git a/drivers/staging/rts5208/rtsx_transport.h b/drivers/staging/rts5208/rtsx_transport.h
deleted file mode 100644
index 097efed24b79..000000000000
--- a/drivers/staging/rts5208/rtsx_transport.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_TRANSPORT_H
-#define __REALTEK_RTSX_TRANSPORT_H
-
-#include "rtsx.h"
-#include "rtsx_chip.h"
-
-#define WAIT_TIME 2000
-
-unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer,
- unsigned int buflen,
- struct scsi_cmnd *srb,
- unsigned int *index,
- unsigned int *offset,
- enum xfer_buf_dir dir);
-void rtsx_stor_set_xfer_buf(unsigned char *buffer, unsigned int buflen,
- struct scsi_cmnd *srb);
-void rtsx_stor_get_xfer_buf(unsigned char *buffer, unsigned int buflen,
- struct scsi_cmnd *srb);
-void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-
-#define rtsx_init_cmd(chip) ((chip)->ci = 0)
-
-void rtsx_add_cmd(struct rtsx_chip *chip, u8 cmd_type, u16 reg_addr, u8 mask,
- u8 data);
-void rtsx_send_cmd_no_wait(struct rtsx_chip *chip);
-int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout);
-
-static inline u8 *rtsx_get_cmd_data(struct rtsx_chip *chip)
-{
-#ifdef CMD_USING_SG
- return (u8 *)(chip->host_sg_tbl_ptr);
-#else
- return (u8 *)(chip->host_cmds_ptr);
-#endif
-}
-
-int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
- int use_sg, enum dma_data_direction dma_dir,
- int timeout);
-
-int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card, void *buf,
- size_t len, int use_sg, unsigned int *index,
- unsigned int *offset,
- enum dma_data_direction dma_dir, int timeout);
-
-#endif /* __REALTEK_RTSX_TRANSPORT_H */
diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c
deleted file mode 100644
index 74c4f476b3a4..000000000000
--- a/drivers/staging/rts5208/sd.c
+++ /dev/null
@@ -1,4717 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-
-#include "rtsx.h"
-#include "sd.h"
-
-#define SD_MAX_RETRY_COUNT 3
-
-static u16 REG_SD_CFG1;
-static u16 REG_SD_CFG2;
-static u16 REG_SD_CFG3;
-static u16 REG_SD_STAT1;
-static u16 REG_SD_STAT2;
-static u16 REG_SD_BUS_STAT;
-static u16 REG_SD_PAD_CTL;
-static u16 REG_SD_SAMPLE_POINT_CTL;
-static u16 REG_SD_PUSH_POINT_CTL;
-static u16 REG_SD_CMD0;
-static u16 REG_SD_CMD1;
-static u16 REG_SD_CMD2;
-static u16 REG_SD_CMD3;
-static u16 REG_SD_CMD4;
-static u16 REG_SD_CMD5;
-static u16 REG_SD_BYTE_CNT_L;
-static u16 REG_SD_BYTE_CNT_H;
-static u16 REG_SD_BLOCK_CNT_L;
-static u16 REG_SD_BLOCK_CNT_H;
-static u16 REG_SD_TRANSFER;
-static u16 REG_SD_VPCLK0_CTL;
-static u16 REG_SD_VPCLK1_CTL;
-static u16 REG_SD_DCMPS0_CTL;
-static u16 REG_SD_DCMPS1_CTL;
-
-static inline void sd_set_err_code(struct rtsx_chip *chip, u8 err_code)
-{
- struct sd_info *sd_card = &chip->sd_card;
-
- sd_card->err_code |= err_code;
-}
-
-static inline void sd_clr_err_code(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
-
- sd_card->err_code = 0;
-}
-
-static inline int sd_check_err_code(struct rtsx_chip *chip, u8 err_code)
-{
- struct sd_info *sd_card = &chip->sd_card;
-
- return sd_card->err_code & err_code;
-}
-
-static void sd_init_reg_addr(struct rtsx_chip *chip)
-{
- REG_SD_CFG1 = 0xFD31;
- REG_SD_CFG2 = 0xFD33;
- REG_SD_CFG3 = 0xFD3E;
- REG_SD_STAT1 = 0xFD30;
- REG_SD_STAT2 = 0;
- REG_SD_BUS_STAT = 0;
- REG_SD_PAD_CTL = 0;
- REG_SD_SAMPLE_POINT_CTL = 0;
- REG_SD_PUSH_POINT_CTL = 0;
- REG_SD_CMD0 = 0xFD34;
- REG_SD_CMD1 = 0xFD35;
- REG_SD_CMD2 = 0xFD36;
- REG_SD_CMD3 = 0xFD37;
- REG_SD_CMD4 = 0xFD38;
- REG_SD_CMD5 = 0xFD5A;
- REG_SD_BYTE_CNT_L = 0xFD39;
- REG_SD_BYTE_CNT_H = 0xFD3A;
- REG_SD_BLOCK_CNT_L = 0xFD3B;
- REG_SD_BLOCK_CNT_H = 0xFD3C;
- REG_SD_TRANSFER = 0xFD32;
- REG_SD_VPCLK0_CTL = 0;
- REG_SD_VPCLK1_CTL = 0;
- REG_SD_DCMPS0_CTL = 0;
- REG_SD_DCMPS1_CTL = 0;
-}
-
-static int sd_check_data0_status(struct rtsx_chip *chip)
-{
- int retval;
- u8 stat;
-
- retval = rtsx_read_register(chip, REG_SD_STAT1, &stat);
- if (retval)
- return retval;
-
- if (!(stat & SD_DAT0_STATUS)) {
- sd_set_err_code(chip, SD_BUSY);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
- u32 arg, u8 rsp_type, u8 *rsp, int rsp_len)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int timeout = 100;
- u16 reg_addr;
- u8 *ptr;
- int stat_idx = 0;
- int rty_cnt = 0;
-
- sd_clr_err_code(chip);
-
- dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d, arg = 0x%08x\n", cmd_idx, arg);
-
- if (rsp_type == SD_RSP_TYPE_R1b)
- timeout = 3000;
-
-RTY_SEND_CMD:
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
- 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END | SD_STAT_IDLE, SD_TRANSFER_END |
- SD_STAT_IDLE);
-
- if (rsp_type == SD_RSP_TYPE_R2) {
- for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
- stat_idx = 16;
- } else if (rsp_type != SD_RSP_TYPE_R0) {
- for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
- stat_idx = 5;
- }
-
- rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0);
-
- retval = rtsx_send_cmd(chip, SD_CARD, timeout);
- if (retval < 0) {
- u8 val;
-
- rtsx_read_register(chip, REG_SD_STAT1, &val);
- dev_dbg(rtsx_dev(chip), "SD_STAT1: 0x%x\n", val);
-
- rtsx_read_register(chip, REG_SD_CFG3, &val);
- dev_dbg(rtsx_dev(chip), "SD_CFG3: 0x%x\n", val);
-
- if (retval == -ETIMEDOUT) {
- if (rsp_type & SD_WAIT_BUSY_END) {
- retval = sd_check_data0_status(chip);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
- return retval;
- }
- } else {
- sd_set_err_code(chip, SD_TO_ERR);
- }
- retval = STATUS_TIMEDOUT;
- } else {
- retval = STATUS_FAIL;
- }
- rtsx_clear_sd_error(chip);
-
- return retval;
- }
-
- if (rsp_type == SD_RSP_TYPE_R0)
- return STATUS_SUCCESS;
-
- ptr = rtsx_get_cmd_data(chip) + 1;
-
- if ((ptr[0] & 0xC0) != 0) {
- sd_set_err_code(chip, SD_STS_ERR);
- return STATUS_FAIL;
- }
-
- if (!(rsp_type & SD_NO_CHECK_CRC7)) {
- if (ptr[stat_idx] & SD_CRC7_ERR) {
- if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
- sd_set_err_code(chip, SD_CRC_ERR);
- return STATUS_FAIL;
- }
- if (rty_cnt < SD_MAX_RETRY_COUNT) {
- wait_timeout(20);
- rty_cnt++;
- goto RTY_SEND_CMD;
- } else {
- sd_set_err_code(chip, SD_CRC_ERR);
- return STATUS_FAIL;
- }
- }
- }
-
- if (rsp_type == SD_RSP_TYPE_R1 || rsp_type == SD_RSP_TYPE_R1b) {
- if (cmd_idx != SEND_RELATIVE_ADDR &&
- cmd_idx != SEND_IF_COND) {
- if (cmd_idx != STOP_TRANSMISSION) {
- if (ptr[1] & 0x80)
- return STATUS_FAIL;
- }
-#ifdef SUPPORT_SD_LOCK
- if (ptr[1] & 0x7D) {
-#else
- if (ptr[1] & 0x7F) {
-#endif
- dev_dbg(rtsx_dev(chip), "ptr[1]: 0x%02x\n",
- ptr[1]);
- return STATUS_FAIL;
- }
- if (ptr[2] & 0xFF) {
- dev_dbg(rtsx_dev(chip), "ptr[2]: 0x%02x\n",
- ptr[2]);
- return STATUS_FAIL;
- }
- if (ptr[3] & 0x80) {
- dev_dbg(rtsx_dev(chip), "ptr[3]: 0x%02x\n",
- ptr[3]);
- return STATUS_FAIL;
- }
- if (ptr[3] & 0x01)
- sd_card->sd_data_buf_ready = 1;
- else
- sd_card->sd_data_buf_ready = 0;
- }
- }
-
- if (rsp && rsp_len)
- memcpy(rsp, ptr, rsp_len);
-
- return STATUS_SUCCESS;
-}
-
-static int sd_read_data(struct rtsx_chip *chip,
- u8 trans_mode, u8 *cmd, int cmd_len, u16 byte_cnt,
- u16 blk_cnt, u8 bus_width, u8 *buf, int buf_len,
- int timeout)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i;
-
- sd_clr_err_code(chip);
-
- if (!buf)
- buf_len = 0;
-
- if (buf_len > 512)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- if (cmd_len) {
- dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", cmd[0] - 0x40);
- for (i = 0; i < (min(cmd_len, 6)); i++)
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0 + i,
- 0xFF, cmd[i]);
- }
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
- (u8)byte_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
- (u8)(byte_cnt >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF,
- (u8)blk_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF,
- (u8)(blk_cnt >> 8));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
- SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
- SD_CHECK_CRC7 | SD_RSP_LEN_6);
- if (trans_mode != SD_TM_AUTO_TUNING)
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- trans_mode | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
- SD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, SD_CARD, timeout);
- if (retval < 0) {
- if (retval == -ETIMEDOUT) {
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- }
-
- return STATUS_FAIL;
- }
-
- if (buf && buf_len) {
- retval = rtsx_read_ppbuf(chip, buf, buf_len);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode,
- u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt,
- u8 bus_width, u8 *buf, int buf_len, int timeout)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i;
-
- sd_clr_err_code(chip);
-
- if (!buf)
- buf_len = 0;
-
- if (buf_len > 512) {
- /* This function can't write data more than one page */
- return STATUS_FAIL;
- }
-
- if (buf && buf_len) {
- retval = rtsx_write_ppbuf(chip, buf, buf_len);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- rtsx_init_cmd(chip);
-
- if (cmd_len) {
- dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", cmd[0] - 0x40);
- for (i = 0; i < (min(cmd_len, 6)); i++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- REG_SD_CMD0 + i, 0xFF, cmd[i]);
- }
- }
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
- (u8)byte_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
- (u8)(byte_cnt >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF,
- (u8)blk_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF,
- (u8)(blk_cnt >> 8));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
- SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
- SD_CHECK_CRC7 | SD_RSP_LEN_6);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- trans_mode | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
- SD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, SD_CARD, timeout);
- if (retval < 0) {
- if (retval == -ETIMEDOUT) {
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- }
-
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_check_csd(struct rtsx_chip *chip, char check_wp)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i;
- u8 csd_ver, trans_speed;
- u8 rsp[16];
-
- for (i = 0; i < 6; i++) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = sd_send_cmd_get_rsp(chip, SEND_CSD, sd_card->sd_addr,
- SD_RSP_TYPE_R2, rsp, 16);
- if (retval == STATUS_SUCCESS)
- break;
- }
-
- if (i == 6)
- return STATUS_FAIL;
-
- memcpy(sd_card->raw_csd, rsp + 1, 15);
-
- dev_dbg(rtsx_dev(chip), "CSD Response:\n");
- dev_dbg(rtsx_dev(chip), "%*ph\n", 16, sd_card->raw_csd);
-
- csd_ver = (rsp[1] & 0xc0) >> 6;
- dev_dbg(rtsx_dev(chip), "csd_ver = %d\n", csd_ver);
-
- trans_speed = rsp[4];
- if ((trans_speed & 0x07) == 0x02) {
- if ((trans_speed & 0xf8) >= 0x30) {
- if (chip->asic_code)
- sd_card->sd_clock = 47;
- else
- sd_card->sd_clock = CLK_50;
-
- } else if ((trans_speed & 0xf8) == 0x28) {
- if (chip->asic_code)
- sd_card->sd_clock = 39;
- else
- sd_card->sd_clock = CLK_40;
-
- } else if ((trans_speed & 0xf8) == 0x20) {
- if (chip->asic_code)
- sd_card->sd_clock = 29;
- else
- sd_card->sd_clock = CLK_30;
-
- } else if ((trans_speed & 0xf8) >= 0x10) {
- if (chip->asic_code)
- sd_card->sd_clock = 23;
- else
- sd_card->sd_clock = CLK_20;
-
- } else if ((trans_speed & 0x08) >= 0x08) {
- if (chip->asic_code)
- sd_card->sd_clock = 19;
- else
- sd_card->sd_clock = CLK_20;
- } else {
- return STATUS_FAIL;
- }
- } else {
- return STATUS_FAIL;
- }
-
- if (CHK_MMC_SECTOR_MODE(sd_card)) {
- sd_card->capacity = 0;
- } else {
- if ((!CHK_SD_HCXC(sd_card)) || csd_ver == 0) {
- u8 blk_size, c_size_mult;
- u16 c_size;
-
- blk_size = rsp[6] & 0x0F;
- c_size = ((u16)(rsp[7] & 0x03) << 10)
- + ((u16)rsp[8] << 2)
- + ((u16)(rsp[9] & 0xC0) >> 6);
- c_size_mult = (u8)((rsp[10] & 0x03) << 1);
- c_size_mult += (rsp[11] & 0x80) >> 7;
- sd_card->capacity = (((u32)(c_size + 1)) *
- (1 << (c_size_mult + 2)))
- << (blk_size - 9);
- } else {
- u32 total_sector = 0;
-
- total_sector = (((u32)rsp[8] & 0x3f) << 16) |
- ((u32)rsp[9] << 8) | (u32)rsp[10];
- sd_card->capacity = (total_sector + 1) << 10;
- }
- }
-
- if (check_wp) {
- if (rsp[15] & 0x30)
- chip->card_wp |= SD_CARD;
-
- dev_dbg(rtsx_dev(chip), "CSD WP Status: 0x%x\n", rsp[15]);
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_set_sample_push_timing(struct rtsx_chip *chip)
-{
- int retval;
- struct sd_info *sd_card = &chip->sd_card;
- u8 val = 0;
-
- if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY)
- val |= 0x10;
-
- if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) {
- if (chip->asic_code) {
- if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) {
- if (val & 0x10)
- val |= 0x04;
- else
- val |= 0x08;
- }
- } else {
- if (val & 0x10)
- val |= 0x04;
- else
- val |= 0x08;
- }
- } else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) ==
- SD_SAMPLE_POINT_DELAY) {
- if (val & 0x10)
- val |= 0x04;
- else
- val |= 0x08;
- }
-
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x1C, val);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static void sd_choose_proper_clock(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
-
- if (CHK_SD_SDR104(sd_card)) {
- if (chip->asic_code)
- sd_card->sd_clock = chip->asic_sd_sdr104_clk;
- else
- sd_card->sd_clock = chip->fpga_sd_sdr104_clk;
-
- } else if (CHK_SD_DDR50(sd_card)) {
- if (chip->asic_code)
- sd_card->sd_clock = chip->asic_sd_ddr50_clk;
- else
- sd_card->sd_clock = chip->fpga_sd_ddr50_clk;
-
- } else if (CHK_SD_SDR50(sd_card)) {
- if (chip->asic_code)
- sd_card->sd_clock = chip->asic_sd_sdr50_clk;
- else
- sd_card->sd_clock = chip->fpga_sd_sdr50_clk;
-
- } else if (CHK_SD_HS(sd_card)) {
- if (chip->asic_code)
- sd_card->sd_clock = chip->asic_sd_hs_clk;
- else
- sd_card->sd_clock = chip->fpga_sd_hs_clk;
-
- } else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) {
- if (chip->asic_code)
- sd_card->sd_clock = chip->asic_mmc_52m_clk;
- else
- sd_card->sd_clock = chip->fpga_mmc_52m_clk;
-
- } else if (CHK_MMC_26M(sd_card)) {
- if (chip->asic_code)
- sd_card->sd_clock = 48;
- else
- sd_card->sd_clock = CLK_50;
- }
-}
-
-static int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div)
-{
- int retval;
- u8 mask = 0, val = 0;
-
- mask = 0x60;
- if (clk_div == SD_CLK_DIVIDE_0)
- val = 0x00;
- else if (clk_div == SD_CLK_DIVIDE_128)
- val = 0x40;
- else if (clk_div == SD_CLK_DIVIDE_256)
- val = 0x20;
-
- retval = rtsx_write_register(chip, REG_SD_CFG1, mask, val);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_set_init_para(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- retval = sd_set_sample_push_timing(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- sd_choose_proper_clock(chip);
-
- retval = switch_clock(chip, sd_card->sd_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int sd_select_card(struct rtsx_chip *chip, int select)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd_idx, cmd_type;
- u32 addr;
-
- if (select) {
- cmd_idx = SELECT_CARD;
- cmd_type = SD_RSP_TYPE_R1;
- addr = sd_card->sd_addr;
- } else {
- cmd_idx = DESELECT_CARD;
- cmd_type = SD_RSP_TYPE_R0;
- addr = 0;
- }
-
- retval = sd_send_cmd_get_rsp(chip, cmd_idx, addr, cmd_type, NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-#ifdef SUPPORT_SD_LOCK
-static int sd_update_lock_status(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 rsp[5];
-
- retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, rsp, 5);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (rsp[1] & 0x02)
- sd_card->sd_lock_status |= SD_LOCKED;
- else
- sd_card->sd_lock_status &= ~SD_LOCKED;
-
- dev_dbg(rtsx_dev(chip), "sd_card->sd_lock_status = 0x%x\n",
- sd_card->sd_lock_status);
-
- if (rsp[1] & 0x01)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-#endif
-
-static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state,
- u8 data_ready, int polling_cnt)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval, i;
- u8 rsp[5];
-
- for (i = 0; i < polling_cnt; i++) {
- retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
- sd_card->sd_addr, SD_RSP_TYPE_R1,
- rsp, 5);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (((rsp[3] & 0x1E) == state) &&
- ((rsp[3] & 0x01) == data_ready))
- return STATUS_SUCCESS;
- }
-
- return STATUS_FAIL;
-}
-
-static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage)
-{
- int retval;
-
- if (voltage == SD_IO_3V3) {
- if (chip->asic_code) {
- retval = rtsx_write_phy_register(chip, 0x08,
- 0x4FC0 |
- chip->phy_voltage);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, SD_PAD_CTL,
- SD_IO_USING_1V8, 0);
- if (retval)
- return retval;
- }
- } else if (voltage == SD_IO_1V8) {
- if (chip->asic_code) {
- retval = rtsx_write_phy_register(chip, 0x08,
- 0x4C40 |
- chip->phy_voltage);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, SD_PAD_CTL,
- SD_IO_USING_1V8,
- SD_IO_USING_1V8);
- if (retval)
- return retval;
- }
- } else {
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_voltage_switch(struct rtsx_chip *chip)
-{
- int retval;
- u8 stat;
-
- retval = rtsx_write_register(chip, SD_BUS_STAT,
- SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP,
- SD_CLK_TOGGLE_EN);
- if (retval)
- return retval;
-
- retval = sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- udelay(chip->sd_voltage_switch_delay);
-
- retval = rtsx_read_register(chip, SD_BUS_STAT, &stat);
- if (retval)
- return retval;
- if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
- SD_DAT1_STATUS | SD_DAT0_STATUS)) {
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_register(chip, SD_BUS_STAT, 0xFF,
- SD_CLK_FORCE_STOP);
- if (retval)
- return retval;
- retval = sd_change_bank_voltage(chip, SD_IO_1V8);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- wait_timeout(50);
-
- retval = rtsx_write_register(chip, SD_BUS_STAT, 0xFF,
- SD_CLK_TOGGLE_EN);
- if (retval)
- return retval;
- wait_timeout(10);
-
- retval = rtsx_read_register(chip, SD_BUS_STAT, &stat);
- if (retval)
- return retval;
- if ((stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
- SD_DAT1_STATUS | SD_DAT0_STATUS)) !=
- (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
- SD_DAT1_STATUS | SD_DAT0_STATUS)) {
- dev_dbg(rtsx_dev(chip), "SD_BUS_STAT: 0x%x\n", stat);
- rtsx_write_register(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN |
- SD_CLK_FORCE_STOP, 0);
- rtsx_write_register(chip, CARD_CLK_EN, 0xFF, 0);
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_register(chip, SD_BUS_STAT,
- SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_reset_dcm(struct rtsx_chip *chip, u8 tune_dir)
-{
- int retval;
-
- if (tune_dir == TUNE_RX) {
- retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF,
- DCM_RESET | DCM_RX);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF, DCM_RX);
- if (retval)
- return retval;
- } else {
- retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF,
- DCM_RESET | DCM_TX);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF, DCM_TX);
- if (retval)
- return retval;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
-{
- struct sd_info *sd_card = &chip->sd_card;
- u16 SD_VP_CTL, SD_DCMPS_CTL;
- u8 val;
- int retval;
- bool ddr_rx = false;
-
- dev_dbg(rtsx_dev(chip), "%s (sample_point = %d, tune_dir = %d)\n",
- __func__, sample_point, tune_dir);
-
- if (tune_dir == TUNE_RX) {
- SD_VP_CTL = SD_VPRX_CTL;
- SD_DCMPS_CTL = SD_DCMPS_RX_CTL;
- if (CHK_SD_DDR50(sd_card))
- ddr_rx = true;
- } else {
- SD_VP_CTL = SD_VPTX_CTL;
- SD_DCMPS_CTL = SD_DCMPS_TX_CTL;
- }
-
- if (chip->asic_code) {
- retval = rtsx_write_register(chip, CLK_CTL, CHANGE_CLK,
- CHANGE_CLK);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SD_VP_CTL, 0x1F,
- sample_point);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, 0);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, PHASE_NOT_RESET);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CLK_CTL, CHANGE_CLK, 0);
- if (retval)
- return retval;
- } else {
- rtsx_read_register(chip, SD_VP_CTL, &val);
- dev_dbg(rtsx_dev(chip), "SD_VP_CTL: 0x%x\n", val);
- rtsx_read_register(chip, SD_DCMPS_CTL, &val);
- dev_dbg(rtsx_dev(chip), "SD_DCMPS_CTL: 0x%x\n", val);
-
- if (ddr_rx) {
- retval = rtsx_write_register(chip, SD_VP_CTL,
- PHASE_CHANGE,
- PHASE_CHANGE);
- if (retval)
- return retval;
- udelay(50);
- retval = rtsx_write_register(chip, SD_VP_CTL, 0xFF,
- PHASE_CHANGE |
- PHASE_NOT_RESET |
- sample_point);
- if (retval)
- return retval;
- } else {
- retval = rtsx_write_register(chip, CLK_CTL,
- CHANGE_CLK, CHANGE_CLK);
- if (retval)
- return retval;
- udelay(50);
- retval = rtsx_write_register(chip, SD_VP_CTL, 0xFF,
- PHASE_NOT_RESET |
- sample_point);
- if (retval)
- return retval;
- }
- udelay(100);
-
- rtsx_init_cmd(chip);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE,
- DCMPS_CHANGE);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL,
- DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE);
- retval = rtsx_send_cmd(chip, SD_CARD, 100);
- if (retval != STATUS_SUCCESS)
- goto fail;
-
- val = *rtsx_get_cmd_data(chip);
- if (val & DCMPS_ERROR)
- goto fail;
-
- if ((val & DCMPS_CURRENT_PHASE) != sample_point)
- goto fail;
-
- retval = rtsx_write_register(chip, SD_DCMPS_CTL,
- DCMPS_CHANGE, 0);
- if (retval)
- return retval;
- if (ddr_rx) {
- retval = rtsx_write_register(chip, SD_VP_CTL,
- PHASE_CHANGE, 0);
- if (retval)
- return retval;
- } else {
- retval = rtsx_write_register(chip, CLK_CTL,
- CHANGE_CLK, 0);
- if (retval)
- return retval;
- }
-
- udelay(50);
- }
-
- retval = rtsx_write_register(chip, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-
-fail:
- rtsx_read_register(chip, SD_VP_CTL, &val);
- dev_dbg(rtsx_dev(chip), "SD_VP_CTL: 0x%x\n", val);
- rtsx_read_register(chip, SD_DCMPS_CTL, &val);
- dev_dbg(rtsx_dev(chip), "SD_DCMPS_CTL: 0x%x\n", val);
-
- rtsx_write_register(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0);
- rtsx_write_register(chip, SD_VP_CTL, PHASE_CHANGE, 0);
- mdelay(10);
- sd_reset_dcm(chip, tune_dir);
- return STATUS_FAIL;
-}
-
-static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd[5], buf[8];
-
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- cmd[0] = 0x40 | SEND_SCR;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 8, 1, bus_width,
- buf, 8, 250);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
- return STATUS_FAIL;
- }
-
- memcpy(sd_card->raw_scr, buf, 8);
-
- if ((buf[0] & 0x0F) == 0)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group,
- u8 func_to_switch, u8 *buf, int buf_len)
-{
- u8 support_mask = 0, query_switch = 0, switch_busy = 0;
- int support_offset = 0, query_switch_offset = 0, check_busy_offset = 0;
-
- if (func_group == SD_FUNC_GROUP_1) {
- support_offset = FUNCTION_GROUP1_SUPPORT_OFFSET;
- query_switch_offset = FUNCTION_GROUP1_QUERY_SWITCH_OFFSET;
- check_busy_offset = FUNCTION_GROUP1_CHECK_BUSY_OFFSET;
-
- switch (func_to_switch) {
- case HS_SUPPORT:
- support_mask = HS_SUPPORT_MASK;
- query_switch = HS_QUERY_SWITCH_OK;
- switch_busy = HS_SWITCH_BUSY;
- break;
-
- case SDR50_SUPPORT:
- support_mask = SDR50_SUPPORT_MASK;
- query_switch = SDR50_QUERY_SWITCH_OK;
- switch_busy = SDR50_SWITCH_BUSY;
- break;
-
- case SDR104_SUPPORT:
- support_mask = SDR104_SUPPORT_MASK;
- query_switch = SDR104_QUERY_SWITCH_OK;
- switch_busy = SDR104_SWITCH_BUSY;
- break;
-
- case DDR50_SUPPORT:
- support_mask = DDR50_SUPPORT_MASK;
- query_switch = DDR50_QUERY_SWITCH_OK;
- switch_busy = DDR50_SWITCH_BUSY;
- break;
-
- default:
- return STATUS_FAIL;
- }
- } else if (func_group == SD_FUNC_GROUP_3) {
- support_offset = FUNCTION_GROUP3_SUPPORT_OFFSET;
- query_switch_offset = FUNCTION_GROUP3_QUERY_SWITCH_OFFSET;
- check_busy_offset = FUNCTION_GROUP3_CHECK_BUSY_OFFSET;
-
- switch (func_to_switch) {
- case DRIVING_TYPE_A:
- support_mask = DRIVING_TYPE_A_MASK;
- query_switch = TYPE_A_QUERY_SWITCH_OK;
- switch_busy = TYPE_A_SWITCH_BUSY;
- break;
-
- case DRIVING_TYPE_C:
- support_mask = DRIVING_TYPE_C_MASK;
- query_switch = TYPE_C_QUERY_SWITCH_OK;
- switch_busy = TYPE_C_SWITCH_BUSY;
- break;
-
- case DRIVING_TYPE_D:
- support_mask = DRIVING_TYPE_D_MASK;
- query_switch = TYPE_D_QUERY_SWITCH_OK;
- switch_busy = TYPE_D_SWITCH_BUSY;
- break;
-
- default:
- return STATUS_FAIL;
- }
- } else if (func_group == SD_FUNC_GROUP_4) {
- support_offset = FUNCTION_GROUP4_SUPPORT_OFFSET;
- query_switch_offset = FUNCTION_GROUP4_QUERY_SWITCH_OFFSET;
- check_busy_offset = FUNCTION_GROUP4_CHECK_BUSY_OFFSET;
-
- switch (func_to_switch) {
- case CURRENT_LIMIT_400:
- support_mask = CURRENT_LIMIT_400_MASK;
- query_switch = CURRENT_LIMIT_400_QUERY_SWITCH_OK;
- switch_busy = CURRENT_LIMIT_400_SWITCH_BUSY;
- break;
-
- case CURRENT_LIMIT_600:
- support_mask = CURRENT_LIMIT_600_MASK;
- query_switch = CURRENT_LIMIT_600_QUERY_SWITCH_OK;
- switch_busy = CURRENT_LIMIT_600_SWITCH_BUSY;
- break;
-
- case CURRENT_LIMIT_800:
- support_mask = CURRENT_LIMIT_800_MASK;
- query_switch = CURRENT_LIMIT_800_QUERY_SWITCH_OK;
- switch_busy = CURRENT_LIMIT_800_SWITCH_BUSY;
- break;
-
- default:
- return STATUS_FAIL;
- }
- } else {
- return STATUS_FAIL;
- }
-
- if (func_group == SD_FUNC_GROUP_1) {
- if (!(buf[support_offset] & support_mask) ||
- ((buf[query_switch_offset] & 0x0F) != query_switch)) {
- return STATUS_FAIL;
- }
- }
-
- /* Check 'Busy Status' */
- if (buf[DATA_STRUCTURE_VER_OFFSET] == 0x01 &&
- ((buf[check_busy_offset] & switch_busy) == switch_busy)) {
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode, u8 func_group,
- u8 func_to_switch, u8 bus_width)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd[5], buf[64];
-
- dev_dbg(rtsx_dev(chip), "%s (mode = %d, func_group = %d, func_to_switch = %d)\n",
- __func__, mode, func_group, func_to_switch);
-
- cmd[0] = 0x40 | SWITCH;
- cmd[1] = mode;
-
- if (func_group == SD_FUNC_GROUP_1) {
- cmd[2] = 0xFF;
- cmd[3] = 0xFF;
- cmd[4] = 0xF0 + func_to_switch;
- } else if (func_group == SD_FUNC_GROUP_3) {
- cmd[2] = 0xFF;
- cmd[3] = 0xF0 + func_to_switch;
- cmd[4] = 0xFF;
- } else if (func_group == SD_FUNC_GROUP_4) {
- cmd[2] = 0xFF;
- cmd[3] = 0x0F + (func_to_switch << 4);
- cmd[4] = 0xFF;
- } else {
- cmd[1] = SD_CHECK_MODE;
- cmd[2] = 0xFF;
- cmd[3] = 0xFF;
- cmd[4] = 0xFF;
- }
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, bus_width,
- buf, 64, 250);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
- return STATUS_FAIL;
- }
-
- dev_dbg(rtsx_dev(chip), "%*ph\n", 64, buf);
-
- if (func_group == NO_ARGUMENT) {
- sd_card->func_group1_mask = buf[0x0D];
- sd_card->func_group2_mask = buf[0x0B];
- sd_card->func_group3_mask = buf[0x09];
- sd_card->func_group4_mask = buf[0x07];
-
- dev_dbg(rtsx_dev(chip), "func_group1_mask = 0x%02x\n",
- buf[0x0D]);
- dev_dbg(rtsx_dev(chip), "func_group2_mask = 0x%02x\n",
- buf[0x0B]);
- dev_dbg(rtsx_dev(chip), "func_group3_mask = 0x%02x\n",
- buf[0x09]);
- dev_dbg(rtsx_dev(chip), "func_group4_mask = 0x%02x\n",
- buf[0x07]);
- } else {
- /* Maximum current consumption, check whether current is
- * acceptable; bit[511:496] = 0x0000 means some error happened.
- */
- u16 cc = ((u16)buf[0] << 8) | buf[1];
-
- dev_dbg(rtsx_dev(chip), "Maximum current consumption: %dmA\n",
- cc);
- if (cc == 0 || cc > 800)
- return STATUS_FAIL;
-
- retval = sd_query_switch_result(chip, func_group,
- func_to_switch, buf, 64);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (cc > 400 || func_to_switch > CURRENT_LIMIT_400) {
- retval = rtsx_write_register(chip, OCPPARA2,
- SD_OCP_THD_MASK,
- chip->sd_800mA_ocp_thd);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PWR_CTL,
- PMOS_STRG_MASK,
- PMOS_STRG_800mA);
- if (retval)
- return retval;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static u8 downgrade_switch_mode(u8 func_group, u8 func_to_switch)
-{
- if (func_group == SD_FUNC_GROUP_1) {
- if (func_to_switch > HS_SUPPORT)
- func_to_switch--;
-
- } else if (func_group == SD_FUNC_GROUP_4) {
- if (func_to_switch > CURRENT_LIMIT_200)
- func_to_switch--;
- }
-
- return func_to_switch;
-}
-
-static int sd_check_switch(struct rtsx_chip *chip,
- u8 func_group, u8 func_to_switch, u8 bus_width)
-{
- int retval;
- int i;
- bool switch_good = false;
-
- for (i = 0; i < 3; i++) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = sd_check_switch_mode(chip, SD_CHECK_MODE, func_group,
- func_to_switch, bus_width);
- if (retval == STATUS_SUCCESS) {
- u8 stat;
-
- retval = sd_check_switch_mode(chip, SD_SWITCH_MODE,
- func_group,
- func_to_switch,
- bus_width);
- if (retval == STATUS_SUCCESS) {
- switch_good = true;
- break;
- }
-
- retval = rtsx_read_register(chip, SD_STAT1, &stat);
- if (retval)
- return retval;
- if (stat & SD_CRC16_ERR) {
- dev_dbg(rtsx_dev(chip), "SD CRC16 error when switching mode\n");
- return STATUS_FAIL;
- }
- }
-
- func_to_switch = downgrade_switch_mode(func_group,
- func_to_switch);
-
- wait_timeout(20);
- }
-
- if (!switch_good)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i;
- u8 func_to_switch = 0;
-
- /* Get supported functions */
- retval = sd_check_switch_mode(chip, SD_CHECK_MODE, NO_ARGUMENT,
- NO_ARGUMENT, bus_width);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- sd_card->func_group1_mask &= ~(sd_card->sd_switch_fail);
-
- /* Function Group 1: Access Mode */
- for (i = 0; i < 4; i++) {
- switch ((u8)(chip->sd_speed_prior >> (i * 8))) {
- case SDR104_SUPPORT:
- if ((sd_card->func_group1_mask & SDR104_SUPPORT_MASK) &&
- chip->sdr104_en) {
- func_to_switch = SDR104_SUPPORT;
- }
- break;
-
- case DDR50_SUPPORT:
- if ((sd_card->func_group1_mask & DDR50_SUPPORT_MASK) &&
- chip->ddr50_en) {
- func_to_switch = DDR50_SUPPORT;
- }
- break;
-
- case SDR50_SUPPORT:
- if ((sd_card->func_group1_mask & SDR50_SUPPORT_MASK) &&
- chip->sdr50_en) {
- func_to_switch = SDR50_SUPPORT;
- }
- break;
-
- case HS_SUPPORT:
- if (sd_card->func_group1_mask & HS_SUPPORT_MASK)
- func_to_switch = HS_SUPPORT;
-
- break;
-
- default:
- continue;
- }
-
- if (func_to_switch)
- break;
- }
- dev_dbg(rtsx_dev(chip), "SD_FUNC_GROUP_1: func_to_switch = 0x%02x",
- func_to_switch);
-
-#ifdef SUPPORT_SD_LOCK
- if ((sd_card->sd_lock_status & SD_SDR_RST) &&
- func_to_switch == DDR50_SUPPORT &&
- (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) {
- func_to_switch = SDR50_SUPPORT;
- dev_dbg(rtsx_dev(chip), "Using SDR50 instead of DDR50 for SD Lock\n");
- }
-#endif
-
- if (func_to_switch) {
- retval = sd_check_switch(chip, SD_FUNC_GROUP_1, func_to_switch,
- bus_width);
- if (retval != STATUS_SUCCESS) {
- if (func_to_switch == SDR104_SUPPORT) {
- sd_card->sd_switch_fail = SDR104_SUPPORT_MASK;
- } else if (func_to_switch == DDR50_SUPPORT) {
- sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
- DDR50_SUPPORT_MASK;
- } else if (func_to_switch == SDR50_SUPPORT) {
- sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
- DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK;
- }
- return STATUS_FAIL;
- }
-
- if (func_to_switch == SDR104_SUPPORT)
- SET_SD_SDR104(sd_card);
- else if (func_to_switch == DDR50_SUPPORT)
- SET_SD_DDR50(sd_card);
- else if (func_to_switch == SDR50_SUPPORT)
- SET_SD_SDR50(sd_card);
- else
- SET_SD_HS(sd_card);
- }
-
- if (CHK_SD_DDR50(sd_card)) {
- retval = rtsx_write_register(chip, SD_PUSH_POINT_CTL, 0x06,
- 0x04);
- if (retval)
- return retval;
- retval = sd_set_sample_push_timing(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- if (!func_to_switch || func_to_switch == HS_SUPPORT) {
- /* Do not try to switch current limit if the card doesn't
- * support UHS mode or we don't want it to support UHS mode
- */
- return STATUS_SUCCESS;
- }
-
- /* Function Group 4: Current Limit */
- func_to_switch = 0xFF;
-
- for (i = 0; i < 4; i++) {
- switch ((u8)(chip->sd_current_prior >> (i * 8))) {
- case CURRENT_LIMIT_800:
- if (sd_card->func_group4_mask & CURRENT_LIMIT_800_MASK)
- func_to_switch = CURRENT_LIMIT_800;
-
- break;
-
- case CURRENT_LIMIT_600:
- if (sd_card->func_group4_mask & CURRENT_LIMIT_600_MASK)
- func_to_switch = CURRENT_LIMIT_600;
-
- break;
-
- case CURRENT_LIMIT_400:
- if (sd_card->func_group4_mask & CURRENT_LIMIT_400_MASK)
- func_to_switch = CURRENT_LIMIT_400;
-
- break;
-
- case CURRENT_LIMIT_200:
- if (sd_card->func_group4_mask & CURRENT_LIMIT_200_MASK)
- func_to_switch = CURRENT_LIMIT_200;
-
- break;
-
- default:
- continue;
- }
-
- if (func_to_switch != 0xFF)
- break;
- }
-
- dev_dbg(rtsx_dev(chip), "SD_FUNC_GROUP_4: func_to_switch = 0x%02x",
- func_to_switch);
-
- if (func_to_switch <= CURRENT_LIMIT_800) {
- retval = sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch,
- bus_width);
- if (retval != STATUS_SUCCESS) {
- if (sd_check_err_code(chip, SD_NO_CARD))
- return STATUS_FAIL;
- }
- dev_dbg(rtsx_dev(chip), "Switch current limit finished! (%d)\n",
- retval);
- }
-
- if (CHK_SD_DDR50(sd_card)) {
- retval = rtsx_write_register(chip, SD_PUSH_POINT_CTL, 0x06, 0);
- if (retval)
- return retval;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_wait_data_idle(struct rtsx_chip *chip)
-{
- int retval = STATUS_TIMEDOUT;
- int i;
- u8 val = 0;
-
- for (i = 0; i < 100; i++) {
- retval = rtsx_read_register(chip, SD_DATA_STATE, &val);
- if (retval)
- return retval;
- if (val & SD_DATA_IDLE) {
- retval = STATUS_SUCCESS;
- break;
- }
- udelay(100);
- }
- dev_dbg(rtsx_dev(chip), "SD_DATA_STATE: 0x%02x\n", val);
-
- return retval;
-}
-
-static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
- int retval;
- u8 cmd[5];
-
- retval = sd_change_phase(chip, sample_point, TUNE_RX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- cmd[0] = 0x40 | SEND_TUNING_PATTERN;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- retval = sd_read_data(chip, SD_TM_AUTO_TUNING, cmd, 5, 0x40, 1,
- SD_BUS_WIDTH_4, NULL, 0, 100);
- if (retval != STATUS_SUCCESS) {
- (void)sd_wait_data_idle(chip);
-
- rtsx_clear_sd_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd[5];
-
- retval = sd_change_phase(chip, sample_point, TUNE_RX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "sd ddr tuning rx\n");
-
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- cmd[0] = 0x40 | SD_STATUS;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1,
- SD_BUS_WIDTH_4, NULL, 0, 100);
- if (retval != STATUS_SUCCESS) {
- (void)sd_wait_data_idle(chip);
-
- rtsx_clear_sd_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int mmc_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd[5], bus_width;
-
- if (CHK_MMC_8BIT(sd_card))
- bus_width = SD_BUS_WIDTH_8;
- else if (CHK_MMC_4BIT(sd_card))
- bus_width = SD_BUS_WIDTH_4;
- else
- bus_width = SD_BUS_WIDTH_1;
-
- retval = sd_change_phase(chip, sample_point, TUNE_RX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "mmc ddr tuning rx\n");
-
- cmd[0] = 0x40 | SEND_EXT_CSD;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 0x200, 1,
- bus_width, NULL, 0, 100);
- if (retval != STATUS_SUCCESS) {
- (void)sd_wait_data_idle(chip);
-
- rtsx_clear_sd_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- retval = sd_change_phase(chip, sample_point, TUNE_TX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
- SD_RSP_80CLK_TIMEOUT_EN);
- if (retval)
- return retval;
-
- retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS) {
- if (sd_check_err_code(chip, SD_RSP_TIMEOUT)) {
- rtsx_write_register(chip, SD_CFG3,
- SD_RSP_80CLK_TIMEOUT_EN, 0);
- return STATUS_FAIL;
- }
- }
-
- retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
- 0);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd[5], bus_width;
-
- retval = sd_change_phase(chip, sample_point, TUNE_TX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_SD(sd_card)) {
- bus_width = SD_BUS_WIDTH_4;
- } else {
- if (CHK_MMC_8BIT(sd_card))
- bus_width = SD_BUS_WIDTH_8;
- else if (CHK_MMC_4BIT(sd_card))
- bus_width = SD_BUS_WIDTH_4;
- else
- bus_width = SD_BUS_WIDTH_1;
- }
-
- retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
- SD_RSP_80CLK_TIMEOUT_EN);
- if (retval)
- return retval;
-
- cmd[0] = 0x40 | PROGRAM_CSD;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- retval = sd_write_data(chip, SD_TM_AUTO_WRITE_2, cmd, 5, 16, 1,
- bus_width, sd_card->raw_csd, 16, 100);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
- rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
- 0);
- if (retval)
- return retval;
-
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1,
- NULL, 0);
-
- return STATUS_SUCCESS;
-}
-
-static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map,
- u8 tune_dir)
-{
- struct sd_info *sd_card = &chip->sd_card;
- struct timing_phase_path path[MAX_PHASE + 1];
- int i, j, cont_path_cnt;
- bool new_block;
- int max_len, final_path_idx;
- u8 final_phase = 0xFF;
-
- if (phase_map == 0xFFFFFFFF) {
- if (tune_dir == TUNE_RX)
- final_phase = (u8)chip->sd_default_rx_phase;
- else
- final_phase = (u8)chip->sd_default_tx_phase;
-
- goto search_finish;
- }
-
- cont_path_cnt = 0;
- new_block = true;
- j = 0;
- for (i = 0; i < MAX_PHASE + 1; i++) {
- if (phase_map & (1 << i)) {
- if (new_block) {
- new_block = false;
- j = cont_path_cnt++;
- path[j].start = i;
- path[j].end = i;
- } else {
- path[j].end = i;
- }
- } else {
- new_block = true;
- if (cont_path_cnt) {
- int idx = cont_path_cnt - 1;
-
- path[idx].len = path[idx].end -
- path[idx].start + 1;
- path[idx].mid = path[idx].start +
- path[idx].len / 2;
- }
- }
- }
-
- if (cont_path_cnt == 0) {
- dev_dbg(rtsx_dev(chip), "No continuous phase path\n");
- goto search_finish;
- } else {
- int idx = cont_path_cnt - 1;
-
- path[idx].len = path[idx].end - path[idx].start + 1;
- path[idx].mid = path[idx].start + path[idx].len / 2;
- }
-
- if (path[0].start == 0 &&
- path[cont_path_cnt - 1].end == MAX_PHASE) {
- path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1;
- path[0].len += path[cont_path_cnt - 1].len;
- path[0].mid = path[0].start + path[0].len / 2;
- if (path[0].mid < 0)
- path[0].mid += MAX_PHASE + 1;
-
- cont_path_cnt--;
- }
-
- max_len = 0;
- final_phase = 0;
- final_path_idx = 0;
- for (i = 0; i < cont_path_cnt; i++) {
- if (path[i].len > max_len) {
- max_len = path[i].len;
- final_phase = (u8)path[i].mid;
- final_path_idx = i;
- }
-
- dev_dbg(rtsx_dev(chip), "path[%d].start = %d\n",
- i, path[i].start);
- dev_dbg(rtsx_dev(chip), "path[%d].end = %d\n", i, path[i].end);
- dev_dbg(rtsx_dev(chip), "path[%d].len = %d\n", i, path[i].len);
- dev_dbg(rtsx_dev(chip), "path[%d].mid = %d\n", i, path[i].mid);
- dev_dbg(rtsx_dev(chip), "\n");
- }
-
- if (tune_dir == TUNE_TX) {
- if (CHK_SD_SDR104(sd_card)) {
- if (max_len > 15) {
- int temp_mid = (max_len - 16) / 2;
- int temp_final_phase =
- path[final_path_idx].end -
- (max_len - (6 + temp_mid));
-
- if (temp_final_phase < 0)
- final_phase = (u8)(temp_final_phase +
- MAX_PHASE + 1);
- else
- final_phase = (u8)temp_final_phase;
- }
- } else if (CHK_SD_SDR50(sd_card)) {
- if (max_len > 12) {
- int temp_mid = (max_len - 13) / 2;
- int temp_final_phase =
- path[final_path_idx].end -
- (max_len - (3 + temp_mid));
-
- if (temp_final_phase < 0)
- final_phase = (u8)(temp_final_phase +
- MAX_PHASE + 1);
- else
- final_phase = (u8)temp_final_phase;
- }
- }
- }
-
-search_finish:
- dev_dbg(rtsx_dev(chip), "Final chosen phase: %d\n", final_phase);
- return final_phase;
-}
-
-static int sd_tuning_rx(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i, j;
- u32 raw_phase_map[3], phase_map;
- u8 final_phase;
- int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point);
-
- if (CHK_SD(sd_card)) {
- if (CHK_SD_DDR50(sd_card))
- tuning_cmd = sd_ddr_tuning_rx_cmd;
- else
- tuning_cmd = sd_sdr_tuning_rx_cmd;
-
- } else {
- if (CHK_MMC_DDR52(sd_card))
- tuning_cmd = mmc_ddr_tuning_rx_cmd;
- else
- return STATUS_FAIL;
- }
-
- for (i = 0; i < 3; i++) {
- raw_phase_map[i] = 0;
- for (j = MAX_PHASE; j >= 0; j--) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = tuning_cmd(chip, (u8)j);
- if (retval == STATUS_SUCCESS)
- raw_phase_map[i] |= 1 << j;
- }
- }
-
- phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2];
- for (i = 0; i < 3; i++)
- dev_dbg(rtsx_dev(chip), "RX raw_phase_map[%d] = 0x%08x\n",
- i, raw_phase_map[i]);
-
- dev_dbg(rtsx_dev(chip), "RX phase_map = 0x%08x\n", phase_map);
-
- final_phase = sd_search_final_phase(chip, phase_map, TUNE_RX);
- if (final_phase == 0xFF)
- return STATUS_FAIL;
-
- retval = sd_change_phase(chip, final_phase, TUNE_RX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i;
- u32 phase_map;
- u8 final_phase;
-
- retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
- SD_RSP_80CLK_TIMEOUT_EN);
- if (retval)
- return retval;
-
- phase_map = 0;
- for (i = MAX_PHASE; i >= 0; i--) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- rtsx_write_register(chip, SD_CFG3,
- SD_RSP_80CLK_TIMEOUT_EN, 0);
- return STATUS_FAIL;
- }
-
- retval = sd_change_phase(chip, (u8)i, TUNE_TX);
- if (retval != STATUS_SUCCESS)
- continue;
-
- retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
- sd_card->sd_addr, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval == STATUS_SUCCESS ||
- !sd_check_err_code(chip, SD_RSP_TIMEOUT))
- phase_map |= 1 << i;
- }
-
- retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
- 0);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "DDR TX pre tune phase_map = 0x%08x\n",
- phase_map);
-
- final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
- if (final_phase == 0xFF)
- return STATUS_FAIL;
-
- retval = sd_change_phase(chip, final_phase, TUNE_TX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "DDR TX pre tune phase: %d\n",
- (int)final_phase);
-
- return STATUS_SUCCESS;
-}
-
-static int sd_tuning_tx(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i, j;
- u32 raw_phase_map[3], phase_map;
- u8 final_phase;
- int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point);
-
- if (CHK_SD(sd_card)) {
- if (CHK_SD_DDR50(sd_card))
- tuning_cmd = sd_ddr_tuning_tx_cmd;
- else
- tuning_cmd = sd_sdr_tuning_tx_cmd;
-
- } else {
- if (CHK_MMC_DDR52(sd_card))
- tuning_cmd = sd_ddr_tuning_tx_cmd;
- else
- return STATUS_FAIL;
- }
-
- for (i = 0; i < 3; i++) {
- raw_phase_map[i] = 0;
- for (j = MAX_PHASE; j >= 0; j--) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- rtsx_write_register(chip, SD_CFG3,
- SD_RSP_80CLK_TIMEOUT_EN, 0);
- return STATUS_FAIL;
- }
-
- retval = tuning_cmd(chip, (u8)j);
- if (retval == STATUS_SUCCESS)
- raw_phase_map[i] |= 1 << j;
- }
- }
-
- phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2];
- for (i = 0; i < 3; i++)
- dev_dbg(rtsx_dev(chip), "TX raw_phase_map[%d] = 0x%08x\n",
- i, raw_phase_map[i]);
-
- dev_dbg(rtsx_dev(chip), "TX phase_map = 0x%08x\n", phase_map);
-
- final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
- if (final_phase == 0xFF)
- return STATUS_FAIL;
-
- retval = sd_change_phase(chip, final_phase, TUNE_TX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_sdr_tuning(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = sd_tuning_tx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sd_tuning_rx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_ddr_tuning(struct rtsx_chip *chip)
-{
- int retval;
-
- if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
- retval = sd_ddr_pre_tuning_tx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = sd_change_phase(chip, (u8)chip->sd_ddr_tx_phase,
- TUNE_TX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = sd_tuning_rx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
- retval = sd_tuning_tx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int mmc_ddr_tuning(struct rtsx_chip *chip)
-{
- int retval;
-
- if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
- retval = sd_ddr_pre_tuning_tx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = sd_change_phase(chip, (u8)chip->mmc_ddr_tx_phase,
- TUNE_TX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = sd_tuning_rx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
- retval = sd_tuning_tx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int sd_switch_clock(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int re_tuning = 0;
-
- retval = select_card(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = switch_clock(chip, sd_card->sd_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (re_tuning) {
- if (CHK_SD(sd_card)) {
- if (CHK_SD_DDR50(sd_card))
- retval = sd_ddr_tuning(chip);
- else
- retval = sd_sdr_tuning(chip);
- } else {
- if (CHK_MMC_DDR52(sd_card))
- retval = mmc_ddr_tuning(chip);
- }
-
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_prepare_reset(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- if (chip->asic_code)
- sd_card->sd_clock = 29;
- else
- sd_card->sd_clock = CLK_30;
-
- sd_card->sd_type = 0;
- sd_card->seq_mode = 0;
- sd_card->sd_data_buf_ready = 0;
- sd_card->capacity = 0;
-
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status = 0;
- sd_card->sd_erase_status = 0;
-#endif
-
- chip->capacity[chip->card2lun[SD_CARD]] = 0;
- chip->sd_io = 0;
-
- retval = sd_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return retval;
-
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0xFF, 0x40);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
- SD_STOP | SD_CLR_ERR);
- if (retval)
- return retval;
-
- retval = select_card(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_pull_ctl_disable(struct rtsx_chip *chip)
-{
- int retval;
-
- if (CHECK_PID(chip, 0x5208)) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF,
- XD_D3_PD | SD_D7_PD | SD_CLK_PD |
- SD_D5_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF,
- SD_D6_PD | SD_D0_PD | SD_D1_PD |
- XD_D5_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF,
- SD_D4_PD | XD_CE_PD | XD_CLE_PD |
- XD_CD_PU);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PD | SD_D3_PD | SD_D2_PD |
- XD_ALE_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU | SD_WP_PD | SD_CD_PU |
- SD_CMD_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- if (retval)
- return retval;
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL1,
- 0xFF, 0x55);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL2,
- 0xFF, 0x55);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL3,
- 0xFF, 0x4B);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL4,
- 0xFF, 0x69);
- if (retval)
- return retval;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-int sd_pull_ctl_enable(struct rtsx_chip *chip)
-{
- int retval;
-
- rtsx_init_cmd(chip);
-
- if (CHECK_PID(chip, 0x5208)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
- XD_D3_PD | SD_DAT7_PU | SD_CLK_NP | SD_D5_PU);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
- SD_D6_PU | SD_D0_PU | SD_D1_PU | XD_D5_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
- SD_D4_PU | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PD | SD_D3_PU | SD_D2_PU | XD_ALE_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
- 0xA8);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
- 0x5A);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
- 0x95);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
- 0xAA);
- }
- }
-
- retval = rtsx_send_cmd(chip, SD_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_init_power(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = sd_power_off_card3v3(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!chip->ft2_fast_mode)
- wait_timeout(250);
-
- retval = enable_card_clock(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (chip->asic_code) {
- retval = sd_pull_ctl_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL,
- FPGA_SD_PULL_CTL_BIT | 0x20, 0);
- if (retval)
- return retval;
- }
-
- if (!chip->ft2_fast_mode) {
- retval = card_power_on(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- wait_timeout(260);
-
-#ifdef SUPPORT_OCP
- if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
- dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
- chip->ocp_stat);
- return STATUS_FAIL;
- }
-#endif
- }
-
- retval = rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN,
- SD_OUTPUT_EN);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_dummy_clock(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = rtsx_write_register(chip, REG_SD_CFG3, 0x01, 0x01);
- if (retval)
- return retval;
- wait_timeout(5);
- retval = rtsx_write_register(chip, REG_SD_CFG3, 0x01, 0);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_read_lba0(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd[5], bus_width;
-
- cmd[0] = 0x40 | READ_SINGLE_BLOCK;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- if (CHK_SD(sd_card)) {
- bus_width = SD_BUS_WIDTH_4;
- } else {
- if (CHK_MMC_8BIT(sd_card))
- bus_width = SD_BUS_WIDTH_8;
- else if (CHK_MMC_4BIT(sd_card))
- bus_width = SD_BUS_WIDTH_4;
- else
- bus_width = SD_BUS_WIDTH_1;
- }
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 512, 1,
- bus_width, NULL, 0, 100);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_check_wp_state(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u32 val;
- u16 sd_card_type;
- u8 cmd[5], buf[64];
-
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- cmd[0] = 0x40 | SD_STATUS;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1,
- SD_BUS_WIDTH_4, buf, 64, 250);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
-
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- return STATUS_FAIL;
- }
-
- dev_dbg(rtsx_dev(chip), "ACMD13:\n");
- dev_dbg(rtsx_dev(chip), "%*ph\n", 64, buf);
-
- sd_card_type = ((u16)buf[2] << 8) | buf[3];
- dev_dbg(rtsx_dev(chip), "sd_card_type = 0x%04x\n", sd_card_type);
- if (sd_card_type == 0x0001 || sd_card_type == 0x0002) {
- /* ROM card or OTP */
- chip->card_wp |= SD_CARD;
- }
-
- /* Check SD Machanical Write-Protect Switch */
- val = rtsx_readl(chip, RTSX_BIPR);
- if (val & SD_WRITE_PROTECT)
- chip->card_wp |= SD_CARD;
-
- return STATUS_SUCCESS;
-}
-
-static int reset_sd(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- bool hi_cap_flow = false;
- int retval, i = 0, j = 0, k = 0;
- bool sd_dont_switch = false;
- bool support_1v8 = false;
- bool try_sdio = true;
- u8 rsp[16];
- u8 switch_bus_width;
- u32 voltage = 0;
- bool sd20_mode = false;
-
- SET_SD(sd_card);
-
-switch_fail:
-
- i = 0;
- j = 0;
- k = 0;
- hi_cap_flow = false;
-
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
- goto SD_UNLOCK_ENTRY;
-#endif
-
- retval = sd_prepare_reset(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- retval = sd_dummy_clock(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) {
- int rty_cnt = 0;
-
- for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- goto status_fail;
- }
-
- retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0,
- SD_RSP_TYPE_R4, rsp, 5);
- if (retval == STATUS_SUCCESS) {
- int func_num = (rsp[1] >> 4) & 0x07;
-
- if (func_num) {
- dev_dbg(rtsx_dev(chip), "SD_IO card (Function number: %d)!\n",
- func_num);
- chip->sd_io = 1;
- goto status_fail;
- }
-
- break;
- }
-
- sd_init_power(chip);
-
- sd_dummy_clock(chip);
- }
-
- dev_dbg(rtsx_dev(chip), "Normal card!\n");
- }
-
- /* Start Initialization Process of SD Card */
-RTY_SD_RST:
- retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- wait_timeout(20);
-
- retval = sd_send_cmd_get_rsp(chip, SEND_IF_COND, 0x000001AA,
- SD_RSP_TYPE_R7, rsp, 5);
- if (retval == STATUS_SUCCESS) {
- if (rsp[4] == 0xAA && ((rsp[3] & 0x0f) == 0x01)) {
- hi_cap_flow = true;
- voltage = SUPPORT_VOLTAGE | 0x40000000;
- }
- }
-
- if (!hi_cap_flow) {
- voltage = SUPPORT_VOLTAGE;
-
- retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0,
- SD_RSP_TYPE_R0, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- wait_timeout(20);
- }
-
- do {
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, 0, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- goto status_fail;
- }
-
- j++;
- if (j < 3)
- goto RTY_SD_RST;
- else
- goto status_fail;
- }
-
- retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage,
- SD_RSP_TYPE_R3, rsp, 5);
- if (retval != STATUS_SUCCESS) {
- k++;
- if (k < 3)
- goto RTY_SD_RST;
- else
- goto status_fail;
- }
-
- i++;
- wait_timeout(20);
- } while (!(rsp[1] & 0x80) && (i < 255));
-
- if (i == 255)
- goto status_fail;
-
- if (hi_cap_flow) {
- if (rsp[1] & 0x40)
- SET_SD_HCXC(sd_card);
- else
- CLR_SD_HCXC(sd_card);
-
- support_1v8 = false;
- } else {
- CLR_SD_HCXC(sd_card);
- support_1v8 = false;
- }
- dev_dbg(rtsx_dev(chip), "support_1v8 = %d\n", support_1v8);
-
- if (support_1v8) {
- retval = sd_voltage_switch(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
- }
-
- retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- for (i = 0; i < 3; i++) {
- retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0,
- SD_RSP_TYPE_R6, rsp, 5);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- sd_card->sd_addr = (u32)rsp[1] << 24;
- sd_card->sd_addr += (u32)rsp[2] << 16;
-
- if (sd_card->sd_addr)
- break;
- }
-
- retval = sd_check_csd(chip, 1);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- retval = sd_select_card(chip, 1);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
-#ifdef SUPPORT_SD_LOCK
-SD_UNLOCK_ENTRY:
- retval = sd_update_lock_status(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- if (sd_card->sd_lock_status & SD_LOCKED) {
- sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST);
- return STATUS_SUCCESS;
- } else if (!(sd_card->sd_lock_status & SD_UNLOCK_POW_ON)) {
- sd_card->sd_lock_status &= ~SD_PWD_EXIST;
- }
-#endif
-
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- if (support_1v8) {
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- switch_bus_width = SD_BUS_WIDTH_4;
- } else {
- switch_bus_width = SD_BUS_WIDTH_1;
- }
-
- retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- if (!(sd_card->raw_csd[4] & 0x40))
- sd_dont_switch = true;
-
- if (!sd_dont_switch) {
- if (sd20_mode) {
- /* Set sd_switch_fail here, because we needn't
- * switch to UHS mode
- */
- sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
- DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK;
- }
-
- /* Check the card whether follow SD1.1 spec or higher */
- retval = sd_check_spec(chip, switch_bus_width);
- if (retval == STATUS_SUCCESS) {
- retval = sd_switch_function(chip, switch_bus_width);
- if (retval != STATUS_SUCCESS) {
- sd_init_power(chip);
- sd_dont_switch = true;
- try_sdio = false;
-
- goto switch_fail;
- }
- } else {
- if (support_1v8) {
- sd_init_power(chip);
- sd_dont_switch = true;
- try_sdio = false;
-
- goto switch_fail;
- }
- }
- }
-
- if (!support_1v8) {
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
- }
-
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
-#endif
-
- if (!sd20_mode && CHK_SD30_SPEED(sd_card)) {
- int read_lba0 = 1;
-
- retval = rtsx_write_register(chip, SD30_DRIVE_SEL, 0x07,
- chip->sd30_drive_sel_1v8);
- if (retval)
- return retval;
-
- retval = sd_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- if (CHK_SD_DDR50(sd_card))
- retval = sd_ddr_tuning(chip);
- else
- retval = sd_sdr_tuning(chip);
-
- if (retval != STATUS_SUCCESS) {
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- try_sdio = false;
- sd20_mode = true;
- goto switch_fail;
- }
-
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
-
- if (CHK_SD_DDR50(sd_card)) {
- retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
- if (retval != STATUS_SUCCESS)
- read_lba0 = 0;
- }
-
- if (read_lba0) {
- retval = sd_read_lba0(chip);
- if (retval != STATUS_SUCCESS) {
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- try_sdio = false;
- sd20_mode = true;
- goto switch_fail;
- }
- }
- }
-
- retval = sd_check_wp_state(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
-
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
- retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_H, 0xFF,
- 0x02);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_L, 0xFF,
- 0x00);
- if (retval)
- return retval;
- }
-#endif
-
- return STATUS_SUCCESS;
-
-status_fail:
- return STATUS_FAIL;
-}
-
-static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 buf[8] = {0}, bus_width, *ptr;
- u16 byte_cnt;
- int len;
-
- retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL,
- 0);
- if (retval != STATUS_SUCCESS)
- return SWITCH_FAIL;
-
- if (width == MMC_8BIT_BUS) {
- buf[0] = 0x55;
- buf[1] = 0xAA;
- len = 8;
- byte_cnt = 8;
- bus_width = SD_BUS_WIDTH_8;
- } else {
- buf[0] = 0x5A;
- len = 4;
- byte_cnt = 4;
- bus_width = SD_BUS_WIDTH_4;
- }
-
- retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0x02);
- if (retval != STATUS_SUCCESS)
- return SWITCH_ERR;
-
- retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3, NULL, 0, byte_cnt, 1,
- bus_width, buf, len, 100);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
- rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
- return SWITCH_ERR;
- }
-
- retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
- if (retval != STATUS_SUCCESS)
- return SWITCH_ERR;
-
- dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", BUSTEST_R);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | BUSTEST_R);
-
- if (width == MMC_8BIT_BUS)
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L,
- 0xFF, 0x08);
- else
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L,
- 0xFF, 0x04);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, SD_CALCULATE_CRC7 |
- SD_NO_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
- SD_CHECK_CRC7 | SD_RSP_LEN_6);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_NORMAL_READ | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
- SD_TRANSFER_END);
-
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2, 0, 0);
- if (width == MMC_8BIT_BUS)
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 1, 0, 0);
-
- retval = rtsx_send_cmd(chip, SD_CARD, 100);
- if (retval < 0) {
- rtsx_clear_sd_error(chip);
- return SWITCH_ERR;
- }
-
- ptr = rtsx_get_cmd_data(chip) + 1;
-
- if (width == MMC_8BIT_BUS) {
- dev_dbg(rtsx_dev(chip), "BUSTEST_R [8bits]: 0x%02x 0x%02x\n",
- ptr[0], ptr[1]);
- if (ptr[0] == 0xAA && ptr[1] == 0x55) {
- u8 rsp[5];
- u32 arg;
-
- if (CHK_MMC_DDR52(sd_card))
- arg = 0x03B70600;
- else
- arg = 0x03B70200;
-
- retval = sd_send_cmd_get_rsp(chip, SWITCH, arg,
- SD_RSP_TYPE_R1b, rsp, 5);
- if (retval == STATUS_SUCCESS &&
- !(rsp[4] & MMC_SWITCH_ERR))
- return SWITCH_SUCCESS;
- }
- } else {
- dev_dbg(rtsx_dev(chip), "BUSTEST_R [4bits]: 0x%02x\n", ptr[0]);
- if (ptr[0] == 0xA5) {
- u8 rsp[5];
- u32 arg;
-
- if (CHK_MMC_DDR52(sd_card))
- arg = 0x03B70500;
- else
- arg = 0x03B70100;
-
- retval = sd_send_cmd_get_rsp(chip, SWITCH, arg,
- SD_RSP_TYPE_R1b, rsp, 5);
- if (retval == STATUS_SUCCESS &&
- !(rsp[4] & MMC_SWITCH_ERR))
- return SWITCH_SUCCESS;
- }
- }
-
- return SWITCH_FAIL;
-}
-
-static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 *ptr, card_type, card_type_mask = 0;
-
- CLR_MMC_HS(sd_card);
-
- dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", SEND_EXT_CSD);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF,
- 0x40 | SEND_EXT_CSD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, 0);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 2);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
- SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
- SD_CHECK_CRC7 | SD_RSP_LEN_6);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_NORMAL_READ | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
- SD_TRANSFER_END);
-
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 196, 0xFF, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 212, 0xFF, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 213, 0xFF, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 214, 0xFF, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 215, 0xFF, 0);
-
- retval = rtsx_send_cmd(chip, SD_CARD, 1000);
- if (retval < 0) {
- if (retval == -ETIMEDOUT) {
- rtsx_clear_sd_error(chip);
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- }
- return STATUS_FAIL;
- }
-
- ptr = rtsx_get_cmd_data(chip);
- if (ptr[0] & SD_TRANSFER_ERR) {
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- return STATUS_FAIL;
- }
-
- if (CHK_MMC_SECTOR_MODE(sd_card)) {
- sd_card->capacity = ((u32)ptr[5] << 24) | ((u32)ptr[4] << 16) |
- ((u32)ptr[3] << 8) | ((u32)ptr[2]);
- }
-
- card_type_mask = 0x03;
- card_type = ptr[1] & card_type_mask;
- if (card_type) {
- u8 rsp[5];
-
- if (card_type & 0x04) {
- if (switch_ddr)
- SET_MMC_DDR52(sd_card);
- else
- SET_MMC_52M(sd_card);
- } else if (card_type & 0x02) {
- SET_MMC_52M(sd_card);
- } else {
- SET_MMC_26M(sd_card);
- }
-
- retval = sd_send_cmd_get_rsp(chip, SWITCH, 0x03B90100,
- SD_RSP_TYPE_R1b, rsp, 5);
- if (retval != STATUS_SUCCESS || (rsp[4] & MMC_SWITCH_ERR))
- CLR_MMC_HS(sd_card);
- }
-
- sd_choose_proper_clock(chip);
- retval = switch_clock(chip, sd_card->sd_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- /* Test Bus Procedure */
- retval = mmc_test_switch_bus(chip, MMC_8BIT_BUS);
- if (retval == SWITCH_SUCCESS) {
- SET_MMC_8BIT(sd_card);
- chip->card_bus_width[chip->card2lun[SD_CARD]] = 8;
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
-#endif
- } else if (retval == SWITCH_FAIL) {
- retval = mmc_test_switch_bus(chip, MMC_4BIT_BUS);
- if (retval == SWITCH_SUCCESS) {
- SET_MMC_4BIT(sd_card);
- chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
-#endif
- } else if (retval == SWITCH_FAIL) {
- CLR_MMC_8BIT(sd_card);
- CLR_MMC_4BIT(sd_card);
- } else {
- return STATUS_FAIL;
- }
- } else {
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int reset_mmc(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval, i = 0, j = 0, k = 0;
- bool switch_ddr = true;
- u8 rsp[16];
- u8 spec_ver = 0;
- u32 temp;
-
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
- goto MMC_UNLOCK_ENTRY;
-#endif
-
-switch_fail:
- retval = sd_prepare_reset(chip);
- if (retval != STATUS_SUCCESS)
- return retval;
-
- SET_MMC(sd_card);
-
-RTY_MMC_RST:
- retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- do {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = sd_send_cmd_get_rsp(chip, SEND_OP_COND,
- (SUPPORT_VOLTAGE | 0x40000000),
- SD_RSP_TYPE_R3, rsp, 5);
- if (retval != STATUS_SUCCESS) {
- if (sd_check_err_code(chip, SD_BUSY) ||
- sd_check_err_code(chip, SD_TO_ERR)) {
- k++;
- if (k < 20) {
- sd_clr_err_code(chip);
- goto RTY_MMC_RST;
- } else {
- return STATUS_FAIL;
- }
- } else {
- j++;
- if (j < 100) {
- sd_clr_err_code(chip);
- goto RTY_MMC_RST;
- } else {
- return STATUS_FAIL;
- }
- }
- }
-
- wait_timeout(20);
- i++;
- } while (!(rsp[1] & 0x80) && (i < 255));
-
- if (i == 255)
- return STATUS_FAIL;
-
- if ((rsp[1] & 0x60) == 0x40)
- SET_MMC_SECTOR_MODE(sd_card);
- else
- CLR_MMC_SECTOR_MODE(sd_card);
-
- retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- sd_card->sd_addr = 0x00100000;
- retval = sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr,
- SD_RSP_TYPE_R6, rsp, 5);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sd_check_csd(chip, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2;
-
- retval = sd_select_card(chip, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
-#ifdef SUPPORT_SD_LOCK
-MMC_UNLOCK_ENTRY:
- retval = sd_update_lock_status(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-#endif
-
- retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- chip->card_bus_width[chip->card2lun[SD_CARD]] = 1;
-
- if (!sd_card->mmc_dont_switch_bus) {
- if (spec_ver == 4) {
- /* MMC 4.x Cards */
- retval = mmc_switch_timing_bus(chip, switch_ddr);
- if (retval != STATUS_SUCCESS) {
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- sd_card->mmc_dont_switch_bus = 1;
- goto switch_fail;
- }
- }
-
- if (CHK_MMC_SECTOR_MODE(sd_card) && sd_card->capacity == 0)
- return STATUS_FAIL;
-
- if (switch_ddr && CHK_MMC_DDR52(sd_card)) {
- retval = sd_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = mmc_ddr_tuning(chip);
- if (retval != STATUS_SUCCESS) {
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- switch_ddr = false;
- goto switch_fail;
- }
-
- retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
- if (retval == STATUS_SUCCESS) {
- retval = sd_read_lba0(chip);
- if (retval != STATUS_SUCCESS) {
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- switch_ddr = false;
- goto switch_fail;
- }
- }
- }
- }
-
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
- retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_H, 0xFF,
- 0x02);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_L, 0xFF,
- 0x00);
- if (retval)
- return retval;
- }
-#endif
-
- temp = rtsx_readl(chip, RTSX_BIPR);
- if (temp & SD_WRITE_PROTECT)
- chip->card_wp |= SD_CARD;
-
- return STATUS_SUCCESS;
-}
-
-int reset_sd_card(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- sd_init_reg_addr(chip);
-
- memset(sd_card, 0, sizeof(struct sd_info));
- chip->capacity[chip->card2lun[SD_CARD]] = 0;
-
- retval = enable_card_clock(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (chip->ignore_sd && CHK_SDIO_EXIST(chip) &&
- !CHK_SDIO_IGNORED(chip)) {
- if (chip->asic_code) {
- retval = sd_pull_ctl_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL,
- FPGA_SD_PULL_CTL_BIT |
- 0x20, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
- retval = card_share_mode(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- chip->sd_io = 1;
- return STATUS_FAIL;
- }
-
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (chip->sd_ctl & RESET_MMC_FIRST) {
- retval = reset_mmc(chip);
- if (retval != STATUS_SUCCESS) {
- if (sd_check_err_code(chip, SD_NO_CARD))
- return STATUS_FAIL;
-
- retval = reset_sd(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
- } else {
- retval = reset_sd(chip);
- if (retval != STATUS_SUCCESS) {
- if (sd_check_err_code(chip, SD_NO_CARD))
- return STATUS_FAIL;
-
- if (chip->sd_io)
- return STATUS_FAIL;
- retval = reset_mmc(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
- }
-
- retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
- if (retval)
- return retval;
-
- chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
-
- retval = sd_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "sd_card->sd_type = 0x%x\n", sd_card->sd_type);
-
- return STATUS_SUCCESS;
-}
-
-static int reset_mmc_only(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- sd_card->sd_type = 0;
- sd_card->seq_mode = 0;
- sd_card->sd_data_buf_ready = 0;
- sd_card->capacity = 0;
- sd_card->sd_switch_fail = 0;
-
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status = 0;
- sd_card->sd_erase_status = 0;
-#endif
-
- chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity = 0;
-
- retval = enable_card_clock(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = reset_mmc(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
- if (retval)
- return retval;
-
- chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
-
- retval = sd_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "In %s, sd_card->sd_type = 0x%x\n",
- __func__, sd_card->sd_type);
-
- return STATUS_SUCCESS;
-}
-
-#define WAIT_DATA_READY_RTY_CNT 255
-
-static int wait_data_buf_ready(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int i, retval;
-
- for (i = 0; i < WAIT_DATA_READY_RTY_CNT; i++) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- return STATUS_FAIL;
- }
-
- sd_card->sd_data_buf_ready = 0;
-
- retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
- sd_card->sd_addr, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (sd_card->sd_data_buf_ready) {
- return sd_send_cmd_get_rsp(chip, SEND_STATUS,
- sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
- }
- }
-
- sd_set_err_code(chip, SD_TO_ERR);
-
- return STATUS_FAIL;
-}
-
-void sd_stop_seq_mode(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- if (sd_card->seq_mode) {
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return;
-
- retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
- SD_RSP_TYPE_R1b, NULL, 0);
- if (retval != STATUS_SUCCESS)
- sd_set_err_code(chip, SD_STS_ERR);
-
- retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
- if (retval != STATUS_SUCCESS)
- sd_set_err_code(chip, SD_STS_ERR);
-
- sd_card->seq_mode = 0;
-
- rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
- }
-}
-
-static inline int sd_auto_tune_clock(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- if (chip->asic_code) {
- if (sd_card->sd_clock > 30)
- sd_card->sd_clock -= 20;
- } else {
- switch (sd_card->sd_clock) {
- case CLK_200:
- sd_card->sd_clock = CLK_150;
- break;
-
- case CLK_150:
- sd_card->sd_clock = CLK_120;
- break;
-
- case CLK_120:
- sd_card->sd_clock = CLK_100;
- break;
-
- case CLK_100:
- sd_card->sd_clock = CLK_80;
- break;
-
- case CLK_80:
- sd_card->sd_clock = CLK_60;
- break;
-
- case CLK_60:
- sd_card->sd_clock = CLK_50;
- break;
-
- default:
- break;
- }
- }
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector,
- u16 sector_cnt)
-{
- struct sd_info *sd_card = &chip->sd_card;
- u32 data_addr;
- u8 cfg2;
- int retval;
-
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- dev_dbg(rtsx_dev(chip), "%s: Read %d %s from 0x%x\n", __func__,
- sector_cnt, (sector_cnt > 1) ? "sectors" : "sector",
- start_sector);
- } else {
- dev_dbg(rtsx_dev(chip), "%s: Write %d %s to 0x%x\n", __func__,
- sector_cnt, (sector_cnt > 1) ? "sectors" : "sector",
- start_sector);
- }
-
- sd_card->cleanup_counter = 0;
-
- if (!(chip->card_ready & SD_CARD)) {
- sd_card->seq_mode = 0;
-
- retval = reset_sd_card(chip);
- if (retval == STATUS_SUCCESS) {
- chip->card_ready |= SD_CARD;
- chip->card_fail &= ~SD_CARD;
- } else {
- chip->card_ready &= ~SD_CARD;
- chip->card_fail |= SD_CARD;
- chip->capacity[chip->card2lun[SD_CARD]] = 0;
- chip->rw_need_retry = 1;
- return STATUS_FAIL;
- }
- }
-
- if (!CHK_SD_HCXC(sd_card) && !CHK_MMC_SECTOR_MODE(sd_card))
- data_addr = start_sector << 9;
- else
- data_addr = start_sector;
-
- sd_clr_err_code(chip);
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_IO_ERR);
- goto RW_FAIL;
- }
-
- if (sd_card->seq_mode &&
- (sd_card->pre_dir != srb->sc_data_direction ||
- ((sd_card->pre_sec_addr + sd_card->pre_sec_cnt) !=
- start_sector))) {
- if (sd_card->pre_sec_cnt < 0x80 &&
- sd_card->pre_dir == DMA_FROM_DEVICE &&
- !CHK_SD30_SPEED(sd_card) &&
- !CHK_SD_HS(sd_card) &&
- !CHK_MMC_HS(sd_card)) {
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- }
-
- retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
- SD_RSP_TYPE_R1b, NULL, 0);
- if (retval != STATUS_SUCCESS) {
- chip->rw_need_retry = 1;
- sd_set_err_code(chip, SD_STS_ERR);
- goto RW_FAIL;
- }
-
- sd_card->seq_mode = 0;
-
- retval = rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
- if (retval != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_IO_ERR);
- goto RW_FAIL;
- }
-
- if (sd_card->pre_sec_cnt < 0x80 &&
- !CHK_SD30_SPEED(sd_card) &&
- !CHK_SD_HS(sd_card) &&
- !CHK_MMC_HS(sd_card)) {
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- }
- }
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF,
- (u8)sector_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF,
- (u8)(sector_cnt >> 8));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-
- if (CHK_MMC_8BIT(sd_card))
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1,
- 0x03, SD_BUS_WIDTH_8);
- else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card))
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1,
- 0x03, SD_BUS_WIDTH_4);
- else
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1,
- 0x03, SD_BUS_WIDTH_1);
-
- if (sd_card->seq_mode) {
- cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 |
- SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 |
- SD_RSP_LEN_0;
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2);
-
- trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512,
- DMA_512);
-
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_AUTO_READ_3 | SD_TRANSFER_START);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
- }
-
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END, SD_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
- } else {
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n",
- READ_MULTIPLE_BLOCK);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF,
- 0x40 | READ_MULTIPLE_BLOCK);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF,
- (u8)(data_addr >> 24));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF,
- (u8)(data_addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF,
- (u8)(data_addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF,
- (u8)data_addr);
-
- cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
- SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 |
- SD_RSP_LEN_6;
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
- cfg2);
-
- trans_dma_enable(srb->sc_data_direction, chip,
- sector_cnt * 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END, SD_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
- } else {
- retval = rtsx_send_cmd(chip, SD_CARD, 50);
- if (retval < 0) {
- rtsx_clear_sd_error(chip);
-
- chip->rw_need_retry = 1;
- sd_set_err_code(chip, SD_TO_ERR);
- goto RW_FAIL;
- }
-
- retval = wait_data_buf_ready(chip);
- if (retval != STATUS_SUCCESS) {
- chip->rw_need_retry = 1;
- sd_set_err_code(chip, SD_TO_ERR);
- goto RW_FAIL;
- }
-
- retval = sd_send_cmd_get_rsp(chip, WRITE_MULTIPLE_BLOCK,
- data_addr, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval != STATUS_SUCCESS) {
- chip->rw_need_retry = 1;
- goto RW_FAIL;
- }
-
- rtsx_init_cmd(chip);
-
- cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 |
- SD_NO_WAIT_BUSY_END |
- SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
- cfg2);
-
- trans_dma_enable(srb->sc_data_direction, chip,
- sector_cnt * 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END, SD_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
- }
-
- sd_card->seq_mode = 1;
- }
-
- retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb),
- scsi_bufflen(srb), scsi_sg_count(srb),
- srb->sc_data_direction, chip->sd_timeout);
- if (retval < 0) {
- u8 stat = 0;
- int err;
-
- sd_card->seq_mode = 0;
-
- if (retval == -ETIMEDOUT)
- err = STATUS_TIMEDOUT;
- else
- err = STATUS_FAIL;
-
- rtsx_read_register(chip, REG_SD_STAT1, &stat);
- rtsx_clear_sd_error(chip);
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- chip->rw_need_retry = 0;
- dev_dbg(rtsx_dev(chip), "No card exist, exit %s\n",
- __func__);
- return STATUS_FAIL;
- }
-
- chip->rw_need_retry = 1;
-
- retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
- SD_RSP_TYPE_R1b, NULL, 0);
- if (retval != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_STS_ERR);
- goto RW_FAIL;
- }
-
- if (stat & (SD_CRC7_ERR | SD_CRC16_ERR | SD_CRC_WRITE_ERR)) {
- dev_dbg(rtsx_dev(chip), "SD CRC error, tune clock!\n");
- sd_set_err_code(chip, SD_CRC_ERR);
- goto RW_FAIL;
- }
-
- if (err == STATUS_TIMEDOUT) {
- sd_set_err_code(chip, SD_TO_ERR);
- goto RW_FAIL;
- }
-
- return err;
- }
-
- sd_card->pre_sec_addr = start_sector;
- sd_card->pre_sec_cnt = sector_cnt;
- sd_card->pre_dir = srb->sc_data_direction;
-
- return STATUS_SUCCESS;
-
-RW_FAIL:
- sd_card->seq_mode = 0;
-
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- chip->rw_need_retry = 0;
- dev_dbg(rtsx_dev(chip), "No card exist, exit %s\n", __func__);
- return STATUS_FAIL;
- }
-
- if (sd_check_err_code(chip, SD_CRC_ERR)) {
- if (CHK_MMC_4BIT(sd_card) || CHK_MMC_8BIT(sd_card)) {
- sd_card->mmc_dont_switch_bus = 1;
- reset_mmc_only(chip);
- sd_card->mmc_dont_switch_bus = 0;
- } else {
- sd_card->need_retune = 1;
- sd_auto_tune_clock(chip);
- }
- } else if (sd_check_err_code(chip, SD_TO_ERR | SD_STS_ERR)) {
- retval = reset_sd_card(chip);
- if (retval != STATUS_SUCCESS) {
- chip->card_ready &= ~SD_CARD;
- chip->card_fail |= SD_CARD;
- chip->capacity[chip->card2lun[SD_CARD]] = 0;
- }
- }
-
- return STATUS_FAIL;
-}
-
-#ifdef SUPPORT_CPRM
-int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, u32 arg,
- u8 rsp_type, u8 *rsp, int rsp_len,
- bool special_check)
-{
- int retval;
- int timeout = 100;
- u16 reg_addr;
- u8 *ptr;
- int stat_idx = 0;
- int rty_cnt = 0;
-
- dev_dbg(rtsx_dev(chip), "EXT SD/MMC CMD %d\n", cmd_idx);
-
- if (rsp_type == SD_RSP_TYPE_R1b)
- timeout = 3000;
-
-RTY_SEND_CMD:
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
- 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
- SD_TRANSFER_END);
-
- if (rsp_type == SD_RSP_TYPE_R2) {
- for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
- stat_idx = 17;
- } else if (rsp_type != SD_RSP_TYPE_R0) {
- for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
- stat_idx = 6;
- }
- rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0, 0);
-
- rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0);
-
- retval = rtsx_send_cmd(chip, SD_CARD, timeout);
- if (retval < 0) {
- if (retval == -ETIMEDOUT) {
- rtsx_clear_sd_error(chip);
-
- if (rsp_type & SD_WAIT_BUSY_END) {
- retval = sd_check_data0_status(chip);
- if (retval != STATUS_SUCCESS)
- return retval;
- } else {
- sd_set_err_code(chip, SD_TO_ERR);
- }
- }
- return STATUS_FAIL;
- }
-
- if (rsp_type == SD_RSP_TYPE_R0)
- return STATUS_SUCCESS;
-
- ptr = rtsx_get_cmd_data(chip) + 1;
-
- if ((ptr[0] & 0xC0) != 0) {
- sd_set_err_code(chip, SD_STS_ERR);
- return STATUS_FAIL;
- }
-
- if (!(rsp_type & SD_NO_CHECK_CRC7)) {
- if (ptr[stat_idx] & SD_CRC7_ERR) {
- if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
- sd_set_err_code(chip, SD_CRC_ERR);
- return STATUS_FAIL;
- }
- if (rty_cnt < SD_MAX_RETRY_COUNT) {
- wait_timeout(20);
- rty_cnt++;
- goto RTY_SEND_CMD;
- } else {
- sd_set_err_code(chip, SD_CRC_ERR);
- return STATUS_FAIL;
- }
- }
- }
-
- if (cmd_idx == SELECT_CARD || cmd_idx == APP_CMD ||
- cmd_idx == SEND_STATUS || cmd_idx == STOP_TRANSMISSION) {
- if (cmd_idx != STOP_TRANSMISSION && !special_check) {
- if (ptr[1] & 0x80)
- return STATUS_FAIL;
- }
-#ifdef SUPPORT_SD_LOCK
- if (ptr[1] & 0x7D) {
-#else
- if (ptr[1] & 0x7F) {
-#endif
- return STATUS_FAIL;
- }
- if (ptr[2] & 0xF8)
- return STATUS_FAIL;
-
- if (cmd_idx == SELECT_CARD) {
- if (rsp_type == SD_RSP_TYPE_R2) {
- if ((ptr[3] & 0x1E) != 0x04)
- return STATUS_FAIL;
- }
- }
- }
-
- if (rsp && rsp_len)
- memcpy(rsp, ptr, rsp_len);
-
- return STATUS_SUCCESS;
-}
-
-int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type)
-{
- int retval, rsp_len;
- u16 reg_addr;
-
- if (rsp_type == SD_RSP_TYPE_R0)
- return STATUS_SUCCESS;
-
- rtsx_init_cmd(chip);
-
- if (rsp_type == SD_RSP_TYPE_R2) {
- for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
-
- rsp_len = 17;
- } else if (rsp_type != SD_RSP_TYPE_R0) {
- for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
-
- rsp_len = 6;
- }
- rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0xFF, 0);
-
- retval = rtsx_send_cmd(chip, SD_CARD, 100);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (rsp) {
- int min_len = (rsp_len < len) ? rsp_len : len;
-
- memcpy(rsp, rtsx_get_cmd_data(chip), min_len);
-
- dev_dbg(rtsx_dev(chip), "min_len = %d\n", min_len);
- dev_dbg(rtsx_dev(chip), "Response in cmd buf: 0x%x 0x%x 0x%x 0x%x\n",
- rsp[0], rsp[1], rsp[2], rsp[3]);
- }
-
- return STATUS_SUCCESS;
-}
-
-int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
- int len;
- u8 buf[18] = {
- 0x00,
- 0x00,
- 0x00,
- 0x0E,
- 0x00,
- 0x00,
- 0x00,
- 0x00,
- 0x53,
- 0x44,
- 0x20,
- 0x43,
- 0x61,
- 0x72,
- 0x64,
- 0x00,
- 0x00,
- 0x00,
- };
-
- sd_card->pre_cmd_err = 0;
-
- if (!(CHK_BIT(chip->lun_mc, lun))) {
- SET_BIT(chip->lun_mc, lun);
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- if (srb->cmnd[2] != 0x53 || srb->cmnd[3] != 0x44 ||
- srb->cmnd[4] != 0x20 || srb->cmnd[5] != 0x43 ||
- srb->cmnd[6] != 0x61 || srb->cmnd[7] != 0x72 ||
- srb->cmnd[8] != 0x64) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- switch (srb->cmnd[1] & 0x0F) {
- case 0:
- sd_card->sd_pass_thru_en = 0;
- break;
-
- case 1:
- sd_card->sd_pass_thru_en = 1;
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- buf[5] = (CHK_SD(sd_card) == 1) ? 0x01 : 0x02;
- if (chip->card_wp & SD_CARD)
- buf[5] |= 0x80;
-
- buf[6] = (u8)(sd_card->sd_addr >> 16);
- buf[7] = (u8)(sd_card->sd_addr >> 24);
-
- buf[15] = chip->max_lun;
-
- len = min_t(int, 18, scsi_bufflen(srb));
- rtsx_stor_set_xfer_buf(buf, len, srb);
-
- return TRANSPORT_GOOD;
-}
-
-static inline int get_rsp_type(struct scsi_cmnd *srb, u8 *rsp_type,
- int *rsp_len)
-{
- if (!rsp_type || !rsp_len)
- return STATUS_FAIL;
-
- switch (srb->cmnd[10]) {
- case 0x03:
- *rsp_type = SD_RSP_TYPE_R0;
- *rsp_len = 0;
- break;
-
- case 0x04:
- *rsp_type = SD_RSP_TYPE_R1;
- *rsp_len = 6;
- break;
-
- case 0x05:
- *rsp_type = SD_RSP_TYPE_R1b;
- *rsp_len = 6;
- break;
-
- case 0x06:
- *rsp_type = SD_RSP_TYPE_R2;
- *rsp_len = 17;
- break;
-
- case 0x07:
- *rsp_type = SD_RSP_TYPE_R3;
- *rsp_len = 6;
- break;
-
- default:
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval, rsp_len;
- u8 cmd_idx, rsp_type;
- bool standby = false, acmd = false;
- u32 arg;
-
- if (!sd_card->sd_pass_thru_en) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- if (sd_card->pre_cmd_err) {
- sd_card->pre_cmd_err = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- cmd_idx = srb->cmnd[2] & 0x3F;
- if (srb->cmnd[1] & 0x02)
- standby = true;
-
- if (srb->cmnd[1] & 0x01)
- acmd = true;
-
- arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
- ((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
-
- retval = get_rsp_type(srb, &rsp_type, &rsp_len);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- sd_card->last_rsp_type = rsp_type;
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
-#ifdef SUPPORT_SD_LOCK
- if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
- if (CHK_MMC_8BIT(sd_card)) {
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
- SD_BUS_WIDTH_8);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
- SD_BUS_WIDTH_4);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
- }
- }
-#else
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-#endif
-
- if (standby) {
- retval = sd_select_card(chip, 0);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_cmd_failed;
- }
-
- if (acmd) {
- retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD,
- sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_cmd_failed;
- }
-
- retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
- sd_card->rsp, rsp_len, false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_cmd_failed;
-
- if (standby) {
- retval = sd_select_card(chip, 1);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_cmd_failed;
- }
-
-#ifdef SUPPORT_SD_LOCK
- retval = sd_update_lock_status(chip);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_cmd_failed;
-#endif
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-
-sd_execute_cmd_failed:
- sd_card->pre_cmd_err = 1;
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- release_sd_card(chip);
- do_reset_sd_card(chip);
- if (!(chip->card_ready & SD_CARD))
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-
- return TRANSPORT_FAILED;
-}
-
-int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval, rsp_len, i;
- bool read_err = false, cmd13_checkbit = false;
- u8 cmd_idx, rsp_type, bus_width;
- bool standby = false, send_cmd12 = false, acmd = false;
- u32 data_len;
-
- if (!sd_card->sd_pass_thru_en) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (sd_card->pre_cmd_err) {
- sd_card->pre_cmd_err = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- cmd_idx = srb->cmnd[2] & 0x3F;
- if (srb->cmnd[1] & 0x04)
- send_cmd12 = true;
-
- if (srb->cmnd[1] & 0x02)
- standby = true;
-
- if (srb->cmnd[1] & 0x01)
- acmd = true;
-
- data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8]
- << 8) | srb->cmnd[9];
-
- retval = get_rsp_type(srb, &rsp_type, &rsp_len);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- sd_card->last_rsp_type = rsp_type;
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
-#ifdef SUPPORT_SD_LOCK
- if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
- if (CHK_MMC_8BIT(sd_card))
- bus_width = SD_BUS_WIDTH_8;
- else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card))
- bus_width = SD_BUS_WIDTH_4;
- else
- bus_width = SD_BUS_WIDTH_1;
- } else {
- bus_width = SD_BUS_WIDTH_4;
- }
- dev_dbg(rtsx_dev(chip), "bus_width = %d\n", bus_width);
-#else
- bus_width = SD_BUS_WIDTH_4;
-#endif
-
- if (data_len < 512) {
- retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
- }
-
- if (standby) {
- retval = sd_select_card(chip, 0);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
- }
-
- if (acmd) {
- retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD,
- sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
- }
-
- if (data_len <= 512) {
- int min_len;
- u8 *buf;
- u16 byte_cnt, blk_cnt;
- u8 cmd[5];
-
- byte_cnt = ((u16)(srb->cmnd[8] & 0x03) << 8) | srb->cmnd[9];
- blk_cnt = 1;
-
- cmd[0] = 0x40 | cmd_idx;
- cmd[1] = srb->cmnd[3];
- cmd[2] = srb->cmnd[4];
- cmd[3] = srb->cmnd[5];
- cmd[4] = srb->cmnd[6];
-
- buf = kmalloc(data_len, GFP_KERNEL);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt,
- blk_cnt, bus_width, buf, data_len, 2000);
- if (retval != STATUS_SUCCESS) {
- read_err = true;
- kfree(buf);
- rtsx_clear_sd_error(chip);
- goto sd_execute_read_cmd_failed;
- }
-
- min_len = min(data_len, scsi_bufflen(srb));
- rtsx_stor_set_xfer_buf(buf, min_len, srb);
-
- kfree(buf);
- } else if (!(data_len & 0x1FF)) {
- rtsx_init_cmd(chip);
-
- trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
- 0x02);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
- 0x00);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H,
- 0xFF, (srb->cmnd[7] & 0xFE) >> 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L,
- 0xFF, (u8)((data_len & 0x0001FE00) >> 9));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF,
- 0x40 | cmd_idx);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF,
- srb->cmnd[3]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF,
- srb->cmnd[4]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF,
- srb->cmnd[5]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF,
- srb->cmnd[6]);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
- 0xFF, SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END, SD_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb),
- scsi_bufflen(srb),
- scsi_sg_count(srb),
- DMA_FROM_DEVICE, 10000);
- if (retval < 0) {
- read_err = true;
- rtsx_clear_sd_error(chip);
- goto sd_execute_read_cmd_failed;
- }
-
- } else {
- goto sd_execute_read_cmd_failed;
- }
-
- retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
-
- if (standby) {
- retval = sd_select_card(chip, 1);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
- }
-
- if (send_cmd12) {
- retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
- SD_RSP_TYPE_R1b, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
- }
-
- if (data_len < 512) {
- retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
-
- retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
-
- retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
- }
-
- if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04))
- cmd13_checkbit = true;
-
- for (i = 0; i < 3; i++) {
- retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS,
- sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0,
- cmd13_checkbit);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-
-sd_execute_read_cmd_failed:
- sd_card->pre_cmd_err = 1;
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- if (read_err)
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-
- release_sd_card(chip);
- do_reset_sd_card(chip);
- if (!(chip->card_ready & SD_CARD))
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-
- return TRANSPORT_FAILED;
-}
-
-int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval, rsp_len, i;
- bool write_err = false, cmd13_checkbit = false;
- u8 cmd_idx, rsp_type;
- bool standby = false, send_cmd12 = false, acmd = false;
- u32 data_len, arg;
-#ifdef SUPPORT_SD_LOCK
- int lock_cmd_fail = 0;
- u8 sd_lock_state = 0;
- u8 lock_cmd_type = 0;
-#endif
-
- if (!sd_card->sd_pass_thru_en) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (sd_card->pre_cmd_err) {
- sd_card->pre_cmd_err = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- cmd_idx = srb->cmnd[2] & 0x3F;
- if (srb->cmnd[1] & 0x04)
- send_cmd12 = true;
-
- if (srb->cmnd[1] & 0x02)
- standby = true;
-
- if (srb->cmnd[1] & 0x01)
- acmd = true;
-
- data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8]
- << 8) | srb->cmnd[9];
- arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
- ((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
-
-#ifdef SUPPORT_SD_LOCK
- if (cmd_idx == LOCK_UNLOCK) {
- sd_lock_state = sd_card->sd_lock_status;
- sd_lock_state &= SD_LOCKED;
- }
-#endif
-
- retval = get_rsp_type(srb, &rsp_type, &rsp_len);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- sd_card->last_rsp_type = rsp_type;
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
-#ifdef SUPPORT_SD_LOCK
- if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
- if (CHK_MMC_8BIT(sd_card)) {
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
- SD_BUS_WIDTH_8);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
- SD_BUS_WIDTH_4);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
- }
- }
-#else
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-#endif
-
- if (data_len < 512) {
- retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
- }
-
- if (standby) {
- retval = sd_select_card(chip, 0);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
- }
-
- if (acmd) {
- retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD,
- sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
- }
-
- retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
- sd_card->rsp, rsp_len, false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
-
- if (data_len <= 512) {
- u16 i;
- u8 *buf;
-
- buf = kmalloc(data_len, GFP_KERNEL);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, data_len, srb);
-
-#ifdef SUPPORT_SD_LOCK
- if (cmd_idx == LOCK_UNLOCK)
- lock_cmd_type = buf[0] & 0x0F;
-#endif
-
- if (data_len > 256) {
- rtsx_init_cmd(chip);
- for (i = 0; i < 256; i++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- PPBUF_BASE2 + i, 0xFF, buf[i]);
- }
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- goto sd_execute_write_cmd_failed;
- }
-
- rtsx_init_cmd(chip);
- for (i = 256; i < data_len; i++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- PPBUF_BASE2 + i, 0xFF, buf[i]);
- }
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- goto sd_execute_write_cmd_failed;
- }
- } else {
- rtsx_init_cmd(chip);
- for (i = 0; i < data_len; i++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- PPBUF_BASE2 + i, 0xFF, buf[i]);
- }
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- goto sd_execute_write_cmd_failed;
- }
- }
-
- kfree(buf);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
- srb->cmnd[8] & 0x03);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
- srb->cmnd[9]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF,
- 0x00);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF,
- 0x01);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END, SD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, SD_CARD, 250);
- } else if (!(data_len & 0x1FF)) {
- rtsx_init_cmd(chip);
-
- trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
- 0x02);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
- 0x00);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H,
- 0xFF, (srb->cmnd[7] & 0xFE) >> 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L,
- 0xFF, (u8)((data_len & 0x0001FE00) >> 9));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END, SD_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb),
- scsi_bufflen(srb),
- scsi_sg_count(srb),
- DMA_TO_DEVICE, 10000);
-
- } else {
- goto sd_execute_write_cmd_failed;
- }
-
- if (retval < 0) {
- write_err = true;
- rtsx_clear_sd_error(chip);
- goto sd_execute_write_cmd_failed;
- }
-
-#ifdef SUPPORT_SD_LOCK
- if (cmd_idx == LOCK_UNLOCK) {
- if (lock_cmd_type == SD_ERASE) {
- sd_card->sd_erase_status = SD_UNDER_ERASING;
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
- }
-
- rtsx_init_cmd(chip);
- rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02);
-
- retval = rtsx_send_cmd(chip, SD_CARD, 250);
- if (retval < 0) {
- write_err = true;
- rtsx_clear_sd_error(chip);
- goto sd_execute_write_cmd_failed;
- }
-
- retval = sd_update_lock_status(chip);
- if (retval != STATUS_SUCCESS) {
- dev_dbg(rtsx_dev(chip), "Lock command fail!\n");
- lock_cmd_fail = 1;
- }
- }
-#endif /* SUPPORT_SD_LOCK */
-
- if (standby) {
- retval = sd_select_card(chip, 1);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
- }
-
- if (send_cmd12) {
- retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
- SD_RSP_TYPE_R1b, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
- }
-
- if (data_len < 512) {
- retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
-
- retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
-
- retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
- }
-
- if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04))
- cmd13_checkbit = true;
-
- for (i = 0; i < 3; i++) {
- retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS,
- sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0,
- cmd13_checkbit);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
-
-#ifdef SUPPORT_SD_LOCK
- if (cmd_idx == LOCK_UNLOCK) {
- if (!lock_cmd_fail) {
- dev_dbg(rtsx_dev(chip), "lock_cmd_type = 0x%x\n",
- lock_cmd_type);
- if (lock_cmd_type & SD_CLR_PWD)
- sd_card->sd_lock_status &= ~SD_PWD_EXIST;
-
- if (lock_cmd_type & SD_SET_PWD)
- sd_card->sd_lock_status |= SD_PWD_EXIST;
- }
-
- dev_dbg(rtsx_dev(chip), "sd_lock_state = 0x%x, sd_card->sd_lock_status = 0x%x\n",
- sd_lock_state, sd_card->sd_lock_status);
- if (sd_lock_state ^ (sd_card->sd_lock_status & SD_LOCKED)) {
- sd_card->sd_lock_notify = 1;
- if (sd_lock_state &&
- (sd_card->sd_lock_status & SD_LOCK_1BIT_MODE)) {
- sd_card->sd_lock_status |= (SD_UNLOCK_POW_ON | SD_SDR_RST);
- if (CHK_SD(sd_card)) {
- retval = reset_sd(chip);
- if (retval != STATUS_SUCCESS) {
- sd_card->sd_lock_status &=
- ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
- goto sd_execute_write_cmd_failed;
- }
- }
-
- sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
- }
- }
- }
-
- if (lock_cmd_fail) {
- scsi_set_resid(srb, 0);
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- return TRANSPORT_FAILED;
- }
-#endif /* SUPPORT_SD_LOCK */
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-
-sd_execute_write_cmd_failed:
- sd_card->pre_cmd_err = 1;
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- if (write_err)
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-
- release_sd_card(chip);
- do_reset_sd_card(chip);
- if (!(chip->card_ready & SD_CARD))
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-
- return TRANSPORT_FAILED;
-}
-
-int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
- int count;
- u16 data_len;
-
- if (!sd_card->sd_pass_thru_en) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (sd_card->pre_cmd_err) {
- sd_card->pre_cmd_err = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- data_len = ((u16)srb->cmnd[7] << 8) | srb->cmnd[8];
-
- if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- } else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) {
- count = (data_len < 17) ? data_len : 17;
- } else {
- count = (data_len < 6) ? data_len : 6;
- }
- rtsx_stor_set_xfer_buf(sd_card->rsp, count, srb);
-
- dev_dbg(rtsx_dev(chip), "Response length: %d\n", data_len);
- dev_dbg(rtsx_dev(chip), "Response: 0x%x 0x%x 0x%x 0x%x\n",
- sd_card->rsp[0], sd_card->rsp[1],
- sd_card->rsp[2], sd_card->rsp[3]);
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-}
-
-int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval;
-
- if (!sd_card->sd_pass_thru_en) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (sd_card->pre_cmd_err) {
- sd_card->pre_cmd_err = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- if (srb->cmnd[2] != 0x53 || srb->cmnd[3] != 0x44 ||
- srb->cmnd[4] != 0x20 || srb->cmnd[5] != 0x43 ||
- srb->cmnd[6] != 0x61 || srb->cmnd[7] != 0x72 ||
- srb->cmnd[8] != 0x64) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- switch (srb->cmnd[1] & 0x0F) {
- case 0:
-#ifdef SUPPORT_SD_LOCK
- if (srb->cmnd[9] == 0x64)
- sd_card->sd_lock_status |= SD_SDR_RST;
-#endif
- retval = reset_sd_card(chip);
- if (retval != STATUS_SUCCESS) {
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_SDR_RST;
-#endif
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- sd_card->pre_cmd_err = 1;
- return TRANSPORT_FAILED;
- }
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_SDR_RST;
-#endif
- break;
-
- case 1:
- retval = reset_sd(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- sd_card->pre_cmd_err = 1;
- return TRANSPORT_FAILED;
- }
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-}
-#endif
-
-void sd_cleanup_work(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
-
- if (sd_card->seq_mode) {
- dev_dbg(rtsx_dev(chip), "SD: stop transmission\n");
- sd_stop_seq_mode(chip);
- sd_card->cleanup_counter = 0;
- }
-}
-
-int sd_power_off_card3v3(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = disable_card_clock(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
- if (retval)
- return retval;
-
- if (!chip->ft2_fast_mode) {
- retval = card_power_off(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- mdelay(50);
- }
-
- if (chip->asic_code) {
- retval = sd_pull_ctl_disable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL,
- FPGA_SD_PULL_CTL_BIT | 0x20,
- FPGA_SD_PULL_CTL_BIT);
- if (retval)
- return retval;
- }
-
- return STATUS_SUCCESS;
-}
-
-int release_sd_card(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- chip->card_ready &= ~SD_CARD;
- chip->card_fail &= ~SD_CARD;
- chip->card_wp &= ~SD_CARD;
-
- chip->sd_io = 0;
- chip->sd_int = 0;
-
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status = 0;
- sd_card->sd_erase_status = 0;
-#endif
-
- memset(sd_card->raw_csd, 0, 16);
- memset(sd_card->raw_scr, 0, 8);
-
- retval = sd_power_off_card3v3(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts5208/sd.h b/drivers/staging/rts5208/sd.h
deleted file mode 100644
index f4ff62653b56..000000000000
--- a/drivers/staging/rts5208/sd.h
+++ /dev/null
@@ -1,289 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_SD_H
-#define __REALTEK_RTSX_SD_H
-
-#include "rtsx_chip.h"
-
-#define SUPPORT_VOLTAGE 0x003C0000
-
-/* Error Code */
-#define SD_NO_ERROR 0x0
-#define SD_CRC_ERR 0x80
-#define SD_TO_ERR 0x40
-#define SD_NO_CARD 0x20
-#define SD_BUSY 0x10
-#define SD_STS_ERR 0x08
-#define SD_RSP_TIMEOUT 0x04
-#define SD_IO_ERR 0x02
-
-/* Return code for MMC switch bus */
-#define SWITCH_SUCCESS 0
-#define SWITCH_ERR 1
-#define SWITCH_FAIL 2
-
-/* MMC/SD Command Index */
-/* Basic command (class 0) */
-#define GO_IDLE_STATE 0
-#define SEND_OP_COND 1
-#define ALL_SEND_CID 2
-#define SET_RELATIVE_ADDR 3
-#define SEND_RELATIVE_ADDR 3
-#define SET_DSR 4
-#define IO_SEND_OP_COND 5
-#define SWITCH 6
-#define SELECT_CARD 7
-#define DESELECT_CARD 7
-/* CMD8 is "SEND_EXT_CSD" for MMC4.x Spec
- * while is "SEND_IF_COND" for SD 2.0
- */
-#define SEND_EXT_CSD 8
-#define SEND_IF_COND 8
-
-#define SEND_CSD 9
-#define SEND_CID 10
-#define VOLTAGE_SWITCH 11
-#define READ_DAT_UTIL_STOP 11
-#define STOP_TRANSMISSION 12
-#define SEND_STATUS 13
-#define GO_INACTIVE_STATE 15
-
-#define SET_BLOCKLEN 16
-#define READ_SINGLE_BLOCK 17
-#define READ_MULTIPLE_BLOCK 18
-#define SEND_TUNING_PATTERN 19
-
-#define BUSTEST_R 14
-#define BUSTEST_W 19
-
-#define WRITE_BLOCK 24
-#define WRITE_MULTIPLE_BLOCK 25
-#define PROGRAM_CSD 27
-
-#define ERASE_WR_BLK_START 32
-#define ERASE_WR_BLK_END 33
-#define ERASE_CMD 38
-
-#define LOCK_UNLOCK 42
-#define IO_RW_DIRECT 52
-
-#define APP_CMD 55
-#define GEN_CMD 56
-
-#define SET_BUS_WIDTH 6
-#define SD_STATUS 13
-#define SEND_NUM_WR_BLOCKS 22
-#define SET_WR_BLK_ERASE_COUNT 23
-#define SD_APP_OP_COND 41
-#define SET_CLR_CARD_DETECT 42
-#define SEND_SCR 51
-
-#define SD_READ_COMPLETE 0x00
-#define SD_READ_TO 0x01
-#define SD_READ_ADVENCE 0x02
-
-#define SD_CHECK_MODE 0x00
-#define SD_SWITCH_MODE 0x80
-#define SD_FUNC_GROUP_1 0x01
-#define SD_FUNC_GROUP_2 0x02
-#define SD_FUNC_GROUP_3 0x03
-#define SD_FUNC_GROUP_4 0x04
-#define SD_CHECK_SPEC_V1_1 0xFF
-
-#define NO_ARGUMENT 0x00
-#define CHECK_PATTERN 0x000000AA
-#define VOLTAGE_SUPPLY_RANGE 0x00000100
-#define SUPPORT_HIGH_AND_EXTENDED_CAPACITY 0x40000000
-#define SUPPORT_MAX_POWER_PERMANCE 0x10000000
-#define SUPPORT_1V8 0x01000000
-
-#define SWITCH_NO_ERR 0x00
-#define CARD_NOT_EXIST 0x01
-#define SPEC_NOT_SUPPORT 0x02
-#define CHECK_MODE_ERR 0x03
-#define CHECK_NOT_READY 0x04
-#define SWITCH_CRC_ERR 0x05
-#define SWITCH_MODE_ERR 0x06
-#define SWITCH_PASS 0x07
-
-#ifdef SUPPORT_SD_LOCK
-#define SD_ERASE 0x08
-#define SD_LOCK 0x04
-#define SD_UNLOCK 0x00
-#define SD_CLR_PWD 0x02
-#define SD_SET_PWD 0x01
-
-#define SD_PWD_LEN 0x10
-
-#define SD_LOCKED 0x80
-#define SD_LOCK_1BIT_MODE 0x40
-#define SD_PWD_EXIST 0x20
-#define SD_UNLOCK_POW_ON 0x01
-#define SD_SDR_RST 0x02
-
-#define SD_NOT_ERASE 0x00
-#define SD_UNDER_ERASING 0x01
-#define SD_COMPLETE_ERASE 0x02
-
-#define SD_RW_FORBIDDEN 0x0F
-
-#endif
-
-#define HS_SUPPORT 0x01
-#define SDR50_SUPPORT 0x02
-#define SDR104_SUPPORT 0x03
-#define DDR50_SUPPORT 0x04
-
-#define HS_SUPPORT_MASK 0x02
-#define SDR50_SUPPORT_MASK 0x04
-#define SDR104_SUPPORT_MASK 0x08
-#define DDR50_SUPPORT_MASK 0x10
-
-#define HS_QUERY_SWITCH_OK 0x01
-#define SDR50_QUERY_SWITCH_OK 0x02
-#define SDR104_QUERY_SWITCH_OK 0x03
-#define DDR50_QUERY_SWITCH_OK 0x04
-
-#define HS_SWITCH_BUSY 0x02
-#define SDR50_SWITCH_BUSY 0x04
-#define SDR104_SWITCH_BUSY 0x08
-#define DDR50_SWITCH_BUSY 0x10
-
-#define FUNCTION_GROUP1_SUPPORT_OFFSET 0x0D
-#define FUNCTION_GROUP1_QUERY_SWITCH_OFFSET 0x10
-#define FUNCTION_GROUP1_CHECK_BUSY_OFFSET 0x1D
-
-#define DRIVING_TYPE_A 0x01
-#define DRIVING_TYPE_B 0x00
-#define DRIVING_TYPE_C 0x02
-#define DRIVING_TYPE_D 0x03
-
-#define DRIVING_TYPE_A_MASK 0x02
-#define DRIVING_TYPE_B_MASK 0x01
-#define DRIVING_TYPE_C_MASK 0x04
-#define DRIVING_TYPE_D_MASK 0x08
-
-#define TYPE_A_QUERY_SWITCH_OK 0x01
-#define TYPE_B_QUERY_SWITCH_OK 0x00
-#define TYPE_C_QUERY_SWITCH_OK 0x02
-#define TYPE_D_QUERY_SWITCH_OK 0x03
-
-#define TYPE_A_SWITCH_BUSY 0x02
-#define TYPE_B_SWITCH_BUSY 0x01
-#define TYPE_C_SWITCH_BUSY 0x04
-#define TYPE_D_SWITCH_BUSY 0x08
-
-#define FUNCTION_GROUP3_SUPPORT_OFFSET 0x09
-#define FUNCTION_GROUP3_QUERY_SWITCH_OFFSET 0x0F
-#define FUNCTION_GROUP3_CHECK_BUSY_OFFSET 0x19
-
-#define CURRENT_LIMIT_200 0x00
-#define CURRENT_LIMIT_400 0x01
-#define CURRENT_LIMIT_600 0x02
-#define CURRENT_LIMIT_800 0x03
-
-#define CURRENT_LIMIT_200_MASK 0x01
-#define CURRENT_LIMIT_400_MASK 0x02
-#define CURRENT_LIMIT_600_MASK 0x04
-#define CURRENT_LIMIT_800_MASK 0x08
-
-#define CURRENT_LIMIT_200_QUERY_SWITCH_OK 0x00
-#define CURRENT_LIMIT_400_QUERY_SWITCH_OK 0x01
-#define CURRENT_LIMIT_600_QUERY_SWITCH_OK 0x02
-#define CURRENT_LIMIT_800_QUERY_SWITCH_OK 0x03
-
-#define CURRENT_LIMIT_200_SWITCH_BUSY 0x01
-#define CURRENT_LIMIT_400_SWITCH_BUSY 0x02
-#define CURRENT_LIMIT_600_SWITCH_BUSY 0x04
-#define CURRENT_LIMIT_800_SWITCH_BUSY 0x08
-
-#define FUNCTION_GROUP4_SUPPORT_OFFSET 0x07
-#define FUNCTION_GROUP4_QUERY_SWITCH_OFFSET 0x0F
-#define FUNCTION_GROUP4_CHECK_BUSY_OFFSET 0x17
-
-#define DATA_STRUCTURE_VER_OFFSET 0x11
-
-#define MAX_PHASE 31
-
-#define MMC_8BIT_BUS 0x0010
-#define MMC_4BIT_BUS 0x0020
-
-#define MMC_SWITCH_ERR 0x80
-
-#define SD_IO_3V3 0
-#define SD_IO_1V8 1
-
-#define TUNE_TX 0x00
-#define TUNE_RX 0x01
-
-#define CHANGE_TX 0x00
-#define CHANGE_RX 0x01
-
-#define DCM_HIGH_FREQUENCY_MODE 0x00
-#define DCM_LOW_FREQUENCY_MODE 0x01
-
-#define DCM_HIGH_FREQUENCY_MODE_SET 0x0C
-#define DCM_LOW_FREQUENCY_MODE_SET 0x00
-
-#define MULTIPLY_BY_1 0x00
-#define MULTIPLY_BY_2 0x01
-#define MULTIPLY_BY_3 0x02
-#define MULTIPLY_BY_4 0x03
-#define MULTIPLY_BY_5 0x04
-#define MULTIPLY_BY_6 0x05
-#define MULTIPLY_BY_7 0x06
-#define MULTIPLY_BY_8 0x07
-#define MULTIPLY_BY_9 0x08
-#define MULTIPLY_BY_10 0x09
-
-#define DIVIDE_BY_2 0x01
-#define DIVIDE_BY_3 0x02
-#define DIVIDE_BY_4 0x03
-#define DIVIDE_BY_5 0x04
-#define DIVIDE_BY_6 0x05
-#define DIVIDE_BY_7 0x06
-#define DIVIDE_BY_8 0x07
-#define DIVIDE_BY_9 0x08
-#define DIVIDE_BY_10 0x09
-
-struct timing_phase_path {
- int start;
- int end;
- int mid;
- int len;
-};
-
-int sd_select_card(struct rtsx_chip *chip, int select);
-int sd_pull_ctl_enable(struct rtsx_chip *chip);
-int reset_sd_card(struct rtsx_chip *chip);
-int sd_switch_clock(struct rtsx_chip *chip);
-void sd_stop_seq_mode(struct rtsx_chip *chip);
-int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 start_sector, u16 sector_cnt);
-void sd_cleanup_work(struct rtsx_chip *chip);
-int sd_power_off_card3v3(struct rtsx_chip *chip);
-int release_sd_card(struct rtsx_chip *chip);
-#ifdef SUPPORT_CPRM
-int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
- u32 arg, u8 rsp_type, u8 *rsp, int rsp_len,
- bool special_check);
-int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type);
-
-int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-#endif
-
-#endif /* __REALTEK_RTSX_SD_H */
diff --git a/drivers/staging/rts5208/spi.c b/drivers/staging/rts5208/spi.c
deleted file mode 100644
index e88fe1a998f8..000000000000
--- a/drivers/staging/rts5208/spi.c
+++ /dev/null
@@ -1,906 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-
-#include "rtsx.h"
-#include "spi.h"
-
-static inline void spi_set_err_code(struct rtsx_chip *chip, u8 err_code)
-{
- struct spi_info *spi = &chip->spi;
-
- spi->err_code = err_code;
-}
-
-static int spi_init(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = rtsx_write_register(chip, SPI_CONTROL, 0xFF,
- CS_POLARITY_LOW | DTO_MSB_FIRST
- | SPI_MASTER | SPI_MODE0 | SPI_AUTO);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SPI_TCTL, EDO_TIMING_MASK,
- SAMPLE_DELAY_HALF);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int spi_set_init_para(struct rtsx_chip *chip)
-{
- struct spi_info *spi = &chip->spi;
- int retval;
-
- retval = rtsx_write_register(chip, SPI_CLK_DIVIDER1, 0xFF,
- (u8)(spi->clk_div >> 8));
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SPI_CLK_DIVIDER0, 0xFF,
- (u8)(spi->clk_div));
- if (retval)
- return retval;
-
- retval = switch_clock(chip, spi->spi_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = select_card(chip, SPI_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_CLK_EN, SPI_CLK_EN,
- SPI_CLK_EN);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_OE, SPI_OUTPUT_EN,
- SPI_OUTPUT_EN);
- if (retval)
- return retval;
-
- wait_timeout(10);
-
- retval = spi_init(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sf_polling_status(struct rtsx_chip *chip, int msec)
-{
- int retval;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, SPI_RDSR);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_POLLING_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, msec);
- if (retval < 0) {
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_BUSY_ERR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sf_enable_write(struct rtsx_chip *chip, u8 ins)
-{
- struct spi_info *spi = &chip->spi;
- int retval;
-
- if (!spi->write_en)
- return STATUS_SUCCESS;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_C_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0) {
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sf_disable_write(struct rtsx_chip *chip, u8 ins)
-{
- struct spi_info *spi = &chip->spi;
- int retval;
-
- if (!spi->write_en)
- return STATUS_SUCCESS;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_C_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0) {
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static void sf_program(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr,
- u16 len)
-{
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, (u8)len);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, (u8)(len >> 8));
- if (addr_mode) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF,
- (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF,
- (u8)(addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CADO_MODE0);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CDO_MODE0);
- }
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-}
-
-static int sf_erase(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr)
-{
- int retval;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- if (addr_mode) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF,
- (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF,
- (u8)(addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CA_MODE0);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_C_MODE0);
- }
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0) {
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int spi_init_eeprom(struct rtsx_chip *chip)
-{
- int retval;
- int clk;
-
- if (chip->asic_code)
- clk = 30;
- else
- clk = CLK_30;
-
- retval = rtsx_write_register(chip, SPI_CLK_DIVIDER1, 0xFF, 0x00);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SPI_CLK_DIVIDER0, 0xFF, 0x27);
- if (retval)
- return retval;
-
- retval = switch_clock(chip, clk);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = select_card(chip, SPI_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_CLK_EN, SPI_CLK_EN,
- SPI_CLK_EN);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_OE, SPI_OUTPUT_EN,
- SPI_OUTPUT_EN);
- if (retval)
- return retval;
-
- wait_timeout(10);
-
- retval = rtsx_write_register(chip, SPI_CONTROL, 0xFF,
- CS_POLARITY_HIGH | SPI_EEPROM_AUTO);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SPI_TCTL, EDO_TIMING_MASK,
- SAMPLE_DELAY_HALF);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int spi_eeprom_program_enable(struct rtsx_chip *chip)
-{
- int retval;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x86);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x13);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CA_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int spi_erase_eeprom_chip(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = spi_init_eeprom(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = spi_eeprom_program_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x12);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x84);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CA_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr)
-{
- int retval;
-
- retval = spi_init_eeprom(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = spi_eeprom_program_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x07);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CA_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val)
-{
- int retval;
- u8 data;
-
- retval = spi_init_eeprom(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x06);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CADI_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- wait_timeout(5);
- retval = rtsx_read_register(chip, SPI_DATA, &data);
- if (retval)
- return retval;
-
- if (val)
- *val = data;
-
- retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val)
-{
- int retval;
-
- retval = spi_init_eeprom(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = spi_eeprom_program_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x05);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, val);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x4E);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CA_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct spi_info *spi = &chip->spi;
-
- dev_dbg(rtsx_dev(chip), "%s: err_code = 0x%x\n", __func__,
- spi->err_code);
- rtsx_stor_set_xfer_buf(&spi->err_code,
- min_t(int, scsi_bufflen(srb), 1), srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - 1);
-
- return STATUS_SUCCESS;
-}
-
-int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct spi_info *spi = &chip->spi;
-
- spi_set_err_code(chip, SPI_NO_ERR);
-
- if (chip->asic_code)
- spi->spi_clock = ((u16)(srb->cmnd[8]) << 8) | srb->cmnd[9];
- else
- spi->spi_clock = srb->cmnd[3];
-
- spi->clk_div = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
- spi->write_en = srb->cmnd[6];
-
- dev_dbg(rtsx_dev(chip), "spi_clock = %d, clk_div = %d, write_en = %d\n",
- spi->spi_clock, spi->clk_div, spi->write_en);
-
- return STATUS_SUCCESS;
-}
-
-int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- u16 len;
- u8 *buf;
-
- spi_set_err_code(chip, SPI_NO_ERR);
-
- len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
- if (len > 512) {
- spi_set_err_code(chip, SPI_INVALID_COMMAND);
- return STATUS_FAIL;
- }
-
- retval = spi_set_init_para(chip);
- if (retval != STATUS_SUCCESS) {
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, srb->cmnd[3]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, srb->cmnd[4]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, srb->cmnd[5]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, srb->cmnd[6]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, srb->cmnd[7]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, srb->cmnd[8]);
-
- if (len == 0) {
- if (srb->cmnd[9]) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
- 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
- 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
- }
- } else {
- if (srb->cmnd[9]) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CADI_MODE0);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CDI_MODE0);
- }
- }
-
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0) {
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- if (len) {
- buf = kmalloc(len, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- retval = rtsx_read_ppbuf(chip, buf, len);
- if (retval != STATUS_SUCCESS) {
- spi_set_err_code(chip, SPI_READ_ERR);
- kfree(buf);
- return STATUS_FAIL;
- }
-
- rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
- scsi_set_resid(srb, 0);
-
- kfree(buf);
- }
-
- return STATUS_SUCCESS;
-}
-
-int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- unsigned int index = 0, offset = 0;
- u8 ins, slow_read;
- u32 addr;
- u16 len;
- u8 *buf;
-
- spi_set_err_code(chip, SPI_NO_ERR);
-
- ins = srb->cmnd[3];
- addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5])
- << 8) | srb->cmnd[6];
- len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
- slow_read = srb->cmnd[9];
-
- retval = spi_set_init_para(chip);
- if (retval != STATUS_SUCCESS) {
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- while (len) {
- u16 pagelen = SF_PAGE_LEN - (u8)addr;
-
- if (pagelen > len)
- pagelen = len;
-
- rtsx_init_cmd(chip);
-
- trans_dma_enable(DMA_FROM_DEVICE, chip, 256, DMA_256);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
-
- if (slow_read) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF,
- (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF,
- (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF,
- (u8)(addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF,
- (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF,
- (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR3, 0xFF,
- (u8)(addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_32);
- }
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF,
- (u8)(pagelen >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF,
- (u8)pagelen);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CADI_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0,
- SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0,
- DMA_FROM_DEVICE, 10000);
- if (retval < 0) {
- kfree(buf);
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset,
- TO_XFER_BUF);
-
- addr += pagelen;
- len -= pagelen;
- }
-
- scsi_set_resid(srb, 0);
- kfree(buf);
-
- return STATUS_SUCCESS;
-}
-
-int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- u8 ins, program_mode;
- u32 addr;
- u16 len;
- u8 *buf;
- unsigned int index = 0, offset = 0;
-
- spi_set_err_code(chip, SPI_NO_ERR);
-
- ins = srb->cmnd[3];
- addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5])
- << 8) | srb->cmnd[6];
- len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
- program_mode = srb->cmnd[9];
-
- retval = spi_set_init_para(chip);
- if (retval != STATUS_SUCCESS) {
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- if (program_mode == BYTE_PROGRAM) {
- buf = kmalloc(4, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- while (len) {
- retval = sf_enable_write(chip, SPI_WREN);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset,
- FROM_XFER_BUF);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF,
- buf[0]);
- sf_program(chip, ins, 1, addr, 1);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0) {
- kfree(buf);
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- retval = sf_polling_status(chip, 100);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- addr++;
- len--;
- }
-
- kfree(buf);
-
- } else if (program_mode == AAI_PROGRAM) {
- int first_byte = 1;
-
- retval = sf_enable_write(chip, SPI_WREN);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf = kmalloc(4, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- while (len) {
- rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset,
- FROM_XFER_BUF);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF,
- buf[0]);
- if (first_byte) {
- sf_program(chip, ins, 1, addr, 1);
- first_byte = 0;
- } else {
- sf_program(chip, ins, 0, 0, 1);
- }
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0) {
- kfree(buf);
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- retval = sf_polling_status(chip, 100);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- len--;
- }
-
- kfree(buf);
-
- retval = sf_disable_write(chip, SPI_WRDI);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sf_polling_status(chip, 100);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else if (program_mode == PAGE_PROGRAM) {
- buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL);
- if (!buf)
- return STATUS_NOMEM;
-
- while (len) {
- u16 pagelen = SF_PAGE_LEN - (u8)addr;
-
- if (pagelen > len)
- pagelen = len;
-
- retval = sf_enable_write(chip, SPI_WREN);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- rtsx_init_cmd(chip);
-
- trans_dma_enable(DMA_TO_DEVICE, chip, 256, DMA_256);
- sf_program(chip, ins, 1, addr, pagelen);
-
- rtsx_send_cmd_no_wait(chip);
-
- rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index,
- &offset, FROM_XFER_BUF);
-
- retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0,
- DMA_TO_DEVICE, 100);
- if (retval < 0) {
- kfree(buf);
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- retval = sf_polling_status(chip, 100);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- addr += pagelen;
- len -= pagelen;
- }
-
- kfree(buf);
- } else {
- spi_set_err_code(chip, SPI_INVALID_COMMAND);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- u8 ins, erase_mode;
- u32 addr;
-
- spi_set_err_code(chip, SPI_NO_ERR);
-
- ins = srb->cmnd[3];
- addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5])
- << 8) | srb->cmnd[6];
- erase_mode = srb->cmnd[9];
-
- retval = spi_set_init_para(chip);
- if (retval != STATUS_SUCCESS) {
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- if (erase_mode == PAGE_ERASE) {
- retval = sf_enable_write(chip, SPI_WREN);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sf_erase(chip, ins, 1, addr);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else if (erase_mode == CHIP_ERASE) {
- retval = sf_enable_write(chip, SPI_WREN);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sf_erase(chip, ins, 0, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- spi_set_err_code(chip, SPI_INVALID_COMMAND);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- u8 ins, status, ewsr;
-
- ins = srb->cmnd[3];
- status = srb->cmnd[4];
- ewsr = srb->cmnd[5];
-
- retval = spi_set_init_para(chip);
- if (retval != STATUS_SUCCESS) {
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- retval = sf_enable_write(chip, ewsr);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, status);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CDO_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts5208/spi.h b/drivers/staging/rts5208/spi.h
deleted file mode 100644
index dcf93c80b2d5..000000000000
--- a/drivers/staging/rts5208/spi.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_SPI_H
-#define __REALTEK_RTSX_SPI_H
-
-/* SPI operation error */
-#define SPI_NO_ERR 0x00
-#define SPI_HW_ERR 0x01
-#define SPI_INVALID_COMMAND 0x02
-#define SPI_READ_ERR 0x03
-#define SPI_WRITE_ERR 0x04
-#define SPI_ERASE_ERR 0x05
-#define SPI_BUSY_ERR 0x06
-
-/* Serial flash instruction */
-#define SPI_READ 0x03
-#define SPI_FAST_READ 0x0B
-#define SPI_WREN 0x06
-#define SPI_WRDI 0x04
-#define SPI_RDSR 0x05
-
-#define SF_PAGE_LEN 256
-
-#define BYTE_PROGRAM 0
-#define AAI_PROGRAM 1
-#define PAGE_PROGRAM 2
-
-#define PAGE_ERASE 0
-#define CHIP_ERASE 1
-
-int spi_erase_eeprom_chip(struct rtsx_chip *chip);
-int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr);
-int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val);
-int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val);
-int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-
-#endif /* __REALTEK_RTSX_SPI_H */
diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c
deleted file mode 100644
index c0af378ada71..000000000000
--- a/drivers/staging/rts5208/xd.c
+++ /dev/null
@@ -1,2145 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-
-#include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-#include "xd.h"
-
-static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no);
-static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, u16 logoff,
- u8 start_page, u8 end_page);
-
-static inline void xd_set_err_code(struct rtsx_chip *chip, u8 err_code)
-{
- struct xd_info *xd_card = &chip->xd_card;
-
- xd_card->err_code = err_code;
-}
-
-static int xd_set_init_para(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval;
-
- if (chip->asic_code)
- xd_card->xd_clock = 47;
- else
- xd_card->xd_clock = CLK_50;
-
- retval = switch_clock(chip, xd_card->xd_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int xd_switch_clock(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval;
-
- retval = select_card(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = switch_clock(chip, xd_card->xd_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int xd_read_id(struct rtsx_chip *chip, u8 id_cmd, u8 *id_buf, u8 buf_len)
-{
- int retval, i;
- u8 *ptr;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, id_cmd);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_READ_ID);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
- XD_TRANSFER_END);
-
- for (i = 0; i < 4; i++)
- rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_ADDRESS1 + i), 0, 0);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 20);
- if (retval < 0)
- return STATUS_FAIL;
-
- ptr = rtsx_get_cmd_data(chip) + 1;
- if (id_buf && buf_len) {
- if (buf_len > 4)
- buf_len = 4;
- memcpy(id_buf, ptr, buf_len);
- }
-
- return STATUS_SUCCESS;
-}
-
-static void xd_assign_phy_addr(struct rtsx_chip *chip, u32 addr, u8 mode)
-{
- struct xd_info *xd_card = &chip->xd_card;
-
- switch (mode) {
- case XD_RW_ADDR:
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2,
- 0xFF, (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS3,
- 0xFF, (u8)(addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF,
- xd_card->addr_cycle |
- XD_CALC_ECC |
- XD_BA_NO_TRANSFORM);
- break;
-
- case XD_ERASE_ADDR:
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1,
- 0xFF, (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2,
- 0xFF, (u8)(addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF,
- (xd_card->addr_cycle - 1) | XD_CALC_ECC |
- XD_BA_NO_TRANSFORM);
- break;
-
- default:
- break;
- }
-}
-
-static int xd_read_redundant(struct rtsx_chip *chip, u32 page_addr,
- u8 *buf, int buf_len)
-{
- int retval, i;
-
- rtsx_init_cmd(chip);
-
- xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER,
- 0xFF, XD_TRANSFER_START | XD_READ_REDUNDANT);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- for (i = 0; i < 6; i++)
- rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_PAGE_STATUS + i),
- 0, 0);
- for (i = 0; i < 4; i++)
- rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_RESERVED0 + i),
- 0, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, XD_PARITY, 0, 0);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 500);
- if (retval < 0)
- return STATUS_FAIL;
-
- if (buf && buf_len) {
- u8 *ptr = rtsx_get_cmd_data(chip) + 1;
-
- if (buf_len > 11)
- buf_len = 11;
- memcpy(buf, ptr, buf_len);
- }
-
- return STATUS_SUCCESS;
-}
-
-static int xd_read_data_from_ppb(struct rtsx_chip *chip, int offset,
- u8 *buf, int buf_len)
-{
- int retval, i;
-
- if (!buf || buf_len < 0)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- for (i = 0; i < buf_len; i++)
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + offset + i,
- 0, 0);
-
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
- return STATUS_FAIL;
- }
-
- memcpy(buf, rtsx_get_cmd_data(chip), buf_len);
-
- return STATUS_SUCCESS;
-}
-
-static int xd_read_cis(struct rtsx_chip *chip, u32 page_addr, u8 *buf,
- int buf_len)
-{
- int retval;
- u8 reg;
-
- if (!buf || buf_len < 10)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
- XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_READ_PAGES);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
- XD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 250);
- if (retval == -ETIMEDOUT) {
- rtsx_clear_xd_error(chip);
- return STATUS_FAIL;
- }
-
- retval = rtsx_read_register(chip, XD_PAGE_STATUS, &reg);
- if (retval)
- return retval;
- if (reg != XD_GPG) {
- rtsx_clear_xd_error(chip);
- return STATUS_FAIL;
- }
-
- retval = rtsx_read_register(chip, XD_CTL, &reg);
- if (retval)
- return retval;
- if (!(reg & XD_ECC1_ERROR) || !(reg & XD_ECC1_UNCORRECTABLE)) {
- retval = xd_read_data_from_ppb(chip, 0, buf, buf_len);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- if (reg & XD_ECC1_ERROR) {
- u8 ecc_bit, ecc_byte;
-
- retval = rtsx_read_register(chip, XD_ECC_BIT1,
- &ecc_bit);
- if (retval)
- return retval;
- retval = rtsx_read_register(chip, XD_ECC_BYTE1,
- &ecc_byte);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "ECC_BIT1 = 0x%x, ECC_BYTE1 = 0x%x\n",
- ecc_bit, ecc_byte);
- if (ecc_byte < buf_len) {
- dev_dbg(rtsx_dev(chip), "Before correct: 0x%x\n",
- buf[ecc_byte]);
- buf[ecc_byte] ^= (1 << ecc_bit);
- dev_dbg(rtsx_dev(chip), "After correct: 0x%x\n",
- buf[ecc_byte]);
- }
- }
- } else if (!(reg & XD_ECC2_ERROR) || !(reg & XD_ECC2_UNCORRECTABLE)) {
- rtsx_clear_xd_error(chip);
-
- retval = xd_read_data_from_ppb(chip, 256, buf, buf_len);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- if (reg & XD_ECC2_ERROR) {
- u8 ecc_bit, ecc_byte;
-
- retval = rtsx_read_register(chip, XD_ECC_BIT2,
- &ecc_bit);
- if (retval)
- return retval;
- retval = rtsx_read_register(chip, XD_ECC_BYTE2,
- &ecc_byte);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "ECC_BIT2 = 0x%x, ECC_BYTE2 = 0x%x\n",
- ecc_bit, ecc_byte);
- if (ecc_byte < buf_len) {
- dev_dbg(rtsx_dev(chip), "Before correct: 0x%x\n",
- buf[ecc_byte]);
- buf[ecc_byte] ^= (1 << ecc_bit);
- dev_dbg(rtsx_dev(chip), "After correct: 0x%x\n",
- buf[ecc_byte]);
- }
- }
- } else {
- rtsx_clear_xd_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static void xd_fill_pull_ctl_disable(struct rtsx_chip *chip)
-{
- if (CHECK_PID(chip, 0x5208)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
- XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
- XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
- XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1,
- 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2,
- 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3,
- 0xFF, 0x4B);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4,
- 0xFF, 0x69);
- }
- }
-}
-
-static void xd_fill_pull_ctl_stage1_barossa(struct rtsx_chip *chip)
-{
- if (CHECK_BARO_PKG(chip, QFN)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x4B);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
- }
-}
-
-static void xd_fill_pull_ctl_enable(struct rtsx_chip *chip)
-{
- if (CHECK_PID(chip, 0x5208)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
- XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
- XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
- XD_WP_PD | XD_CE_PU | XD_CLE_PD | XD_CD_PU);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PU | XD_WE_PU | XD_RE_PU | XD_ALE_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1,
- 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2,
- 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3,
- 0xFF, 0x53);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4,
- 0xFF, 0xA9);
- }
- }
-}
-
-static int xd_pull_ctl_disable(struct rtsx_chip *chip)
-{
- int retval;
-
- if (CHECK_PID(chip, 0x5208)) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF,
- XD_D3_PD |
- XD_D2_PD |
- XD_D1_PD |
- XD_D0_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF,
- XD_D7_PD |
- XD_D6_PD |
- XD_D5_PD |
- XD_D4_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF,
- XD_WP_PD |
- XD_CE_PD |
- XD_CLE_PD |
- XD_CD_PU);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PD |
- XD_WE_PD |
- XD_RE_PD |
- XD_ALE_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU |
- SD_WP_PD |
- SD_CD_PU |
- SD_CMD_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- if (retval)
- return retval;
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL1,
- 0xFF, 0x55);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL2,
- 0xFF, 0x55);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL3,
- 0xFF, 0x4B);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL4,
- 0xFF, 0x69);
- if (retval)
- return retval;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static int reset_xd(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval, i, j;
- u8 *ptr, id_buf[4], redunt[11];
-
- retval = select_card(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 0xFF,
- XD_PGSTS_NOT_FF);
- if (chip->asic_code) {
- if (!CHECK_PID(chip, 0x5288))
- xd_fill_pull_ctl_disable(chip);
- else
- xd_fill_pull_ctl_stage1_barossa(chip);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
- (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN3) |
- 0x20);
- }
-
- if (!chip->ft2_fast_mode)
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_INIT,
- XD_NO_AUTO_PWR_OFF, 0);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- if (!chip->ft2_fast_mode) {
- retval = card_power_off(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- wait_timeout(250);
-
- rtsx_init_cmd(chip);
-
- if (chip->asic_code) {
- xd_fill_pull_ctl_enable(chip);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
- (FPGA_XD_PULL_CTL_EN1 &
- FPGA_XD_PULL_CTL_EN2) |
- 0x20);
- }
-
- retval = rtsx_send_cmd(chip, XD_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- retval = card_power_on(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
-#ifdef SUPPORT_OCP
- wait_timeout(50);
- if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
- dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
- chip->ocp_stat);
- return STATUS_FAIL;
- }
-#endif
- }
-
- rtsx_init_cmd(chip);
-
- if (chip->ft2_fast_mode) {
- if (chip->asic_code) {
- xd_fill_pull_ctl_enable(chip);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
- (FPGA_XD_PULL_CTL_EN1 &
- FPGA_XD_PULL_CTL_EN2) |
- 0x20);
- }
- }
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, XD_OUTPUT_EN);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CTL, XD_CE_DISEN, XD_CE_DISEN);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- if (!chip->ft2_fast_mode)
- wait_timeout(200);
-
- retval = xd_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- /* Read ID to check if the timing setting is right */
- for (i = 0; i < 4; i++) {
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DTCTL, 0xFF,
- XD_TIME_SETUP_STEP * 3 +
- XD_TIME_RW_STEP * (2 + i) + XD_TIME_RWN_STEP * i);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CATCTL, 0xFF,
- XD_TIME_SETUP_STEP * 3 +
- XD_TIME_RW_STEP * (4 + i) +
- XD_TIME_RWN_STEP * (3 + i));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_RESET);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- ptr = rtsx_get_cmd_data(chip) + 1;
-
- dev_dbg(rtsx_dev(chip), "XD_DAT: 0x%x, XD_CTL: 0x%x\n",
- ptr[0], ptr[1]);
-
- if (((ptr[0] & READY_FLAG) != READY_STATE) ||
- !(ptr[1] & XD_RDY))
- continue;
-
- retval = xd_read_id(chip, READ_ID, id_buf, 4);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "READ_ID: 0x%x 0x%x 0x%x 0x%x\n",
- id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
-
- xd_card->device_code = id_buf[1];
-
- /* Check if the xD card is supported */
- switch (xd_card->device_code) {
- case XD_4M_X8_512_1:
- case XD_4M_X8_512_2:
- xd_card->block_shift = 4;
- xd_card->page_off = 0x0F;
- xd_card->addr_cycle = 3;
- xd_card->zone_cnt = 1;
- xd_card->capacity = 8000;
- XD_SET_4MB(xd_card);
- break;
- case XD_8M_X8_512:
- xd_card->block_shift = 4;
- xd_card->page_off = 0x0F;
- xd_card->addr_cycle = 3;
- xd_card->zone_cnt = 1;
- xd_card->capacity = 16000;
- break;
- case XD_16M_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 3;
- xd_card->zone_cnt = 1;
- xd_card->capacity = 32000;
- break;
- case XD_32M_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 3;
- xd_card->zone_cnt = 2;
- xd_card->capacity = 64000;
- break;
- case XD_64M_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 4;
- xd_card->zone_cnt = 4;
- xd_card->capacity = 128000;
- break;
- case XD_128M_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 4;
- xd_card->zone_cnt = 8;
- xd_card->capacity = 256000;
- break;
- case XD_256M_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 4;
- xd_card->zone_cnt = 16;
- xd_card->capacity = 512000;
- break;
- case XD_512M_X8:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 4;
- xd_card->zone_cnt = 32;
- xd_card->capacity = 1024000;
- break;
- case XD_1G_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 4;
- xd_card->zone_cnt = 64;
- xd_card->capacity = 2048000;
- break;
- case XD_2G_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 4;
- xd_card->zone_cnt = 128;
- xd_card->capacity = 4096000;
- break;
- default:
- continue;
- }
-
- /* Confirm timing setting */
- for (j = 0; j < 10; j++) {
- retval = xd_read_id(chip, READ_ID, id_buf, 4);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (id_buf[1] != xd_card->device_code)
- break;
- }
-
- if (j == 10)
- break;
- }
-
- if (i == 4) {
- xd_card->block_shift = 0;
- xd_card->page_off = 0;
- xd_card->addr_cycle = 0;
- xd_card->capacity = 0;
-
- return STATUS_FAIL;
- }
-
- retval = xd_read_id(chip, READ_XD_ID, id_buf, 4);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- dev_dbg(rtsx_dev(chip), "READ_XD_ID: 0x%x 0x%x 0x%x 0x%x\n",
- id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
- if (id_buf[2] != XD_ID_CODE)
- return STATUS_FAIL;
-
- /* Search CIS block */
- for (i = 0; i < 24; i++) {
- u32 page_addr;
-
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- page_addr = (u32)i << xd_card->block_shift;
-
- for (j = 0; j < 3; j++) {
- retval = xd_read_redundant(chip, page_addr, redunt, 11);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (j == 3)
- continue;
-
- if (redunt[BLOCK_STATUS] != XD_GBLK)
- continue;
-
- j = 0;
- if (redunt[PAGE_STATUS] != XD_GPG) {
- for (j = 1; j <= 8; j++) {
- retval = xd_read_redundant(chip, page_addr + j,
- redunt, 11);
- if (retval == STATUS_SUCCESS) {
- if (redunt[PAGE_STATUS] == XD_GPG)
- break;
- }
- }
-
- if (j == 9)
- break;
- }
-
- /* Check CIS data */
- if (redunt[BLOCK_STATUS] == XD_GBLK &&
- (redunt[PARITY] & XD_BA1_ALL0)) {
- u8 buf[10];
-
- page_addr += j;
-
- retval = xd_read_cis(chip, page_addr, buf, 10);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (buf[0] == 0x01 && buf[1] == 0x03 &&
- buf[2] == 0xD9 &&
- buf[3] == 0x01 && buf[4] == 0xFF &&
- buf[5] == 0x18 && buf[6] == 0x02 &&
- buf[7] == 0xDF && buf[8] == 0x01 &&
- buf[9] == 0x20) {
- xd_card->cis_block = (u16)i;
- }
- }
-
- break;
- }
-
- dev_dbg(rtsx_dev(chip), "CIS block: 0x%x\n", xd_card->cis_block);
- if (xd_card->cis_block == 0xFFFF)
- return STATUS_FAIL;
-
- chip->capacity[chip->card2lun[XD_CARD]] = xd_card->capacity;
-
- return STATUS_SUCCESS;
-}
-
-static int xd_check_data_blank(u8 *redunt)
-{
- int i;
-
- for (i = 0; i < 6; i++) {
- if (redunt[PAGE_STATUS + i] != 0xFF)
- return 0;
- }
-
- if ((redunt[PARITY] & (XD_ECC1_ALL1 | XD_ECC2_ALL1))
- != (XD_ECC1_ALL1 | XD_ECC2_ALL1))
- return 0;
-
- for (i = 0; i < 4; i++) {
- if (redunt[RESERVED0 + i] != 0xFF)
- return 0;
- }
-
- return 1;
-}
-
-static u16 xd_load_log_block_addr(u8 *redunt)
-{
- u16 addr = 0xFFFF;
-
- if (redunt[PARITY] & XD_BA1_BA2_EQL)
- addr = ((u16)redunt[BLOCK_ADDR1_H] << 8) |
- redunt[BLOCK_ADDR1_L];
- else if (redunt[PARITY] & XD_BA1_VALID)
- addr = ((u16)redunt[BLOCK_ADDR1_H] << 8) |
- redunt[BLOCK_ADDR1_L];
- else if (redunt[PARITY] & XD_BA2_VALID)
- addr = ((u16)redunt[BLOCK_ADDR2_H] << 8) |
- redunt[BLOCK_ADDR2_L];
-
- return addr;
-}
-
-static int xd_init_l2p_tbl(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int size, i;
-
- dev_dbg(rtsx_dev(chip), "%s: zone_cnt = %d\n", __func__,
- xd_card->zone_cnt);
-
- if (xd_card->zone_cnt < 1)
- return STATUS_FAIL;
-
- size = xd_card->zone_cnt * sizeof(struct zone_entry);
- dev_dbg(rtsx_dev(chip), "Buffer size for l2p table is %d\n", size);
-
- xd_card->zone = vmalloc(size);
- if (!xd_card->zone)
- return STATUS_ERROR;
-
- for (i = 0; i < xd_card->zone_cnt; i++) {
- xd_card->zone[i].build_flag = 0;
- xd_card->zone[i].l2p_table = NULL;
- xd_card->zone[i].free_table = NULL;
- xd_card->zone[i].get_index = 0;
- xd_card->zone[i].set_index = 0;
- xd_card->zone[i].unused_blk_cnt = 0;
- }
-
- return STATUS_SUCCESS;
-}
-
-static inline void free_zone(struct zone_entry *zone)
-{
- if (!zone)
- return;
-
- zone->build_flag = 0;
- zone->set_index = 0;
- zone->get_index = 0;
- zone->unused_blk_cnt = 0;
- vfree(zone->l2p_table);
- zone->l2p_table = NULL;
- vfree(zone->free_table);
- zone->free_table = NULL;
-}
-
-static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk)
-{
- struct xd_info *xd_card = &chip->xd_card;
- struct zone_entry *zone;
- int zone_no;
-
- zone_no = (int)phy_blk >> 10;
- if (zone_no >= xd_card->zone_cnt) {
- dev_dbg(rtsx_dev(chip), "Set unused block to invalid zone (zone_no = %d, zone_cnt = %d)\n",
- zone_no, xd_card->zone_cnt);
- return;
- }
- zone = &xd_card->zone[zone_no];
-
- if (!zone->free_table) {
- if (xd_build_l2p_tbl(chip, zone_no) != STATUS_SUCCESS)
- return;
- }
-
- if (zone->set_index >= XD_FREE_TABLE_CNT ||
- zone->set_index < 0) {
- free_zone(zone);
- dev_dbg(rtsx_dev(chip), "Set unused block fail, invalid set_index\n");
- return;
- }
-
- dev_dbg(rtsx_dev(chip), "Set unused block to index %d\n",
- zone->set_index);
-
- zone->free_table[zone->set_index++] = (u16)(phy_blk & 0x3ff);
- if (zone->set_index >= XD_FREE_TABLE_CNT)
- zone->set_index = 0;
- zone->unused_blk_cnt++;
-}
-
-static u32 xd_get_unused_block(struct rtsx_chip *chip, int zone_no)
-{
- struct xd_info *xd_card = &chip->xd_card;
- struct zone_entry *zone;
- u32 phy_blk;
-
- if (zone_no >= xd_card->zone_cnt) {
- dev_dbg(rtsx_dev(chip), "Get unused block from invalid zone (zone_no = %d, zone_cnt = %d)\n",
- zone_no, xd_card->zone_cnt);
- return BLK_NOT_FOUND;
- }
- zone = &xd_card->zone[zone_no];
-
- if (zone->unused_blk_cnt == 0 ||
- zone->set_index == zone->get_index) {
- free_zone(zone);
- dev_dbg(rtsx_dev(chip), "Get unused block fail, no unused block available\n");
- return BLK_NOT_FOUND;
- }
- if (zone->get_index >= XD_FREE_TABLE_CNT || zone->get_index < 0) {
- free_zone(zone);
- dev_dbg(rtsx_dev(chip), "Get unused block fail, invalid get_index\n");
- return BLK_NOT_FOUND;
- }
-
- dev_dbg(rtsx_dev(chip), "Get unused block from index %d\n",
- zone->get_index);
-
- phy_blk = zone->free_table[zone->get_index];
- zone->free_table[zone->get_index++] = 0xFFFF;
- if (zone->get_index >= XD_FREE_TABLE_CNT)
- zone->get_index = 0;
- zone->unused_blk_cnt--;
-
- phy_blk += ((u32)(zone_no) << 10);
- return phy_blk;
-}
-
-static void xd_set_l2p_tbl(struct rtsx_chip *chip,
- int zone_no, u16 log_off, u16 phy_off)
-{
- struct xd_info *xd_card = &chip->xd_card;
- struct zone_entry *zone;
-
- zone = &xd_card->zone[zone_no];
- zone->l2p_table[log_off] = phy_off;
-}
-
-static u32 xd_get_l2p_tbl(struct rtsx_chip *chip, int zone_no, u16 log_off)
-{
- struct xd_info *xd_card = &chip->xd_card;
- struct zone_entry *zone;
- int retval;
-
- zone = &xd_card->zone[zone_no];
- if (zone->l2p_table[log_off] == 0xFFFF) {
- u32 phy_blk = 0;
- int i;
-
-#ifdef XD_DELAY_WRITE
- retval = xd_delay_write(chip);
- if (retval != STATUS_SUCCESS) {
- dev_dbg(rtsx_dev(chip), "In %s, delay write fail!\n",
- __func__);
- return BLK_NOT_FOUND;
- }
-#endif
-
- if (zone->unused_blk_cnt <= 0) {
- dev_dbg(rtsx_dev(chip), "No unused block!\n");
- return BLK_NOT_FOUND;
- }
-
- for (i = 0; i < zone->unused_blk_cnt; i++) {
- phy_blk = xd_get_unused_block(chip, zone_no);
- if (phy_blk == BLK_NOT_FOUND) {
- dev_dbg(rtsx_dev(chip), "No unused block available!\n");
- return BLK_NOT_FOUND;
- }
-
- retval = xd_init_page(chip, phy_blk, log_off,
- 0, xd_card->page_off + 1);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i >= zone->unused_blk_cnt) {
- dev_dbg(rtsx_dev(chip), "No good unused block available!\n");
- return BLK_NOT_FOUND;
- }
-
- xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(phy_blk & 0x3FF));
- return phy_blk;
- }
-
- return (u32)zone->l2p_table[log_off] + ((u32)(zone_no) << 10);
-}
-
-int reset_xd_card(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval;
-
- memset(xd_card, 0, sizeof(struct xd_info));
-
- xd_card->block_shift = 0;
- xd_card->page_off = 0;
- xd_card->addr_cycle = 0;
- xd_card->capacity = 0;
- xd_card->zone_cnt = 0;
- xd_card->cis_block = 0xFFFF;
- xd_card->delay_write.delay_write_flag = 0;
-
- retval = enable_card_clock(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = reset_xd(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = xd_init_l2p_tbl(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int xd_mark_bad_block(struct rtsx_chip *chip, u32 phy_blk)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval;
- u32 page_addr;
- u8 reg = 0;
-
- dev_dbg(rtsx_dev(chip), "mark block 0x%x as bad block\n", phy_blk);
-
- if (phy_blk == BLK_NOT_FOUND)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_LATER_BBLK);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_H, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_L, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED0, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED1, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED2, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED3, 0xFF, 0xFF);
-
- page_addr = phy_blk << xd_card->block_shift;
-
- xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF,
- xd_card->page_off + 1);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_WRITE_REDUNDANT);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 500);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
- rtsx_read_register(chip, XD_DAT, &reg);
- if (reg & PROGRAM_ERROR)
- xd_set_err_code(chip, XD_PRG_ERROR);
- else
- xd_set_err_code(chip, XD_TO_ERROR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk,
- u16 logoff, u8 start_page, u8 end_page)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval;
- u32 page_addr;
- u8 reg = 0;
-
- dev_dbg(rtsx_dev(chip), "Init block 0x%x\n", phy_blk);
-
- if (start_page > end_page)
- return STATUS_FAIL;
- if (phy_blk == BLK_NOT_FOUND)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H,
- 0xFF, (u8)(logoff >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)logoff);
-
- page_addr = (phy_blk << xd_card->block_shift) + start_page;
-
- xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG,
- XD_BA_TRANSFORM, XD_BA_TRANSFORM);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT,
- 0xFF, (end_page - start_page));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER,
- 0xFF, XD_TRANSFER_START | XD_WRITE_REDUNDANT);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 500);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
- rtsx_read_register(chip, XD_DAT, &reg);
- if (reg & PROGRAM_ERROR) {
- xd_mark_bad_block(chip, phy_blk);
- xd_set_err_code(chip, XD_PRG_ERROR);
- } else {
- xd_set_err_code(chip, XD_TO_ERROR);
- }
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk,
- u8 start_page, u8 end_page)
-{
- struct xd_info *xd_card = &chip->xd_card;
- u32 old_page, new_page;
- u8 i, reg = 0;
- int retval;
-
- dev_dbg(rtsx_dev(chip), "Copy page from block 0x%x to block 0x%x\n",
- old_blk, new_blk);
-
- if (start_page > end_page)
- return STATUS_FAIL;
-
- if (old_blk == BLK_NOT_FOUND || new_blk == BLK_NOT_FOUND)
- return STATUS_FAIL;
-
- old_page = (old_blk << xd_card->block_shift) + start_page;
- new_page = (new_blk << xd_card->block_shift) + start_page;
-
- XD_CLR_BAD_NEWBLK(xd_card);
-
- retval = rtsx_write_register(chip, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
- if (retval)
- return retval;
-
- for (i = start_page; i < end_page; i++) {
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- rtsx_clear_xd_error(chip);
- xd_set_err_code(chip, XD_NO_CARD);
- return STATUS_FAIL;
- }
-
- rtsx_init_cmd(chip);
-
- xd_assign_phy_addr(chip, old_page, XD_RW_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
- XD_AUTO_CHK_DATA_STATUS, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_READ_PAGES);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 500);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
- reg = 0;
- rtsx_read_register(chip, XD_CTL, &reg);
- if (reg & (XD_ECC1_ERROR | XD_ECC2_ERROR)) {
- mdelay(100);
-
- if (detect_card_cd(chip,
- XD_CARD) != STATUS_SUCCESS) {
- xd_set_err_code(chip, XD_NO_CARD);
- return STATUS_FAIL;
- }
-
- if (((reg & XD_ECC1_ERROR) &&
- (reg & XD_ECC1_UNCORRECTABLE)) ||
- ((reg & XD_ECC2_ERROR) &&
- (reg & XD_ECC2_UNCORRECTABLE))) {
- rtsx_write_register(chip,
- XD_PAGE_STATUS,
- 0xFF,
- XD_BPG);
- rtsx_write_register(chip,
- XD_BLOCK_STATUS,
- 0xFF,
- XD_GBLK);
- XD_SET_BAD_OLDBLK(xd_card);
- dev_dbg(rtsx_dev(chip), "old block 0x%x ecc error\n",
- old_blk);
- }
- } else {
- xd_set_err_code(chip, XD_TO_ERROR);
- return STATUS_FAIL;
- }
- }
-
- if (XD_CHK_BAD_OLDBLK(xd_card))
- rtsx_clear_xd_error(chip);
-
- rtsx_init_cmd(chip);
-
- xd_assign_phy_addr(chip, new_page, XD_RW_ADDR);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_WRITE_PAGES);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 300);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
- reg = 0;
- rtsx_read_register(chip, XD_DAT, &reg);
- if (reg & PROGRAM_ERROR) {
- xd_mark_bad_block(chip, new_blk);
- xd_set_err_code(chip, XD_PRG_ERROR);
- XD_SET_BAD_NEWBLK(xd_card);
- } else {
- xd_set_err_code(chip, XD_TO_ERROR);
- }
- return STATUS_FAIL;
- }
-
- old_page++;
- new_page++;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int xd_reset_cmd(struct rtsx_chip *chip)
-{
- int retval;
- u8 *ptr;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER,
- 0xFF, XD_TRANSFER_START | XD_RESET);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
- rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- ptr = rtsx_get_cmd_data(chip) + 1;
- if (((ptr[0] & READY_FLAG) == READY_STATE) && (ptr[1] & XD_RDY))
- return STATUS_SUCCESS;
-
- return STATUS_FAIL;
-}
-
-static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk)
-{
- struct xd_info *xd_card = &chip->xd_card;
- u32 page_addr;
- u8 reg = 0, *ptr;
- int i, retval;
-
- if (phy_blk == BLK_NOT_FOUND)
- return STATUS_FAIL;
-
- page_addr = phy_blk << xd_card->block_shift;
-
- for (i = 0; i < 3; i++) {
- rtsx_init_cmd(chip);
-
- xd_assign_phy_addr(chip, page_addr, XD_ERASE_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_ERASE);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
- rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 250);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
- rtsx_read_register(chip, XD_DAT, &reg);
- if (reg & PROGRAM_ERROR) {
- xd_mark_bad_block(chip, phy_blk);
- xd_set_err_code(chip, XD_PRG_ERROR);
- return STATUS_FAIL;
- }
- xd_set_err_code(chip, XD_ERASE_FAIL);
- retval = xd_reset_cmd(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- continue;
- }
-
- ptr = rtsx_get_cmd_data(chip) + 1;
- if (*ptr & PROGRAM_ERROR) {
- xd_mark_bad_block(chip, phy_blk);
- xd_set_err_code(chip, XD_PRG_ERROR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
- }
-
- xd_mark_bad_block(chip, phy_blk);
- xd_set_err_code(chip, XD_ERASE_FAIL);
- return STATUS_FAIL;
-}
-
-static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no)
-{
- struct xd_info *xd_card = &chip->xd_card;
- struct zone_entry *zone;
- int retval;
- u32 start, end, i;
- u16 max_logoff, cur_fst_page_logoff;
- u16 cur_lst_page_logoff, ent_lst_page_logoff;
- u8 redunt[11];
-
- dev_dbg(rtsx_dev(chip), "%s: %d\n", __func__, zone_no);
-
- if (!xd_card->zone) {
- retval = xd_init_l2p_tbl(chip);
- if (retval != STATUS_SUCCESS)
- return retval;
- }
-
- if (xd_card->zone[zone_no].build_flag) {
- dev_dbg(rtsx_dev(chip), "l2p table of zone %d has been built\n",
- zone_no);
- return STATUS_SUCCESS;
- }
-
- zone = &xd_card->zone[zone_no];
-
- if (!zone->l2p_table) {
- zone->l2p_table = vmalloc(2000);
- if (!zone->l2p_table)
- goto build_fail;
- }
- memset((u8 *)(zone->l2p_table), 0xff, 2000);
-
- if (!zone->free_table) {
- zone->free_table = vmalloc(XD_FREE_TABLE_CNT * 2);
- if (!zone->free_table)
- goto build_fail;
- }
- memset((u8 *)(zone->free_table), 0xff, XD_FREE_TABLE_CNT * 2);
-
- if (zone_no == 0) {
- if (xd_card->cis_block == 0xFFFF)
- start = 0;
- else
- start = xd_card->cis_block + 1;
- if (XD_CHK_4MB(xd_card)) {
- end = 0x200;
- max_logoff = 499;
- } else {
- end = 0x400;
- max_logoff = 999;
- }
- } else {
- start = (u32)(zone_no) << 10;
- end = (u32)(zone_no + 1) << 10;
- max_logoff = 999;
- }
-
- dev_dbg(rtsx_dev(chip), "start block 0x%x, end block 0x%x\n",
- start, end);
-
- zone->set_index = 0;
- zone->get_index = 0;
- zone->unused_blk_cnt = 0;
-
- for (i = start; i < end; i++) {
- u32 page_addr = i << xd_card->block_shift;
- u32 phy_block;
-
- retval = xd_read_redundant(chip, page_addr, redunt, 11);
- if (retval != STATUS_SUCCESS)
- continue;
-
- if (redunt[BLOCK_STATUS] != 0xFF) {
- dev_dbg(rtsx_dev(chip), "bad block\n");
- continue;
- }
-
- if (xd_check_data_blank(redunt)) {
- dev_dbg(rtsx_dev(chip), "blank block\n");
- xd_set_unused_block(chip, i);
- continue;
- }
-
- cur_fst_page_logoff = xd_load_log_block_addr(redunt);
- if (cur_fst_page_logoff == 0xFFFF ||
- cur_fst_page_logoff > max_logoff) {
- retval = xd_erase_block(chip, i);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, i);
- continue;
- }
-
- if (zone_no == 0 && cur_fst_page_logoff == 0 &&
- redunt[PAGE_STATUS] != XD_GPG)
- XD_SET_MBR_FAIL(xd_card);
-
- if (zone->l2p_table[cur_fst_page_logoff] == 0xFFFF) {
- zone->l2p_table[cur_fst_page_logoff] = (u16)(i & 0x3FF);
- continue;
- }
-
- phy_block = zone->l2p_table[cur_fst_page_logoff] +
- ((u32)((zone_no) << 10));
-
- page_addr = ((i + 1) << xd_card->block_shift) - 1;
-
- retval = xd_read_redundant(chip, page_addr, redunt, 11);
- if (retval != STATUS_SUCCESS)
- continue;
-
- cur_lst_page_logoff = xd_load_log_block_addr(redunt);
- if (cur_lst_page_logoff == cur_fst_page_logoff) {
- int m;
-
- page_addr = ((phy_block + 1) <<
- xd_card->block_shift) - 1;
-
- for (m = 0; m < 3; m++) {
- retval = xd_read_redundant(chip, page_addr,
- redunt, 11);
- if (retval == STATUS_SUCCESS)
- break;
- }
-
- if (m == 3) {
- zone->l2p_table[cur_fst_page_logoff] =
- (u16)(i & 0x3FF);
- retval = xd_erase_block(chip, phy_block);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, phy_block);
- continue;
- }
-
- ent_lst_page_logoff = xd_load_log_block_addr(redunt);
- if (ent_lst_page_logoff != cur_fst_page_logoff) {
- zone->l2p_table[cur_fst_page_logoff] =
- (u16)(i & 0x3FF);
- retval = xd_erase_block(chip, phy_block);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, phy_block);
- continue;
- } else {
- retval = xd_erase_block(chip, i);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, i);
- }
- } else {
- retval = xd_erase_block(chip, i);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, i);
- }
- }
-
- if (XD_CHK_4MB(xd_card))
- end = 500;
- else
- end = 1000;
-
- i = 0;
- for (start = 0; start < end; start++) {
- if (zone->l2p_table[start] == 0xFFFF)
- i++;
- }
-
- dev_dbg(rtsx_dev(chip), "Block count %d, invalid L2P entry %d\n",
- end, i);
- dev_dbg(rtsx_dev(chip), "Total unused block: %d\n",
- zone->unused_blk_cnt);
-
- if ((zone->unused_blk_cnt - i) < 1)
- chip->card_wp |= XD_CARD;
-
- zone->build_flag = 1;
-
- return STATUS_SUCCESS;
-
-build_fail:
- vfree(zone->l2p_table);
- zone->l2p_table = NULL;
- vfree(zone->free_table);
- zone->free_table = NULL;
-
- return STATUS_FAIL;
-}
-
-static int xd_send_cmd(struct rtsx_chip *chip, u8 cmd)
-{
- int retval;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, cmd);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_SET_CMD);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 200);
- if (retval < 0)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk,
- u32 log_blk, u8 start_page, u8 end_page,
- u8 *buf, unsigned int *index,
- unsigned int *offset)
-{
- struct xd_info *xd_card = &chip->xd_card;
- u32 page_addr, new_blk;
- u16 log_off;
- u8 reg_val, page_cnt;
- int zone_no, retval, i;
-
- if (start_page > end_page)
- goto status_fail;
-
- page_cnt = end_page - start_page;
- zone_no = (int)(log_blk / 1000);
- log_off = (u16)(log_blk % 1000);
-
- if ((phy_blk & 0x3FF) == 0x3FF) {
- for (i = 0; i < 256; i++) {
- page_addr = ((u32)i) << xd_card->block_shift;
-
- retval = xd_read_redundant(chip, page_addr, NULL, 0);
- if (retval == STATUS_SUCCESS)
- break;
-
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- xd_set_err_code(chip, XD_NO_CARD);
- goto status_fail;
- }
- }
- }
-
- page_addr = (phy_blk << xd_card->block_shift) + start_page;
-
- rtsx_init_cmd(chip);
-
- xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_PPB_TO_SIE, XD_PPB_TO_SIE);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
- XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS);
-
- trans_dma_enable(chip->srb->sc_data_direction, chip,
- page_cnt * 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_READ_PAGES);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END | XD_PPB_EMPTY,
- XD_TRANSFER_END | XD_PPB_EMPTY);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512,
- scsi_sg_count(chip->srb),
- index, offset, DMA_FROM_DEVICE,
- chip->xd_timeout);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
-
- if (retval == -ETIMEDOUT) {
- xd_set_err_code(chip, XD_TO_ERROR);
- goto status_fail;
- } else {
- goto fail;
- }
- }
-
- return STATUS_SUCCESS;
-
-fail:
- retval = rtsx_read_register(chip, XD_PAGE_STATUS, &reg_val);
- if (retval)
- return retval;
-
- if (reg_val != XD_GPG)
- xd_set_err_code(chip, XD_PRG_ERROR);
-
- retval = rtsx_read_register(chip, XD_CTL, &reg_val);
- if (retval)
- return retval;
-
- if (((reg_val & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) ==
- (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) ||
- ((reg_val & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) ==
- (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) {
- wait_timeout(100);
-
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- xd_set_err_code(chip, XD_NO_CARD);
- goto status_fail;
- }
-
- xd_set_err_code(chip, XD_ECC_ERROR);
-
- new_blk = xd_get_unused_block(chip, zone_no);
- if (new_blk == NO_NEW_BLK) {
- XD_CLR_BAD_OLDBLK(xd_card);
- goto status_fail;
- }
-
- retval = xd_copy_page(chip, phy_blk, new_blk, 0,
- xd_card->page_off + 1);
- if (retval != STATUS_SUCCESS) {
- if (!XD_CHK_BAD_NEWBLK(xd_card)) {
- retval = xd_erase_block(chip, new_blk);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, new_blk);
- } else {
- XD_CLR_BAD_NEWBLK(xd_card);
- }
- XD_CLR_BAD_OLDBLK(xd_card);
- goto status_fail;
- }
- xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
- xd_erase_block(chip, phy_blk);
- xd_mark_bad_block(chip, phy_blk);
- XD_CLR_BAD_OLDBLK(xd_card);
- }
-
-status_fail:
- return STATUS_FAIL;
-}
-
-static int xd_finish_write(struct rtsx_chip *chip,
- u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval, zone_no;
- u16 log_off;
-
- dev_dbg(rtsx_dev(chip), "old_blk = 0x%x, ", old_blk);
- dev_dbg(rtsx_dev(chip), "new_blk = 0x%x, ", new_blk);
- dev_dbg(rtsx_dev(chip), "log_blk = 0x%x\n", log_blk);
-
- if (page_off > xd_card->page_off)
- return STATUS_FAIL;
-
- zone_no = (int)(log_blk / 1000);
- log_off = (u16)(log_blk % 1000);
-
- if (old_blk == BLK_NOT_FOUND) {
- retval = xd_init_page(chip, new_blk, log_off,
- page_off, xd_card->page_off + 1);
- if (retval != STATUS_SUCCESS) {
- retval = xd_erase_block(chip, new_blk);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, new_blk);
- return STATUS_FAIL;
- }
- } else {
- retval = xd_copy_page(chip, old_blk, new_blk,
- page_off, xd_card->page_off + 1);
- if (retval != STATUS_SUCCESS) {
- if (!XD_CHK_BAD_NEWBLK(xd_card)) {
- retval = xd_erase_block(chip, new_blk);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, new_blk);
- }
- XD_CLR_BAD_NEWBLK(xd_card);
- return STATUS_FAIL;
- }
-
- retval = xd_erase_block(chip, old_blk);
- if (retval == STATUS_SUCCESS) {
- if (XD_CHK_BAD_OLDBLK(xd_card)) {
- xd_mark_bad_block(chip, old_blk);
- XD_CLR_BAD_OLDBLK(xd_card);
- } else {
- xd_set_unused_block(chip, old_blk);
- }
- } else {
- xd_set_err_code(chip, XD_NO_ERROR);
- XD_CLR_BAD_OLDBLK(xd_card);
- }
- }
-
- xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
-
- return STATUS_SUCCESS;
-}
-
-static int xd_prepare_write(struct rtsx_chip *chip,
- u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off)
-{
- int retval;
-
- dev_dbg(rtsx_dev(chip), "%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x, page_off = %d\n",
- __func__, old_blk, new_blk, log_blk, (int)page_off);
-
- if (page_off) {
- retval = xd_copy_page(chip, old_blk, new_blk, 0, page_off);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk,
- u32 new_blk, u32 log_blk, u8 start_page,
- u8 end_page, u8 *buf, unsigned int *index,
- unsigned int *offset)
-{
- struct xd_info *xd_card = &chip->xd_card;
- u32 page_addr;
- int zone_no, retval;
- u16 log_off;
- u8 page_cnt, reg_val;
-
- dev_dbg(rtsx_dev(chip), "%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n",
- __func__, old_blk, new_blk, log_blk);
-
- if (start_page > end_page)
- goto status_fail;
-
- page_cnt = end_page - start_page;
- zone_no = (int)(log_blk / 1000);
- log_off = (u16)(log_blk % 1000);
-
- page_addr = (new_blk << xd_card->block_shift) + start_page;
-
- retval = xd_send_cmd(chip, READ1_1);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H,
- 0xFF, (u8)(log_off >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)log_off);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_GBLK);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG);
-
- xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM,
- XD_BA_TRANSFORM);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-
- trans_dma_enable(chip->srb->sc_data_direction, chip,
- page_cnt * 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER,
- 0xFF, XD_TRANSFER_START | XD_WRITE_PAGES);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512,
- scsi_sg_count(chip->srb),
- index, offset, DMA_TO_DEVICE, chip->xd_timeout);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
-
- if (retval == -ETIMEDOUT) {
- xd_set_err_code(chip, XD_TO_ERROR);
- goto status_fail;
- } else {
- goto fail;
- }
- }
-
- if (end_page == (xd_card->page_off + 1)) {
- xd_card->delay_write.delay_write_flag = 0;
-
- if (old_blk != BLK_NOT_FOUND) {
- retval = xd_erase_block(chip, old_blk);
- if (retval == STATUS_SUCCESS) {
- if (XD_CHK_BAD_OLDBLK(xd_card)) {
- xd_mark_bad_block(chip, old_blk);
- XD_CLR_BAD_OLDBLK(xd_card);
- } else {
- xd_set_unused_block(chip, old_blk);
- }
- } else {
- xd_set_err_code(chip, XD_NO_ERROR);
- XD_CLR_BAD_OLDBLK(xd_card);
- }
- }
- xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
- }
-
- return STATUS_SUCCESS;
-
-fail:
- retval = rtsx_read_register(chip, XD_DAT, &reg_val);
- if (retval)
- return retval;
- if (reg_val & PROGRAM_ERROR) {
- xd_set_err_code(chip, XD_PRG_ERROR);
- xd_mark_bad_block(chip, new_blk);
- }
-
-status_fail:
- return STATUS_FAIL;
-}
-
-#ifdef XD_DELAY_WRITE
-int xd_delay_write(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- struct xd_delay_write_tag *delay_write = &xd_card->delay_write;
- int retval;
-
- if (delay_write->delay_write_flag) {
- retval = xd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- delay_write->delay_write_flag = 0;
- retval = xd_finish_write(chip,
- delay_write->old_phyblock,
- delay_write->new_phyblock,
- delay_write->logblock,
- delay_write->pageoff);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-#endif
-
-int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 start_sector, u16 sector_cnt)
-{
- struct xd_info *xd_card = &chip->xd_card;
- unsigned int lun = SCSI_LUN(srb);
-#ifdef XD_DELAY_WRITE
- struct xd_delay_write_tag *delay_write = &xd_card->delay_write;
-#endif
- int retval, zone_no;
- unsigned int index = 0, offset = 0;
- u32 log_blk, old_blk = 0, new_blk = 0;
- u16 log_off, total_sec_cnt = sector_cnt;
- u8 start_page, end_page = 0, page_cnt;
- u8 *ptr;
-
- xd_set_err_code(chip, XD_NO_ERROR);
-
- xd_card->cleanup_counter = 0;
-
- dev_dbg(rtsx_dev(chip), "%s: scsi_sg_count = %d\n", __func__,
- scsi_sg_count(srb));
-
- ptr = (u8 *)scsi_sglist(srb);
-
- retval = xd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- chip->card_fail |= XD_CARD;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
-
- log_blk = start_sector >> xd_card->block_shift;
- start_page = (u8)start_sector & xd_card->page_off;
- zone_no = (int)(log_blk / 1000);
- log_off = (u16)(log_blk % 1000);
-
- if (xd_card->zone[zone_no].build_flag == 0) {
- retval = xd_build_l2p_tbl(chip, zone_no);
- if (retval != STATUS_SUCCESS) {
- chip->card_fail |= XD_CARD;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
-#ifdef XD_DELAY_WRITE
- if (delay_write->delay_write_flag &&
- delay_write->logblock == log_blk &&
- start_page > delay_write->pageoff) {
- delay_write->delay_write_flag = 0;
- if (delay_write->old_phyblock != BLK_NOT_FOUND) {
- retval = xd_copy_page(chip,
- delay_write->old_phyblock,
- delay_write->new_phyblock,
- delay_write->pageoff,
- start_page);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
- }
- old_blk = delay_write->old_phyblock;
- new_blk = delay_write->new_phyblock;
- } else if (delay_write->delay_write_flag &&
- (delay_write->logblock == log_blk) &&
- (start_page == delay_write->pageoff)) {
- delay_write->delay_write_flag = 0;
- old_blk = delay_write->old_phyblock;
- new_blk = delay_write->new_phyblock;
- } else {
- retval = xd_delay_write(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-#endif
- old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
- new_blk = xd_get_unused_block(chip, zone_no);
- if (old_blk == BLK_NOT_FOUND ||
- new_blk == BLK_NOT_FOUND) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-
- retval = xd_prepare_write(chip, old_blk, new_blk,
- log_blk, start_page);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, XD_CARD) !=
- STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-#ifdef XD_DELAY_WRITE
- }
-#endif
- } else {
-#ifdef XD_DELAY_WRITE
- retval = xd_delay_write(chip);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return STATUS_FAIL;
- }
-#endif
-
- old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
- if (old_blk == BLK_NOT_FOUND) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return STATUS_FAIL;
- }
- }
-
- dev_dbg(rtsx_dev(chip), "old_blk = 0x%x\n", old_blk);
-
- while (total_sec_cnt) {
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- chip->card_fail |= XD_CARD;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
-
- if ((start_page + total_sec_cnt) > (xd_card->page_off + 1))
- end_page = xd_card->page_off + 1;
- else
- end_page = start_page + (u8)total_sec_cnt;
-
- page_cnt = end_page - start_page;
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- retval = xd_read_multiple_pages(chip, old_blk, log_blk,
- start_page, end_page,
- ptr, &index, &offset);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return STATUS_FAIL;
- }
- } else {
- retval = xd_write_multiple_pages(chip, old_blk,
- new_blk, log_blk,
- start_page, end_page,
- ptr, &index, &offset);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
- }
-
- total_sec_cnt -= page_cnt;
- if (scsi_sg_count(srb) == 0)
- ptr += page_cnt * 512;
-
- if (total_sec_cnt == 0)
- break;
-
- log_blk++;
- zone_no = (int)(log_blk / 1000);
- log_off = (u16)(log_blk % 1000);
-
- if (xd_card->zone[zone_no].build_flag == 0) {
- retval = xd_build_l2p_tbl(chip, zone_no);
- if (retval != STATUS_SUCCESS) {
- chip->card_fail |= XD_CARD;
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- }
-
- old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
- if (old_blk == BLK_NOT_FOUND) {
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- else
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
-
- return STATUS_FAIL;
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
- new_blk = xd_get_unused_block(chip, zone_no);
- if (new_blk == BLK_NOT_FOUND) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
- }
-
- start_page = 0;
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE &&
- (end_page != (xd_card->page_off + 1))) {
-#ifdef XD_DELAY_WRITE
- delay_write->delay_write_flag = 1;
- delay_write->old_phyblock = old_blk;
- delay_write->new_phyblock = new_blk;
- delay_write->logblock = log_blk;
- delay_write->pageoff = end_page;
-#else
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- chip->card_fail |= XD_CARD;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
-
- retval = xd_finish_write(chip, old_blk, new_blk,
- log_blk, end_page);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-#endif
- }
-
- scsi_set_resid(srb, 0);
-
- return STATUS_SUCCESS;
-}
-
-void xd_free_l2p_tbl(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int i = 0;
-
- if (xd_card->zone) {
- for (i = 0; i < xd_card->zone_cnt; i++) {
- vfree(xd_card->zone[i].l2p_table);
- xd_card->zone[i].l2p_table = NULL;
- vfree(xd_card->zone[i].free_table);
- xd_card->zone[i].free_table = NULL;
- }
- vfree(xd_card->zone);
- xd_card->zone = NULL;
- }
-}
-
-void xd_cleanup_work(struct rtsx_chip *chip)
-{
-#ifdef XD_DELAY_WRITE
- struct xd_info *xd_card = &chip->xd_card;
-
- if (xd_card->delay_write.delay_write_flag) {
- dev_dbg(rtsx_dev(chip), "xD: delay write\n");
- xd_delay_write(chip);
- xd_card->cleanup_counter = 0;
- }
-#endif
-}
-
-int xd_power_off_card3v3(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = disable_card_clock(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
- if (retval)
- return retval;
-
- if (!chip->ft2_fast_mode) {
- retval = card_power_off(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- wait_timeout(50);
- }
-
- if (chip->asic_code) {
- retval = xd_pull_ctl_disable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL, 0xFF, 0xDF);
- if (retval)
- return retval;
- }
-
- return STATUS_SUCCESS;
-}
-
-int release_xd_card(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval;
-
- chip->card_ready &= ~XD_CARD;
- chip->card_fail &= ~XD_CARD;
- chip->card_wp &= ~XD_CARD;
-
- xd_card->delay_write.delay_write_flag = 0;
-
- xd_free_l2p_tbl(chip);
-
- retval = xd_power_off_card3v3(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts5208/xd.h b/drivers/staging/rts5208/xd.h
deleted file mode 100644
index 98c00f268e56..000000000000
--- a/drivers/staging/rts5208/xd.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_XD_H
-#define __REALTEK_RTSX_XD_H
-
-#define XD_DELAY_WRITE
-
-/* Error Codes */
-#define XD_NO_ERROR 0x00
-#define XD_NO_MEMORY 0x80
-#define XD_PRG_ERROR 0x40
-#define XD_NO_CARD 0x20
-#define XD_READ_FAIL 0x10
-#define XD_ERASE_FAIL 0x08
-#define XD_WRITE_FAIL 0x04
-#define XD_ECC_ERROR 0x02
-#define XD_TO_ERROR 0x01
-
-/* XD Commands */
-#define READ1_1 0x00
-#define READ1_2 0x01
-#define READ2 0x50
-#define READ_ID 0x90
-#define RESET 0xff
-#define PAGE_PRG_1 0x80
-#define PAGE_PRG_2 0x10
-#define BLK_ERASE_1 0x60
-#define BLK_ERASE_2 0xD0
-#define READ_STS 0x70
-#define READ_XD_ID 0x9A
-#define COPY_BACK_512 0x8A
-#define COPY_BACK_2K 0x85
-#define READ1_1_2 0x30
-#define READ1_1_3 0x35
-#define CHG_DAT_OUT_1 0x05
-#define RDM_DAT_OUT_1 0x05
-#define CHG_DAT_OUT_2 0xE0
-#define RDM_DAT_OUT_2 0xE0
-#define CHG_DAT_OUT_2 0xE0
-#define CHG_DAT_IN_1 0x85
-#define CACHE_PRG 0x15
-
-/* Redundant Area Related */
-#define XD_EXTRA_SIZE 0x10
-#define XD_2K_EXTRA_SIZE 0x40
-
-#define NOT_WRITE_PROTECTED 0x80
-#define READY_STATE 0x40
-#define PROGRAM_ERROR 0x01
-#define PROGRAM_ERROR_N_1 0x02
-#define INTERNAL_READY 0x20
-#define READY_FLAG 0x5F
-
-#define XD_8M_X8_512 0xE6
-#define XD_16M_X8_512 0x73
-#define XD_32M_X8_512 0x75
-#define XD_64M_X8_512 0x76
-#define XD_128M_X8_512 0x79
-#define XD_256M_X8_512 0x71
-#define XD_128M_X8_2048 0xF1
-#define XD_256M_X8_2048 0xDA
-#define XD_512M_X8 0xDC
-#define XD_128M_X16_2048 0xC1
-#define XD_4M_X8_512_1 0xE3
-#define XD_4M_X8_512_2 0xE5
-#define XD_1G_X8_512 0xD3
-#define XD_2G_X8_512 0xD5
-
-#define XD_ID_CODE 0xB5
-
-#define VENDOR_BLOCK 0xEFFF
-#define CIS_BLOCK 0xDFFF
-
-#define BLK_NOT_FOUND 0xFFFFFFFF
-
-#define NO_NEW_BLK 0xFFFFFFFF
-
-#define PAGE_CORRECTABLE 0x0
-#define PAGE_NOTCORRECTABLE 0x1
-
-#define NO_OFFSET 0x0
-#define WITH_OFFSET 0x1
-
-#define SECT_PER_PAGE 4
-#define XD_ADDR_MODE_2C XD_ADDR_MODE_2A
-
-#define ZONE0_BAD_BLOCK 23
-#define NOT_ZONE0_BAD_BLOCK 24
-
-#define XD_RW_ADDR 0x01
-#define XD_ERASE_ADDR 0x02
-
-#define XD_PAGE_512(xd_card) \
-do { \
- (xd_card)->block_shift = 5; \
- (xd_card)->page_off = 0x1F; \
-} while (0)
-
-#define XD_SET_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag |= 0x01)
-#define XD_CLR_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag &= ~0x01)
-#define XD_CHK_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag & 0x01)
-
-#define XD_SET_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag |= 0x02)
-#define XD_CLR_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag &= ~0x02)
-#define XD_CHK_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag & 0x02)
-
-#define XD_SET_MBR_FAIL(xd_card) ((xd_card)->multi_flag |= 0x04)
-#define XD_CLR_MBR_FAIL(xd_card) ((xd_card)->multi_flag &= ~0x04)
-#define XD_CHK_MBR_FAIL(xd_card) ((xd_card)->multi_flag & 0x04)
-
-#define XD_SET_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag |= 0x08)
-#define XD_CLR_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag &= ~0x08)
-#define XD_CHK_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag & 0x08)
-
-#define XD_SET_4MB(xd_card) ((xd_card)->multi_flag |= 0x10)
-#define XD_CLR_4MB(xd_card) ((xd_card)->multi_flag &= ~0x10)
-#define XD_CHK_4MB(xd_card) ((xd_card)->multi_flag & 0x10)
-
-#define XD_SET_ECC_ERR(xd_card) ((xd_card)->multi_flag |= 0x40)
-#define XD_CLR_ECC_ERR(xd_card) ((xd_card)->multi_flag &= ~0x40)
-#define XD_CHK_ECC_ERR(xd_card) ((xd_card)->multi_flag & 0x40)
-
-#define PAGE_STATUS 0
-#define BLOCK_STATUS 1
-#define BLOCK_ADDR1_L 2
-#define BLOCK_ADDR1_H 3
-#define BLOCK_ADDR2_L 4
-#define BLOCK_ADDR2_H 5
-#define RESERVED0 6
-#define RESERVED1 7
-#define RESERVED2 8
-#define RESERVED3 9
-#define PARITY 10
-
-#define CIS0_0 0
-#define CIS0_1 1
-#define CIS0_2 2
-#define CIS0_3 3
-#define CIS0_4 4
-#define CIS0_5 5
-#define CIS0_6 6
-#define CIS0_7 7
-#define CIS0_8 8
-#define CIS0_9 9
-#define CIS1_0 256
-#define CIS1_1 (256 + 1)
-#define CIS1_2 (256 + 2)
-#define CIS1_3 (256 + 3)
-#define CIS1_4 (256 + 4)
-#define CIS1_5 (256 + 5)
-#define CIS1_6 (256 + 6)
-#define CIS1_7 (256 + 7)
-#define CIS1_8 (256 + 8)
-#define CIS1_9 (256 + 9)
-
-int reset_xd_card(struct rtsx_chip *chip);
-#ifdef XD_DELAY_WRITE
-int xd_delay_write(struct rtsx_chip *chip);
-#endif
-int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 start_sector, u16 sector_cnt);
-void xd_free_l2p_tbl(struct rtsx_chip *chip);
-void xd_cleanup_work(struct rtsx_chip *chip);
-int xd_power_off_card3v3(struct rtsx_chip *chip);
-int release_xd_card(struct rtsx_chip *chip);
-
-#endif /* __REALTEK_RTSX_XD_H */
diff --git a/drivers/staging/sm750fb/TODO b/drivers/staging/sm750fb/TODO
index 481409eb3fb3..9dd57c566257 100644
--- a/drivers/staging/sm750fb/TODO
+++ b/drivers/staging/sm750fb/TODO
@@ -12,8 +12,3 @@ TODO:
Note:
- This driver will be removed from staging after the drm driver is ready
- The drm driver is getting ready at https://gitlab.com/sudipm/sm750/tree/sm750
-
-Please send any patches to
- Greg Kroah-Hartman <greg@kroah.com>
- Sudip Mukherjee <sudipm.mukherjee@gmail.com>
- Teddy Wang <teddy.wang@siliconmotion.com>
diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
index 133ed15f3dbc..dc0d715ed970 100644
--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
@@ -96,7 +96,8 @@ static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance,
static int audio_vchi_callback(struct vchiq_instance *vchiq_instance,
enum vchiq_reason reason,
struct vchiq_header *header,
- unsigned int handle, void *userdata)
+ unsigned int handle,
+ void *cb_data, void __user *cb_userdata)
{
struct bcm2835_audio_instance *instance = vchiq_get_service_userdata(vchiq_instance,
handle);
diff --git a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h
index 6c40d8c1dde6..ee4469f4fc51 100644
--- a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h
+++ b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h
@@ -56,7 +56,7 @@ struct vchiq_service_base {
enum vchiq_reason reason,
struct vchiq_header *header,
unsigned int handle,
- void *bulk_userdata);
+ void *cb_data, void __user *cb_userdata);
void *userdata;
};
@@ -64,7 +64,8 @@ struct vchiq_completion_data_kernel {
enum vchiq_reason reason;
struct vchiq_header *header;
void *service_userdata;
- void *bulk_userdata;
+ void *cb_data;
+ void __user *cb_userdata;
};
struct vchiq_service_params_kernel {
@@ -73,7 +74,7 @@ struct vchiq_service_params_kernel {
enum vchiq_reason reason,
struct vchiq_header *header,
unsigned int handle,
- void *bulk_userdata);
+ void *cb_data, void __user *cb_userdata);
void *userdata;
short version; /* Increment for non-trivial changes */
short version_min; /* Update for incompatible changes */
diff --git a/drivers/staging/vc04_services/interface/TESTING b/drivers/staging/vc04_services/interface/TESTING
index 273952dc9d85..c98f688b07e0 100644
--- a/drivers/staging/vc04_services/interface/TESTING
+++ b/drivers/staging/vc04_services/interface/TESTING
@@ -52,10 +52,10 @@ Here are the most common kernel configurations:
* Ping test
- Command: vchiq_test -p 1
+ Command: vchiq_test -p
Expected output:
- Ping test - service:echo, iters:1, version 3
+ Ping test - service:echo, iters:1000, version 3
vchi ping (size 0) -> 57.000000us
vchi ping (size 0, 0 async, 0 oneway) -> 122.000000us
vchi bulk (size 0, 0 async, 0 oneway) -> 546.000000us
diff --git a/drivers/staging/vc04_services/interface/TODO b/drivers/staging/vc04_services/interface/TODO
index dfb1ee49633f..f6f24600aa86 100644
--- a/drivers/staging/vc04_services/interface/TODO
+++ b/drivers/staging/vc04_services/interface/TODO
@@ -26,16 +26,3 @@ kthreads, userspace, limitations) could be very helpful for reviewers.
The code follows the 80 characters limitation yet tends to go 3 or 4 levels of
indentation deep making it very unpleasant to read. This is specially relevant
in the character driver ioctl code and in the core thread functions.
-
-* Clean up Sparse warnings from __user annotations. See
-vchiq_irq_queue_bulk_tx_rx(). Ensure that the address of "&waiter->bulk_waiter"
-is never disclosed to userspace.
-
-* Fix behavior of message handling
-
-The polling behavior of vchiq_bulk_transmit(), vchiq_bulk_receive() and
-vchiq_queue_kernel_message() looks broken. A possible signal should be
-propagated back to user space to let the calling task handle it before
-retrying. Hopefully these msleep(1) shouldn't be necessary anymore.
-
-https://lore.kernel.org/linux-staging/CAK8P3a3HGm1cPo4sW9fOY4E8AN8yAq3tevXxU5m8bmtmsU8WKw@mail.gmail.com/
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index 6c488b1e2624..a4e83e5d619b 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -14,7 +14,6 @@
#include <linux/device.h>
#include <linux/device/bus.h>
#include <linux/mm.h>
-#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/bug.h>
#include <linux/completion.h>
@@ -36,7 +35,6 @@
#include "vchiq_arm.h"
#include "vchiq_bus.h"
#include "vchiq_debugfs.h"
-#include "vchiq_pagelist.h"
#define DEVICE_NAME "vchiq"
@@ -48,7 +46,6 @@
#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1
#define BELL0 0x00
-#define BELL2 0x08
#define ARM_DS_ACTIVE BIT(2)
@@ -109,21 +106,9 @@ struct vchiq_arm_state {
int first_connect;
};
-struct vchiq_pagelist_info {
- struct pagelist *pagelist;
- size_t pagelist_buffer_size;
- dma_addr_t dma_addr;
- enum dma_data_direction dma_dir;
- unsigned int num_pages;
- unsigned int pages_need_release;
- struct page **pages;
- struct scatterlist *scatterlist;
- unsigned int scatterlist_mapped;
-};
-
static int
-vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle, void *data,
- unsigned int size, enum vchiq_bulk_dir dir);
+vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_bulk *bulk_params);
static irqreturn_t
vchiq_doorbell_irq(int irq, void *dev_id)
@@ -146,35 +131,6 @@ vchiq_doorbell_irq(int irq, void *dev_id)
return ret;
}
-static void
-cleanup_pagelistinfo(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo)
-{
- if (pagelistinfo->scatterlist_mapped) {
- dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist,
- pagelistinfo->num_pages, pagelistinfo->dma_dir);
- }
-
- if (pagelistinfo->pages_need_release)
- unpin_user_pages(pagelistinfo->pages, pagelistinfo->num_pages);
-
- dma_free_coherent(instance->state->dev, pagelistinfo->pagelist_buffer_size,
- pagelistinfo->pagelist, pagelistinfo->dma_addr);
-}
-
-static inline bool
-is_adjacent_block(u32 *addrs, dma_addr_t addr, unsigned int k)
-{
- u32 tmp;
-
- if (!k)
- return false;
-
- tmp = (addrs[k - 1] & PAGE_MASK) +
- (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT);
-
- return tmp == (addr & PAGE_MASK);
-}
-
/*
* This function is called by the vchiq stack once it has been connected to
* the videocore and clients can start to use the stack.
@@ -225,270 +181,6 @@ void vchiq_add_connected_callback(struct vchiq_device *device, void (*callback)(
}
EXPORT_SYMBOL(vchiq_add_connected_callback);
-/* There is a potential problem with partial cache lines (pages?)
- * at the ends of the block when reading. If the CPU accessed anything in
- * the same line (page?) then it may have pulled old data into the cache,
- * obscuring the new data underneath. We can solve this by transferring the
- * partial cache lines separately, and allowing the ARM to copy into the
- * cached area.
- */
-
-static struct vchiq_pagelist_info *
-create_pagelist(struct vchiq_instance *instance, char *buf, char __user *ubuf,
- size_t count, unsigned short type)
-{
- struct vchiq_drv_mgmt *drv_mgmt;
- struct pagelist *pagelist;
- struct vchiq_pagelist_info *pagelistinfo;
- struct page **pages;
- u32 *addrs;
- unsigned int num_pages, offset, i, k;
- int actual_pages;
- size_t pagelist_size;
- struct scatterlist *scatterlist, *sg;
- int dma_buffers;
- dma_addr_t dma_addr;
-
- if (count >= INT_MAX - PAGE_SIZE)
- return NULL;
-
- drv_mgmt = dev_get_drvdata(instance->state->dev);
-
- if (buf)
- offset = (uintptr_t)buf & (PAGE_SIZE - 1);
- else
- offset = (uintptr_t)ubuf & (PAGE_SIZE - 1);
- num_pages = DIV_ROUND_UP(count + offset, PAGE_SIZE);
-
- if ((size_t)num_pages > (SIZE_MAX - sizeof(struct pagelist) -
- sizeof(struct vchiq_pagelist_info)) /
- (sizeof(u32) + sizeof(pages[0]) +
- sizeof(struct scatterlist)))
- return NULL;
-
- pagelist_size = sizeof(struct pagelist) +
- (num_pages * sizeof(u32)) +
- (num_pages * sizeof(pages[0]) +
- (num_pages * sizeof(struct scatterlist))) +
- sizeof(struct vchiq_pagelist_info);
-
- /* Allocate enough storage to hold the page pointers and the page
- * list
- */
- pagelist = dma_alloc_coherent(instance->state->dev, pagelist_size, &dma_addr,
- GFP_KERNEL);
-
- dev_dbg(instance->state->dev, "arm: %pK\n", pagelist);
-
- if (!pagelist)
- return NULL;
-
- addrs = pagelist->addrs;
- pages = (struct page **)(addrs + num_pages);
- scatterlist = (struct scatterlist *)(pages + num_pages);
- pagelistinfo = (struct vchiq_pagelist_info *)
- (scatterlist + num_pages);
-
- pagelist->length = count;
- pagelist->type = type;
- pagelist->offset = offset;
-
- /* Populate the fields of the pagelistinfo structure */
- pagelistinfo->pagelist = pagelist;
- pagelistinfo->pagelist_buffer_size = pagelist_size;
- pagelistinfo->dma_addr = dma_addr;
- pagelistinfo->dma_dir = (type == PAGELIST_WRITE) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE;
- pagelistinfo->num_pages = num_pages;
- pagelistinfo->pages_need_release = 0;
- pagelistinfo->pages = pages;
- pagelistinfo->scatterlist = scatterlist;
- pagelistinfo->scatterlist_mapped = 0;
-
- if (buf) {
- unsigned long length = count;
- unsigned int off = offset;
-
- for (actual_pages = 0; actual_pages < num_pages;
- actual_pages++) {
- struct page *pg =
- vmalloc_to_page((buf +
- (actual_pages * PAGE_SIZE)));
- size_t bytes = PAGE_SIZE - off;
-
- if (!pg) {
- cleanup_pagelistinfo(instance, pagelistinfo);
- return NULL;
- }
-
- if (bytes > length)
- bytes = length;
- pages[actual_pages] = pg;
- length -= bytes;
- off = 0;
- }
- /* do not try and release vmalloc pages */
- } else {
- actual_pages = pin_user_pages_fast((unsigned long)ubuf & PAGE_MASK, num_pages,
- type == PAGELIST_READ, pages);
-
- if (actual_pages != num_pages) {
- dev_dbg(instance->state->dev, "arm: Only %d/%d pages locked\n",
- actual_pages, num_pages);
-
- /* This is probably due to the process being killed */
- if (actual_pages > 0)
- unpin_user_pages(pages, actual_pages);
- cleanup_pagelistinfo(instance, pagelistinfo);
- return NULL;
- }
- /* release user pages */
- pagelistinfo->pages_need_release = 1;
- }
-
- /*
- * Initialize the scatterlist so that the magic cookie
- * is filled if debugging is enabled
- */
- sg_init_table(scatterlist, num_pages);
- /* Now set the pages for each scatterlist */
- for (i = 0; i < num_pages; i++) {
- unsigned int len = PAGE_SIZE - offset;
-
- if (len > count)
- len = count;
- sg_set_page(scatterlist + i, pages[i], len, offset);
- offset = 0;
- count -= len;
- }
-
- dma_buffers = dma_map_sg(instance->state->dev,
- scatterlist,
- num_pages,
- pagelistinfo->dma_dir);
-
- if (dma_buffers == 0) {
- cleanup_pagelistinfo(instance, pagelistinfo);
- return NULL;
- }
-
- pagelistinfo->scatterlist_mapped = 1;
-
- /* Combine adjacent blocks for performance */
- k = 0;
- for_each_sg(scatterlist, sg, dma_buffers, i) {
- unsigned int len = sg_dma_len(sg);
- dma_addr_t addr = sg_dma_address(sg);
-
- /* Note: addrs is the address + page_count - 1
- * The firmware expects blocks after the first to be page-
- * aligned and a multiple of the page size
- */
- WARN_ON(len == 0);
- WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
- WARN_ON(i && (addr & ~PAGE_MASK));
- if (is_adjacent_block(addrs, addr, k))
- addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
- else
- addrs[k++] = (addr & PAGE_MASK) |
- (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
- }
-
- /* Partial cache lines (fragments) require special measures */
- if ((type == PAGELIST_READ) &&
- ((pagelist->offset & (drv_mgmt->info->cache_line_size - 1)) ||
- ((pagelist->offset + pagelist->length) &
- (drv_mgmt->info->cache_line_size - 1)))) {
- char *fragments;
-
- if (down_interruptible(&drv_mgmt->free_fragments_sema)) {
- cleanup_pagelistinfo(instance, pagelistinfo);
- return NULL;
- }
-
- WARN_ON(!drv_mgmt->free_fragments);
-
- down(&drv_mgmt->free_fragments_mutex);
- fragments = drv_mgmt->free_fragments;
- WARN_ON(!fragments);
- drv_mgmt->free_fragments = *(char **)drv_mgmt->free_fragments;
- up(&drv_mgmt->free_fragments_mutex);
- pagelist->type = PAGELIST_READ_WITH_FRAGMENTS +
- (fragments - drv_mgmt->fragments_base) / drv_mgmt->fragments_size;
- }
-
- return pagelistinfo;
-}
-
-static void
-free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo,
- int actual)
-{
- struct vchiq_drv_mgmt *drv_mgmt;
- struct pagelist *pagelist = pagelistinfo->pagelist;
- struct page **pages = pagelistinfo->pages;
- unsigned int num_pages = pagelistinfo->num_pages;
-
- dev_dbg(instance->state->dev, "arm: %pK, %d\n", pagelistinfo->pagelist, actual);
-
- drv_mgmt = dev_get_drvdata(instance->state->dev);
-
- /*
- * NOTE: dma_unmap_sg must be called before the
- * cpu can touch any of the data/pages.
- */
- dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist,
- pagelistinfo->num_pages, pagelistinfo->dma_dir);
- pagelistinfo->scatterlist_mapped = 0;
-
- /* Deal with any partial cache lines (fragments) */
- if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS && drv_mgmt->fragments_base) {
- char *fragments = drv_mgmt->fragments_base +
- (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) *
- drv_mgmt->fragments_size;
- int head_bytes, tail_bytes;
-
- head_bytes = (drv_mgmt->info->cache_line_size - pagelist->offset) &
- (drv_mgmt->info->cache_line_size - 1);
- tail_bytes = (pagelist->offset + actual) &
- (drv_mgmt->info->cache_line_size - 1);
-
- if ((actual >= 0) && (head_bytes != 0)) {
- if (head_bytes > actual)
- head_bytes = actual;
-
- memcpy_to_page(pages[0],
- pagelist->offset,
- fragments,
- head_bytes);
- }
- if ((actual >= 0) && (head_bytes < actual) &&
- (tail_bytes != 0))
- memcpy_to_page(pages[num_pages - 1],
- (pagelist->offset + actual) &
- (PAGE_SIZE - 1) & ~(drv_mgmt->info->cache_line_size - 1),
- fragments + drv_mgmt->info->cache_line_size,
- tail_bytes);
-
- down(&drv_mgmt->free_fragments_mutex);
- *(char **)fragments = drv_mgmt->free_fragments;
- drv_mgmt->free_fragments = fragments;
- up(&drv_mgmt->free_fragments_mutex);
- up(&drv_mgmt->free_fragments_sema);
- }
-
- /* Need to mark all the pages dirty. */
- if (pagelist->type != PAGELIST_WRITE &&
- pagelistinfo->pages_need_release) {
- unsigned int i;
-
- for (i = 0; i < num_pages; i++)
- set_page_dirty(pages[i]);
- }
-
- cleanup_pagelistinfo(instance, pagelistinfo);
-}
-
static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
{
struct device *dev = &pdev->dev;
@@ -616,58 +308,6 @@ static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state *
return (struct vchiq_arm_state *)state->platform_state;
}
-void
-remote_event_signal(struct vchiq_state *state, struct remote_event *event)
-{
- struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(state->dev);
-
- /*
- * Ensure that all writes to shared data structures have completed
- * before signalling the peer.
- */
- wmb();
-
- event->fired = 1;
-
- dsb(sy); /* data barrier operation */
-
- if (event->armed)
- writel(0, mgmt->regs + BELL2); /* trigger vc interrupt */
-}
-
-int
-vchiq_prepare_bulk_data(struct vchiq_instance *instance, struct vchiq_bulk *bulk, void *offset,
- void __user *uoffset, int size, int dir)
-{
- struct vchiq_pagelist_info *pagelistinfo;
-
- pagelistinfo = create_pagelist(instance, offset, uoffset, size,
- (dir == VCHIQ_BULK_RECEIVE)
- ? PAGELIST_READ
- : PAGELIST_WRITE);
-
- if (!pagelistinfo)
- return -ENOMEM;
-
- bulk->data = pagelistinfo->dma_addr;
-
- /*
- * Store the pagelistinfo address in remote_data,
- * which isn't used by the slave.
- */
- bulk->remote_data = pagelistinfo;
-
- return 0;
-}
-
-void
-vchiq_complete_bulk(struct vchiq_instance *instance, struct vchiq_bulk *bulk)
-{
- if (bulk && bulk->remote_data && bulk->actual)
- free_pagelist(instance, (struct vchiq_pagelist_info *)bulk->remote_data,
- bulk->actual);
-}
-
void vchiq_dump_platform_state(struct seq_file *f)
{
seq_puts(f, " Platform: 2835 (VC master)\n");
@@ -851,34 +491,31 @@ int
vchiq_bulk_transmit(struct vchiq_instance *instance, unsigned int handle, const void *data,
unsigned int size, void *userdata, enum vchiq_bulk_mode mode)
{
+ struct vchiq_bulk bulk_params = {};
int ret;
- while (1) {
- switch (mode) {
- case VCHIQ_BULK_MODE_NOCALLBACK:
- case VCHIQ_BULK_MODE_CALLBACK:
- ret = vchiq_bulk_xfer_callback_interruptible(instance, handle,
- (void *)data, NULL,
- size, mode, userdata,
- VCHIQ_BULK_TRANSMIT);
- break;
- case VCHIQ_BULK_MODE_BLOCKING:
- ret = vchiq_blocking_bulk_transfer(instance, handle, (void *)data, size,
- VCHIQ_BULK_TRANSMIT);
- break;
- default:
- return -EINVAL;
- }
-
- /*
- * vchiq_*_bulk_transfer() may return -EAGAIN, so we need
- * to implement a retry mechanism since this function is
- * supposed to block until queued
- */
- if (ret != -EAGAIN)
- break;
-
- msleep(1);
+ switch (mode) {
+ case VCHIQ_BULK_MODE_NOCALLBACK:
+ case VCHIQ_BULK_MODE_CALLBACK:
+
+ bulk_params.offset = (void *)data;
+ bulk_params.mode = mode;
+ bulk_params.size = size;
+ bulk_params.cb_data = userdata;
+ bulk_params.dir = VCHIQ_BULK_TRANSMIT;
+
+ ret = vchiq_bulk_xfer_callback(instance, handle, &bulk_params);
+ break;
+ case VCHIQ_BULK_MODE_BLOCKING:
+ bulk_params.offset = (void *)data;
+ bulk_params.mode = mode;
+ bulk_params.size = size;
+ bulk_params.dir = VCHIQ_BULK_TRANSMIT;
+
+ ret = vchiq_blocking_bulk_transfer(instance, handle, &bulk_params);
+ break;
+ default:
+ return -EINVAL;
}
return ret;
@@ -889,34 +526,31 @@ int vchiq_bulk_receive(struct vchiq_instance *instance, unsigned int handle,
void *data, unsigned int size, void *userdata,
enum vchiq_bulk_mode mode)
{
+ struct vchiq_bulk bulk_params = {};
int ret;
- while (1) {
- switch (mode) {
- case VCHIQ_BULK_MODE_NOCALLBACK:
- case VCHIQ_BULK_MODE_CALLBACK:
- ret = vchiq_bulk_xfer_callback_interruptible(instance, handle,
- (void *)data, NULL,
- size, mode, userdata,
- VCHIQ_BULK_RECEIVE);
- break;
- case VCHIQ_BULK_MODE_BLOCKING:
- ret = vchiq_blocking_bulk_transfer(instance, handle, (void *)data, size,
- VCHIQ_BULK_RECEIVE);
- break;
- default:
- return -EINVAL;
- }
-
- /*
- * vchiq_*_bulk_transfer() may return -EAGAIN, so we need
- * to implement a retry mechanism since this function is
- * supposed to block until queued
- */
- if (ret != -EAGAIN)
- break;
-
- msleep(1);
+ switch (mode) {
+ case VCHIQ_BULK_MODE_NOCALLBACK:
+ case VCHIQ_BULK_MODE_CALLBACK:
+
+ bulk_params.offset = (void *)data;
+ bulk_params.mode = mode;
+ bulk_params.size = size;
+ bulk_params.cb_data = userdata;
+ bulk_params.dir = VCHIQ_BULK_RECEIVE;
+
+ ret = vchiq_bulk_xfer_callback(instance, handle, &bulk_params);
+ break;
+ case VCHIQ_BULK_MODE_BLOCKING:
+ bulk_params.offset = (void *)data;
+ bulk_params.mode = mode;
+ bulk_params.size = size;
+ bulk_params.dir = VCHIQ_BULK_RECEIVE;
+
+ ret = vchiq_blocking_bulk_transfer(instance, handle, &bulk_params);
+ break;
+ default:
+ return -EINVAL;
}
return ret;
@@ -924,8 +558,8 @@ int vchiq_bulk_receive(struct vchiq_instance *instance, unsigned int handle,
EXPORT_SYMBOL(vchiq_bulk_receive);
static int
-vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle, void *data,
- unsigned int size, enum vchiq_bulk_dir dir)
+vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_bulk *bulk_params)
{
struct vchiq_service *service;
struct bulk_waiter_node *waiter = NULL, *iter;
@@ -953,13 +587,14 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl
if (bulk) {
/* This thread has an outstanding bulk transfer. */
/* FIXME: why compare a dma address to a pointer? */
- if ((bulk->data != (dma_addr_t)(uintptr_t)data) || (bulk->size != size)) {
+ if ((bulk->dma_addr != (dma_addr_t)(uintptr_t)bulk_params->dma_addr) ||
+ (bulk->size != bulk_params->size)) {
/*
* This is not a retry of the previous one.
* Cancel the signal when the transfer completes.
*/
spin_lock(&service->state->bulk_waiter_spinlock);
- bulk->userdata = NULL;
+ bulk->waiter = NULL;
spin_unlock(&service->state->bulk_waiter_spinlock);
}
}
@@ -969,15 +604,16 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl
return -ENOMEM;
}
- ret = vchiq_bulk_xfer_blocking_interruptible(instance, handle, data, NULL, size,
- &waiter->bulk_waiter, dir);
+ bulk_params->waiter = &waiter->bulk_waiter;
+
+ ret = vchiq_bulk_xfer_blocking(instance, handle, bulk_params);
if ((ret != -EAGAIN) || fatal_signal_pending(current) || !waiter->bulk_waiter.bulk) {
struct vchiq_bulk *bulk = waiter->bulk_waiter.bulk;
if (bulk) {
/* Cancel the signal when the transfer completes. */
spin_lock(&service->state->bulk_waiter_spinlock);
- bulk->userdata = NULL;
+ bulk->waiter = NULL;
spin_unlock(&service->state->bulk_waiter_spinlock);
}
kfree(waiter);
@@ -996,7 +632,7 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl
static int
add_completion(struct vchiq_instance *instance, enum vchiq_reason reason,
struct vchiq_header *header, struct user_service *user_service,
- void *bulk_userdata)
+ void *cb_data, void __user *cb_userdata)
{
struct vchiq_completion_data_kernel *completion;
struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(instance->state->dev);
@@ -1026,7 +662,8 @@ add_completion(struct vchiq_instance *instance, enum vchiq_reason reason,
completion->reason = reason;
/* N.B. service_userdata is updated while processing AWAIT_COMPLETION */
completion->service_userdata = user_service->service;
- completion->bulk_userdata = bulk_userdata;
+ completion->cb_data = cb_data;
+ completion->cb_userdata = cb_userdata;
if (reason == VCHIQ_SERVICE_CLOSED) {
/*
@@ -1057,8 +694,8 @@ add_completion(struct vchiq_instance *instance, enum vchiq_reason reason,
static int
service_single_message(struct vchiq_instance *instance,
- enum vchiq_reason reason,
- struct vchiq_service *service, void *bulk_userdata)
+ enum vchiq_reason reason, struct vchiq_service *service,
+ void *cb_data, void __user *cb_userdata)
{
struct user_service *user_service;
@@ -1076,7 +713,7 @@ service_single_message(struct vchiq_instance *instance,
dev_dbg(instance->state->dev,
"arm: Inserting extra MESSAGE_AVAILABLE\n");
ret = add_completion(instance, reason, NULL, user_service,
- bulk_userdata);
+ cb_data, cb_userdata);
if (ret)
return ret;
}
@@ -1094,7 +731,8 @@ service_single_message(struct vchiq_instance *instance,
int
service_callback(struct vchiq_instance *instance, enum vchiq_reason reason,
- struct vchiq_header *header, unsigned int handle, void *bulk_userdata)
+ struct vchiq_header *header, unsigned int handle,
+ void *cb_data, void __user *cb_userdata)
{
/*
* How do we ensure the callback goes to the right client?
@@ -1133,9 +771,9 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason,
rcu_read_unlock();
dev_dbg(service->state->dev,
- "arm: service %p(%d,%p), reason %d, header %p, instance %p, bulk_userdata %p\n",
+ "arm: service %p(%d,%p), reason %d, header %p, instance %p, cb_data %p, cb_userdata %p\n",
user_service, service->localport, user_service->userdata,
- reason, header, instance, bulk_userdata);
+ reason, header, instance, cb_data, cb_userdata);
if (header && user_service->is_vchi) {
spin_lock(&service->state->msg_queue_spinlock);
@@ -1147,8 +785,8 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason,
DEBUG_TRACE(SERVICE_CALLBACK_LINE);
DEBUG_COUNT(MSG_QUEUE_FULL_COUNT);
- ret = service_single_message(instance, reason,
- service, bulk_userdata);
+ ret = service_single_message(instance, reason, service,
+ cb_data, cb_userdata);
if (ret) {
DEBUG_TRACE(SERVICE_CALLBACK_LINE);
vchiq_service_put(service);
@@ -1186,7 +824,7 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason,
return 0;
return add_completion(instance, reason, header, user_service,
- bulk_userdata);
+ cb_data, cb_userdata);
}
void vchiq_dump_platform_instances(struct vchiq_state *state, struct seq_file *f)
@@ -1273,7 +911,8 @@ static int
vchiq_keepalive_vchiq_callback(struct vchiq_instance *instance,
enum vchiq_reason reason,
struct vchiq_header *header,
- unsigned int service_user, void *bulk_user)
+ unsigned int service_user,
+ void *cb_data, void __user *cb_userdata)
{
dev_err(instance->state->dev, "suspend: %s: callback reason %d\n",
__func__, reason);
@@ -1715,7 +1354,6 @@ MODULE_DEVICE_TABLE(of, vchiq_of_match);
static int vchiq_probe(struct platform_device *pdev)
{
- struct device_node *fw_node;
const struct vchiq_platform_info *info;
struct vchiq_drv_mgmt *mgmt;
int ret;
@@ -1724,8 +1362,8 @@ static int vchiq_probe(struct platform_device *pdev)
if (!info)
return -EINVAL;
- fw_node = of_find_compatible_node(NULL, NULL,
- "raspberrypi,bcm2835-firmware");
+ struct device_node *fw_node __free(device_node) =
+ of_find_compatible_node(NULL, NULL, "raspberrypi,bcm2835-firmware");
if (!fw_node) {
dev_err(&pdev->dev, "Missing firmware node\n");
return -ENOENT;
@@ -1736,7 +1374,6 @@ static int vchiq_probe(struct platform_device *pdev)
return -ENOMEM;
mgmt->fw = devm_rpi_firmware_get(&pdev->dev, fw_node);
- of_node_put(fw_node);
if (!mgmt->fw)
return -EPROBE_DEFER;
@@ -1744,8 +1381,10 @@ static int vchiq_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mgmt);
ret = vchiq_platform_init(pdev, &mgmt->state);
- if (ret)
- goto failed_platform_init;
+ if (ret) {
+ dev_err(&pdev->dev, "arm: Could not initialize vchiq platform\n");
+ return ret;
+ }
vchiq_debugfs_init(&mgmt->state);
@@ -1759,18 +1398,13 @@ static int vchiq_probe(struct platform_device *pdev)
ret = vchiq_register_chrdev(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "arm: Failed to initialize vchiq cdev\n");
- goto error_exit;
+ return ret;
}
bcm2835_audio = vchiq_device_register(&pdev->dev, "bcm2835-audio");
bcm2835_camera = vchiq_device_register(&pdev->dev, "bcm2835-camera");
return 0;
-
-failed_platform_init:
- dev_err(&pdev->dev, "arm: Could not initialize vchiq platform\n");
-error_exit:
- return ret;
}
static void vchiq_remove(struct platform_device *pdev)
@@ -1797,7 +1431,7 @@ static struct platform_driver vchiq_driver = {
.of_match_table = vchiq_of_match,
},
.probe = vchiq_probe,
- .remove_new = vchiq_remove,
+ .remove = vchiq_remove,
};
static int __init vchiq_driver_init(void)
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
index b402aac333d9..e32b02f99024 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
@@ -155,7 +155,8 @@ static inline int vchiq_register_chrdev(struct device *parent) { return 0; }
extern int
service_callback(struct vchiq_instance *vchiq_instance, enum vchiq_reason reason,
- struct vchiq_header *header, unsigned int handle, void *bulk_userdata);
+ struct vchiq_header *header, unsigned int handle,
+ void *cb_data, void __user *cb_userdata);
extern void
free_bulk_waiter(struct vchiq_instance *instance);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
index 1f94db6e0cd9..8d5795db4f39 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -5,6 +5,8 @@
#include <linux/completion.h>
#include <linux/mutex.h>
#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/highmem.h>
#include <linux/kthread.h>
#include <linux/wait.h>
#include <linux/delay.h>
@@ -61,12 +63,16 @@
#define MAKE_REMOTE_USE (VCHIQ_MSG_REMOTE_USE << TYPE_SHIFT)
#define MAKE_REMOTE_USE_ACTIVE (VCHIQ_MSG_REMOTE_USE_ACTIVE << TYPE_SHIFT)
+#define PAGELIST_WRITE 0
+#define PAGELIST_READ 1
+#define PAGELIST_READ_WITH_FRAGMENTS 2
+
+#define BELL2 0x08
+
/* Ensure the fields are wide enough */
-static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX))
- == 0);
+static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX)) == 0);
static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0);
-static_assert((unsigned int)VCHIQ_PORT_MAX <
- (unsigned int)VCHIQ_PORT_FREE);
+static_assert((unsigned int)VCHIQ_PORT_MAX < (unsigned int)VCHIQ_PORT_FREE);
#define VCHIQ_MSGID_PADDING VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING, 0, 0)
#define VCHIQ_MSGID_CLAIMED 0x40000000
@@ -449,15 +455,26 @@ mark_service_closing(struct vchiq_service *service)
static inline int
make_service_callback(struct vchiq_service *service, enum vchiq_reason reason,
- struct vchiq_header *header, void *bulk_userdata)
+ struct vchiq_header *header, struct vchiq_bulk *bulk)
{
+ void *cb_data = NULL;
+ void __user *cb_userdata = NULL;
int status;
- dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %pK, %pK)\n",
+ /*
+ * If a bulk transfer is in progress, pass bulk->cb_*data to the
+ * callback function.
+ */
+ if (bulk) {
+ cb_data = bulk->cb_data;
+ cb_userdata = bulk->cb_userdata;
+ }
+
+ dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %pK, %pK %pK)\n",
service->state->id, service->localport, reason_names[reason],
- header, bulk_userdata);
+ header, cb_data, cb_userdata);
status = service->base.callback(service->instance, reason, header, service->handle,
- bulk_userdata);
+ cb_data, cb_userdata);
if (status && (status != -EAGAIN)) {
dev_warn(service->state->dev,
"core: %d: ignoring ERROR from callback to service %x\n",
@@ -526,6 +543,25 @@ remote_event_wait(wait_queue_head_t *wq, struct remote_event *event)
return ret;
}
+static void
+remote_event_signal(struct vchiq_state *state, struct remote_event *event)
+{
+ struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(state->dev);
+
+ /*
+ * Ensure that all writes to shared data structures have completed
+ * before signalling the peer.
+ */
+ wmb();
+
+ event->fired = 1;
+
+ dsb(sy); /* data barrier operation */
+
+ if (event->armed)
+ writel(0, mgmt->regs + BELL2); /* trigger vc interrupt */
+}
+
/*
* Acknowledge that the event has been signalled, and wake any waiters. Usually
* called as a result of the doorbell being rung.
@@ -911,6 +947,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
struct vchiq_service_quota *quota = NULL;
struct vchiq_header *header;
int type = VCHIQ_MSG_TYPE(msgid);
+ int svc_fourcc;
size_t stride;
@@ -922,7 +959,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
if (!(flags & QMFLAGS_NO_MUTEX_LOCK) &&
mutex_lock_killable(&state->slot_mutex))
- return -EAGAIN;
+ return -EINTR;
if (type == VCHIQ_MSG_DATA) {
int tx_end_index;
@@ -962,8 +999,8 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
spin_unlock(&state->quota_spinlock);
mutex_unlock(&state->slot_mutex);
- if (wait_for_completion_interruptible(&state->data_quota_event))
- return -EAGAIN;
+ if (wait_for_completion_killable(&state->data_quota_event))
+ return -EINTR;
mutex_lock(&state->slot_mutex);
spin_lock(&state->quota_spinlock);
@@ -986,12 +1023,12 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
quota->message_use_count, quota->slot_use_count);
VCHIQ_SERVICE_STATS_INC(service, quota_stalls);
mutex_unlock(&state->slot_mutex);
- if (wait_for_completion_interruptible(&quota->quota_event))
- return -EAGAIN;
+ if (wait_for_completion_killable(&quota->quota_event))
+ return -EINTR;
if (service->closing)
return -EHOSTDOWN;
if (mutex_lock_killable(&state->slot_mutex))
- return -EAGAIN;
+ return -EINTR;
if (service->srvstate != VCHIQ_SRVSTATE_OPEN) {
/* The service has been closed */
mutex_unlock(&state->slot_mutex);
@@ -1103,17 +1140,13 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
header->msgid = msgid;
header->size = size;
- {
- int svc_fourcc;
-
- svc_fourcc = service
- ? service->base.fourcc
- : VCHIQ_MAKE_FOURCC('?', '?', '?', '?');
+ svc_fourcc = service ? service->base.fourcc
+ : VCHIQ_MAKE_FOURCC('?', '?', '?', '?');
- dev_dbg(state->dev, "core_msg: Sent Msg %s(%u) to %p4cc s:%u d:%d len:%zu\n",
- msg_type_str(VCHIQ_MSG_TYPE(msgid)), VCHIQ_MSG_TYPE(msgid),
- &svc_fourcc, VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid), size);
- }
+ dev_dbg(state->dev, "core_msg: Sent Msg %s(%u) to %p4cc s:%u d:%d len:%zu\n",
+ msg_type_str(VCHIQ_MSG_TYPE(msgid)),
+ VCHIQ_MSG_TYPE(msgid), &svc_fourcc,
+ VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid), size);
/* Make sure the new header is visible to the peer. */
wmb();
@@ -1175,9 +1208,8 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service,
state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size,
VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid));
- callback_result =
- copy_message_data(copy_callback, context,
- header->data, size);
+ callback_result = copy_message_data(copy_callback, context,
+ header->data, size);
if (callback_result < 0) {
mutex_unlock(&state->slot_mutex);
@@ -1288,6 +1320,42 @@ get_bulk_reason(struct vchiq_bulk *bulk)
return VCHIQ_BULK_RECEIVE_DONE;
}
+static int service_notify_bulk(struct vchiq_service *service,
+ struct vchiq_bulk *bulk)
+{
+ if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) {
+ if (bulk->dir == VCHIQ_BULK_TRANSMIT) {
+ VCHIQ_SERVICE_STATS_INC(service, bulk_tx_count);
+ VCHIQ_SERVICE_STATS_ADD(service, bulk_tx_bytes,
+ bulk->actual);
+ } else {
+ VCHIQ_SERVICE_STATS_INC(service, bulk_rx_count);
+ VCHIQ_SERVICE_STATS_ADD(service, bulk_rx_bytes,
+ bulk->actual);
+ }
+ } else {
+ VCHIQ_SERVICE_STATS_INC(service, bulk_aborted_count);
+ }
+
+ if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) {
+ struct bulk_waiter *waiter;
+
+ spin_lock(&service->state->bulk_waiter_spinlock);
+ waiter = bulk->waiter;
+ if (waiter) {
+ waiter->actual = bulk->actual;
+ complete(&waiter->event);
+ }
+ spin_unlock(&service->state->bulk_waiter_spinlock);
+ } else if (bulk->mode == VCHIQ_BULK_MODE_CALLBACK) {
+ enum vchiq_reason reason = get_bulk_reason(bulk);
+
+ return make_service_callback(service, reason, NULL, bulk);
+ }
+
+ return 0;
+}
+
/* Called by the slot handler - don't hold the bulk mutex */
static int
notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue,
@@ -1311,38 +1379,10 @@ notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue,
* Only generate callbacks for non-dummy bulk
* requests, and non-terminated services
*/
- if (bulk->data && service->instance) {
- if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) {
- if (bulk->dir == VCHIQ_BULK_TRANSMIT) {
- VCHIQ_SERVICE_STATS_INC(service, bulk_tx_count);
- VCHIQ_SERVICE_STATS_ADD(service, bulk_tx_bytes,
- bulk->actual);
- } else {
- VCHIQ_SERVICE_STATS_INC(service, bulk_rx_count);
- VCHIQ_SERVICE_STATS_ADD(service, bulk_rx_bytes,
- bulk->actual);
- }
- } else {
- VCHIQ_SERVICE_STATS_INC(service, bulk_aborted_count);
- }
- if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) {
- struct bulk_waiter *waiter;
-
- spin_lock(&service->state->bulk_waiter_spinlock);
- waiter = bulk->userdata;
- if (waiter) {
- waiter->actual = bulk->actual;
- complete(&waiter->event);
- }
- spin_unlock(&service->state->bulk_waiter_spinlock);
- } else if (bulk->mode == VCHIQ_BULK_MODE_CALLBACK) {
- enum vchiq_reason reason =
- get_bulk_reason(bulk);
- status = make_service_callback(service, reason, NULL,
- bulk->userdata);
- if (status == -EAGAIN)
- break;
- }
+ if (bulk->dma_addr && service->instance) {
+ status = service_notify_bulk(service, bulk);
+ if (status == -EAGAIN)
+ break;
}
queue->remove++;
@@ -1415,6 +1455,331 @@ poll_services(struct vchiq_state *state)
poll_services_of_group(state, group);
}
+static void
+cleanup_pagelistinfo(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo)
+{
+ if (pagelistinfo->scatterlist_mapped) {
+ dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist,
+ pagelistinfo->num_pages, pagelistinfo->dma_dir);
+ }
+
+ if (pagelistinfo->pages_need_release)
+ unpin_user_pages(pagelistinfo->pages, pagelistinfo->num_pages);
+
+ dma_free_coherent(instance->state->dev, pagelistinfo->pagelist_buffer_size,
+ pagelistinfo->pagelist, pagelistinfo->dma_addr);
+}
+
+static inline bool
+is_adjacent_block(u32 *addrs, dma_addr_t addr, unsigned int k)
+{
+ u32 tmp;
+
+ if (!k)
+ return false;
+
+ tmp = (addrs[k - 1] & PAGE_MASK) +
+ (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT);
+
+ return tmp == (addr & PAGE_MASK);
+}
+
+/* There is a potential problem with partial cache lines (pages?)
+ * at the ends of the block when reading. If the CPU accessed anything in
+ * the same line (page?) then it may have pulled old data into the cache,
+ * obscuring the new data underneath. We can solve this by transferring the
+ * partial cache lines separately, and allowing the ARM to copy into the
+ * cached area.
+ */
+static struct vchiq_pagelist_info *
+create_pagelist(struct vchiq_instance *instance, struct vchiq_bulk *bulk)
+{
+ struct vchiq_drv_mgmt *drv_mgmt;
+ struct pagelist *pagelist;
+ struct vchiq_pagelist_info *pagelistinfo;
+ struct page **pages;
+ u32 *addrs;
+ unsigned int num_pages, offset, i, k;
+ int actual_pages;
+ size_t pagelist_size;
+ struct scatterlist *scatterlist, *sg;
+ int dma_buffers;
+ unsigned int cache_line_size;
+ dma_addr_t dma_addr;
+ size_t count = bulk->size;
+ unsigned short type = (bulk->dir == VCHIQ_BULK_RECEIVE)
+ ? PAGELIST_READ : PAGELIST_WRITE;
+
+ if (count >= INT_MAX - PAGE_SIZE)
+ return NULL;
+
+ drv_mgmt = dev_get_drvdata(instance->state->dev);
+
+ if (bulk->offset)
+ offset = (uintptr_t)bulk->offset & (PAGE_SIZE - 1);
+ else
+ offset = (uintptr_t)bulk->uoffset & (PAGE_SIZE - 1);
+ num_pages = DIV_ROUND_UP(count + offset, PAGE_SIZE);
+
+ if ((size_t)num_pages > (SIZE_MAX - sizeof(struct pagelist) -
+ sizeof(struct vchiq_pagelist_info)) /
+ (sizeof(u32) + sizeof(pages[0]) +
+ sizeof(struct scatterlist)))
+ return NULL;
+
+ pagelist_size = sizeof(struct pagelist) +
+ (num_pages * sizeof(u32)) +
+ (num_pages * sizeof(pages[0]) +
+ (num_pages * sizeof(struct scatterlist))) +
+ sizeof(struct vchiq_pagelist_info);
+
+ /* Allocate enough storage to hold the page pointers and the page
+ * list
+ */
+ pagelist = dma_alloc_coherent(instance->state->dev, pagelist_size, &dma_addr,
+ GFP_KERNEL);
+
+ dev_dbg(instance->state->dev, "arm: %pK\n", pagelist);
+
+ if (!pagelist)
+ return NULL;
+
+ addrs = pagelist->addrs;
+ pages = (struct page **)(addrs + num_pages);
+ scatterlist = (struct scatterlist *)(pages + num_pages);
+ pagelistinfo = (struct vchiq_pagelist_info *)
+ (scatterlist + num_pages);
+
+ pagelist->length = count;
+ pagelist->type = type;
+ pagelist->offset = offset;
+
+ /* Populate the fields of the pagelistinfo structure */
+ pagelistinfo->pagelist = pagelist;
+ pagelistinfo->pagelist_buffer_size = pagelist_size;
+ pagelistinfo->dma_addr = dma_addr;
+ pagelistinfo->dma_dir = (type == PAGELIST_WRITE) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ pagelistinfo->num_pages = num_pages;
+ pagelistinfo->pages_need_release = 0;
+ pagelistinfo->pages = pages;
+ pagelistinfo->scatterlist = scatterlist;
+ pagelistinfo->scatterlist_mapped = 0;
+
+ if (bulk->offset) {
+ unsigned long length = count;
+ unsigned int off = offset;
+
+ for (actual_pages = 0; actual_pages < num_pages;
+ actual_pages++) {
+ struct page *pg =
+ vmalloc_to_page(((unsigned int *)bulk->offset +
+ (actual_pages * PAGE_SIZE)));
+ size_t bytes = PAGE_SIZE - off;
+
+ if (!pg) {
+ cleanup_pagelistinfo(instance, pagelistinfo);
+ return NULL;
+ }
+
+ if (bytes > length)
+ bytes = length;
+ pages[actual_pages] = pg;
+ length -= bytes;
+ off = 0;
+ }
+ /* do not try and release vmalloc pages */
+ } else {
+ actual_pages =
+ pin_user_pages_fast((unsigned long)bulk->uoffset & PAGE_MASK, num_pages,
+ type == PAGELIST_READ, pages);
+
+ if (actual_pages != num_pages) {
+ dev_dbg(instance->state->dev, "arm: Only %d/%d pages locked\n",
+ actual_pages, num_pages);
+
+ /* This is probably due to the process being killed */
+ if (actual_pages > 0)
+ unpin_user_pages(pages, actual_pages);
+ cleanup_pagelistinfo(instance, pagelistinfo);
+ return NULL;
+ }
+ /* release user pages */
+ pagelistinfo->pages_need_release = 1;
+ }
+
+ /*
+ * Initialize the scatterlist so that the magic cookie
+ * is filled if debugging is enabled
+ */
+ sg_init_table(scatterlist, num_pages);
+ /* Now set the pages for each scatterlist */
+ for (i = 0; i < num_pages; i++) {
+ unsigned int len = PAGE_SIZE - offset;
+
+ if (len > count)
+ len = count;
+ sg_set_page(scatterlist + i, pages[i], len, offset);
+ offset = 0;
+ count -= len;
+ }
+
+ dma_buffers = dma_map_sg(instance->state->dev,
+ scatterlist,
+ num_pages,
+ pagelistinfo->dma_dir);
+
+ if (dma_buffers == 0) {
+ cleanup_pagelistinfo(instance, pagelistinfo);
+ return NULL;
+ }
+
+ pagelistinfo->scatterlist_mapped = 1;
+
+ /* Combine adjacent blocks for performance */
+ k = 0;
+ for_each_sg(scatterlist, sg, dma_buffers, i) {
+ unsigned int len = sg_dma_len(sg);
+ dma_addr_t addr = sg_dma_address(sg);
+
+ /* Note: addrs is the address + page_count - 1
+ * The firmware expects blocks after the first to be page-
+ * aligned and a multiple of the page size
+ */
+ WARN_ON(len == 0);
+ WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
+ WARN_ON(i && (addr & ~PAGE_MASK));
+ if (is_adjacent_block(addrs, addr, k))
+ addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
+ else
+ addrs[k++] = (addr & PAGE_MASK) |
+ (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
+ }
+
+ /* Partial cache lines (fragments) require special measures */
+ cache_line_size = drv_mgmt->info->cache_line_size;
+ if ((type == PAGELIST_READ) &&
+ ((pagelist->offset & (cache_line_size - 1)) ||
+ ((pagelist->offset + pagelist->length) & (cache_line_size - 1)))) {
+ char *fragments;
+
+ if (down_interruptible(&drv_mgmt->free_fragments_sema)) {
+ cleanup_pagelistinfo(instance, pagelistinfo);
+ return NULL;
+ }
+
+ WARN_ON(!drv_mgmt->free_fragments);
+
+ down(&drv_mgmt->free_fragments_mutex);
+ fragments = drv_mgmt->free_fragments;
+ WARN_ON(!fragments);
+ drv_mgmt->free_fragments = *(char **)drv_mgmt->free_fragments;
+ up(&drv_mgmt->free_fragments_mutex);
+ pagelist->type = PAGELIST_READ_WITH_FRAGMENTS +
+ (fragments - drv_mgmt->fragments_base) / drv_mgmt->fragments_size;
+ }
+
+ return pagelistinfo;
+}
+
+static void
+free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo,
+ int actual)
+{
+ struct vchiq_drv_mgmt *drv_mgmt;
+ struct pagelist *pagelist = pagelistinfo->pagelist;
+ struct page **pages = pagelistinfo->pages;
+ unsigned int num_pages = pagelistinfo->num_pages;
+ unsigned int cache_line_size;
+
+ dev_dbg(instance->state->dev, "arm: %pK, %d\n", pagelistinfo->pagelist, actual);
+
+ drv_mgmt = dev_get_drvdata(instance->state->dev);
+
+ /*
+ * NOTE: dma_unmap_sg must be called before the
+ * cpu can touch any of the data/pages.
+ */
+ dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist,
+ pagelistinfo->num_pages, pagelistinfo->dma_dir);
+ pagelistinfo->scatterlist_mapped = 0;
+
+ /* Deal with any partial cache lines (fragments) */
+ cache_line_size = drv_mgmt->info->cache_line_size;
+ if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS && drv_mgmt->fragments_base) {
+ char *fragments = drv_mgmt->fragments_base +
+ (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) *
+ drv_mgmt->fragments_size;
+ int head_bytes, tail_bytes;
+
+ head_bytes = (cache_line_size - pagelist->offset) &
+ (cache_line_size - 1);
+ tail_bytes = (pagelist->offset + actual) &
+ (cache_line_size - 1);
+
+ if ((actual >= 0) && (head_bytes != 0)) {
+ if (head_bytes > actual)
+ head_bytes = actual;
+
+ memcpy_to_page(pages[0], pagelist->offset,
+ fragments, head_bytes);
+ }
+ if ((actual >= 0) && (head_bytes < actual) &&
+ (tail_bytes != 0))
+ memcpy_to_page(pages[num_pages - 1],
+ (pagelist->offset + actual) &
+ (PAGE_SIZE - 1) & ~(cache_line_size - 1),
+ fragments + cache_line_size,
+ tail_bytes);
+
+ down(&drv_mgmt->free_fragments_mutex);
+ *(char **)fragments = drv_mgmt->free_fragments;
+ drv_mgmt->free_fragments = fragments;
+ up(&drv_mgmt->free_fragments_mutex);
+ up(&drv_mgmt->free_fragments_sema);
+ }
+
+ /* Need to mark all the pages dirty. */
+ if (pagelist->type != PAGELIST_WRITE &&
+ pagelistinfo->pages_need_release) {
+ unsigned int i;
+
+ for (i = 0; i < num_pages; i++)
+ set_page_dirty(pages[i]);
+ }
+
+ cleanup_pagelistinfo(instance, pagelistinfo);
+}
+
+static int
+vchiq_prepare_bulk_data(struct vchiq_instance *instance, struct vchiq_bulk *bulk)
+{
+ struct vchiq_pagelist_info *pagelistinfo;
+
+ pagelistinfo = create_pagelist(instance, bulk);
+
+ if (!pagelistinfo)
+ return -ENOMEM;
+
+ bulk->dma_addr = pagelistinfo->dma_addr;
+
+ /*
+ * Store the pagelistinfo address in remote_data,
+ * which isn't used by the slave.
+ */
+ bulk->remote_data = pagelistinfo;
+
+ return 0;
+}
+
+static void
+vchiq_complete_bulk(struct vchiq_instance *instance, struct vchiq_bulk *bulk)
+{
+ if (bulk && bulk->remote_data && bulk->actual)
+ free_pagelist(instance, (struct vchiq_pagelist_info *)bulk->remote_data,
+ bulk->actual);
+}
+
/* Called with the bulk_mutex held */
static void
abort_outstanding_bulks(struct vchiq_service *service,
@@ -1452,7 +1817,7 @@ abort_outstanding_bulks(struct vchiq_service *service,
service->remoteport, bulk->size, bulk->remote_size);
} else {
/* fabricate a matching dummy bulk */
- bulk->data = 0;
+ bulk->dma_addr = 0;
bulk->size = 0;
bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED;
bulk->dir = is_tx ? VCHIQ_BULK_TRANSMIT :
@@ -1468,8 +1833,10 @@ static int
parse_open(struct vchiq_state *state, struct vchiq_header *header)
{
const struct vchiq_open_payload *payload;
+ struct vchiq_openack_payload ack_payload;
struct vchiq_service *service = NULL;
int msgid, size;
+ int openack_id;
unsigned int localport, remoteport, fourcc;
short version, version_min;
@@ -1504,34 +1871,36 @@ parse_open(struct vchiq_state *state, struct vchiq_header *header)
}
service->peer_version = version;
- if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) {
- struct vchiq_openack_payload ack_payload = {
- service->version
- };
- int openack_id = MAKE_OPENACK(service->localport, remoteport);
+ if (service->srvstate != VCHIQ_SRVSTATE_LISTENING)
+ goto done;
- if (state->version_common <
- VCHIQ_VERSION_SYNCHRONOUS_MODE)
- service->sync = 0;
+ ack_payload.version = service->version;
+ openack_id = MAKE_OPENACK(service->localport, remoteport);
- /* Acknowledge the OPEN */
- if (service->sync) {
- if (queue_message_sync(state, NULL, openack_id, memcpy_copy_callback,
- &ack_payload, sizeof(ack_payload)) == -EAGAIN)
- goto bail_not_ready;
+ if (state->version_common < VCHIQ_VERSION_SYNCHRONOUS_MODE)
+ service->sync = 0;
- /* The service is now open */
- set_service_state(service, VCHIQ_SRVSTATE_OPENSYNC);
- } else {
- if (queue_message(state, NULL, openack_id, memcpy_copy_callback,
- &ack_payload, sizeof(ack_payload), 0) == -EAGAIN)
- goto bail_not_ready;
+ /* Acknowledge the OPEN */
+ if (service->sync) {
+ if (queue_message_sync(state, NULL, openack_id,
+ memcpy_copy_callback,
+ &ack_payload,
+ sizeof(ack_payload)) == -EAGAIN)
+ goto bail_not_ready;
- /* The service is now open */
- set_service_state(service, VCHIQ_SRVSTATE_OPEN);
- }
+ /* The service is now open */
+ set_service_state(service, VCHIQ_SRVSTATE_OPENSYNC);
+ } else {
+ if (queue_message(state, NULL, openack_id,
+ memcpy_copy_callback, &ack_payload,
+ sizeof(ack_payload), 0) == -EINTR)
+ goto bail_not_ready;
+
+ /* The service is now open */
+ set_service_state(service, VCHIQ_SRVSTATE_OPEN);
}
+done:
/* Success - the message has been dealt with */
vchiq_service_put(service);
return 1;
@@ -1539,7 +1908,7 @@ parse_open(struct vchiq_state *state, struct vchiq_header *header)
fail_open:
/* No available service, or an invalid request - send a CLOSE */
if (queue_message(state, NULL, MAKE_CLOSE(0, VCHIQ_MSG_SRCPORT(msgid)),
- NULL, NULL, 0, 0) == -EAGAIN)
+ NULL, NULL, 0, 0) == -EINTR)
goto bail_not_ready;
return 1;
@@ -1753,7 +2122,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
dev_dbg(state->dev, "core: %d: prs %s@%pK (%d->%d) %x@%pad\n",
state->id, msg_type_str(type), header, remoteport,
- localport, bulk->actual, &bulk->data);
+ localport, bulk->actual, &bulk->dma_addr);
dev_dbg(state->dev, "core: %d: prs:%d %cx li=%x ri=%x p=%x\n",
state->id, localport,
@@ -1786,7 +2155,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
if (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT) {
/* Send a PAUSE in response */
if (queue_message(state, NULL, MAKE_PAUSE, NULL, NULL, 0,
- QMFLAGS_NO_MUTEX_UNLOCK) == -EAGAIN)
+ QMFLAGS_NO_MUTEX_UNLOCK) == -EINTR)
goto bail_not_ready;
}
/* At this point slot_mutex is held */
@@ -1903,7 +2272,7 @@ handle_poll(struct vchiq_state *state)
case VCHIQ_CONNSTATE_PAUSING:
if (queue_message(state, NULL, MAKE_PAUSE, NULL, NULL, 0,
- QMFLAGS_NO_MUTEX_UNLOCK) != -EAGAIN) {
+ QMFLAGS_NO_MUTEX_UNLOCK) != -EINTR) {
vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSE_SENT);
} else {
/* Retry later */
@@ -1913,7 +2282,7 @@ handle_poll(struct vchiq_state *state)
case VCHIQ_CONNSTATE_RESUMING:
if (queue_message(state, NULL, MAKE_RESUME, NULL, NULL, 0,
- QMFLAGS_NO_MUTEX_LOCK) != -EAGAIN) {
+ QMFLAGS_NO_MUTEX_LOCK) != -EINTR) {
vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
} else {
/*
@@ -2662,56 +3031,58 @@ close_service_complete(struct vchiq_service *service, int failstate)
* returned to user context.
*/
static int
-vchiq_bulk_xfer_queue_msg_interruptible(struct vchiq_service *service,
- void *offset, void __user *uoffset,
- int size, void *userdata,
- enum vchiq_bulk_mode mode,
- enum vchiq_bulk_dir dir)
+vchiq_bulk_xfer_queue_msg_killable(struct vchiq_service *service,
+ struct vchiq_bulk *bulk_params)
{
struct vchiq_bulk_queue *queue;
struct bulk_waiter *bulk_waiter = NULL;
struct vchiq_bulk *bulk;
struct vchiq_state *state = service->state;
- const char dir_char = (dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r';
- const int dir_msgtype = (dir == VCHIQ_BULK_TRANSMIT) ?
+ const char dir_char = (bulk_params->dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r';
+ const int dir_msgtype = (bulk_params->dir == VCHIQ_BULK_TRANSMIT) ?
VCHIQ_MSG_BULK_TX : VCHIQ_MSG_BULK_RX;
int status = -EINVAL;
int payload[2];
- if (mode == VCHIQ_BULK_MODE_BLOCKING) {
- bulk_waiter = userdata;
+ if (bulk_params->mode == VCHIQ_BULK_MODE_BLOCKING) {
+ bulk_waiter = bulk_params->waiter;
init_completion(&bulk_waiter->event);
bulk_waiter->actual = 0;
bulk_waiter->bulk = NULL;
}
- queue = (dir == VCHIQ_BULK_TRANSMIT) ?
+ queue = (bulk_params->dir == VCHIQ_BULK_TRANSMIT) ?
&service->bulk_tx : &service->bulk_rx;
if (mutex_lock_killable(&service->bulk_mutex))
- return -EAGAIN;
+ return -EINTR;
if (queue->local_insert == queue->remove + VCHIQ_NUM_SERVICE_BULKS) {
VCHIQ_SERVICE_STATS_INC(service, bulk_stalls);
do {
mutex_unlock(&service->bulk_mutex);
- if (wait_for_completion_interruptible(&service->bulk_remove_event))
- return -EAGAIN;
+ if (wait_for_completion_killable(&service->bulk_remove_event))
+ return -EINTR;
if (mutex_lock_killable(&service->bulk_mutex))
- return -EAGAIN;
+ return -EINTR;
} while (queue->local_insert == queue->remove +
VCHIQ_NUM_SERVICE_BULKS);
}
bulk = &queue->bulks[BULK_INDEX(queue->local_insert)];
- bulk->mode = mode;
- bulk->dir = dir;
- bulk->userdata = userdata;
- bulk->size = size;
+ /* Initiliaze the 'bulk' slot with bulk parameters passed in. */
+ bulk->mode = bulk_params->mode;
+ bulk->dir = bulk_params->dir;
+ bulk->waiter = bulk_params->waiter;
+ bulk->cb_data = bulk_params->cb_data;
+ bulk->cb_userdata = bulk_params->cb_userdata;
+ bulk->size = bulk_params->size;
+ bulk->offset = bulk_params->offset;
+ bulk->uoffset = bulk_params->uoffset;
bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED;
- if (vchiq_prepare_bulk_data(service->instance, bulk, offset, uoffset, size, dir))
+ if (vchiq_prepare_bulk_data(service->instance, bulk))
goto unlock_error_exit;
/*
@@ -2722,21 +3093,21 @@ vchiq_bulk_xfer_queue_msg_interruptible(struct vchiq_service *service,
dev_dbg(state->dev, "core: %d: bt (%d->%d) %cx %x@%pad %pK\n",
state->id, service->localport, service->remoteport,
- dir_char, size, &bulk->data, userdata);
+ dir_char, bulk->size, &bulk->dma_addr, bulk->cb_data);
/*
* The slot mutex must be held when the service is being closed, so
* claim it here to ensure that isn't happening
*/
if (mutex_lock_killable(&state->slot_mutex)) {
- status = -EAGAIN;
+ status = -EINTR;
goto cancel_bulk_error_exit;
}
if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
goto unlock_both_error_exit;
- payload[0] = lower_32_bits(bulk->data);
+ payload[0] = lower_32_bits(bulk->dma_addr);
payload[1] = bulk->size;
status = queue_message(state,
NULL,
@@ -2761,13 +3132,13 @@ vchiq_bulk_xfer_queue_msg_interruptible(struct vchiq_service *service,
state->id, service->localport, dir_char, queue->local_insert,
queue->remote_insert, queue->process);
- if (bulk_waiter) {
- bulk_waiter->bulk = bulk;
- if (wait_for_completion_interruptible(&bulk_waiter->event))
- status = -EAGAIN;
- else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)
- status = -EINVAL;
- }
+ if (bulk_waiter) {
+ bulk_waiter->bulk = bulk;
+ if (wait_for_completion_killable(&bulk_waiter->event))
+ status = -EINTR;
+ else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)
+ status = -EINVAL;
+ }
return status;
@@ -2803,19 +3174,21 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd)
if (close_recvd) {
dev_err(state->dev, "core: (1) called in state %s\n",
srvstate_names[service->srvstate]);
- } else if (is_server) {
- if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) {
- status = -EINVAL;
- } else {
- service->client_id = 0;
- service->remoteport = VCHIQ_PORT_FREE;
- if (service->srvstate == VCHIQ_SRVSTATE_CLOSEWAIT)
- set_service_state(service, VCHIQ_SRVSTATE_LISTENING);
- }
- complete(&service->remove_event);
- } else {
+ break;
+ } else if (!is_server) {
vchiq_free_service_internal(service);
+ break;
+ }
+
+ if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) {
+ status = -EINVAL;
+ } else {
+ service->client_id = 0;
+ service->remoteport = VCHIQ_PORT_FREE;
+ if (service->srvstate == VCHIQ_SRVSTATE_CLOSEWAIT)
+ set_service_state(service, VCHIQ_SRVSTATE_LISTENING);
}
+ complete(&service->remove_event);
break;
case VCHIQ_SRVSTATE_OPENING:
if (close_recvd) {
@@ -2945,6 +3318,7 @@ int
vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instance)
{
struct vchiq_service *service;
+ int status = 0;
int i;
/* Find all services registered to this client and enable them. */
@@ -2956,9 +3330,10 @@ vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instanc
}
if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) {
- if (queue_message(state, NULL, MAKE_CONNECT, NULL, NULL, 0,
- QMFLAGS_IS_BLOCKING) == -EAGAIN)
- return -EAGAIN;
+ status = queue_message(state, NULL, MAKE_CONNECT, NULL, NULL, 0,
+ QMFLAGS_IS_BLOCKING);
+ if (status)
+ return status;
vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTING);
}
@@ -2971,7 +3346,7 @@ vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instanc
complete(&state->connect);
}
- return 0;
+ return status;
}
void
@@ -3105,12 +3480,10 @@ vchiq_remove_service(struct vchiq_instance *instance, unsigned int handle)
}
int
-vchiq_bulk_xfer_blocking_interruptible(struct vchiq_instance *instance, unsigned int handle,
- void *offset, void __user *uoffset, int size,
- void __user *userdata, enum vchiq_bulk_dir dir)
+vchiq_bulk_xfer_blocking(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_bulk *bulk_params)
{
struct vchiq_service *service = find_service_by_handle(instance, handle);
- enum vchiq_bulk_mode mode = VCHIQ_BULK_MODE_BLOCKING;
int status = -EINVAL;
if (!service)
@@ -3119,15 +3492,13 @@ vchiq_bulk_xfer_blocking_interruptible(struct vchiq_instance *instance, unsigned
if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
goto error_exit;
- if (!offset && !uoffset)
+ if (!bulk_params->offset && !bulk_params->uoffset)
goto error_exit;
if (vchiq_check_service(service))
goto error_exit;
-
- status = vchiq_bulk_xfer_queue_msg_interruptible(service, offset, uoffset, size,
- userdata, mode, dir);
+ status = vchiq_bulk_xfer_queue_msg_killable(service, bulk_params);
error_exit:
vchiq_service_put(service);
@@ -3136,10 +3507,8 @@ error_exit:
}
int
-vchiq_bulk_xfer_callback_interruptible(struct vchiq_instance *instance, unsigned int handle,
- void *offset, void __user *uoffset, int size,
- enum vchiq_bulk_mode mode, void *userdata,
- enum vchiq_bulk_dir dir)
+vchiq_bulk_xfer_callback(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_bulk *bulk_params)
{
struct vchiq_service *service = find_service_by_handle(instance, handle);
int status = -EINVAL;
@@ -3147,21 +3516,20 @@ vchiq_bulk_xfer_callback_interruptible(struct vchiq_instance *instance, unsigned
if (!service)
return -EINVAL;
- if (mode != VCHIQ_BULK_MODE_CALLBACK &&
- mode != VCHIQ_BULK_MODE_NOCALLBACK)
+ if (bulk_params->mode != VCHIQ_BULK_MODE_CALLBACK &&
+ bulk_params->mode != VCHIQ_BULK_MODE_NOCALLBACK)
goto error_exit;
if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
goto error_exit;
- if (!offset && !uoffset)
+ if (!bulk_params->offset && !bulk_params->uoffset)
goto error_exit;
if (vchiq_check_service(service))
goto error_exit;
- status = vchiq_bulk_xfer_queue_msg_interruptible(service, offset, uoffset,
- size, userdata, mode, dir);
+ status = vchiq_bulk_xfer_queue_msg_killable(service, bulk_params);
error_exit:
vchiq_service_put(service);
@@ -3175,8 +3543,8 @@ error_exit:
* and the call should be retried after being returned to user context.
*/
int
-vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance,
- unsigned int handle, struct bulk_waiter *userdata)
+vchiq_bulk_xfer_waiting(struct vchiq_instance *instance,
+ unsigned int handle, struct bulk_waiter *waiter)
{
struct vchiq_service *service = find_service_by_handle(instance, handle);
struct bulk_waiter *bulk_waiter;
@@ -3185,7 +3553,7 @@ vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance,
if (!service)
return -EINVAL;
- if (!userdata)
+ if (!waiter)
goto error_exit;
if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
@@ -3194,14 +3562,14 @@ vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance,
if (vchiq_check_service(service))
goto error_exit;
- bulk_waiter = userdata;
+ bulk_waiter = waiter;
vchiq_service_put(service);
status = 0;
- if (wait_for_completion_interruptible(&bulk_waiter->event))
- return -EAGAIN;
+ if (wait_for_completion_killable(&bulk_waiter->event))
+ return -EINTR;
else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)
return -EINVAL;
@@ -3267,24 +3635,8 @@ error_exit:
int vchiq_queue_kernel_message(struct vchiq_instance *instance, unsigned int handle, void *data,
unsigned int size)
{
- int status;
-
- while (1) {
- status = vchiq_queue_message(instance, handle, memcpy_copy_callback,
- data, size);
-
- /*
- * vchiq_queue_message() may return -EAGAIN, so we need to
- * implement a retry mechanism since this function is supposed
- * to block until queued
- */
- if (status != -EAGAIN)
- break;
-
- msleep(1);
- }
-
- return status;
+ return vchiq_queue_message(instance, handle, memcpy_copy_callback,
+ data, size);
}
EXPORT_SYMBOL(vchiq_queue_kernel_message);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
index 468463f31801..9b4e766990a4 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
@@ -6,11 +6,12 @@
#include <linux/mutex.h>
#include <linux/completion.h>
-#include <linux/debugfs.h>
+#include <linux/dma-mapping.h>
#include <linux/dev_printk.h>
#include <linux/kthread.h>
#include <linux/kref.h>
#include <linux/rcupdate.h>
+#include <linux/seq_file.h>
#include <linux/spinlock_types.h>
#include <linux/wait.h>
@@ -113,12 +114,16 @@ enum vchiq_bulk_dir {
struct vchiq_bulk {
short mode;
short dir;
- void *userdata;
- dma_addr_t data;
+ void *cb_data;
+ void __user *cb_userdata;
+ struct bulk_waiter *waiter;
+ dma_addr_t dma_addr;
int size;
void *remote_data;
int remote_size;
int actual;
+ void *offset;
+ void __user *uoffset;
};
struct vchiq_bulk_queue {
@@ -409,6 +414,28 @@ struct vchiq_state {
struct opaque_platform_state *platform_state;
};
+struct pagelist {
+ u32 length;
+ u16 type;
+ u16 offset;
+ u32 addrs[1]; /* N.B. 12 LSBs hold the number
+ * of following pages at consecutive
+ * addresses.
+ */
+};
+
+struct vchiq_pagelist_info {
+ struct pagelist *pagelist;
+ size_t pagelist_buffer_size;
+ dma_addr_t dma_addr;
+ enum dma_data_direction dma_dir;
+ unsigned int num_pages;
+ unsigned int pages_need_release;
+ struct page **pages;
+ struct scatterlist *scatterlist;
+ unsigned int scatterlist_mapped;
+};
+
static inline bool vchiq_remote_initialised(const struct vchiq_state *state)
{
return state->remote && state->remote->initialised;
@@ -471,19 +498,16 @@ extern void
remote_event_pollall(struct vchiq_state *state);
extern int
-vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance,
- unsigned int handle, struct bulk_waiter *userdata);
+vchiq_bulk_xfer_waiting(struct vchiq_instance *instance, unsigned int handle,
+ struct bulk_waiter *userdata);
extern int
-vchiq_bulk_xfer_blocking_interruptible(struct vchiq_instance *instance, unsigned int handle,
- void *offset, void __user *uoffset, int size,
- void __user *userdata, enum vchiq_bulk_dir dir);
+vchiq_bulk_xfer_blocking(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_bulk *bulk);
extern int
-vchiq_bulk_xfer_callback_interruptible(struct vchiq_instance *instance, unsigned int handle,
- void *offset, void __user *uoffset, int size,
- enum vchiq_bulk_mode mode, void *userdata,
- enum vchiq_bulk_dir dir);
+vchiq_bulk_xfer_callback(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_bulk *bulk);
extern void
vchiq_dump_state(struct seq_file *f, struct vchiq_state *state);
@@ -529,13 +553,6 @@ vchiq_queue_message(struct vchiq_instance *instance, unsigned int handle,
void *context,
size_t size);
-int vchiq_prepare_bulk_data(struct vchiq_instance *instance, struct vchiq_bulk *bulk, void *offset,
- void __user *uoffset, int size, int dir);
-
-void vchiq_complete_bulk(struct vchiq_instance *instance, struct vchiq_bulk *bulk);
-
-void remote_event_signal(struct vchiq_state *state, struct remote_event *event);
-
void vchiq_dump_platform_state(struct seq_file *f);
void vchiq_dump_platform_instances(struct vchiq_state *state, struct seq_file *f);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h
index fabffd81b1ec..b29e6693c949 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h
@@ -4,7 +4,8 @@
#ifndef VCHIQ_DEBUGFS_H
#define VCHIQ_DEBUGFS_H
-#include "vchiq_core.h"
+struct vchiq_state;
+struct vchiq_instance;
struct vchiq_debugfs_node {
struct dentry *dentry;
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
index d41a4624cc92..454f43416503 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
@@ -288,7 +288,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
{
struct vchiq_service *service;
struct bulk_waiter_node *waiter = NULL, *iter;
- void *userdata;
+ struct vchiq_bulk bulk_params = {};
int status = 0;
int ret;
@@ -303,12 +303,14 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
goto out;
}
- userdata = &waiter->bulk_waiter;
-
- status = vchiq_bulk_xfer_blocking_interruptible(instance, args->handle,
- NULL, args->data, args->size,
- userdata, dir);
+ bulk_params.uoffset = args->data;
+ bulk_params.mode = args->mode;
+ bulk_params.size = args->size;
+ bulk_params.dir = dir;
+ bulk_params.waiter = &waiter->bulk_waiter;
+ status = vchiq_bulk_xfer_blocking(instance, args->handle,
+ &bulk_params);
} else if (args->mode == VCHIQ_BULK_MODE_WAITING) {
mutex_lock(&instance->bulk_waiter_list_mutex);
list_for_each_entry(iter, &instance->bulk_waiter_list,
@@ -328,16 +330,18 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
}
dev_dbg(service->state->dev, "arm: found bulk_waiter %pK for pid %d\n",
waiter, current->pid);
- userdata = &waiter->bulk_waiter;
- status = vchiq_bulk_xfer_waiting_interruptible(instance, args->handle, userdata);
+ status = vchiq_bulk_xfer_waiting(instance, args->handle,
+ &waiter->bulk_waiter);
} else {
- userdata = args->userdata;
-
- status = vchiq_bulk_xfer_callback_interruptible(instance, args->handle, NULL,
- args->data, args->size,
- args->mode, userdata, dir);
-
+ bulk_params.uoffset = args->data;
+ bulk_params.mode = args->mode;
+ bulk_params.size = args->size;
+ bulk_params.dir = dir;
+ bulk_params.cb_userdata = args->userdata;
+
+ status = vchiq_bulk_xfer_callback(instance, args->handle,
+ &bulk_params);
}
if (!waiter) {
@@ -350,7 +354,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
if (waiter->bulk_waiter.bulk) {
/* Cancel the signal when the transfer completes. */
spin_lock(&service->state->bulk_waiter_spinlock);
- waiter->bulk_waiter.bulk->userdata = NULL;
+ waiter->bulk_waiter.bulk->waiter = NULL;
spin_unlock(&service->state->bulk_waiter_spinlock);
}
kfree(waiter);
@@ -410,7 +414,7 @@ struct vchiq_completion_data32 {
enum vchiq_reason reason;
compat_uptr_t header;
compat_uptr_t service_userdata;
- compat_uptr_t bulk_userdata;
+ compat_uptr_t cb_data;
};
static int vchiq_put_completion(struct vchiq_completion_data __user *buf,
@@ -424,7 +428,7 @@ static int vchiq_put_completion(struct vchiq_completion_data __user *buf,
.reason = completion->reason,
.header = ptr_to_compat(completion->header),
.service_userdata = ptr_to_compat(completion->service_userdata),
- .bulk_userdata = ptr_to_compat(completion->bulk_userdata),
+ .cb_data = ptr_to_compat(completion->cb_userdata),
};
if (copy_to_user(&buf32[index], &tmp, sizeof(tmp)))
return -EFAULT;
@@ -545,11 +549,7 @@ static int vchiq_ioc_await_completion(struct vchiq_instance *instance,
!instance->use_close_delivered)
vchiq_service_put(service);
- /*
- * FIXME: address space mismatch, does bulk_userdata
- * actually point to user or kernel memory?
- */
- user_completion.bulk_userdata = completion->bulk_userdata;
+ user_completion.cb_userdata = completion->cb_userdata;
if (vchiq_put_completion(args->buf, &user_completion, ret)) {
if (ret == 0)
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
index 17550831f86c..afb71a83cfe7 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
@@ -47,7 +47,7 @@ struct vchiq_completion_data {
enum vchiq_reason reason;
struct vchiq_header __user *header;
void __user *service_userdata;
- void __user *bulk_userdata;
+ void __user *cb_userdata;
};
struct vchiq_await_completion {
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h
deleted file mode 100644
index ebd12bfabb63..000000000000
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */
-
-#ifndef VCHIQ_PAGELIST_H
-#define VCHIQ_PAGELIST_H
-
-#define PAGELIST_WRITE 0
-#define PAGELIST_READ 1
-#define PAGELIST_READ_WITH_FRAGMENTS 2
-
-struct pagelist {
- u32 length;
- u16 type;
- u16 offset;
- u32 addrs[1]; /* N.B. 12 LSBs hold the number
- * of following pages at consecutive
- * addresses.
- */
-};
-
-#endif /* VCHIQ_PAGELIST_H */
diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
index 67489c334f7b..3fe482bd2793 100644
--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
@@ -551,7 +551,8 @@ static void bulk_abort_cb(struct vchiq_mmal_instance *instance,
/* incoming event service callback */
static int mmal_service_callback(struct vchiq_instance *vchiq_instance,
enum vchiq_reason reason, struct vchiq_header *header,
- unsigned int handle, void *bulk_ctx)
+ unsigned int handle, void *cb_data,
+ void __user *cb_userdata)
{
struct vchiq_mmal_instance *instance = vchiq_get_service_userdata(vchiq_instance, handle);
u32 msg_len;
@@ -626,11 +627,11 @@ static int mmal_service_callback(struct vchiq_instance *vchiq_instance,
break;
case VCHIQ_BULK_RECEIVE_DONE:
- bulk_receive_cb(instance, bulk_ctx);
+ bulk_receive_cb(instance, cb_data);
break;
case VCHIQ_BULK_RECEIVE_ABORTED:
- bulk_abort_cb(instance, bulk_ctx);
+ bulk_abort_cb(instance, cb_data);
break;
case VCHIQ_SERVICE_CLOSED:
diff --git a/drivers/staging/vme_user/vme_bridge.h b/drivers/staging/vme_user/vme_bridge.h
index 9bdc41bb6602..abf880d68b12 100644
--- a/drivers/staging/vme_user/vme_bridge.h
+++ b/drivers/staging/vme_user/vme_bridge.h
@@ -128,39 +128,49 @@ struct vme_bridge {
struct mutex irq_mtx;
/* Slave Functions */
- int (*slave_get)(struct vme_slave_resource *, int *, unsigned long long *,
- unsigned long long *, dma_addr_t *, u32 *, u32 *);
- int (*slave_set)(struct vme_slave_resource *, int, unsigned long long,
- unsigned long long, dma_addr_t, u32, u32);
+ int (*slave_get)(struct vme_slave_resource *image, int *enabled,
+ unsigned long long *vme_base, unsigned long long *size,
+ dma_addr_t *buf_base, u32 *aspace, u32 *cycle);
+ int (*slave_set)(struct vme_slave_resource *image, int enabled,
+ unsigned long long vme_base, unsigned long long size,
+ dma_addr_t buf_base, u32 aspace, u32 cycle);
/* Master Functions */
- int (*master_get)(struct vme_master_resource *, int *, unsigned long long *,
- unsigned long long *, u32 *, u32 *, u32 *);
- int (*master_set)(struct vme_master_resource *, int, unsigned long long,
- unsigned long long, u32, u32, u32);
- ssize_t (*master_read)(struct vme_master_resource *, void *, size_t, loff_t);
- ssize_t (*master_write)(struct vme_master_resource *, void *, size_t, loff_t);
- unsigned int (*master_rmw)(struct vme_master_resource *, unsigned int,
- unsigned int, unsigned int, loff_t);
+ int (*master_get)(struct vme_master_resource *image, int *enabled,
+ unsigned long long *vme_base, unsigned long long *size,
+ u32 *aspace, u32 *cycle, u32 *dwidth);
+ int (*master_set)(struct vme_master_resource *image, int enabled,
+ unsigned long long vme_base, unsigned long long size,
+ u32 aspace, u32 cycle, u32 dwidth);
+ ssize_t (*master_read)(struct vme_master_resource *image, void *buf,
+ size_t count, loff_t offset);
+ ssize_t (*master_write)(struct vme_master_resource *image, void *buf,
+ size_t count, loff_t offset);
+ unsigned int (*master_rmw)(struct vme_master_resource *image,
+ unsigned int mask, unsigned int compare,
+ unsigned int swap, loff_t offset);
/* DMA Functions */
- int (*dma_list_add)(struct vme_dma_list *, struct vme_dma_attr *,
- struct vme_dma_attr *, size_t);
- int (*dma_list_exec)(struct vme_dma_list *);
- int (*dma_list_empty)(struct vme_dma_list *);
+ int (*dma_list_add)(struct vme_dma_list *list, struct vme_dma_attr *src,
+ struct vme_dma_attr *dest, size_t count);
+ int (*dma_list_exec)(struct vme_dma_list *list);
+ int (*dma_list_empty)(struct vme_dma_list *list);
/* Interrupt Functions */
- void (*irq_set)(struct vme_bridge *, int, int, int);
- int (*irq_generate)(struct vme_bridge *, int, int);
+ void (*irq_set)(struct vme_bridge *bridge, int level, int state, int sync);
+ int (*irq_generate)(struct vme_bridge *bridge, int level, int statid);
/* Location monitor functions */
- int (*lm_set)(struct vme_lm_resource *, unsigned long long, u32, u32);
- int (*lm_get)(struct vme_lm_resource *, unsigned long long *, u32 *, u32 *);
- int (*lm_attach)(struct vme_lm_resource *, int, void (*callback)(void *), void *);
- int (*lm_detach)(struct vme_lm_resource *, int);
+ int (*lm_set)(struct vme_lm_resource *lm, unsigned long long lm_base,
+ u32 aspace, u32 cycle);
+ int (*lm_get)(struct vme_lm_resource *lm, unsigned long long *lm_base,
+ u32 *aspace, u32 *cycle);
+ int (*lm_attach)(struct vme_lm_resource *lm, int monitor,
+ void (*callback)(void *), void *data);
+ int (*lm_detach)(struct vme_lm_resource *lm, int monitor);
/* CR/CSR space functions */
- int (*slot_get)(struct vme_bridge *);
+ int (*slot_get)(struct vme_bridge *bridge);
/* Bridge parent interface */
void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *dma);
diff --git a/drivers/staging/vt6655/Kconfig b/drivers/staging/vt6655/Kconfig
deleted file mode 100644
index 077f62ebe80c..000000000000
--- a/drivers/staging/vt6655/Kconfig
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config VT6655
- tristate "VIA Technologies VT6655 support"
- depends on PCI && HAS_IOPORT && MAC80211 && m
- help
- This is a vendor-written driver for VIA VT6655.
diff --git a/drivers/staging/vt6655/Makefile b/drivers/staging/vt6655/Makefile
deleted file mode 100644
index e70357ec0af8..000000000000
--- a/drivers/staging/vt6655/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-vt6655_stage-y += device_main.o \
- card.o \
- channel.o \
- mac.o \
- baseband.o \
- rxtx.o \
- dpc.o \
- power.o \
- srom.o \
- key.o \
- rf.o
-
-obj-$(CONFIG_VT6655) += vt6655_stage.o
diff --git a/drivers/staging/vt6655/TODO b/drivers/staging/vt6655/TODO
deleted file mode 100644
index 27654bd0ff5d..000000000000
--- a/drivers/staging/vt6655/TODO
+++ /dev/null
@@ -1,20 +0,0 @@
-TODO:
-- remove __cplusplus ifdefs -- done
-- prepare for merge with vt6656 driver:
- - rename DEVICE_PRT() to DBG_PRT() -- done
- - share 80211*.h includes
- - split rf.c
- - remove dead code
- - abstract VT3253 chipset specific code
-- add common vt665x infrastructure
-- kill ttype.h
-- switch to use MAC80211
-- verify unsigned long usage for x86-64 arch
-- reduce .data footprint
-- use kernel coding style
-- checkpatch.pl fixes
-- sparse fixes
-- integrate with drivers/net/wireless
-
-Please send any patches to Greg Kroah-Hartman <greg@kroah.com>
-and Philipp Hortmann <philipp.g.hortmann@gmail.com>.
diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c
deleted file mode 100644
index f7824396c5ff..000000000000
--- a/drivers/staging/vt6655/baseband.c
+++ /dev/null
@@ -1,2257 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions to access baseband
- *
- * Author: Kyle Hsu
- *
- * Date: Aug.22, 2002
- *
- * Functions:
- * bb_get_frame_time - Calculate data frame transmitting time
- * bb_read_embedded - Embedded read baseband register via MAC
- * bb_write_embedded - Embedded write baseband register via MAC
- * bb_vt3253_init - VIA VT3253 baseband chip init code
- *
- * Revision History:
- * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
- * 08-07-2003 Bryan YC Fan: Add MAXIM2827/2825 and RFMD2959 support.
- * 08-26-2003 Kyle Hsu : Modify BBuGetFrameTime() and
- * BBvCalculateParameter().
- * cancel the setting of MAC_REG_SOFTPWRCTL on
- * BBbVT3253Init().
- * Add the comments.
- * 09-01-2003 Bryan YC Fan: RF & BB tables updated.
- * Modified BBvLoopbackOn & BBvLoopbackOff().
- *
- *
- */
-
-#include "mac.h"
-#include "baseband.h"
-#include "srom.h"
-#include "rf.h"
-
-/*--------------------- Static Classes ----------------------------*/
-
-/*--------------------- Static Variables --------------------------*/
-
-/*--------------------- Static Functions --------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Static Definitions -------------------------*/
-
-/*--------------------- Static Classes ----------------------------*/
-
-/*--------------------- Static Variables --------------------------*/
-
-#define CB_VT3253_INIT_FOR_RFMD 446
-static const unsigned char by_vt3253_init_tab_rfmd[CB_VT3253_INIT_FOR_RFMD][2] = {
- {0x00, 0x30},
- {0x01, 0x00},
- {0x02, 0x00},
- {0x03, 0x00},
- {0x04, 0x00},
- {0x05, 0x00},
- {0x06, 0x00},
- {0x07, 0x00},
- {0x08, 0x70},
- {0x09, 0x45},
- {0x0a, 0x2a},
- {0x0b, 0x76},
- {0x0c, 0x00},
- {0x0d, 0x01},
- {0x0e, 0x80},
- {0x0f, 0x00},
- {0x10, 0x00},
- {0x11, 0x00},
- {0x12, 0x00},
- {0x13, 0x00},
- {0x14, 0x00},
- {0x15, 0x00},
- {0x16, 0x00},
- {0x17, 0x00},
- {0x18, 0x00},
- {0x19, 0x00},
- {0x1a, 0x00},
- {0x1b, 0x9d},
- {0x1c, 0x05},
- {0x1d, 0x00},
- {0x1e, 0x00},
- {0x1f, 0x00},
- {0x20, 0x00},
- {0x21, 0x00},
- {0x22, 0x00},
- {0x23, 0x00},
- {0x24, 0x00},
- {0x25, 0x4a},
- {0x26, 0x00},
- {0x27, 0x00},
- {0x28, 0x00},
- {0x29, 0x00},
- {0x2a, 0x00},
- {0x2b, 0x00},
- {0x2c, 0x00},
- {0x2d, 0xa8},
- {0x2e, 0x1a},
- {0x2f, 0x0c},
- {0x30, 0x26},
- {0x31, 0x5b},
- {0x32, 0x00},
- {0x33, 0x00},
- {0x34, 0x00},
- {0x35, 0x00},
- {0x36, 0xaa},
- {0x37, 0xaa},
- {0x38, 0xff},
- {0x39, 0xff},
- {0x3a, 0x00},
- {0x3b, 0x00},
- {0x3c, 0x00},
- {0x3d, 0x0d},
- {0x3e, 0x51},
- {0x3f, 0x04},
- {0x40, 0x00},
- {0x41, 0x08},
- {0x42, 0x00},
- {0x43, 0x08},
- {0x44, 0x06},
- {0x45, 0x14},
- {0x46, 0x05},
- {0x47, 0x08},
- {0x48, 0x00},
- {0x49, 0x00},
- {0x4a, 0x00},
- {0x4b, 0x00},
- {0x4c, 0x09},
- {0x4d, 0x80},
- {0x4e, 0x00},
- {0x4f, 0xc5},
- {0x50, 0x14},
- {0x51, 0x19},
- {0x52, 0x00},
- {0x53, 0x00},
- {0x54, 0x00},
- {0x55, 0x00},
- {0x56, 0x00},
- {0x57, 0x00},
- {0x58, 0x00},
- {0x59, 0xb0},
- {0x5a, 0x00},
- {0x5b, 0x00},
- {0x5c, 0x00},
- {0x5d, 0x00},
- {0x5e, 0x00},
- {0x5f, 0x00},
- {0x60, 0x44},
- {0x61, 0x04},
- {0x62, 0x00},
- {0x63, 0x00},
- {0x64, 0x00},
- {0x65, 0x00},
- {0x66, 0x04},
- {0x67, 0xb7},
- {0x68, 0x00},
- {0x69, 0x00},
- {0x6a, 0x00},
- {0x6b, 0x00},
- {0x6c, 0x00},
- {0x6d, 0x03},
- {0x6e, 0x01},
- {0x6f, 0x00},
- {0x70, 0x00},
- {0x71, 0x00},
- {0x72, 0x00},
- {0x73, 0x00},
- {0x74, 0x00},
- {0x75, 0x00},
- {0x76, 0x00},
- {0x77, 0x00},
- {0x78, 0x00},
- {0x79, 0x00},
- {0x7a, 0x00},
- {0x7b, 0x00},
- {0x7c, 0x00},
- {0x7d, 0x00},
- {0x7e, 0x00},
- {0x7f, 0x00},
- {0x80, 0x0b},
- {0x81, 0x00},
- {0x82, 0x3c},
- {0x83, 0x00},
- {0x84, 0x00},
- {0x85, 0x00},
- {0x86, 0x00},
- {0x87, 0x00},
- {0x88, 0x08},
- {0x89, 0x00},
- {0x8a, 0x08},
- {0x8b, 0xa6},
- {0x8c, 0x84},
- {0x8d, 0x47},
- {0x8e, 0xbb},
- {0x8f, 0x02},
- {0x90, 0x21},
- {0x91, 0x0c},
- {0x92, 0x04},
- {0x93, 0x22},
- {0x94, 0x00},
- {0x95, 0x00},
- {0x96, 0x00},
- {0x97, 0xeb},
- {0x98, 0x00},
- {0x99, 0x00},
- {0x9a, 0x00},
- {0x9b, 0x00},
- {0x9c, 0x00},
- {0x9d, 0x00},
- {0x9e, 0x00},
- {0x9f, 0x00},
- {0xa0, 0x00},
- {0xa1, 0x00},
- {0xa2, 0x00},
- {0xa3, 0x00},
- {0xa4, 0x00},
- {0xa5, 0x00},
- {0xa6, 0x10},
- {0xa7, 0x04},
- {0xa8, 0x10},
- {0xa9, 0x00},
- {0xaa, 0x8f},
- {0xab, 0x00},
- {0xac, 0x00},
- {0xad, 0x00},
- {0xae, 0x00},
- {0xaf, 0x80},
- {0xb0, 0x38},
- {0xb1, 0x00},
- {0xb2, 0x00},
- {0xb3, 0x00},
- {0xb4, 0xee},
- {0xb5, 0xff},
- {0xb6, 0x10},
- {0xb7, 0x00},
- {0xb8, 0x00},
- {0xb9, 0x00},
- {0xba, 0x00},
- {0xbb, 0x03},
- {0xbc, 0x00},
- {0xbd, 0x00},
- {0xbe, 0x00},
- {0xbf, 0x00},
- {0xc0, 0x10},
- {0xc1, 0x10},
- {0xc2, 0x18},
- {0xc3, 0x20},
- {0xc4, 0x10},
- {0xc5, 0x00},
- {0xc6, 0x22},
- {0xc7, 0x14},
- {0xc8, 0x0f},
- {0xc9, 0x08},
- {0xca, 0xa4},
- {0xcb, 0xa7},
- {0xcc, 0x3c},
- {0xcd, 0x10},
- {0xce, 0x20},
- {0xcf, 0x00},
- {0xd0, 0x00},
- {0xd1, 0x10},
- {0xd2, 0x00},
- {0xd3, 0x00},
- {0xd4, 0x10},
- {0xd5, 0x33},
- {0xd6, 0x70},
- {0xd7, 0x01},
- {0xd8, 0x00},
- {0xd9, 0x00},
- {0xda, 0x00},
- {0xdb, 0x00},
- {0xdc, 0x00},
- {0xdd, 0x00},
- {0xde, 0x00},
- {0xdf, 0x00},
- {0xe0, 0x00},
- {0xe1, 0x00},
- {0xe2, 0xcc},
- {0xe3, 0x04},
- {0xe4, 0x08},
- {0xe5, 0x10},
- {0xe6, 0x00},
- {0xe7, 0x0e},
- {0xe8, 0x88},
- {0xe9, 0xd4},
- {0xea, 0x05},
- {0xeb, 0xf0},
- {0xec, 0x79},
- {0xed, 0x0f},
- {0xee, 0x04},
- {0xef, 0x04},
- {0xf0, 0x00},
- {0xf1, 0x00},
- {0xf2, 0x00},
- {0xf3, 0x00},
- {0xf4, 0x00},
- {0xf5, 0x00},
- {0xf6, 0x00},
- {0xf7, 0x00},
- {0xf8, 0x00},
- {0xf9, 0x00},
- {0xF0, 0x00},
- {0xF1, 0xF8},
- {0xF0, 0x80},
- {0xF0, 0x00},
- {0xF1, 0xF4},
- {0xF0, 0x81},
- {0xF0, 0x01},
- {0xF1, 0xF0},
- {0xF0, 0x82},
- {0xF0, 0x02},
- {0xF1, 0xEC},
- {0xF0, 0x83},
- {0xF0, 0x03},
- {0xF1, 0xE8},
- {0xF0, 0x84},
- {0xF0, 0x04},
- {0xF1, 0xE4},
- {0xF0, 0x85},
- {0xF0, 0x05},
- {0xF1, 0xE0},
- {0xF0, 0x86},
- {0xF0, 0x06},
- {0xF1, 0xDC},
- {0xF0, 0x87},
- {0xF0, 0x07},
- {0xF1, 0xD8},
- {0xF0, 0x88},
- {0xF0, 0x08},
- {0xF1, 0xD4},
- {0xF0, 0x89},
- {0xF0, 0x09},
- {0xF1, 0xD0},
- {0xF0, 0x8A},
- {0xF0, 0x0A},
- {0xF1, 0xCC},
- {0xF0, 0x8B},
- {0xF0, 0x0B},
- {0xF1, 0xC8},
- {0xF0, 0x8C},
- {0xF0, 0x0C},
- {0xF1, 0xC4},
- {0xF0, 0x8D},
- {0xF0, 0x0D},
- {0xF1, 0xC0},
- {0xF0, 0x8E},
- {0xF0, 0x0E},
- {0xF1, 0xBC},
- {0xF0, 0x8F},
- {0xF0, 0x0F},
- {0xF1, 0xB8},
- {0xF0, 0x90},
- {0xF0, 0x10},
- {0xF1, 0xB4},
- {0xF0, 0x91},
- {0xF0, 0x11},
- {0xF1, 0xB0},
- {0xF0, 0x92},
- {0xF0, 0x12},
- {0xF1, 0xAC},
- {0xF0, 0x93},
- {0xF0, 0x13},
- {0xF1, 0xA8},
- {0xF0, 0x94},
- {0xF0, 0x14},
- {0xF1, 0xA4},
- {0xF0, 0x95},
- {0xF0, 0x15},
- {0xF1, 0xA0},
- {0xF0, 0x96},
- {0xF0, 0x16},
- {0xF1, 0x9C},
- {0xF0, 0x97},
- {0xF0, 0x17},
- {0xF1, 0x98},
- {0xF0, 0x98},
- {0xF0, 0x18},
- {0xF1, 0x94},
- {0xF0, 0x99},
- {0xF0, 0x19},
- {0xF1, 0x90},
- {0xF0, 0x9A},
- {0xF0, 0x1A},
- {0xF1, 0x8C},
- {0xF0, 0x9B},
- {0xF0, 0x1B},
- {0xF1, 0x88},
- {0xF0, 0x9C},
- {0xF0, 0x1C},
- {0xF1, 0x84},
- {0xF0, 0x9D},
- {0xF0, 0x1D},
- {0xF1, 0x80},
- {0xF0, 0x9E},
- {0xF0, 0x1E},
- {0xF1, 0x7C},
- {0xF0, 0x9F},
- {0xF0, 0x1F},
- {0xF1, 0x78},
- {0xF0, 0xA0},
- {0xF0, 0x20},
- {0xF1, 0x74},
- {0xF0, 0xA1},
- {0xF0, 0x21},
- {0xF1, 0x70},
- {0xF0, 0xA2},
- {0xF0, 0x22},
- {0xF1, 0x6C},
- {0xF0, 0xA3},
- {0xF0, 0x23},
- {0xF1, 0x68},
- {0xF0, 0xA4},
- {0xF0, 0x24},
- {0xF1, 0x64},
- {0xF0, 0xA5},
- {0xF0, 0x25},
- {0xF1, 0x60},
- {0xF0, 0xA6},
- {0xF0, 0x26},
- {0xF1, 0x5C},
- {0xF0, 0xA7},
- {0xF0, 0x27},
- {0xF1, 0x58},
- {0xF0, 0xA8},
- {0xF0, 0x28},
- {0xF1, 0x54},
- {0xF0, 0xA9},
- {0xF0, 0x29},
- {0xF1, 0x50},
- {0xF0, 0xAA},
- {0xF0, 0x2A},
- {0xF1, 0x4C},
- {0xF0, 0xAB},
- {0xF0, 0x2B},
- {0xF1, 0x48},
- {0xF0, 0xAC},
- {0xF0, 0x2C},
- {0xF1, 0x44},
- {0xF0, 0xAD},
- {0xF0, 0x2D},
- {0xF1, 0x40},
- {0xF0, 0xAE},
- {0xF0, 0x2E},
- {0xF1, 0x3C},
- {0xF0, 0xAF},
- {0xF0, 0x2F},
- {0xF1, 0x38},
- {0xF0, 0xB0},
- {0xF0, 0x30},
- {0xF1, 0x34},
- {0xF0, 0xB1},
- {0xF0, 0x31},
- {0xF1, 0x30},
- {0xF0, 0xB2},
- {0xF0, 0x32},
- {0xF1, 0x2C},
- {0xF0, 0xB3},
- {0xF0, 0x33},
- {0xF1, 0x28},
- {0xF0, 0xB4},
- {0xF0, 0x34},
- {0xF1, 0x24},
- {0xF0, 0xB5},
- {0xF0, 0x35},
- {0xF1, 0x20},
- {0xF0, 0xB6},
- {0xF0, 0x36},
- {0xF1, 0x1C},
- {0xF0, 0xB7},
- {0xF0, 0x37},
- {0xF1, 0x18},
- {0xF0, 0xB8},
- {0xF0, 0x38},
- {0xF1, 0x14},
- {0xF0, 0xB9},
- {0xF0, 0x39},
- {0xF1, 0x10},
- {0xF0, 0xBA},
- {0xF0, 0x3A},
- {0xF1, 0x0C},
- {0xF0, 0xBB},
- {0xF0, 0x3B},
- {0xF1, 0x08},
- {0xF0, 0x00},
- {0xF0, 0x3C},
- {0xF1, 0x04},
- {0xF0, 0xBD},
- {0xF0, 0x3D},
- {0xF1, 0x00},
- {0xF0, 0xBE},
- {0xF0, 0x3E},
- {0xF1, 0x00},
- {0xF0, 0xBF},
- {0xF0, 0x3F},
- {0xF1, 0x00},
- {0xF0, 0xC0},
- {0xF0, 0x00},
-};
-
-#define CB_VT3253B0_INIT_FOR_RFMD 256
-static const unsigned char vt3253b0_rfmd[CB_VT3253B0_INIT_FOR_RFMD][2] = {
- {0x00, 0x31},
- {0x01, 0x00},
- {0x02, 0x00},
- {0x03, 0x00},
- {0x04, 0x00},
- {0x05, 0x81},
- {0x06, 0x00},
- {0x07, 0x00},
- {0x08, 0x38},
- {0x09, 0x45},
- {0x0a, 0x2a},
- {0x0b, 0x76},
- {0x0c, 0x00},
- {0x0d, 0x00},
- {0x0e, 0x80},
- {0x0f, 0x00},
- {0x10, 0x00},
- {0x11, 0x00},
- {0x12, 0x00},
- {0x13, 0x00},
- {0x14, 0x00},
- {0x15, 0x00},
- {0x16, 0x00},
- {0x17, 0x00},
- {0x18, 0x00},
- {0x19, 0x00},
- {0x1a, 0x00},
- {0x1b, 0x8e},
- {0x1c, 0x06},
- {0x1d, 0x00},
- {0x1e, 0x00},
- {0x1f, 0x00},
- {0x20, 0x00},
- {0x21, 0x00},
- {0x22, 0x00},
- {0x23, 0x00},
- {0x24, 0x00},
- {0x25, 0x4a},
- {0x26, 0x00},
- {0x27, 0x00},
- {0x28, 0x00},
- {0x29, 0x00},
- {0x2a, 0x00},
- {0x2b, 0x00},
- {0x2c, 0x00},
- {0x2d, 0x34},
- {0x2e, 0x18},
- {0x2f, 0x0c},
- {0x30, 0x26},
- {0x31, 0x5b},
- {0x32, 0x00},
- {0x33, 0x00},
- {0x34, 0x00},
- {0x35, 0x00},
- {0x36, 0xaa},
- {0x37, 0xaa},
- {0x38, 0xff},
- {0x39, 0xff},
- {0x3a, 0xf8},
- {0x3b, 0x00},
- {0x3c, 0x00},
- {0x3d, 0x09},
- {0x3e, 0x0d},
- {0x3f, 0x04},
- {0x40, 0x00},
- {0x41, 0x08},
- {0x42, 0x00},
- {0x43, 0x08},
- {0x44, 0x08},
- {0x45, 0x14},
- {0x46, 0x05},
- {0x47, 0x08},
- {0x48, 0x00},
- {0x49, 0x00},
- {0x4a, 0x00},
- {0x4b, 0x00},
- {0x4c, 0x09},
- {0x4d, 0x80},
- {0x4e, 0x00},
- {0x4f, 0xc5},
- {0x50, 0x14},
- {0x51, 0x19},
- {0x52, 0x00},
- {0x53, 0x00},
- {0x54, 0x00},
- {0x55, 0x00},
- {0x56, 0x00},
- {0x57, 0x00},
- {0x58, 0x00},
- {0x59, 0xb0},
- {0x5a, 0x00},
- {0x5b, 0x00},
- {0x5c, 0x00},
- {0x5d, 0x00},
- {0x5e, 0x00},
- {0x5f, 0x00},
- {0x60, 0x39},
- {0x61, 0x83},
- {0x62, 0x00},
- {0x63, 0x00},
- {0x64, 0x00},
- {0x65, 0x00},
- {0x66, 0xc0},
- {0x67, 0x49},
- {0x68, 0x00},
- {0x69, 0x00},
- {0x6a, 0x00},
- {0x6b, 0x00},
- {0x6c, 0x00},
- {0x6d, 0x03},
- {0x6e, 0x01},
- {0x6f, 0x00},
- {0x70, 0x00},
- {0x71, 0x00},
- {0x72, 0x00},
- {0x73, 0x00},
- {0x74, 0x00},
- {0x75, 0x00},
- {0x76, 0x00},
- {0x77, 0x00},
- {0x78, 0x00},
- {0x79, 0x00},
- {0x7a, 0x00},
- {0x7b, 0x00},
- {0x7c, 0x00},
- {0x7d, 0x00},
- {0x7e, 0x00},
- {0x7f, 0x00},
- {0x80, 0x89},
- {0x81, 0x00},
- {0x82, 0x0e},
- {0x83, 0x00},
- {0x84, 0x00},
- {0x85, 0x00},
- {0x86, 0x00},
- {0x87, 0x00},
- {0x88, 0x08},
- {0x89, 0x00},
- {0x8a, 0x0e},
- {0x8b, 0xa7},
- {0x8c, 0x88},
- {0x8d, 0x47},
- {0x8e, 0xaa},
- {0x8f, 0x02},
- {0x90, 0x23},
- {0x91, 0x0c},
- {0x92, 0x06},
- {0x93, 0x08},
- {0x94, 0x00},
- {0x95, 0x00},
- {0x96, 0x00},
- {0x97, 0xeb},
- {0x98, 0x00},
- {0x99, 0x00},
- {0x9a, 0x00},
- {0x9b, 0x00},
- {0x9c, 0x00},
- {0x9d, 0x00},
- {0x9e, 0x00},
- {0x9f, 0x00},
- {0xa0, 0x00},
- {0xa1, 0x00},
- {0xa2, 0x00},
- {0xa3, 0xcd},
- {0xa4, 0x07},
- {0xa5, 0x33},
- {0xa6, 0x18},
- {0xa7, 0x00},
- {0xa8, 0x18},
- {0xa9, 0x00},
- {0xaa, 0x28},
- {0xab, 0x00},
- {0xac, 0x00},
- {0xad, 0x00},
- {0xae, 0x00},
- {0xaf, 0x18},
- {0xb0, 0x38},
- {0xb1, 0x30},
- {0xb2, 0x00},
- {0xb3, 0x00},
- {0xb4, 0x00},
- {0xb5, 0x00},
- {0xb6, 0x84},
- {0xb7, 0xfd},
- {0xb8, 0x00},
- {0xb9, 0x00},
- {0xba, 0x00},
- {0xbb, 0x03},
- {0xbc, 0x00},
- {0xbd, 0x00},
- {0xbe, 0x00},
- {0xbf, 0x00},
- {0xc0, 0x10},
- {0xc1, 0x20},
- {0xc2, 0x18},
- {0xc3, 0x20},
- {0xc4, 0x10},
- {0xc5, 0x2c},
- {0xc6, 0x1e},
- {0xc7, 0x10},
- {0xc8, 0x12},
- {0xc9, 0x01},
- {0xca, 0x6f},
- {0xcb, 0xa7},
- {0xcc, 0x3c},
- {0xcd, 0x10},
- {0xce, 0x00},
- {0xcf, 0x22},
- {0xd0, 0x00},
- {0xd1, 0x10},
- {0xd2, 0x00},
- {0xd3, 0x00},
- {0xd4, 0x10},
- {0xd5, 0x33},
- {0xd6, 0x80},
- {0xd7, 0x21},
- {0xd8, 0x00},
- {0xd9, 0x00},
- {0xda, 0x00},
- {0xdb, 0x00},
- {0xdc, 0x00},
- {0xdd, 0x00},
- {0xde, 0x00},
- {0xdf, 0x00},
- {0xe0, 0x00},
- {0xe1, 0xB3},
- {0xe2, 0x00},
- {0xe3, 0x00},
- {0xe4, 0x00},
- {0xe5, 0x10},
- {0xe6, 0x00},
- {0xe7, 0x18},
- {0xe8, 0x08},
- {0xe9, 0xd4},
- {0xea, 0x00},
- {0xeb, 0xff},
- {0xec, 0x79},
- {0xed, 0x10},
- {0xee, 0x30},
- {0xef, 0x02},
- {0xf0, 0x00},
- {0xf1, 0x09},
- {0xf2, 0x00},
- {0xf3, 0x00},
- {0xf4, 0x00},
- {0xf5, 0x00},
- {0xf6, 0x00},
- {0xf7, 0x00},
- {0xf8, 0x00},
- {0xf9, 0x00},
- {0xfa, 0x00},
- {0xfb, 0x00},
- {0xfc, 0x00},
- {0xfd, 0x00},
- {0xfe, 0x00},
- {0xff, 0x00},
-};
-
-#define CB_VT3253B0_AGC_FOR_RFMD2959 195
-/* For RFMD2959 */
-static
-unsigned char vt3253b0_agc4_rfmd2959[CB_VT3253B0_AGC_FOR_RFMD2959][2] = {
- {0xF0, 0x00},
- {0xF1, 0x3E},
- {0xF0, 0x80},
- {0xF0, 0x00},
- {0xF1, 0x3E},
- {0xF0, 0x81},
- {0xF0, 0x01},
- {0xF1, 0x3E},
- {0xF0, 0x82},
- {0xF0, 0x02},
- {0xF1, 0x3E},
- {0xF0, 0x83},
- {0xF0, 0x03},
- {0xF1, 0x3B},
- {0xF0, 0x84},
- {0xF0, 0x04},
- {0xF1, 0x39},
- {0xF0, 0x85},
- {0xF0, 0x05},
- {0xF1, 0x38},
- {0xF0, 0x86},
- {0xF0, 0x06},
- {0xF1, 0x37},
- {0xF0, 0x87},
- {0xF0, 0x07},
- {0xF1, 0x36},
- {0xF0, 0x88},
- {0xF0, 0x08},
- {0xF1, 0x35},
- {0xF0, 0x89},
- {0xF0, 0x09},
- {0xF1, 0x35},
- {0xF0, 0x8A},
- {0xF0, 0x0A},
- {0xF1, 0x34},
- {0xF0, 0x8B},
- {0xF0, 0x0B},
- {0xF1, 0x34},
- {0xF0, 0x8C},
- {0xF0, 0x0C},
- {0xF1, 0x33},
- {0xF0, 0x8D},
- {0xF0, 0x0D},
- {0xF1, 0x32},
- {0xF0, 0x8E},
- {0xF0, 0x0E},
- {0xF1, 0x31},
- {0xF0, 0x8F},
- {0xF0, 0x0F},
- {0xF1, 0x30},
- {0xF0, 0x90},
- {0xF0, 0x10},
- {0xF1, 0x2F},
- {0xF0, 0x91},
- {0xF0, 0x11},
- {0xF1, 0x2F},
- {0xF0, 0x92},
- {0xF0, 0x12},
- {0xF1, 0x2E},
- {0xF0, 0x93},
- {0xF0, 0x13},
- {0xF1, 0x2D},
- {0xF0, 0x94},
- {0xF0, 0x14},
- {0xF1, 0x2C},
- {0xF0, 0x95},
- {0xF0, 0x15},
- {0xF1, 0x2B},
- {0xF0, 0x96},
- {0xF0, 0x16},
- {0xF1, 0x2B},
- {0xF0, 0x97},
- {0xF0, 0x17},
- {0xF1, 0x2A},
- {0xF0, 0x98},
- {0xF0, 0x18},
- {0xF1, 0x29},
- {0xF0, 0x99},
- {0xF0, 0x19},
- {0xF1, 0x28},
- {0xF0, 0x9A},
- {0xF0, 0x1A},
- {0xF1, 0x27},
- {0xF0, 0x9B},
- {0xF0, 0x1B},
- {0xF1, 0x26},
- {0xF0, 0x9C},
- {0xF0, 0x1C},
- {0xF1, 0x25},
- {0xF0, 0x9D},
- {0xF0, 0x1D},
- {0xF1, 0x24},
- {0xF0, 0x9E},
- {0xF0, 0x1E},
- {0xF1, 0x24},
- {0xF0, 0x9F},
- {0xF0, 0x1F},
- {0xF1, 0x23},
- {0xF0, 0xA0},
- {0xF0, 0x20},
- {0xF1, 0x22},
- {0xF0, 0xA1},
- {0xF0, 0x21},
- {0xF1, 0x21},
- {0xF0, 0xA2},
- {0xF0, 0x22},
- {0xF1, 0x20},
- {0xF0, 0xA3},
- {0xF0, 0x23},
- {0xF1, 0x20},
- {0xF0, 0xA4},
- {0xF0, 0x24},
- {0xF1, 0x1F},
- {0xF0, 0xA5},
- {0xF0, 0x25},
- {0xF1, 0x1E},
- {0xF0, 0xA6},
- {0xF0, 0x26},
- {0xF1, 0x1D},
- {0xF0, 0xA7},
- {0xF0, 0x27},
- {0xF1, 0x1C},
- {0xF0, 0xA8},
- {0xF0, 0x28},
- {0xF1, 0x1B},
- {0xF0, 0xA9},
- {0xF0, 0x29},
- {0xF1, 0x1B},
- {0xF0, 0xAA},
- {0xF0, 0x2A},
- {0xF1, 0x1A},
- {0xF0, 0xAB},
- {0xF0, 0x2B},
- {0xF1, 0x1A},
- {0xF0, 0xAC},
- {0xF0, 0x2C},
- {0xF1, 0x19},
- {0xF0, 0xAD},
- {0xF0, 0x2D},
- {0xF1, 0x18},
- {0xF0, 0xAE},
- {0xF0, 0x2E},
- {0xF1, 0x17},
- {0xF0, 0xAF},
- {0xF0, 0x2F},
- {0xF1, 0x16},
- {0xF0, 0xB0},
- {0xF0, 0x30},
- {0xF1, 0x15},
- {0xF0, 0xB1},
- {0xF0, 0x31},
- {0xF1, 0x15},
- {0xF0, 0xB2},
- {0xF0, 0x32},
- {0xF1, 0x15},
- {0xF0, 0xB3},
- {0xF0, 0x33},
- {0xF1, 0x14},
- {0xF0, 0xB4},
- {0xF0, 0x34},
- {0xF1, 0x13},
- {0xF0, 0xB5},
- {0xF0, 0x35},
- {0xF1, 0x12},
- {0xF0, 0xB6},
- {0xF0, 0x36},
- {0xF1, 0x11},
- {0xF0, 0xB7},
- {0xF0, 0x37},
- {0xF1, 0x10},
- {0xF0, 0xB8},
- {0xF0, 0x38},
- {0xF1, 0x0F},
- {0xF0, 0xB9},
- {0xF0, 0x39},
- {0xF1, 0x0E},
- {0xF0, 0xBA},
- {0xF0, 0x3A},
- {0xF1, 0x0D},
- {0xF0, 0xBB},
- {0xF0, 0x3B},
- {0xF1, 0x0C},
- {0xF0, 0xBC},
- {0xF0, 0x3C},
- {0xF1, 0x0B},
- {0xF0, 0xBD},
- {0xF0, 0x3D},
- {0xF1, 0x0B},
- {0xF0, 0xBE},
- {0xF0, 0x3E},
- {0xF1, 0x0A},
- {0xF0, 0xBF},
- {0xF0, 0x3F},
- {0xF1, 0x09},
- {0xF0, 0x00},
-};
-
-#define CB_VT3253B0_INIT_FOR_AIROHA2230 256
-/* For AIROHA */
-static
-unsigned char vt3253b0_airoha2230[CB_VT3253B0_INIT_FOR_AIROHA2230][2] = {
- {0x00, 0x31},
- {0x01, 0x00},
- {0x02, 0x00},
- {0x03, 0x00},
- {0x04, 0x00},
- {0x05, 0x80},
- {0x06, 0x00},
- {0x07, 0x00},
- {0x08, 0x70},
- {0x09, 0x41},
- {0x0a, 0x2A},
- {0x0b, 0x76},
- {0x0c, 0x00},
- {0x0d, 0x00},
- {0x0e, 0x80},
- {0x0f, 0x00},
- {0x10, 0x00},
- {0x11, 0x00},
- {0x12, 0x00},
- {0x13, 0x00},
- {0x14, 0x00},
- {0x15, 0x00},
- {0x16, 0x00},
- {0x17, 0x00},
- {0x18, 0x00},
- {0x19, 0x00},
- {0x1a, 0x00},
- {0x1b, 0x8f},
- {0x1c, 0x09},
- {0x1d, 0x00},
- {0x1e, 0x00},
- {0x1f, 0x00},
- {0x20, 0x00},
- {0x21, 0x00},
- {0x22, 0x00},
- {0x23, 0x00},
- {0x24, 0x00},
- {0x25, 0x4a},
- {0x26, 0x00},
- {0x27, 0x00},
- {0x28, 0x00},
- {0x29, 0x00},
- {0x2a, 0x00},
- {0x2b, 0x00},
- {0x2c, 0x00},
- {0x2d, 0x4a},
- {0x2e, 0x00},
- {0x2f, 0x0a},
- {0x30, 0x26},
- {0x31, 0x5b},
- {0x32, 0x00},
- {0x33, 0x00},
- {0x34, 0x00},
- {0x35, 0x00},
- {0x36, 0xaa},
- {0x37, 0xaa},
- {0x38, 0xff},
- {0x39, 0xff},
- {0x3a, 0x79},
- {0x3b, 0x00},
- {0x3c, 0x00},
- {0x3d, 0x0b},
- {0x3e, 0x48},
- {0x3f, 0x04},
- {0x40, 0x00},
- {0x41, 0x08},
- {0x42, 0x00},
- {0x43, 0x08},
- {0x44, 0x08},
- {0x45, 0x14},
- {0x46, 0x05},
- {0x47, 0x09},
- {0x48, 0x00},
- {0x49, 0x00},
- {0x4a, 0x00},
- {0x4b, 0x00},
- {0x4c, 0x09},
- {0x4d, 0x73},
- {0x4e, 0x00},
- {0x4f, 0xc5},
- {0x50, 0x15},
- {0x51, 0x19},
- {0x52, 0x00},
- {0x53, 0x00},
- {0x54, 0x00},
- {0x55, 0x00},
- {0x56, 0x00},
- {0x57, 0x00},
- {0x58, 0x00},
- {0x59, 0xb0},
- {0x5a, 0x00},
- {0x5b, 0x00},
- {0x5c, 0x00},
- {0x5d, 0x00},
- {0x5e, 0x00},
- {0x5f, 0x00},
- {0x60, 0xe4},
- {0x61, 0x80},
- {0x62, 0x00},
- {0x63, 0x00},
- {0x64, 0x00},
- {0x65, 0x00},
- {0x66, 0x98},
- {0x67, 0x0a},
- {0x68, 0x00},
- {0x69, 0x00},
- {0x6a, 0x00},
- {0x6b, 0x00},
- {0x6c, 0x00}, /* RobertYu:20050125, request by JJSue */
- {0x6d, 0x03},
- {0x6e, 0x01},
- {0x6f, 0x00},
- {0x70, 0x00},
- {0x71, 0x00},
- {0x72, 0x00},
- {0x73, 0x00},
- {0x74, 0x00},
- {0x75, 0x00},
- {0x76, 0x00},
- {0x77, 0x00},
- {0x78, 0x00},
- {0x79, 0x00},
- {0x7a, 0x00},
- {0x7b, 0x00},
- {0x7c, 0x00},
- {0x7d, 0x00},
- {0x7e, 0x00},
- {0x7f, 0x00},
- {0x80, 0x8c},
- {0x81, 0x01},
- {0x82, 0x09},
- {0x83, 0x00},
- {0x84, 0x00},
- {0x85, 0x00},
- {0x86, 0x00},
- {0x87, 0x00},
- {0x88, 0x08},
- {0x89, 0x00},
- {0x8a, 0x0f},
- {0x8b, 0xb7},
- {0x8c, 0x88},
- {0x8d, 0x47},
- {0x8e, 0xaa},
- {0x8f, 0x02},
- {0x90, 0x22},
- {0x91, 0x00},
- {0x92, 0x00},
- {0x93, 0x00},
- {0x94, 0x00},
- {0x95, 0x00},
- {0x96, 0x00},
- {0x97, 0xeb},
- {0x98, 0x00},
- {0x99, 0x00},
- {0x9a, 0x00},
- {0x9b, 0x00},
- {0x9c, 0x00},
- {0x9d, 0x00},
- {0x9e, 0x00},
- {0x9f, 0x01},
- {0xa0, 0x00},
- {0xa1, 0x00},
- {0xa2, 0x00},
- {0xa3, 0x00},
- {0xa4, 0x00},
- {0xa5, 0x00},
- {0xa6, 0x10},
- {0xa7, 0x00},
- {0xa8, 0x18},
- {0xa9, 0x00},
- {0xaa, 0x00},
- {0xab, 0x00},
- {0xac, 0x00},
- {0xad, 0x00},
- {0xae, 0x00},
- {0xaf, 0x18},
- {0xb0, 0x38},
- {0xb1, 0x30},
- {0xb2, 0x00},
- {0xb3, 0x00},
- {0xb4, 0xff},
- {0xb5, 0x0f},
- {0xb6, 0xe4},
- {0xb7, 0xe2},
- {0xb8, 0x00},
- {0xb9, 0x00},
- {0xba, 0x00},
- {0xbb, 0x03},
- {0xbc, 0x01},
- {0xbd, 0x00},
- {0xbe, 0x00},
- {0xbf, 0x00},
- {0xc0, 0x18},
- {0xc1, 0x20},
- {0xc2, 0x07},
- {0xc3, 0x18},
- {0xc4, 0xff},
- {0xc5, 0x2c},
- {0xc6, 0x0c},
- {0xc7, 0x0a},
- {0xc8, 0x0e},
- {0xc9, 0x01},
- {0xca, 0x68},
- {0xcb, 0xa7},
- {0xcc, 0x3c},
- {0xcd, 0x10},
- {0xce, 0x00},
- {0xcf, 0x25},
- {0xd0, 0x40},
- {0xd1, 0x12},
- {0xd2, 0x00},
- {0xd3, 0x00},
- {0xd4, 0x10},
- {0xd5, 0x28},
- {0xd6, 0x80},
- {0xd7, 0x2A},
- {0xd8, 0x00},
- {0xd9, 0x00},
- {0xda, 0x00},
- {0xdb, 0x00},
- {0xdc, 0x00},
- {0xdd, 0x00},
- {0xde, 0x00},
- {0xdf, 0x00},
- {0xe0, 0x00},
- {0xe1, 0xB3},
- {0xe2, 0x00},
- {0xe3, 0x00},
- {0xe4, 0x00},
- {0xe5, 0x10},
- {0xe6, 0x00},
- {0xe7, 0x1C},
- {0xe8, 0x00},
- {0xe9, 0xf4},
- {0xea, 0x00},
- {0xeb, 0xff},
- {0xec, 0x79},
- {0xed, 0x20},
- {0xee, 0x30},
- {0xef, 0x01},
- {0xf0, 0x00},
- {0xf1, 0x3e},
- {0xf2, 0x00},
- {0xf3, 0x00},
- {0xf4, 0x00},
- {0xf5, 0x00},
- {0xf6, 0x00},
- {0xf7, 0x00},
- {0xf8, 0x00},
- {0xf9, 0x00},
- {0xfa, 0x00},
- {0xfb, 0x00},
- {0xfc, 0x00},
- {0xfd, 0x00},
- {0xfe, 0x00},
- {0xff, 0x00},
-};
-
-#define CB_VT3253B0_INIT_FOR_UW2451 256
-/* For UW2451 */
-static unsigned char vt3253b0_uw2451[CB_VT3253B0_INIT_FOR_UW2451][2] = {
- {0x00, 0x31},
- {0x01, 0x00},
- {0x02, 0x00},
- {0x03, 0x00},
- {0x04, 0x00},
- {0x05, 0x81},
- {0x06, 0x00},
- {0x07, 0x00},
- {0x08, 0x38},
- {0x09, 0x45},
- {0x0a, 0x28},
- {0x0b, 0x76},
- {0x0c, 0x00},
- {0x0d, 0x00},
- {0x0e, 0x80},
- {0x0f, 0x00},
- {0x10, 0x00},
- {0x11, 0x00},
- {0x12, 0x00},
- {0x13, 0x00},
- {0x14, 0x00},
- {0x15, 0x00},
- {0x16, 0x00},
- {0x17, 0x00},
- {0x18, 0x00},
- {0x19, 0x00},
- {0x1a, 0x00},
- {0x1b, 0x8f},
- {0x1c, 0x0f},
- {0x1d, 0x00},
- {0x1e, 0x00},
- {0x1f, 0x00},
- {0x20, 0x00},
- {0x21, 0x00},
- {0x22, 0x00},
- {0x23, 0x00},
- {0x24, 0x00},
- {0x25, 0x4a},
- {0x26, 0x00},
- {0x27, 0x00},
- {0x28, 0x00},
- {0x29, 0x00},
- {0x2a, 0x00},
- {0x2b, 0x00},
- {0x2c, 0x00},
- {0x2d, 0x18},
- {0x2e, 0x00},
- {0x2f, 0x0a},
- {0x30, 0x26},
- {0x31, 0x5b},
- {0x32, 0x00},
- {0x33, 0x00},
- {0x34, 0x00},
- {0x35, 0x00},
- {0x36, 0xaa},
- {0x37, 0xaa},
- {0x38, 0xff},
- {0x39, 0xff},
- {0x3a, 0x00},
- {0x3b, 0x00},
- {0x3c, 0x00},
- {0x3d, 0x03},
- {0x3e, 0x1d},
- {0x3f, 0x04},
- {0x40, 0x00},
- {0x41, 0x08},
- {0x42, 0x00},
- {0x43, 0x08},
- {0x44, 0x08},
- {0x45, 0x14},
- {0x46, 0x05},
- {0x47, 0x09},
- {0x48, 0x00},
- {0x49, 0x00},
- {0x4a, 0x00},
- {0x4b, 0x00},
- {0x4c, 0x09},
- {0x4d, 0x90},
- {0x4e, 0x00},
- {0x4f, 0xc5},
- {0x50, 0x15},
- {0x51, 0x19},
- {0x52, 0x00},
- {0x53, 0x00},
- {0x54, 0x00},
- {0x55, 0x00},
- {0x56, 0x00},
- {0x57, 0x00},
- {0x58, 0x00},
- {0x59, 0xb0},
- {0x5a, 0x00},
- {0x5b, 0x00},
- {0x5c, 0x00},
- {0x5d, 0x00},
- {0x5e, 0x00},
- {0x5f, 0x00},
- {0x60, 0xb3},
- {0x61, 0x81},
- {0x62, 0x00},
- {0x63, 0x00},
- {0x64, 0x00},
- {0x65, 0x00},
- {0x66, 0x57},
- {0x67, 0x6c},
- {0x68, 0x00},
- {0x69, 0x00},
- {0x6a, 0x00},
- {0x6b, 0x00},
- {0x6c, 0x00}, /* RobertYu:20050125, request by JJSue */
- {0x6d, 0x03},
- {0x6e, 0x01},
- {0x6f, 0x00},
- {0x70, 0x00},
- {0x71, 0x00},
- {0x72, 0x00},
- {0x73, 0x00},
- {0x74, 0x00},
- {0x75, 0x00},
- {0x76, 0x00},
- {0x77, 0x00},
- {0x78, 0x00},
- {0x79, 0x00},
- {0x7a, 0x00},
- {0x7b, 0x00},
- {0x7c, 0x00},
- {0x7d, 0x00},
- {0x7e, 0x00},
- {0x7f, 0x00},
- {0x80, 0x8c},
- {0x81, 0x00},
- {0x82, 0x0e},
- {0x83, 0x00},
- {0x84, 0x00},
- {0x85, 0x00},
- {0x86, 0x00},
- {0x87, 0x00},
- {0x88, 0x08},
- {0x89, 0x00},
- {0x8a, 0x0e},
- {0x8b, 0xa7},
- {0x8c, 0x88},
- {0x8d, 0x47},
- {0x8e, 0xaa},
- {0x8f, 0x02},
- {0x90, 0x00},
- {0x91, 0x00},
- {0x92, 0x00},
- {0x93, 0x00},
- {0x94, 0x00},
- {0x95, 0x00},
- {0x96, 0x00},
- {0x97, 0xe3},
- {0x98, 0x00},
- {0x99, 0x00},
- {0x9a, 0x00},
- {0x9b, 0x00},
- {0x9c, 0x00},
- {0x9d, 0x00},
- {0x9e, 0x00},
- {0x9f, 0x00},
- {0xa0, 0x00},
- {0xa1, 0x00},
- {0xa2, 0x00},
- {0xa3, 0x00},
- {0xa4, 0x00},
- {0xa5, 0x00},
- {0xa6, 0x10},
- {0xa7, 0x00},
- {0xa8, 0x18},
- {0xa9, 0x00},
- {0xaa, 0x00},
- {0xab, 0x00},
- {0xac, 0x00},
- {0xad, 0x00},
- {0xae, 0x00},
- {0xaf, 0x18},
- {0xb0, 0x18},
- {0xb1, 0x30},
- {0xb2, 0x00},
- {0xb3, 0x00},
- {0xb4, 0x00},
- {0xb5, 0x00},
- {0xb6, 0x00},
- {0xb7, 0x00},
- {0xb8, 0x00},
- {0xb9, 0x00},
- {0xba, 0x00},
- {0xbb, 0x03},
- {0xbc, 0x01},
- {0xbd, 0x00},
- {0xbe, 0x00},
- {0xbf, 0x00},
- {0xc0, 0x10},
- {0xc1, 0x20},
- {0xc2, 0x00},
- {0xc3, 0x20},
- {0xc4, 0x00},
- {0xc5, 0x2c},
- {0xc6, 0x1c},
- {0xc7, 0x10},
- {0xc8, 0x10},
- {0xc9, 0x01},
- {0xca, 0x68},
- {0xcb, 0xa7},
- {0xcc, 0x3c},
- {0xcd, 0x09},
- {0xce, 0x00},
- {0xcf, 0x20},
- {0xd0, 0x40},
- {0xd1, 0x10},
- {0xd2, 0x00},
- {0xd3, 0x00},
- {0xd4, 0x20},
- {0xd5, 0x28},
- {0xd6, 0xa0},
- {0xd7, 0x2a},
- {0xd8, 0x00},
- {0xd9, 0x00},
- {0xda, 0x00},
- {0xdb, 0x00},
- {0xdc, 0x00},
- {0xdd, 0x00},
- {0xde, 0x00},
- {0xdf, 0x00},
- {0xe0, 0x00},
- {0xe1, 0xd3},
- {0xe2, 0xc0},
- {0xe3, 0x00},
- {0xe4, 0x00},
- {0xe5, 0x10},
- {0xe6, 0x00},
- {0xe7, 0x12},
- {0xe8, 0x12},
- {0xe9, 0x34},
- {0xea, 0x00},
- {0xeb, 0xff},
- {0xec, 0x79},
- {0xed, 0x20},
- {0xee, 0x30},
- {0xef, 0x01},
- {0xf0, 0x00},
- {0xf1, 0x3e},
- {0xf2, 0x00},
- {0xf3, 0x00},
- {0xf4, 0x00},
- {0xf5, 0x00},
- {0xf6, 0x00},
- {0xf7, 0x00},
- {0xf8, 0x00},
- {0xf9, 0x00},
- {0xfa, 0x00},
- {0xfb, 0x00},
- {0xfc, 0x00},
- {0xfd, 0x00},
- {0xfe, 0x00},
- {0xff, 0x00},
-};
-
-#define CB_VT3253B0_AGC 193
-/* For AIROHA */
-static unsigned char vt3253b0_agc[CB_VT3253B0_AGC][2] = {
- {0xF0, 0x00},
- {0xF1, 0x00},
- {0xF0, 0x80},
- {0xF0, 0x01},
- {0xF1, 0x00},
- {0xF0, 0x81},
- {0xF0, 0x02},
- {0xF1, 0x02},
- {0xF0, 0x82},
- {0xF0, 0x03},
- {0xF1, 0x04},
- {0xF0, 0x83},
- {0xF0, 0x03},
- {0xF1, 0x04},
- {0xF0, 0x84},
- {0xF0, 0x04},
- {0xF1, 0x06},
- {0xF0, 0x85},
- {0xF0, 0x05},
- {0xF1, 0x06},
- {0xF0, 0x86},
- {0xF0, 0x06},
- {0xF1, 0x06},
- {0xF0, 0x87},
- {0xF0, 0x07},
- {0xF1, 0x08},
- {0xF0, 0x88},
- {0xF0, 0x08},
- {0xF1, 0x08},
- {0xF0, 0x89},
- {0xF0, 0x09},
- {0xF1, 0x0A},
- {0xF0, 0x8A},
- {0xF0, 0x0A},
- {0xF1, 0x0A},
- {0xF0, 0x8B},
- {0xF0, 0x0B},
- {0xF1, 0x0C},
- {0xF0, 0x8C},
- {0xF0, 0x0C},
- {0xF1, 0x0C},
- {0xF0, 0x8D},
- {0xF0, 0x0D},
- {0xF1, 0x0E},
- {0xF0, 0x8E},
- {0xF0, 0x0E},
- {0xF1, 0x0E},
- {0xF0, 0x8F},
- {0xF0, 0x0F},
- {0xF1, 0x10},
- {0xF0, 0x90},
- {0xF0, 0x10},
- {0xF1, 0x10},
- {0xF0, 0x91},
- {0xF0, 0x11},
- {0xF1, 0x12},
- {0xF0, 0x92},
- {0xF0, 0x12},
- {0xF1, 0x12},
- {0xF0, 0x93},
- {0xF0, 0x13},
- {0xF1, 0x14},
- {0xF0, 0x94},
- {0xF0, 0x14},
- {0xF1, 0x14},
- {0xF0, 0x95},
- {0xF0, 0x15},
- {0xF1, 0x16},
- {0xF0, 0x96},
- {0xF0, 0x16},
- {0xF1, 0x16},
- {0xF0, 0x97},
- {0xF0, 0x17},
- {0xF1, 0x18},
- {0xF0, 0x98},
- {0xF0, 0x18},
- {0xF1, 0x18},
- {0xF0, 0x99},
- {0xF0, 0x19},
- {0xF1, 0x1A},
- {0xF0, 0x9A},
- {0xF0, 0x1A},
- {0xF1, 0x1A},
- {0xF0, 0x9B},
- {0xF0, 0x1B},
- {0xF1, 0x1C},
- {0xF0, 0x9C},
- {0xF0, 0x1C},
- {0xF1, 0x1C},
- {0xF0, 0x9D},
- {0xF0, 0x1D},
- {0xF1, 0x1E},
- {0xF0, 0x9E},
- {0xF0, 0x1E},
- {0xF1, 0x1E},
- {0xF0, 0x9F},
- {0xF0, 0x1F},
- {0xF1, 0x20},
- {0xF0, 0xA0},
- {0xF0, 0x20},
- {0xF1, 0x20},
- {0xF0, 0xA1},
- {0xF0, 0x21},
- {0xF1, 0x22},
- {0xF0, 0xA2},
- {0xF0, 0x22},
- {0xF1, 0x22},
- {0xF0, 0xA3},
- {0xF0, 0x23},
- {0xF1, 0x24},
- {0xF0, 0xA4},
- {0xF0, 0x24},
- {0xF1, 0x24},
- {0xF0, 0xA5},
- {0xF0, 0x25},
- {0xF1, 0x26},
- {0xF0, 0xA6},
- {0xF0, 0x26},
- {0xF1, 0x26},
- {0xF0, 0xA7},
- {0xF0, 0x27},
- {0xF1, 0x28},
- {0xF0, 0xA8},
- {0xF0, 0x28},
- {0xF1, 0x28},
- {0xF0, 0xA9},
- {0xF0, 0x29},
- {0xF1, 0x2A},
- {0xF0, 0xAA},
- {0xF0, 0x2A},
- {0xF1, 0x2A},
- {0xF0, 0xAB},
- {0xF0, 0x2B},
- {0xF1, 0x2C},
- {0xF0, 0xAC},
- {0xF0, 0x2C},
- {0xF1, 0x2C},
- {0xF0, 0xAD},
- {0xF0, 0x2D},
- {0xF1, 0x2E},
- {0xF0, 0xAE},
- {0xF0, 0x2E},
- {0xF1, 0x2E},
- {0xF0, 0xAF},
- {0xF0, 0x2F},
- {0xF1, 0x30},
- {0xF0, 0xB0},
- {0xF0, 0x30},
- {0xF1, 0x30},
- {0xF0, 0xB1},
- {0xF0, 0x31},
- {0xF1, 0x32},
- {0xF0, 0xB2},
- {0xF0, 0x32},
- {0xF1, 0x32},
- {0xF0, 0xB3},
- {0xF0, 0x33},
- {0xF1, 0x34},
- {0xF0, 0xB4},
- {0xF0, 0x34},
- {0xF1, 0x34},
- {0xF0, 0xB5},
- {0xF0, 0x35},
- {0xF1, 0x36},
- {0xF0, 0xB6},
- {0xF0, 0x36},
- {0xF1, 0x36},
- {0xF0, 0xB7},
- {0xF0, 0x37},
- {0xF1, 0x38},
- {0xF0, 0xB8},
- {0xF0, 0x38},
- {0xF1, 0x38},
- {0xF0, 0xB9},
- {0xF0, 0x39},
- {0xF1, 0x3A},
- {0xF0, 0xBA},
- {0xF0, 0x3A},
- {0xF1, 0x3A},
- {0xF0, 0xBB},
- {0xF0, 0x3B},
- {0xF1, 0x3C},
- {0xF0, 0xBC},
- {0xF0, 0x3C},
- {0xF1, 0x3C},
- {0xF0, 0xBD},
- {0xF0, 0x3D},
- {0xF1, 0x3E},
- {0xF0, 0xBE},
- {0xF0, 0x3E},
- {0xF1, 0x3E},
- {0xF0, 0xBF},
- {0xF0, 0x00},
-};
-
-static const unsigned short awc_frame_time[MAX_RATE] = {
- 10, 20, 55, 110, 24, 36, 48, 72, 96, 144, 192, 216
-};
-
-/*--------------------- Export Variables --------------------------*/
-/*
- * Description: Calculate data frame transmitting time
- *
- * Parameters:
- * In:
- * preamble_type - Preamble Type
- * by_pkt_type - PK_TYPE_11A, PK_TYPE_11B, PK_TYPE_11GB, PK_TYPE_11GA
- * cb_frame_length - Baseband Type
- * tx_rate - Tx Rate
- * Out:
- *
- * Return Value: FrameTime
- *
- */
-unsigned int bb_get_frame_time(unsigned char preamble_type,
- unsigned char by_pkt_type,
- unsigned int cb_frame_length,
- unsigned short tx_rate)
-{
- unsigned int frame_time;
- unsigned int preamble;
- unsigned int tmp;
- unsigned int rate_idx = (unsigned int)tx_rate;
- unsigned int rate = 0;
-
- if (rate_idx > RATE_54M)
- return 0;
-
- rate = (unsigned int)awc_frame_time[rate_idx];
-
- if (rate_idx <= 3) { /* CCK mode */
- if (preamble_type == PREAMBLE_SHORT)
- preamble = 96;
- else
- preamble = 192;
- frame_time = (cb_frame_length * 80) / rate; /* ????? */
- tmp = (frame_time * rate) / 80;
- if (cb_frame_length != tmp)
- frame_time++;
-
- return preamble + frame_time;
- }
- frame_time = (cb_frame_length * 8 + 22) / rate; /* ???????? */
- tmp = ((frame_time * rate) - 22) / 8;
- if (cb_frame_length != tmp)
- frame_time++;
-
- frame_time = frame_time * 4; /* ??????? */
- if (by_pkt_type != PK_TYPE_11A)
- frame_time += 6; /* ?????? */
-
- return 20 + frame_time; /* ?????? */
-}
-
-/*
- * Description: Calculate Length, Service, and Signal fields of Phy for Tx
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * frame_length - Tx Frame Length
- * tx_rate - Tx Rate
- * Out:
- * struct vnt_phy_field *phy
- * - pointer to Phy Length field
- * - pointer to Phy Service field
- * - pointer to Phy Signal field
- *
- * Return Value: none
- *
- */
-void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length,
- u16 tx_rate, u8 pkt_type, struct vnt_phy_field *phy)
-{
- u32 bit_count;
- u32 count = 0;
- u32 tmp;
- int ext_bit;
- u8 preamble_type = priv->preamble_type;
-
- bit_count = frame_length * 8;
- ext_bit = false;
-
- switch (tx_rate) {
- case RATE_1M:
- count = bit_count;
-
- phy->signal = 0x00;
-
- break;
- case RATE_2M:
- count = bit_count / 2;
-
- if (preamble_type == PREAMBLE_SHORT)
- phy->signal = 0x09;
- else
- phy->signal = 0x01;
-
- break;
- case RATE_5M:
- count = (bit_count * 10) / 55;
- tmp = (count * 55) / 10;
-
- if (tmp != bit_count)
- count++;
-
- if (preamble_type == PREAMBLE_SHORT)
- phy->signal = 0x0a;
- else
- phy->signal = 0x02;
-
- break;
- case RATE_11M:
- count = bit_count / 11;
- tmp = count * 11;
-
- if (tmp != bit_count) {
- count++;
-
- if ((bit_count - tmp) <= 3)
- ext_bit = true;
- }
-
- if (preamble_type == PREAMBLE_SHORT)
- phy->signal = 0x0b;
- else
- phy->signal = 0x03;
-
- break;
- case RATE_6M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9b;
- else
- phy->signal = 0x8b;
-
- break;
- case RATE_9M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9f;
- else
- phy->signal = 0x8f;
-
- break;
- case RATE_12M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9a;
- else
- phy->signal = 0x8a;
-
- break;
- case RATE_18M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9e;
- else
- phy->signal = 0x8e;
-
- break;
- case RATE_24M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x99;
- else
- phy->signal = 0x89;
-
- break;
- case RATE_36M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9d;
- else
- phy->signal = 0x8d;
-
- break;
- case RATE_48M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x98;
- else
- phy->signal = 0x88;
-
- break;
- case RATE_54M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9c;
- else
- phy->signal = 0x8c;
- break;
- default:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9c;
- else
- phy->signal = 0x8c;
- break;
- }
-
- if (pkt_type == PK_TYPE_11B) {
- phy->service = 0x00;
- if (ext_bit)
- phy->service |= 0x80;
- phy->len = cpu_to_le16((u16)count);
- } else {
- phy->service = 0x00;
- phy->len = cpu_to_le16((u16)frame_length);
- }
-}
-
-/*
- * Description: Read a byte from BASEBAND, by embedded programming
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * by_bb_addr - address of register in Baseband
- * Out:
- * pby_data - data read
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool bb_read_embedded(struct vnt_private *priv, unsigned char by_bb_addr,
- unsigned char *pby_data)
-{
- void __iomem *iobase = priv->port_offset;
- unsigned short ww;
- unsigned char by_value;
-
- /* BB reg offset */
- iowrite8(by_bb_addr, iobase + MAC_REG_BBREGADR);
-
- /* turn on REGR */
- vt6655_mac_reg_bits_on(iobase, MAC_REG_BBREGCTL, BBREGCTL_REGR);
- /* W_MAX_TIMEOUT is the timeout period */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- by_value = ioread8(iobase + MAC_REG_BBREGCTL);
- if (by_value & BBREGCTL_DONE)
- break;
- }
-
- /* get BB data */
- *pby_data = ioread8(iobase + MAC_REG_BBREGDATA);
-
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x30)\n");
- return false;
- }
- return true;
-}
-
-/*
- * Description: Write a Byte to BASEBAND, by embedded programming
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * by_bb_addr - address of register in Baseband
- * by_data - data to write
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool bb_write_embedded(struct vnt_private *priv, unsigned char by_bb_addr,
- unsigned char by_data)
-{
- void __iomem *iobase = priv->port_offset;
- unsigned short ww;
- unsigned char by_value;
-
- /* BB reg offset */
- iowrite8(by_bb_addr, iobase + MAC_REG_BBREGADR);
- /* set BB data */
- iowrite8(by_data, iobase + MAC_REG_BBREGDATA);
-
- /* turn on BBREGCTL_REGW */
- vt6655_mac_reg_bits_on(iobase, MAC_REG_BBREGCTL, BBREGCTL_REGW);
- /* W_MAX_TIMEOUT is the timeout period */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- by_value = ioread8(iobase + MAC_REG_BBREGCTL);
- if (by_value & BBREGCTL_DONE)
- break;
- }
-
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x31)\n");
- return false;
- }
- return true;
-}
-
-/*
- * Description: VIA VT3253 Baseband chip init function
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * byRevId - Revision ID
- * rf_type - RF type
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-
-bool bb_vt3253_init(struct vnt_private *priv)
-{
- bool result = true;
- int ii;
- void __iomem *iobase = priv->port_offset;
- unsigned char rf_type = priv->rf_type;
- unsigned char by_local_id = priv->local_id;
-
- if (rf_type == RF_RFMD2959) {
- if (by_local_id <= REV_ID_VT3253_A1) {
- for (ii = 0; ii < CB_VT3253_INIT_FOR_RFMD; ii++)
- result &= bb_write_embedded(priv,
- by_vt3253_init_tab_rfmd[ii][0],
- by_vt3253_init_tab_rfmd[ii][1]);
-
- } else {
- for (ii = 0; ii < CB_VT3253B0_INIT_FOR_RFMD; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_rfmd[ii][0],
- vt3253b0_rfmd[ii][1]);
-
- for (ii = 0; ii < CB_VT3253B0_AGC_FOR_RFMD2959; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_agc4_rfmd2959[ii][0],
- vt3253b0_agc4_rfmd2959[ii][1]);
-
- iowrite32(0x23, iobase + MAC_REG_ITRTMSET);
- vt6655_mac_reg_bits_on(iobase, MAC_REG_PAPEDELAY, BIT(0));
- }
- priv->bbvga[0] = 0x18;
- priv->bbvga[1] = 0x0A;
- priv->bbvga[2] = 0x0;
- priv->bbvga[3] = 0x0;
- priv->dbm_threshold[0] = -70;
- priv->dbm_threshold[1] = -50;
- priv->dbm_threshold[2] = 0;
- priv->dbm_threshold[3] = 0;
- } else if ((rf_type == RF_AIROHA) || (rf_type == RF_AL2230S)) {
- for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_airoha2230[ii][0],
- vt3253b0_airoha2230[ii][1]);
-
- for (ii = 0; ii < CB_VT3253B0_AGC; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_agc[ii][0], vt3253b0_agc[ii][1]);
-
- priv->bbvga[0] = 0x1C;
- priv->bbvga[1] = 0x10;
- priv->bbvga[2] = 0x0;
- priv->bbvga[3] = 0x0;
- priv->dbm_threshold[0] = -70;
- priv->dbm_threshold[1] = -48;
- priv->dbm_threshold[2] = 0;
- priv->dbm_threshold[3] = 0;
- } else if (rf_type == RF_UW2451) {
- for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_uw2451[ii][0],
- vt3253b0_uw2451[ii][1]);
-
- for (ii = 0; ii < CB_VT3253B0_AGC; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_agc[ii][0],
- vt3253b0_agc[ii][1]);
-
- iowrite8(0x23, iobase + MAC_REG_ITRTMSET);
- vt6655_mac_reg_bits_on(iobase, MAC_REG_PAPEDELAY, BIT(0));
-
- priv->bbvga[0] = 0x14;
- priv->bbvga[1] = 0x0A;
- priv->bbvga[2] = 0x0;
- priv->bbvga[3] = 0x0;
- priv->dbm_threshold[0] = -60;
- priv->dbm_threshold[1] = -50;
- priv->dbm_threshold[2] = 0;
- priv->dbm_threshold[3] = 0;
- } else if (rf_type == RF_VT3226) {
- for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_airoha2230[ii][0],
- vt3253b0_airoha2230[ii][1]);
-
- for (ii = 0; ii < CB_VT3253B0_AGC; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_agc[ii][0], vt3253b0_agc[ii][1]);
-
- priv->bbvga[0] = 0x1C;
- priv->bbvga[1] = 0x10;
- priv->bbvga[2] = 0x0;
- priv->bbvga[3] = 0x0;
- priv->dbm_threshold[0] = -70;
- priv->dbm_threshold[1] = -48;
- priv->dbm_threshold[2] = 0;
- priv->dbm_threshold[3] = 0;
- /* Fix VT3226 DFC system timing issue */
- vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT);
- /* {{ RobertYu: 20050104 */
- } else {
- /* No VGA Table now */
- priv->update_bbvga = false;
- priv->bbvga[0] = 0x1C;
- }
-
- if (by_local_id > REV_ID_VT3253_A1) {
- bb_write_embedded(priv, 0x04, 0x7F);
- bb_write_embedded(priv, 0x0D, 0x01);
- }
-
- return result;
-}
-
-/*
- * Description: Set ShortSlotTime mode
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void
-bb_set_short_slot_time(struct vnt_private *priv)
-{
- unsigned char by_bb_rx_conf = 0;
- unsigned char by_bb_vga = 0;
-
- bb_read_embedded(priv, 0x0A, &by_bb_rx_conf); /* CR10 */
-
- if (priv->short_slot_time)
- by_bb_rx_conf &= 0xDF; /* 1101 1111 */
- else
- by_bb_rx_conf |= 0x20; /* 0010 0000 */
-
- /* patch for 3253B0 Baseband with Cardbus module */
- bb_read_embedded(priv, 0xE7, &by_bb_vga);
- if (by_bb_vga == priv->bbvga[0])
- by_bb_rx_conf |= 0x20; /* 0010 0000 */
-
- bb_write_embedded(priv, 0x0A, by_bb_rx_conf); /* CR10 */
-}
-
-void bb_set_vga_gain_offset(struct vnt_private *priv, unsigned char by_data)
-{
- unsigned char by_bb_rx_conf = 0;
-
- bb_write_embedded(priv, 0xE7, by_data);
-
- bb_read_embedded(priv, 0x0A, &by_bb_rx_conf); /* CR10 */
- /* patch for 3253B0 Baseband with Cardbus module */
- if (by_data == priv->bbvga[0])
- by_bb_rx_conf |= 0x20; /* 0010 0000 */
- else if (priv->short_slot_time)
- by_bb_rx_conf &= 0xDF; /* 1101 1111 */
- else
- by_bb_rx_conf |= 0x20; /* 0010 0000 */
- priv->bbvga_current = by_data;
- bb_write_embedded(priv, 0x0A, by_bb_rx_conf); /* CR10 */
-}
-
-/*
- * Description: Baseband SoftwareReset
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void
-bb_software_reset(struct vnt_private *priv)
-{
- bb_write_embedded(priv, 0x50, 0x40);
- bb_write_embedded(priv, 0x50, 0);
- bb_write_embedded(priv, 0x9C, 0x01);
- bb_write_embedded(priv, 0x9C, 0);
-}
-
-/*
- * Description: Set Tx Antenna mode
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * by_antenna_mode - Antenna Mode
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-
-void
-bb_set_tx_antenna_mode(struct vnt_private *priv, unsigned char by_antenna_mode)
-{
- unsigned char by_bb_tx_conf;
-
- bb_read_embedded(priv, 0x09, &by_bb_tx_conf); /* CR09 */
- if (by_antenna_mode == ANT_DIVERSITY) {
- /* bit 1 is diversity */
- by_bb_tx_conf |= 0x02;
- } else if (by_antenna_mode == ANT_A) {
- /* bit 2 is ANTSEL */
- by_bb_tx_conf &= 0xF9; /* 1111 1001 */
- } else if (by_antenna_mode == ANT_B) {
- by_bb_tx_conf &= 0xFD; /* 1111 1101 */
- by_bb_tx_conf |= 0x04;
- }
- bb_write_embedded(priv, 0x09, by_bb_tx_conf); /* CR09 */
-}
-
-/*
- * Description: Set Rx Antenna mode
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * by_antenna_mode - Antenna Mode
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-
-void
-bb_set_rx_antenna_mode(struct vnt_private *priv, unsigned char by_antenna_mode)
-{
- unsigned char by_bb_rx_conf;
-
- bb_read_embedded(priv, 0x0A, &by_bb_rx_conf); /* CR10 */
- if (by_antenna_mode == ANT_DIVERSITY) {
- by_bb_rx_conf |= 0x01;
-
- } else if (by_antenna_mode == ANT_A) {
- by_bb_rx_conf &= 0xFC; /* 1111 1100 */
- } else if (by_antenna_mode == ANT_B) {
- by_bb_rx_conf &= 0xFE; /* 1111 1110 */
- by_bb_rx_conf |= 0x02;
- }
- bb_write_embedded(priv, 0x0A, by_bb_rx_conf); /* CR10 */
-}
-
-/*
- * Description: bb_set_deep_sleep
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void
-bb_set_deep_sleep(struct vnt_private *priv, unsigned char by_local_id)
-{
- bb_write_embedded(priv, 0x0C, 0x17); /* CR12 */
- bb_write_embedded(priv, 0x0D, 0xB9); /* CR13 */
-}
-
diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h
deleted file mode 100644
index e4a02c240a1c..000000000000
--- a/drivers/staging/vt6655/baseband.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions to access baseband
- *
- * Author: Jerry Chen
- *
- * Date: Jun. 5, 2002
- *
- */
-
-#ifndef __BASEBAND_H__
-#define __BASEBAND_H__
-
-#include "device.h"
-
-/*
- * Registers in the BASEBAND
- */
-#define BB_MAX_CONTEXT_SIZE 256
-
-/*
- * Baseband RF pair definition in eeprom (Bits 6..0)
- */
-
-#define PREAMBLE_LONG 0
-#define PREAMBLE_SHORT 1
-
-#define F5G 0
-#define F2_4G 1
-
-#define TOP_RATE_54M 0x80000000
-#define TOP_RATE_48M 0x40000000
-#define TOP_RATE_36M 0x20000000
-#define TOP_RATE_24M 0x10000000
-#define TOP_RATE_18M 0x08000000
-#define TOP_RATE_12M 0x04000000
-#define TOP_RATE_11M 0x02000000
-#define TOP_RATE_9M 0x01000000
-#define TOP_RATE_6M 0x00800000
-#define TOP_RATE_55M 0x00400000
-#define TOP_RATE_2M 0x00200000
-#define TOP_RATE_1M 0x00100000
-
-unsigned int bb_get_frame_time(unsigned char preamble_type,
- unsigned char by_pkt_type,
- unsigned int cb_frame_length,
- unsigned short w_rate);
-
-void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length,
- u16 tx_rate, u8 pkt_type, struct vnt_phy_field *phy);
-
-bool bb_read_embedded(struct vnt_private *priv, unsigned char by_bb_addr,
- unsigned char *pby_data);
-bool bb_write_embedded(struct vnt_private *priv, unsigned char by_bb_addr,
- unsigned char by_data);
-
-void bb_set_short_slot_time(struct vnt_private *priv);
-void bb_set_vga_gain_offset(struct vnt_private *priv, unsigned char by_data);
-
-/* VT3253 Baseband */
-bool bb_vt3253_init(struct vnt_private *priv);
-void bb_software_reset(struct vnt_private *priv);
-void bb_set_tx_antenna_mode(struct vnt_private *priv,
- unsigned char by_antenna_mode);
-void bb_set_rx_antenna_mode(struct vnt_private *priv,
- unsigned char by_antenna_mode);
-void bb_set_deep_sleep(struct vnt_private *priv, unsigned char by_local_id);
-
-#endif /* __BASEBAND_H__ */
diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c
deleted file mode 100644
index 6a2e390e9493..000000000000
--- a/drivers/staging/vt6655/card.c
+++ /dev/null
@@ -1,836 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Provide functions to setup NIC operation mode
- * Functions:
- * s_vSafeResetTx - Rest Tx
- * card_set_rspinf - Set RSPINF
- * CARDvUpdateBasicTopRate - Update BasicTopRate
- * CARDbAddBasicRate - Add to BasicRateSet
- * CARDbIsOFDMinBasicRate - Check if any OFDM rate is in BasicRateSet
- * card_get_tsf_offset - Calculate TSFOffset
- * vt6655_get_current_tsf - Read Current NIC TSF counter
- * card_get_next_tbtt - Calculate Next Beacon TSF counter
- * CARDvSetFirstNextTBTT - Set NIC Beacon time
- * CARDvUpdateNextTBTT - Sync. NIC Beacon time
- * card_radio_power_off - Turn Off NIC Radio Power
- *
- * Revision History:
- * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
- * 08-26-2003 Kyle Hsu: Modify the definition type of iobase.
- * 09-01-2003 Bryan YC Fan: Add vUpdateIFS().
- *
- */
-
-#include "card.h"
-#include "baseband.h"
-#include "mac.h"
-#include "desc.h"
-#include "rf.h"
-#include "power.h"
-
-/*--------------------- Static Definitions -------------------------*/
-
-#define C_SIFS_A 16 /* micro sec. */
-#define C_SIFS_BG 10
-
-#define C_EIFS 80 /* micro sec. */
-
-#define C_SLOT_SHORT 9 /* micro sec. */
-#define C_SLOT_LONG 20
-
-#define C_CWMIN_A 15 /* slot time */
-#define C_CWMIN_B 31
-
-#define C_CWMAX 1023 /* slot time */
-
-#define WAIT_BEACON_TX_DOWN_TMO 3 /* Times */
-
-/*--------------------- Static Variables --------------------------*/
-
-static const unsigned short rx_bcn_tsf_off[MAX_RATE] = {
- 17, 17, 17, 17, 34, 23, 17, 11, 8, 5, 4, 3};
-
-/*--------------------- Static Functions --------------------------*/
-
-static void vt6655_mac_set_bb_type(void __iomem *iobase, u32 mask)
-{
- u32 reg_value;
-
- reg_value = ioread32(iobase + MAC_REG_ENCFG);
- reg_value = reg_value & ~ENCFG_BBTYPE_MASK;
- reg_value = reg_value | mask;
- iowrite32(reg_value, iobase + MAC_REG_ENCFG);
-}
-
-/*--------------------- Export Functions --------------------------*/
-
-/*
- * Description: Calculate TxRate and RsvTime fields for RSPINF in OFDM mode.
- *
- * Parameters:
- * In:
- * wRate - Tx Rate
- * byPktType - Tx Packet type
- * Out:
- * tx_rate - pointer to RSPINF TxRate field
- * rsv_time - pointer to RSPINF RsvTime field
- *
- * Return Value: none
- */
-static void calculate_ofdmr_parameter(unsigned char rate,
- u8 bb_type,
- unsigned char *tx_rate,
- unsigned char *rsv_time)
-{
- switch (rate) {
- case RATE_6M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x9B;
- *rsv_time = 44;
- } else {
- *tx_rate = 0x8B;
- *rsv_time = 50;
- }
- break;
-
- case RATE_9M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x9F;
- *rsv_time = 36;
- } else {
- *tx_rate = 0x8F;
- *rsv_time = 42;
- }
- break;
-
- case RATE_12M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x9A;
- *rsv_time = 32;
- } else {
- *tx_rate = 0x8A;
- *rsv_time = 38;
- }
- break;
-
- case RATE_18M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x9E;
- *rsv_time = 28;
- } else {
- *tx_rate = 0x8E;
- *rsv_time = 34;
- }
- break;
-
- case RATE_36M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x9D;
- *rsv_time = 24;
- } else {
- *tx_rate = 0x8D;
- *rsv_time = 30;
- }
- break;
-
- case RATE_48M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x98;
- *rsv_time = 24;
- } else {
- *tx_rate = 0x88;
- *rsv_time = 30;
- }
- break;
-
- case RATE_54M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x9C;
- *rsv_time = 24;
- } else {
- *tx_rate = 0x8C;
- *rsv_time = 30;
- }
- break;
-
- case RATE_24M:
- default:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x99;
- *rsv_time = 28;
- } else {
- *tx_rate = 0x89;
- *rsv_time = 34;
- }
- break;
- }
-}
-
-/*--------------------- Export Functions --------------------------*/
-
-/*
- * Description: Update IFS
- *
- * Parameters:
- * In:
- * priv - The adapter to be set
- * Out:
- * none
- *
- * Return Value: None.
- */
-bool card_set_phy_parameter(struct vnt_private *priv, u8 bb_type)
-{
- unsigned char cw_max_min = 0;
- unsigned char slot = 0;
- unsigned char sifs = 0;
- unsigned char difs = 0;
- int i;
-
- /* Set SIFS, DIFS, EIFS, SlotTime, CwMin */
- if (bb_type == BB_TYPE_11A) {
- vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11A);
- bb_write_embedded(priv, 0x88, 0x03);
- slot = C_SLOT_SHORT;
- sifs = C_SIFS_A;
- difs = C_SIFS_A + 2 * C_SLOT_SHORT;
- cw_max_min = 0xA4;
- } else if (bb_type == BB_TYPE_11B) {
- vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11B);
- bb_write_embedded(priv, 0x88, 0x02);
- slot = C_SLOT_LONG;
- sifs = C_SIFS_BG;
- difs = C_SIFS_BG + 2 * C_SLOT_LONG;
- cw_max_min = 0xA5;
- } else { /* PK_TYPE_11GA & PK_TYPE_11GB */
- vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11G);
- bb_write_embedded(priv, 0x88, 0x08);
- sifs = C_SIFS_BG;
-
- if (priv->short_slot_time) {
- slot = C_SLOT_SHORT;
- difs = C_SIFS_BG + 2 * C_SLOT_SHORT;
- } else {
- slot = C_SLOT_LONG;
- difs = C_SIFS_BG + 2 * C_SLOT_LONG;
- }
-
- cw_max_min = 0xa4;
-
- for (i = RATE_54M; i >= RATE_6M; i--) {
- if (priv->basic_rates & ((u32)(0x1 << i))) {
- cw_max_min |= 0x1;
- break;
- }
- }
- }
-
- if (priv->rf_type == RF_RFMD2959) {
- /*
- * bcs TX_PE will reserve 3 us hardware's processing
- * time here is 2 us.
- */
- sifs -= 3;
- difs -= 3;
- /*
- * TX_PE will reserve 3 us for MAX2829 A mode only, it is for
- * better TX throughput; MAC will need 2 us to process, so the
- * SIFS, DIFS can be shorter by 2 us.
- */
- }
-
- if (priv->sifs != sifs) {
- priv->sifs = sifs;
- iowrite8(priv->sifs, priv->port_offset + MAC_REG_SIFS);
- }
- if (priv->difs != difs) {
- priv->difs = difs;
- iowrite8(priv->difs, priv->port_offset + MAC_REG_DIFS);
- }
- if (priv->eifs != C_EIFS) {
- priv->eifs = C_EIFS;
- iowrite8(priv->eifs, priv->port_offset + MAC_REG_EIFS);
- }
- if (priv->slot != slot) {
- priv->slot = slot;
- iowrite8(priv->slot, priv->port_offset + MAC_REG_SLOT);
-
- bb_set_short_slot_time(priv);
- }
- if (priv->cw_max_min != cw_max_min) {
- priv->cw_max_min = cw_max_min;
- iowrite8(priv->cw_max_min, priv->port_offset + MAC_REG_CWMAXMIN0);
- }
-
- priv->packet_type = card_get_pkt_type(priv);
-
- card_set_rspinf(priv, bb_type);
-
- return true;
-}
-
-/*
- * Description: Sync. TSF counter to BSS
- * Get TSF offset and write to HW
- *
- * Parameters:
- * In:
- * priv - The adapter to be sync.
- * rx_rate - data rate of receive beacon
- * bss_timestamp - Rx BCN's TSF
- * qwLocalTSF - Local TSF
- * Out:
- * none
- *
- * Return Value: none
- */
-bool card_update_tsf(struct vnt_private *priv, unsigned char rx_rate,
- u64 bss_timestamp)
-{
- u64 local_tsf;
- u64 tsf_offset = 0;
-
- local_tsf = vt6655_get_current_tsf(priv);
-
- if (bss_timestamp != local_tsf) {
- tsf_offset = card_get_tsf_offset(rx_rate, bss_timestamp,
- local_tsf);
- /* adjust TSF, HW's TSF add TSF Offset reg */
- tsf_offset = le64_to_cpu(tsf_offset);
- iowrite32((u32)tsf_offset, priv->port_offset + MAC_REG_TSFOFST);
- iowrite32((u32)(tsf_offset >> 32), priv->port_offset + MAC_REG_TSFOFST + 4);
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TSFSYNCEN);
- }
- return true;
-}
-
-/*
- * Description: Set NIC TSF counter for first Beacon time
- * Get NEXTTBTT from adjusted TSF and Beacon Interval
- *
- * Parameters:
- * In:
- * priv - The adapter to be set.
- * beacon_interval - Beacon Interval
- * Out:
- * none
- *
- * Return Value: true if succeed; otherwise false
- */
-bool card_set_beacon_period(struct vnt_private *priv,
- unsigned short beacon_interval)
-{
- u64 next_tbtt;
-
- next_tbtt = vt6655_get_current_tsf(priv); /* Get Local TSF counter */
-
- next_tbtt = card_get_next_tbtt(next_tbtt, beacon_interval);
-
- /* set HW beacon interval */
- iowrite16(beacon_interval, priv->port_offset + MAC_REG_BI);
- priv->beacon_interval = beacon_interval;
- /* Set NextTBTT */
- next_tbtt = le64_to_cpu(next_tbtt);
- iowrite32((u32)next_tbtt, priv->port_offset + MAC_REG_NEXTTBTT);
- iowrite32((u32)(next_tbtt >> 32), priv->port_offset + MAC_REG_NEXTTBTT + 4);
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
-
- return true;
-}
-
-/*
- * Description: Turn off Radio power
- *
- * Parameters:
- * In:
- * priv - The adapter to be turned off
- * Out:
- * none
- *
- */
-void card_radio_power_off(struct vnt_private *priv)
-{
- if (priv->radio_off)
- return;
-
- switch (priv->rf_type) {
- case RF_RFMD2959:
- vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL,
- SOFTPWRCTL_TXPEINV);
- vt6655_mac_word_reg_bits_on(priv->port_offset, MAC_REG_SOFTPWRCTL,
- SOFTPWRCTL_SWPE1);
- break;
-
- case RF_AIROHA:
- case RF_AL2230S:
- vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL,
- SOFTPWRCTL_SWPE2);
- vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL,
- SOFTPWRCTL_SWPE3);
- break;
- }
-
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_RXON);
-
- bb_set_deep_sleep(priv, priv->local_id);
-
- priv->radio_off = true;
- pr_debug("chester power off\n");
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_GPIOCTL0, LED_ACTSET); /* LED issue */
-}
-
-void card_safe_reset_tx(struct vnt_private *priv)
-{
- unsigned int uu;
- struct vnt_tx_desc *curr_td;
-
- /* initialize TD index */
- priv->tail_td[0] = &priv->ap_td0_rings[0];
- priv->apCurrTD[0] = &priv->ap_td0_rings[0];
-
- priv->tail_td[1] = &priv->ap_td1_rings[0];
- priv->apCurrTD[1] = &priv->ap_td1_rings[0];
-
- for (uu = 0; uu < TYPE_MAXTD; uu++)
- priv->iTDUsed[uu] = 0;
-
- for (uu = 0; uu < priv->opts.tx_descs[0]; uu++) {
- curr_td = &priv->ap_td0_rings[uu];
- curr_td->td0.owner = OWNED_BY_HOST;
- /* init all Tx Packet pointer to NULL */
- }
- for (uu = 0; uu < priv->opts.tx_descs[1]; uu++) {
- curr_td = &priv->ap_td1_rings[uu];
- curr_td->td0.owner = OWNED_BY_HOST;
- /* init all Tx Packet pointer to NULL */
- }
-
- /* set MAC TD pointer */
- vt6655_mac_set_curr_tx_desc_addr(TYPE_TXDMA0, priv, priv->td0_pool_dma);
-
- vt6655_mac_set_curr_tx_desc_addr(TYPE_AC0DMA, priv, priv->td1_pool_dma);
-
- /* set MAC Beacon TX pointer */
- iowrite32((u32)priv->tx_beacon_dma, priv->port_offset + MAC_REG_BCNDMAPTR);
-}
-
-/*
- * Description:
- * Reset Rx
- *
- * Parameters:
- * In:
- * priv - Pointer to the adapter
- * Out:
- * none
- *
- * Return Value: none
- */
-void CARDvSafeResetRx(struct vnt_private *priv)
-{
- unsigned int uu;
- struct vnt_rx_desc *pDesc;
-
- /* initialize RD index */
- priv->pCurrRD[0] = &priv->aRD0Ring[0];
- priv->pCurrRD[1] = &priv->aRD1Ring[0];
-
- /* init state, all RD is chip's */
- for (uu = 0; uu < priv->opts.rx_descs0; uu++) {
- pDesc = &priv->aRD0Ring[uu];
- pDesc->rd0.res_count = cpu_to_le16(priv->rx_buf_sz);
- pDesc->rd0.owner = OWNED_BY_NIC;
- pDesc->rd1.req_count = cpu_to_le16(priv->rx_buf_sz);
- }
-
- /* init state, all RD is chip's */
- for (uu = 0; uu < priv->opts.rx_descs1; uu++) {
- pDesc = &priv->aRD1Ring[uu];
- pDesc->rd0.res_count = cpu_to_le16(priv->rx_buf_sz);
- pDesc->rd0.owner = OWNED_BY_NIC;
- pDesc->rd1.req_count = cpu_to_le16(priv->rx_buf_sz);
- }
-
- /* set perPkt mode */
- iowrite32(RX_PERPKT, priv->port_offset + MAC_REG_RXDMACTL0);
- iowrite32(RX_PERPKT, priv->port_offset + MAC_REG_RXDMACTL1);
- /* set MAC RD pointer */
- vt6655_mac_set_curr_rx_0_desc_addr(priv, priv->rd0_pool_dma);
-
- vt6655_mac_set_curr_rx_1_desc_addr(priv, priv->rd1_pool_dma);
-}
-
-/*
- * Description: Get response Control frame rate in CCK mode
- *
- * Parameters:
- * In:
- * priv - The adapter to be set
- * wRateIdx - Receiving data rate
- * Out:
- * none
- *
- * Return Value: response Control frame rate
- */
-static unsigned short CARDwGetCCKControlRate(struct vnt_private *priv,
- unsigned short wRateIdx)
-{
- unsigned int ui = (unsigned int)wRateIdx;
-
- while (ui > RATE_1M) {
- if (priv->basic_rates & ((u32)0x1 << ui))
- return (unsigned short)ui;
-
- ui--;
- }
- return (unsigned short)RATE_1M;
-}
-
-/*
- * Description: Get response Control frame rate in OFDM mode
- *
- * Parameters:
- * In:
- * priv - The adapter to be set
- * wRateIdx - Receiving data rate
- * Out:
- * none
- *
- * Return Value: response Control frame rate
- */
-static unsigned short CARDwGetOFDMControlRate(struct vnt_private *priv,
- unsigned short wRateIdx)
-{
- unsigned int ui = (unsigned int)wRateIdx;
-
- pr_debug("BASIC RATE: %X\n", priv->basic_rates);
-
- if (!CARDbIsOFDMinBasicRate((void *)priv)) {
- pr_debug("%s:(NO OFDM) %d\n", __func__, wRateIdx);
- if (wRateIdx > RATE_24M)
- wRateIdx = RATE_24M;
- return wRateIdx;
- }
- while (ui > RATE_11M) {
- if (priv->basic_rates & ((u32)0x1 << ui)) {
- pr_debug("%s : %d\n", __func__, ui);
- return (unsigned short)ui;
- }
- ui--;
- }
- pr_debug("%s: 6M\n", __func__);
- return (unsigned short)RATE_24M;
-}
-
-/*
- * Description: Set RSPINF
- *
- * Parameters:
- * In:
- * priv - The adapter to be set
- * Out:
- * none
- *
- * Return Value: None.
- */
-void card_set_rspinf(struct vnt_private *priv, u8 bb_type)
-{
- union vnt_phy_field_swap phy;
- unsigned char byTxRate, byRsvTime; /* For OFDM */
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* Set to Page1 */
- VT6655_MAC_SELECT_PAGE1(priv->port_offset);
-
- /* RSPINF_b_1 */
- vnt_get_phy_field(priv, 14,
- CARDwGetCCKControlRate(priv, RATE_1M),
- PK_TYPE_11B, &phy.field_read);
-
- /* swap over to get correct write order */
- swap(phy.swap[0], phy.swap[1]);
-
- iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_1);
-
- /* RSPINF_b_2 */
- vnt_get_phy_field(priv, 14,
- CARDwGetCCKControlRate(priv, RATE_2M),
- PK_TYPE_11B, &phy.field_read);
-
- swap(phy.swap[0], phy.swap[1]);
-
- iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_2);
-
- /* RSPINF_b_5 */
- vnt_get_phy_field(priv, 14,
- CARDwGetCCKControlRate(priv, RATE_5M),
- PK_TYPE_11B, &phy.field_read);
-
- swap(phy.swap[0], phy.swap[1]);
-
- iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_5);
-
- /* RSPINF_b_11 */
- vnt_get_phy_field(priv, 14,
- CARDwGetCCKControlRate(priv, RATE_11M),
- PK_TYPE_11B, &phy.field_read);
-
- swap(phy.swap[0], phy.swap[1]);
-
- iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_11);
-
- /* RSPINF_a_6 */
- calculate_ofdmr_parameter(RATE_6M,
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_6);
- /* RSPINF_a_9 */
- calculate_ofdmr_parameter(RATE_9M,
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_9);
- /* RSPINF_a_12 */
- calculate_ofdmr_parameter(RATE_12M,
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_12);
- /* RSPINF_a_18 */
- calculate_ofdmr_parameter(RATE_18M,
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_18);
- /* RSPINF_a_24 */
- calculate_ofdmr_parameter(RATE_24M,
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_24);
- /* RSPINF_a_36 */
- calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv,
- RATE_36M),
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_36);
- /* RSPINF_a_48 */
- calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv,
- RATE_48M),
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_48);
- /* RSPINF_a_54 */
- calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv,
- RATE_54M),
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_54);
- /* RSPINF_a_72 */
- calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv,
- RATE_54M),
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_72);
- /* Set to Page0 */
- VT6655_MAC_SELECT_PAGE0(priv->port_offset);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-void CARDvUpdateBasicTopRate(struct vnt_private *priv)
-{
- unsigned char byTopOFDM = RATE_24M, byTopCCK = RATE_1M;
- unsigned char ii;
-
- /* Determines the highest basic rate. */
- for (ii = RATE_54M; ii >= RATE_6M; ii--) {
- if ((priv->basic_rates) & ((u32)(1 << ii))) {
- byTopOFDM = ii;
- break;
- }
- }
- priv->byTopOFDMBasicRate = byTopOFDM;
-
- for (ii = RATE_11M;; ii--) {
- if ((priv->basic_rates) & ((u32)(1 << ii))) {
- byTopCCK = ii;
- break;
- }
- if (ii == RATE_1M)
- break;
- }
- priv->byTopCCKBasicRate = byTopCCK;
-}
-
-bool CARDbIsOFDMinBasicRate(struct vnt_private *priv)
-{
- int ii;
-
- for (ii = RATE_54M; ii >= RATE_6M; ii--) {
- if ((priv->basic_rates) & ((u32)BIT(ii)))
- return true;
- }
- return false;
-}
-
-unsigned char card_get_pkt_type(struct vnt_private *priv)
-{
- if (priv->byBBType == BB_TYPE_11A || priv->byBBType == BB_TYPE_11B)
- return (unsigned char)priv->byBBType;
- else if (CARDbIsOFDMinBasicRate((void *)priv))
- return PK_TYPE_11GA;
- else
- return PK_TYPE_11GB;
-}
-
-/*
- * Description: Calculate TSF offset of two TSF input
- * Get TSF Offset from RxBCN's TSF and local TSF
- *
- * Parameters:
- * In:
- * priv - The adapter to be sync.
- * qwTSF1 - Rx BCN's TSF
- * qwTSF2 - Local TSF
- * Out:
- * none
- *
- * Return Value: TSF Offset value
- */
-u64 card_get_tsf_offset(unsigned char rx_rate, u64 qwTSF1, u64 qwTSF2)
-{
- unsigned short wRxBcnTSFOffst;
-
- wRxBcnTSFOffst = rx_bcn_tsf_off[rx_rate % MAX_RATE];
-
- qwTSF2 += (u64)wRxBcnTSFOffst;
-
- return qwTSF1 - qwTSF2;
-}
-
-/*
- * Description: Read NIC TSF counter
- * Get local TSF counter
- *
- * Parameters:
- * In:
- * priv - The adapter to be read
- * Out:
- * none
- *
- * Return Value: Current TSF counter
- */
-u64 vt6655_get_current_tsf(struct vnt_private *priv)
-{
- void __iomem *iobase = priv->port_offset;
- unsigned short ww;
- unsigned char data;
- u32 low, high;
-
- vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TSFCNTRRD);
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- data = ioread8(iobase + MAC_REG_TFTCTL);
- if (!(data & TFTCTL_TSFCNTRRD))
- break;
- }
- if (ww == W_MAX_TIMEOUT)
- return 0;
- low = ioread32(iobase + MAC_REG_TSFCNTR);
- high = ioread32(iobase + MAC_REG_TSFCNTR + 4);
- return le64_to_cpu(low + ((u64)high << 32));
-}
-
-/*
- * Description: Read NIC TSF counter
- * Get NEXTTBTT from adjusted TSF and Beacon Interval
- *
- * Parameters:
- * In:
- * qwTSF - Current TSF counter
- * wbeaconInterval - Beacon Interval
- * Out:
- * qwCurrTSF - Current TSF counter
- *
- * Return Value: TSF value of next Beacon
- */
-u64 card_get_next_tbtt(u64 qwTSF, unsigned short beacon_interval)
-{
- u32 beacon_int;
-
- beacon_int = beacon_interval * 1024;
- if (beacon_int) {
- do_div(qwTSF, beacon_int);
- qwTSF += 1;
- qwTSF *= beacon_int;
- }
-
- return qwTSF;
-}
-
-/*
- * Description: Set NIC TSF counter for first Beacon time
- * Get NEXTTBTT from adjusted TSF and Beacon Interval
- *
- * Parameters:
- * In:
- * iobase - IO Base
- * beacon_interval - Beacon Interval
- * Out:
- * none
- *
- * Return Value: none
- */
-void CARDvSetFirstNextTBTT(struct vnt_private *priv,
- unsigned short beacon_interval)
-{
- void __iomem *iobase = priv->port_offset;
- u64 next_tbtt;
-
- next_tbtt = vt6655_get_current_tsf(priv); /* Get Local TSF counter */
-
- next_tbtt = card_get_next_tbtt(next_tbtt, beacon_interval);
- /* Set NextTBTT */
- next_tbtt = le64_to_cpu(next_tbtt);
- iowrite32((u32)next_tbtt, iobase + MAC_REG_NEXTTBTT);
- iowrite32((u32)(next_tbtt >> 32), iobase + MAC_REG_NEXTTBTT + 4);
- vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
-}
-
-/*
- * Description: Sync NIC TSF counter for Beacon time
- * Get NEXTTBTT and write to HW
- *
- * Parameters:
- * In:
- * priv - The adapter to be set
- * qwTSF - Current TSF counter
- * beacon_interval - Beacon Interval
- * Out:
- * none
- *
- * Return Value: none
- */
-void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF,
- unsigned short beacon_interval)
-{
- void __iomem *iobase = priv->port_offset;
-
- qwTSF = card_get_next_tbtt(qwTSF, beacon_interval);
- /* Set NextTBTT */
- qwTSF = le64_to_cpu(qwTSF);
- iowrite32((u32)qwTSF, iobase + MAC_REG_NEXTTBTT);
- iowrite32((u32)(qwTSF >> 32), iobase + MAC_REG_NEXTTBTT + 4);
- vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
- pr_debug("Card:Update Next TBTT[%8llx]\n", qwTSF);
-}
diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h
deleted file mode 100644
index f6b462ebca51..000000000000
--- a/drivers/staging/vt6655/card.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Provide functions to setup NIC operation mode
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- */
-
-#ifndef __CARD_H__
-#define __CARD_H__
-
-#include <linux/types.h>
-#include <linux/nl80211.h>
-
-/*
- * Loopback mode
- *
- * LOBYTE is MAC LB mode, HIBYTE is MII LB mode
- */
-#define CARD_LB_NONE MAKEWORD(MAC_LB_NONE, 0)
-/* PHY must ISO, avoid MAC loopback packet go out */
-#define CARD_LB_MAC MAKEWORD(MAC_LB_INTERNAL, 0)
-#define CARD_LB_PHY MAKEWORD(MAC_LB_EXT, 0)
-
-#define DEFAULT_MSDU_LIFETIME 512 /* ms */
-#define DEFAULT_MSDU_LIFETIME_RES_64us 8000 /* 64us */
-
-#define DEFAULT_MGN_LIFETIME 8 /* ms */
-#define DEFAULT_MGN_LIFETIME_RES_64us 125 /* 64us */
-
-#define CB_MAX_CHANNEL_24G 14
-#define CB_MAX_CHANNEL_5G 42
-#define CB_MAX_CHANNEL (CB_MAX_CHANNEL_24G + CB_MAX_CHANNEL_5G)
-
-struct vnt_private;
-
-void card_set_rspinf(struct vnt_private *priv, u8 bb_type);
-void CARDvUpdateBasicTopRate(struct vnt_private *priv);
-bool CARDbIsOFDMinBasicRate(struct vnt_private *priv);
-void CARDvSetFirstNextTBTT(struct vnt_private *priv,
- unsigned short beacon_interval);
-void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF,
- unsigned short beacon_interval);
-u64 vt6655_get_current_tsf(struct vnt_private *priv);
-u64 card_get_next_tbtt(u64 qwTSF, unsigned short beacon_interval);
-u64 card_get_tsf_offset(unsigned char rx_rate, u64 qwTSF1, u64 qwTSF2);
-unsigned char card_get_pkt_type(struct vnt_private *priv);
-void card_safe_reset_tx(struct vnt_private *priv);
-void CARDvSafeResetRx(struct vnt_private *priv);
-void card_radio_power_off(struct vnt_private *priv);
-bool card_set_phy_parameter(struct vnt_private *priv, u8 bb_type);
-bool card_update_tsf(struct vnt_private *priv, unsigned char rx_rate,
- u64 bss_timestamp);
-bool card_set_beacon_period(struct vnt_private *priv,
- unsigned short beacon_interval);
-
-#endif /* __CARD_H__ */
diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c
deleted file mode 100644
index 771c1364b0f0..000000000000
--- a/drivers/staging/vt6655/channel.c
+++ /dev/null
@@ -1,135 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- */
-
-#include "baseband.h"
-#include "channel.h"
-#include "device.h"
-#include "rf.h"
-
-static struct ieee80211_rate vnt_rates_bg[] = {
- { .bitrate = 10, .hw_value = RATE_1M },
- { .bitrate = 20, .hw_value = RATE_2M },
- { .bitrate = 55, .hw_value = RATE_5M },
- { .bitrate = 110, .hw_value = RATE_11M },
- { .bitrate = 60, .hw_value = RATE_6M },
- { .bitrate = 90, .hw_value = RATE_9M },
- { .bitrate = 120, .hw_value = RATE_12M },
- { .bitrate = 180, .hw_value = RATE_18M },
- { .bitrate = 240, .hw_value = RATE_24M },
- { .bitrate = 360, .hw_value = RATE_36M },
- { .bitrate = 480, .hw_value = RATE_48M },
- { .bitrate = 540, .hw_value = RATE_54M },
-};
-
-static struct ieee80211_channel vnt_channels_2ghz[] = {
- { .center_freq = 2412, .hw_value = 1 },
- { .center_freq = 2417, .hw_value = 2 },
- { .center_freq = 2422, .hw_value = 3 },
- { .center_freq = 2427, .hw_value = 4 },
- { .center_freq = 2432, .hw_value = 5 },
- { .center_freq = 2437, .hw_value = 6 },
- { .center_freq = 2442, .hw_value = 7 },
- { .center_freq = 2447, .hw_value = 8 },
- { .center_freq = 2452, .hw_value = 9 },
- { .center_freq = 2457, .hw_value = 10 },
- { .center_freq = 2462, .hw_value = 11 },
- { .center_freq = 2467, .hw_value = 12 },
- { .center_freq = 2472, .hw_value = 13 },
- { .center_freq = 2484, .hw_value = 14 }
-};
-
-static struct ieee80211_supported_band vnt_supported_2ghz_band = {
- .channels = vnt_channels_2ghz,
- .n_channels = ARRAY_SIZE(vnt_channels_2ghz),
- .bitrates = vnt_rates_bg,
- .n_bitrates = ARRAY_SIZE(vnt_rates_bg),
-};
-
-static void vnt_init_band(struct vnt_private *priv,
- struct ieee80211_supported_band *supported_band,
- enum nl80211_band band)
-{
- int i;
-
- for (i = 0; i < supported_band->n_channels; i++) {
- supported_band->channels[i].max_power = 0x3f;
- supported_band->channels[i].flags =
- IEEE80211_CHAN_NO_HT40;
- }
-
- priv->hw->wiphy->bands[band] = supported_band;
-}
-
-void vnt_init_bands(struct vnt_private *priv)
-{
- vnt_init_band(priv, &vnt_supported_2ghz_band, NL80211_BAND_2GHZ);
-}
-
-/**
- * set_channel() - Set NIC media channel
- *
- * @priv: The adapter to be set
- * @ch: Channel to be set
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch)
-{
- bool ret = true;
-
- if (priv->current_ch == ch->hw_value)
- return ret;
-
- /* Set VGA to max sensitivity */
- if (priv->update_bbvga &&
- priv->bbvga_current != priv->bbvga[0]) {
- priv->bbvga_current = priv->bbvga[0];
-
- bb_set_vga_gain_offset(priv, priv->bbvga_current);
- }
-
- /* clear NAV */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_MACCR, MACCR_CLRNAV);
-
- /* TX_PE will reserve 3 us for MAX2829 A mode only,
- * it is for better TX throughput
- */
-
- priv->current_ch = ch->hw_value;
- ret &= RFbSelectChannel(priv, priv->rf_type,
- ch->hw_value);
-
- /* Init Synthesizer Table */
- if (priv->bEnablePSMode)
- rf_write_wake_prog_syn(priv, priv->rf_type, ch->hw_value);
-
- bb_software_reset(priv);
-
- if (priv->local_id > REV_ID_VT3253_B1) {
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* set HW default power register */
- VT6655_MAC_SELECT_PAGE1(priv->port_offset);
- RFbSetPower(priv, RATE_1M, priv->current_ch);
- iowrite8(priv->cur_pwr, priv->port_offset + MAC_REG_PWRCCK);
- RFbSetPower(priv, RATE_6M, priv->current_ch);
- iowrite8(priv->cur_pwr, priv->port_offset + MAC_REG_PWROFDM);
- VT6655_MAC_SELECT_PAGE0(priv->port_offset);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- }
-
- if (priv->byBBType == BB_TYPE_11B)
- RFbSetPower(priv, RATE_1M, priv->current_ch);
- else
- RFbSetPower(priv, RATE_6M, priv->current_ch);
-
- return ret;
-}
diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h
deleted file mode 100644
index 78b2d82317e5..000000000000
--- a/drivers/staging/vt6655/channel.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- */
-
-#ifndef _CHANNEL_H_
-#define _CHANNEL_H_
-
-#include "card.h"
-
-void vnt_init_bands(struct vnt_private *priv);
-
-bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch);
-
-#endif /* _CHANNEL_H_ */
diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h
deleted file mode 100644
index 17a40c53b8ff..000000000000
--- a/drivers/staging/vt6655/desc.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:The header file of descriptor
- *
- * Revision History:
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- */
-
-#ifndef __DESC_H__
-#define __DESC_H__
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include "linux/ieee80211.h"
-
-#define B_OWNED_BY_CHIP 1
-#define B_OWNED_BY_HOST 0
-
-/* Bits in the RSR register */
-#define RSR_ADDRBROAD 0x80
-#define RSR_ADDRMULTI 0x40
-#define RSR_ADDRUNI 0x00
-#define RSR_IVLDTYP 0x20
-#define RSR_IVLDLEN 0x10 /* invalid len (> 2312 byte) */
-#define RSR_BSSIDOK 0x08
-#define RSR_CRCOK 0x04
-#define RSR_BCNSSIDOK 0x02
-#define RSR_ADDROK 0x01
-
-/* Bits in the new RSR register */
-#define NEWRSR_DECRYPTOK 0x10
-#define NEWRSR_CFPIND 0x08
-#define NEWRSR_HWUTSF 0x04
-#define NEWRSR_BCNHITAID 0x02
-#define NEWRSR_BCNHITAID0 0x01
-
-/* Bits in the TSR0 register */
-#define TSR0_PWRSTS1_2 0xC0
-#define TSR0_PWRSTS7 0x20
-#define TSR0_NCR 0x1F
-
-/* Bits in the TSR1 register */
-#define TSR1_TERR 0x80
-#define TSR1_PWRSTS4_6 0x70
-#define TSR1_RETRYTMO 0x08
-#define TSR1_TMO 0x04
-#define TSR1_PWRSTS3 0x02
-#define ACK_DATA 0x01
-
-/* Bits in the TCR register */
-#define EDMSDU 0x04 /* end of sdu */
-#define TCR_EDP 0x02 /* end of packet */
-#define TCR_STP 0x01 /* start of packet */
-
-/* max transmit or receive buffer size */
-#define CB_MAX_BUF_SIZE 2900U
- /* NOTE: must be multiple of 4 */
-#define CB_MAX_TX_BUF_SIZE CB_MAX_BUF_SIZE
-#define CB_MAX_RX_BUF_SIZE_NORMAL CB_MAX_BUF_SIZE
-
-#define CB_BEACON_BUF_SIZE 512U
-
-#define CB_MAX_RX_DESC 128
-#define CB_MIN_RX_DESC 16
-#define CB_MAX_TX_DESC 64
-#define CB_MIN_TX_DESC 16
-
-#define CB_MAX_RECEIVED_PACKETS 16
- /*
- * limit our receive routine to indicating
- * this many at a time for 2 reasons:
- * 1. driver flow control to protocol layer
- * 2. limit the time used in ISR routine
- */
-
-#define CB_EXTRA_RD_NUM 32
-#define CB_RD_NUM 32
-#define CB_TD_NUM 32
-
-/*
- * max number of physical segments in a single NDIS packet. Above this
- * threshold, the packet is copied into a single physically contiguous buffer
- */
-#define CB_MAX_SEGMENT 4
-
-#define CB_MIN_MAP_REG_NUM 4
-#define CB_MAX_MAP_REG_NUM CB_MAX_TX_DESC
-
-#define CB_PROTOCOL_RESERVED_SECTION 16
-
-/*
- * if retrys excess 15 times , tx will abort, and if tx fifo underflow,
- * tx will fail, we should try to resend it
- */
-#define CB_MAX_TX_ABORT_RETRY 3
-
-/* WMAC definition FIFO Control */
-#define FIFOCTL_AUTO_FB_1 0x1000
-#define FIFOCTL_AUTO_FB_0 0x0800
-#define FIFOCTL_GRPACK 0x0400
-#define FIFOCTL_11GA 0x0300
-#define FIFOCTL_11GB 0x0200
-#define FIFOCTL_11B 0x0100
-#define FIFOCTL_11A 0x0000
-#define FIFOCTL_RTS 0x0080
-#define FIFOCTL_ISDMA0 0x0040
-#define FIFOCTL_GENINT 0x0020
-#define FIFOCTL_TMOEN 0x0010
-#define FIFOCTL_LRETRY 0x0008
-#define FIFOCTL_CRCDIS 0x0004
-#define FIFOCTL_NEEDACK 0x0002
-#define FIFOCTL_LHEAD 0x0001
-
-/* WMAC definition Frag Control */
-#define FRAGCTL_AES 0x0300
-#define FRAGCTL_TKIP 0x0200
-#define FRAGCTL_LEGACY 0x0100
-#define FRAGCTL_NONENCRYPT 0x0000
-#define FRAGCTL_ENDFRAG 0x0003
-#define FRAGCTL_MIDFRAG 0x0002
-#define FRAGCTL_STAFRAG 0x0001
-#define FRAGCTL_NONFRAG 0x0000
-
-#define TYPE_TXDMA0 0
-#define TYPE_AC0DMA 1
-#define TYPE_ATIMDMA 2
-#define TYPE_SYNCDMA 3
-#define TYPE_MAXTD 2
-
-#define TYPE_BEACONDMA 4
-
-#define TYPE_RXDMA0 0
-#define TYPE_RXDMA1 1
-#define TYPE_MAXRD 2
-
-/* TD_INFO flags control bit */
-#define TD_FLAGS_NETIF_SKB 0x01 /* check if need release skb */
-/* check if called from private skb (hostap) */
-#define TD_FLAGS_PRIV_SKB 0x02
-#define TD_FLAGS_PS_RETRY 0x04 /* check if PS STA frame re-transmit */
-
-/*
- * ref_sk_buff is used for mapping the skb structure between pre-built
- * driver-obj & running kernel. Since different kernel version (2.4x) may
- * change skb structure, i.e. pre-built driver-obj may link to older skb that
- * leads error.
- */
-
-struct vnt_rd_info {
- struct sk_buff *skb;
- dma_addr_t skb_dma;
-};
-
-struct vnt_rdes0 {
- volatile __le16 res_count;
-#ifdef __BIG_ENDIAN
- union {
- volatile u16 f15_reserved;
- struct {
- volatile u8 f8_reserved1;
- volatile u8 owner:1;
- volatile u8 f7_reserved:7;
- } __packed;
- } __packed;
-#else
- u16 f15_reserved:15;
- u16 owner:1;
-#endif
-} __packed;
-
-struct vnt_rdes1 {
- __le16 req_count;
- u16 reserved;
-} __packed;
-
-/* Rx descriptor*/
-struct vnt_rx_desc {
- volatile struct vnt_rdes0 rd0;
- volatile struct vnt_rdes1 rd1;
- volatile __le32 buff_addr;
- volatile __le32 next_desc;
- struct vnt_rx_desc *next __aligned(8);
- struct vnt_rd_info *rd_info __aligned(8);
-} __packed;
-
-struct vnt_tdes0 {
- volatile u8 tsr0;
- volatile u8 tsr1;
-#ifdef __BIG_ENDIAN
- union {
- volatile u16 f15_txtime;
- struct {
- volatile u8 f8_reserved;
- volatile u8 owner:1;
- volatile u8 f7_reserved:7;
- } __packed;
- } __packed;
-#else
- volatile u16 f15_txtime:15;
- volatile u16 owner:1;
-#endif
-} __packed;
-
-struct vnt_tdes1 {
- volatile __le16 req_count;
- volatile u8 tcr;
- volatile u8 reserved;
-} __packed;
-
-struct vnt_td_info {
- void *mic_hdr;
- struct sk_buff *skb;
- unsigned char *buf;
- dma_addr_t buf_dma;
- u16 req_count;
- u8 flags;
-};
-
-/* transmit descriptor */
-struct vnt_tx_desc {
- volatile struct vnt_tdes0 td0;
- volatile struct vnt_tdes1 td1;
- volatile __le32 buff_addr;
- volatile __le32 next_desc;
- struct vnt_tx_desc *next __aligned(8);
- struct vnt_td_info *td_info __aligned(8);
-} __packed;
-
-/* Length, Service, and Signal fields of Phy for Tx */
-struct vnt_phy_field {
- u8 signal;
- u8 service;
- __le16 len;
-} __packed;
-
-union vnt_phy_field_swap {
- struct vnt_phy_field field_read;
- u16 swap[2];
- u32 field_write;
-};
-
-#endif /* __DESC_H__ */
diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h
deleted file mode 100644
index 5eaab6b172d3..000000000000
--- a/drivers/staging/vt6655/device.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: MAC Data structure
- *
- * Author: Tevin Chen
- *
- * Date: Mar 17, 1997
- *
- */
-
-#ifndef __DEVICE_H__
-#define __DEVICE_H__
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/interrupt.h>
-#include <linux/crc32.h>
-#include <net/mac80211.h>
-
-/* device specific */
-
-#include "device_cfg.h"
-#include "card.h"
-#include "srom.h"
-#include "desc.h"
-#include "key.h"
-#include "mac.h"
-
-/*--------------------- Export Definitions -------------------------*/
-
-#define RATE_1M 0
-#define RATE_2M 1
-#define RATE_5M 2
-#define RATE_11M 3
-#define RATE_6M 4
-#define RATE_9M 5
-#define RATE_12M 6
-#define RATE_18M 7
-#define RATE_24M 8
-#define RATE_36M 9
-#define RATE_48M 10
-#define RATE_54M 11
-#define MAX_RATE 12
-
-#define AUTO_FB_NONE 0
-#define AUTO_FB_0 1
-#define AUTO_FB_1 2
-
-#define FB_RATE0 0
-#define FB_RATE1 1
-
-/* Antenna Mode */
-#define ANT_A 0
-#define ANT_B 1
-#define ANT_DIVERSITY 2
-#define ANT_RXD_TXA 3
-#define ANT_RXD_TXB 4
-#define ANT_UNKNOWN 0xFF
-
-#define BB_VGA_LEVEL 4
-#define BB_VGA_CHANGE_THRESHOLD 16
-
-#define MAKE_BEACON_RESERVED 10 /* (us) */
-
-/* BUILD OBJ mode */
-
-#define AVAIL_TD(p, q) ((p)->opts.tx_descs[(q)] - ((p)->iTDUsed[(q)]))
-
-/* 0:11A 1:11B 2:11G */
-#define BB_TYPE_11A 0
-#define BB_TYPE_11B 1
-#define BB_TYPE_11G 2
-
-/* 0:11a, 1:11b, 2:11gb (only CCK in BasicRate), 3:11ga (OFDM in BasicRate) */
-#define PK_TYPE_11A 0
-#define PK_TYPE_11B 1
-#define PK_TYPE_11GB 2
-#define PK_TYPE_11GA 3
-
-#define OWNED_BY_HOST 0
-#define OWNED_BY_NIC 1
-
-struct vnt_options {
- int rx_descs0; /* Number of RX descriptors0 */
- int rx_descs1; /* Number of RX descriptors1 */
- int tx_descs[2]; /* Number of TX descriptors 0, 1 */
- int int_works; /* interrupt limits */
- int short_retry;
- int long_retry;
- int bbp_type;
- u32 flags;
-};
-
-struct vnt_private {
- struct pci_dev *pcid;
- /* mac80211 */
- struct ieee80211_hw *hw;
- struct ieee80211_vif *vif;
- unsigned long key_entry_inuse;
- u32 basic_rates;
- u16 current_aid;
- int mc_list_count;
- u8 mac_hw;
-
-/* dma addr, rx/tx pool */
- dma_addr_t pool_dma;
- dma_addr_t rd0_pool_dma;
- dma_addr_t rd1_pool_dma;
-
- dma_addr_t td0_pool_dma;
- dma_addr_t td1_pool_dma;
-
- dma_addr_t tx_bufs_dma0;
- dma_addr_t tx_bufs_dma1;
- dma_addr_t tx_beacon_dma;
-
- unsigned char *tx0_bufs;
- unsigned char *tx1_bufs;
- unsigned char *tx_beacon_bufs;
-
- void __iomem *port_offset;
- u32 memaddr;
- u32 ioaddr;
-
- spinlock_t lock;
-
- volatile int iTDUsed[TYPE_MAXTD];
-
- struct vnt_tx_desc *apCurrTD[TYPE_MAXTD];
- struct vnt_tx_desc *tail_td[TYPE_MAXTD];
-
- struct vnt_tx_desc *ap_td0_rings;
- struct vnt_tx_desc *ap_td1_rings;
-
- struct vnt_rx_desc *aRD0Ring;
- struct vnt_rx_desc *aRD1Ring;
- struct vnt_rx_desc *pCurrRD[TYPE_MAXRD];
-
- struct vnt_options opts;
-
- u32 flags;
-
- u32 rx_buf_sz;
- u8 rx_rate;
-
- u32 rx_bytes;
-
- /* Version control */
- unsigned char local_id;
- unsigned char rf_type;
-
- unsigned char max_pwr_level;
- unsigned char byZoneType;
- bool bZoneRegExist;
- unsigned char byOriginalZonetype;
-
- unsigned char abyCurrentNetAddr[ETH_ALEN]; __aligned(2)
- bool bLinkPass; /* link status: OK or fail */
-
- unsigned int current_rssi;
- unsigned char byCurrSQ;
-
- unsigned long dwTxAntennaSel;
- unsigned long dwRxAntennaSel;
- unsigned char byAntennaCount;
- unsigned char byRxAntennaMode;
- unsigned char byTxAntennaMode;
- bool bTxRxAntInv;
-
- unsigned char *pbyTmpBuff;
- unsigned int uSIFS; /* Current SIFS */
- unsigned int uDIFS; /* Current DIFS */
- unsigned int uEIFS; /* Current EIFS */
- unsigned int uSlot; /* Current SlotTime */
- unsigned int uCwMin; /* Current CwMin */
- unsigned int uCwMax; /* CwMax is fixed on 1023. */
- /* PHY parameter */
- unsigned char sifs;
- unsigned char difs;
- unsigned char eifs;
- unsigned char slot;
- unsigned char cw_max_min;
-
- u8 byBBType; /* 0:11A, 1:11B, 2:11G */
- u8 packet_type; /*
- * 0:11a,1:11b,2:11gb (only CCK
- * in BasicRate), 3:11ga (OFDM in
- * Basic Rate)
- */
- unsigned short wBasicRate;
- unsigned char byACKRate;
- unsigned char byTopOFDMBasicRate;
- unsigned char byTopCCKBasicRate;
-
- unsigned char byMinChannel;
- unsigned char byMaxChannel;
-
- unsigned char preamble_type;
- unsigned char byShortPreamble;
-
- unsigned short wCurrentRate;
- unsigned char byShortRetryLimit;
- unsigned char byLongRetryLimit;
- enum nl80211_iftype op_mode;
- bool bBSSIDFilter;
- unsigned short wMaxTransmitMSDULifetime;
-
- bool bEncryptionEnable;
- bool bLongHeader;
- bool short_slot_time;
- bool bProtectMode;
- bool bNonERPPresent;
- bool bBarkerPreambleMd;
-
- bool bRadioControlOff;
- bool radio_off;
- bool bEnablePSMode;
- unsigned short wListenInterval;
- bool bPWBitOn;
-
- /* GPIO Radio Control */
- unsigned char byRadioCtl;
- unsigned char byGPIO;
- bool hw_radio_off;
- bool bPrvActive4RadioOFF;
- bool bGPIOBlockRead;
-
- /* Beacon related */
- unsigned short wSeqCounter;
- unsigned short wBCNBufLen;
- bool bBeaconBufReady;
- bool bBeaconSent;
- bool bIsBeaconBufReadySet;
- unsigned int cbBeaconBufReadySetCnt;
- bool bFixRate;
- u16 current_ch;
-
- bool bAES;
-
- unsigned char byAutoFBCtrl;
-
- /* For Update BaseBand VGA Gain Offset */
- bool update_bbvga;
- unsigned int uBBVGADiffCount;
- unsigned char bbvga_new;
- unsigned char bbvga_current;
- unsigned char bbvga[BB_VGA_LEVEL];
- long dbm_threshold[BB_VGA_LEVEL];
-
- unsigned char bb_pre_edrssi;
- unsigned char byBBPreEDIndex;
-
- unsigned long dwDiagRefCount;
-
- /* For FOE Tuning */
- unsigned char byFOETuning;
-
- /* For RF Power table */
- unsigned char byCCKPwr;
- unsigned char byOFDMPwrG;
- unsigned char cur_pwr;
- char byCurPwrdBm;
- unsigned char abyCCKPwrTbl[CB_MAX_CHANNEL_24G + 1];
- unsigned char abyOFDMPwrTbl[CB_MAX_CHANNEL + 1];
- char abyCCKDefaultPwr[CB_MAX_CHANNEL_24G + 1];
- char abyOFDMDefaultPwr[CB_MAX_CHANNEL + 1];
- char abyRegPwr[CB_MAX_CHANNEL + 1];
- char abyLocalPwr[CB_MAX_CHANNEL + 1];
-
- /* BaseBand Loopback Use */
- unsigned char byBBCR4d;
- unsigned char byBBCRc9;
- unsigned char byBBCR88;
- unsigned char byBBCR09;
-
- unsigned char abyEEPROM[EEP_MAX_CONTEXT_SIZE]; /* unsigned long alignment */
-
- unsigned short beacon_interval;
- u16 wake_up_count;
-
- struct work_struct interrupt_work;
-
- struct ieee80211_low_level_stats low_stats;
-};
-
-#endif
diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h
deleted file mode 100644
index 2d647a3619ba..000000000000
--- a/drivers/staging/vt6655/device_cfg.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Driver configuration header
- * Author: Lyndon Chen
- *
- * Date: Dec 17, 2002
- *
- */
-
-#ifndef __DEVICE_CONFIG_H
-#define __DEVICE_CONFIG_H
-
-#include <linux/types.h>
-
-#define VID_TABLE_SIZE 64
-#define MCAST_TABLE_SIZE 64
-#define MCAM_SIZE 32
-#define VCAM_SIZE 32
-#define TX_QUEUE_NO 8
-
-#define DEVICE_NAME "vt6655"
-#define DEVICE_FULL_DRV_NAM "VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver"
-
-#ifndef MAJOR_VERSION
-#define MAJOR_VERSION 1
-#endif
-
-#ifndef MINOR_VERSION
-#define MINOR_VERSION 17
-#endif
-
-#ifndef DEVICE_VERSION
-#define DEVICE_VERSION "1.19.12"
-#endif
-
-#include <linux/fs.h>
-#include <linux/fcntl.h>
-
-#define PKT_BUF_SZ 2390
-
-#endif
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
deleted file mode 100644
index bf3ecf720206..000000000000
--- a/drivers/staging/vt6655/device_main.c
+++ /dev/null
@@ -1,1868 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: driver entry for initial, open, close, tx and rx.
- *
- * Author: Lyndon Chen
- *
- * Date: Jan 8, 2003
- *
- * Functions:
- *
- * vt6655_probe - module initial (insmod) driver entry
- * vt6655_remove - module remove entry
- * device_free_info - device structure resource free function
- * device_print_info - print out resource
- * device_rx_srv - rx service function
- * device_alloc_rx_buf - rx buffer pre-allocated function
- * device_free_rx_buf - free rx buffer function
- * device_free_tx_buf - free tx buffer function
- * device_init_rd0_ring - initial rd dma0 ring
- * device_init_rd1_ring - initial rd dma1 ring
- * device_init_td0_ring - initial tx dma0 ring buffer
- * device_init_td1_ring - initial tx dma1 ring buffer
- * device_init_registers - initial MAC & BBP & RF internal registers.
- * device_init_rings - initial tx/rx ring buffer
- * device_free_rings - free all allocated ring buffer
- * device_tx_srv - tx interrupt service function
- *
- * Revision History:
- */
-
-#include <linux/file.h>
-#include "device.h"
-#include "card.h"
-#include "channel.h"
-#include "baseband.h"
-#include "mac.h"
-#include "power.h"
-#include "rxtx.h"
-#include "dpc.h"
-#include "rf.h"
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <linux/slab.h>
-
-/*--------------------- Static Definitions -------------------------*/
-/*
- * Define module options
- */
-MODULE_AUTHOR("VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver");
-
-#define DEVICE_PARAM(N, D)
-
-#define RX_DESC_MIN0 16
-#define RX_DESC_MAX0 128
-#define RX_DESC_DEF0 32
-DEVICE_PARAM(RxDescriptors0, "Number of receive descriptors0");
-
-#define RX_DESC_MIN1 16
-#define RX_DESC_MAX1 128
-#define RX_DESC_DEF1 32
-DEVICE_PARAM(RxDescriptors1, "Number of receive descriptors1");
-
-#define TX_DESC_MIN0 16
-#define TX_DESC_MAX0 128
-#define TX_DESC_DEF0 32
-DEVICE_PARAM(TxDescriptors0, "Number of transmit descriptors0");
-
-#define TX_DESC_MIN1 16
-#define TX_DESC_MAX1 128
-#define TX_DESC_DEF1 64
-DEVICE_PARAM(TxDescriptors1, "Number of transmit descriptors1");
-
-#define INT_WORKS_DEF 20
-#define INT_WORKS_MIN 10
-#define INT_WORKS_MAX 64
-
-DEVICE_PARAM(int_works, "Number of packets per interrupt services");
-
-#define RTS_THRESH_DEF 2347
-
-#define FRAG_THRESH_DEF 2346
-
-#define SHORT_RETRY_MIN 0
-#define SHORT_RETRY_MAX 31
-#define SHORT_RETRY_DEF 8
-
-DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits");
-
-#define LONG_RETRY_MIN 0
-#define LONG_RETRY_MAX 15
-#define LONG_RETRY_DEF 4
-
-DEVICE_PARAM(LongRetryLimit, "long frame retry limits");
-
-/* BasebandType[] baseband type selected
- * 0: indicate 802.11a type
- * 1: indicate 802.11b type
- * 2: indicate 802.11g type
- */
-#define BBP_TYPE_MIN 0
-#define BBP_TYPE_MAX 2
-#define BBP_TYPE_DEF 2
-
-DEVICE_PARAM(BasebandType, "baseband type");
-
-/*
- * Static vars definitions
- */
-static const struct pci_device_id vt6655_pci_id_table[] = {
- { PCI_VDEVICE(VIA, 0x3253) },
- { 0, }
-};
-
-/*--------------------- Static Functions --------------------------*/
-
-static int vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent);
-static void device_free_info(struct vnt_private *priv);
-static void device_print_info(struct vnt_private *priv);
-
-static void vt6655_mac_write_bssid_addr(void __iomem *iobase, const u8 *mac_addr);
-static void vt6655_mac_read_ether_addr(void __iomem *iobase, u8 *mac_addr);
-
-static int device_init_rd0_ring(struct vnt_private *priv);
-static int device_init_rd1_ring(struct vnt_private *priv);
-static int device_init_td0_ring(struct vnt_private *priv);
-static int device_init_td1_ring(struct vnt_private *priv);
-
-static int device_rx_srv(struct vnt_private *priv, unsigned int idx);
-static int device_tx_srv(struct vnt_private *priv, unsigned int idx);
-static bool device_alloc_rx_buf(struct vnt_private *, struct vnt_rx_desc *);
-static void device_free_rx_buf(struct vnt_private *priv,
- struct vnt_rx_desc *rd);
-static void device_init_registers(struct vnt_private *priv);
-static void device_free_tx_buf(struct vnt_private *, struct vnt_tx_desc *);
-static void device_free_td0_ring(struct vnt_private *priv);
-static void device_free_td1_ring(struct vnt_private *priv);
-static void device_free_rd0_ring(struct vnt_private *priv);
-static void device_free_rd1_ring(struct vnt_private *priv);
-static void device_free_rings(struct vnt_private *priv);
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Export Functions --------------------------*/
-
-static void vt6655_remove(struct pci_dev *pcid)
-{
- struct vnt_private *priv = pci_get_drvdata(pcid);
-
- if (!priv)
- return;
- device_free_info(priv);
-}
-
-static void device_get_options(struct vnt_private *priv)
-{
- struct vnt_options *opts = &priv->opts;
-
- opts->rx_descs0 = RX_DESC_DEF0;
- opts->rx_descs1 = RX_DESC_DEF1;
- opts->tx_descs[0] = TX_DESC_DEF0;
- opts->tx_descs[1] = TX_DESC_DEF1;
- opts->int_works = INT_WORKS_DEF;
-
- opts->short_retry = SHORT_RETRY_DEF;
- opts->long_retry = LONG_RETRY_DEF;
- opts->bbp_type = BBP_TYPE_DEF;
-}
-
-static void
-device_set_options(struct vnt_private *priv)
-{
- priv->byShortRetryLimit = priv->opts.short_retry;
- priv->byLongRetryLimit = priv->opts.long_retry;
- priv->byBBType = priv->opts.bbp_type;
- priv->packet_type = priv->byBBType;
- priv->byAutoFBCtrl = AUTO_FB_0;
- priv->update_bbvga = true;
- priv->preamble_type = 0;
-
- pr_debug(" byShortRetryLimit= %d\n", (int)priv->byShortRetryLimit);
- pr_debug(" byLongRetryLimit= %d\n", (int)priv->byLongRetryLimit);
- pr_debug(" preamble_type= %d\n", (int)priv->preamble_type);
- pr_debug(" byShortPreamble= %d\n", (int)priv->byShortPreamble);
- pr_debug(" byBBType= %d\n", (int)priv->byBBType);
-}
-
-static void vt6655_mac_write_bssid_addr(void __iomem *iobase, const u8 *mac_addr)
-{
- iowrite8(1, iobase + MAC_REG_PAGE1SEL);
- for (int i = 0; i < 6; i++)
- iowrite8(mac_addr[i], iobase + MAC_REG_BSSID0 + i);
- iowrite8(0, iobase + MAC_REG_PAGE1SEL);
-}
-
-static void vt6655_mac_read_ether_addr(void __iomem *iobase, u8 *mac_addr)
-{
- iowrite8(1, iobase + MAC_REG_PAGE1SEL);
- for (int i = 0; i < 6; i++)
- mac_addr[i] = ioread8(iobase + MAC_REG_PAR0 + i);
- iowrite8(0, iobase + MAC_REG_PAGE1SEL);
-}
-
-static void vt6655_mac_dma_ctl(void __iomem *iobase, u8 reg_index)
-{
- u32 reg_value;
-
- reg_value = ioread32(iobase + reg_index);
- if (reg_value & DMACTL_RUN)
- iowrite32(DMACTL_WAKE, iobase + reg_index);
- else
- iowrite32(DMACTL_RUN, iobase + reg_index);
-}
-
-static void vt6655_mac_set_bits(void __iomem *iobase, u32 mask)
-{
- u32 reg_value;
-
- reg_value = ioread32(iobase + MAC_REG_ENCFG);
- reg_value = reg_value | mask;
- iowrite32(reg_value, iobase + MAC_REG_ENCFG);
-}
-
-static void vt6655_mac_clear_bits(void __iomem *iobase, u32 mask)
-{
- u32 reg_value;
-
- reg_value = ioread32(iobase + MAC_REG_ENCFG);
- reg_value = reg_value & ~mask;
- iowrite32(reg_value, iobase + MAC_REG_ENCFG);
-}
-
-static void vt6655_mac_en_protect_md(void __iomem *iobase)
-{
- vt6655_mac_set_bits(iobase, ENCFG_PROTECTMD);
-}
-
-static void vt6655_mac_dis_protect_md(void __iomem *iobase)
-{
- vt6655_mac_clear_bits(iobase, ENCFG_PROTECTMD);
-}
-
-static void vt6655_mac_en_barker_preamble_md(void __iomem *iobase)
-{
- vt6655_mac_set_bits(iobase, ENCFG_BARKERPREAM);
-}
-
-static void vt6655_mac_dis_barker_preamble_md(void __iomem *iobase)
-{
- vt6655_mac_clear_bits(iobase, ENCFG_BARKERPREAM);
-}
-
-/*
- * Initialisation of MAC & BBP registers
- */
-
-static void device_init_registers(struct vnt_private *priv)
-{
- unsigned long flags;
- unsigned int ii;
- unsigned char byValue;
- unsigned char byCCKPwrdBm = 0;
- unsigned char byOFDMPwrdBm = 0;
-
- MACbShutdown(priv);
- bb_software_reset(priv);
-
- /* Do MACbSoftwareReset in MACvInitialize */
- MACbSoftwareReset(priv);
-
- priv->bAES = false;
-
- /* Only used in 11g type, sync with ERP IE */
- priv->bProtectMode = false;
-
- priv->bNonERPPresent = false;
- priv->bBarkerPreambleMd = false;
- priv->wCurrentRate = RATE_1M;
- priv->byTopOFDMBasicRate = RATE_24M;
- priv->byTopCCKBasicRate = RATE_1M;
-
- /* init MAC */
- MACvInitialize(priv);
-
- /* Get Local ID */
- priv->local_id = ioread8(priv->port_offset + MAC_REG_LOCALID);
-
- spin_lock_irqsave(&priv->lock, flags);
-
- SROMvReadAllContents(priv->port_offset, priv->abyEEPROM);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- /* Get Channel range */
- priv->byMinChannel = 1;
- priv->byMaxChannel = CB_MAX_CHANNEL;
-
- /* Get Antena */
- byValue = SROMbyReadEmbedded(priv->port_offset, EEP_OFS_ANTENNA);
- if (byValue & EEP_ANTINV)
- priv->bTxRxAntInv = true;
- else
- priv->bTxRxAntInv = false;
-
- byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
- /* if not set default is All */
- if (byValue == 0)
- byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
-
- if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) {
- priv->byAntennaCount = 2;
- priv->byTxAntennaMode = ANT_B;
- priv->dwTxAntennaSel = 1;
- priv->dwRxAntennaSel = 1;
-
- if (priv->bTxRxAntInv)
- priv->byRxAntennaMode = ANT_A;
- else
- priv->byRxAntennaMode = ANT_B;
- } else {
- priv->byAntennaCount = 1;
- priv->dwTxAntennaSel = 0;
- priv->dwRxAntennaSel = 0;
-
- if (byValue & EEP_ANTENNA_AUX) {
- priv->byTxAntennaMode = ANT_A;
-
- if (priv->bTxRxAntInv)
- priv->byRxAntennaMode = ANT_B;
- else
- priv->byRxAntennaMode = ANT_A;
- } else {
- priv->byTxAntennaMode = ANT_B;
-
- if (priv->bTxRxAntInv)
- priv->byRxAntennaMode = ANT_A;
- else
- priv->byRxAntennaMode = ANT_B;
- }
- }
-
- /* Set initial antenna mode */
- bb_set_tx_antenna_mode(priv, priv->byTxAntennaMode);
- bb_set_rx_antenna_mode(priv, priv->byRxAntennaMode);
-
- /* zonetype initial */
- priv->byOriginalZonetype = priv->abyEEPROM[EEP_OFS_ZONETYPE];
-
- if (!priv->bZoneRegExist)
- priv->byZoneType = priv->abyEEPROM[EEP_OFS_ZONETYPE];
-
- pr_debug("priv->byZoneType = %x\n", priv->byZoneType);
-
- /* Init RF module */
- RFbInit(priv);
-
- /* Get Desire Power Value */
- priv->cur_pwr = 0xFF;
- priv->byCCKPwr = SROMbyReadEmbedded(priv->port_offset, EEP_OFS_PWR_CCK);
- priv->byOFDMPwrG = SROMbyReadEmbedded(priv->port_offset,
- EEP_OFS_PWR_OFDMG);
-
- /* Load power Table */
- for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) {
- priv->abyCCKPwrTbl[ii + 1] =
- SROMbyReadEmbedded(priv->port_offset,
- (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL));
- if (priv->abyCCKPwrTbl[ii + 1] == 0)
- priv->abyCCKPwrTbl[ii + 1] = priv->byCCKPwr;
-
- priv->abyOFDMPwrTbl[ii + 1] =
- SROMbyReadEmbedded(priv->port_offset,
- (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL));
- if (priv->abyOFDMPwrTbl[ii + 1] == 0)
- priv->abyOFDMPwrTbl[ii + 1] = priv->byOFDMPwrG;
-
- priv->abyCCKDefaultPwr[ii + 1] = byCCKPwrdBm;
- priv->abyOFDMDefaultPwr[ii + 1] = byOFDMPwrdBm;
- }
-
- /* recover 12,13 ,14channel for EUROPE by 11 channel */
- for (ii = 11; ii < 14; ii++) {
- priv->abyCCKPwrTbl[ii] = priv->abyCCKPwrTbl[10];
- priv->abyOFDMPwrTbl[ii] = priv->abyOFDMPwrTbl[10];
- }
-
- /* Load OFDM A Power Table */
- for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) {
- priv->abyOFDMPwrTbl[ii + CB_MAX_CHANNEL_24G + 1] =
- SROMbyReadEmbedded(priv->port_offset,
- (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL));
-
- priv->abyOFDMDefaultPwr[ii + CB_MAX_CHANNEL_24G + 1] =
- SROMbyReadEmbedded(priv->port_offset,
- (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm));
- }
-
- if (priv->local_id > REV_ID_VT3253_B1) {
- VT6655_MAC_SELECT_PAGE1(priv->port_offset);
-
- iowrite8(MSRCTL1_TXPWR | MSRCTL1_CSAPAREN, priv->port_offset + MAC_REG_MSRCTL + 1);
-
- VT6655_MAC_SELECT_PAGE0(priv->port_offset);
- }
-
- /* use relative tx timeout and 802.11i D4 */
- vt6655_mac_word_reg_bits_on(priv->port_offset, MAC_REG_CFG,
- (CFG_TKIPOPT | CFG_NOTXTIMEOUT));
-
- /* set performance parameter by registry */
- vt6655_mac_set_short_retry_limit(priv, priv->byShortRetryLimit);
- MACvSetLongRetryLimit(priv, priv->byLongRetryLimit);
-
- /* reset TSF counter */
- iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL);
- /* enable TSF counter */
- iowrite8(TFTCTL_TSFCNTREN, priv->port_offset + MAC_REG_TFTCTL);
-
- /* initialize BBP registers */
- bb_vt3253_init(priv);
-
- if (priv->update_bbvga) {
- priv->bbvga_current = priv->bbvga[0];
- priv->bbvga_new = priv->bbvga_current;
- bb_set_vga_gain_offset(priv, priv->bbvga[0]);
- }
-
- bb_set_rx_antenna_mode(priv, priv->byRxAntennaMode);
- bb_set_tx_antenna_mode(priv, priv->byTxAntennaMode);
-
- /* Set BB and packet type at the same time. */
- /* Set Short Slot Time, xIFS, and RSPINF. */
- priv->wCurrentRate = RATE_54M;
-
- priv->radio_off = false;
-
- priv->byRadioCtl = SROMbyReadEmbedded(priv->port_offset,
- EEP_OFS_RADIOCTL);
- priv->hw_radio_off = false;
-
- if (priv->byRadioCtl & EEP_RADIOCTL_ENABLE) {
- /* Get GPIO */
- priv->byGPIO = ioread8(priv->port_offset + MAC_REG_GPIOCTL1);
-
- if (((priv->byGPIO & GPIO0_DATA) &&
- !(priv->byRadioCtl & EEP_RADIOCTL_INV)) ||
- (!(priv->byGPIO & GPIO0_DATA) &&
- (priv->byRadioCtl & EEP_RADIOCTL_INV)))
- priv->hw_radio_off = true;
- }
-
- if (priv->hw_radio_off || priv->bRadioControlOff)
- card_radio_power_off(priv);
-
- /* get Permanent network address */
- SROMvReadEtherAddress(priv->port_offset, priv->abyCurrentNetAddr);
- pr_debug("Network address = %pM\n", priv->abyCurrentNetAddr);
-
- /* reset Tx pointer */
- CARDvSafeResetRx(priv);
- /* reset Rx pointer */
- card_safe_reset_tx(priv);
-
- if (priv->local_id <= REV_ID_VT3253_A1)
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_RCR, RCR_WPAERR);
-
- /* Turn On Rx DMA */
- vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL0);
- vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL1);
-
- /* start the adapter */
- iowrite8(HOSTCR_MACEN | HOSTCR_RXON | HOSTCR_TXON, priv->port_offset + MAC_REG_HOSTCR);
-}
-
-static void device_print_info(struct vnt_private *priv)
-{
- dev_info(&priv->pcid->dev, "MAC=%pM IO=0x%lx Mem=0x%lx IRQ=%d\n",
- priv->abyCurrentNetAddr, (unsigned long)priv->ioaddr,
- (unsigned long)priv->port_offset, priv->pcid->irq);
-}
-
-static void device_free_info(struct vnt_private *priv)
-{
- if (!priv)
- return;
-
- if (priv->mac_hw)
- ieee80211_unregister_hw(priv->hw);
-
- if (priv->port_offset)
- iounmap(priv->port_offset);
-
- if (priv->pcid)
- pci_release_regions(priv->pcid);
-
- if (priv->hw)
- ieee80211_free_hw(priv->hw);
-}
-
-static bool device_init_rings(struct vnt_private *priv)
-{
- void *vir_pool;
-
- /*allocate all RD/TD rings a single pool*/
- vir_pool = dma_alloc_coherent(&priv->pcid->dev,
- priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) +
- priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) +
- priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) +
- priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
- &priv->pool_dma, GFP_ATOMIC);
- if (!vir_pool) {
- dev_err(&priv->pcid->dev, "allocate desc dma memory failed\n");
- return false;
- }
-
- priv->aRD0Ring = vir_pool;
- priv->aRD1Ring = vir_pool +
- priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc);
-
- priv->rd0_pool_dma = priv->pool_dma;
- priv->rd1_pool_dma = priv->rd0_pool_dma +
- priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc);
-
- priv->tx0_bufs = dma_alloc_coherent(&priv->pcid->dev,
- priv->opts.tx_descs[0] * PKT_BUF_SZ +
- priv->opts.tx_descs[1] * PKT_BUF_SZ +
- CB_BEACON_BUF_SIZE +
- CB_MAX_BUF_SIZE,
- &priv->tx_bufs_dma0, GFP_ATOMIC);
- if (!priv->tx0_bufs) {
- dev_err(&priv->pcid->dev, "allocate buf dma memory failed\n");
-
- dma_free_coherent(&priv->pcid->dev,
- priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) +
- priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) +
- priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) +
- priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
- vir_pool, priv->pool_dma);
- return false;
- }
-
- priv->td0_pool_dma = priv->rd1_pool_dma +
- priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc);
-
- priv->td1_pool_dma = priv->td0_pool_dma +
- priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc);
-
- /* vir_pool: pvoid type */
- priv->ap_td0_rings = vir_pool
- + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc)
- + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc);
-
- priv->ap_td1_rings = vir_pool
- + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc)
- + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc)
- + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc);
-
- priv->tx1_bufs = priv->tx0_bufs +
- priv->opts.tx_descs[0] * PKT_BUF_SZ;
-
- priv->tx_beacon_bufs = priv->tx1_bufs +
- priv->opts.tx_descs[1] * PKT_BUF_SZ;
-
- priv->pbyTmpBuff = priv->tx_beacon_bufs +
- CB_BEACON_BUF_SIZE;
-
- priv->tx_bufs_dma1 = priv->tx_bufs_dma0 +
- priv->opts.tx_descs[0] * PKT_BUF_SZ;
-
- priv->tx_beacon_dma = priv->tx_bufs_dma1 +
- priv->opts.tx_descs[1] * PKT_BUF_SZ;
-
- return true;
-}
-
-static void device_free_rings(struct vnt_private *priv)
-{
- dma_free_coherent(&priv->pcid->dev,
- priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) +
- priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) +
- priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) +
- priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
- priv->aRD0Ring, priv->pool_dma);
-
- dma_free_coherent(&priv->pcid->dev,
- priv->opts.tx_descs[0] * PKT_BUF_SZ +
- priv->opts.tx_descs[1] * PKT_BUF_SZ +
- CB_BEACON_BUF_SIZE +
- CB_MAX_BUF_SIZE,
- priv->tx0_bufs, priv->tx_bufs_dma0);
-}
-
-static int device_init_rd0_ring(struct vnt_private *priv)
-{
- int i;
- dma_addr_t curr = priv->rd0_pool_dma;
- struct vnt_rx_desc *desc;
- int ret;
-
- /* Init the RD0 ring entries */
- for (i = 0; i < priv->opts.rx_descs0;
- i ++, curr += sizeof(struct vnt_rx_desc)) {
- desc = &priv->aRD0Ring[i];
- desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL);
- if (!desc->rd_info) {
- ret = -ENOMEM;
- goto err_free_desc;
- }
-
- if (!device_alloc_rx_buf(priv, desc)) {
- dev_err(&priv->pcid->dev, "can not alloc rx bufs\n");
- ret = -ENOMEM;
- goto err_free_rd;
- }
-
- desc->next = &priv->aRD0Ring[(i + 1) % priv->opts.rx_descs0];
- desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc));
- }
-
- if (i > 0)
- priv->aRD0Ring[i - 1].next_desc = cpu_to_le32(priv->rd0_pool_dma);
- priv->pCurrRD[0] = &priv->aRD0Ring[0];
-
- return 0;
-
-err_free_rd:
- kfree(desc->rd_info);
-
-err_free_desc:
- while (i--) {
- desc = &priv->aRD0Ring[i];
- device_free_rx_buf(priv, desc);
- kfree(desc->rd_info);
- }
-
- return ret;
-}
-
-static int device_init_rd1_ring(struct vnt_private *priv)
-{
- int i;
- dma_addr_t curr = priv->rd1_pool_dma;
- struct vnt_rx_desc *desc;
- int ret;
-
- /* Init the RD1 ring entries */
- for (i = 0; i < priv->opts.rx_descs1;
- i ++, curr += sizeof(struct vnt_rx_desc)) {
- desc = &priv->aRD1Ring[i];
- desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL);
- if (!desc->rd_info) {
- ret = -ENOMEM;
- goto err_free_desc;
- }
-
- if (!device_alloc_rx_buf(priv, desc)) {
- dev_err(&priv->pcid->dev, "can not alloc rx bufs\n");
- ret = -ENOMEM;
- goto err_free_rd;
- }
-
- desc->next = &priv->aRD1Ring[(i + 1) % priv->opts.rx_descs1];
- desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc));
- }
-
- if (i > 0)
- priv->aRD1Ring[i - 1].next_desc = cpu_to_le32(priv->rd1_pool_dma);
- priv->pCurrRD[1] = &priv->aRD1Ring[0];
-
- return 0;
-
-err_free_rd:
- kfree(desc->rd_info);
-
-err_free_desc:
- while (i--) {
- desc = &priv->aRD1Ring[i];
- device_free_rx_buf(priv, desc);
- kfree(desc->rd_info);
- }
-
- return ret;
-}
-
-static void device_free_rd0_ring(struct vnt_private *priv)
-{
- int i;
-
- for (i = 0; i < priv->opts.rx_descs0; i++) {
- struct vnt_rx_desc *desc = &priv->aRD0Ring[i];
-
- device_free_rx_buf(priv, desc);
- kfree(desc->rd_info);
- }
-}
-
-static void device_free_rd1_ring(struct vnt_private *priv)
-{
- int i;
-
- for (i = 0; i < priv->opts.rx_descs1; i++) {
- struct vnt_rx_desc *desc = &priv->aRD1Ring[i];
-
- device_free_rx_buf(priv, desc);
- kfree(desc->rd_info);
- }
-}
-
-static int device_init_td0_ring(struct vnt_private *priv)
-{
- int i;
- dma_addr_t curr;
- struct vnt_tx_desc *desc;
- int ret;
-
- curr = priv->td0_pool_dma;
- for (i = 0; i < priv->opts.tx_descs[0];
- i++, curr += sizeof(struct vnt_tx_desc)) {
- desc = &priv->ap_td0_rings[i];
- desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL);
- if (!desc->td_info) {
- ret = -ENOMEM;
- goto err_free_desc;
- }
-
- desc->td_info->buf = priv->tx0_bufs + i * PKT_BUF_SZ;
- desc->td_info->buf_dma = priv->tx_bufs_dma0 + i * PKT_BUF_SZ;
-
- desc->next = &(priv->ap_td0_rings[(i + 1) % priv->opts.tx_descs[0]]);
- desc->next_desc = cpu_to_le32(curr +
- sizeof(struct vnt_tx_desc));
- }
-
- if (i > 0)
- priv->ap_td0_rings[i - 1].next_desc = cpu_to_le32(priv->td0_pool_dma);
- priv->tail_td[0] = priv->apCurrTD[0] = &priv->ap_td0_rings[0];
-
- return 0;
-
-err_free_desc:
- while (i--) {
- desc = &priv->ap_td0_rings[i];
- kfree(desc->td_info);
- }
-
- return ret;
-}
-
-static int device_init_td1_ring(struct vnt_private *priv)
-{
- int i;
- dma_addr_t curr;
- struct vnt_tx_desc *desc;
- int ret;
-
- /* Init the TD ring entries */
- curr = priv->td1_pool_dma;
- for (i = 0; i < priv->opts.tx_descs[1];
- i++, curr += sizeof(struct vnt_tx_desc)) {
- desc = &priv->ap_td1_rings[i];
- desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL);
- if (!desc->td_info) {
- ret = -ENOMEM;
- goto err_free_desc;
- }
-
- desc->td_info->buf = priv->tx1_bufs + i * PKT_BUF_SZ;
- desc->td_info->buf_dma = priv->tx_bufs_dma1 + i * PKT_BUF_SZ;
-
- desc->next = &(priv->ap_td1_rings[(i + 1) % priv->opts.tx_descs[1]]);
- desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_tx_desc));
- }
-
- if (i > 0)
- priv->ap_td1_rings[i - 1].next_desc = cpu_to_le32(priv->td1_pool_dma);
- priv->tail_td[1] = priv->apCurrTD[1] = &priv->ap_td1_rings[0];
-
- return 0;
-
-err_free_desc:
- while (i--) {
- desc = &priv->ap_td1_rings[i];
- kfree(desc->td_info);
- }
-
- return ret;
-}
-
-static void device_free_td0_ring(struct vnt_private *priv)
-{
- int i;
-
- for (i = 0; i < priv->opts.tx_descs[0]; i++) {
- struct vnt_tx_desc *desc = &priv->ap_td0_rings[i];
- struct vnt_td_info *td_info = desc->td_info;
-
- dev_kfree_skb(td_info->skb);
- kfree(desc->td_info);
- }
-}
-
-static void device_free_td1_ring(struct vnt_private *priv)
-{
- int i;
-
- for (i = 0; i < priv->opts.tx_descs[1]; i++) {
- struct vnt_tx_desc *desc = &priv->ap_td1_rings[i];
- struct vnt_td_info *td_info = desc->td_info;
-
- dev_kfree_skb(td_info->skb);
- kfree(desc->td_info);
- }
-}
-
-/*-----------------------------------------------------------------*/
-
-static int device_rx_srv(struct vnt_private *priv, unsigned int idx)
-{
- struct vnt_rx_desc *rd;
- int works = 0;
-
- for (rd = priv->pCurrRD[idx];
- rd->rd0.owner == OWNED_BY_HOST;
- rd = rd->next) {
- if (works++ > 15)
- break;
-
- if (!rd->rd_info->skb)
- break;
-
- if (vnt_receive_frame(priv, rd)) {
- if (!device_alloc_rx_buf(priv, rd)) {
- dev_err(&priv->pcid->dev,
- "can not allocate rx buf\n");
- break;
- }
- }
- rd->rd0.owner = OWNED_BY_NIC;
- }
-
- priv->pCurrRD[idx] = rd;
-
- return works;
-}
-
-static bool device_alloc_rx_buf(struct vnt_private *priv,
- struct vnt_rx_desc *rd)
-{
- struct vnt_rd_info *rd_info = rd->rd_info;
-
- rd_info->skb = dev_alloc_skb((int)priv->rx_buf_sz);
- if (!rd_info->skb)
- return false;
-
- rd_info->skb_dma =
- dma_map_single(&priv->pcid->dev,
- skb_put(rd_info->skb, skb_tailroom(rd_info->skb)),
- priv->rx_buf_sz, DMA_FROM_DEVICE);
- if (dma_mapping_error(&priv->pcid->dev, rd_info->skb_dma)) {
- dev_kfree_skb(rd_info->skb);
- rd_info->skb = NULL;
- return false;
- }
-
- *((unsigned int *)&rd->rd0) = 0; /* FIX cast */
-
- rd->rd0.res_count = cpu_to_le16(priv->rx_buf_sz);
- rd->rd0.owner = OWNED_BY_NIC;
- rd->rd1.req_count = cpu_to_le16(priv->rx_buf_sz);
- rd->buff_addr = cpu_to_le32(rd_info->skb_dma);
-
- return true;
-}
-
-static void device_free_rx_buf(struct vnt_private *priv,
- struct vnt_rx_desc *rd)
-{
- struct vnt_rd_info *rd_info = rd->rd_info;
-
- dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma,
- priv->rx_buf_sz, DMA_FROM_DEVICE);
- dev_kfree_skb(rd_info->skb);
-}
-
-static const u8 fallback_rate0[5][5] = {
- {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M},
- {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M},
- {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M},
- {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M},
- {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M}
-};
-
-static const u8 fallback_rate1[5][5] = {
- {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M},
- {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M},
- {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M},
- {RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M},
- {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M}
-};
-
-static int vnt_int_report_rate(struct vnt_private *priv,
- struct vnt_td_info *context, u8 tsr0, u8 tsr1)
-{
- struct vnt_tx_fifo_head *fifo_head;
- struct ieee80211_tx_info *info;
- struct ieee80211_rate *rate;
- u16 fb_option;
- u8 tx_retry = (tsr0 & TSR0_NCR);
- s8 idx;
-
- if (!context)
- return -ENOMEM;
-
- if (!context->skb)
- return -EINVAL;
-
- fifo_head = (struct vnt_tx_fifo_head *)context->buf;
- fb_option = (le16_to_cpu(fifo_head->fifo_ctl) &
- (FIFOCTL_AUTO_FB_0 | FIFOCTL_AUTO_FB_1));
-
- info = IEEE80211_SKB_CB(context->skb);
- idx = info->control.rates[0].idx;
-
- if (fb_option && !(tsr1 & TSR1_TERR)) {
- u8 tx_rate;
- u8 retry = tx_retry;
-
- rate = ieee80211_get_tx_rate(priv->hw, info);
- tx_rate = rate->hw_value - RATE_18M;
-
- if (retry > 4)
- retry = 4;
-
- if (fb_option & FIFOCTL_AUTO_FB_0)
- tx_rate = fallback_rate0[tx_rate][retry];
- else if (fb_option & FIFOCTL_AUTO_FB_1)
- tx_rate = fallback_rate1[tx_rate][retry];
-
- if (info->band == NL80211_BAND_5GHZ)
- idx = tx_rate - RATE_6M;
- else
- idx = tx_rate;
- }
-
- ieee80211_tx_info_clear_status(info);
-
- info->status.rates[0].count = tx_retry;
-
- if (!(tsr1 & TSR1_TERR)) {
- info->status.rates[0].idx = idx;
-
- if (info->flags & IEEE80211_TX_CTL_NO_ACK)
- info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
- else
- info->flags |= IEEE80211_TX_STAT_ACK;
- }
-
- return 0;
-}
-
-static int device_tx_srv(struct vnt_private *priv, unsigned int idx)
-{
- struct vnt_tx_desc *desc;
- int works = 0;
- unsigned char byTsr0;
- unsigned char byTsr1;
-
- for (desc = priv->tail_td[idx]; priv->iTDUsed[idx] > 0; desc = desc->next) {
- if (desc->td0.owner == OWNED_BY_NIC)
- break;
- if (works++ > 15)
- break;
-
- byTsr0 = desc->td0.tsr0;
- byTsr1 = desc->td0.tsr1;
-
- /* Only the status of first TD in the chain is correct */
- if (desc->td1.tcr & TCR_STP) {
- if ((desc->td_info->flags & TD_FLAGS_NETIF_SKB) != 0) {
- if (!(byTsr1 & TSR1_TERR)) {
- if (byTsr0 != 0) {
- pr_debug(" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X]\n",
- (int)idx, byTsr1,
- byTsr0);
- }
- } else {
- pr_debug(" Tx[%d] dropped & tsr1[%02X] tsr0[%02X]\n",
- (int)idx, byTsr1, byTsr0);
- }
- }
-
- if (byTsr1 & TSR1_TERR) {
- if ((desc->td_info->flags & TD_FLAGS_PRIV_SKB) != 0) {
- pr_debug(" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X]\n",
- (int)idx, byTsr1, byTsr0);
- }
- }
-
- vnt_int_report_rate(priv, desc->td_info, byTsr0, byTsr1);
-
- device_free_tx_buf(priv, desc);
- priv->iTDUsed[idx]--;
- }
- }
-
- priv->tail_td[idx] = desc;
-
- return works;
-}
-
-static void device_error(struct vnt_private *priv, unsigned short status)
-{
- if (status & ISR_FETALERR) {
- dev_err(&priv->pcid->dev, "Hardware fatal error\n");
-
- MACbShutdown(priv);
- return;
- }
-}
-
-static void device_free_tx_buf(struct vnt_private *priv,
- struct vnt_tx_desc *desc)
-{
- struct vnt_td_info *td_info = desc->td_info;
- struct sk_buff *skb = td_info->skb;
-
- if (skb)
- ieee80211_tx_status_irqsafe(priv->hw, skb);
-
- td_info->skb = NULL;
- td_info->flags = 0;
-}
-
-static void vnt_check_bb_vga(struct vnt_private *priv)
-{
- long dbm;
- int i;
-
- if (!priv->update_bbvga)
- return;
-
- if (priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
- return;
-
- if (!(priv->vif->cfg.assoc && priv->current_rssi))
- return;
-
- RFvRSSITodBm(priv, (u8)priv->current_rssi, &dbm);
-
- for (i = 0; i < BB_VGA_LEVEL; i++) {
- if (dbm < priv->dbm_threshold[i]) {
- priv->bbvga_new = priv->bbvga[i];
- break;
- }
- }
-
- if (priv->bbvga_new == priv->bbvga_current) {
- priv->uBBVGADiffCount = 1;
- return;
- }
-
- priv->uBBVGADiffCount++;
-
- if (priv->uBBVGADiffCount == 1) {
- /* first VGA diff gain */
- bb_set_vga_gain_offset(priv, priv->bbvga_new);
-
- dev_dbg(&priv->pcid->dev,
- "First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
- (int)dbm, priv->bbvga_new,
- priv->bbvga_current,
- (int)priv->uBBVGADiffCount);
- }
-
- if (priv->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) {
- dev_dbg(&priv->pcid->dev,
- "RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
- (int)dbm, priv->bbvga_new,
- priv->bbvga_current,
- (int)priv->uBBVGADiffCount);
-
- bb_set_vga_gain_offset(priv, priv->bbvga_new);
- }
-}
-
-static void vnt_interrupt_process(struct vnt_private *priv)
-{
- struct ieee80211_low_level_stats *low_stats = &priv->low_stats;
- int max_count = 0;
- u32 mib_counter;
- u32 isr;
- unsigned long flags;
-
- isr = ioread32(priv->port_offset + MAC_REG_ISR);
-
- if (isr == 0)
- return;
-
- if (isr == 0xffffffff) {
- pr_debug("isr = 0xffff\n");
- return;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* Read low level stats */
- mib_counter = ioread32(priv->port_offset + MAC_REG_MIBCNTR);
-
- low_stats->dot11RTSSuccessCount += mib_counter & 0xff;
- low_stats->dot11RTSFailureCount += (mib_counter >> 8) & 0xff;
- low_stats->dot11ACKFailureCount += (mib_counter >> 16) & 0xff;
- low_stats->dot11FCSErrorCount += (mib_counter >> 24) & 0xff;
-
- /*
- * TBD....
- * Must do this after doing rx/tx, cause ISR bit is slow
- * than RD/TD write back
- * update ISR counter
- */
- while (isr && priv->vif) {
- iowrite32(isr, priv->port_offset + MAC_REG_ISR);
-
- if (isr & ISR_FETALERR) {
- pr_debug(" ISR_FETALERR\n");
- iowrite8(0, priv->port_offset + MAC_REG_SOFTPWRCTL);
- iowrite16(SOFTPWRCTL_SWPECTI, priv->port_offset + MAC_REG_SOFTPWRCTL);
- device_error(priv, isr);
- }
-
- if (isr & ISR_TBTT) {
- if (priv->op_mode != NL80211_IFTYPE_ADHOC)
- vnt_check_bb_vga(priv);
-
- priv->bBeaconSent = false;
- if (priv->bEnablePSMode)
- PSbIsNextTBTTWakeUp((void *)priv);
-
- if ((priv->op_mode == NL80211_IFTYPE_AP ||
- priv->op_mode == NL80211_IFTYPE_ADHOC) &&
- priv->vif->bss_conf.enable_beacon)
- MACvOneShotTimer1MicroSec(priv,
- (priv->vif->bss_conf.beacon_int -
- MAKE_BEACON_RESERVED) << 10);
-
- /* TODO: adhoc PS mode */
- }
-
- if (isr & ISR_BNTX) {
- if (priv->op_mode == NL80211_IFTYPE_ADHOC) {
- priv->bIsBeaconBufReadySet = false;
- priv->cbBeaconBufReadySetCnt = 0;
- }
-
- priv->bBeaconSent = true;
- }
-
- if (isr & ISR_RXDMA0)
- max_count += device_rx_srv(priv, TYPE_RXDMA0);
-
- if (isr & ISR_RXDMA1)
- max_count += device_rx_srv(priv, TYPE_RXDMA1);
-
- if (isr & ISR_TXDMA0)
- max_count += device_tx_srv(priv, TYPE_TXDMA0);
-
- if (isr & ISR_AC0DMA)
- max_count += device_tx_srv(priv, TYPE_AC0DMA);
-
- if (isr & ISR_SOFTTIMER1) {
- if (priv->vif->bss_conf.enable_beacon)
- vnt_beacon_make(priv, priv->vif);
- }
-
- /* If both buffers available wake the queue */
- if (AVAIL_TD(priv, TYPE_TXDMA0) &&
- AVAIL_TD(priv, TYPE_AC0DMA) &&
- ieee80211_queue_stopped(priv->hw, 0))
- ieee80211_wake_queues(priv->hw);
-
- isr = ioread32(priv->port_offset + MAC_REG_ISR);
-
- vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL0);
- vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL1);
-
- if (max_count > priv->opts.int_works)
- break;
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static void vnt_interrupt_work(struct work_struct *work)
-{
- struct vnt_private *priv =
- container_of(work, struct vnt_private, interrupt_work);
-
- if (priv->vif)
- vnt_interrupt_process(priv);
-
- iowrite32(IMR_MASK_VALUE, priv->port_offset + MAC_REG_IMR);
-}
-
-static irqreturn_t vnt_interrupt(int irq, void *arg)
-{
- struct vnt_private *priv = arg;
-
- schedule_work(&priv->interrupt_work);
-
- iowrite32(0, priv->port_offset + MAC_REG_IMR);
-
- return IRQ_HANDLED;
-}
-
-static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
-{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct vnt_tx_desc *head_td;
- u32 dma_idx;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- if (ieee80211_is_data(hdr->frame_control))
- dma_idx = TYPE_AC0DMA;
- else
- dma_idx = TYPE_TXDMA0;
-
- if (AVAIL_TD(priv, dma_idx) < 1) {
- spin_unlock_irqrestore(&priv->lock, flags);
- ieee80211_stop_queues(priv->hw);
- return -ENOMEM;
- }
-
- head_td = priv->apCurrTD[dma_idx];
-
- head_td->td1.tcr = 0;
-
- head_td->td_info->skb = skb;
-
- if (dma_idx == TYPE_AC0DMA)
- head_td->td_info->flags = TD_FLAGS_NETIF_SKB;
-
- priv->apCurrTD[dma_idx] = head_td->next;
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- vnt_generate_fifo_header(priv, dma_idx, head_td, skb);
-
- spin_lock_irqsave(&priv->lock, flags);
-
- priv->bPWBitOn = false;
-
- /* Set TSR1 & ReqCount in TxDescHead */
- head_td->td1.tcr |= (TCR_STP | TCR_EDP | EDMSDU);
- head_td->td1.req_count = cpu_to_le16(head_td->td_info->req_count);
-
- head_td->buff_addr = cpu_to_le32(head_td->td_info->buf_dma);
-
- /* Poll Transmit the adapter */
- wmb();
- head_td->td0.owner = OWNED_BY_NIC;
- wmb(); /* second memory barrier */
-
- if (head_td->td_info->flags & TD_FLAGS_NETIF_SKB)
- vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_AC0DMACTL);
- else
- vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_TXDMACTL0);
-
- priv->iTDUsed[dma_idx]++;
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-static void vnt_tx_80211(struct ieee80211_hw *hw,
- struct ieee80211_tx_control *control,
- struct sk_buff *skb)
-{
- struct vnt_private *priv = hw->priv;
-
- if (vnt_tx_packet(priv, skb))
- ieee80211_free_txskb(hw, skb);
-}
-
-static int vnt_start(struct ieee80211_hw *hw)
-{
- struct vnt_private *priv = hw->priv;
- int ret;
-
- priv->rx_buf_sz = PKT_BUF_SZ;
- if (!device_init_rings(priv))
- return -ENOMEM;
-
- ret = request_irq(priv->pcid->irq, vnt_interrupt,
- IRQF_SHARED, "vt6655", priv);
- if (ret) {
- dev_dbg(&priv->pcid->dev, "failed to start irq\n");
- goto err_free_rings;
- }
-
- dev_dbg(&priv->pcid->dev, "call device init rd0 ring\n");
- ret = device_init_rd0_ring(priv);
- if (ret)
- goto err_free_irq;
- ret = device_init_rd1_ring(priv);
- if (ret)
- goto err_free_rd0_ring;
- ret = device_init_td0_ring(priv);
- if (ret)
- goto err_free_rd1_ring;
- ret = device_init_td1_ring(priv);
- if (ret)
- goto err_free_td0_ring;
-
- device_init_registers(priv);
-
- dev_dbg(&priv->pcid->dev, "enable MAC interrupt\n");
- iowrite32(IMR_MASK_VALUE, priv->port_offset + MAC_REG_IMR);
-
- ieee80211_wake_queues(hw);
-
- return 0;
-
-err_free_td0_ring:
- device_free_td0_ring(priv);
-err_free_rd1_ring:
- device_free_rd1_ring(priv);
-err_free_rd0_ring:
- device_free_rd0_ring(priv);
-err_free_irq:
- free_irq(priv->pcid->irq, priv);
-err_free_rings:
- device_free_rings(priv);
- return ret;
-}
-
-static void vnt_stop(struct ieee80211_hw *hw, bool suspend)
-{
- struct vnt_private *priv = hw->priv;
-
- ieee80211_stop_queues(hw);
-
- cancel_work_sync(&priv->interrupt_work);
-
- MACbShutdown(priv);
- MACbSoftwareReset(priv);
- card_radio_power_off(priv);
-
- device_free_td0_ring(priv);
- device_free_td1_ring(priv);
- device_free_rd0_ring(priv);
- device_free_rd1_ring(priv);
- device_free_rings(priv);
-
- free_irq(priv->pcid->irq, priv);
-}
-
-static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- priv->vif = vif;
-
- switch (vif->type) {
- case NL80211_IFTYPE_STATION:
- break;
- case NL80211_IFTYPE_ADHOC:
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_RCR, RCR_UNICAST);
-
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_ADHOC);
-
- break;
- case NL80211_IFTYPE_AP:
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_RCR, RCR_UNICAST);
-
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_AP);
-
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- priv->op_mode = vif->type;
-
- return 0;
-}
-
-static void vnt_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- switch (vif->type) {
- case NL80211_IFTYPE_STATION:
- break;
- case NL80211_IFTYPE_ADHOC:
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX);
- vt6655_mac_reg_bits_off(priv->port_offset,
- MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_ADHOC);
- break;
- case NL80211_IFTYPE_AP:
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX);
- vt6655_mac_reg_bits_off(priv->port_offset,
- MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_AP);
- break;
- default:
- break;
- }
-
- priv->op_mode = NL80211_IFTYPE_UNSPECIFIED;
-}
-
-static int vnt_config(struct ieee80211_hw *hw, u32 changed)
-{
- struct vnt_private *priv = hw->priv;
- struct ieee80211_conf *conf = &hw->conf;
- u8 bb_type;
-
- if (changed & IEEE80211_CONF_CHANGE_PS) {
- if (conf->flags & IEEE80211_CONF_PS)
- PSvEnablePowerSaving(priv, conf->listen_interval);
- else
- PSvDisablePowerSaving(priv);
- }
-
- if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) ||
- (conf->flags & IEEE80211_CONF_OFFCHANNEL)) {
- set_channel(priv, conf->chandef.chan);
-
- if (conf->chandef.chan->band == NL80211_BAND_5GHZ)
- bb_type = BB_TYPE_11A;
- else
- bb_type = BB_TYPE_11G;
-
- if (priv->byBBType != bb_type) {
- priv->byBBType = bb_type;
-
- card_set_phy_parameter(priv, priv->byBBType);
- }
- }
-
- if (changed & IEEE80211_CONF_CHANGE_POWER) {
- if (priv->byBBType == BB_TYPE_11B)
- priv->wCurrentRate = RATE_1M;
- else
- priv->wCurrentRate = RATE_54M;
-
- RFbSetPower(priv, priv->wCurrentRate,
- conf->chandef.chan->hw_value);
- }
-
- return 0;
-}
-
-static void vnt_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf, u64 changed)
-{
- struct vnt_private *priv = hw->priv;
-
- priv->current_aid = vif->cfg.aid;
-
- if (changed & BSS_CHANGED_BSSID && conf->bssid) {
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- vt6655_mac_write_bssid_addr(priv->port_offset, conf->bssid);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- }
-
- if (changed & BSS_CHANGED_BASIC_RATES) {
- priv->basic_rates = conf->basic_rates;
-
- CARDvUpdateBasicTopRate(priv);
-
- dev_dbg(&priv->pcid->dev,
- "basic rates %x\n", conf->basic_rates);
- }
-
- if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- if (conf->use_short_preamble) {
- vt6655_mac_en_barker_preamble_md(priv->port_offset);
- priv->preamble_type = true;
- } else {
- vt6655_mac_dis_barker_preamble_md(priv->port_offset);
- priv->preamble_type = false;
- }
- }
-
- if (changed & BSS_CHANGED_ERP_CTS_PROT) {
- if (conf->use_cts_prot)
- vt6655_mac_en_protect_md(priv->port_offset);
- else
- vt6655_mac_dis_protect_md(priv->port_offset);
- }
-
- if (changed & BSS_CHANGED_ERP_SLOT) {
- if (conf->use_short_slot)
- priv->short_slot_time = true;
- else
- priv->short_slot_time = false;
-
- card_set_phy_parameter(priv, priv->byBBType);
- bb_set_vga_gain_offset(priv, priv->bbvga[0]);
- }
-
- if (changed & BSS_CHANGED_TXPOWER)
- RFbSetPower(priv, priv->wCurrentRate,
- conf->chanreq.oper.chan->hw_value);
-
- if (changed & BSS_CHANGED_BEACON_ENABLED) {
- dev_dbg(&priv->pcid->dev,
- "Beacon enable %d\n", conf->enable_beacon);
-
- if (conf->enable_beacon) {
- vnt_beacon_enable(priv, vif, conf);
-
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX);
- } else {
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TCR,
- TCR_AUTOBCNTX);
- }
- }
-
- if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INFO) &&
- priv->op_mode != NL80211_IFTYPE_AP) {
- if (vif->cfg.assoc && conf->beacon_rate) {
- card_update_tsf(priv, conf->beacon_rate->hw_value,
- conf->sync_tsf);
-
- card_set_beacon_period(priv, conf->beacon_int);
-
- CARDvSetFirstNextTBTT(priv, conf->beacon_int);
- } else {
- iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL);
- iowrite8(TFTCTL_TSFCNTREN, priv->port_offset + MAC_REG_TFTCTL);
- }
- }
-}
-
-static u64 vnt_prepare_multicast(struct ieee80211_hw *hw,
- struct netdev_hw_addr_list *mc_list)
-{
- struct vnt_private *priv = hw->priv;
- struct netdev_hw_addr *ha;
- u64 mc_filter = 0;
- u32 bit_nr = 0;
-
- netdev_hw_addr_list_for_each(ha, mc_list) {
- bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
-
- mc_filter |= 1ULL << (bit_nr & 0x3f);
- }
-
- priv->mc_list_count = mc_list->count;
-
- return mc_filter;
-}
-
-static void vnt_configure(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *total_flags, u64 multicast)
-{
- struct vnt_private *priv = hw->priv;
- u8 rx_mode = 0;
-
- *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC;
-
- rx_mode = ioread8(priv->port_offset + MAC_REG_RCR);
-
- dev_dbg(&priv->pcid->dev, "rx mode in = %x\n", rx_mode);
-
- if (changed_flags & FIF_ALLMULTI) {
- if (*total_flags & FIF_ALLMULTI) {
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- if (priv->mc_list_count > 2) {
- VT6655_MAC_SELECT_PAGE1(priv->port_offset);
-
- iowrite32(0xffffffff, priv->port_offset + MAC_REG_MAR0);
- iowrite32(0xffffffff, priv->port_offset + MAC_REG_MAR0 + 4);
-
- VT6655_MAC_SELECT_PAGE0(priv->port_offset);
- } else {
- VT6655_MAC_SELECT_PAGE1(priv->port_offset);
-
- multicast = le64_to_cpu(multicast);
- iowrite32((u32)multicast, priv->port_offset + MAC_REG_MAR0);
- iowrite32((u32)(multicast >> 32),
- priv->port_offset + MAC_REG_MAR0 + 4);
-
- VT6655_MAC_SELECT_PAGE0(priv->port_offset);
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- rx_mode |= RCR_MULTICAST | RCR_BROADCAST;
- } else {
- rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST);
- }
- }
-
- if (changed_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) {
- rx_mode |= RCR_MULTICAST | RCR_BROADCAST;
-
- if (*total_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC))
- rx_mode &= ~RCR_BSSID;
- else
- rx_mode |= RCR_BSSID;
- }
-
- iowrite8(rx_mode, priv->port_offset + MAC_REG_RCR);
-
- dev_dbg(&priv->pcid->dev, "rx mode out= %x\n", rx_mode);
-}
-
-static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
-{
- struct vnt_private *priv = hw->priv;
-
- switch (cmd) {
- case SET_KEY:
- if (vnt_set_keys(hw, sta, vif, key))
- return -EOPNOTSUPP;
- break;
- case DISABLE_KEY:
- if (test_bit(key->hw_key_idx, &priv->key_entry_inuse))
- clear_bit(key->hw_key_idx, &priv->key_entry_inuse);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static int vnt_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
-{
- struct vnt_private *priv = hw->priv;
-
- memcpy(stats, &priv->low_stats, sizeof(*stats));
-
- return 0;
-}
-
-static u64 vnt_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
- u64 tsf;
-
- tsf = vt6655_get_current_tsf(priv);
-
- return tsf;
-}
-
-static void vnt_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- u64 tsf)
-{
- struct vnt_private *priv = hw->priv;
-
- CARDvUpdateNextTBTT(priv, tsf, vif->bss_conf.beacon_int);
-}
-
-static void vnt_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- /* reset TSF counter */
- iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL);
-}
-
-static const struct ieee80211_ops vnt_mac_ops = {
- .add_chanctx = ieee80211_emulate_add_chanctx,
- .remove_chanctx = ieee80211_emulate_remove_chanctx,
- .change_chanctx = ieee80211_emulate_change_chanctx,
- .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
- .tx = vnt_tx_80211,
- .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = vnt_start,
- .stop = vnt_stop,
- .add_interface = vnt_add_interface,
- .remove_interface = vnt_remove_interface,
- .config = vnt_config,
- .bss_info_changed = vnt_bss_info_changed,
- .prepare_multicast = vnt_prepare_multicast,
- .configure_filter = vnt_configure,
- .set_key = vnt_set_key,
- .get_stats = vnt_get_stats,
- .get_tsf = vnt_get_tsf,
- .set_tsf = vnt_set_tsf,
- .reset_tsf = vnt_reset_tsf,
-};
-
-static int vnt_init(struct vnt_private *priv)
-{
- SET_IEEE80211_PERM_ADDR(priv->hw, priv->abyCurrentNetAddr);
-
- vnt_init_bands(priv);
-
- if (ieee80211_register_hw(priv->hw))
- return -ENODEV;
-
- priv->mac_hw = true;
-
- card_radio_power_off(priv);
-
- return 0;
-}
-
-static int
-vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
-{
- struct vnt_private *priv;
- struct ieee80211_hw *hw;
- struct wiphy *wiphy;
- int rc;
-
- dev_notice(&pcid->dev,
- "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION);
-
- dev_notice(&pcid->dev,
- "Copyright (c) 2003 VIA Networking Technologies, Inc.\n");
-
- hw = ieee80211_alloc_hw(sizeof(*priv), &vnt_mac_ops);
- if (!hw) {
- dev_err(&pcid->dev, "could not register ieee80211_hw\n");
- return -ENOMEM;
- }
-
- priv = hw->priv;
- priv->pcid = pcid;
-
- spin_lock_init(&priv->lock);
-
- priv->hw = hw;
-
- SET_IEEE80211_DEV(priv->hw, &pcid->dev);
-
- if (pci_enable_device(pcid)) {
- device_free_info(priv);
- return -ENODEV;
- }
-
- dev_dbg(&pcid->dev,
- "Before get pci_info memaddr is %x\n", priv->memaddr);
-
- pci_set_master(pcid);
-
- priv->memaddr = pci_resource_start(pcid, 0);
- priv->ioaddr = pci_resource_start(pcid, 1);
- priv->port_offset = ioremap(priv->memaddr & PCI_BASE_ADDRESS_MEM_MASK,
- 256);
- if (!priv->port_offset) {
- dev_err(&pcid->dev, ": Failed to IO remapping ..\n");
- device_free_info(priv);
- return -ENODEV;
- }
-
- rc = pci_request_regions(pcid, DEVICE_NAME);
- if (rc) {
- dev_err(&pcid->dev, ": Failed to find PCI device\n");
- device_free_info(priv);
- return -ENODEV;
- }
-
- if (dma_set_mask(&pcid->dev, DMA_BIT_MASK(32))) {
- dev_err(&pcid->dev, ": Failed to set dma 32 bit mask\n");
- device_free_info(priv);
- return -ENODEV;
- }
-
- INIT_WORK(&priv->interrupt_work, vnt_interrupt_work);
-
- /* do reset */
- if (!MACbSoftwareReset(priv)) {
- dev_err(&pcid->dev, ": Failed to access MAC hardware..\n");
- device_free_info(priv);
- return -ENODEV;
- }
- /* initial to reload eeprom */
- MACvInitialize(priv);
- vt6655_mac_read_ether_addr(priv->port_offset, priv->abyCurrentNetAddr);
-
- /* Get RFType */
- priv->rf_type = SROMbyReadEmbedded(priv->port_offset, EEP_OFS_RFTYPE);
- priv->rf_type &= RF_MASK;
-
- dev_dbg(&pcid->dev, "RF Type = %x\n", priv->rf_type);
-
- device_get_options(priv);
- device_set_options(priv);
-
- wiphy = priv->hw->wiphy;
-
- wiphy->frag_threshold = FRAG_THRESH_DEF;
- wiphy->rts_threshold = RTS_THRESH_DEF;
- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
-
- ieee80211_hw_set(priv->hw, TIMING_BEACON_ONLY);
- ieee80211_hw_set(priv->hw, SIGNAL_DBM);
- ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS);
- ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS);
- ieee80211_hw_set(priv->hw, SUPPORTS_PS);
-
- priv->hw->max_signal = 100;
-
- if (vnt_init(priv)) {
- device_free_info(priv);
- return -ENODEV;
- }
-
- device_print_info(priv);
- pci_set_drvdata(pcid, priv);
-
- return 0;
-}
-
-/*------------------------------------------------------------------*/
-
-static int __maybe_unused vt6655_suspend(struct device *dev_d)
-{
- struct vnt_private *priv = dev_get_drvdata(dev_d);
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- MACbShutdown(priv);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-static int __maybe_unused vt6655_resume(struct device *dev_d)
-{
- device_wakeup_disable(dev_d);
-
- return 0;
-}
-
-MODULE_DEVICE_TABLE(pci, vt6655_pci_id_table);
-
-static SIMPLE_DEV_PM_OPS(vt6655_pm_ops, vt6655_suspend, vt6655_resume);
-
-static struct pci_driver device_driver = {
- .name = DEVICE_NAME,
- .id_table = vt6655_pci_id_table,
- .probe = vt6655_probe,
- .remove = vt6655_remove,
- .driver.pm = &vt6655_pm_ops,
-};
-
-module_pci_driver(device_driver);
diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c
deleted file mode 100644
index 7ada188e2048..000000000000
--- a/drivers/staging/vt6655/dpc.c
+++ /dev/null
@@ -1,145 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: handle dpc rx functions
- *
- * Author: Lyndon Chen
- *
- * Date: May 20, 2003
- *
- * Functions:
- *
- * Revision History:
- *
- */
-
-#include "device.h"
-#include "baseband.h"
-#include "rf.h"
-#include "dpc.h"
-
-static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb,
- u16 bytes_received)
-{
- struct ieee80211_hw *hw = priv->hw;
- struct ieee80211_supported_band *sband;
- struct ieee80211_rx_status rx_status = { 0 };
- struct ieee80211_hdr *hdr;
- __le16 fc;
- u8 *rsr, *new_rsr, *rssi;
- __le64 *tsf_time;
- u16 frame_size;
- int ii, r;
- u8 *rx_rate;
- u8 *skb_data;
- u8 rate_idx = 0;
- u8 rate[MAX_RATE] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108};
- long rx_dbm;
-
- /* [31:16]RcvByteCount ( not include 4-byte Status ) */
- frame_size = le16_to_cpu(*((__le16 *)(skb->data + 2)));
- if (frame_size > 2346 || frame_size < 14) {
- dev_dbg(&priv->pcid->dev, "------- WRONG Length 1\n");
- return false;
- }
-
- skb_data = (u8 *)skb->data;
-
- rx_rate = skb_data + 1;
-
- sband = hw->wiphy->bands[hw->conf.chandef.chan->band];
-
- for (r = RATE_1M; r < MAX_RATE; r++) {
- if (*rx_rate == rate[r])
- break;
- }
-
- priv->rx_rate = r;
-
- for (ii = 0; ii < sband->n_bitrates; ii++) {
- if (sband->bitrates[ii].hw_value == r) {
- rate_idx = ii;
- break;
- }
- }
-
- if (ii == sband->n_bitrates) {
- dev_dbg(&priv->pcid->dev, "Wrong RxRate %x\n", *rx_rate);
- return false;
- }
-
- tsf_time = (__le64 *)(skb_data + bytes_received - 12);
- new_rsr = skb_data + bytes_received - 3;
- rssi = skb_data + bytes_received - 2;
- rsr = skb_data + bytes_received - 1;
- if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN))
- return false;
-
- RFvRSSITodBm(priv, *rssi, &rx_dbm);
-
- priv->bb_pre_edrssi = (u8)rx_dbm + 1;
- priv->current_rssi = *rssi;
-
- skb_pull(skb, 4);
- skb_trim(skb, frame_size);
-
- rx_status.mactime = le64_to_cpu(*tsf_time);
- rx_status.band = hw->conf.chandef.chan->band;
- rx_status.signal = rx_dbm;
- rx_status.flag = 0;
- rx_status.freq = hw->conf.chandef.chan->center_freq;
-
- if (!(*rsr & RSR_CRCOK))
- rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
-
- hdr = (struct ieee80211_hdr *)(skb->data);
- fc = hdr->frame_control;
-
- rx_status.rate_idx = rate_idx;
-
- if (ieee80211_has_protected(fc)) {
- if (priv->local_id > REV_ID_VT3253_A1)
- rx_status.flag |= RX_FLAG_DECRYPTED;
-
- /* Drop packet */
- if (!(*new_rsr & NEWRSR_DECRYPTOK))
- return false;
- }
-
- memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
-
- ieee80211_rx_irqsafe(priv->hw, skb);
-
- return true;
-}
-
-bool vnt_receive_frame(struct vnt_private *priv, struct vnt_rx_desc *curr_rd)
-{
- struct vnt_rd_info *rd_info = curr_rd->rd_info;
- struct sk_buff *skb;
- u16 frame_size;
-
- skb = rd_info->skb;
-
- dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma,
- priv->rx_buf_sz, DMA_FROM_DEVICE);
-
- frame_size = le16_to_cpu(curr_rd->rd1.req_count)
- - le16_to_cpu(curr_rd->rd0.res_count);
-
- if ((frame_size > 2364) || (frame_size < 33)) {
- /* Frame Size error drop this packet.*/
- dev_dbg(&priv->pcid->dev, "Wrong frame size %d\n", frame_size);
- dev_kfree_skb_irq(skb);
- return true;
- }
-
- if (vnt_rx_data(priv, skb, frame_size))
- return true;
-
- dev_kfree_skb_irq(skb);
-
- return true;
-}
diff --git a/drivers/staging/vt6655/dpc.h b/drivers/staging/vt6655/dpc.h
deleted file mode 100644
index 40364c0ab7f6..000000000000
--- a/drivers/staging/vt6655/dpc.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:
- *
- * Author: Jerry Chen
- *
- * Date: Jun. 27, 2002
- *
- */
-
-#ifndef __DPC_H__
-#define __DPC_H__
-
-#include "device.h"
-
-bool vnt_receive_frame(struct vnt_private *priv, struct vnt_rx_desc *curr_rd);
-
-#endif /* __RXTX_H__ */
diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c
deleted file mode 100644
index 1469015eb5b4..000000000000
--- a/drivers/staging/vt6655/key.c
+++ /dev/null
@@ -1,143 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions for 802.11i Key management
- *
- * Author: Jerry Chen
- *
- * Date: May 29, 2003
- *
- */
-
-#include "key.h"
-#include "mac.h"
-
-static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr,
- struct ieee80211_key_conf *key, u32 key_type,
- u32 mode, bool onfly_latch)
-{
- struct vnt_private *priv = hw->priv;
- u8 broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- u16 key_mode = 0;
- u32 entry = 0;
- u8 *bssid;
- u8 key_inx = key->keyidx;
- u8 i;
-
- if (mac_addr)
- bssid = mac_addr;
- else
- bssid = &broadcast[0];
-
- if (key_type != VNT_KEY_DEFAULTKEY) {
- for (i = 0; i < (MAX_KEY_TABLE - 1); i++) {
- if (!test_bit(i, &priv->key_entry_inuse)) {
- set_bit(i, &priv->key_entry_inuse);
-
- key->hw_key_idx = i;
- entry = key->hw_key_idx;
- break;
- }
- }
- }
-
- switch (key_type) {
- case VNT_KEY_DEFAULTKEY:
- /* default key last entry */
- entry = MAX_KEY_TABLE - 1;
- key->hw_key_idx = entry;
- fallthrough;
- case VNT_KEY_ALLGROUP:
- key_mode |= VNT_KEY_ALLGROUP;
- if (onfly_latch)
- key_mode |= VNT_KEY_ONFLY_ALL;
- fallthrough;
- case VNT_KEY_GROUP_ADDRESS:
- key_mode |= mode;
- fallthrough;
- case VNT_KEY_GROUP:
- key_mode |= (mode << 4);
- key_mode |= VNT_KEY_GROUP;
- break;
- case VNT_KEY_PAIRWISE:
- key_mode |= mode;
- key_inx = 4;
- break;
- default:
- return -EINVAL;
- }
-
- if (onfly_latch)
- key_mode |= VNT_KEY_ONFLY;
-
- if (mode == KEY_CTL_WEP) {
- if (key->keylen == WLAN_KEY_LEN_WEP40)
- key->key[15] &= 0x7f;
- if (key->keylen == WLAN_KEY_LEN_WEP104)
- key->key[15] |= 0x80;
- }
-
- MACvSetKeyEntry(priv, key_mode, entry, key_inx,
- bssid, (u32 *)key->key, priv->local_id);
-
- return 0;
-}
-
-int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
- struct ieee80211_vif *vif, struct ieee80211_key_conf *key)
-{
- struct ieee80211_bss_conf *conf = &vif->bss_conf;
- struct vnt_private *priv = hw->priv;
- u8 *mac_addr = NULL;
- u8 key_dec_mode = 0;
- int ret = 0;
- u32 u;
-
- if (sta)
- mac_addr = &sta->addr[0];
-
- switch (key->cipher) {
- case 0:
- for (u = 0 ; u < MAX_KEY_TABLE; u++)
- MACvDisableKeyEntry(priv, u);
- return ret;
-
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- for (u = 0; u < MAX_KEY_TABLE; u++)
- MACvDisableKeyEntry(priv, u);
-
- vnt_set_keymode(hw, mac_addr,
- key, VNT_KEY_DEFAULTKEY, KEY_CTL_WEP, true);
-
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-
- return ret;
- case WLAN_CIPHER_SUITE_TKIP:
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-
- key_dec_mode = KEY_CTL_TKIP;
-
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- key_dec_mode = KEY_CTL_CCMP;
-
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- }
-
- if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
- vnt_set_keymode(hw, mac_addr,
- key, VNT_KEY_PAIRWISE, key_dec_mode, true);
- } else {
- vnt_set_keymode(hw, mac_addr,
- key, VNT_KEY_DEFAULTKEY, key_dec_mode, true);
-
- vnt_set_keymode(hw, (u8 *)conf->bssid,
- key, VNT_KEY_GROUP_ADDRESS, key_dec_mode, true);
- }
-
- return 0;
-}
diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h
deleted file mode 100644
index d88da9dfb5c3..000000000000
--- a/drivers/staging/vt6655/key.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions for 802.11i Key management
- *
- * Author: Jerry Chen
- *
- * Date: May 29, 2003
- *
- */
-
-#ifndef __KEY_H__
-#define __KEY_H__
-
-#include <net/mac80211.h>
-
-/*--------------------- Export Definitions -------------------------*/
-#define MAX_GROUP_KEY 4
-#define MAX_KEY_TABLE 11
-#define MAX_KEY_LEN 32
-#define AES_KEY_LEN 16
-
-#define AUTHENTICATOR_KEY 0x10000000
-#define USE_KEYRSC 0x20000000
-#define PAIRWISE_KEY 0x40000000
-#define TRANSMIT_KEY 0x80000000
-
-#define GROUP_KEY 0x00000000
-
-#define KEY_CTL_WEP 0x00
-#define KEY_CTL_NONE 0x01
-#define KEY_CTL_TKIP 0x02
-#define KEY_CTL_CCMP 0x03
-#define KEY_CTL_INVALID 0xFF
-
-#define VNT_KEY_DEFAULTKEY 0x1
-#define VNT_KEY_GROUP_ADDRESS 0x2
-#define VNT_KEY_ALLGROUP 0x4
-#define VNT_KEY_GROUP 0x40
-#define VNT_KEY_PAIRWISE 0x00
-#define VNT_KEY_ONFLY 0x8000
-#define VNT_KEY_ONFLY_ALL 0x4000
-
-struct vnt_private;
-
-int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
- struct ieee80211_vif *vif, struct ieee80211_key_conf *key);
-
-#endif /* __KEY_H__ */
diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c
deleted file mode 100644
index b4ebc7d31961..000000000000
--- a/drivers/staging/vt6655/mac.c
+++ /dev/null
@@ -1,851 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: MAC routines
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- * Functions:
- * vt6655_mac_is_reg_bits_off - Test if All test Bits Off
- * vt6655_mac_set_short_retry_limit - Set 802.11 Short Retry limit
- * MACvSetLongRetryLimit - Set 802.11 Long Retry limit
- * vt6655_mac_set_loopback_mode - Set MAC Loopback Mode
- * vt6655_mac_save_context - Save Context of MAC Registers
- * vt6655_mac_restore_context - Restore Context of MAC Registers
- * MACbSoftwareReset - Software Reset MAC
- * vt6655_mac_safe_rx_off - Turn Off MAC Rx
- * vt6655_mac_safe_tx_off - Turn Off MAC Tx
- * vt6655_mac_safe_stop - Stop MAC function
- * MACbShutdown - Shut down MAC
- * MACvInitialize - Initialize MAC
- * MACvSetCurrRxDescAddr - Set Rx Descriptors Address
- * MACvSetCurrTx0DescAddr - Set Tx0 Descriptors Address
- * MACvSetCurrTx1DescAddr - Set Tx1 Descriptors Address
- * MACvTimer0MicroSDelay - Micro Second Delay Loop by MAC
- *
- * Revision History:
- * 08-22-2003 Kyle Hsu : Porting MAC functions from sim53
- * 09-03-2003 Bryan YC Fan : Add MACvClearBusSusInd()&
- * MACvEnableBusSusEn()
- * 09-18-2003 Jerry Chen : Add MACvSetKeyEntry & MACvDisableKeyEntry
- *
- */
-
-#include "mac.h"
-
-void vt6655_mac_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask)
-{
- unsigned char reg_value;
-
- reg_value = ioread8(iobase + reg_offset);
- iowrite8(reg_value | bit_mask, iobase + reg_offset);
-}
-
-void vt6655_mac_word_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask)
-{
- unsigned short reg_value;
-
- reg_value = ioread16(iobase + reg_offset);
- iowrite16(reg_value | (bit_mask), iobase + reg_offset);
-}
-
-void vt6655_mac_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask)
-{
- unsigned char reg_value;
-
- reg_value = ioread8(iobase + reg_offset);
- iowrite8(reg_value & ~(bit_mask), iobase + reg_offset);
-}
-
-void vt6655_mac_word_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask)
-{
- unsigned short reg_value;
-
- reg_value = ioread16(iobase + reg_offset);
- iowrite16(reg_value & ~(bit_mask), iobase + reg_offset);
-}
-
-static void vt6655_mac_clear_stck_ds(void __iomem *iobase)
-{
- u8 reg_value;
-
- reg_value = ioread8(iobase + MAC_REG_STICKHW);
- reg_value = reg_value & 0xFC;
- iowrite8(reg_value, iobase + MAC_REG_STICKHW);
-}
-
-/*
- * Description:
- * Test if all test bits off
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * reg_offset - Offset of MAC Register
- * mask - Test bits
- * Out:
- * none
- *
- * Return Value: true if all test bits Off; otherwise false
- *
- */
-static bool vt6655_mac_is_reg_bits_off(struct vnt_private *priv,
- unsigned char reg_offset,
- unsigned char mask)
-{
- void __iomem *io_base = priv->port_offset;
-
- return !(ioread8(io_base + reg_offset) & mask);
-}
-
-/*
- * Description:
- * Set 802.11 Short Retry Limit
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * retry_limit - Retry Limit
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void vt6655_mac_set_short_retry_limit(struct vnt_private *priv, unsigned char retry_limit)
-{
- void __iomem *io_base = priv->port_offset;
- /* set SRT */
- iowrite8(retry_limit, io_base + MAC_REG_SRT);
-}
-
-/*
- * Description:
- * Set 802.11 Long Retry Limit
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * byRetryLimit- Retry Limit
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void MACvSetLongRetryLimit(struct vnt_private *priv,
- unsigned char byRetryLimit)
-{
- void __iomem *io_base = priv->port_offset;
- /* set LRT */
- iowrite8(byRetryLimit, io_base + MAC_REG_LRT);
-}
-
-/*
- * Description:
- * Set MAC Loopback mode
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * loopback_mode - Loopback Mode
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-static void vt6655_mac_set_loopback_mode(struct vnt_private *priv, u8 loopback_mode)
-{
- void __iomem *io_base = priv->port_offset;
-
- loopback_mode <<= 6;
- /* set TCR */
- iowrite8((ioread8(io_base + MAC_REG_TEST) & 0x3f) | loopback_mode, io_base + MAC_REG_TEST);
-}
-
-/*
- * Description:
- * Save MAC registers to context buffer
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * cxt_buf - Context buffer
- *
- * Return Value: none
- *
- */
-static void vt6655_mac_save_context(struct vnt_private *priv, u8 *cxt_buf)
-{
- void __iomem *io_base = priv->port_offset;
-
- /* read page0 register */
- memcpy_fromio(cxt_buf, io_base, MAC_MAX_CONTEXT_SIZE_PAGE0);
-
- VT6655_MAC_SELECT_PAGE1(io_base);
-
- /* read page1 register */
- memcpy_fromio(cxt_buf + MAC_MAX_CONTEXT_SIZE_PAGE0, io_base,
- MAC_MAX_CONTEXT_SIZE_PAGE1);
-
- VT6655_MAC_SELECT_PAGE0(io_base);
-}
-
-/*
- * Description:
- * Restore MAC registers from context buffer
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * cxt_buf - Context buffer
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-static void vt6655_mac_restore_context(struct vnt_private *priv, u8 *cxt_buf)
-{
- void __iomem *io_base = priv->port_offset;
-
- VT6655_MAC_SELECT_PAGE1(io_base);
- /* restore page1 */
- memcpy_toio(io_base, cxt_buf + MAC_MAX_CONTEXT_SIZE_PAGE0,
- MAC_MAX_CONTEXT_SIZE_PAGE1);
-
- VT6655_MAC_SELECT_PAGE0(io_base);
-
- /* restore RCR,TCR,IMR... */
- memcpy_toio(io_base + MAC_REG_RCR, cxt_buf + MAC_REG_RCR,
- MAC_REG_ISR - MAC_REG_RCR);
-
- /* restore MAC Config. */
- memcpy_toio(io_base + MAC_REG_LRT, cxt_buf + MAC_REG_LRT,
- MAC_REG_PAGE1SEL - MAC_REG_LRT);
-
- iowrite8(*(cxt_buf + MAC_REG_CFG), io_base + MAC_REG_CFG);
-
- /* restore PS Config. */
- memcpy_toio(io_base + MAC_REG_PSCFG, cxt_buf + MAC_REG_PSCFG,
- MAC_REG_BBREGCTL - MAC_REG_PSCFG);
-
- /* restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR */
- iowrite32(*(u32 *)(cxt_buf + MAC_REG_TXDMAPTR0),
- io_base + MAC_REG_TXDMAPTR0);
- iowrite32(*(u32 *)(cxt_buf + MAC_REG_AC0DMAPTR),
- io_base + MAC_REG_AC0DMAPTR);
- iowrite32(*(u32 *)(cxt_buf + MAC_REG_BCNDMAPTR),
- io_base + MAC_REG_BCNDMAPTR);
- iowrite32(*(u32 *)(cxt_buf + MAC_REG_RXDMAPTR0),
- io_base + MAC_REG_RXDMAPTR0);
- iowrite32(*(u32 *)(cxt_buf + MAC_REG_RXDMAPTR1),
- io_base + MAC_REG_RXDMAPTR1);
-}
-
-/*
- * Description:
- * Software Reset MAC
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: true if Reset Success; otherwise false
- *
- */
-bool MACbSoftwareReset(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
-
- /* turn on HOSTCR_SOFTRST, just write 0x01 to reset */
- iowrite8(0x01, io_base + MAC_REG_HOSTCR);
-
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_SOFTRST))
- break;
- }
- if (ww == W_MAX_TIMEOUT)
- return false;
- return true;
-}
-
-/*
- * Description:
- * save some important register's value, then do reset, then restore
- * register's value
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-static void vt6655_mac_save_soft_reset(struct vnt_private *priv)
-{
- u8 tmp_reg_data[MAC_MAX_CONTEXT_SIZE_PAGE0 + MAC_MAX_CONTEXT_SIZE_PAGE1];
-
- /* PATCH....
- * save some important register's value, then do
- * reset, then restore register's value
- */
- /* save MAC context */
- vt6655_mac_save_context(priv, tmp_reg_data);
- /* do reset */
- MACbSoftwareReset(priv);
- /* restore MAC context, except CR0 */
- vt6655_mac_restore_context(priv, tmp_reg_data);
-}
-
-/*
- * Description:
- * Turn Off MAC Rx
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-static bool vt6655_mac_safe_rx_off(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
-
- /* turn off wow temp for turn off Rx safely */
-
- /* Clear RX DMA0,1 */
- iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_RXDMACTL0);
- iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_RXDMACTL1);
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread32(io_base + MAC_REG_RXDMACTL0) & DMACTL_RUN))
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x10)\n");
- return false;
- }
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread32(io_base + MAC_REG_RXDMACTL1) & DMACTL_RUN))
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x11)\n");
- return false;
- }
-
- /* try to safe shutdown RX */
- vt6655_mac_reg_bits_off(io_base, MAC_REG_HOSTCR, HOSTCR_RXON);
- /* W_MAX_TIMEOUT is the timeout period */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_RXONST))
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x12)\n");
- return false;
- }
- return true;
-}
-
-/*
- * Description:
- * Turn Off MAC Tx
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-static bool vt6655_mac_safe_tx_off(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
-
- /* Clear TX DMA */
- /* Tx0 */
- iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_TXDMACTL0);
- /* AC0 */
- iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_AC0DMACTL);
-
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread32(io_base + MAC_REG_TXDMACTL0) & DMACTL_RUN))
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x20)\n");
- return false;
- }
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread32(io_base + MAC_REG_AC0DMACTL) & DMACTL_RUN))
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x21)\n");
- return false;
- }
-
- /* try to safe shutdown TX */
- vt6655_mac_reg_bits_off(io_base, MAC_REG_HOSTCR, HOSTCR_TXON);
-
- /* W_MAX_TIMEOUT is the timeout period */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_TXONST))
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x24)\n");
- return false;
- }
- return true;
-}
-
-/*
- * Description:
- * Stop MAC function
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-static bool vt6655_mac_safe_stop(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
-
- vt6655_mac_reg_bits_off(io_base, MAC_REG_TCR, TCR_AUTOBCNTX);
-
- if (!vt6655_mac_safe_rx_off(priv)) {
- pr_debug(" vt6655_mac_safe_rx_off == false)\n");
- vt6655_mac_save_soft_reset(priv);
- return false;
- }
- if (!vt6655_mac_safe_tx_off(priv)) {
- pr_debug(" vt6655_mac_safe_tx_off == false)\n");
- vt6655_mac_save_soft_reset(priv);
- return false;
- }
-
- vt6655_mac_reg_bits_off(io_base, MAC_REG_HOSTCR, HOSTCR_MACEN);
-
- return true;
-}
-
-/*
- * Description:
- * Shut Down MAC
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-bool MACbShutdown(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
- /* disable MAC IMR */
- iowrite32(0, io_base + MAC_REG_IMR);
- vt6655_mac_set_loopback_mode(priv, MAC_LB_INTERNAL);
- /* stop the adapter */
- if (!vt6655_mac_safe_stop(priv)) {
- vt6655_mac_set_loopback_mode(priv, MAC_LB_NONE);
- return false;
- }
- vt6655_mac_set_loopback_mode(priv, MAC_LB_NONE);
- return true;
-}
-
-/*
- * Description:
- * Initialize MAC
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void MACvInitialize(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
- /* clear sticky bits */
- vt6655_mac_clear_stck_ds(io_base);
- /* disable force PME-enable */
- iowrite8(PME_OVR, io_base + MAC_REG_PMC1);
- /* only 3253 A */
-
- /* do reset */
- MACbSoftwareReset(priv);
-
- /* reset TSF counter */
- iowrite8(TFTCTL_TSFCNTRST, io_base + MAC_REG_TFTCTL);
- /* enable TSF counter */
- iowrite8(TFTCTL_TSFCNTREN, io_base + MAC_REG_TFTCTL);
-}
-
-/*
- * Description:
- * Set the chip with current rx descriptor address
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * curr_desc_addr - Descriptor Address
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void vt6655_mac_set_curr_rx_0_desc_addr(struct vnt_private *priv, u32 curr_desc_addr)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
- unsigned char org_dma_ctl;
-
- org_dma_ctl = ioread8(io_base + MAC_REG_RXDMACTL0);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL0 + 2);
-
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_RXDMACTL0) & DMACTL_RUN))
- break;
- }
-
- iowrite32(curr_desc_addr, io_base + MAC_REG_RXDMAPTR0);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL0);
-}
-
-/*
- * Description:
- * Set the chip with current rx descriptor address
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * curr_desc_addr - Descriptor Address
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void vt6655_mac_set_curr_rx_1_desc_addr(struct vnt_private *priv, u32 curr_desc_addr)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
- unsigned char org_dma_ctl;
-
- org_dma_ctl = ioread8(io_base + MAC_REG_RXDMACTL1);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL1 + 2);
-
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_RXDMACTL1) & DMACTL_RUN))
- break;
- }
-
- iowrite32(curr_desc_addr, io_base + MAC_REG_RXDMAPTR1);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL1);
-}
-
-/*
- * Description:
- * Set the chip with current tx0 descriptor address
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * curr_desc_addr - Descriptor Address
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-static void vt6655_mac_set_curr_tx_0_desc_addr_ex(struct vnt_private *priv, u32 curr_desc_addr)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
- unsigned char org_dma_ctl;
-
- org_dma_ctl = ioread8(io_base + MAC_REG_TXDMACTL0);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_TXDMACTL0 + 2);
-
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_TXDMACTL0) & DMACTL_RUN))
- break;
- }
-
- iowrite32(curr_desc_addr, io_base + MAC_REG_TXDMAPTR0);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_TXDMACTL0);
-}
-
-/*
- * Description:
- * Set the chip with current AC0 descriptor address
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * curr_desc_addr - Descriptor Address
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-/* TxDMA1 = AC0DMA */
-static void vt6655_mac_set_curr_ac_0_desc_addr_ex(struct vnt_private *priv, u32 curr_desc_addr)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
- unsigned char org_dma_ctl;
-
- org_dma_ctl = ioread8(io_base + MAC_REG_AC0DMACTL);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_AC0DMACTL + 2);
-
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_AC0DMACTL) & DMACTL_RUN))
- break;
- }
- if (ww == W_MAX_TIMEOUT)
- pr_debug(" DBG_PORT80(0x26)\n");
- iowrite32(curr_desc_addr, io_base + MAC_REG_AC0DMAPTR);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_AC0DMACTL);
-}
-
-void vt6655_mac_set_curr_tx_desc_addr(int tx_type, struct vnt_private *priv, u32 curr_desc_addr)
-{
- if (tx_type == TYPE_AC0DMA)
- vt6655_mac_set_curr_ac_0_desc_addr_ex(priv, curr_desc_addr);
- else if (tx_type == TYPE_TXDMA0)
- vt6655_mac_set_curr_tx_0_desc_addr_ex(priv, curr_desc_addr);
-}
-
-/*
- * Description:
- * Micro Second Delay via MAC
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * uDelay - Delay time (timer resolution is 4 us)
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned char byValue;
- unsigned int uu, ii;
-
- iowrite8(0, io_base + MAC_REG_TMCTL0);
- iowrite32(uDelay, io_base + MAC_REG_TMDATA0);
- iowrite8((TMCTL_TMD | TMCTL_TE), io_base + MAC_REG_TMCTL0);
- for (ii = 0; ii < 66; ii++) { /* assume max PCI clock is 66Mhz */
- for (uu = 0; uu < uDelay; uu++) {
- byValue = ioread8(io_base + MAC_REG_TMCTL0);
- if ((byValue == 0) ||
- (byValue & TMCTL_TSUSP)) {
- iowrite8(0, io_base + MAC_REG_TMCTL0);
- return;
- }
- }
- }
- iowrite8(0, io_base + MAC_REG_TMCTL0);
-}
-
-/*
- * Description:
- * Micro Second One shot timer via MAC
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * uDelay - Delay time
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void MACvOneShotTimer1MicroSec(struct vnt_private *priv,
- unsigned int uDelayTime)
-{
- void __iomem *io_base = priv->port_offset;
-
- iowrite8(0, io_base + MAC_REG_TMCTL1);
- iowrite32(uDelayTime, io_base + MAC_REG_TMDATA1);
- iowrite8((TMCTL_TMD | TMCTL_TE), io_base + MAC_REG_TMCTL1);
-}
-
-void MACvSetMISCFifo(struct vnt_private *priv, unsigned short offset,
- u32 data)
-{
- void __iomem *io_base = priv->port_offset;
-
- if (offset > 273)
- return;
- iowrite16(offset, io_base + MAC_REG_MISCFFNDEX);
- iowrite32(data, io_base + MAC_REG_MISCFFDATA);
- iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
-}
-
-bool MACbPSWakeup(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned int ww;
- /* Read PSCTL */
- if (vt6655_mac_is_reg_bits_off(priv, MAC_REG_PSCTL, PSCTL_PS))
- return true;
-
- /* Disable PS */
- vt6655_mac_reg_bits_off(io_base, MAC_REG_PSCTL, PSCTL_PSEN);
-
- /* Check if SyncFlushOK */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (ioread8(io_base + MAC_REG_PSCTL) & PSCTL_WAKEDONE)
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x33)\n");
- return false;
- }
- return true;
-}
-
-/*
- * Description:
- * Set the Key by MISCFIFO
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- *
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-
-void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl,
- unsigned int uEntryIdx, unsigned int uKeyIdx,
- unsigned char *pbyAddr, u32 *pdwKey,
- unsigned char local_id)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short offset;
- u32 data;
- int ii;
-
- if (local_id <= 1)
- return;
-
- offset = MISCFIFO_KEYETRY0;
- offset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
-
- data = 0;
- data |= wKeyCtl;
- data <<= 16;
- data |= MAKEWORD(*(pbyAddr + 4), *(pbyAddr + 5));
- pr_debug("1. offset: %d, Data: %X, KeyCtl:%X\n",
- offset, data, wKeyCtl);
-
- iowrite16(offset, io_base + MAC_REG_MISCFFNDEX);
- iowrite32(data, io_base + MAC_REG_MISCFFDATA);
- iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
- offset++;
-
- data = 0;
- data |= *(pbyAddr + 3);
- data <<= 8;
- data |= *(pbyAddr + 2);
- data <<= 8;
- data |= *(pbyAddr + 1);
- data <<= 8;
- data |= *pbyAddr;
- pr_debug("2. offset: %d, Data: %X\n", offset, data);
-
- iowrite16(offset, io_base + MAC_REG_MISCFFNDEX);
- iowrite32(data, io_base + MAC_REG_MISCFFDATA);
- iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
- offset++;
-
- offset += (uKeyIdx * 4);
- for (ii = 0; ii < 4; ii++) {
- /* always push 128 bits */
- pr_debug("3.(%d) offset: %d, Data: %X\n",
- ii, offset + ii, *pdwKey);
- iowrite16(offset + ii, io_base + MAC_REG_MISCFFNDEX);
- iowrite32(*pdwKey++, io_base + MAC_REG_MISCFFDATA);
- iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
- }
-}
-
-/*
- * Description:
- * Disable the Key Entry by MISCFIFO
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- *
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short offset;
-
- offset = MISCFIFO_KEYETRY0;
- offset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
-
- iowrite16(offset, io_base + MAC_REG_MISCFFNDEX);
- iowrite32(0, io_base + MAC_REG_MISCFFDATA);
- iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
-}
diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h
deleted file mode 100644
index a33af2852227..000000000000
--- a/drivers/staging/vt6655/mac.h
+++ /dev/null
@@ -1,580 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: MAC routines
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- * Revision History:
- * 07-01-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
- * 08-25-2003 Kyle Hsu: Porting MAC functions from sim53.
- * 09-03-2003 Bryan YC Fan: Add vt6655_mac_dis_protect_md & vt6655_mac_en_protect_md
- */
-
-#ifndef __MAC_H__
-#define __MAC_H__
-
-#include "device.h"
-
-/*--------------------- Export Definitions -------------------------*/
-/* Registers in the MAC */
-#define MAC_MAX_CONTEXT_SIZE_PAGE0 256
-#define MAC_MAX_CONTEXT_SIZE_PAGE1 128
-
-/* Registers not related to 802.11b */
-#define MAC_REG_BCFG0 0x00
-#define MAC_REG_BCFG1 0x01
-#define MAC_REG_FCR0 0x02
-#define MAC_REG_FCR1 0x03
-#define MAC_REG_BISTCMD 0x04
-#define MAC_REG_BISTSR0 0x05
-#define MAC_REG_BISTSR1 0x06
-#define MAC_REG_BISTSR2 0x07
-#define MAC_REG_I2MCSR 0x08
-#define MAC_REG_I2MTGID 0x09
-#define MAC_REG_I2MTGAD 0x0A
-#define MAC_REG_I2MCFG 0x0B
-#define MAC_REG_I2MDIPT 0x0C
-#define MAC_REG_I2MDOPT 0x0E
-#define MAC_REG_PMC0 0x10
-#define MAC_REG_PMC1 0x11
-#define MAC_REG_STICKHW 0x12
-#define MAC_REG_LOCALID 0x14
-#define MAC_REG_TESTCFG 0x15
-#define MAC_REG_JUMPER0 0x16
-#define MAC_REG_JUMPER1 0x17
-#define MAC_REG_TMCTL0 0x18
-#define MAC_REG_TMCTL1 0x19
-#define MAC_REG_TMDATA0 0x1C
-
-/* MAC Parameter related */
-#define MAC_REG_LRT 0x20
-#define MAC_REG_SRT 0x21
-#define MAC_REG_SIFS 0x22
-#define MAC_REG_DIFS 0x23
-#define MAC_REG_EIFS 0x24
-#define MAC_REG_SLOT 0x25
-#define MAC_REG_BI 0x26
-#define MAC_REG_CWMAXMIN0 0x28
-#define MAC_REG_LINKOFFTOTM 0x2A
-#define MAC_REG_SWTMOT 0x2B
-#define MAC_REG_MIBCNTR 0x2C
-#define MAC_REG_RTSOKCNT 0x2C
-#define MAC_REG_RTSFAILCNT 0x2D
-#define MAC_REG_ACKFAILCNT 0x2E
-#define MAC_REG_FCSERRCNT 0x2F
-
-/* TSF Related */
-#define MAC_REG_TSFCNTR 0x30
-#define MAC_REG_NEXTTBTT 0x38
-#define MAC_REG_TSFOFST 0x40
-#define MAC_REG_TFTCTL 0x48
-
-/* WMAC Control/Status Related */
-#define MAC_REG_ENCFG 0x4C
-#define MAC_REG_PAGE1SEL 0x4F
-#define MAC_REG_CFG 0x50
-#define MAC_REG_TEST 0x52
-#define MAC_REG_HOSTCR 0x54
-#define MAC_REG_MACCR 0x55
-#define MAC_REG_RCR 0x56
-#define MAC_REG_TCR 0x57
-#define MAC_REG_IMR 0x58
-#define MAC_REG_ISR 0x5C
-
-/* Power Saving Related */
-#define MAC_REG_PSCFG 0x60
-#define MAC_REG_PSCTL 0x61
-#define MAC_REG_PSPWRSIG 0x62
-#define MAC_REG_BBCR13 0x63
-#define MAC_REG_AIDATIM 0x64
-#define MAC_REG_PWBT 0x66
-#define MAC_REG_WAKEOKTMR 0x68
-#define MAC_REG_CALTMR 0x69
-#define MAC_REG_SYNSPACCNT 0x6A
-#define MAC_REG_WAKSYNOPT 0x6B
-
-/* Baseband/IF Control Group */
-#define MAC_REG_BBREGCTL 0x6C
-#define MAC_REG_CHANNEL 0x6D
-#define MAC_REG_BBREGADR 0x6E
-#define MAC_REG_BBREGDATA 0x6F
-#define MAC_REG_IFREGCTL 0x70
-#define MAC_REG_IFDATA 0x71
-#define MAC_REG_ITRTMSET 0x74
-#define MAC_REG_PAPEDELAY 0x77
-#define MAC_REG_SOFTPWRCTL 0x78
-#define MAC_REG_GPIOCTL0 0x7A
-#define MAC_REG_GPIOCTL1 0x7B
-
-/* MAC DMA Related Group */
-#define MAC_REG_TXDMACTL0 0x7C
-#define MAC_REG_TXDMAPTR0 0x80
-#define MAC_REG_AC0DMACTL 0x84
-#define MAC_REG_AC0DMAPTR 0x88
-#define MAC_REG_BCNDMACTL 0x8C
-#define MAC_REG_BCNDMAPTR 0x90
-#define MAC_REG_RXDMACTL0 0x94
-#define MAC_REG_RXDMAPTR0 0x98
-#define MAC_REG_RXDMACTL1 0x9C
-#define MAC_REG_RXDMAPTR1 0xA0
-#define MAC_REG_SYNCDMACTL 0xA4
-#define MAC_REG_SYNCDMAPTR 0xA8
-#define MAC_REG_ATIMDMACTL 0xAC
-#define MAC_REG_ATIMDMAPTR 0xB0
-
-/* MiscFF PIO related */
-#define MAC_REG_MISCFFNDEX 0xB4
-#define MAC_REG_MISCFFCTL 0xB6
-#define MAC_REG_MISCFFDATA 0xB8
-
-/* Extend SW Timer */
-#define MAC_REG_TMDATA1 0xBC
-
-/* WOW Related Group */
-#define MAC_REG_WAKEUPEN0 0xC0
-#define MAC_REG_WAKEUPEN1 0xC1
-#define MAC_REG_WAKEUPSR0 0xC2
-#define MAC_REG_WAKEUPSR1 0xC3
-#define MAC_REG_WAKE128_0 0xC4
-#define MAC_REG_WAKE128_1 0xD4
-#define MAC_REG_WAKE128_2 0xE4
-#define MAC_REG_WAKE128_3 0xF4
-
-/************** Page 1 ******************/
-#define MAC_REG_CRC_128_0 0x04
-#define MAC_REG_CRC_128_1 0x06
-#define MAC_REG_CRC_128_2 0x08
-#define MAC_REG_CRC_128_3 0x0A
-
-/* MAC Configuration Group */
-#define MAC_REG_PAR0 0x0C
-#define MAC_REG_PAR4 0x10
-#define MAC_REG_BSSID0 0x14
-#define MAC_REG_BSSID4 0x18
-#define MAC_REG_MAR0 0x1C
-#define MAC_REG_MAR4 0x20
-
-/* MAC RSPPKT INFO Group */
-#define MAC_REG_RSPINF_B_1 0x24
-#define MAC_REG_RSPINF_B_2 0x28
-#define MAC_REG_RSPINF_B_5 0x2C
-#define MAC_REG_RSPINF_B_11 0x30
-#define MAC_REG_RSPINF_A_6 0x34
-#define MAC_REG_RSPINF_A_9 0x36
-#define MAC_REG_RSPINF_A_12 0x38
-#define MAC_REG_RSPINF_A_18 0x3A
-#define MAC_REG_RSPINF_A_24 0x3C
-#define MAC_REG_RSPINF_A_36 0x3E
-#define MAC_REG_RSPINF_A_48 0x40
-#define MAC_REG_RSPINF_A_54 0x42
-#define MAC_REG_RSPINF_A_72 0x44
-
-/* 802.11h relative */
-#define MAC_REG_QUIETINIT 0x60
-#define MAC_REG_QUIETGAP 0x62
-#define MAC_REG_QUIETDUR 0x64
-#define MAC_REG_MSRCTL 0x66
-#define MAC_REG_MSRBBSTS 0x67
-#define MAC_REG_MSRSTART 0x68
-#define MAC_REG_MSRDURATION 0x70
-#define MAC_REG_CCAFRACTION 0x72
-#define MAC_REG_PWRCCK 0x73
-#define MAC_REG_PWROFDM 0x7C
-
-/* Bits in the BCFG0 register */
-#define BCFG0_PERROFF 0x40
-#define BCFG0_MRDMDIS 0x20
-#define BCFG0_MRDLDIS 0x10
-#define BCFG0_MWMEN 0x08
-#define BCFG0_VSERREN 0x02
-#define BCFG0_LATMEN 0x01
-
-/* Bits in the BCFG1 register */
-#define BCFG1_CFUNOPT 0x80
-#define BCFG1_CREQOPT 0x40
-#define BCFG1_DMA8 0x10
-#define BCFG1_ARBITOPT 0x08
-#define BCFG1_PCIMEN 0x04
-#define BCFG1_MIOEN 0x02
-#define BCFG1_CISDLYEN 0x01
-
-/* Bits in RAMBIST registers */
-#define BISTCMD_TSTPAT5 0x00
-#define BISTCMD_TSTPATA 0x80
-#define BISTCMD_TSTERR 0x20
-#define BISTCMD_TSTPATF 0x18
-#define BISTCMD_TSTPAT0 0x10
-#define BISTCMD_TSTMODE 0x04
-#define BISTCMD_TSTITTX 0x03
-#define BISTCMD_TSTATRX 0x02
-#define BISTCMD_TSTATTX 0x01
-#define BISTCMD_TSTRX 0x00
-#define BISTSR0_BISTGO 0x01
-#define BISTSR1_TSTSR 0x01
-#define BISTSR2_CMDPRTEN 0x02
-#define BISTSR2_RAMTSTEN 0x01
-
-/* Bits in the I2MCFG EEPROM register */
-#define I2MCFG_BOUNDCTL 0x80
-#define I2MCFG_WAITCTL 0x20
-#define I2MCFG_SCLOECTL 0x10
-#define I2MCFG_WBUSYCTL 0x08
-#define I2MCFG_NORETRY 0x04
-#define I2MCFG_I2MLDSEQ 0x02
-#define I2MCFG_I2CMFAST 0x01
-
-/* Bits in the I2MCSR EEPROM register */
-#define I2MCSR_EEMW 0x80
-#define I2MCSR_EEMR 0x40
-#define I2MCSR_AUTOLD 0x08
-#define I2MCSR_NACK 0x02
-#define I2MCSR_DONE 0x01
-
-/* Bits in the PMC1 register */
-#define SPS_RST 0x80
-#define PCISTIKY 0x40
-#define PME_OVR 0x02
-
-/* Bits in the STICKYHW register */
-#define STICKHW_DS1_SHADOW 0x02
-#define STICKHW_DS0_SHADOW 0x01
-
-/* Bits in the TMCTL register */
-#define TMCTL_TSUSP 0x04
-#define TMCTL_TMD 0x02
-#define TMCTL_TE 0x01
-
-/* Bits in the TFTCTL register */
-#define TFTCTL_HWUTSF 0x80
-#define TFTCTL_TBTTSYNC 0x40
-#define TFTCTL_HWUTSFEN 0x20
-#define TFTCTL_TSFCNTRRD 0x10
-#define TFTCTL_TBTTSYNCEN 0x08
-#define TFTCTL_TSFSYNCEN 0x04
-#define TFTCTL_TSFCNTRST 0x02
-#define TFTCTL_TSFCNTREN 0x01
-
-/* Bits in the EnhanceCFG register */
-#define ENCFG_BARKERPREAM 0x00020000
-#define ENCFG_NXTBTTCFPSTR 0x00010000
-#define ENCFG_BCNSUSCLR 0x00000200
-#define ENCFG_BCNSUSIND 0x00000100
-#define ENCFG_CFP_PROTECTEN 0x00000040
-#define ENCFG_PROTECTMD 0x00000020
-#define ENCFG_HWPARCFP 0x00000010
-#define ENCFG_CFNULRSP 0x00000004
-#define ENCFG_BBTYPE_MASK 0x00000003
-#define ENCFG_BBTYPE_G 0x00000002
-#define ENCFG_BBTYPE_B 0x00000001
-#define ENCFG_BBTYPE_A 0x00000000
-
-/* Bits in the Page1Sel register */
-#define PAGE1_SEL 0x01
-
-/* Bits in the CFG register */
-#define CFG_TKIPOPT 0x80
-#define CFG_RXDMAOPT 0x40
-#define CFG_TMOT_SW 0x20
-#define CFG_TMOT_HWLONG 0x10
-#define CFG_TMOT_HW 0x00
-#define CFG_CFPENDOPT 0x08
-#define CFG_BCNSUSEN 0x04
-#define CFG_NOTXTIMEOUT 0x02
-#define CFG_NOBUFOPT 0x01
-
-/* Bits in the TEST register */
-#define TEST_LBEXT 0x80
-#define TEST_LBINT 0x40
-#define TEST_LBNONE 0x00
-#define TEST_SOFTINT 0x20
-#define TEST_CONTTX 0x10
-#define TEST_TXPE 0x08
-#define TEST_NAVDIS 0x04
-#define TEST_NOCTS 0x02
-#define TEST_NOACK 0x01
-
-/* Bits in the HOSTCR register */
-#define HOSTCR_TXONST 0x80
-#define HOSTCR_RXONST 0x40
-#define HOSTCR_ADHOC 0x20 /* Network Type 1 = Ad-hoc */
-#define HOSTCR_AP 0x10 /* Port Type 1 = AP */
-#define HOSTCR_TXON 0x08 /* 0000 1000 */
-#define HOSTCR_RXON 0x04 /* 0000 0100 */
-#define HOSTCR_MACEN 0x02 /* 0000 0010 */
-#define HOSTCR_SOFTRST 0x01 /* 0000 0001 */
-
-/* Bits in the MACCR register */
-#define MACCR_SYNCFLUSHOK 0x04
-#define MACCR_SYNCFLUSH 0x02
-#define MACCR_CLRNAV 0x01
-
-/* Bits in the MAC_REG_GPIOCTL0 register */
-#define LED_ACTSET 0x01
-#define LED_RFOFF 0x02
-#define LED_NOCONNECT 0x04
-
-/* Bits in the RCR register */
-#define RCR_SSID 0x80
-#define RCR_RXALLTYPE 0x40
-#define RCR_UNICAST 0x20
-#define RCR_BROADCAST 0x10
-#define RCR_MULTICAST 0x08
-#define RCR_WPAERR 0x04
-#define RCR_ERRCRC 0x02
-#define RCR_BSSID 0x01
-
-/* Bits in the TCR register */
-#define TCR_SYNCDCFOPT 0x02
-#define TCR_AUTOBCNTX 0x01 /* Beacon automatically transmit enable */
-
-/* Bits in the IMR register */
-#define IMR_MEASURESTART 0x80000000
-#define IMR_QUIETSTART 0x20000000
-#define IMR_RADARDETECT 0x10000000
-#define IMR_MEASUREEND 0x08000000
-#define IMR_SOFTTIMER1 0x00200000
-#define IMR_RXDMA1 0x00001000 /* 0000 0000 0001 0000 0000 0000 */
-#define IMR_RXNOBUF 0x00000800
-#define IMR_MIBNEARFULL 0x00000400
-#define IMR_SOFTINT 0x00000200
-#define IMR_FETALERR 0x00000100
-#define IMR_WATCHDOG 0x00000080
-#define IMR_SOFTTIMER 0x00000040
-#define IMR_GPIO 0x00000020
-#define IMR_TBTT 0x00000010
-#define IMR_RXDMA0 0x00000008
-#define IMR_BNTX 0x00000004
-#define IMR_AC0DMA 0x00000002
-#define IMR_TXDMA0 0x00000001
-
-/* Bits in the ISR register */
-#define ISR_MEASURESTART 0x80000000
-#define ISR_QUIETSTART 0x20000000
-#define ISR_RADARDETECT 0x10000000
-#define ISR_MEASUREEND 0x08000000
-#define ISR_SOFTTIMER1 0x00200000
-#define ISR_RXDMA1 0x00001000 /* 0000 0000 0001 0000 0000 0000 */
-#define ISR_RXNOBUF 0x00000800 /* 0000 0000 0000 1000 0000 0000 */
-#define ISR_MIBNEARFULL 0x00000400 /* 0000 0000 0000 0100 0000 0000 */
-#define ISR_SOFTINT 0x00000200
-#define ISR_FETALERR 0x00000100
-#define ISR_WATCHDOG 0x00000080
-#define ISR_SOFTTIMER 0x00000040
-#define ISR_GPIO 0x00000020
-#define ISR_TBTT 0x00000010
-#define ISR_RXDMA0 0x00000008
-#define ISR_BNTX 0x00000004
-#define ISR_AC0DMA 0x00000002
-#define ISR_TXDMA0 0x00000001
-
-/* Bits in the PSCFG register */
-#define PSCFG_PHILIPMD 0x40
-#define PSCFG_WAKECALEN 0x20
-#define PSCFG_WAKETMREN 0x10
-#define PSCFG_BBPSPROG 0x08
-#define PSCFG_WAKESYN 0x04
-#define PSCFG_SLEEPSYN 0x02
-#define PSCFG_AUTOSLEEP 0x01
-
-/* Bits in the PSCTL register */
-#define PSCTL_WAKEDONE 0x20
-#define PSCTL_PS 0x10
-#define PSCTL_GO2DOZE 0x08
-#define PSCTL_LNBCN 0x04
-#define PSCTL_ALBCN 0x02
-#define PSCTL_PSEN 0x01
-
-/* Bits in the PSPWSIG register */
-#define PSSIG_WPE3 0x80
-#define PSSIG_WPE2 0x40
-#define PSSIG_WPE1 0x20
-#define PSSIG_WRADIOPE 0x10
-#define PSSIG_SPE3 0x08
-#define PSSIG_SPE2 0x04
-#define PSSIG_SPE1 0x02
-#define PSSIG_SRADIOPE 0x01
-
-/* Bits in the BBREGCTL register */
-#define BBREGCTL_DONE 0x04
-#define BBREGCTL_REGR 0x02
-#define BBREGCTL_REGW 0x01
-
-/* Bits in the IFREGCTL register */
-#define IFREGCTL_DONE 0x04
-#define IFREGCTL_IFRF 0x02
-#define IFREGCTL_REGW 0x01
-
-/* Bits in the SOFTPWRCTL register */
-#define SOFTPWRCTL_RFLEOPT 0x0800
-#define SOFTPWRCTL_TXPEINV 0x0200
-#define SOFTPWRCTL_SWPECTI 0x0100
-#define SOFTPWRCTL_SWPAPE 0x0020
-#define SOFTPWRCTL_SWCALEN 0x0010
-#define SOFTPWRCTL_SWRADIO_PE 0x0008
-#define SOFTPWRCTL_SWPE2 0x0004
-#define SOFTPWRCTL_SWPE1 0x0002
-#define SOFTPWRCTL_SWPE3 0x0001
-
-/* Bits in the GPIOCTL1 register */
-#define GPIO1_DATA1 0x20
-#define GPIO1_MD1 0x10
-#define GPIO1_DATA0 0x02
-#define GPIO1_MD0 0x01
-
-/* Bits in the DMACTL register */
-#define DMACTL_CLRRUN 0x00080000
-#define DMACTL_RUN 0x00000008
-#define DMACTL_WAKE 0x00000004
-#define DMACTL_DEAD 0x00000002
-#define DMACTL_ACTIVE 0x00000001
-
-/* Bits in the RXDMACTL0 register */
-#define RX_PERPKT 0x00000100
-#define RX_PERPKTCLR 0x01000000
-
-/* Bits in the BCNDMACTL register */
-#define BEACON_READY 0x01
-
-/* Bits in the MISCFFCTL register */
-#define MISCFFCTL_WRITE 0x0001
-
-/* Bits in WAKEUPEN0 */
-#define WAKEUPEN0_DIRPKT 0x10
-#define WAKEUPEN0_LINKOFF 0x08
-#define WAKEUPEN0_ATIMEN 0x04
-#define WAKEUPEN0_TIMEN 0x02
-#define WAKEUPEN0_MAGICEN 0x01
-
-/* Bits in WAKEUPEN1 */
-#define WAKEUPEN1_128_3 0x08
-#define WAKEUPEN1_128_2 0x04
-#define WAKEUPEN1_128_1 0x02
-#define WAKEUPEN1_128_0 0x01
-
-/* Bits in WAKEUPSR0 */
-#define WAKEUPSR0_DIRPKT 0x10
-#define WAKEUPSR0_LINKOFF 0x08
-#define WAKEUPSR0_ATIMEN 0x04
-#define WAKEUPSR0_TIMEN 0x02
-#define WAKEUPSR0_MAGICEN 0x01
-
-/* Bits in WAKEUPSR1 */
-#define WAKEUPSR1_128_3 0x08
-#define WAKEUPSR1_128_2 0x04
-#define WAKEUPSR1_128_1 0x02
-#define WAKEUPSR1_128_0 0x01
-
-/* Bits in the MAC_REG_GPIOCTL register */
-#define GPIO0_MD 0x01
-#define GPIO0_DATA 0x02
-#define GPIO0_INTMD 0x04
-#define GPIO1_MD 0x10
-#define GPIO1_DATA 0x20
-
-/* Bits in the MSRCTL register */
-#define MSRCTL_FINISH 0x80
-#define MSRCTL_READY 0x40
-#define MSRCTL_RADARDETECT 0x20
-#define MSRCTL_EN 0x10
-#define MSRCTL_QUIETTXCHK 0x08
-#define MSRCTL_QUIETRPT 0x04
-#define MSRCTL_QUIETINT 0x02
-#define MSRCTL_QUIETEN 0x01
-
-/* Bits in the MSRCTL1 register */
-#define MSRCTL1_TXPWR 0x08
-#define MSRCTL1_CSAPAREN 0x04
-#define MSRCTL1_TXPAUSE 0x01
-
-/* Loopback mode */
-#define MAC_LB_EXT 0x02
-#define MAC_LB_INTERNAL 0x01
-#define MAC_LB_NONE 0x00
-
-#define DEFAULT_BI 0x200
-
-/* MiscFIFO Offset */
-#define MISCFIFO_KEYETRY0 32
-#define MISCFIFO_KEYENTRYSIZE 22
-#define MISCFIFO_SYNINFO_IDX 10
-#define MISCFIFO_SYNDATA_IDX 11
-#define MISCFIFO_SYNDATASIZE 21
-
-/* enabled mask value of irq */
-#define IMR_MASK_VALUE (IMR_SOFTTIMER1 | \
- IMR_RXDMA1 | \
- IMR_RXNOBUF | \
- IMR_MIBNEARFULL | \
- IMR_SOFTINT | \
- IMR_FETALERR | \
- IMR_WATCHDOG | \
- IMR_SOFTTIMER | \
- IMR_GPIO | \
- IMR_TBTT | \
- IMR_RXDMA0 | \
- IMR_BNTX | \
- IMR_AC0DMA | \
- IMR_TXDMA0)
-
-/* max time out delay time */
-#define W_MAX_TIMEOUT 0xFFF0U
-
-/* wait time within loop */
-#define CB_DELAY_LOOP_WAIT 10 /* 10ms */
-
-/* revision id */
-#define REV_ID_VT3253_A0 0x00
-#define REV_ID_VT3253_A1 0x01
-#define REV_ID_VT3253_B0 0x08
-#define REV_ID_VT3253_B1 0x09
-
-/*--------------------- Export Types ------------------------------*/
-
-/*--------------------- Export Macros ------------------------------*/
-
-#define VT6655_MAC_SELECT_PAGE0(iobase) iowrite8(0, (iobase) + MAC_REG_PAGE1SEL)
-
-#define VT6655_MAC_SELECT_PAGE1(iobase) iowrite8(1, (iobase) + MAC_REG_PAGE1SEL)
-
-#define MAKEWORD(lb, hb) \
- ((unsigned short)(((unsigned char)(lb)) | (((unsigned short)((unsigned char)(hb))) << 8)))
-
-void vt6655_mac_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask);
-void vt6655_mac_word_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask);
-void vt6655_mac_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask);
-void vt6655_mac_word_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask);
-
-void vt6655_mac_set_short_retry_limit(struct vnt_private *priv, unsigned char retry_limit);
-
-void MACvSetLongRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit);
-
-bool MACbSoftwareReset(struct vnt_private *priv);
-bool MACbShutdown(struct vnt_private *priv);
-void MACvInitialize(struct vnt_private *priv);
-void vt6655_mac_set_curr_rx_0_desc_addr(struct vnt_private *priv, u32 curr_desc_addr);
-void vt6655_mac_set_curr_rx_1_desc_addr(struct vnt_private *priv, u32 curr_desc_addr);
-void vt6655_mac_set_curr_tx_desc_addr(int tx_type, struct vnt_private *priv, u32 curr_desc_addr);
-void MACvSetCurrSyncDescAddrEx(struct vnt_private *priv,
- u32 curr_desc_addr);
-void MACvSetCurrATIMDescAddrEx(struct vnt_private *priv,
- u32 curr_desc_addr);
-void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay);
-void MACvOneShotTimer1MicroSec(struct vnt_private *priv, unsigned int uDelayTime);
-
-void MACvSetMISCFifo(struct vnt_private *priv, unsigned short wOffset,
- u32 dwData);
-
-bool MACbPSWakeup(struct vnt_private *priv);
-
-void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl,
- unsigned int uEntryIdx, unsigned int uKeyIdx,
- unsigned char *pbyAddr, u32 *pdwKey,
- unsigned char local_id);
-void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx);
-
-#endif /* __MAC_H__ */
diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c
deleted file mode 100644
index 8527ad3eff48..000000000000
--- a/drivers/staging/vt6655/power.c
+++ /dev/null
@@ -1,144 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handles 802.11 power management functions
- *
- * Author: Lyndon Chen
- *
- * Date: July 17, 2002
- *
- * Functions:
- * PSvEnablePowerSaving - Enable Power Saving Mode
- * PSvDiasblePowerSaving - Disable Power Saving Mode
- * PSbConsiderPowerDown - Decide if we can Power Down
- * PSvSendPSPOLL - Send PS-POLL packet
- * PSbSendNullPacket - Send Null packet
- * PSbIsNextTBTTWakeUp - Decide if we need to wake up at next Beacon
- *
- * Revision History:
- *
- */
-
-#include "mac.h"
-#include "device.h"
-#include "power.h"
-#include "card.h"
-
-/*--------------------- Static Definitions -------------------------*/
-
-/*--------------------- Static Classes ----------------------------*/
-
-/*--------------------- Static Functions --------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Export Functions --------------------------*/
-
-/*
- *
- * Routine Description:
- * Enable hw power saving functions
- *
- * Return Value:
- * None.
- *
- */
-
-void PSvEnablePowerSaving(struct vnt_private *priv,
- unsigned short wListenInterval)
-{
- u16 wAID = priv->current_aid | BIT(14) | BIT(15);
-
- /* set period of power up before TBTT */
- iowrite16(C_PWBT, priv->port_offset + MAC_REG_PWBT);
- if (priv->op_mode != NL80211_IFTYPE_ADHOC) {
- /* set AID */
- iowrite16(wAID, priv->port_offset + MAC_REG_AIDATIM);
- }
-
- /* Set AutoSleep */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
-
- /* Set HWUTSF */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
-
- if (wListenInterval >= 2) {
- /* clear always listen beacon */
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN);
- /* first time set listen next beacon */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_LNBCN);
- } else {
- /* always listen beacon */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN);
- }
-
- /* enable power saving hw function */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_PSEN);
- priv->bEnablePSMode = true;
-
- priv->bPWBitOn = true;
- pr_debug("PS:Power Saving Mode Enable...\n");
-}
-
-/*
- *
- * Routine Description:
- * Disable hw power saving functions
- *
- * Return Value:
- * None.
- *
- */
-
-void PSvDisablePowerSaving(struct vnt_private *priv)
-{
- /* disable power saving hw function */
- MACbPSWakeup(priv);
-
- /* clear AutoSleep */
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
-
- /* clear HWUTSF */
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
-
- /* set always listen beacon */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN);
-
- priv->bEnablePSMode = false;
-
- priv->bPWBitOn = false;
-}
-
-/*
- *
- * Routine Description:
- * Check if Next TBTT must wake up
- *
- * Return Value:
- * None.
- *
- */
-
-bool PSbIsNextTBTTWakeUp(struct vnt_private *priv)
-{
- struct ieee80211_hw *hw = priv->hw;
- struct ieee80211_conf *conf = &hw->conf;
- bool wake_up = false;
-
- if (conf->listen_interval > 1) {
- if (!priv->wake_up_count)
- priv->wake_up_count = conf->listen_interval;
-
- --priv->wake_up_count;
-
- if (priv->wake_up_count == 1) {
- /* Turn on wake up to listen next beacon */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_LNBCN);
- wake_up = true;
- }
- }
-
- return wake_up;
-}
diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h
deleted file mode 100644
index 060516f81f5b..000000000000
--- a/drivers/staging/vt6655/power.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handles 802.11 power management functions
- *
- * Author: Lyndon Chen
- *
- * Date: July 17, 2002
- *
- */
-
-#ifndef __POWER_H__
-#define __POWER_H__
-
-#include "device.h"
-
-#define C_PWBT 1000 /* micro sec. power up before TBTT */
-#define PS_FAST_INTERVAL 1 /* Fast power saving listen interval */
-#define PS_MAX_INTERVAL 4 /* MAX power saving listen interval */
-
-void PSvDisablePowerSaving(struct vnt_private *priv);
-
-void PSvEnablePowerSaving(struct vnt_private *priv, unsigned short wListenInterval);
-
-bool PSbIsNextTBTTWakeUp(struct vnt_private *priv);
-
-#endif /* __POWER_H__ */
diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c
deleted file mode 100644
index d319ec21c97b..000000000000
--- a/drivers/staging/vt6655/rf.c
+++ /dev/null
@@ -1,535 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: rf function code
- *
- * Author: Jerry Chen
- *
- * Date: Feb. 19, 2004
- *
- * Functions:
- * IFRFbWriteEmbedded - Embedded write RF register via MAC
- *
- * Revision History:
- * RobertYu 2005
- * chester 2008
- *
- */
-
-#include "mac.h"
-#include "srom.h"
-#include "rf.h"
-#include "baseband.h"
-
-#define BY_AL2230_REG_LEN 23 /* 24bit */
-#define CB_AL2230_INIT_SEQ 15
-#define SWITCH_CHANNEL_DELAY_AL2230 200 /* us */
-#define AL2230_PWR_IDX_LEN 64
-
-#define BY_AL7230_REG_LEN 23 /* 24bit */
-#define CB_AL7230_INIT_SEQ 16
-#define SWITCH_CHANNEL_DELAY_AL7230 200 /* us */
-#define AL7230_PWR_IDX_LEN 64
-
-static const unsigned long al2230_init_table[CB_AL2230_INIT_SEQ] = {
- 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x01A00200 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x00FFF300 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0F4DC500 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0805B600 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0146C700 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x00068800 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0403B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x00DBBA00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x00099B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0BDFFC00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x00000D00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x00580F00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW
-};
-
-static const unsigned long al2230_channel_table0[CB_MAX_CHANNEL] = {
- 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */
- 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */
- 0x03E79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */
- 0x03E79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */
- 0x03F7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */
- 0x03F7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */
- 0x03E7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */
- 0x03E7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */
- 0x03F7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */
- 0x03F7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */
- 0x03E7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */
- 0x03E7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */
- 0x03F7C000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */
- 0x03E7C000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */
-};
-
-static const unsigned long al2230_channel_table1[CB_MAX_CHANNEL] = {
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */
- 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */
- 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */
- 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */
- 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */
- 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */
- 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */
- 0x06666100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */
-};
-
-static unsigned long al2230_power_table[AL2230_PWR_IDX_LEN] = {
- 0x04040900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04041900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04042900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04043900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04044900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04045900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04046900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04047900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04048900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04049900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0404A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0404B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0404C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0404D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0404E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0404F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04050900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04051900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04052900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04053900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04054900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04055900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04056900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04057900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04058900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04059900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0405A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0405B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0405C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0405D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0405E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0405F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04060900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04061900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04062900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04063900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04064900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04065900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04066900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04067900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04068900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04069900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0406A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0406B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0406C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0406D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0406E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0406F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04070900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04071900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04072900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04073900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04074900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04075900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04076900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04077900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04078900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04079900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0407A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0407B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0407C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0407D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0407E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0407F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW
-};
-
-/*
- * Description: Write to IF/RF, by embedded programming
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * dwData - data to write
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData)
-{
- void __iomem *iobase = priv->port_offset;
- unsigned short ww;
- unsigned long dwValue;
-
- iowrite32((u32)dwData, iobase + MAC_REG_IFREGCTL);
-
- /* W_MAX_TIMEOUT is the timeout period */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- dwValue = ioread32(iobase + MAC_REG_IFREGCTL);
- if (dwValue & IFREGCTL_DONE)
- break;
- }
-
- if (ww == W_MAX_TIMEOUT)
- return false;
-
- return true;
-}
-
-/*
- * Description: AIROHA IFRF chip init function
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-static bool RFbAL2230Init(struct vnt_private *priv)
-{
- void __iomem *iobase = priv->port_offset;
- int ii;
- bool ret;
-
- ret = true;
-
- /* 3-wire control for normal mode */
- iowrite8(0, iobase + MAC_REG_SOFTPWRCTL);
-
- vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL,
- (SOFTPWRCTL_SWPECTI | SOFTPWRCTL_TXPEINV));
- /* PLL Off */
- vt6655_mac_word_reg_bits_off(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
-
- /* patch abnormal AL2230 frequency output */
- IFRFbWriteEmbedded(priv, (0x07168700 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW));
-
- for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++)
- ret &= IFRFbWriteEmbedded(priv, al2230_init_table[ii]);
- MACvTimer0MicroSDelay(priv, 30); /* delay 30 us */
-
- /* PLL On */
- vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
-
- MACvTimer0MicroSDelay(priv, 150);/* 150us */
- ret &= IFRFbWriteEmbedded(priv, (0x00d80f00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW));
- MACvTimer0MicroSDelay(priv, 30);/* 30us */
- ret &= IFRFbWriteEmbedded(priv, (0x00780f00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW));
- MACvTimer0MicroSDelay(priv, 30);/* 30us */
- ret &= IFRFbWriteEmbedded(priv,
- al2230_init_table[CB_AL2230_INIT_SEQ - 1]);
-
- vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 |
- SOFTPWRCTL_SWPE2 |
- SOFTPWRCTL_SWPECTI |
- SOFTPWRCTL_TXPEINV));
-
- /* 3-wire control for power saving mode */
- iowrite8(PSSIG_WPE3 | PSSIG_WPE2, iobase + MAC_REG_PSPWRSIG);
-
- return ret;
-}
-
-static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byChannel)
-{
- void __iomem *iobase = priv->port_offset;
- bool ret;
-
- ret = true;
-
- ret &= IFRFbWriteEmbedded(priv, al2230_channel_table0[byChannel - 1]);
- ret &= IFRFbWriteEmbedded(priv, al2230_channel_table1[byChannel - 1]);
-
- /* Set Channel[7] = 0 to tell H/W channel is changing now. */
- iowrite8(byChannel & 0x7F, iobase + MAC_REG_CHANNEL);
- MACvTimer0MicroSDelay(priv, SWITCH_CHANNEL_DELAY_AL2230);
- /* Set Channel[7] = 1 to tell H/W channel change is done. */
- iowrite8(byChannel | 0x80, iobase + MAC_REG_CHANNEL);
-
- return ret;
-}
-
-/*
- * Description: RF init function
- *
- * Parameters:
- * In:
- * byBBType
- * rf_type
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool RFbInit(struct vnt_private *priv)
-{
- bool ret = true;
-
- switch (priv->rf_type) {
- case RF_AIROHA:
- case RF_AL2230S:
- priv->max_pwr_level = AL2230_PWR_IDX_LEN;
- ret = RFbAL2230Init(priv);
- break;
- case RF_NOTHING:
- ret = true;
- break;
- default:
- ret = false;
- break;
- }
- return ret;
-}
-
-/*
- * Description: Select channel
- *
- * Parameters:
- * In:
- * rf_type
- * byChannel - Channel number
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool RFbSelectChannel(struct vnt_private *priv, unsigned char rf_type,
- u16 byChannel)
-{
- bool ret = true;
-
- switch (rf_type) {
- case RF_AIROHA:
- case RF_AL2230S:
- ret = RFbAL2230SelectChannel(priv, byChannel);
- break;
- /*{{ RobertYu: 20050104 */
- case RF_NOTHING:
- ret = true;
- break;
- default:
- ret = false;
- break;
- }
- return ret;
-}
-
-/*
- * Description: Write WakeProgSyn
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * rf_type - RF type
- * channel - Channel number
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool rf_write_wake_prog_syn(struct vnt_private *priv, unsigned char rf_type,
- u16 channel)
-{
- void __iomem *iobase = priv->port_offset;
- int i;
- unsigned char init_count = 0;
- unsigned char sleep_count = 0;
- unsigned short idx = MISCFIFO_SYNDATA_IDX;
-
- iowrite16(0, iobase + MAC_REG_MISCFFNDEX);
- switch (rf_type) {
- case RF_AIROHA:
- case RF_AL2230S:
-
- if (channel > CB_MAX_CHANNEL_24G)
- return false;
-
- /* Init Reg + Channel Reg (2) */
- init_count = CB_AL2230_INIT_SEQ + 2;
- sleep_count = 0;
-
- for (i = 0; i < CB_AL2230_INIT_SEQ; i++)
- MACvSetMISCFifo(priv, idx++, al2230_init_table[i]);
-
- MACvSetMISCFifo(priv, idx++, al2230_channel_table0[channel - 1]);
- MACvSetMISCFifo(priv, idx++, al2230_channel_table1[channel - 1]);
- break;
-
- /* Need to check, PLLON need to be low for channel setting */
-
- case RF_NOTHING:
- return true;
-
- default:
- return false;
- }
-
- MACvSetMISCFifo(priv, MISCFIFO_SYNINFO_IDX, (unsigned long)MAKEWORD(sleep_count, init_count));
-
- return true;
-}
-
-/*
- * Description: Set Tx power
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * dwRFPowerTable - RF Tx Power Setting
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool RFbSetPower(struct vnt_private *priv, unsigned int rate, u16 uCH)
-{
- bool ret;
- unsigned char byPwr = 0;
- unsigned char byDec = 0;
-
- if (priv->dwDiagRefCount != 0)
- return true;
-
- if ((uCH < 1) || (uCH > CB_MAX_CHANNEL))
- return false;
-
- switch (rate) {
- case RATE_1M:
- case RATE_2M:
- case RATE_5M:
- case RATE_11M:
- if (uCH > CB_MAX_CHANNEL_24G)
- return false;
-
- byPwr = priv->abyCCKPwrTbl[uCH];
- break;
- case RATE_6M:
- case RATE_9M:
- case RATE_12M:
- case RATE_18M:
- byPwr = priv->abyOFDMPwrTbl[uCH];
- byDec = byPwr + 10;
-
- if (byDec >= priv->max_pwr_level)
- byDec = priv->max_pwr_level - 1;
-
- byPwr = byDec;
- break;
- case RATE_24M:
- case RATE_36M:
- case RATE_48M:
- case RATE_54M:
- byPwr = priv->abyOFDMPwrTbl[uCH];
- break;
- }
-
- if (priv->cur_pwr == byPwr)
- return true;
-
- ret = RFbRawSetPower(priv, byPwr, rate);
- if (ret)
- priv->cur_pwr = byPwr;
-
- return ret;
-}
-
-/*
- * Description: Set Tx power
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * dwRFPowerTable - RF Tx Power Setting
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-
-bool RFbRawSetPower(struct vnt_private *priv, unsigned char byPwr,
- unsigned int rate)
-{
- bool ret = true;
-
- if (byPwr >= priv->max_pwr_level)
- return false;
-
- switch (priv->rf_type) {
- case RF_AIROHA:
- ret &= IFRFbWriteEmbedded(priv, al2230_power_table[byPwr]);
- if (rate <= RATE_11M)
- ret &= IFRFbWriteEmbedded(priv, 0x0001B400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW);
- else
- ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW);
-
- break;
-
- case RF_AL2230S:
- ret &= IFRFbWriteEmbedded(priv, al2230_power_table[byPwr]);
- if (rate <= RATE_11M) {
- ret &= IFRFbWriteEmbedded(priv, 0x040C1400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW);
- ret &= IFRFbWriteEmbedded(priv, 0x00299B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW);
- } else {
- ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW);
- ret &= IFRFbWriteEmbedded(priv, 0x00099B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW);
- }
-
- break;
-
- default:
- break;
- }
- return ret;
-}
-
-/*
- *
- * Routine Description:
- * Translate RSSI to dBm
- *
- * Parameters:
- * In:
- * priv - The adapter to be translated
- * byCurrRSSI - RSSI to be translated
- * Out:
- * pdwdbm - Translated dbm number
- *
- * Return Value: none
- *
- */
-void
-RFvRSSITodBm(struct vnt_private *priv, unsigned char byCurrRSSI, long *pldBm)
-{
- unsigned char byIdx = (((byCurrRSSI & 0xC0) >> 6) & 0x03);
- long b = (byCurrRSSI & 0x3F);
- long a = 0;
- unsigned char abyAIROHARF[4] = {0, 18, 0, 40};
-
- switch (priv->rf_type) {
- case RF_AIROHA:
- case RF_AL2230S:
- a = abyAIROHARF[byIdx];
- break;
- default:
- break;
- }
-
- *pldBm = -1 * (a + b * 2);
-}
-
diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h
deleted file mode 100644
index 8eef100c7ef2..000000000000
--- a/drivers/staging/vt6655/rf.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:
- *
- * Author: Jerry Chen
- *
- * Date: Feb. 19, 2004
- *
- */
-
-#ifndef __RF_H__
-#define __RF_H__
-
-#include "device.h"
-
-/*--------------------- Export Definitions -------------------------*/
-/*
- * Baseband RF pair definition in eeprom (Bits 6..0)
- */
-#define RF_RFMD2959 0x01
-#define RF_MAXIMAG 0x02
-#define RF_AIROHA 0x03
-
-#define RF_UW2451 0x05
-#define RF_MAXIMG 0x06
-#define RF_MAXIM2829 0x07 /* RobertYu: 20041118 */
-#define RF_UW2452 0x08 /* RobertYu: 20041210 */
-#define RF_AIROHA7230 0x0a /* RobertYu: 20050104 */
-#define RF_UW2453 0x0b
-
-#define RF_VT3226 0x09
-#define RF_AL2230S 0x0e
-
-#define RF_NOTHING 0x7E
-#define RF_EMU 0x80
-#define RF_MASK 0x7F
-
-#define ZONE_FCC 0
-#define ZONE_MKK1 1
-#define ZONE_ETSI 2
-#define ZONE_IC 3
-#define ZONE_SPAIN 4
-#define ZONE_FRANCE 5
-#define ZONE_MKK 6
-#define ZONE_ISRAEL 7
-
-/* [20050104] CB_MAXIM2829_CHANNEL_5G_HIGH, CB_UW2452_CHANNEL_5G_HIGH: 40==>41 */
-#define CB_MAXIM2829_CHANNEL_5G_HIGH 41 /* Index41: channel = 100, Tf = 5500MHz, set the (A3:A0=0101) D6=1 */
-#define CB_UW2452_CHANNEL_5G_HIGH 41 /* [20041210] Index41: channel = 100, Tf = 5500MHz, change VCO2->VCO3 */
-
-/*--------------------- Export Classes ----------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Export Functions --------------------------*/
-
-bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData);
-bool RFbSelectChannel(struct vnt_private *priv, unsigned char rf_type, u16 byChannel);
-bool RFbInit(struct vnt_private *priv);
-bool rf_write_wake_prog_syn(struct vnt_private *priv, unsigned char rf_type, u16 channel);
-bool RFbSetPower(struct vnt_private *priv, unsigned int rate, u16 uCH);
-bool RFbRawSetPower(struct vnt_private *priv, unsigned char byPwr,
- unsigned int rate);
-
-void RFvRSSITodBm(struct vnt_private *priv, unsigned char byCurrRSSI,
- long *pldBm);
-
-#endif /* __RF_H__ */
diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c
deleted file mode 100644
index 3705cb1e87b6..000000000000
--- a/drivers/staging/vt6655/rxtx.c
+++ /dev/null
@@ -1,1462 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: handle WMAC/802.3/802.11 rx & tx functions
- *
- * Author: Lyndon Chen
- *
- * Date: May 20, 2003
- *
- * Functions:
- * s_vGenerateTxParameter - Generate tx dma required parameter.
- * vGenerateMACHeader - Translate 802.3 to 802.11 header
- * cbGetFragCount - Calculate fragment number count
- * csBeacon_xmit - beacon tx function
- * csMgmt_xmit - management tx function
- * s_cbFillTxBufHead - fulfill tx dma buffer header
- * s_uGetDataDuration - get tx data required duration
- * s_uFillDataHead- fulfill tx data duration header
- * s_uGetRTSCTSDuration- get rtx/cts required duration
- * get_rtscts_time- get rts/cts reserved time
- * s_uGetTxRsvTime- get frame reserved time
- * s_vFillCTSHead- fulfill CTS ctl header
- * s_vFillFragParameter- Set fragment ctl parameter.
- * s_vFillRTSHead- fulfill RTS ctl header
- * s_vFillTxKey- fulfill tx encrypt key
- * s_vSWencryption- Software encrypt header
- * vDMA0_tx_80211- tx 802.11 frame via dma0
- * vGenerateFIFOHeader- Generate tx FIFO ctl header
- *
- * Revision History:
- *
- */
-
-#include "device.h"
-#include "rxtx.h"
-#include "card.h"
-#include "mac.h"
-#include "baseband.h"
-#include "rf.h"
-
-/*--------------------- Static Definitions -------------------------*/
-
-/*--------------------- Static Classes ----------------------------*/
-
-/*--------------------- Static Variables --------------------------*/
-
-/*--------------------- Static Functions --------------------------*/
-
-/*--------------------- Static Definitions -------------------------*/
-/* if packet size < 256 -> in-direct send
- * vpacket size >= 256 -> direct send
- */
-#define CRITICAL_PACKET_LEN 256
-
-static const unsigned short time_stamp_off[2][MAX_RATE] = {
- {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, /* Long Preamble */
- {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, /* Short Preamble */
-};
-
-static const unsigned short fb_opt0[2][5] = {
- {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, /* fallback_rate0 */
- {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, /* fallback_rate1 */
-};
-
-static const unsigned short fb_opt1[2][5] = {
- {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, /* fallback_rate0 */
- {RATE_6M, RATE_6M, RATE_12M, RATE_12M, RATE_18M}, /* fallback_rate1 */
-};
-
-#define RTSDUR_BB 0
-#define RTSDUR_BA 1
-#define RTSDUR_AA 2
-#define CTSDUR_BA 3
-#define RTSDUR_BA_F0 4
-#define RTSDUR_AA_F0 5
-#define RTSDUR_BA_F1 6
-#define RTSDUR_AA_F1 7
-#define CTSDUR_BA_F0 8
-#define CTSDUR_BA_F1 9
-#define DATADUR_B 10
-#define DATADUR_A 11
-#define DATADUR_A_F0 12
-#define DATADUR_A_F1 13
-
-/*--------------------- Static Functions --------------------------*/
-static
-void
-s_vFillRTSHead(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- void *pvRTS,
- unsigned int cbFrameLength,
- bool bNeedAck,
- bool bDisCRC,
- struct ieee80211_hdr *hdr,
- unsigned short wCurrentRate,
- unsigned char byFBOption
-);
-
-static
-void
-s_vGenerateTxParameter(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- struct vnt_tx_fifo_head *,
- void *pvRrvTime,
- void *pvRTS,
- void *pvCTS,
- unsigned int cbFrameSize,
- bool bNeedACK,
- unsigned int uDMAIdx,
- void *psEthHeader,
- unsigned short wCurrentRate
-);
-
-static unsigned int
-s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
- unsigned char *pbyTxBufferAddr,
- unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD,
- unsigned int uNodeIndex);
-
-static
-__le16
-s_uFillDataHead(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- void *pTxDataHead,
- unsigned int cbFrameLength,
- unsigned int uDMAIdx,
- bool bNeedAck,
- unsigned int uFragIdx,
- unsigned int cbLastFragmentSize,
- unsigned int uMACfragNum,
- unsigned char byFBOption,
- unsigned short wCurrentRate,
- bool is_pspoll
-);
-
-/*--------------------- Export Variables --------------------------*/
-
-static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate)
-{
- return cpu_to_le16(time_stamp_off[priv->preamble_type % 2]
- [rate % MAX_RATE]);
-}
-
-/* byPktType : PK_TYPE_11A 0
- * PK_TYPE_11B 1
- * PK_TYPE_11GB 2
- * PK_TYPE_11GA 3
- */
-static
-unsigned int
-s_uGetTxRsvTime(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- unsigned int cbFrameLength,
- unsigned short wRate,
- bool bNeedAck
-)
-{
- unsigned int uDataTime, uAckTime;
-
- uDataTime = bb_get_frame_time(pDevice->preamble_type, byPktType, cbFrameLength, wRate);
-
- if (!bNeedAck)
- return uDataTime;
-
- /*
- * CCK mode - 11b
- * OFDM mode - 11g 2.4G & 11a 5G
- */
- uAckTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14,
- byPktType == PK_TYPE_11B ?
- pDevice->byTopCCKBasicRate :
- pDevice->byTopOFDMBasicRate);
-
- return uDataTime + pDevice->uSIFS + uAckTime;
-}
-
-static __le16 vnt_rxtx_rsvtime_le16(struct vnt_private *priv, u8 pkt_type,
- u32 frame_length, u16 rate, bool need_ack)
-{
- return cpu_to_le16((u16)s_uGetTxRsvTime(priv, pkt_type,
- frame_length, rate, need_ack));
-}
-
-/* byFreqType: 0=>5GHZ 1=>2.4GHZ */
-static __le16 get_rtscts_time(struct vnt_private *priv,
- unsigned char rts_rsvtype,
- unsigned char pkt_type,
- unsigned int frame_length,
- unsigned short current_rate)
-{
- unsigned int rrv_time = 0;
- unsigned int rts_time = 0;
- unsigned int cts_time = 0;
- unsigned int ack_time = 0;
- unsigned int data_time = 0;
-
- data_time = bb_get_frame_time(priv->preamble_type, pkt_type, frame_length, current_rate);
- if (rts_rsvtype == 0) { /* RTSTxRrvTime_bb */
- rts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 20, priv->byTopCCKBasicRate);
- ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopCCKBasicRate);
- cts_time = ack_time;
- } else if (rts_rsvtype == 1) { /* RTSTxRrvTime_ba, only in 2.4GHZ */
- rts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 20, priv->byTopCCKBasicRate);
- cts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopCCKBasicRate);
- ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopOFDMBasicRate);
- } else if (rts_rsvtype == 2) { /* RTSTxRrvTime_aa */
- rts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 20, priv->byTopOFDMBasicRate);
- ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopOFDMBasicRate);
- cts_time = ack_time;
- } else if (rts_rsvtype == 3) { /* CTSTxRrvTime_ba, only in 2.4GHZ */
- cts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopCCKBasicRate);
- ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopOFDMBasicRate);
- rrv_time = cts_time + ack_time + data_time + 2 * priv->uSIFS;
- return cpu_to_le16((u16)rrv_time);
- }
-
- /* RTSRrvTime */
- rrv_time = rts_time + cts_time + ack_time + data_time + 3 * priv->uSIFS;
- return cpu_to_le16((u16)rrv_time);
-}
-
-/* byFreqType 0: 5GHz, 1:2.4Ghz */
-static
-unsigned int
-s_uGetDataDuration(
- struct vnt_private *pDevice,
- unsigned char byDurType,
- unsigned int cbFrameLength,
- unsigned char byPktType,
- unsigned short wRate,
- bool bNeedAck,
- unsigned int uFragIdx,
- unsigned int cbLastFragmentSize,
- unsigned int uMACfragNum,
- unsigned char byFBOption
-)
-{
- bool bLastFrag = false;
- unsigned int uAckTime = 0, uNextPktTime = 0, len;
-
- if (uFragIdx == (uMACfragNum - 1))
- bLastFrag = true;
-
- if (uFragIdx == (uMACfragNum - 2))
- len = cbLastFragmentSize;
- else
- len = cbFrameLength;
-
- switch (byDurType) {
- case DATADUR_B: /* DATADUR_B */
- if (bNeedAck) {
- uAckTime = bb_get_frame_time(pDevice->preamble_type,
- byPktType, 14,
- pDevice->byTopCCKBasicRate);
- }
- /* Non Frag or Last Frag */
- if ((uMACfragNum == 1) || bLastFrag) {
- if (!bNeedAck)
- return 0;
- } else {
- /* First Frag or Mid Frag */
- uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType,
- len, wRate, bNeedAck);
- }
-
- return pDevice->uSIFS + uAckTime + uNextPktTime;
-
- case DATADUR_A: /* DATADUR_A */
- if (bNeedAck) {
- uAckTime = bb_get_frame_time(pDevice->preamble_type,
- byPktType, 14,
- pDevice->byTopOFDMBasicRate);
- }
- /* Non Frag or Last Frag */
- if ((uMACfragNum == 1) || bLastFrag) {
- if (!bNeedAck)
- return 0;
- } else {
- /* First Frag or Mid Frag */
- uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType,
- len, wRate, bNeedAck);
- }
-
- return pDevice->uSIFS + uAckTime + uNextPktTime;
-
- case DATADUR_A_F0: /* DATADUR_A_F0 */
- case DATADUR_A_F1: /* DATADUR_A_F1 */
- if (bNeedAck) {
- uAckTime = bb_get_frame_time(pDevice->preamble_type,
- byPktType, 14,
- pDevice->byTopOFDMBasicRate);
- }
- /* Non Frag or Last Frag */
- if ((uMACfragNum == 1) || bLastFrag) {
- if (!bNeedAck)
- return 0;
- } else {
- /* First Frag or Mid Frag */
- if (wRate < RATE_18M)
- wRate = RATE_18M;
- else if (wRate > RATE_54M)
- wRate = RATE_54M;
-
- wRate -= RATE_18M;
-
- if (byFBOption == AUTO_FB_0)
- wRate = fb_opt0[FB_RATE0][wRate];
- else
- wRate = fb_opt1[FB_RATE0][wRate];
-
- uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType,
- len, wRate, bNeedAck);
- }
-
- return pDevice->uSIFS + uAckTime + uNextPktTime;
-
- default:
- break;
- }
-
- return 0;
-}
-
-/* byFreqType: 0=>5GHZ 1=>2.4GHZ */
-static
-__le16
-s_uGetRTSCTSDuration(
- struct vnt_private *pDevice,
- unsigned char byDurType,
- unsigned int cbFrameLength,
- unsigned char byPktType,
- unsigned short wRate,
- bool bNeedAck,
- unsigned char byFBOption
-)
-{
- unsigned int uCTSTime = 0, uDurTime = 0;
-
- switch (byDurType) {
- case RTSDUR_BB: /* RTSDuration_bb */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate);
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
- break;
-
- case RTSDUR_BA: /* RTSDuration_ba */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate);
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
- break;
-
- case RTSDUR_AA: /* RTSDuration_aa */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopOFDMBasicRate);
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
- break;
-
- case CTSDUR_BA: /* CTSDuration_ba */
- uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
- break;
-
- case RTSDUR_BA_F0: /* RTSDuration_ba_f0 */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate);
- if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE0][wRate - RATE_18M], bNeedAck);
- else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE0][wRate - RATE_18M], bNeedAck);
-
- break;
-
- case RTSDUR_AA_F0: /* RTSDuration_aa_f0 */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopOFDMBasicRate);
- if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE0][wRate - RATE_18M], bNeedAck);
- else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE0][wRate - RATE_18M], bNeedAck);
-
- break;
-
- case RTSDUR_BA_F1: /* RTSDuration_ba_f1 */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate);
- if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE1][wRate - RATE_18M], bNeedAck);
- else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE1][wRate - RATE_18M], bNeedAck);
-
- break;
-
- case RTSDUR_AA_F1: /* RTSDuration_aa_f1 */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopOFDMBasicRate);
- if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE1][wRate - RATE_18M], bNeedAck);
- else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE1][wRate - RATE_18M], bNeedAck);
-
- break;
-
- case CTSDUR_BA_F0: /* CTSDuration_ba_f0 */
- if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE0][wRate - RATE_18M], bNeedAck);
- else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE0][wRate - RATE_18M], bNeedAck);
-
- break;
-
- case CTSDUR_BA_F1: /* CTSDuration_ba_f1 */
- if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE1][wRate - RATE_18M], bNeedAck);
- else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE1][wRate - RATE_18M], bNeedAck);
-
- break;
-
- default:
- break;
- }
-
- return cpu_to_le16((u16)uDurTime);
-}
-
-static
-__le16
-s_uFillDataHead(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- void *pTxDataHead,
- unsigned int cbFrameLength,
- unsigned int uDMAIdx,
- bool bNeedAck,
- unsigned int uFragIdx,
- unsigned int cbLastFragmentSize,
- unsigned int uMACfragNum,
- unsigned char byFBOption,
- unsigned short wCurrentRate,
- bool is_pspoll
-)
-{
- struct vnt_tx_datahead_ab *buf = pTxDataHead;
-
- if (!pTxDataHead)
- return 0;
-
- if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- /* Auto Fallback */
- struct vnt_tx_datahead_g_fb *buf = pTxDataHead;
-
- if (byFBOption == AUTO_FB_NONE) {
- struct vnt_tx_datahead_g *buf = pTxDataHead;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &buf->a);
-
- vnt_get_phy_field(pDevice, cbFrameLength,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->b);
-
- if (is_pspoll) {
- __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15));
-
- buf->duration_a = dur;
- buf->duration_b = dur;
- } else {
- /* Get Duration and TimeStamp */
- buf->duration_a =
- cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength,
- byPktType, wCurrentRate, bNeedAck, uFragIdx,
- cbLastFragmentSize, uMACfragNum,
- byFBOption));
- buf->duration_b =
- cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength,
- PK_TYPE_11B, pDevice->byTopCCKBasicRate,
- bNeedAck, uFragIdx, cbLastFragmentSize,
- uMACfragNum, byFBOption));
- }
-
- buf->time_stamp_off_a = vnt_time_stamp_off(pDevice, wCurrentRate);
- buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate);
-
- return buf->duration_a;
- }
-
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &buf->a);
-
- vnt_get_phy_field(pDevice, cbFrameLength,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->b);
- /* Get Duration and TimeStamp */
- buf->duration_a = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
- buf->duration_b = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B,
- pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
- buf->duration_a_f0 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
- buf->duration_a_f1 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
-
- buf->time_stamp_off_a = vnt_time_stamp_off(pDevice, wCurrentRate);
- buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate);
-
- return buf->duration_a;
- /* if (byFBOption == AUTO_FB_NONE) */
- } else if (byPktType == PK_TYPE_11A) {
- struct vnt_tx_datahead_ab *buf = pTxDataHead;
-
- if (byFBOption != AUTO_FB_NONE) {
- /* Auto Fallback */
- struct vnt_tx_datahead_a_fb *buf = pTxDataHead;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &buf->a);
-
- /* Get Duration and TimeStampOff */
- buf->duration = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
- buf->duration_f0 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
- buf->duration_f1 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
- buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
- return buf->duration;
- }
-
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &buf->ab);
-
- if (is_pspoll) {
- __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15));
-
- buf->duration = dur;
- } else {
- /* Get Duration and TimeStampOff */
- buf->duration =
- cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx,
- cbLastFragmentSize, uMACfragNum,
- byFBOption));
- }
-
- buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
- return buf->duration;
- }
-
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &buf->ab);
-
- if (is_pspoll) {
- __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15));
-
- buf->duration = dur;
- } else {
- /* Get Duration and TimeStampOff */
- buf->duration =
- cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx,
- cbLastFragmentSize, uMACfragNum,
- byFBOption));
- }
-
- buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
- return buf->duration;
-}
-
-static
-void
-s_vFillRTSHead(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- void *pvRTS,
- unsigned int cbFrameLength,
- bool bNeedAck,
- bool bDisCRC,
- struct ieee80211_hdr *hdr,
- unsigned short wCurrentRate,
- unsigned char byFBOption
-)
-{
- unsigned int uRTSFrameLen = 20;
-
- if (!pvRTS)
- return;
-
- if (bDisCRC) {
- /* When CRCDIS bit is on, H/W forgot to generate FCS for
- * RTS frame, in this case we need to decrease its length by 4.
- */
- uRTSFrameLen -= 4;
- }
-
- /* Note: So far RTSHead doesn't appear in ATIM & Beacom DMA,
- * so we don't need to take them into account.
- * Otherwise, we need to modify codes for them.
- */
- if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- if (byFBOption == AUTO_FB_NONE) {
- struct vnt_rts_g *buf = pvRTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->b);
-
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopOFDMBasicRate,
- byPktType, &buf->a);
- /* Get Duration */
- buf->duration_bb =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
- cbFrameLength, PK_TYPE_11B,
- pDevice->byTopCCKBasicRate,
- bNeedAck, byFBOption);
- buf->duration_aa =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->duration_ba =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
-
- buf->data.duration = buf->duration_aa;
- /* Get RTS Frame body */
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_RTS);
-
- ether_addr_copy(buf->data.ra, hdr->addr1);
- ether_addr_copy(buf->data.ta, hdr->addr2);
- } else {
- struct vnt_rts_g_fb *buf = pvRTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->b);
-
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopOFDMBasicRate,
- byPktType, &buf->a);
- /* Get Duration */
- buf->duration_bb =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
- cbFrameLength, PK_TYPE_11B,
- pDevice->byTopCCKBasicRate,
- bNeedAck, byFBOption);
- buf->duration_aa =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->duration_ba =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->rts_duration_ba_f0 =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->rts_duration_aa_f0 =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->rts_duration_ba_f1 =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->rts_duration_aa_f1 =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->data.duration = buf->duration_aa;
- /* Get RTS Frame body */
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_RTS);
-
- ether_addr_copy(buf->data.ra, hdr->addr1);
- ether_addr_copy(buf->data.ta, hdr->addr2);
- } /* if (byFBOption == AUTO_FB_NONE) */
- } else if (byPktType == PK_TYPE_11A) {
- if (byFBOption == AUTO_FB_NONE) {
- struct vnt_rts_ab *buf = pvRTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopOFDMBasicRate,
- byPktType, &buf->ab);
- /* Get Duration */
- buf->duration =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->data.duration = buf->duration;
- /* Get RTS Frame body */
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_RTS);
-
- ether_addr_copy(buf->data.ra, hdr->addr1);
- ether_addr_copy(buf->data.ta, hdr->addr2);
- } else {
- struct vnt_rts_a_fb *buf = pvRTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopOFDMBasicRate,
- byPktType, &buf->a);
- /* Get Duration */
- buf->duration =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->rts_duration_f0 =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->rts_duration_f1 =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->data.duration = buf->duration;
- /* Get RTS Frame body */
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_RTS);
-
- ether_addr_copy(buf->data.ra, hdr->addr1);
- ether_addr_copy(buf->data.ta, hdr->addr2);
- }
- } else if (byPktType == PK_TYPE_11B) {
- struct vnt_rts_ab *buf = pvRTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->ab);
- /* Get Duration */
- buf->duration =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength,
- byPktType, wCurrentRate, bNeedAck,
- byFBOption);
-
- buf->data.duration = buf->duration;
- /* Get RTS Frame body */
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
-
- ether_addr_copy(buf->data.ra, hdr->addr1);
- ether_addr_copy(buf->data.ta, hdr->addr2);
- }
-}
-
-static
-void
-s_vFillCTSHead(
- struct vnt_private *pDevice,
- unsigned int uDMAIdx,
- unsigned char byPktType,
- void *pvCTS,
- unsigned int cbFrameLength,
- bool bNeedAck,
- bool bDisCRC,
- unsigned short wCurrentRate,
- unsigned char byFBOption
-)
-{
- unsigned int uCTSFrameLen = 14;
-
- if (!pvCTS)
- return;
-
- if (bDisCRC) {
- /* When CRCDIS bit is on, H/W forgot to generate FCS for
- * CTS frame, in this case we need to decrease its length by 4.
- */
- uCTSFrameLen -= 4;
- }
-
- if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) {
- /* Auto Fall back */
- struct vnt_cts_fb *buf = pvCTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uCTSFrameLen,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->b);
-
- buf->duration_ba =
- s_uGetRTSCTSDuration(pDevice, CTSDUR_BA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
-
- /* Get CTSDuration_ba_f0 */
- buf->cts_duration_ba_f0 =
- s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
-
- /* Get CTSDuration_ba_f1 */
- buf->cts_duration_ba_f1 =
- s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
-
- /* Get CTS Frame body */
- buf->data.duration = buf->duration_ba;
-
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_CTS);
-
- buf->reserved2 = 0x0;
-
- ether_addr_copy(buf->data.ra,
- pDevice->abyCurrentNetAddr);
- } else { /* if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) */
- struct vnt_cts *buf = pvCTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uCTSFrameLen,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->b);
-
- /* Get CTSDuration_ba */
- buf->duration_ba =
- s_uGetRTSCTSDuration(pDevice, CTSDUR_BA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
-
- /* Get CTS Frame body */
- buf->data.duration = buf->duration_ba;
-
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_CTS);
-
- buf->reserved2 = 0x0;
- ether_addr_copy(buf->data.ra,
- pDevice->abyCurrentNetAddr);
- }
- }
-}
-
-/*
- *
- * Description:
- * Generate FIFO control for MAC & Baseband controller
- *
- * Parameters:
- * In:
- * pDevice - Pointer to adapter
- * pTxDataHead - Transmit Data Buffer
- * pTxBufHead - pTxBufHead
- * pvRrvTime - pvRrvTime
- * pvRTS - RTS Buffer
- * pCTS - CTS Buffer
- * cbFrameSize - Transmit Data Length (Hdr+Payload+FCS)
- * bNeedACK - If need ACK
- * uDescIdx - Desc Index
- * Out:
- * none
- *
- * Return Value: none
- *
- -
- * unsigned int cbFrameSize, Hdr+Payload+FCS
- */
-static
-void
-s_vGenerateTxParameter(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- struct vnt_tx_fifo_head *tx_buffer_head,
- void *pvRrvTime,
- void *pvRTS,
- void *pvCTS,
- unsigned int cbFrameSize,
- bool bNeedACK,
- unsigned int uDMAIdx,
- void *psEthHeader,
- unsigned short wCurrentRate
-)
-{
- u16 fifo_ctl = le16_to_cpu(tx_buffer_head->fifo_ctl);
- bool bDisCRC = false;
- unsigned char byFBOption = AUTO_FB_NONE;
-
- tx_buffer_head->current_rate = cpu_to_le16(wCurrentRate);
-
- if (fifo_ctl & FIFOCTL_CRCDIS)
- bDisCRC = true;
-
- if (fifo_ctl & FIFOCTL_AUTO_FB_0)
- byFBOption = AUTO_FB_0;
- else if (fifo_ctl & FIFOCTL_AUTO_FB_1)
- byFBOption = AUTO_FB_1;
-
- if (!pvRrvTime)
- return;
-
- if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- if (pvRTS) { /* RTS_need */
- /* Fill RsvTime */
- struct vnt_rrv_time_rts *buf = pvRrvTime;
-
- buf->rts_rrv_time_aa = get_rtscts_time(pDevice, 2, byPktType, cbFrameSize, wCurrentRate);
- buf->rts_rrv_time_ba = get_rtscts_time(pDevice, 1, byPktType, cbFrameSize, wCurrentRate);
- buf->rts_rrv_time_bb = get_rtscts_time(pDevice, 0, byPktType, cbFrameSize, wCurrentRate);
- buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
- buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK);
-
- s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
- } else {/* RTS_needless, PCF mode */
- struct vnt_rrv_time_cts *buf = pvRrvTime;
-
- buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
- buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK);
- buf->cts_rrv_time_ba = get_rtscts_time(pDevice, 3, byPktType, cbFrameSize, wCurrentRate);
-
- /* Fill CTS */
- s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption);
- }
- } else if (byPktType == PK_TYPE_11A) {
- if (pvRTS) {/* RTS_need, non PCF mode */
- struct vnt_rrv_time_ab *buf = pvRrvTime;
-
- buf->rts_rrv_time = get_rtscts_time(pDevice, 2, byPktType, cbFrameSize, wCurrentRate);
- buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
-
- /* Fill RTS */
- s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
- } else if (!pvRTS) {/* RTS_needless, non PCF mode */
- struct vnt_rrv_time_ab *buf = pvRrvTime;
-
- buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK);
- }
- } else if (byPktType == PK_TYPE_11B) {
- if (pvRTS) {/* RTS_need, non PCF mode */
- struct vnt_rrv_time_ab *buf = pvRrvTime;
-
- buf->rts_rrv_time = get_rtscts_time(pDevice, 0, byPktType, cbFrameSize, wCurrentRate);
- buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK);
-
- /* Fill RTS */
- s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
- } else { /* RTS_needless, non PCF mode */
- struct vnt_rrv_time_ab *buf = pvRrvTime;
-
- buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK);
- }
- }
-}
-
-static unsigned int
-s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
- unsigned char *pbyTxBufferAddr,
- unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD,
- unsigned int is_pspoll)
-{
- struct vnt_td_info *td_info = pHeadTD->td_info;
- struct sk_buff *skb = td_info->skb;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct vnt_tx_fifo_head *tx_buffer_head =
- (struct vnt_tx_fifo_head *)td_info->buf;
- u16 fifo_ctl = le16_to_cpu(tx_buffer_head->fifo_ctl);
- unsigned int cbFrameSize;
- __le16 uDuration;
- unsigned char *pbyBuffer;
- unsigned int uLength = 0;
- unsigned int cbMICHDR = 0;
- unsigned int uMACfragNum = 1;
- unsigned int uPadding = 0;
- unsigned int cbReqCount = 0;
- bool bNeedACK = (bool)(fifo_ctl & FIFOCTL_NEEDACK);
- bool bRTS = (bool)(fifo_ctl & FIFOCTL_RTS);
- struct vnt_tx_desc *ptdCurr;
- unsigned int cbHeaderLength = 0;
- void *pvRrvTime = NULL;
- struct vnt_mic_hdr *pMICHDR = NULL;
- void *pvRTS = NULL;
- void *pvCTS = NULL;
- void *pvTxDataHd = NULL;
- unsigned short wTxBufSize; /* FFinfo size */
- unsigned char byFBOption = AUTO_FB_NONE;
-
- cbFrameSize = skb->len + 4;
-
- if (info->control.hw_key) {
- switch (info->control.hw_key->cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- cbMICHDR = sizeof(struct vnt_mic_hdr);
- break;
- default:
- break;
- }
-
- cbFrameSize += info->control.hw_key->icv_len;
-
- if (pDevice->local_id > REV_ID_VT3253_A1) {
- /* MAC Header should be padding 0 to DW alignment. */
- uPadding = 4 - (ieee80211_get_hdrlen_from_skb(skb) % 4);
- uPadding %= 4;
- }
- }
-
- /*
- * Use for AUTO FALL BACK
- */
- if (fifo_ctl & FIFOCTL_AUTO_FB_0)
- byFBOption = AUTO_FB_0;
- else if (fifo_ctl & FIFOCTL_AUTO_FB_1)
- byFBOption = AUTO_FB_1;
-
- /* Set RrvTime/RTS/CTS Buffer */
- wTxBufSize = sizeof(struct vnt_tx_fifo_head);
- if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {/* 802.11g packet */
-
- if (byFBOption == AUTO_FB_NONE) {
- if (bRTS) {/* RTS_need */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts));
- pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
- pvCTS = NULL;
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g));
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g) +
- sizeof(struct vnt_tx_datahead_g);
- } else { /* RTS_needless */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts));
- pvRTS = NULL;
- pvCTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_cts) + cbMICHDR + sizeof(struct vnt_cts));
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
- }
- } else {
- /* Auto Fall Back */
- if (bRTS) {/* RTS_need */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts));
- pvRTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
- pvCTS = NULL;
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g_fb));
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g_fb) + sizeof(struct vnt_tx_datahead_g_fb);
- } else { /* RTS_needless */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts));
- pvRTS = NULL;
- pvCTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts_fb));
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts_fb) + sizeof(struct vnt_tx_datahead_g_fb);
- }
- } /* Auto Fall Back */
- } else {/* 802.11a/b packet */
-
- if (byFBOption == AUTO_FB_NONE) {
- if (bRTS) {
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
- pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
- pvCTS = NULL;
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_ab));
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
- cbMICHDR + sizeof(struct vnt_rts_ab) + sizeof(struct vnt_tx_datahead_ab);
- } else { /* RTS_needless, need MICHDR */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
- pvRTS = NULL;
- pvCTS = NULL;
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
- cbMICHDR + sizeof(struct vnt_tx_datahead_ab);
- }
- } else {
- /* Auto Fall Back */
- if (bRTS) { /* RTS_need */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
- pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
- pvCTS = NULL;
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_a_fb));
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
- cbMICHDR + sizeof(struct vnt_rts_a_fb) + sizeof(struct vnt_tx_datahead_a_fb);
- } else { /* RTS_needless */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
- pvRTS = NULL;
- pvCTS = NULL;
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
- cbMICHDR + sizeof(struct vnt_tx_datahead_a_fb);
- }
- } /* Auto Fall Back */
- }
-
- td_info->mic_hdr = pMICHDR;
-
- memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderLength - wTxBufSize));
-
- /* Fill FIFO,RrvTime,RTS,and CTS */
- s_vGenerateTxParameter(pDevice, byPktType, tx_buffer_head, pvRrvTime, pvRTS, pvCTS,
- cbFrameSize, bNeedACK, uDMAIdx, hdr, pDevice->wCurrentRate);
- /* Fill DataHead */
- uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK,
- 0, 0, uMACfragNum, byFBOption, pDevice->wCurrentRate, is_pspoll);
-
- hdr->duration_id = uDuration;
-
- cbReqCount = cbHeaderLength + uPadding + skb->len;
- pbyBuffer = (unsigned char *)pHeadTD->td_info->buf;
- uLength = cbHeaderLength + uPadding;
-
- /* Copy the Packet into a tx Buffer */
- memcpy((pbyBuffer + uLength), skb->data, skb->len);
-
- ptdCurr = pHeadTD;
-
- ptdCurr->td_info->req_count = (u16)cbReqCount;
-
- return cbHeaderLength;
-}
-
-static void vnt_fill_txkey(struct ieee80211_hdr *hdr, u8 *key_buffer,
- struct ieee80211_key_conf *tx_key,
- struct sk_buff *skb, u16 payload_len,
- struct vnt_mic_hdr *mic_hdr)
-{
- u64 pn64;
- u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb));
-
- /* strip header and icv len from payload */
- payload_len -= ieee80211_get_hdrlen_from_skb(skb);
- payload_len -= tx_key->icv_len;
-
- switch (tx_key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- memcpy(key_buffer, iv, 3);
- memcpy(key_buffer + 3, tx_key->key, tx_key->keylen);
-
- if (tx_key->keylen == WLAN_KEY_LEN_WEP40) {
- memcpy(key_buffer + 8, iv, 3);
- memcpy(key_buffer + 11,
- tx_key->key, WLAN_KEY_LEN_WEP40);
- }
-
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- ieee80211_get_tkip_p2k(tx_key, skb, key_buffer);
-
- break;
- case WLAN_CIPHER_SUITE_CCMP:
-
- if (!mic_hdr)
- return;
-
- mic_hdr->id = 0x59;
- mic_hdr->payload_len = cpu_to_be16(payload_len);
- ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2);
-
- pn64 = atomic64_read(&tx_key->tx_pn);
- mic_hdr->ccmp_pn[5] = pn64;
- mic_hdr->ccmp_pn[4] = pn64 >> 8;
- mic_hdr->ccmp_pn[3] = pn64 >> 16;
- mic_hdr->ccmp_pn[2] = pn64 >> 24;
- mic_hdr->ccmp_pn[1] = pn64 >> 32;
- mic_hdr->ccmp_pn[0] = pn64 >> 40;
-
- if (ieee80211_has_a4(hdr->frame_control))
- mic_hdr->hlen = cpu_to_be16(28);
- else
- mic_hdr->hlen = cpu_to_be16(22);
-
- ether_addr_copy(mic_hdr->addr1, hdr->addr1);
- ether_addr_copy(mic_hdr->addr2, hdr->addr2);
- ether_addr_copy(mic_hdr->addr3, hdr->addr3);
-
- mic_hdr->frame_control = cpu_to_le16(
- le16_to_cpu(hdr->frame_control) & 0xc78f);
- mic_hdr->seq_ctrl = cpu_to_le16(
- le16_to_cpu(hdr->seq_ctrl) & 0xf);
-
- if (ieee80211_has_a4(hdr->frame_control))
- ether_addr_copy(mic_hdr->addr4, hdr->addr4);
-
- memcpy(key_buffer, tx_key->key, WLAN_KEY_LEN_CCMP);
-
- break;
- default:
- break;
- }
-}
-
-int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx,
- struct vnt_tx_desc *head_td, struct sk_buff *skb)
-{
- struct vnt_td_info *td_info = head_td->td_info;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_tx_rate *tx_rate = &info->control.rates[0];
- struct ieee80211_rate *rate;
- struct ieee80211_key_conf *tx_key;
- struct ieee80211_hdr *hdr;
- struct vnt_tx_fifo_head *tx_buffer_head =
- (struct vnt_tx_fifo_head *)td_info->buf;
- u16 tx_body_size = skb->len, current_rate;
- u8 pkt_type;
- bool is_pspoll = false;
-
- memset(tx_buffer_head, 0, sizeof(*tx_buffer_head));
-
- hdr = (struct ieee80211_hdr *)(skb->data);
-
- rate = ieee80211_get_tx_rate(priv->hw, info);
-
- current_rate = rate->hw_value;
- if (priv->wCurrentRate != current_rate &&
- !(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
- priv->wCurrentRate = current_rate;
-
- RFbSetPower(priv, priv->wCurrentRate,
- priv->hw->conf.chandef.chan->hw_value);
- }
-
- if (current_rate > RATE_11M) {
- if (info->band == NL80211_BAND_5GHZ) {
- pkt_type = PK_TYPE_11A;
- } else {
- if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
- pkt_type = PK_TYPE_11GB;
- else
- pkt_type = PK_TYPE_11GA;
- }
- } else {
- pkt_type = PK_TYPE_11B;
- }
-
- /*Set fifo controls */
- if (pkt_type == PK_TYPE_11A)
- tx_buffer_head->fifo_ctl = 0;
- else if (pkt_type == PK_TYPE_11B)
- tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11B);
- else if (pkt_type == PK_TYPE_11GB)
- tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GB);
- else if (pkt_type == PK_TYPE_11GA)
- tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GA);
-
- /* generate interrupt */
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT);
-
- if (!ieee80211_is_data(hdr->frame_control)) {
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_TMOEN);
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_ISDMA0);
- tx_buffer_head->time_stamp =
- cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
- } else {
- tx_buffer_head->time_stamp =
- cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);
- }
-
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_NEEDACK);
-
- if (ieee80211_has_retry(hdr->frame_control))
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LRETRY);
-
- if (tx_rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
- priv->preamble_type = PREAMBLE_SHORT;
- else
- priv->preamble_type = PREAMBLE_LONG;
-
- if (tx_rate->flags & IEEE80211_TX_RC_USE_RTS_CTS)
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_RTS);
-
- if (ieee80211_has_a4(hdr->frame_control)) {
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LHEAD);
- priv->bLongHeader = true;
- }
-
- if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER)
- is_pspoll = true;
-
- tx_buffer_head->frag_ctl =
- cpu_to_le16(ieee80211_get_hdrlen_from_skb(skb) << 10);
-
- if (info->control.hw_key) {
- switch (info->control.hw_key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_LEGACY);
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_TKIP);
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_AES);
- break;
- default:
- break;
- }
- }
-
- tx_buffer_head->current_rate = cpu_to_le16(current_rate);
-
- /* legacy rates TODO use ieee80211_tx_rate */
- if (current_rate >= RATE_18M && ieee80211_is_data(hdr->frame_control)) {
- if (priv->byAutoFBCtrl == AUTO_FB_0)
- tx_buffer_head->fifo_ctl |=
- cpu_to_le16(FIFOCTL_AUTO_FB_0);
- else if (priv->byAutoFBCtrl == AUTO_FB_1)
- tx_buffer_head->fifo_ctl |=
- cpu_to_le16(FIFOCTL_AUTO_FB_1);
- }
-
- tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG);
-
- s_cbFillTxBufHead(priv, pkt_type, (u8 *)tx_buffer_head,
- dma_idx, head_td, is_pspoll);
-
- if (info->control.hw_key) {
- tx_key = info->control.hw_key;
- if (tx_key->keylen > 0)
- vnt_fill_txkey(hdr, tx_buffer_head->tx_key,
- tx_key, skb, tx_body_size,
- td_info->mic_hdr);
- }
-
- return 0;
-}
-
-static int vnt_beacon_xmit(struct vnt_private *priv,
- struct sk_buff *skb)
-{
- struct vnt_tx_short_buf_head *short_head =
- (struct vnt_tx_short_buf_head *)priv->tx_beacon_bufs;
- struct ieee80211_mgmt *mgmt_hdr = (struct ieee80211_mgmt *)
- (priv->tx_beacon_bufs + sizeof(*short_head));
- struct ieee80211_tx_info *info;
- u32 frame_size = skb->len + 4;
- u16 current_rate;
-
- memset(priv->tx_beacon_bufs, 0, sizeof(*short_head));
-
- if (priv->byBBType == BB_TYPE_11A) {
- current_rate = RATE_6M;
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, frame_size, current_rate,
- PK_TYPE_11A, &short_head->ab);
-
- /* Get Duration and TimeStampOff */
- short_head->duration =
- cpu_to_le16((u16)s_uGetDataDuration(priv, DATADUR_B,
- frame_size, PK_TYPE_11A, current_rate,
- false, 0, 0, 1, AUTO_FB_NONE));
-
- short_head->time_stamp_off =
- vnt_time_stamp_off(priv, current_rate);
- } else {
- current_rate = RATE_1M;
- short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_11B);
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, frame_size, current_rate,
- PK_TYPE_11B, &short_head->ab);
-
- /* Get Duration and TimeStampOff */
- short_head->duration =
- cpu_to_le16((u16)s_uGetDataDuration(priv, DATADUR_B,
- frame_size, PK_TYPE_11B, current_rate,
- false, 0, 0, 1, AUTO_FB_NONE));
-
- short_head->time_stamp_off =
- vnt_time_stamp_off(priv, current_rate);
- }
-
- short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT);
-
- /* Copy Beacon */
- memcpy(mgmt_hdr, skb->data, skb->len);
-
- /* time stamp always 0 */
- mgmt_hdr->u.beacon.timestamp = 0;
-
- info = IEEE80211_SKB_CB(skb);
- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)mgmt_hdr;
-
- hdr->duration_id = 0;
- hdr->seq_ctrl = cpu_to_le16(priv->wSeqCounter << 4);
- }
-
- priv->wSeqCounter++;
- if (priv->wSeqCounter > 0x0fff)
- priv->wSeqCounter = 0;
-
- priv->wBCNBufLen = sizeof(*short_head) + skb->len;
-
- iowrite32((u32)priv->tx_beacon_dma, priv->port_offset + MAC_REG_BCNDMAPTR);
-
- iowrite16(priv->wBCNBufLen, priv->port_offset + MAC_REG_BCNDMACTL + 2);
- /* Set auto Transmit on */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX);
- /* Poll Transmit the adapter */
- iowrite8(BEACON_READY, priv->port_offset + MAC_REG_BCNDMACTL);
-
- return 0;
-}
-
-int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif)
-{
- struct sk_buff *beacon;
-
- beacon = ieee80211_beacon_get(priv->hw, vif, 0);
- if (!beacon)
- return -ENOMEM;
-
- if (vnt_beacon_xmit(priv, beacon)) {
- ieee80211_free_txskb(priv->hw, beacon);
- return -ENODEV;
- }
-
- return 0;
-}
-
-int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf)
-{
- iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL);
-
- iowrite8(TFTCTL_TSFCNTREN, priv->port_offset + MAC_REG_TFTCTL);
-
- CARDvSetFirstNextTBTT(priv, conf->beacon_int);
-
- card_set_beacon_period(priv, conf->beacon_int);
-
- return vnt_beacon_make(priv, vif);
-}
diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h
deleted file mode 100644
index be1e5180d57b..000000000000
--- a/drivers/staging/vt6655/rxtx.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:
- *
- * Author: Jerry Chen
- *
- * Date: Jun. 27, 2002
- *
- */
-
-#ifndef __RXTX_H__
-#define __RXTX_H__
-
-#include "device.h"
-
-#define DEFAULT_MSDU_LIFETIME_RES_64us 8000 /* 64us */
-#define DEFAULT_MGN_LIFETIME_RES_64us 125 /* 64us */
-
-/*--------------------- Export Definitions -------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Export Functions --------------------------*/
-
-/* MIC HDR data header */
-struct vnt_mic_hdr {
- u8 id;
- u8 tx_priority;
- u8 mic_addr2[ETH_ALEN];
- u8 ccmp_pn[IEEE80211_CCMP_PN_LEN];
- __be16 payload_len;
- __be16 hlen;
- __le16 frame_control;
- u8 addr1[ETH_ALEN];
- u8 addr2[ETH_ALEN];
- u8 addr3[ETH_ALEN];
- __le16 seq_ctrl;
- u8 addr4[ETH_ALEN];
- u16 packing; /* packing to 48 bytes */
-} __packed;
-
-/* RsvTime buffer header */
-struct vnt_rrv_time_rts {
- __le16 rts_rrv_time_ba;
- __le16 rts_rrv_time_aa;
- __le16 rts_rrv_time_bb;
- u16 reserved;
- __le16 rrv_time_b;
- __le16 rrv_time_a;
-} __packed;
-
-struct vnt_rrv_time_cts {
- __le16 cts_rrv_time_ba;
- u16 reserved;
- __le16 rrv_time_b;
- __le16 rrv_time_a;
-} __packed;
-
-struct vnt_rrv_time_ab {
- __le16 rts_rrv_time;
- __le16 rrv_time;
-} __packed;
-
-/* TX data header */
-struct vnt_tx_datahead_g {
- struct vnt_phy_field b;
- struct vnt_phy_field a;
- __le16 duration_b;
- __le16 duration_a;
- __le16 time_stamp_off_b;
- __le16 time_stamp_off_a;
-} __packed;
-
-struct vnt_tx_datahead_g_fb {
- struct vnt_phy_field b;
- struct vnt_phy_field a;
- __le16 duration_b;
- __le16 duration_a;
- __le16 duration_a_f0;
- __le16 duration_a_f1;
- __le16 time_stamp_off_b;
- __le16 time_stamp_off_a;
-} __packed;
-
-struct vnt_tx_datahead_ab {
- struct vnt_phy_field ab;
- __le16 duration;
- __le16 time_stamp_off;
-} __packed;
-
-struct vnt_tx_datahead_a_fb {
- struct vnt_phy_field a;
- __le16 duration;
- __le16 time_stamp_off;
- __le16 duration_f0;
- __le16 duration_f1;
-} __packed;
-
-/* RTS buffer header */
-struct vnt_rts_g {
- struct vnt_phy_field b;
- struct vnt_phy_field a;
- __le16 duration_ba;
- __le16 duration_aa;
- __le16 duration_bb;
- u16 reserved;
- struct ieee80211_rts data;
-} __packed __aligned(2);
-
-struct vnt_rts_g_fb {
- struct vnt_phy_field b;
- struct vnt_phy_field a;
- __le16 duration_ba;
- __le16 duration_aa;
- __le16 duration_bb;
- u16 wReserved;
- __le16 rts_duration_ba_f0;
- __le16 rts_duration_aa_f0;
- __le16 rts_duration_ba_f1;
- __le16 rts_duration_aa_f1;
- struct ieee80211_rts data;
-} __packed __aligned(2);
-
-struct vnt_rts_ab {
- struct vnt_phy_field ab;
- __le16 duration;
- u16 reserved;
- struct ieee80211_rts data;
-} __packed __aligned(2);
-
-struct vnt_rts_a_fb {
- struct vnt_phy_field a;
- __le16 duration;
- u16 reserved;
- __le16 rts_duration_f0;
- __le16 rts_duration_f1;
- struct ieee80211_rts data;
-} __packed __aligned(2);
-
-/* CTS buffer header */
-struct vnt_cts {
- struct vnt_phy_field b;
- __le16 duration_ba;
- u16 reserved;
- struct ieee80211_cts data;
- u16 reserved2;
-} __packed __aligned(2);
-
-struct vnt_cts_fb {
- struct vnt_phy_field b;
- __le16 duration_ba;
- u16 reserved;
- __le16 cts_duration_ba_f0;
- __le16 cts_duration_ba_f1;
- struct ieee80211_cts data;
- u16 reserved2;
-} __packed __aligned(2);
-
-struct vnt_tx_fifo_head {
- u8 tx_key[WLAN_KEY_LEN_CCMP];
- __le16 fifo_ctl;
- __le16 time_stamp;
- __le16 frag_ctl;
- __le16 current_rate;
-} __packed;
-
-struct vnt_tx_short_buf_head {
- __le16 fifo_ctl;
- u16 time_stamp;
- struct vnt_phy_field ab;
- __le16 duration;
- __le16 time_stamp_off;
-} __packed;
-
-int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx,
- struct vnt_tx_desc *head_td, struct sk_buff *skb);
-int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif);
-int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf);
-
-#endif /* __RXTX_H__ */
diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c
deleted file mode 100644
index e80556509c58..000000000000
--- a/drivers/staging/vt6655/srom.c
+++ /dev/null
@@ -1,139 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:Implement functions to access eeprom
- *
- * Author: Jerry Chen
- *
- * Date: Jan 29, 2003
- *
- * Functions:
- * SROMbyReadEmbedded - Embedded read eeprom via MAC
- * SROMbWriteEmbedded - Embedded write eeprom via MAC
- * SROMvRegBitsOn - Set Bits On in eeprom
- * SROMvRegBitsOff - Clear Bits Off in eeprom
- * SROMbIsRegBitsOn - Test if Bits On in eeprom
- * SROMbIsRegBitsOff - Test if Bits Off in eeprom
- * SROMvReadAllContents - Read all contents in eeprom
- * SROMvWriteAllContents - Write all contents in eeprom
- * SROMvReadEtherAddress - Read Ethernet Address in eeprom
- * SROMvWriteEtherAddress - Write Ethernet Address in eeprom
- * SROMvReadSubSysVenId - Read Sub_VID and Sub_SysId in eeprom
- * SROMbAutoLoad - Auto Load eeprom to MAC register
- *
- * Revision History:
- *
- */
-
-#include "device.h"
-#include "mac.h"
-#include "srom.h"
-
-/*--------------------- Static Definitions -------------------------*/
-
-/*--------------------- Static Classes ----------------------------*/
-
-/*--------------------- Static Variables --------------------------*/
-
-/*--------------------- Static Functions --------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Export Functions --------------------------*/
-
-/*
- * Description: Read a byte from EEPROM, by MAC I2C
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * contnt_offset - address of EEPROM
- * Out:
- * none
- *
- * Return Value: data read
- *
- */
-unsigned char SROMbyReadEmbedded(void __iomem *iobase,
- unsigned char contnt_offset)
-{
- unsigned short wDelay, wNoACK;
- unsigned char byWait;
- unsigned char byData;
- unsigned char byOrg;
-
- byOrg = ioread8(iobase + MAC_REG_I2MCFG);
- /* turn off hardware retry for getting NACK */
- iowrite8(byOrg & (~I2MCFG_NORETRY), iobase + MAC_REG_I2MCFG);
- for (wNoACK = 0; wNoACK < W_MAX_I2CRETRY; wNoACK++) {
- iowrite8(EEP_I2C_DEV_ID, iobase + MAC_REG_I2MTGID);
- iowrite8(contnt_offset, iobase + MAC_REG_I2MTGAD);
-
- /* issue read command */
- iowrite8(I2MCSR_EEMR, iobase + MAC_REG_I2MCSR);
- /* wait DONE be set */
- for (wDelay = 0; wDelay < W_MAX_TIMEOUT; wDelay++) {
- byWait = ioread8(iobase + MAC_REG_I2MCSR);
- if (byWait & (I2MCSR_DONE | I2MCSR_NACK))
- break;
- udelay(CB_DELAY_LOOP_WAIT);
- }
- if ((wDelay < W_MAX_TIMEOUT) &&
- (!(byWait & I2MCSR_NACK))) {
- break;
- }
- }
- byData = ioread8(iobase + MAC_REG_I2MDIPT);
- iowrite8(byOrg, iobase + MAC_REG_I2MCFG);
- return byData;
-}
-
-/*
- * Description: Read all contents of eeprom to buffer
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * Out:
- * pbyEepromRegs - EEPROM content Buffer
- *
- * Return Value: none
- *
- */
-void SROMvReadAllContents(void __iomem *iobase, unsigned char *pbyEepromRegs)
-{
- int ii;
-
- /* ii = Rom Address */
- for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) {
- *pbyEepromRegs = SROMbyReadEmbedded(iobase,
- (unsigned char)ii);
- pbyEepromRegs++;
- }
-}
-
-/*
- * Description: Read Ethernet Address from eeprom to buffer
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * Out:
- * pbyEtherAddress - Ethernet Address buffer
- *
- * Return Value: none
- *
- */
-void SROMvReadEtherAddress(void __iomem *iobase,
- unsigned char *pbyEtherAddress)
-{
- unsigned char ii;
-
- /* ii = Rom Address */
- for (ii = 0; ii < ETH_ALEN; ii++) {
- *pbyEtherAddress = SROMbyReadEmbedded(iobase, ii);
- pbyEtherAddress++;
- }
-}
diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h
deleted file mode 100644
index b03073ffa18a..000000000000
--- a/drivers/staging/vt6655/srom.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions to access eeprom
- *
- * Author: Jerry Chen
- *
- * Date: Jan 29, 2003
- */
-
-#ifndef __SROM_H__
-#define __SROM_H__
-
-/*--------------------- Export Definitions -------------------------*/
-
-#define EEP_MAX_CONTEXT_SIZE 256
-
-#define CB_EEPROM_READBYTE_WAIT 900 /* us */
-
-#define W_MAX_I2CRETRY 0x0fff
-
-/* Contents in the EEPROM */
-#define EEP_OFS_PAR 0x00 /* physical address */
-#define EEP_OFS_ANTENNA 0x16
-#define EEP_OFS_RADIOCTL 0x17
-#define EEP_OFS_RFTYPE 0x1B /* for select RF */
-#define EEP_OFS_MINCHANNEL 0x1C /* Min Channel # */
-#define EEP_OFS_MAXCHANNEL 0x1D /* Max Channel # */
-#define EEP_OFS_SIGNATURE 0x1E
-#define EEP_OFS_ZONETYPE 0x1F
-#define EEP_OFS_RFTABLE 0x20 /* RF POWER TABLE */
-#define EEP_OFS_PWR_CCK 0x20
-#define EEP_OFS_SETPT_CCK 0x21
-#define EEP_OFS_PWR_OFDMG 0x23
-#define EEP_OFS_SETPT_OFDMG 0x24
-#define EEP_OFS_PWR_FORMULA_OST 0x26
-#define EEP_OFS_MAJOR_VER 0x2E
-#define EEP_OFS_MINOR_VER 0x2F
-#define EEP_OFS_CCK_PWR_TBL 0x30
-#define EEP_OFS_CCK_PWR_dBm 0x3F
-#define EEP_OFS_OFDM_PWR_TBL 0x40
-#define EEP_OFS_OFDM_PWR_dBm 0x4F
-/*{{ RobertYu: 20041124 */
-#define EEP_OFS_SETPT_OFDMA 0x4E
-#define EEP_OFS_OFDMA_PWR_TBL 0x50
-/*}}*/
-#define EEP_OFS_OFDMA_PWR_dBm 0xD2
-
-/*----------need to remove --------------------*/
-#define EEP_OFS_BBTAB_LEN 0x70 /* BB Table Length */
-#define EEP_OFS_BBTAB_ADR 0x71 /* BB Table Offset */
-#define EEP_OFS_CHECKSUM 0xFF /* reserved area for baseband 28h~78h */
-
-#define EEP_I2C_DEV_ID 0x50 /* EEPROM device address on I2C bus */
-
-/* Bits in EEP_OFS_ANTENNA */
-#define EEP_ANTENNA_MAIN 0x01
-#define EEP_ANTENNA_AUX 0x02
-#define EEP_ANTINV 0x04
-
-/* Bits in EEP_OFS_RADIOCTL */
-#define EEP_RADIOCTL_ENABLE 0x80
-#define EEP_RADIOCTL_INV 0x01
-
-/*--------------------- Export Types ------------------------------*/
-
-/*--------------------- Export Macros ------------------------------*/
-
-/*--------------------- Export Classes ----------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Export Functions --------------------------*/
-
-unsigned char SROMbyReadEmbedded(void __iomem *iobase,
- unsigned char byContntOffset);
-
-void SROMvReadAllContents(void __iomem *iobase, unsigned char *pbyEepromRegs);
-
-void SROMvReadEtherAddress(void __iomem *iobase,
- unsigned char *pbyEtherAddress);
-
-#endif /* __EEPROM_H__*/
diff --git a/drivers/staging/vt6655/test b/drivers/staging/vt6655/test
deleted file mode 100644
index ba6dec774478..000000000000
--- a/drivers/staging/vt6655/test
+++ /dev/null
@@ -1,9 +0,0 @@
-KSP := /lib/modules/$(shell uname -r)/build \
- /usr/src/linux-$(shell uname -r) \
- /usr/src/linux-$(shell uname -r | sed 's/-.*//') \
-# /usr/src/kernel-headers-$(shell uname -r) \
-# /usr/src/kernel-source-$(shell uname -r) \
-# /usr/src/linux-$(shell uname -r | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \
-# /usr/src/linux /home/plice
-test_dir = $(shell [ -e $(dir)/include/linux ] && echo $(dir))
-KSP := $(foreach dir, $(KSP), $(test_dir))
diff --git a/drivers/staging/vt6656/Kconfig b/drivers/staging/vt6656/Kconfig
deleted file mode 100644
index f52a3f1d9a2e..000000000000
--- a/drivers/staging/vt6656/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config VT6656
- tristate "VIA Technologies VT6656 support"
- depends on MAC80211 && USB && WLAN && m
- select FW_LOADER
- help
- This is a vendor-written driver for VIA VT6656.
diff --git a/drivers/staging/vt6656/Makefile b/drivers/staging/vt6656/Makefile
deleted file mode 100644
index f696a9d7a143..000000000000
--- a/drivers/staging/vt6656/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-vt6656_stage-y += main_usb.o \
- card.o \
- mac.o \
- baseband.o \
- wcmd.o\
- rxtx.o \
- power.o \
- key.o \
- rf.o \
- usbpipe.o \
- channel.o
-
-obj-$(CONFIG_VT6656) += vt6656_stage.o
diff --git a/drivers/staging/vt6656/TODO b/drivers/staging/vt6656/TODO
deleted file mode 100644
index cca78d2d3cfe..000000000000
--- a/drivers/staging/vt6656/TODO
+++ /dev/null
@@ -1,17 +0,0 @@
-TODO:
-- remove __cplusplus ifdefs -- done
-- remove kernel version compatibility wrappers
-- remove support for older wireless extensions
-- prepare for merge with vt6655 driver:
- - remove PRINT_K() macro
- - split rf.c
- - abstract VT3184 chipset specific code
-- add common vt665x infrastructure
-- kill ttype.h -- done
-- switch to use MAC80211
-- use kernel coding style
-- sparse fixes
-- integrate with drivers/net/wireless
-
-Please send any patches to Greg Kroah-Hartman <greg@kroah.com>
-and Forest Bond <forest@alittletooquiet.net>.
diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c
deleted file mode 100644
index ad7b963f0d98..000000000000
--- a/drivers/staging/vt6656/baseband.c
+++ /dev/null
@@ -1,455 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions to access baseband
- *
- * Author: Jerry Chen
- *
- * Date: Jun. 5, 2002
- *
- * Functions:
- * vnt_get_frame_time - Calculate data frame transmitting time
- * vnt_get_phy_field - Calculate PhyLength, PhyService and Phy
- * Signal parameter for baseband Tx
- * vnt_vt3184_init - VIA VT3184 baseband chip init code
- *
- * Revision History:
- *
- *
- */
-
-#include <linux/bits.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include "device.h"
-#include "mac.h"
-#include "baseband.h"
-#include "rf.h"
-#include "usbpipe.h"
-
-static const u8 vnt_vt3184_agc[] = {
- 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x06, 0x06,
- 0x08, 0x08, 0x0a, 0x0a, 0x0c, 0x0c, 0x0e, 0x0e, /* 0x0f */
- 0x10, 0x10, 0x12, 0x12, 0x14, 0x14, 0x16, 0x16,
- 0x18, 0x18, 0x1a, 0x1a, 0x1c, 0x1c, 0x1e, 0x1e, /* 0x1f */
- 0x20, 0x20, 0x22, 0x22, 0x24, 0x24, 0x26, 0x26,
- 0x28, 0x28, 0x2a, 0x2a, 0x2c, 0x2c, 0x2e, 0x2e, /* 0x2f */
- 0x30, 0x30, 0x32, 0x32, 0x34, 0x34, 0x36, 0x36,
- 0x38, 0x38, 0x3a, 0x3a, 0x3c, 0x3c, 0x3e, 0x3e /* 0x3f */
-};
-
-static u8 vnt_vt3184_al2230[] = {
- 0x31, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
- 0x70, 0x45, 0x2a, 0x76, 0x00, 0x00, 0x80, 0x00, /* 0x0f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x8e, 0x0a, 0x00, 0x00, 0x00, /* 0x1f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x0c, /* 0x2f */
- 0x26, 0x5b, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa,
- 0xff, 0xff, 0x79, 0x00, 0x00, 0x0b, 0x48, 0x04, /* 0x3f */
- 0x00, 0x08, 0x00, 0x08, 0x08, 0x14, 0x05, 0x09,
- 0x00, 0x00, 0x00, 0x00, 0x09, 0x73, 0x00, 0xc5, /* 0x4f */
- 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f */
- 0xe4, 0x80, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0a,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* 0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7f */
- 0x8c, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x1f, 0xb7, 0x88, 0x47, 0xaa, 0x00, /* 0x8f */
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x9f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x18, /* 0xaf */
- 0x38, 0x30, 0x00, 0x00, 0xff, 0x0f, 0xe4, 0xe2,
- 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, /* 0xbf */
- 0x18, 0x20, 0x07, 0x18, 0xff, 0xff, 0x0e, 0x0a,
- 0x0e, 0x00, 0x82, 0xa7, 0x3c, 0x10, 0x30, 0x05, /* 0xcf */
- 0x40, 0x12, 0x00, 0x00, 0x10, 0x28, 0x80, 0x2a,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf */
- 0x00, 0xf3, 0x00, 0x00, 0x00, 0x10, 0x00, 0x12,
- 0x00, 0xf4, 0x00, 0xff, 0x79, 0x20, 0x30, 0x05, /* 0xef */
- 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xff */
-};
-
-/* {{RobertYu:20060515, new BB setting for VT3226D0 */
-static const u8 vnt_vt3184_vt3226d0[] = {
- 0x31, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
- 0x70, 0x45, 0x2a, 0x76, 0x00, 0x00, 0x80, 0x00, /* 0x0f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x8e, 0x0a, 0x00, 0x00, 0x00, /* 0x1f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x0c, /* 0x2f */
- 0x26, 0x5b, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa,
- 0xff, 0xff, 0x79, 0x00, 0x00, 0x0b, 0x48, 0x04, /* 0x3f */
- 0x00, 0x08, 0x00, 0x08, 0x08, 0x14, 0x05, 0x09,
- 0x00, 0x00, 0x00, 0x00, 0x09, 0x73, 0x00, 0xc5, /* 0x4f */
- 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f */
- 0xe4, 0x80, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0a,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* 0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7f */
- 0x8c, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x1f, 0xb7, 0x88, 0x47, 0xaa, 0x00, /* 0x8f */
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x9f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, /* 0xaf */
- 0x38, 0x30, 0x00, 0x00, 0xff, 0x0f, 0xe4, 0xe2,
- 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, /* 0xbf */
- 0x18, 0x20, 0x07, 0x18, 0xff, 0xff, 0x10, 0x0a,
- 0x0e, 0x00, 0x84, 0xa7, 0x3c, 0x10, 0x24, 0x05, /* 0xcf */
- 0x40, 0x12, 0x00, 0x00, 0x10, 0x28, 0x80, 0x2a,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf */
- 0x00, 0xf3, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10,
- 0x00, 0xf4, 0x00, 0xff, 0x79, 0x20, 0x30, 0x08, /* 0xef */
- 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xff */
-};
-
-struct vnt_threshold {
- u8 bb_pre_ed_rssi;
- u8 cr_201;
- u8 cr_206;
-};
-
-static const struct vnt_threshold al2230_vnt_threshold[] = {
- {0, 0x00, 0x30}, /* Max sensitivity */
- {68, 0x00, 0x36},
- {67, 0x00, 0x43},
- {66, 0x00, 0x51},
- {65, 0x00, 0x62},
- {64, 0x00, 0x79},
- {63, 0x00, 0x93},
- {62, 0x00, 0xb9},
- {61, 0x00, 0xe3},
- {60, 0x01, 0x18},
- {59, 0x01, 0x54},
- {58, 0x01, 0xa0},
- {57, 0x02, 0x20},
- {56, 0x02, 0xa0},
- {55, 0x03, 0x00},
- {53, 0x06, 0x00},
- {51, 0x09, 0x00},
- {49, 0x0e, 0x00},
- {47, 0x15, 0x00},
- {46, 0x1a, 0x00},
- {45, 0xff, 0x00}
-};
-
-static const struct vnt_threshold vt3226_vnt_threshold[] = {
- {0, 0x00, 0x24}, /* Max sensitivity */
- {68, 0x00, 0x2d},
- {67, 0x00, 0x36},
- {66, 0x00, 0x43},
- {65, 0x00, 0x52},
- {64, 0x00, 0x68},
- {63, 0x00, 0x80},
- {62, 0x00, 0x9c},
- {61, 0x00, 0xc0},
- {60, 0x00, 0xea},
- {59, 0x01, 0x30},
- {58, 0x01, 0x70},
- {57, 0x01, 0xb0},
- {56, 0x02, 0x30},
- {55, 0x02, 0xc0},
- {53, 0x04, 0x00},
- {51, 0x07, 0x00},
- {49, 0x0a, 0x00},
- {47, 0x11, 0x00},
- {45, 0x18, 0x00},
- {43, 0x26, 0x00},
- {42, 0x36, 0x00},
- {41, 0xff, 0x00}
-};
-
-/*
- * Description: Set Antenna mode
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * antenna_mode - Antenna Mode
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-int vnt_set_antenna_mode(struct vnt_private *priv, u8 antenna_mode)
-{
- switch (antenna_mode) {
- case ANT_TXA:
- case ANT_TXB:
- break;
- case ANT_RXA:
- priv->bb_rx_conf &= 0xFC;
- break;
- case ANT_RXB:
- priv->bb_rx_conf &= 0xFE;
- priv->bb_rx_conf |= 0x02;
- break;
- }
-
- return vnt_control_out(priv, MESSAGE_TYPE_SET_ANTMD,
- (u16)antenna_mode, 0, 0, NULL);
-}
-
-/*
- * Description: Set Antenna mode
- *
- * Parameters:
- * In:
- * pDevice - Device Structure
- * byAntennaMode - Antenna Mode
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-
-int vnt_vt3184_init(struct vnt_private *priv)
-{
- int ret;
- u16 length;
- u8 *addr = NULL;
- const u8 *c_addr;
- u8 data;
-
- ret = vnt_control_in(priv, MESSAGE_TYPE_READ, 0, MESSAGE_REQUEST_EEPROM,
- EEP_MAX_CONTEXT_SIZE, priv->eeprom);
- if (ret)
- goto end;
-
- priv->rf_type = priv->eeprom[EEP_OFS_RFTYPE];
-
- dev_dbg(&priv->usb->dev, "RF Type %d\n", priv->rf_type);
-
- if ((priv->rf_type == RF_AL2230) ||
- (priv->rf_type == RF_AL2230S)) {
- priv->bb_rx_conf = vnt_vt3184_al2230[10];
- length = sizeof(vnt_vt3184_al2230);
- addr = vnt_vt3184_al2230;
-
- priv->bb_vga[0] = 0x1c;
- priv->bb_vga[1] = 0x10;
- priv->bb_vga[2] = 0x0;
- priv->bb_vga[3] = 0x0;
-
- } else if ((priv->rf_type == RF_VT3226) ||
- (priv->rf_type == RF_VT3226D0)) {
- priv->bb_rx_conf = vnt_vt3184_vt3226d0[10];
- length = sizeof(vnt_vt3184_vt3226d0);
- c_addr = vnt_vt3184_vt3226d0;
-
- priv->bb_vga[0] = 0x20;
- priv->bb_vga[1] = 0x10;
- priv->bb_vga[2] = 0x0;
- priv->bb_vga[3] = 0x0;
-
- /* Fix VT3226 DFC system timing issue */
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL2,
- SOFTPWRCTL_RFLEOPT);
- if (ret)
- goto end;
- } else {
- goto end;
- }
-
- if (addr)
- c_addr = addr;
-
- ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
- MESSAGE_REQUEST_BBREG, length, c_addr);
- if (ret)
- goto end;
-
- ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
- MESSAGE_REQUEST_BBAGC,
- sizeof(vnt_vt3184_agc), vnt_vt3184_agc);
- if (ret)
- goto end;
-
- if ((priv->rf_type == RF_VT3226) ||
- (priv->rf_type == RF_VT3226D0)) {
- data = (priv->rf_type == RF_VT3226D0) ? 0x11 : 0x23;
-
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG,
- MAC_REG_ITRTMSET, data);
- if (ret)
- goto end;
-
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_PAPEDELAY, BIT(0));
- if (ret)
- goto end;
- }
-
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x04, 0x7f);
- if (ret)
- goto end;
-
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0x01);
- if (ret)
- goto end;
-
- ret = vnt_rf_table_download(priv);
- if (ret)
- goto end;
-
- /* Fix for TX USB resets from vendors driver */
- ret = vnt_control_in(priv, MESSAGE_TYPE_READ, USB_REG4,
- MESSAGE_REQUEST_MEM, sizeof(data), &data);
- if (ret)
- goto end;
-
- data |= 0x2;
-
- ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, USB_REG4,
- MESSAGE_REQUEST_MEM, sizeof(data), &data);
-
-end:
- return ret;
-}
-
-/*
- * Description: Set ShortSlotTime mode
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-int vnt_set_short_slot_time(struct vnt_private *priv)
-{
- int ret = 0;
- u8 bb_vga = 0;
-
- if (priv->short_slot_time)
- priv->bb_rx_conf &= 0xdf;
- else
- priv->bb_rx_conf |= 0x20;
-
- ret = vnt_control_in_u8(priv, MESSAGE_REQUEST_BBREG, 0xe7, &bb_vga);
- if (ret)
- return ret;
-
- if (bb_vga == priv->bb_vga[0])
- priv->bb_rx_conf |= 0x20;
-
- return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0a,
- priv->bb_rx_conf);
-}
-
-int vnt_set_vga_gain_offset(struct vnt_private *priv, u8 data)
-{
- int ret;
-
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xE7, data);
- if (ret)
- return ret;
-
- /* patch for 3253B0 Baseband with Cardbus module */
- if (priv->short_slot_time)
- priv->bb_rx_conf &= 0xdf; /* 1101 1111 */
- else
- priv->bb_rx_conf |= 0x20; /* 0010 0000 */
-
- return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0a,
- priv->bb_rx_conf);
-}
-
-/*
- * Description: vnt_set_deep_sleep
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-int vnt_set_deep_sleep(struct vnt_private *priv)
-{
- int ret = 0;
-
- /* CR12 */
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0c, 0x17);
- if (ret)
- return ret;
-
- /* CR13 */
- return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0xB9);
-}
-
-int vnt_exit_deep_sleep(struct vnt_private *priv)
-{
- int ret = 0;
-
- /* CR12 */
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0c, 0x00);
- if (ret)
- return ret;
-
- /* CR13 */
- return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0x01);
-}
-
-int vnt_update_pre_ed_threshold(struct vnt_private *priv, int scanning)
-{
- const struct vnt_threshold *threshold = NULL;
- u8 length;
- u8 cr_201, cr_206;
- u8 ed_inx;
- int ret;
-
- switch (priv->rf_type) {
- case RF_AL2230:
- case RF_AL2230S:
- threshold = al2230_vnt_threshold;
- length = ARRAY_SIZE(al2230_vnt_threshold);
- break;
-
- case RF_VT3226:
- case RF_VT3226D0:
- threshold = vt3226_vnt_threshold;
- length = ARRAY_SIZE(vt3226_vnt_threshold);
- break;
- }
-
- if (!threshold)
- return -EINVAL;
-
- for (ed_inx = scanning ? 0 : length - 1; ed_inx > 0; ed_inx--) {
- if (priv->bb_pre_ed_rssi <= threshold[ed_inx].bb_pre_ed_rssi)
- break;
- }
-
- cr_201 = threshold[ed_inx].cr_201;
- cr_206 = threshold[ed_inx].cr_206;
-
- if (ed_inx == priv->bb_pre_ed_index && !scanning)
- return 0;
-
- priv->bb_pre_ed_index = ed_inx;
-
- dev_dbg(&priv->usb->dev, "%s bb_pre_ed_rssi %d\n",
- __func__, priv->bb_pre_ed_rssi);
-
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xc9, cr_201);
- if (ret)
- return ret;
-
- return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xce, cr_206);
-}
-
diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h
deleted file mode 100644
index dce50a311f24..000000000000
--- a/drivers/staging/vt6656/baseband.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions to access baseband
- *
- * Author: Jerry Chen
- *
- * Date: Jun. 5, 2002
- *
- * Revision History:
- * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
- * 08-26-2003 Kyle Hsu : Add defines of packet type and TX rate.
- */
-
-#ifndef __BASEBAND_H__
-#define __BASEBAND_H__
-
-#include "device.h"
-
-#define PREAMBLE_LONG 0
-#define PREAMBLE_SHORT 1
-
-/*
- * Registers in the BASEBAND
- */
-#define BB_MAX_CONTEXT_SIZE 256
-
-#define C_SIFS_A 16 /* usec */
-#define C_SIFS_BG 10
-
-#define C_EIFS 80 /* usec */
-
-#define C_SLOT_SHORT 9 /* usec */
-#define C_SLOT_LONG 20
-
-#define C_CWMIN_A 15 /* slot time */
-#define C_CWMIN_B 31
-
-#define C_CWMAX 1023 /* slot time */
-
-/* 0:11A 1:11B 2:11G */
-#define BB_TYPE_11A 0
-#define BB_TYPE_11B 1
-#define BB_TYPE_11G 2
-
-/* 0:11a, 1:11b, 2:11gb (only CCK in BasicRate), 3:11ga (OFDM in BasicRate) */
-#define PK_TYPE_11A 0
-#define PK_TYPE_11B 1
-#define PK_TYPE_11GB 2
-#define PK_TYPE_11GA 3
-
-#define TOP_RATE_54M 0x80000000
-#define TOP_RATE_48M 0x40000000
-#define TOP_RATE_36M 0x20000000
-#define TOP_RATE_24M 0x10000000
-#define TOP_RATE_18M 0x08000000
-#define TOP_RATE_12M 0x04000000
-#define TOP_RATE_11M 0x02000000
-#define TOP_RATE_9M 0x01000000
-#define TOP_RATE_6M 0x00800000
-#define TOP_RATE_55M 0x00400000
-#define TOP_RATE_2M 0x00200000
-#define TOP_RATE_1M 0x00100000
-
-int vnt_set_short_slot_time(struct vnt_private *priv);
-int vnt_set_vga_gain_offset(struct vnt_private *priv, u8 data);
-int vnt_set_antenna_mode(struct vnt_private *priv, u8 antenna_mode);
-int vnt_vt3184_init(struct vnt_private *priv);
-int vnt_set_deep_sleep(struct vnt_private *priv);
-int vnt_exit_deep_sleep(struct vnt_private *priv);
-int vnt_update_pre_ed_threshold(struct vnt_private *priv, int scanning);
-
-#endif /* __BASEBAND_H__ */
diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c
deleted file mode 100644
index b9dc0d13c00c..000000000000
--- a/drivers/staging/vt6656/card.c
+++ /dev/null
@@ -1,456 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Provide functions to setup NIC operation mode
- * Functions:
- * vnt_set_rspinf - Set RSPINF
- * vnt_update_ifs - Update slotTime,SIFS,DIFS, and EIFS
- * vnt_update_top_rates - Update BasicTopRate
- * vnt_add_basic_rate - Add to BasicRateSet
- * vnt_ofdm_min_rate - Check if any OFDM rate is in BasicRateSet
- * vnt_get_tsf_offset - Calculate TSFOffset
- * vnt_get_next_tbtt - Calculate Next Beacon TSF counter
- * vnt_reset_next_tbtt - Set NIC Beacon time
- * vnt_update_next_tbtt - Sync. NIC Beacon time
- * vnt_radio_power_off - Turn Off NIC Radio Power
- * vnt_radio_power_on - Turn On NIC Radio Power
- *
- * Revision History:
- * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
- * 08-26-2003 Kyle Hsu: Modify the definition type of dwIoBase.
- * 09-01-2003 Bryan YC Fan: Add vnt_update_ifs().
- *
- */
-
-#include <linux/bitops.h>
-#include <linux/errno.h>
-#include "device.h"
-#include "card.h"
-#include "baseband.h"
-#include "mac.h"
-#include "desc.h"
-#include "rf.h"
-#include "power.h"
-#include "key.h"
-#include "usbpipe.h"
-
-/* const u16 cw_rxbcntsf_off[MAX_RATE] =
- * {17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3};
- */
-
-static const u16 cw_rxbcntsf_off[MAX_RATE] = {
- 192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3
-};
-
-int vnt_set_channel(struct vnt_private *priv, u32 connection_channel)
-{
- int ret;
-
- if (connection_channel > CB_MAX_CHANNEL || !connection_channel)
- return -EINVAL;
-
- /* clear NAV */
- vnt_mac_reg_bits_on(priv, MAC_REG_MACCR, MACCR_CLRNAV);
-
- /* Set Channel[7] = 0 to tell H/W channel is changing now. */
- vnt_mac_reg_bits_off(priv, MAC_REG_CHANNEL,
- (BIT(7) | BIT(5) | BIT(4)));
-
- ret = vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNEL,
- connection_channel, 0, 0, NULL);
- if (ret)
- return ret;
-
- return vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_CHANNEL,
- (u8)(connection_channel | 0x80));
-}
-
-static const u8 vnt_rspinf_b_short_table[] = {
- 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x09, 0x00,
- 0x15, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0b, 0x80
-};
-
-static const u8 vnt_rspinf_b_long_table[] = {
- 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00,
- 0x15, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x03, 0x80
-};
-
-static const u8 vnt_rspinf_a_table[] = {
- 0x9b, 0x18, 0x9f, 0x10, 0x9a, 0x0a, 0x9e, 0x08, 0x99,
- 0x08, 0x9d, 0x04, 0x98, 0x04, 0x9c, 0x04, 0x9c, 0x04
-};
-
-static const u8 vnt_rspinf_gb_table[] = {
- 0x8b, 0x1e, 0x8f, 0x16, 0x8a, 0x12, 0x8e, 0x0e, 0x89,
- 0x0e, 0x8d, 0x0a, 0x88, 0x0a, 0x8c, 0x0a, 0x8c, 0x0a
-};
-
-int vnt_set_rspinf(struct vnt_private *priv, u8 bb_type)
-{
- const u8 *data;
- u16 len;
- int ret;
-
- if (priv->preamble_type) {
- data = vnt_rspinf_b_short_table;
- len = ARRAY_SIZE(vnt_rspinf_b_short_table);
- } else {
- data = vnt_rspinf_b_long_table;
- len = ARRAY_SIZE(vnt_rspinf_b_long_table);
- }
-
- /* RSPINF_b_1 to RSPINF_b_11 */
- ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_B_1,
- MESSAGE_REQUEST_MACREG, len, data);
- if (ret)
- return ret;
-
- if (bb_type == BB_TYPE_11A) {
- data = vnt_rspinf_a_table;
- len = ARRAY_SIZE(vnt_rspinf_a_table);
- } else {
- data = vnt_rspinf_gb_table;
- len = ARRAY_SIZE(vnt_rspinf_gb_table);
- }
-
- /* RSPINF_a_6 to RSPINF_a_72 */
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_A_6,
- MESSAGE_REQUEST_MACREG, len, data);
-}
-
-int vnt_update_ifs(struct vnt_private *priv)
-{
- u8 max_min = 0;
- u8 data[4];
- int ret;
-
- if (priv->packet_type == PK_TYPE_11A) {
- priv->slot = C_SLOT_SHORT;
- priv->sifs = C_SIFS_A;
- priv->difs = C_SIFS_A + 2 * C_SLOT_SHORT;
- max_min = 4;
- } else {
- priv->sifs = C_SIFS_BG;
-
- if (priv->short_slot_time) {
- priv->slot = C_SLOT_SHORT;
- max_min = 4;
- } else {
- priv->slot = C_SLOT_LONG;
- max_min = 5;
- }
-
- priv->difs = C_SIFS_BG + 2 * priv->slot;
- }
-
- priv->eifs = C_EIFS;
-
- data[0] = (u8)priv->sifs;
- data[1] = (u8)priv->difs;
- data[2] = (u8)priv->eifs;
- data[3] = (u8)priv->slot;
-
- ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_SIFS,
- MESSAGE_REQUEST_MACREG, 4, &data[0]);
- if (ret)
- return ret;
-
- max_min |= 0xa0;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_CWMAXMIN0,
- MESSAGE_REQUEST_MACREG, 1, &max_min);
-}
-
-void vnt_update_top_rates(struct vnt_private *priv)
-{
- int pos;
-
- pos = fls(priv->basic_rates & GENMASK(RATE_54M, RATE_6M));
- priv->top_ofdm_basic_rate = pos ? (pos - 1) : RATE_24M;
-
- pos = fls(priv->basic_rates & GENMASK(RATE_11M, RATE_1M));
- priv->top_cck_basic_rate = pos ? (pos - 1) : RATE_1M;
-}
-
-bool vnt_ofdm_min_rate(struct vnt_private *priv)
-{
- return priv->basic_rates & GENMASK(RATE_54M, RATE_6M) ? true : false;
-}
-
-u8 vnt_get_pkt_type(struct vnt_private *priv)
-{
- if (priv->bb_type == BB_TYPE_11A || priv->bb_type == BB_TYPE_11B)
- return (u8)priv->bb_type;
- else if (vnt_ofdm_min_rate(priv))
- return PK_TYPE_11GA;
- return PK_TYPE_11GB;
-}
-
-/*
- * Description: Calculate TSF offset of two TSF input
- * Get TSF Offset from RxBCN's TSF and local TSF
- *
- * Parameters:
- * In:
- * rx_rate - rx rate.
- * tsf1 - Rx BCN's TSF
- * tsf2 - Local TSF
- * Out:
- * none
- *
- * Return Value: TSF Offset value
- *
- */
-u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2)
-{
- return tsf1 - tsf2 - (u64)cw_rxbcntsf_off[rx_rate % MAX_RATE];
-}
-
-int vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate,
- u64 time_stamp, u64 local_tsf)
-{
- u64 tsf_offset = 0;
- u8 data[8];
-
- tsf_offset = vnt_get_tsf_offset(rx_rate, time_stamp, local_tsf);
-
- data[0] = (u8)tsf_offset;
- data[1] = (u8)(tsf_offset >> 8);
- data[2] = (u8)(tsf_offset >> 16);
- data[3] = (u8)(tsf_offset >> 24);
- data[4] = (u8)(tsf_offset >> 32);
- data[5] = (u8)(tsf_offset >> 40);
- data[6] = (u8)(tsf_offset >> 48);
- data[7] = (u8)(tsf_offset >> 56);
-
- return vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT,
- MESSAGE_REQUEST_TSF, 0, 8, data);
-}
-
-/*
- * Description: Clear NIC TSF counter
- * Clear local TSF counter
- *
- * Parameters:
- * In:
- * priv - The adapter to be read
- *
- * Return Value: true if success; otherwise false
- *
- */
-bool vnt_clear_current_tsf(struct vnt_private *priv)
-{
- vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
-
- priv->current_tsf = 0;
-
- return true;
-}
-
-/*
- * Description: Read NIC TSF counter
- * Get NEXTTBTT from adjusted TSF and Beacon Interval
- *
- * Parameters:
- * In:
- * tsf - Current TSF counter
- * beacon_interval - Beacon Interval
- * Out:
- * tsf - Current TSF counter
- *
- * Return Value: TSF value of next Beacon
- *
- */
-u64 vnt_get_next_tbtt(u64 tsf, u16 beacon_interval)
-{
- u32 beacon_int;
-
- beacon_int = beacon_interval * 1024;
-
- /* Next TBTT =
- * ((local_current_TSF / beacon_interval) + 1) * beacon_interval
- */
- if (beacon_int) {
- do_div(tsf, beacon_int);
- tsf += 1;
- tsf *= beacon_int;
- }
-
- return tsf;
-}
-
-int vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval)
-{
- u64 next_tbtt = 0;
- u8 data[8];
-
- vnt_clear_current_tsf(priv);
-
- next_tbtt = vnt_get_next_tbtt(next_tbtt, beacon_interval);
-
- data[0] = (u8)next_tbtt;
- data[1] = (u8)(next_tbtt >> 8);
- data[2] = (u8)(next_tbtt >> 16);
- data[3] = (u8)(next_tbtt >> 24);
- data[4] = (u8)(next_tbtt >> 32);
- data[5] = (u8)(next_tbtt >> 40);
- data[6] = (u8)(next_tbtt >> 48);
- data[7] = (u8)(next_tbtt >> 56);
-
- return vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT,
- MESSAGE_REQUEST_TBTT, 0, 8, data);
-}
-
-int vnt_update_next_tbtt(struct vnt_private *priv, u64 tsf,
- u16 beacon_interval)
-{
- u8 data[8];
- int ret;
-
- tsf = vnt_get_next_tbtt(tsf, beacon_interval);
-
- data[0] = (u8)tsf;
- data[1] = (u8)(tsf >> 8);
- data[2] = (u8)(tsf >> 16);
- data[3] = (u8)(tsf >> 24);
- data[4] = (u8)(tsf >> 32);
- data[5] = (u8)(tsf >> 40);
- data[6] = (u8)(tsf >> 48);
- data[7] = (u8)(tsf >> 56);
-
- ret = vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT,
- MESSAGE_REQUEST_TBTT, 0, 8, data);
- if (ret)
- return ret;
-
- dev_dbg(&priv->usb->dev, "%s TBTT: %8llx\n", __func__, tsf);
- return 0;
-}
-
-/*
- * Description: Turn off Radio power
- *
- * Parameters:
- * In:
- * priv - The adapter to be turned off
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-int vnt_radio_power_off(struct vnt_private *priv)
-{
- int ret = 0;
-
- switch (priv->rf_type) {
- case RF_AL2230:
- case RF_AL2230S:
- case RF_VT3226:
- case RF_VT3226D0:
- ret = vnt_mac_reg_bits_off(priv, MAC_REG_SOFTPWRCTL,
- (SOFTPWRCTL_SWPE2 |
- SOFTPWRCTL_SWPE3));
- break;
- }
-
- if (ret)
- goto end;
-
- ret = vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_RXON);
- if (ret)
- goto end;
-
- ret = vnt_set_deep_sleep(priv);
- if (ret)
- goto end;
-
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD);
-
-end:
- return ret;
-}
-
-/*
- * Description: Turn on Radio power
- *
- * Parameters:
- * In:
- * priv - The adapter to be turned on
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-int vnt_radio_power_on(struct vnt_private *priv)
-{
- int ret = 0;
-
- ret = vnt_exit_deep_sleep(priv);
- if (ret)
- return ret;
-
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_RXON);
- if (ret)
- return ret;
-
- switch (priv->rf_type) {
- case RF_AL2230:
- case RF_AL2230S:
- case RF_VT3226:
- case RF_VT3226D0:
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL,
- (SOFTPWRCTL_SWPE2 |
- SOFTPWRCTL_SWPE3));
- if (ret)
- return ret;
- }
-
- return vnt_mac_reg_bits_off(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD);
-}
-
-int vnt_set_bss_mode(struct vnt_private *priv)
-{
- int ret;
- unsigned char type = priv->bb_type;
- unsigned char data = 0;
- unsigned char bb_vga_2_3 = 0x00;
-
- ret = vnt_mac_set_bb_type(priv, type);
- if (ret)
- return ret;
-
- priv->packet_type = vnt_get_pkt_type(priv);
-
- if (priv->bb_type == BB_TYPE_11A) {
- data = 0x03;
- bb_vga_2_3 = 0x10;
- } else if (priv->bb_type == BB_TYPE_11B) {
- data = 0x02;
- } else if (priv->bb_type == BB_TYPE_11G) {
- data = 0x08;
- }
-
- if (data) {
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG,
- 0x88, data);
- if (ret)
- return ret;
- }
-
- ret = vnt_update_ifs(priv);
- if (ret)
- return ret;
-
- ret = vnt_set_rspinf(priv, priv->bb_type);
- if (ret)
- return ret;
-
- priv->bb_vga[2] = bb_vga_2_3;
- priv->bb_vga[3] = bb_vga_2_3;
-
- return vnt_set_vga_gain_offset(priv, priv->bb_vga[0]);
-}
diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h
deleted file mode 100644
index eb01f7cc871f..000000000000
--- a/drivers/staging/vt6656/card.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Provide functions to setup NIC operation mode
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- */
-
-#ifndef __CARD_H__
-#define __CARD_H__
-#include "device.h"
-
-/* init card type */
-
-#define CB_MAX_CHANNEL_24G 14
-#define CB_MAX_CHANNEL_5G 42 /* add channel9(5045MHz), 41==>42 */
-#define CB_MAX_CHANNEL (CB_MAX_CHANNEL_24G + CB_MAX_CHANNEL_5G)
-
-struct vnt_private;
-
-int vnt_set_channel(struct vnt_private *priv, u32 connection_channel);
-int vnt_set_rspinf(struct vnt_private *priv, u8 bb_type);
-int vnt_update_ifs(struct vnt_private *priv);
-void vnt_update_top_rates(struct vnt_private *priv);
-bool vnt_ofdm_min_rate(struct vnt_private *priv);
-int vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate,
- u64 time_stamp, u64 local_tsf);
-bool vnt_clear_current_tsf(struct vnt_private *priv);
-int vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval);
-int vnt_update_next_tbtt(struct vnt_private *priv, u64 tsf,
- u16 beacon_interval);
-u64 vnt_get_next_tbtt(u64 tsf, u16 beacon_interval);
-u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2);
-int vnt_radio_power_off(struct vnt_private *priv);
-int vnt_radio_power_on(struct vnt_private *priv);
-u8 vnt_get_pkt_type(struct vnt_private *priv);
-int vnt_set_bss_mode(struct vnt_private *priv);
-
-#endif /* __CARD_H__ */
diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c
deleted file mode 100644
index 413e2fc4a50d..000000000000
--- a/drivers/staging/vt6656/channel.c
+++ /dev/null
@@ -1,77 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Channel number mapping
- *
- * Author: Lucas Lin
- *
- * Date: Dec 24, 2004
- *
- *
- *
- * Revision History:
- * 01-18-2005 RobertYu: remove the for loop searching in
- * ChannelValid, change ChannelRuleTab
- * to lookup-type, reorder table items.
- *
- *
- */
-
-#include "device.h"
-#include "channel.h"
-#include "rf.h"
-
-static struct ieee80211_rate vnt_rates_bg[] = {
- { .bitrate = 10, .hw_value = RATE_1M },
- { .bitrate = 20, .hw_value = RATE_2M },
- { .bitrate = 55, .hw_value = RATE_5M },
- { .bitrate = 110, .hw_value = RATE_11M },
- { .bitrate = 60, .hw_value = RATE_6M },
- { .bitrate = 90, .hw_value = RATE_9M },
- { .bitrate = 120, .hw_value = RATE_12M },
- { .bitrate = 180, .hw_value = RATE_18M },
- { .bitrate = 240, .hw_value = RATE_24M },
- { .bitrate = 360, .hw_value = RATE_36M },
- { .bitrate = 480, .hw_value = RATE_48M },
- { .bitrate = 540, .hw_value = RATE_54M },
-};
-
-static struct ieee80211_channel vnt_channels_2ghz[] = {
- { .center_freq = 2412, .hw_value = 1 },
- { .center_freq = 2417, .hw_value = 2 },
- { .center_freq = 2422, .hw_value = 3 },
- { .center_freq = 2427, .hw_value = 4 },
- { .center_freq = 2432, .hw_value = 5 },
- { .center_freq = 2437, .hw_value = 6 },
- { .center_freq = 2442, .hw_value = 7 },
- { .center_freq = 2447, .hw_value = 8 },
- { .center_freq = 2452, .hw_value = 9 },
- { .center_freq = 2457, .hw_value = 10 },
- { .center_freq = 2462, .hw_value = 11 },
- { .center_freq = 2467, .hw_value = 12 },
- { .center_freq = 2472, .hw_value = 13 },
- { .center_freq = 2484, .hw_value = 14 }
-};
-
-static struct ieee80211_supported_band vnt_supported_2ghz_band = {
- .channels = vnt_channels_2ghz,
- .n_channels = ARRAY_SIZE(vnt_channels_2ghz),
- .bitrates = vnt_rates_bg,
- .n_bitrates = ARRAY_SIZE(vnt_rates_bg),
-};
-
-void vnt_init_bands(struct vnt_private *priv)
-{
- struct ieee80211_channel *ch;
- int i;
-
- ch = vnt_channels_2ghz;
- for (i = 0; i < ARRAY_SIZE(vnt_channels_2ghz); i++) {
- ch[i].max_power = VNT_RF_MAX_POWER;
- ch[i].flags = IEEE80211_CHAN_NO_HT40;
- }
- priv->hw->wiphy->bands[NL80211_BAND_2GHZ] =
- &vnt_supported_2ghz_band;
-}
diff --git a/drivers/staging/vt6656/channel.h b/drivers/staging/vt6656/channel.h
deleted file mode 100644
index 723660e40310..000000000000
--- a/drivers/staging/vt6656/channel.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Country Regulation Rules header file
- *
- * Author: Lucas Lin
- *
- * Date: Dec 23, 2004
- *
- */
-
-#ifndef _CHANNEL_H_
-#define _CHANNEL_H_
-
-#include "device.h"
-
-void vnt_init_bands(struct vnt_private *priv);
-
-#endif /* _CHANNEL_H_ */
diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h
deleted file mode 100644
index c13561e528db..000000000000
--- a/drivers/staging/vt6656/desc.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:The header file of descriptor
- *
- * Revision History:
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- */
-
-#ifndef __DESC_H__
-#define __DESC_H__
-
-#include <linux/bits.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-
-/* max transmit or receive buffer size */
-#define CB_MAX_BUF_SIZE 2900U /* NOTE: must be multiple of 4 */
-
-#define MAX_TOTAL_SIZE_WITH_ALL_HEADERS CB_MAX_BUF_SIZE
-
-#define MAX_INTERRUPT_SIZE 32
-
-#define CB_MAX_RX_DESC 128 /* max # of descriptors */
-#define CB_MIN_RX_DESC 16 /* min # of RX descriptors */
-#define CB_MAX_TX_DESC 128 /* max # of descriptors */
-#define CB_MIN_TX_DESC 16 /* min # of TX descriptors */
-
-/*
- * bits in the RSR register
- */
-#define RSR_ADDRBROAD BIT(7)
-#define RSR_ADDRMULTI BIT(6)
-#define RSR_ADDRUNI 0x00
-#define RSR_IVLDTYP BIT(5) /* invalid packet type */
-#define RSR_IVLDLEN BIT(4) /* invalid len (> 2312 byte) */
-#define RSR_BSSIDOK BIT(3)
-#define RSR_CRCOK BIT(2)
-#define RSR_BCNSSIDOK BIT(1)
-#define RSR_ADDROK BIT(0)
-
-/*
- * bits in the new RSR register
- */
-#define NEWRSR_DECRYPTOK BIT(4)
-#define NEWRSR_CFPIND BIT(3)
-#define NEWRSR_HWUTSF BIT(2)
-#define NEWRSR_BCNHITAID BIT(1)
-#define NEWRSR_BCNHITAID0 BIT(0)
-
-/*
- * bits in the TSR register
- */
-#define TSR_RETRYTMO BIT(3)
-#define TSR_TMO BIT(2)
-#define TSR_ACKDATA BIT(1)
-#define TSR_VALID BIT(0)
-
-#define FIFOCTL_AUTO_FB_1 0x1000
-#define FIFOCTL_AUTO_FB_0 0x0800
-#define FIFOCTL_GRPACK 0x0400
-#define FIFOCTL_11GA 0x0300
-#define FIFOCTL_11GB 0x0200
-#define FIFOCTL_11B 0x0100
-#define FIFOCTL_11A 0x0000
-#define FIFOCTL_RTS 0x0080
-#define FIFOCTL_ISDMA0 0x0040
-#define FIFOCTL_GENINT 0x0020
-#define FIFOCTL_TMOEN 0x0010
-#define FIFOCTL_LRETRY 0x0008
-#define FIFOCTL_CRCDIS 0x0004
-#define FIFOCTL_NEEDACK 0x0002
-#define FIFOCTL_LHEAD 0x0001
-
-/* WMAC definition Frag Control */
-#define FRAGCTL_AES 0x0300
-#define FRAGCTL_TKIP 0x0200
-#define FRAGCTL_LEGACY 0x0100
-#define FRAGCTL_NONENCRYPT 0x0000
-#define FRAGCTL_ENDFRAG 0x0003
-#define FRAGCTL_MIDFRAG 0x0002
-#define FRAGCTL_STAFRAG 0x0001
-#define FRAGCTL_NONFRAG 0x0000
-
-#endif /* __DESC_H__ */
diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h
deleted file mode 100644
index ca974d61d3f4..000000000000
--- a/drivers/staging/vt6656/device.h
+++ /dev/null
@@ -1,386 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: MAC Data structure
- *
- * Author: Tevin Chen
- *
- * Date: Mar 17, 1997
- *
- */
-
-#ifndef __DEVICE_H__
-#define __DEVICE_H__
-
-#include <linux/bits.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/suspend.h>
-#include <linux/if_arp.h>
-#include <linux/wireless.h>
-#include <linux/timer.h>
-#include <linux/usb.h>
-#include <linux/crc32.h>
-#include <net/mac80211.h>
-
-#ifdef SIOCETHTOOL
-#define DEVICE_ETHTOOL_IOCTL_SUPPORT
-#include <linux/ethtool.h>
-#else
-#undef DEVICE_ETHTOOL_IOCTL_SUPPORT
-#endif
-
-#define RATE_1M 0
-#define RATE_2M 1
-#define RATE_5M 2
-#define RATE_11M 3
-#define RATE_6M 4
-#define RATE_9M 5
-#define RATE_12M 6
-#define RATE_18M 7
-#define RATE_24M 8
-#define RATE_36M 9
-#define RATE_48M 10
-#define RATE_54M 11
-#define RATE_AUTO 12
-
-#define MAX_RATE 12
-#define VNT_B_RATES (BIT(RATE_1M) | BIT(RATE_2M) |\
- BIT(RATE_5M) | BIT(RATE_11M))
-
-/*
- * device specific
- */
-
-#include "wcmd.h"
-#include "desc.h"
-#include "key.h"
-#include "card.h"
-
-#define VNT_USB_VENDOR_ID 0x160a
-#define VNT_USB_PRODUCT_ID 0x3184
-
-#define DEVICE_NAME "vt6656"
-#define DEVICE_FULL_DRV_NAM "VIA Networking Wireless LAN USB Driver"
-
-#define DEVICE_VERSION "mac80211"
-
-#define FIRMWARE_VERSION 0x133 /* version 1.51 */
-#define FIRMWARE_NAME "vntwusb.fw"
-#define FIRMWARE_CHUNK_SIZE 0x400
-
-#define MAX_UINTS 8
-#define OPTION_DEFAULT { [0 ... MAX_UINTS - 1] = -1}
-
-#define DUPLICATE_RX_CACHE_LENGTH 5
-
-#define AUTO_FB_NONE 0
-#define AUTO_FB_0 1
-#define AUTO_FB_1 2
-
-#define FB_RATE0 0
-#define FB_RATE1 1
-
-/* Antenna Mode */
-#define ANT_A 0
-#define ANT_B 1
-#define ANT_DIVERSITY 2
-#define ANT_RXD_TXA 3
-#define ANT_RXD_TXB 4
-#define ANT_UNKNOWN 0xFF
-#define ANT_TXA 0
-#define ANT_TXB 1
-#define ANT_RXA 2
-#define ANT_RXB 3
-
-#define BB_VGA_LEVEL 4
-#define BB_VGA_CHANGE_THRESHOLD 3
-
-#define EEP_MAX_CONTEXT_SIZE 256
-
-/* Contents in the EEPROM */
-#define EEP_OFS_PAR 0x0
-#define EEP_OFS_ANTENNA 0x17
-#define EEP_OFS_RADIOCTL 0x18
-#define EEP_OFS_RFTYPE 0x1b
-#define EEP_OFS_MINCHANNEL 0x1c
-#define EEP_OFS_MAXCHANNEL 0x1d
-#define EEP_OFS_SIGNATURE 0x1e
-#define EEP_OFS_ZONETYPE 0x1f
-#define EEP_OFS_RFTABLE 0x20
-#define EEP_OFS_PWR_CCK 0x20
-#define EEP_OFS_SETPT_CCK 0x21
-#define EEP_OFS_PWR_OFDMG 0x23
-
-#define EEP_OFS_CALIB_TX_IQ 0x24
-#define EEP_OFS_CALIB_TX_DC 0x25
-#define EEP_OFS_CALIB_RX_IQ 0x26
-
-#define EEP_OFS_MAJOR_VER 0x2e
-#define EEP_OFS_MINOR_VER 0x2f
-
-#define EEP_OFS_CCK_PWR_TBL 0x30
-#define EEP_OFS_OFDM_PWR_TBL 0x40
-#define EEP_OFS_OFDMA_PWR_TBL 0x50
-
-/* Bits in EEP_OFS_ANTENNA */
-#define EEP_ANTENNA_MAIN BIT(0)
-#define EEP_ANTENNA_AUX BIT(1)
-#define EEP_ANTINV BIT(2)
-
-/* Bits in EEP_OFS_RADIOCTL */
-#define EEP_RADIOCTL_ENABLE BIT(7)
-
-/* control commands */
-#define MESSAGE_TYPE_READ 0x1
-#define MESSAGE_TYPE_WRITE 0x0
-#define MESSAGE_TYPE_LOCK_OR 0x2
-#define MESSAGE_TYPE_LOCK_AND 0x3
-#define MESSAGE_TYPE_WRITE_MASK 0x4
-#define MESSAGE_TYPE_CARDINIT 0x5
-#define MESSAGE_TYPE_INIT_RSP 0x6
-#define MESSAGE_TYPE_MACSHUTDOWN 0x7
-#define MESSAGE_TYPE_SETKEY 0x8
-#define MESSAGE_TYPE_CLRKEYENTRY 0x9
-#define MESSAGE_TYPE_WRITE_MISCFF 0xa
-#define MESSAGE_TYPE_SET_ANTMD 0xb
-#define MESSAGE_TYPE_SELECT_CHANNEL 0xc
-#define MESSAGE_TYPE_SET_TSFTBTT 0xd
-#define MESSAGE_TYPE_SET_SSTIFS 0xe
-#define MESSAGE_TYPE_CHANGE_BBTYPE 0xf
-#define MESSAGE_TYPE_DISABLE_PS 0x10
-#define MESSAGE_TYPE_WRITE_IFRF 0x11
-
-/* command read/write(index) */
-#define MESSAGE_REQUEST_MEM 0x1
-#define MESSAGE_REQUEST_BBREG 0x2
-#define MESSAGE_REQUEST_MACREG 0x3
-#define MESSAGE_REQUEST_EEPROM 0x4
-#define MESSAGE_REQUEST_TSF 0x5
-#define MESSAGE_REQUEST_TBTT 0x6
-#define MESSAGE_REQUEST_BBAGC 0x7
-#define MESSAGE_REQUEST_VERSION 0x8
-#define MESSAGE_REQUEST_RF_INIT 0x9
-#define MESSAGE_REQUEST_RF_INIT2 0xa
-#define MESSAGE_REQUEST_RF_CH0 0xb
-#define MESSAGE_REQUEST_RF_CH1 0xc
-#define MESSAGE_REQUEST_RF_CH2 0xd
-
-/* USB registers */
-#define USB_REG4 0x604
-
-#define DEVICE_INIT_COLD 0x0 /* cold init */
-#define DEVICE_INIT_RESET 0x1 /* reset init or Dx to D0 power remain */
-#define DEVICE_INIT_DXPL 0x2 /* Dx to D0 power lost init */
-
-/* Device init */
-struct vnt_cmd_card_init {
- u8 init_class;
- u8 exist_sw_net_addr;
- u8 sw_net_addr[6];
- u8 short_retry_limit;
- u8 long_retry_limit;
-};
-
-struct vnt_rsp_card_init {
- u8 status;
- u8 net_addr[6];
- u8 rf_type;
- u8 min_channel;
- u8 max_channel;
-};
-
-/* USB */
-
-/*
- * Enum of context types for SendPacket
- */
-enum {
- CONTEXT_DATA_PACKET = 0,
- CONTEXT_BEACON_PACKET
-};
-
-struct vnt_rx_header {
- u32 wbk_status;
- u8 rx_sts;
- u8 rx_rate;
- u16 pay_load_len;
-} __packed;
-
-struct vnt_rx_tail {
- __le64 tsf_time;
- u8 sq;
- u8 new_rsr;
- u8 rssi;
- u8 rsr;
- u8 sq_3;
-} __packed;
-
-/* RCB (Receive Control Block) */
-struct vnt_rcb {
- void *priv;
- struct urb *urb;
- struct sk_buff *skb;
-};
-
-/* used to track bulk out irps */
-struct vnt_usb_send_context {
- void *priv;
- struct sk_buff *skb;
- void *tx_buffer;
- u32 frame_len;
- u16 tx_hdr_size;
- u16 tx_rate;
- u8 type;
- u8 pkt_no;
- u8 pkt_type;
- bool in_use;
-};
-
-/*
- * Structure to keep track of USB interrupt packets
- */
-struct vnt_interrupt_buffer {
- u8 *data_buf;
-};
-
-/* flags for options */
-#define DEVICE_FLAGS_UNPLUG 0
-#define DEVICE_FLAGS_DISCONNECTED 1
-
-struct vnt_private {
- /* mac80211 */
- struct ieee80211_hw *hw;
- struct ieee80211_vif *vif;
- u8 mac_hw;
- /* netdev */
- struct usb_device *usb;
- struct usb_interface *intf;
-
- u64 tsf_time;
-
- u32 rx_buf_sz;
- int mc_list_count;
-
- spinlock_t lock; /* prepare tx USB URB */
- struct mutex usb_lock; /* USB control messages */
-
- unsigned long flags;
-
- /* USB */
- struct urb *interrupt_urb;
- u32 int_interval;
-
- /* Variables to track resources for the BULK In Pipe */
- struct vnt_rcb *rcb[CB_MAX_RX_DESC];
- u32 num_rcb;
-
- /* Variables to track resources for the BULK Out Pipe */
- struct vnt_usb_send_context *tx_context[CB_MAX_TX_DESC];
- struct usb_anchor tx_submitted;
- u32 num_tx_context;
-
- /* Variables to track resources for the Interrupt In Pipe */
- struct vnt_interrupt_buffer int_buf;
-
- /* Version control */
- u16 firmware_version;
- u8 local_id;
- u8 rf_type;
- u8 bb_rx_conf;
-
- struct vnt_cmd_card_init init_command;
- struct vnt_rsp_card_init init_response;
- u8 current_net_addr[ETH_ALEN] __aligned(2);
- u8 permanent_net_addr[ETH_ALEN] __aligned(2);
-
- u8 exist_sw_net_addr;
-
- u64 current_tsf;
-
- /* 802.11 MAC specific */
- u32 current_rssi;
-
- /* Antenna Diversity */
- int tx_rx_ant_inv;
- u32 rx_antenna_sel;
- u8 rx_antenna_mode;
- u8 tx_antenna_mode;
- u8 radio_ctl;
-
- /* IFS & Cw */
- u32 sifs; /* Current SIFS */
- u32 difs; /* Current DIFS */
- u32 eifs; /* Current EIFS */
- u32 slot; /* Current SlotTime */
-
- /* Rate */
- u8 bb_type; /* 0: 11A, 1:11B, 2:11G */
- u8 packet_type; /* 0:11a 1:11b 2:11gb 3:11ga */
- u32 basic_rates;
- u8 top_ofdm_basic_rate;
- u8 top_cck_basic_rate;
-
- u8 eeprom[EEP_MAX_CONTEXT_SIZE]; /*u32 alignment */
-
- u8 preamble_type;
-
- /* For RF Power table */
- u8 cck_pwr;
- u8 ofdm_pwr_g;
- u8 ofdm_pwr_a;
- u8 power;
- u8 cck_pwr_tbl[14];
- u8 ofdm_pwr_tbl[14];
- u8 ofdm_a_pwr_tbl[42];
-
- u16 tx_rate_fb0;
- u16 tx_rate_fb1;
-
- enum nl80211_iftype op_mode;
-
- int short_slot_time;
-
- /* Power save */
- u16 current_aid;
-
- /* Beacon related */
- u16 seq_counter;
-
- enum vnt_cmd_state command_state;
-
- enum vnt_cmd command;
-
- /* 802.11 counter */
-
- enum vnt_cmd cmd_queue[CMD_Q_SIZE];
- u32 cmd_dequeue_idx;
- u32 cmd_enqueue_idx;
- u32 free_cmd_queue;
- int cmd_running;
-
- unsigned long key_entry_inuse;
-
- u8 auto_fb_ctrl;
-
- /* For Update BaseBand VGA Gain Offset */
- u8 bb_vga[BB_VGA_LEVEL];
-
- u8 bb_pre_ed_rssi;
- u8 bb_pre_ed_index;
-
- /* command timer */
- struct delayed_work run_command_work;
-
- struct ieee80211_low_level_stats low_stats;
-};
-
-int vnt_init(struct vnt_private *priv);
-
-#endif
diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c
deleted file mode 100644
index bdc5f30c4f9d..000000000000
--- a/drivers/staging/vt6656/key.c
+++ /dev/null
@@ -1,142 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions for 802.11i Key management
- *
- * Author: Jerry Chen
- *
- * Date: May 29, 2003
- *
- * Functions:
- *
- * Revision History:
- *
- */
-
-#include "mac.h"
-#include "key.h"
-#include "usbpipe.h"
-
-int vnt_key_init_table(struct vnt_private *priv)
-{
- u8 i;
- u8 data[MAX_KEY_TABLE];
-
- for (i = 0; i < MAX_KEY_TABLE; i++)
- data[i] = i;
-
- return vnt_control_out(priv, MESSAGE_TYPE_CLRKEYENTRY,
- 0, 0, ARRAY_SIZE(data), data);
-}
-
-static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr,
- struct ieee80211_key_conf *key, u32 key_type,
- u32 mode)
-{
- struct vnt_private *priv = hw->priv;
- u8 broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- u16 key_mode = 0;
- u32 entry = 0;
- u8 *bssid;
- u8 key_inx = key->keyidx;
- u8 i;
-
- if (mac_addr)
- bssid = mac_addr;
- else
- bssid = &broadcast[0];
-
- if (key_type != VNT_KEY_DEFAULTKEY) {
- for (i = 0; i < (MAX_KEY_TABLE - 1); i++) {
- if (!test_bit(i, &priv->key_entry_inuse)) {
- set_bit(i, &priv->key_entry_inuse);
-
- key->hw_key_idx = i;
- entry = key->hw_key_idx;
- break;
- }
- }
- }
-
- switch (key_type) {
- case VNT_KEY_DEFAULTKEY:
- /* default key last entry */
- entry = MAX_KEY_TABLE - 1;
- key->hw_key_idx = entry;
- fallthrough;
- case VNT_KEY_GROUP_ADDRESS:
- key_mode = mode | (mode << 4);
- break;
- case VNT_KEY_GROUP:
- key_mode = mode << 4;
- break;
- case VNT_KEY_PAIRWISE:
- key_mode |= mode;
- key_inx = 4;
- break;
- default:
- return -EINVAL;
- }
-
- key_mode |= key_type;
-
- if (mode == KEY_CTL_WEP) {
- if (key->keylen == WLAN_KEY_LEN_WEP40)
- key->key[15] &= 0x7f;
- if (key->keylen == WLAN_KEY_LEN_WEP104)
- key->key[15] |= 0x80;
- }
-
- return vnt_mac_set_keyentry(priv, key_mode, entry,
- key_inx, bssid, key->key);
-}
-
-int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
- struct ieee80211_vif *vif, struct ieee80211_key_conf *key)
-{
- struct vnt_private *priv = hw->priv;
- u8 *mac_addr = NULL;
- u8 key_dec_mode = 0;
-
- if (sta)
- mac_addr = &sta->addr[0];
-
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY,
- KEY_CTL_WEP);
-
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-
- return vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY,
- KEY_CTL_WEP);
-
- case WLAN_CIPHER_SUITE_TKIP:
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-
- key_dec_mode = KEY_CTL_TKIP;
-
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- if (priv->local_id <= MAC_REVISION_A1)
- return -EOPNOTSUPP;
-
- key_dec_mode = KEY_CTL_CCMP;
-
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
- return vnt_set_keymode(hw, mac_addr, key, VNT_KEY_PAIRWISE,
- key_dec_mode);
-
- return vnt_set_keymode(hw, mac_addr, key,
- VNT_KEY_GROUP_ADDRESS, key_dec_mode);
-}
diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h
deleted file mode 100644
index 6f1d5b4f6da7..000000000000
--- a/drivers/staging/vt6656/key.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions for 802.11i Key management
- *
- * Author: Jerry Chen
- *
- * Date: May 29, 2003
- *
- */
-
-#ifndef __KEY_H__
-#define __KEY_H__
-
-#include "device.h"
-
-#define MAX_KEY_TABLE 11
-
-#define KEY_CTL_WEP 0x00
-#define KEY_CTL_NONE 0x01
-#define KEY_CTL_TKIP 0x02
-#define KEY_CTL_CCMP 0x03
-
-#define VNT_KEY_ONFLY_ALL 0x4000
-#define VNT_KEY_ONFLY 0x8000
-#define VNT_KEY_ALLGROUP 0x04
-#define VNT_KEY_GROUP 0x40
-#define VNT_KEY_PAIRWISE VNT_KEY_ONFLY
-#define VNT_KEY_GROUP_ADDRESS (VNT_KEY_ALLGROUP | VNT_KEY_GROUP)
-#define VNT_KEY_DEFAULTKEY (VNT_KEY_GROUP_ADDRESS | VNT_KEY_ONFLY |\
- VNT_KEY_ONFLY_ALL)
-
-int vnt_key_init_table(struct vnt_private *priv);
-
-int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
- struct ieee80211_vif *vif, struct ieee80211_key_conf *key);
-
-#endif /* __KEY_H__ */
diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c
deleted file mode 100644
index 49430c0a99b8..000000000000
--- a/drivers/staging/vt6656/mac.c
+++ /dev/null
@@ -1,183 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: MAC routines
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- * Functions:
- *
- * Revision History:
- */
-
-#include <linux/etherdevice.h>
-
-#include "desc.h"
-#include "mac.h"
-#include "usbpipe.h"
-
-int vnt_mac_set_filter(struct vnt_private *priv, u64 mc_filter)
-{
- __le64 le_mc = cpu_to_le64(mc_filter);
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_MAR0,
- MESSAGE_REQUEST_MACREG, sizeof(le_mc),
- (u8 *)&le_mc);
-}
-
-int vnt_mac_shutdown(struct vnt_private *priv)
-{
- return vnt_control_out(priv, MESSAGE_TYPE_MACSHUTDOWN, 0, 0, 0, NULL);
-}
-
-int vnt_mac_set_bb_type(struct vnt_private *priv, u8 type)
-{
- u8 data[2];
-
- data[0] = type;
- data[1] = EN_CFG_BB_TYPE_MASK;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG0,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data),
- data);
-}
-
-int vnt_mac_disable_keyentry(struct vnt_private *priv, u8 entry_idx)
-{
- return vnt_control_out(priv, MESSAGE_TYPE_CLRKEYENTRY, 0, 0,
- sizeof(entry_idx), &entry_idx);
-}
-
-int vnt_mac_set_keyentry(struct vnt_private *priv, u16 key_ctl, u32 entry_idx,
- u32 key_idx, u8 *addr, u8 *key)
-{
- struct vnt_mac_set_key set_key;
- u16 offset;
-
- offset = MISCFIFO_KEYETRY0;
- offset += entry_idx * MISCFIFO_KEYENTRYSIZE;
-
- set_key.u.write.key_ctl = cpu_to_le16(key_ctl);
- ether_addr_copy(set_key.u.write.addr, addr);
-
- /* swap over swap[0] and swap[1] to get correct write order */
- swap(set_key.u.swap[0], set_key.u.swap[1]);
-
- memcpy(set_key.key, key, WLAN_KEY_LEN_CCMP);
-
- dev_dbg(&priv->usb->dev, "offset %d key ctl %d set key %24ph\n",
- offset, key_ctl, (u8 *)&set_key);
-
- return vnt_control_out(priv, MESSAGE_TYPE_SETKEY, offset,
- (u16)key_idx, sizeof(struct vnt_mac_set_key),
- (u8 *)&set_key);
-}
-
-int vnt_mac_reg_bits_off(struct vnt_private *priv, u8 reg_ofs, u8 bits)
-{
- u8 data[2];
-
- data[0] = 0;
- data[1] = bits;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, reg_ofs,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_reg_bits_on(struct vnt_private *priv, u8 reg_ofs, u8 bits)
-{
- u8 data[2];
-
- data[0] = bits;
- data[1] = bits;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, reg_ofs,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_write_word(struct vnt_private *priv, u8 reg_ofs, u16 word)
-{
- u8 data[2];
-
- data[0] = (u8)(word & 0xff);
- data[1] = (u8)(word >> 8);
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE, reg_ofs,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_set_bssid_addr(struct vnt_private *priv, u8 *addr)
-{
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_BSSID0,
- MESSAGE_REQUEST_MACREG, ETH_ALEN, addr);
-}
-
-int vnt_mac_enable_protect_mode(struct vnt_private *priv)
-{
- u8 data[2];
-
- data[0] = EN_CFG_PROTECT_MD;
- data[1] = EN_CFG_PROTECT_MD;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG0,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_disable_protect_mode(struct vnt_private *priv)
-{
- u8 data[2];
-
- data[0] = 0;
- data[1] = EN_CFG_PROTECT_MD;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG0,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_enable_barker_preamble_mode(struct vnt_private *priv)
-{
- u8 data[2];
-
- data[0] = EN_CFG_BARKER_PREAM;
- data[1] = EN_CFG_BARKER_PREAM;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG2,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_disable_barker_preamble_mode(struct vnt_private *priv)
-{
- u8 data[2];
-
- data[0] = 0;
- data[1] = EN_CFG_BARKER_PREAM;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG2,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_set_beacon_interval(struct vnt_private *priv, u16 interval)
-{
- u8 data[2];
-
- data[0] = (u8)(interval & 0xff);
- data[1] = (u8)(interval >> 8);
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_BI,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_set_led(struct vnt_private *priv, u8 state, u8 led)
-{
- u8 data[2];
-
- data[0] = led;
- data[1] = state;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_PAPEDELAY,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h
deleted file mode 100644
index 0ac845bd3c5a..000000000000
--- a/drivers/staging/vt6656/mac.h
+++ /dev/null
@@ -1,373 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: MAC routines
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- * Revision History:
- * 07-01-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
- * 08-25-2003 Kyle Hsu: Porting MAC functions from sim53.
- * 09-03-2003 Bryan YC Fan: Add MACvDisableProtectMD & MACvEnableProtectMD
- */
-
-#ifndef __MAC_H__
-#define __MAC_H__
-
-#include <linux/bits.h>
-#include "device.h"
-
-#define REV_ID_VT3253_A0 0x00
-#define REV_ID_VT3253_A1 0x01
-#define REV_ID_VT3253_B0 0x08
-#define REV_ID_VT3253_B1 0x09
-
-/* Registers in the MAC */
-#define MAC_REG_BISTCMD 0x04
-#define MAC_REG_BISTSR0 0x05
-#define MAC_REG_BISTSR1 0x06
-#define MAC_REG_BISTSR2 0x07
-#define MAC_REG_I2MCSR 0x08
-#define MAC_REG_I2MTGID 0x09
-#define MAC_REG_I2MTGAD 0x0a
-#define MAC_REG_I2MCFG 0x0b
-#define MAC_REG_I2MDIPT 0x0c
-#define MAC_REG_I2MDOPT 0x0e
-#define MAC_REG_USBSUS 0x0f
-
-#define MAC_REG_LOCALID 0x14
-#define MAC_REG_TESTCFG 0x15
-#define MAC_REG_JUMPER0 0x16
-#define MAC_REG_JUMPER1 0x17
-#define MAC_REG_TMCTL 0x18
-#define MAC_REG_TMDATA0 0x1c
-#define MAC_REG_TMDATA1 0x1d
-#define MAC_REG_TMDATA2 0x1e
-#define MAC_REG_TMDATA3 0x1f
-
-/* MAC Parameter related */
-#define MAC_REG_LRT 0x20
-#define MAC_REG_SRT 0x21
-#define MAC_REG_SIFS 0x22
-#define MAC_REG_DIFS 0x23
-#define MAC_REG_EIFS 0x24
-#define MAC_REG_SLOT 0x25
-#define MAC_REG_BI 0x26
-#define MAC_REG_CWMAXMIN0 0x28
-#define MAC_REG_LINKOFFTOTM 0x2a
-#define MAC_REG_SWTMOT 0x2b
-#define MAC_REG_RTSOKCNT 0x2c
-#define MAC_REG_RTSFAILCNT 0x2d
-#define MAC_REG_ACKFAILCNT 0x2e
-#define MAC_REG_FCSERRCNT 0x2f
-
-/* TSF Related */
-#define MAC_REG_TSFCNTR 0x30
-#define MAC_REG_NEXTTBTT 0x38
-#define MAC_REG_TSFOFST 0x40
-#define MAC_REG_TFTCTL 0x48
-
-/* WMAC Control/Status Related */
-#define MAC_REG_ENCFG0 0x4c
-#define MAC_REG_ENCFG1 0x4d
-#define MAC_REG_ENCFG2 0x4e
-
-#define MAC_REG_CFG 0x50
-#define MAC_REG_TEST 0x52
-#define MAC_REG_HOSTCR 0x54
-#define MAC_REG_MACCR 0x55
-#define MAC_REG_RCR 0x56
-#define MAC_REG_TCR 0x57
-#define MAC_REG_IMR 0x58
-#define MAC_REG_ISR 0x5c
-#define MAC_REG_ISR1 0x5d
-
-/* Power Saving Related */
-#define MAC_REG_PSCFG 0x60
-#define MAC_REG_PSCTL 0x61
-#define MAC_REG_PSPWRSIG 0x62
-#define MAC_REG_BBCR13 0x63
-#define MAC_REG_AIDATIM 0x64
-#define MAC_REG_PWBT 0x66
-#define MAC_REG_WAKEOKTMR 0x68
-#define MAC_REG_CALTMR 0x69
-#define MAC_REG_SYNSPACCNT 0x6a
-#define MAC_REG_WAKSYNOPT 0x6b
-
-/* Baseband/IF Control Group */
-#define MAC_REG_BBREGCTL 0x6c
-#define MAC_REG_CHANNEL 0x6d
-#define MAC_REG_BBREGADR 0x6e
-#define MAC_REG_BBREGDATA 0x6f
-#define MAC_REG_IFREGCTL 0x70
-#define MAC_REG_IFDATA 0x71
-#define MAC_REG_ITRTMSET 0x74
-#define MAC_REG_PAPEDELAY 0x77
-#define MAC_REG_SOFTPWRCTL 0x78
-#define MAC_REG_SOFTPWRCTL2 0x79
-#define MAC_REG_GPIOCTL0 0x7a
-#define MAC_REG_GPIOCTL1 0x7b
-
-/* MiscFF PIO related */
-#define MAC_REG_MISCFFNDEX 0xbc
-#define MAC_REG_MISCFFCTL 0xbe
-#define MAC_REG_MISCFFDATA 0xc0
-
-/* MAC Configuration Group */
-#define MAC_REG_PAR0 0xc4
-#define MAC_REG_PAR4 0xc8
-#define MAC_REG_BSSID0 0xcc
-#define MAC_REG_BSSID4 0xd0
-#define MAC_REG_MAR0 0xd4
-#define MAC_REG_MAR4 0xd8
-
-/* MAC RSPPKT INFO Group */
-#define MAC_REG_RSPINF_B_1 0xdC
-#define MAC_REG_RSPINF_B_2 0xe0
-#define MAC_REG_RSPINF_B_5 0xe4
-#define MAC_REG_RSPINF_B_11 0xe8
-#define MAC_REG_RSPINF_A_6 0xec
-#define MAC_REG_RSPINF_A_9 0xee
-#define MAC_REG_RSPINF_A_12 0xf0
-#define MAC_REG_RSPINF_A_18 0xf2
-#define MAC_REG_RSPINF_A_24 0xf4
-#define MAC_REG_RSPINF_A_36 0xf6
-#define MAC_REG_RSPINF_A_48 0xf8
-#define MAC_REG_RSPINF_A_54 0xfa
-#define MAC_REG_RSPINF_A_72 0xfc
-
-/* Bits in the I2MCFG EEPROM register */
-#define I2MCFG_BOUNDCTL BIT(7)
-#define I2MCFG_WAITCTL BIT(5)
-#define I2MCFG_SCLOECTL BIT(4)
-#define I2MCFG_WBUSYCTL BIT(3)
-#define I2MCFG_NORETRY BIT(2)
-#define I2MCFG_I2MLDSEQ BIT(1)
-#define I2MCFG_I2CMFAST BIT(0)
-
-/* Bits in the I2MCSR EEPROM register */
-#define I2MCSR_EEMW BIT(7)
-#define I2MCSR_EEMR BIT(6)
-#define I2MCSR_AUTOLD BIT(3)
-#define I2MCSR_NACK BIT(1)
-#define I2MCSR_DONE BIT(0)
-
-/* Bits in the TMCTL register */
-#define TMCTL_TSUSP BIT(2)
-#define TMCTL_TMD BIT(1)
-#define TMCTL_TE BIT(0)
-
-/* Bits in the TFTCTL register */
-#define TFTCTL_HWUTSF BIT(7)
-#define TFTCTL_TBTTSYNC BIT(6)
-#define TFTCTL_HWUTSFEN BIT(5)
-#define TFTCTL_TSFCNTRRD BIT(4)
-#define TFTCTL_TBTTSYNCEN BIT(3)
-#define TFTCTL_TSFSYNCEN BIT(2)
-#define TFTCTL_TSFCNTRST BIT(1)
-#define TFTCTL_TSFCNTREN BIT(0)
-
-/* Bits in the EnhanceCFG_0 register */
-#define EN_CFG_BB_TYPE_A 0x00
-#define EN_CFG_BB_TYPE_B BIT(0)
-#define EN_CFG_BB_TYPE_G BIT(1)
-#define EN_CFG_BB_TYPE_MASK (EN_CFG_BB_TYPE_B | EN_CFG_BB_TYPE_G)
-#define EN_CFG_PROTECT_MD BIT(5)
-
-/* Bits in the EnhanceCFG_1 register */
-#define EN_CFG_BCN_SUS_IND BIT(0)
-#define EN_CFG_BCN_SUS_CLR BIT(1)
-
-/* Bits in the EnhanceCFG_2 register */
-#define EN_CFG_NXTBTTCFPSTR BIT(0)
-#define EN_CFG_BARKER_PREAM BIT(1)
-#define EN_CFG_PKT_BURST_MD BIT(2)
-
-/* Bits in the CFG register */
-#define CFG_TKIPOPT BIT(7)
-#define CFG_RXDMAOPT BIT(6)
-#define CFG_TMOT_SW BIT(5)
-#define CFG_TMOT_HWLONG BIT(4)
-#define CFG_TMOT_HW 0x00
-#define CFG_CFPENDOPT BIT(3)
-#define CFG_BCNSUSEN BIT(2)
-#define CFG_NOTXTIMEOUT BIT(1)
-#define CFG_NOBUFOPT BIT(0)
-
-/* Bits in the TEST register */
-#define TEST_LBEXT BIT(7)
-#define TEST_LBINT BIT(6)
-#define TEST_LBNONE 0x00
-#define TEST_SOFTINT BIT(5)
-#define TEST_CONTTX BIT(4)
-#define TEST_TXPE BIT(3)
-#define TEST_NAVDIS BIT(2)
-#define TEST_NOCTS BIT(1)
-#define TEST_NOACK BIT(0)
-
-/* Bits in the HOSTCR register */
-#define HOSTCR_TXONST BIT(7)
-#define HOSTCR_RXONST BIT(6)
-#define HOSTCR_ADHOC BIT(5)
-#define HOSTCR_AP BIT(4)
-#define HOSTCR_TXON BIT(3)
-#define HOSTCR_RXON BIT(2)
-#define HOSTCR_MACEN BIT(1)
-#define HOSTCR_SOFTRST BIT(0)
-
-/* Bits in the MACCR register */
-#define MACCR_SYNCFLUSHOK BIT(2)
-#define MACCR_SYNCFLUSH BIT(1)
-#define MACCR_CLRNAV BIT(0)
-
-/* Bits in the RCR register */
-#define RCR_SSID BIT(7)
-#define RCR_RXALLTYPE BIT(6)
-#define RCR_UNICAST BIT(5)
-#define RCR_BROADCAST BIT(4)
-#define RCR_MULTICAST BIT(3)
-#define RCR_WPAERR BIT(2)
-#define RCR_ERRCRC BIT(1)
-#define RCR_BSSID BIT(0)
-
-/* Bits in the TCR register */
-#define TCR_SYNCDCFOPT BIT(1)
-#define TCR_AUTOBCNTX BIT(0)
-
-/* ISR1 */
-#define ISR_GPIO3 BIT(6)
-#define ISR_RXNOBUF BIT(3)
-#define ISR_MIBNEARFULL BIT(2)
-#define ISR_SOFTINT BIT(1)
-#define ISR_FETALERR BIT(0)
-
-#define LEDSTS_STS 0x06
-#define LEDSTS_TMLEN 0x78
-#define LEDSTS_OFF 0x00
-#define LEDSTS_ON 0x02
-#define LEDSTS_SLOW 0x04
-#define LEDSTS_INTER 0x06
-
-/* ISR0 */
-#define ISR_WATCHDOG BIT(7)
-#define ISR_SOFTTIMER BIT(6)
-#define ISR_GPIO0 BIT(5)
-#define ISR_TBTT BIT(4)
-#define ISR_RXDMA0 BIT(3)
-#define ISR_BNTX BIT(2)
-#define ISR_ACTX BIT(0)
-
-/* Bits in the PSCFG register */
-#define PSCFG_PHILIPMD BIT(6)
-#define PSCFG_WAKECALEN BIT(5)
-#define PSCFG_WAKETMREN BIT(4)
-#define PSCFG_BBPSPROG BIT(3)
-#define PSCFG_WAKESYN BIT(2)
-#define PSCFG_SLEEPSYN BIT(1)
-#define PSCFG_AUTOSLEEP BIT(0)
-
-/* Bits in the PSCTL register */
-#define PSCTL_WAKEDONE BIT(5)
-#define PSCTL_PS BIT(4)
-#define PSCTL_GO2DOZE BIT(3)
-#define PSCTL_LNBCN BIT(2)
-#define PSCTL_ALBCN BIT(1)
-#define PSCTL_PSEN BIT(0)
-
-/* Bits in the PSPWSIG register */
-#define PSSIG_WPE3 BIT(7)
-#define PSSIG_WPE2 BIT(6)
-#define PSSIG_WPE1 BIT(5)
-#define PSSIG_WRADIOPE BIT(4)
-#define PSSIG_SPE3 BIT(3)
-#define PSSIG_SPE2 BIT(2)
-#define PSSIG_SPE1 BIT(1)
-#define PSSIG_SRADIOPE BIT(0)
-
-/* Bits in the BBREGCTL register */
-#define BBREGCTL_DONE BIT(2)
-#define BBREGCTL_REGR BIT(1)
-#define BBREGCTL_REGW BIT(0)
-
-/* Bits in the IFREGCTL register */
-#define IFREGCTL_DONE BIT(2)
-#define IFREGCTL_IFRF BIT(1)
-#define IFREGCTL_REGW BIT(0)
-
-/* Bits in the SOFTPWRCTL register */
-#define SOFTPWRCTL_RFLEOPT BIT(3)
-#define SOFTPWRCTL_TXPEINV BIT(1)
-#define SOFTPWRCTL_SWPECTI BIT(0)
-#define SOFTPWRCTL_SWPAPE BIT(5)
-#define SOFTPWRCTL_SWCALEN BIT(4)
-#define SOFTPWRCTL_SWRADIO_PE BIT(3)
-#define SOFTPWRCTL_SWPE2 BIT(2)
-#define SOFTPWRCTL_SWPE1 BIT(1)
-#define SOFTPWRCTL_SWPE3 BIT(0)
-
-/* Bits in the GPIOCTL1 register */
-#define GPIO3_MD BIT(5)
-#define GPIO3_DATA BIT(6)
-#define GPIO3_INTMD BIT(7)
-
-/* Bits in the MISCFFCTL register */
-#define MISCFFCTL_WRITE BIT(0)
-
-/* Loopback mode */
-#define MAC_LB_EXT BIT(1)
-#define MAC_LB_INTERNAL BIT(0)
-#define MAC_LB_NONE 0x00
-
-/* Ethernet address filter type */
-#define PKT_TYPE_NONE 0x00 /* turn off receiver */
-#define PKT_TYPE_ALL_MULTICAST BIT(7)
-#define PKT_TYPE_PROMISCUOUS BIT(6)
-#define PKT_TYPE_DIRECTED BIT(5) /* obselete */
-#define PKT_TYPE_BROADCAST BIT(4)
-#define PKT_TYPE_MULTICAST BIT(3)
-#define PKT_TYPE_ERROR_WPA BIT(2)
-#define PKT_TYPE_ERROR_CRC BIT(1)
-#define PKT_TYPE_BSSID BIT(0)
-
-#define DEFAULT_BI 0x200
-
-/* MiscFIFO Offset */
-#define MISCFIFO_KEYETRY0 32
-#define MISCFIFO_KEYENTRYSIZE 22
-
-#define MAC_REVISION_A0 0x00
-#define MAC_REVISION_A1 0x01
-
-struct vnt_mac_set_key {
- union {
- struct {
- u8 addr[ETH_ALEN];
- __le16 key_ctl;
- } write __packed;
- u32 swap[2];
- } u;
- u8 key[WLAN_KEY_LEN_CCMP];
-} __packed;
-
-int vnt_mac_set_filter(struct vnt_private *priv, u64 mc_filter);
-int vnt_mac_shutdown(struct vnt_private *priv);
-int vnt_mac_set_bb_type(struct vnt_private *priv, u8 type);
-int vnt_mac_disable_keyentry(struct vnt_private *priv, u8 entry_idx);
-int vnt_mac_set_keyentry(struct vnt_private *priv, u16 key_ctl, u32 entry_idx,
- u32 key_idx, u8 *addr, u8 *key);
-int vnt_mac_reg_bits_off(struct vnt_private *priv, u8 reg_ofs, u8 bits);
-int vnt_mac_reg_bits_on(struct vnt_private *priv, u8 reg_ofs, u8 bits);
-int vnt_mac_write_word(struct vnt_private *priv, u8 reg_ofs, u16 word);
-int vnt_mac_set_bssid_addr(struct vnt_private *priv, u8 *addr);
-int vnt_mac_enable_protect_mode(struct vnt_private *priv);
-int vnt_mac_disable_protect_mode(struct vnt_private *priv);
-int vnt_mac_enable_barker_preamble_mode(struct vnt_private *priv);
-int vnt_mac_disable_barker_preamble_mode(struct vnt_private *priv);
-int vnt_mac_set_beacon_interval(struct vnt_private *priv, u16 interval);
-int vnt_mac_set_led(struct vnt_private *privpriv, u8 state, u8 led);
-
-#endif /* __MAC_H__ */
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
deleted file mode 100644
index 4f09e733e7a8..000000000000
--- a/drivers/staging/vt6656/main_usb.c
+++ /dev/null
@@ -1,1121 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: driver entry for initial, open, close, tx and rx.
- *
- * Author: Lyndon Chen
- *
- * Date: Dec 8, 2005
- *
- * Functions:
- *
- * vt6656_probe - module initial (insmod) driver entry
- * vnt_free_tx_bufs - free tx buffer function
- * vnt_init_registers- initial MAC & BBP & RF internal registers.
- *
- * Revision History:
- */
-#undef __NO_VERSION__
-
-#include <linux/bits.h>
-#include <linux/etherdevice.h>
-#include <linux/file.h>
-#include <linux/kernel.h>
-#include "device.h"
-#include "card.h"
-#include "baseband.h"
-#include "mac.h"
-#include "power.h"
-#include "wcmd.h"
-#include "rxtx.h"
-#include "rf.h"
-#include "usbpipe.h"
-#include "channel.h"
-
-/*
- * define module options
- */
-
-/* version information */
-#define DRIVER_AUTHOR \
- "VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>"
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(DEVICE_FULL_DRV_NAM);
-
-#define RX_DESC_DEF0 64
-static int vnt_rx_buffers = RX_DESC_DEF0;
-module_param_named(rx_buffers, vnt_rx_buffers, int, 0644);
-MODULE_PARM_DESC(rx_buffers, "Number of receive usb rx buffers");
-
-#define TX_DESC_DEF0 64
-static int vnt_tx_buffers = TX_DESC_DEF0;
-module_param_named(tx_buffers, vnt_tx_buffers, int, 0644);
-MODULE_PARM_DESC(tx_buffers, "Number of receive usb tx buffers");
-
-#define RTS_THRESH_DEF 2347
-#define FRAG_THRESH_DEF 2346
-
-/* BasebandType[] baseband type selected
- * 0: indicate 802.11a type
- * 1: indicate 802.11b type
- * 2: indicate 802.11g type
- */
-
-#define BBP_TYPE_DEF 2
-
-/*
- * Static vars definitions
- */
-
-static const struct usb_device_id vt6656_table[] = {
- {USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)},
- {}
-};
-
-static void vnt_set_options(struct vnt_private *priv)
-{
- /* Set number of TX buffers */
- if (vnt_tx_buffers < CB_MIN_TX_DESC || vnt_tx_buffers > CB_MAX_TX_DESC)
- priv->num_tx_context = TX_DESC_DEF0;
- else
- priv->num_tx_context = vnt_tx_buffers;
-
- /* Set number of RX buffers */
- if (vnt_rx_buffers < CB_MIN_RX_DESC || vnt_rx_buffers > CB_MAX_RX_DESC)
- priv->num_rcb = RX_DESC_DEF0;
- else
- priv->num_rcb = vnt_rx_buffers;
-
- priv->op_mode = NL80211_IFTYPE_UNSPECIFIED;
- priv->bb_type = BBP_TYPE_DEF;
- priv->packet_type = priv->bb_type;
- priv->preamble_type = PREAMBLE_LONG;
- priv->exist_sw_net_addr = false;
-}
-
-static int vnt_download_firmware(struct vnt_private *priv)
-{
- struct device *dev = &priv->usb->dev;
- const struct firmware *fw;
- u16 length;
- int ii;
- int ret = 0;
-
- dev_dbg(dev, "---->Download firmware\n");
-
- ret = request_firmware(&fw, FIRMWARE_NAME, dev);
- if (ret) {
- dev_err(dev, "firmware file %s request failed (%d)\n",
- FIRMWARE_NAME, ret);
- goto end;
- }
-
- for (ii = 0; ii < fw->size; ii += FIRMWARE_CHUNK_SIZE) {
- length = min_t(int, fw->size - ii, FIRMWARE_CHUNK_SIZE);
-
- ret = vnt_control_out(priv, 0, 0x1200 + ii, 0x0000, length,
- fw->data + ii);
- if (ret)
- goto free_fw;
-
- dev_dbg(dev, "Download firmware...%d %zu\n", ii, fw->size);
- }
-
-free_fw:
- release_firmware(fw);
-end:
- return ret;
-}
-
-static int vnt_firmware_branch_to_sram(struct vnt_private *priv)
-{
- dev_dbg(&priv->usb->dev, "---->Branch to Sram\n");
-
- return vnt_control_out(priv, 1, 0x1200, 0x0000, 0, NULL);
-}
-
-static int vnt_check_firmware_version(struct vnt_private *priv)
-{
- int ret = 0;
-
- ret = vnt_control_in(priv, MESSAGE_TYPE_READ, 0,
- MESSAGE_REQUEST_VERSION, 2,
- (u8 *)&priv->firmware_version);
- if (ret) {
- dev_dbg(&priv->usb->dev,
- "Could not get firmware version: %d.\n", ret);
- goto end;
- }
-
- dev_dbg(&priv->usb->dev, "Firmware Version [%04x]\n",
- priv->firmware_version);
-
- if (priv->firmware_version == 0xFFFF) {
- dev_dbg(&priv->usb->dev, "In Loader.\n");
- ret = -EINVAL;
- goto end;
- }
-
- if (priv->firmware_version < FIRMWARE_VERSION) {
- /* branch to loader for download new firmware */
- ret = vnt_firmware_branch_to_sram(priv);
- if (ret) {
- dev_dbg(&priv->usb->dev,
- "Could not branch to SRAM: %d.\n", ret);
- } else {
- ret = -EINVAL;
- }
- }
-
-end:
- return ret;
-}
-
-/*
- * initialization of MAC & BBP registers
- */
-static int vnt_init_registers(struct vnt_private *priv)
-{
- int ret;
- struct vnt_cmd_card_init *init_cmd = &priv->init_command;
- struct vnt_rsp_card_init *init_rsp = &priv->init_response;
- u8 antenna;
- int ii;
- u8 tmp;
- u8 calib_tx_iq = 0, calib_tx_dc = 0, calib_rx_iq = 0;
-
- dev_dbg(&priv->usb->dev, "---->INIbInitAdapter. [%d][%d]\n",
- DEVICE_INIT_COLD, priv->packet_type);
-
- ret = vnt_check_firmware_version(priv);
- if (ret) {
- ret = vnt_download_firmware(priv);
- if (ret) {
- dev_dbg(&priv->usb->dev,
- "Could not download firmware: %d.\n", ret);
- goto end;
- }
-
- ret = vnt_firmware_branch_to_sram(priv);
- if (ret) {
- dev_dbg(&priv->usb->dev,
- "Could not branch to SRAM: %d.\n", ret);
- goto end;
- }
- }
-
- ret = vnt_vt3184_init(priv);
- if (ret) {
- dev_dbg(&priv->usb->dev, "vnt_vt3184_init fail\n");
- goto end;
- }
-
- init_cmd->init_class = DEVICE_INIT_COLD;
- init_cmd->exist_sw_net_addr = priv->exist_sw_net_addr;
- for (ii = 0; ii < ARRAY_SIZE(init_cmd->sw_net_addr); ii++)
- init_cmd->sw_net_addr[ii] = priv->current_net_addr[ii];
- init_cmd->short_retry_limit = priv->hw->wiphy->retry_short;
- init_cmd->long_retry_limit = priv->hw->wiphy->retry_long;
-
- /* issue card_init command to device */
- ret = vnt_control_out(priv, MESSAGE_TYPE_CARDINIT, 0, 0,
- sizeof(struct vnt_cmd_card_init),
- (u8 *)init_cmd);
- if (ret) {
- dev_dbg(&priv->usb->dev, "Issue Card init fail\n");
- goto end;
- }
-
- ret = vnt_control_in(priv, MESSAGE_TYPE_INIT_RSP, 0, 0,
- sizeof(struct vnt_rsp_card_init),
- (u8 *)init_rsp);
- if (ret) {
- dev_dbg(&priv->usb->dev, "Cardinit request in status fail!\n");
- goto end;
- }
-
- /* local ID for AES functions */
- ret = vnt_control_in(priv, MESSAGE_TYPE_READ, MAC_REG_LOCALID,
- MESSAGE_REQUEST_MACREG, 1, &priv->local_id);
- if (ret)
- goto end;
-
- /* do MACbSoftwareReset in MACvInitialize */
-
- priv->top_ofdm_basic_rate = RATE_24M;
- priv->top_cck_basic_rate = RATE_1M;
-
- /* target to IF pin while programming to RF chip */
- priv->power = 0xFF;
-
- priv->cck_pwr = priv->eeprom[EEP_OFS_PWR_CCK];
- priv->ofdm_pwr_g = priv->eeprom[EEP_OFS_PWR_OFDMG];
- /* load power table */
- for (ii = 0; ii < ARRAY_SIZE(priv->cck_pwr_tbl); ii++) {
- priv->cck_pwr_tbl[ii] =
- priv->eeprom[ii + EEP_OFS_CCK_PWR_TBL];
- if (priv->cck_pwr_tbl[ii] == 0)
- priv->cck_pwr_tbl[ii] = priv->cck_pwr;
-
- priv->ofdm_pwr_tbl[ii] =
- priv->eeprom[ii + EEP_OFS_OFDM_PWR_TBL];
- if (priv->ofdm_pwr_tbl[ii] == 0)
- priv->ofdm_pwr_tbl[ii] = priv->ofdm_pwr_g;
- }
-
- /*
- * original zonetype is USA, but custom zonetype is Europe,
- * then need to recover 12, 13, 14 channels with 11 channel
- */
- for (ii = 11; ii < ARRAY_SIZE(priv->cck_pwr_tbl); ii++) {
- priv->cck_pwr_tbl[ii] = priv->cck_pwr_tbl[10];
- priv->ofdm_pwr_tbl[ii] = priv->ofdm_pwr_tbl[10];
- }
-
- priv->ofdm_pwr_a = 0x34; /* same as RFbMA2829SelectChannel */
-
- /* load OFDM A power table */
- for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) {
- priv->ofdm_a_pwr_tbl[ii] =
- priv->eeprom[ii + EEP_OFS_OFDMA_PWR_TBL];
-
- if (priv->ofdm_a_pwr_tbl[ii] == 0)
- priv->ofdm_a_pwr_tbl[ii] = priv->ofdm_pwr_a;
- }
-
- antenna = priv->eeprom[EEP_OFS_ANTENNA];
-
- if (antenna & EEP_ANTINV)
- priv->tx_rx_ant_inv = true;
- else
- priv->tx_rx_ant_inv = false;
-
- antenna &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
-
- if (antenna == 0) /* if not set default is both */
- antenna = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
-
- if (antenna == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) {
- priv->tx_antenna_mode = ANT_B;
- priv->rx_antenna_sel = 1;
-
- if (priv->tx_rx_ant_inv)
- priv->rx_antenna_mode = ANT_A;
- else
- priv->rx_antenna_mode = ANT_B;
- } else {
- priv->rx_antenna_sel = 0;
-
- if (antenna & EEP_ANTENNA_AUX) {
- priv->tx_antenna_mode = ANT_A;
-
- if (priv->tx_rx_ant_inv)
- priv->rx_antenna_mode = ANT_B;
- else
- priv->rx_antenna_mode = ANT_A;
- } else {
- priv->tx_antenna_mode = ANT_B;
-
- if (priv->tx_rx_ant_inv)
- priv->rx_antenna_mode = ANT_A;
- else
- priv->rx_antenna_mode = ANT_B;
- }
- }
-
- /* Set initial antenna mode */
- ret = vnt_set_antenna_mode(priv, priv->rx_antenna_mode);
- if (ret)
- goto end;
-
- /* default Auto Mode */
- priv->bb_type = BB_TYPE_11G;
-
- /* get RFType */
- priv->rf_type = init_rsp->rf_type;
-
- /* load vt3266 calibration parameters in EEPROM */
- if (priv->rf_type == RF_VT3226D0) {
- if ((priv->eeprom[EEP_OFS_MAJOR_VER] == 0x1) &&
- (priv->eeprom[EEP_OFS_MINOR_VER] >= 0x4)) {
- calib_tx_iq = priv->eeprom[EEP_OFS_CALIB_TX_IQ];
- calib_tx_dc = priv->eeprom[EEP_OFS_CALIB_TX_DC];
- calib_rx_iq = priv->eeprom[EEP_OFS_CALIB_RX_IQ];
- if (calib_tx_iq || calib_tx_dc || calib_rx_iq) {
- /* CR255, enable TX/RX IQ and
- * DC compensation mode
- */
- ret = vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xff, 0x03);
- if (ret)
- goto end;
-
- /* CR251, TX I/Q Imbalance Calibration */
- ret = vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xfb, calib_tx_iq);
- if (ret)
- goto end;
-
- /* CR252, TX DC-Offset Calibration */
- ret = vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xfC, calib_tx_dc);
- if (ret)
- goto end;
-
- /* CR253, RX I/Q Imbalance Calibration */
- ret = vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xfd, calib_rx_iq);
- if (ret)
- goto end;
- } else {
- /* CR255, turn off
- * BB Calibration compensation
- */
- ret = vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xff, 0x0);
- if (ret)
- goto end;
- }
- }
- }
-
- /* get permanent network address */
- memcpy(priv->permanent_net_addr, init_rsp->net_addr, 6);
- ether_addr_copy(priv->current_net_addr, priv->permanent_net_addr);
-
- /* if exist SW network address, use it */
- dev_dbg(&priv->usb->dev, "Network address = %pM\n",
- priv->current_net_addr);
-
- priv->radio_ctl = priv->eeprom[EEP_OFS_RADIOCTL];
-
- if ((priv->radio_ctl & EEP_RADIOCTL_ENABLE) != 0) {
- ret = vnt_control_in(priv, MESSAGE_TYPE_READ,
- MAC_REG_GPIOCTL1, MESSAGE_REQUEST_MACREG,
- 1, &tmp);
- if (ret)
- goto end;
-
- if ((tmp & GPIO3_DATA) == 0) {
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1,
- GPIO3_INTMD);
- } else {
- ret = vnt_mac_reg_bits_off(priv, MAC_REG_GPIOCTL1,
- GPIO3_INTMD);
- }
-
- if (ret)
- goto end;
- }
-
- ret = vnt_mac_set_led(priv, LEDSTS_TMLEN, 0x38);
- if (ret)
- goto end;
-
- ret = vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_SLOW);
- if (ret)
- goto end;
-
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL0, BIT(0));
- if (ret)
- goto end;
-
- ret = vnt_radio_power_on(priv);
- if (ret)
- goto end;
-
- dev_dbg(&priv->usb->dev, "<----INIbInitAdapter Exit\n");
-
-end:
- return ret;
-}
-
-static void vnt_free_tx_bufs(struct vnt_private *priv)
-{
- struct vnt_usb_send_context *tx_context;
- int ii;
-
- usb_kill_anchored_urbs(&priv->tx_submitted);
-
- for (ii = 0; ii < priv->num_tx_context; ii++) {
- tx_context = priv->tx_context[ii];
- if (!tx_context)
- continue;
-
- kfree(tx_context);
- }
-}
-
-static void vnt_free_rx_bufs(struct vnt_private *priv)
-{
- struct vnt_rcb *rcb;
- int ii;
-
- for (ii = 0; ii < priv->num_rcb; ii++) {
- rcb = priv->rcb[ii];
- if (!rcb)
- continue;
-
- /* deallocate URBs */
- if (rcb->urb) {
- usb_kill_urb(rcb->urb);
- usb_free_urb(rcb->urb);
- }
-
- /* deallocate skb */
- if (rcb->skb)
- dev_kfree_skb(rcb->skb);
-
- kfree(rcb);
- }
-}
-
-static void vnt_free_int_bufs(struct vnt_private *priv)
-{
- kfree(priv->int_buf.data_buf);
-}
-
-static int vnt_alloc_bufs(struct vnt_private *priv)
-{
- int ret;
- struct vnt_usb_send_context *tx_context;
- struct vnt_rcb *rcb;
- int ii;
-
- init_usb_anchor(&priv->tx_submitted);
-
- for (ii = 0; ii < priv->num_tx_context; ii++) {
- tx_context = kmalloc(sizeof(*tx_context), GFP_KERNEL);
- if (!tx_context) {
- ret = -ENOMEM;
- goto free_tx;
- }
-
- priv->tx_context[ii] = tx_context;
- tx_context->priv = priv;
- tx_context->pkt_no = ii;
- tx_context->in_use = false;
- }
-
- for (ii = 0; ii < priv->num_rcb; ii++) {
- priv->rcb[ii] = kzalloc(sizeof(*priv->rcb[ii]), GFP_KERNEL);
- if (!priv->rcb[ii]) {
- ret = -ENOMEM;
- goto free_rx_tx;
- }
-
- rcb = priv->rcb[ii];
-
- rcb->priv = priv;
-
- /* allocate URBs */
- rcb->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!rcb->urb) {
- ret = -ENOMEM;
- goto free_rx_tx;
- }
-
- rcb->skb = dev_alloc_skb(priv->rx_buf_sz);
- if (!rcb->skb) {
- ret = -ENOMEM;
- goto free_rx_tx;
- }
- /* submit rx urb */
- ret = vnt_submit_rx_urb(priv, rcb);
- if (ret)
- goto free_rx_tx;
- }
-
- priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!priv->interrupt_urb) {
- ret = -ENOMEM;
- goto free_rx_tx;
- }
-
- priv->int_buf.data_buf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL);
- if (!priv->int_buf.data_buf) {
- ret = -ENOMEM;
- goto free_rx_tx_urb;
- }
-
- return 0;
-
-free_rx_tx_urb:
- usb_free_urb(priv->interrupt_urb);
-free_rx_tx:
- vnt_free_rx_bufs(priv);
-free_tx:
- vnt_free_tx_bufs(priv);
- return ret;
-}
-
-static void vnt_tx_80211(struct ieee80211_hw *hw,
- struct ieee80211_tx_control *control,
- struct sk_buff *skb)
-{
- struct vnt_private *priv = hw->priv;
-
- if (vnt_tx_packet(priv, skb))
- ieee80211_free_txskb(hw, skb);
-}
-
-static int vnt_start(struct ieee80211_hw *hw)
-{
- int ret;
- struct vnt_private *priv = hw->priv;
-
- priv->rx_buf_sz = MAX_TOTAL_SIZE_WITH_ALL_HEADERS;
-
- ret = vnt_alloc_bufs(priv);
- if (ret) {
- dev_dbg(&priv->usb->dev, "vnt_alloc_bufs fail...\n");
- goto err;
- }
-
- clear_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags);
-
- ret = vnt_init_registers(priv);
- if (ret) {
- dev_dbg(&priv->usb->dev, " init register fail\n");
- goto free_all;
- }
-
- ret = vnt_key_init_table(priv);
- if (ret)
- goto free_all;
-
- priv->int_interval = 1; /* bInterval is set to 1 */
-
- ret = vnt_start_interrupt_urb(priv);
- if (ret)
- goto free_all;
-
- ieee80211_wake_queues(hw);
-
- return 0;
-
-free_all:
- vnt_free_rx_bufs(priv);
- vnt_free_tx_bufs(priv);
- vnt_free_int_bufs(priv);
-
- usb_kill_urb(priv->interrupt_urb);
- usb_free_urb(priv->interrupt_urb);
-err:
- return ret;
-}
-
-static void vnt_stop(struct ieee80211_hw *hw, bool suspend)
-{
- struct vnt_private *priv = hw->priv;
- int i;
-
- if (!priv)
- return;
-
- for (i = 0; i < MAX_KEY_TABLE; i++)
- vnt_mac_disable_keyentry(priv, i);
-
- /* clear all keys */
- priv->key_entry_inuse = 0;
-
- if (!test_bit(DEVICE_FLAGS_UNPLUG, &priv->flags))
- vnt_mac_shutdown(priv);
-
- ieee80211_stop_queues(hw);
-
- set_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags);
-
- cancel_delayed_work_sync(&priv->run_command_work);
-
- priv->cmd_running = false;
-
- vnt_free_tx_bufs(priv);
- vnt_free_rx_bufs(priv);
- vnt_free_int_bufs(priv);
-
- usb_kill_urb(priv->interrupt_urb);
- usb_free_urb(priv->interrupt_urb);
-}
-
-static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- priv->vif = vif;
-
- switch (vif->type) {
- case NL80211_IFTYPE_STATION:
- break;
- case NL80211_IFTYPE_ADHOC:
- vnt_mac_reg_bits_off(priv, MAC_REG_RCR, RCR_UNICAST);
-
- vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_ADHOC);
-
- break;
- case NL80211_IFTYPE_AP:
- vnt_mac_reg_bits_off(priv, MAC_REG_RCR, RCR_UNICAST);
-
- vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_AP);
-
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- priv->op_mode = vif->type;
-
- /* LED blink on TX */
- vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_INTER);
-
- return 0;
-}
-
-static void vnt_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- switch (vif->type) {
- case NL80211_IFTYPE_STATION:
- break;
- case NL80211_IFTYPE_ADHOC:
- vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
- vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
- vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_ADHOC);
- break;
- case NL80211_IFTYPE_AP:
- vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
- vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
- vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_AP);
- break;
- default:
- break;
- }
-
- vnt_radio_power_off(priv);
-
- priv->op_mode = NL80211_IFTYPE_UNSPECIFIED;
-
- /* LED slow blink */
- vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_SLOW);
-}
-
-static int vnt_config(struct ieee80211_hw *hw, u32 changed)
-{
- struct vnt_private *priv = hw->priv;
- struct ieee80211_conf *conf = &hw->conf;
-
- if (changed & IEEE80211_CONF_CHANGE_PS) {
- if (conf->flags & IEEE80211_CONF_PS)
- vnt_enable_power_saving(priv, conf->listen_interval);
- else
- vnt_disable_power_saving(priv);
- }
-
- if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) ||
- (conf->flags & IEEE80211_CONF_OFFCHANNEL)) {
- vnt_set_channel(priv, conf->chandef.chan->hw_value);
-
- if (conf->chandef.chan->band == NL80211_BAND_5GHZ)
- priv->bb_type = BB_TYPE_11A;
- else
- priv->bb_type = BB_TYPE_11G;
- }
-
- if (changed & IEEE80211_CONF_CHANGE_POWER)
- vnt_rf_setpower(priv, conf->chandef.chan);
-
- if (conf->flags & (IEEE80211_CONF_OFFCHANNEL | IEEE80211_CONF_IDLE))
- /* Set max sensitivity*/
- vnt_update_pre_ed_threshold(priv, true);
- else
- vnt_update_pre_ed_threshold(priv, false);
-
- return 0;
-}
-
-static void vnt_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf, u64 changed)
-{
- struct vnt_private *priv = hw->priv;
-
- priv->current_aid = vif->cfg.aid;
-
- if (changed & BSS_CHANGED_BSSID && conf->bssid)
- vnt_mac_set_bssid_addr(priv, (u8 *)conf->bssid);
-
- if (changed & BSS_CHANGED_BASIC_RATES) {
- priv->basic_rates = conf->basic_rates;
-
- vnt_update_top_rates(priv);
-
- dev_dbg(&priv->usb->dev, "basic rates %x\n", conf->basic_rates);
- }
-
- if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- if (conf->use_short_preamble) {
- vnt_mac_enable_barker_preamble_mode(priv);
- priv->preamble_type = PREAMBLE_SHORT;
- } else {
- vnt_mac_disable_barker_preamble_mode(priv);
- priv->preamble_type = PREAMBLE_LONG;
- }
- }
-
- if (changed & BSS_CHANGED_ERP_CTS_PROT) {
- if (conf->use_cts_prot)
- vnt_mac_enable_protect_mode(priv);
- else
- vnt_mac_disable_protect_mode(priv);
- }
-
- if (changed & BSS_CHANGED_ERP_SLOT) {
- if (conf->use_short_slot)
- priv->short_slot_time = true;
- else
- priv->short_slot_time = false;
-
- vnt_set_short_slot_time(priv);
- vnt_set_vga_gain_offset(priv, priv->bb_vga[0]);
- }
-
- if (changed & (BSS_CHANGED_BASIC_RATES | BSS_CHANGED_ERP_PREAMBLE |
- BSS_CHANGED_ERP_SLOT))
- vnt_set_bss_mode(priv);
-
- if (changed & (BSS_CHANGED_TXPOWER | BSS_CHANGED_BANDWIDTH))
- vnt_rf_setpower(priv, conf->chanreq.oper.chan);
-
- if (changed & BSS_CHANGED_BEACON_ENABLED) {
- dev_dbg(&priv->usb->dev,
- "Beacon enable %d\n", conf->enable_beacon);
-
- if (conf->enable_beacon) {
- vnt_beacon_enable(priv, vif, conf);
-
- vnt_mac_reg_bits_on(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
- } else {
- vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
- }
- }
-
- if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INFO) &&
- priv->op_mode != NL80211_IFTYPE_AP) {
- if (vif->cfg.assoc && conf->beacon_rate) {
- u16 ps_beacon_int = conf->beacon_int;
-
- if (conf->dtim_period)
- ps_beacon_int *= conf->dtim_period;
- else if (hw->conf.listen_interval)
- ps_beacon_int *= hw->conf.listen_interval;
-
- vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL,
- TFTCTL_TSFCNTREN);
-
- vnt_mac_set_beacon_interval(priv, ps_beacon_int);
-
- vnt_reset_next_tbtt(priv, conf->beacon_int);
-
- vnt_adjust_tsf(priv, conf->beacon_rate->hw_value,
- conf->sync_tsf, priv->current_tsf);
-
- vnt_update_next_tbtt(priv,
- conf->sync_tsf, ps_beacon_int);
- } else {
- vnt_clear_current_tsf(priv);
-
- vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL,
- TFTCTL_TSFCNTREN);
- }
- }
-}
-
-static u64 vnt_prepare_multicast(struct ieee80211_hw *hw,
- struct netdev_hw_addr_list *mc_list)
-{
- struct vnt_private *priv = hw->priv;
- struct netdev_hw_addr *ha;
- u64 mc_filter = 0;
- u32 bit_nr;
-
- netdev_hw_addr_list_for_each(ha, mc_list) {
- bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
- mc_filter |= BIT_ULL(bit_nr);
- }
-
- priv->mc_list_count = mc_list->count;
-
- return mc_filter;
-}
-
-static void vnt_configure(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *total_flags, u64 multicast)
-{
- struct vnt_private *priv = hw->priv;
- u8 rx_mode = 0;
-
- *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC;
-
- vnt_control_in(priv, MESSAGE_TYPE_READ, MAC_REG_RCR,
- MESSAGE_REQUEST_MACREG, sizeof(u8), &rx_mode);
-
- dev_dbg(&priv->usb->dev, "rx mode in = %x\n", rx_mode);
-
- if (changed_flags & FIF_ALLMULTI) {
- if (*total_flags & FIF_ALLMULTI) {
- if (priv->mc_list_count > 2)
- vnt_mac_set_filter(priv, ~0);
- else
- vnt_mac_set_filter(priv, multicast);
-
- rx_mode |= RCR_MULTICAST | RCR_BROADCAST;
- } else {
- rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST);
- }
- }
-
- if (changed_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) {
- if (*total_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC))
- rx_mode &= ~RCR_BSSID;
- else
- rx_mode |= RCR_BSSID;
- }
-
- vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_RCR, rx_mode);
-
- dev_dbg(&priv->usb->dev, "rx mode out= %x\n", rx_mode);
-}
-
-static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
-{
- struct vnt_private *priv = hw->priv;
-
- switch (cmd) {
- case SET_KEY:
- return vnt_set_keys(hw, sta, vif, key);
- case DISABLE_KEY:
- if (test_bit(key->hw_key_idx, &priv->key_entry_inuse)) {
- clear_bit(key->hw_key_idx, &priv->key_entry_inuse);
-
- vnt_mac_disable_keyentry(priv, key->hw_key_idx);
- }
- break;
-
- default:
- break;
- }
-
- return 0;
-}
-
-static int vnt_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
-{
- struct vnt_private *priv = hw->priv;
-
- memcpy(stats, &priv->low_stats, sizeof(*stats));
-
- return 0;
-}
-
-static u64 vnt_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- return priv->current_tsf;
-}
-
-static void vnt_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- u64 tsf)
-{
- struct vnt_private *priv = hw->priv;
-
- vnt_update_next_tbtt(priv, tsf, vif->bss_conf.beacon_int);
-}
-
-static void vnt_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
-
- vnt_clear_current_tsf(priv);
-}
-
-static const struct ieee80211_ops vnt_mac_ops = {
- .add_chanctx = ieee80211_emulate_add_chanctx,
- .remove_chanctx = ieee80211_emulate_remove_chanctx,
- .change_chanctx = ieee80211_emulate_change_chanctx,
- .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
- .tx = vnt_tx_80211,
- .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = vnt_start,
- .stop = vnt_stop,
- .add_interface = vnt_add_interface,
- .remove_interface = vnt_remove_interface,
- .config = vnt_config,
- .bss_info_changed = vnt_bss_info_changed,
- .prepare_multicast = vnt_prepare_multicast,
- .configure_filter = vnt_configure,
- .set_key = vnt_set_key,
- .get_stats = vnt_get_stats,
- .get_tsf = vnt_get_tsf,
- .set_tsf = vnt_set_tsf,
- .reset_tsf = vnt_reset_tsf,
-};
-
-int vnt_init(struct vnt_private *priv)
-{
- if (vnt_init_registers(priv))
- return -EAGAIN;
-
- SET_IEEE80211_PERM_ADDR(priv->hw, priv->permanent_net_addr);
-
- vnt_init_bands(priv);
-
- if (ieee80211_register_hw(priv->hw))
- return -ENODEV;
-
- priv->mac_hw = true;
-
- vnt_radio_power_off(priv);
-
- return 0;
-}
-
-static int
-vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
- struct usb_device *udev;
- struct vnt_private *priv;
- struct ieee80211_hw *hw;
- struct wiphy *wiphy;
- int rc;
-
- udev = usb_get_dev(interface_to_usbdev(intf));
-
- dev_notice(&udev->dev, "%s Ver. %s\n",
- DEVICE_FULL_DRV_NAM, DEVICE_VERSION);
- dev_notice(&udev->dev,
- "Copyright (c) 2004 VIA Networking Technologies, Inc.\n");
-
- hw = ieee80211_alloc_hw(sizeof(struct vnt_private), &vnt_mac_ops);
- if (!hw) {
- dev_err(&udev->dev, "could not register ieee80211_hw\n");
- rc = -ENOMEM;
- goto err_nomem;
- }
-
- priv = hw->priv;
- priv->hw = hw;
- priv->usb = udev;
- priv->intf = intf;
-
- vnt_set_options(priv);
-
- spin_lock_init(&priv->lock);
- mutex_init(&priv->usb_lock);
-
- INIT_DELAYED_WORK(&priv->run_command_work, vnt_run_command);
-
- usb_set_intfdata(intf, priv);
-
- wiphy = priv->hw->wiphy;
-
- wiphy->frag_threshold = FRAG_THRESH_DEF;
- wiphy->rts_threshold = RTS_THRESH_DEF;
- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
-
- ieee80211_hw_set(priv->hw, TIMING_BEACON_ONLY);
- ieee80211_hw_set(priv->hw, SIGNAL_DBM);
- ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS);
- ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS);
- ieee80211_hw_set(priv->hw, SUPPORTS_PS);
- ieee80211_hw_set(priv->hw, PS_NULLFUNC_STACK);
-
- priv->hw->extra_tx_headroom =
- sizeof(struct vnt_tx_buffer) + sizeof(struct vnt_tx_usb_header);
- priv->hw->max_signal = 100;
-
- SET_IEEE80211_DEV(priv->hw, &intf->dev);
-
- rc = usb_reset_device(priv->usb);
- if (rc)
- dev_warn(&priv->usb->dev,
- "%s reset fail status=%d\n", __func__, rc);
-
- clear_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags);
- vnt_reset_command_timer(priv);
-
- vnt_schedule_command(priv, WLAN_CMD_INIT_MAC80211);
-
- return 0;
-
-err_nomem:
- usb_put_dev(udev);
-
- return rc;
-}
-
-static void vt6656_disconnect(struct usb_interface *intf)
-{
- struct vnt_private *priv = usb_get_intfdata(intf);
-
- if (!priv)
- return;
-
- if (priv->mac_hw)
- ieee80211_unregister_hw(priv->hw);
-
- usb_set_intfdata(intf, NULL);
- usb_put_dev(interface_to_usbdev(intf));
-
- set_bit(DEVICE_FLAGS_UNPLUG, &priv->flags);
-
- ieee80211_free_hw(priv->hw);
-}
-
-#ifdef CONFIG_PM
-
-static int vt6656_suspend(struct usb_interface *intf, pm_message_t message)
-{
- return 0;
-}
-
-static int vt6656_resume(struct usb_interface *intf)
-{
- return 0;
-}
-
-#endif /* CONFIG_PM */
-
-MODULE_DEVICE_TABLE(usb, vt6656_table);
-
-static struct usb_driver vt6656_driver = {
- .name = DEVICE_NAME,
- .probe = vt6656_probe,
- .disconnect = vt6656_disconnect,
- .id_table = vt6656_table,
-#ifdef CONFIG_PM
- .suspend = vt6656_suspend,
- .resume = vt6656_resume,
-#endif /* CONFIG_PM */
-};
-
-module_usb_driver(vt6656_driver);
-
-MODULE_FIRMWARE(FIRMWARE_NAME);
diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c
deleted file mode 100644
index e5411f6284c7..000000000000
--- a/drivers/staging/vt6656/power.c
+++ /dev/null
@@ -1,112 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handles 802.11 power management functions
- *
- * Author: Lyndon Chen
- *
- * Date: July 17, 2002
- *
- * Functions:
- * vnt_enable_power_saving - Enable Power Saving Mode
- * PSvDiasblePowerSaving - Disable Power Saving Mode
- * vnt_next_tbtt_wakeup - Decide if we need to wake up at next Beacon
- *
- * Revision History:
- *
- */
-
-#include "mac.h"
-#include "device.h"
-#include "power.h"
-#include "wcmd.h"
-#include "rxtx.h"
-#include "card.h"
-#include "usbpipe.h"
-
-/*
- *
- * Routine Description:
- * Enable hw power saving functions
- *
- * Return Value:
- * None.
- *
- */
-
-void vnt_enable_power_saving(struct vnt_private *priv, u16 listen_interval)
-{
- u16 aid = priv->current_aid | BIT(14) | BIT(15);
-
- /* set period of power up before TBTT */
- vnt_mac_write_word(priv, MAC_REG_PWBT, C_PWBT);
-
- if (priv->op_mode != NL80211_IFTYPE_ADHOC)
- /* set AID */
- vnt_mac_write_word(priv, MAC_REG_AIDATIM, aid);
-
- /* Warren:06-18-2004,the sequence must follow
- * PSEN->AUTOSLEEP->GO2DOZE
- */
- /* enable power saving hw function */
- vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_PSEN);
-
- /* Set AutoSleep */
- vnt_mac_reg_bits_on(priv, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
-
- /* Warren:MUST turn on this once before turn on AUTOSLEEP ,or the
- * AUTOSLEEP doesn't work
- */
- vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_GO2DOZE);
-
- /* always listen beacon */
- vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_ALBCN);
-
- dev_dbg(&priv->usb->dev, "PS:Power Saving Mode Enable...\n");
-}
-
-int vnt_disable_power_saving(struct vnt_private *priv)
-{
- int ret;
-
- /* disable power saving hw function */
- ret = vnt_control_out(priv, MESSAGE_TYPE_DISABLE_PS, 0,
- 0, 0, NULL);
- if (ret)
- return ret;
-
- /* clear AutoSleep */
- vnt_mac_reg_bits_off(priv, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
-
- /* set always listen beacon */
- vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_ALBCN);
-
- return 0;
-}
-
-/*
- *
- * Routine Description:
- * Check if Next TBTT must wake up
- *
- * Return Value:
- * None.
- *
- */
-
-int vnt_next_tbtt_wakeup(struct vnt_private *priv)
-{
- struct ieee80211_hw *hw = priv->hw;
- struct ieee80211_conf *conf = &hw->conf;
- int wake_up = false;
-
- if (conf->listen_interval > 1) {
- /* Turn on wake up to listen next beacon */
- vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_LNBCN);
- wake_up = true;
- }
-
- return wake_up;
-}
diff --git a/drivers/staging/vt6656/power.h b/drivers/staging/vt6656/power.h
deleted file mode 100644
index 9f9c70072933..000000000000
--- a/drivers/staging/vt6656/power.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handles 802.11 power management functions
- *
- * Author: Lyndon Chen
- *
- * Date: July 17, 2002
- *
- */
-
-#ifndef __POWER_H__
-#define __POWER_H__
-
-#define C_PWBT 1000 /* micro sec. power up before TBTT */
-
-int vnt_disable_power_saving(struct vnt_private *priv);
-void vnt_enable_power_saving(struct vnt_private *priv, u16 listen_interval);
-int vnt_next_tbtt_wakeup(struct vnt_private *priv);
-
-#endif /* __POWER_H__ */
diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c
deleted file mode 100644
index 464602c74727..000000000000
--- a/drivers/staging/vt6656/rf.c
+++ /dev/null
@@ -1,443 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: rf function code
- *
- * Author: Jerry Chen
- *
- * Date: Feb. 19, 2004
- *
- * Functions:
- * vnt_rf_write_embedded - Embedded write RF register via MAC
- *
- * Revision History:
- * RF_VT3226: RobertYu:20051111, VT3226C0 and before
- * RF_VT3226D0: RobertYu:20051228
- * RF_VT3342A0: RobertYu:20060609
- *
- */
-
-#include <linux/errno.h>
-#include "mac.h"
-#include "rf.h"
-#include "baseband.h"
-#include "usbpipe.h"
-
-#define CB_AL2230_INIT_SEQ 15
-#define CB_AL7230_INIT_SEQ 16
-#define CB_VT3226_INIT_SEQ 11
-#define CB_VT3342_INIT_SEQ 13
-
-static u8 al2230_init_table[CB_AL2230_INIT_SEQ][3] = {
- {0x03, 0xf7, 0x90},
- {0x03, 0x33, 0x31},
- {0x01, 0xb8, 0x02},
- {0x00, 0xff, 0xf3},
- {0x00, 0x05, 0xa4},
- {0x0f, 0x4d, 0xc5},
- {0x08, 0x05, 0xb6},
- {0x01, 0x47, 0xc7},
- {0x00, 0x06, 0x88},
- {0x04, 0x03, 0xb9},
- {0x00, 0xdb, 0xba},
- {0x00, 0x09, 0x9b},
- {0x0b, 0xdf, 0xfc},
- {0x00, 0x00, 0x0d},
- {0x00, 0x58, 0x0f}
-};
-
-static u8 al2230_channel_table0[CB_MAX_CHANNEL_24G][3] = {
- {0x03, 0xf7, 0x90},
- {0x03, 0xf7, 0x90},
- {0x03, 0xe7, 0x90},
- {0x03, 0xe7, 0x90},
- {0x03, 0xf7, 0xa0},
- {0x03, 0xf7, 0xa0},
- {0x03, 0xe7, 0xa0},
- {0x03, 0xe7, 0xa0},
- {0x03, 0xf7, 0xb0},
- {0x03, 0xf7, 0xb0},
- {0x03, 0xe7, 0xb0},
- {0x03, 0xe7, 0xb0},
- {0x03, 0xf7, 0xc0},
- {0x03, 0xe7, 0xc0}
-};
-
-static u8 al2230_channel_table1[CB_MAX_CHANNEL_24G][3] = {
- {0x03, 0x33, 0x31},
- {0x0b, 0x33, 0x31},
- {0x03, 0x33, 0x31},
- {0x0b, 0x33, 0x31},
- {0x03, 0x33, 0x31},
- {0x0b, 0x33, 0x31},
- {0x03, 0x33, 0x31},
- {0x0b, 0x33, 0x31},
- {0x03, 0x33, 0x31},
- {0x0b, 0x33, 0x31},
- {0x03, 0x33, 0x31},
- {0x0b, 0x33, 0x31},
- {0x03, 0x33, 0x31},
- {0x06, 0x66, 0x61}
-};
-
-static u8 vt3226_init_table[CB_VT3226_INIT_SEQ][3] = {
- {0x03, 0xff, 0x80},
- {0x02, 0x82, 0xa1},
- {0x03, 0xc6, 0xa2},
- {0x01, 0x97, 0x93},
- {0x03, 0x66, 0x64},
- {0x00, 0x61, 0xa5},
- {0x01, 0x7b, 0xd6},
- {0x00, 0x80, 0x17},
- {0x03, 0xf8, 0x08},
- {0x00, 0x02, 0x39},
- {0x02, 0x00, 0x2a}
-};
-
-static u8 vt3226d0_init_table[CB_VT3226_INIT_SEQ][3] = {
- {0x03, 0xff, 0x80},
- {0x03, 0x02, 0x21},
- {0x03, 0xc6, 0xa2},
- {0x01, 0x97, 0x93},
- {0x03, 0x66, 0x64},
- {0x00, 0x71, 0xa5},
- {0x01, 0x15, 0xc6},
- {0x01, 0x2e, 0x07},
- {0x00, 0x58, 0x08},
- {0x00, 0x02, 0x79},
- {0x02, 0x01, 0xaa}
-};
-
-static u8 vt3226_channel_table0[CB_MAX_CHANNEL_24G][3] = {
- {0x01, 0x97, 0x83},
- {0x01, 0x97, 0x83},
- {0x01, 0x97, 0x93},
- {0x01, 0x97, 0x93},
- {0x01, 0x97, 0x93},
- {0x01, 0x97, 0x93},
- {0x01, 0x97, 0xa3},
- {0x01, 0x97, 0xa3},
- {0x01, 0x97, 0xa3},
- {0x01, 0x97, 0xa3},
- {0x01, 0x97, 0xb3},
- {0x01, 0x97, 0xb3},
- {0x01, 0x97, 0xb3},
- {0x03, 0x37, 0xc3}
-};
-
-static u8 vt3226_channel_table1[CB_MAX_CHANNEL_24G][3] = {
- {0x02, 0x66, 0x64},
- {0x03, 0x66, 0x64},
- {0x00, 0x66, 0x64},
- {0x01, 0x66, 0x64},
- {0x02, 0x66, 0x64},
- {0x03, 0x66, 0x64},
- {0x00, 0x66, 0x64},
- {0x01, 0x66, 0x64},
- {0x02, 0x66, 0x64},
- {0x03, 0x66, 0x64},
- {0x00, 0x66, 0x64},
- {0x01, 0x66, 0x64},
- {0x02, 0x66, 0x64},
- {0x00, 0xcc, 0xc4}
-};
-
-static const u32 vt3226d0_lo_current_table[CB_MAX_CHANNEL_24G] = {
- 0x0135c600,
- 0x0135c600,
- 0x0235c600,
- 0x0235c600,
- 0x0235c600,
- 0x0335c600,
- 0x0335c600,
- 0x0335c600,
- 0x0335c600,
- 0x0335c600,
- 0x0335c600,
- 0x0335c600,
- 0x0335c600,
- 0x0135c600
-};
-
-enum {
- VNT_TABLE_INIT = 0,
- VNT_TABLE_INIT_2 = 0,
- VNT_TABLE_0 = 1,
- VNT_TABLE_1 = 2,
- VNT_TABLE_2 = 1
-};
-
-struct vnt_table_info {
- u8 *addr;
- int length;
-};
-
-static const struct vnt_table_info vnt_table_seq[][3] = {
- { /* RF_AL2230, RF_AL2230S init table, channel table 0 and 1 */
- {&al2230_init_table[0][0], CB_AL2230_INIT_SEQ * 3},
- {&al2230_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3},
- {&al2230_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3}
- }, { /* RF_VT3226 init table, channel table 0 and 1 */
- {&vt3226_init_table[0][0], CB_VT3226_INIT_SEQ * 3},
- {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3},
- {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3}
- }, { /* RF_VT3226D0 init table, channel table 0 and 1 */
- {&vt3226d0_init_table[0][0], CB_VT3226_INIT_SEQ * 3},
- {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3},
- {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3}
- }
-};
-
-/*
- * Description: Write to IF/RF, by embedded programming
- */
-int vnt_rf_write_embedded(struct vnt_private *priv, u32 data)
-{
- u8 reg_data[4];
-
- data |= (VNT_RF_REG_LEN << 3) | IFREGCTL_REGW;
-
- reg_data[0] = (u8)data;
- reg_data[1] = (u8)(data >> 8);
- reg_data[2] = (u8)(data >> 16);
- reg_data[3] = (u8)(data >> 24);
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_IFRF, 0, 0,
- ARRAY_SIZE(reg_data), reg_data);
-}
-
-static u8 vnt_rf_addpower(struct vnt_private *priv)
-{
- int base;
- s32 rssi = -priv->current_rssi;
-
- if (!rssi)
- return 7;
-
- if (priv->rf_type == RF_VT3226D0)
- base = -60;
- else
- base = -70;
-
- if (rssi < base)
- return ((rssi - base + 1) / -5) * 2 + 5;
-
- return 0;
-}
-
-/* Set Tx power by power level and rate */
-static int vnt_rf_set_txpower(struct vnt_private *priv, u8 power,
- struct ieee80211_channel *ch)
-{
- u32 power_setting = 0;
- int ret = 0;
-
- power += vnt_rf_addpower(priv);
- if (power > VNT_RF_MAX_POWER)
- power = VNT_RF_MAX_POWER;
-
- if (priv->power == power)
- return 0;
-
- priv->power = power;
-
- switch (priv->rf_type) {
- case RF_AL2230:
- power_setting = 0x0404090 | (power << 12);
-
- ret = vnt_rf_write_embedded(priv, power_setting);
- if (ret)
- return ret;
-
- if (ch->flags & IEEE80211_CHAN_NO_OFDM)
- ret = vnt_rf_write_embedded(priv, 0x0001b400);
- else
- ret = vnt_rf_write_embedded(priv, 0x0005a400);
-
- break;
- case RF_AL2230S:
- power_setting = 0x0404090 | (power << 12);
-
- ret = vnt_rf_write_embedded(priv, power_setting);
- if (ret)
- return ret;
-
- if (ch->flags & IEEE80211_CHAN_NO_OFDM) {
- ret = vnt_rf_write_embedded(priv, 0x040c1400);
- if (ret)
- return ret;
-
- ret = vnt_rf_write_embedded(priv, 0x00299b00);
- } else {
- ret = vnt_rf_write_embedded(priv, 0x0005a400);
- if (ret)
- return ret;
-
- ret = vnt_rf_write_embedded(priv, 0x00099b00);
- }
-
- break;
-
- case RF_VT3226:
- power_setting = ((0x3f - power) << 20) | (0x17 << 8);
-
- ret = vnt_rf_write_embedded(priv, power_setting);
- break;
- case RF_VT3226D0:
- if (ch->flags & IEEE80211_CHAN_NO_OFDM) {
- u16 hw_value = ch->hw_value;
-
- power_setting = ((0x3f - power) << 20) | (0xe07 << 8);
-
- ret = vnt_rf_write_embedded(priv, power_setting);
- if (ret)
- return ret;
-
- ret = vnt_rf_write_embedded(priv, 0x03c6a200);
- if (ret)
- return ret;
-
- dev_dbg(&priv->usb->dev,
- "%s 11b channel [%d]\n", __func__, hw_value);
-
- hw_value--;
-
- if (hw_value < ARRAY_SIZE(vt3226d0_lo_current_table)) {
- ret = vnt_rf_write_embedded(priv,
- vt3226d0_lo_current_table[hw_value]);
- if (ret)
- return ret;
- }
-
- ret = vnt_rf_write_embedded(priv, 0x015C0800);
- } else {
- dev_dbg(&priv->usb->dev,
- "@@@@ %s> 11G mode\n", __func__);
-
- power_setting = ((0x3f - power) << 20) | (0x7 << 8);
-
- ret = vnt_rf_write_embedded(priv, power_setting);
- if (ret)
- return ret;
-
- ret = vnt_rf_write_embedded(priv, 0x00C6A200);
- if (ret)
- return ret;
-
- ret = vnt_rf_write_embedded(priv, 0x016BC600);
- if (ret)
- return ret;
-
- ret = vnt_rf_write_embedded(priv, 0x00900800);
- }
-
- break;
-
- default:
- break;
- }
- return ret;
-}
-
-/* Set Tx power by channel number type */
-int vnt_rf_setpower(struct vnt_private *priv,
- struct ieee80211_channel *ch)
-{
- u16 channel;
- u8 power = priv->cck_pwr;
-
- if (!ch)
- return -EINVAL;
-
- /* set channel number to array number */
- channel = ch->hw_value - 1;
-
- if (ch->flags & IEEE80211_CHAN_NO_OFDM) {
- if (channel < ARRAY_SIZE(priv->cck_pwr_tbl))
- power = priv->cck_pwr_tbl[channel];
- } else if (ch->band == NL80211_BAND_5GHZ) {
- /* remove 14 channels to array size */
- channel -= 14;
-
- if (channel < ARRAY_SIZE(priv->ofdm_a_pwr_tbl))
- power = priv->ofdm_a_pwr_tbl[channel];
- } else {
- if (channel < ARRAY_SIZE(priv->ofdm_pwr_tbl))
- power = priv->ofdm_pwr_tbl[channel];
- }
-
- return vnt_rf_set_txpower(priv, power, ch);
-}
-
-/* Convert rssi to dbm */
-void vnt_rf_rssi_to_dbm(struct vnt_private *priv, u8 rssi, long *dbm)
-{
- u8 idx = ((rssi & 0xc0) >> 6) & 0x03;
- long b = rssi & 0x3f;
- long a = 0;
- u8 airoharf[4] = {0, 18, 0, 40};
-
- switch (priv->rf_type) {
- case RF_AL2230:
- case RF_AL2230S:
- case RF_VT3226:
- case RF_VT3226D0:
- a = airoharf[idx];
- break;
- default:
- break;
- }
-
- *dbm = -1 * (a + b * 2);
-}
-
-int vnt_rf_table_download(struct vnt_private *priv)
-{
- int ret;
- int idx = -1;
- const struct vnt_table_info *table_seq;
-
- switch (priv->rf_type) {
- case RF_AL2230:
- case RF_AL2230S:
- idx = 0;
- break;
- case RF_VT3226:
- idx = 1;
- break;
- case RF_VT3226D0:
- idx = 2;
- break;
- }
-
- if (idx < 0)
- return 0;
-
- table_seq = &vnt_table_seq[idx][0];
-
- /* Init Table */
- ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
- MESSAGE_REQUEST_RF_INIT,
- table_seq[VNT_TABLE_INIT].length,
- table_seq[VNT_TABLE_INIT].addr);
- if (ret)
- return ret;
-
- /* Channel Table 0 */
- ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
- MESSAGE_REQUEST_RF_CH0,
- table_seq[VNT_TABLE_0].length,
- table_seq[VNT_TABLE_0].addr);
- if (ret)
- return ret;
-
- /* Channel Table 1 */
- ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
- MESSAGE_REQUEST_RF_CH1,
- table_seq[VNT_TABLE_1].length,
- table_seq[VNT_TABLE_1].addr);
-
- return ret;
-}
diff --git a/drivers/staging/vt6656/rf.h b/drivers/staging/vt6656/rf.h
deleted file mode 100644
index b47e149875d1..000000000000
--- a/drivers/staging/vt6656/rf.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:
- *
- * Author: Jerry Chen
- *
- * Date: Feb. 19, 2004
- *
- */
-
-#ifndef __RF_H__
-#define __RF_H__
-
-#include "device.h"
-
-/* Baseband RF pair definition in eeprom (Bits 6..0) */
-#define RF_RFMD2959 0x01
-#define RF_MAXIMAG 0x02
-#define RF_AL2230 0x03
-#define RF_GCT5103 0x04
-#define RF_UW2451 0x05
-#define RF_MAXIMG 0x06
-#define RF_MAXIM2829 0x07
-#define RF_UW2452 0x08
-#define RF_VT3226 0x09
-#define RF_AIROHA7230 0x0a
-#define RF_UW2453 0x0b
-#define RF_VT3226D0 0x0c /* RobertYu:20051114 */
-#define RF_VT3342A0 0x0d /* RobertYu:20060609 */
-#define RF_AL2230S 0x0e
-
-#define RF_EMU 0x80
-#define RF_MASK 0x7F
-
-#define VNT_RF_MAX_POWER 0x3f
-#define VNT_RF_REG_LEN 0x17 /* 24 bit length */
-
-int vnt_rf_write_embedded(struct vnt_private *priv, u32 data);
-int vnt_rf_setpower(struct vnt_private *priv, struct ieee80211_channel *ch);
-void vnt_rf_rssi_to_dbm(struct vnt_private *priv, u8 rssi, long *dbm);
-int vnt_rf_table_download(struct vnt_private *priv);
-
-#endif /* __RF_H__ */
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
deleted file mode 100644
index cd99091c6c28..000000000000
--- a/drivers/staging/vt6656/rxtx.c
+++ /dev/null
@@ -1,730 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: handle WMAC/802.3/802.11 rx & tx functions
- *
- * Author: Lyndon Chen
- *
- * Date: May 20, 2003
- *
- * Functions:
- * vnt_generate_tx_parameter - Generate tx dma required parameter.
- * vnt_get_rsvtime- get frame reserved time
- * vnt_fill_cts_head- fulfill CTS ctl header
- *
- * Revision History:
- *
- */
-
-#include <linux/etherdevice.h>
-#include "device.h"
-#include "rxtx.h"
-#include "card.h"
-#include "mac.h"
-#include "rf.h"
-#include "usbpipe.h"
-
-static const u16 vnt_time_stampoff[2][MAX_RATE] = {
- /* Long Preamble */
- {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23},
-
- /* Short Preamble */
- {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23},
-};
-
-#define DATADUR_B 10
-#define DATADUR_A 11
-
-static const u8 vnt_phy_signal[] = {
- 0x00, /* RATE_1M */
- 0x01, /* RATE_2M */
- 0x02, /* RATE_5M */
- 0x03, /* RATE_11M */
- 0x8b, /* RATE_6M */
- 0x8f, /* RATE_9M */
- 0x8a, /* RATE_12M */
- 0x8e, /* RATE_18M */
- 0x89, /* RATE_24M */
- 0x8d, /* RATE_36M */
- 0x88, /* RATE_48M */
- 0x8c /* RATE_54M */
-};
-
-static struct vnt_usb_send_context
- *vnt_get_free_context(struct vnt_private *priv)
-{
- struct vnt_usb_send_context *context = NULL;
- int ii;
-
- for (ii = 0; ii < priv->num_tx_context; ii++) {
- if (!priv->tx_context[ii])
- return NULL;
-
- context = priv->tx_context[ii];
- if (!context->in_use) {
- context->in_use = true;
- return context;
- }
- }
-
- if (ii == priv->num_tx_context) {
- dev_dbg(&priv->usb->dev, "%s No Free Tx Context\n", __func__);
-
- ieee80211_stop_queues(priv->hw);
- }
-
- return NULL;
-}
-
-/* Get Length, Service, and Signal fields of Phy for Tx */
-static void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length,
- u16 tx_rate, u8 pkt_type,
- struct vnt_phy_field *phy)
-{
- u32 bit_count;
- u32 count = 0;
- u32 tmp;
- int ext_bit;
- int i;
- u8 mask = 0;
- u8 preamble_type = priv->preamble_type;
-
- bit_count = frame_length * 8;
- ext_bit = false;
-
- switch (tx_rate) {
- case RATE_1M:
- count = bit_count;
- break;
- case RATE_2M:
- count = bit_count / 2;
- break;
- case RATE_5M:
- count = DIV_ROUND_UP(bit_count * 10, 55);
- break;
- case RATE_11M:
- count = bit_count / 11;
- tmp = count * 11;
-
- if (tmp != bit_count) {
- count++;
-
- if ((bit_count - tmp) <= 3)
- ext_bit = true;
- }
-
- break;
- }
-
- if (tx_rate > RATE_11M) {
- if (pkt_type == PK_TYPE_11A)
- mask = BIT(4);
- } else if (tx_rate > RATE_1M) {
- if (preamble_type == PREAMBLE_SHORT)
- mask = BIT(3);
- }
-
- i = tx_rate > RATE_54M ? RATE_54M : tx_rate;
- phy->signal = vnt_phy_signal[i] | mask;
- phy->service = 0x00;
-
- if (pkt_type == PK_TYPE_11B) {
- if (ext_bit)
- phy->service |= 0x80;
- phy->len = cpu_to_le16((u16)count);
- } else {
- phy->len = cpu_to_le16((u16)frame_length);
- }
-}
-
-static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate)
-{
- return cpu_to_le16(vnt_time_stampoff[priv->preamble_type % 2]
- [rate % MAX_RATE]);
-}
-
-static __le16 vnt_rxtx_rsvtime_le16(struct vnt_usb_send_context *context)
-{
- struct vnt_private *priv = context->priv;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(context->skb);
- struct ieee80211_rate *rate = ieee80211_get_tx_rate(priv->hw, info);
-
- return ieee80211_generic_frame_duration(priv->hw,
- info->control.vif, info->band,
- context->frame_len,
- rate);
-}
-
-static __le16 vnt_get_rts_duration(struct vnt_usb_send_context *context)
-{
- struct vnt_private *priv = context->priv;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(context->skb);
-
- return ieee80211_rts_duration(priv->hw, priv->vif,
- context->frame_len, info);
-}
-
-static __le16 vnt_get_cts_duration(struct vnt_usb_send_context *context)
-{
- struct vnt_private *priv = context->priv;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(context->skb);
-
- return ieee80211_ctstoself_duration(priv->hw, priv->vif,
- context->frame_len, info);
-}
-
-static void vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context,
- struct vnt_tx_datahead_g *buf)
-{
- struct vnt_private *priv = tx_context->priv;
- struct ieee80211_hdr *hdr =
- (struct ieee80211_hdr *)tx_context->skb->data;
- u32 frame_len = tx_context->frame_len;
- u16 rate = tx_context->tx_rate;
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, frame_len, rate, tx_context->pkt_type, &buf->a);
- vnt_get_phy_field(priv, frame_len, priv->top_cck_basic_rate,
- PK_TYPE_11B, &buf->b);
-
- /* Get Duration and TimeStamp */
- buf->duration_a = hdr->duration_id;
- buf->duration_b = hdr->duration_id;
- buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate);
- buf->time_stamp_off_b = vnt_time_stamp_off(priv,
- priv->top_cck_basic_rate);
-}
-
-static void vnt_rxtx_datahead_ab(struct vnt_usb_send_context *tx_context,
- struct vnt_tx_datahead_ab *buf)
-{
- struct vnt_private *priv = tx_context->priv;
- struct ieee80211_hdr *hdr =
- (struct ieee80211_hdr *)tx_context->skb->data;
- u32 frame_len = tx_context->frame_len;
- u16 rate = tx_context->tx_rate;
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, frame_len, rate,
- tx_context->pkt_type, &buf->ab);
-
- /* Get Duration and TimeStampOff */
- buf->duration = hdr->duration_id;
- buf->time_stamp_off = vnt_time_stamp_off(priv, rate);
-}
-
-static void vnt_fill_ieee80211_rts(struct vnt_usb_send_context *tx_context,
- struct ieee80211_rts *rts, __le16 duration)
-{
- struct ieee80211_hdr *hdr =
- (struct ieee80211_hdr *)tx_context->skb->data;
-
- rts->duration = duration;
- rts->frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
-
- ether_addr_copy(rts->ra, hdr->addr1);
- ether_addr_copy(rts->ta, hdr->addr2);
-}
-
-static void vnt_rxtx_rts_g_head(struct vnt_usb_send_context *tx_context,
- struct vnt_rts_g *buf)
-{
- struct vnt_private *priv = tx_context->priv;
- u16 rts_frame_len = 20;
-
- vnt_get_phy_field(priv, rts_frame_len, priv->top_cck_basic_rate,
- PK_TYPE_11B, &buf->b);
- vnt_get_phy_field(priv, rts_frame_len, priv->top_ofdm_basic_rate,
- tx_context->pkt_type, &buf->a);
-
- buf->duration_bb = vnt_get_rts_duration(tx_context);
- buf->duration_aa = buf->duration_bb;
- buf->duration_ba = buf->duration_bb;
-
- vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration_aa);
-
- vnt_rxtx_datahead_g(tx_context, &buf->data_head);
-}
-
-static void vnt_rxtx_rts_ab_head(struct vnt_usb_send_context *tx_context,
- struct vnt_rts_ab *buf)
-{
- struct vnt_private *priv = tx_context->priv;
- u16 rts_frame_len = 20;
-
- vnt_get_phy_field(priv, rts_frame_len, priv->top_ofdm_basic_rate,
- tx_context->pkt_type, &buf->ab);
-
- buf->duration = vnt_get_rts_duration(tx_context);
-
- vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration);
-
- vnt_rxtx_datahead_ab(tx_context, &buf->data_head);
-}
-
-static void vnt_fill_cts_head(struct vnt_usb_send_context *tx_context,
- union vnt_tx_data_head *head)
-{
- struct vnt_private *priv = tx_context->priv;
- struct vnt_cts *buf = &head->cts_g;
- u32 cts_frame_len = 14;
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, cts_frame_len, priv->top_cck_basic_rate,
- PK_TYPE_11B, &buf->b);
- /* Get CTSDuration_ba */
- buf->duration_ba = vnt_get_cts_duration(tx_context);
- /*Get CTS Frame body*/
- buf->data.duration = buf->duration_ba;
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
-
- ether_addr_copy(buf->data.ra, priv->current_net_addr);
-
- vnt_rxtx_datahead_g(tx_context, &buf->data_head);
-}
-
-/* returns true if mic_hdr is needed */
-static bool vnt_fill_txkey(struct vnt_tx_buffer *tx_buffer, struct sk_buff *skb)
-{
- struct vnt_tx_fifo_head *fifo = &tx_buffer->fifo_head;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_key_conf *tx_key = info->control.hw_key;
- struct vnt_mic_hdr *mic_hdr;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- u64 pn64;
- u16 payload_len = skb->len;
- u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb));
-
- /* strip header and icv len from payload */
- payload_len -= ieee80211_get_hdrlen_from_skb(skb);
- payload_len -= tx_key->icv_len;
-
- switch (tx_key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- memcpy(fifo->tx_key, iv, 3);
- memcpy(fifo->tx_key + 3, tx_key->key, tx_key->keylen);
-
- if (tx_key->keylen == WLAN_KEY_LEN_WEP40) {
- memcpy(fifo->tx_key + 8, iv, 3);
- memcpy(fifo->tx_key + 11,
- tx_key->key, WLAN_KEY_LEN_WEP40);
- }
-
- fifo->frag_ctl |= cpu_to_le16(FRAGCTL_LEGACY);
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- ieee80211_get_tkip_p2k(tx_key, skb, fifo->tx_key);
-
- fifo->frag_ctl |= cpu_to_le16(FRAGCTL_TKIP);
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- if (info->control.use_cts_prot) {
- if (info->control.use_rts)
- mic_hdr = &tx_buffer->tx_head.tx_rts.tx.mic.hdr;
- else
- mic_hdr = &tx_buffer->tx_head.tx_cts.tx.mic.hdr;
- } else {
- mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
- }
-
- mic_hdr->id = 0x59;
- mic_hdr->payload_len = cpu_to_be16(payload_len);
- ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2);
-
- pn64 = atomic64_read(&tx_key->tx_pn);
- mic_hdr->ccmp_pn[5] = pn64;
- mic_hdr->ccmp_pn[4] = pn64 >> 8;
- mic_hdr->ccmp_pn[3] = pn64 >> 16;
- mic_hdr->ccmp_pn[2] = pn64 >> 24;
- mic_hdr->ccmp_pn[1] = pn64 >> 32;
- mic_hdr->ccmp_pn[0] = pn64 >> 40;
-
- if (ieee80211_has_a4(hdr->frame_control))
- mic_hdr->hlen = cpu_to_be16(28);
- else
- mic_hdr->hlen = cpu_to_be16(22);
-
- ether_addr_copy(mic_hdr->addr1, hdr->addr1);
- ether_addr_copy(mic_hdr->addr2, hdr->addr2);
- ether_addr_copy(mic_hdr->addr3, hdr->addr3);
-
- mic_hdr->frame_control = cpu_to_le16(le16_to_cpu(hdr->frame_control) & 0xc78f);
- mic_hdr->seq_ctrl = cpu_to_le16(le16_to_cpu(hdr->seq_ctrl) & 0xf);
-
- if (ieee80211_has_a4(hdr->frame_control))
- ether_addr_copy(mic_hdr->addr4, hdr->addr4);
-
- memcpy(fifo->tx_key, tx_key->key, WLAN_KEY_LEN_CCMP);
-
- fifo->frag_ctl |= cpu_to_le16(FRAGCTL_AES);
- return true;
- default:
- break;
- }
-
- return false;
-}
-
-static void vnt_rxtx_rts(struct vnt_usb_send_context *tx_context)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_context->skb);
- struct vnt_tx_buffer *tx_buffer = tx_context->tx_buffer;
- union vnt_tx_head *tx_head = &tx_buffer->tx_head;
- struct vnt_rrv_time_rts *buf = &tx_head->tx_rts.rts;
- union vnt_tx_data_head *head = &tx_head->tx_rts.tx.head;
-
- buf->rts_rrv_time_aa = vnt_get_rts_duration(tx_context);
- buf->rts_rrv_time_ba = buf->rts_rrv_time_aa;
- buf->rts_rrv_time_bb = buf->rts_rrv_time_aa;
-
- buf->rrv_time_a = vnt_rxtx_rsvtime_le16(tx_context);
- buf->rrv_time_b = buf->rrv_time_a;
-
- if (info->control.hw_key) {
- if (vnt_fill_txkey(tx_buffer, tx_context->skb))
- head = &tx_head->tx_rts.tx.mic.head;
- }
-
- vnt_rxtx_rts_g_head(tx_context, &head->rts_g);
-}
-
-static void vnt_rxtx_cts(struct vnt_usb_send_context *tx_context)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_context->skb);
- struct vnt_tx_buffer *tx_buffer = tx_context->tx_buffer;
- union vnt_tx_head *tx_head = &tx_buffer->tx_head;
- struct vnt_rrv_time_cts *buf = &tx_head->tx_cts.cts;
- union vnt_tx_data_head *head = &tx_head->tx_cts.tx.head;
-
- buf->rrv_time_a = vnt_rxtx_rsvtime_le16(tx_context);
- buf->rrv_time_b = buf->rrv_time_a;
-
- buf->cts_rrv_time_ba = vnt_get_cts_duration(tx_context);
-
- if (info->control.hw_key) {
- if (vnt_fill_txkey(tx_buffer, tx_context->skb))
- head = &tx_head->tx_cts.tx.mic.head;
- }
-
- vnt_fill_cts_head(tx_context, head);
-}
-
-static void vnt_rxtx_ab(struct vnt_usb_send_context *tx_context)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_context->skb);
- struct vnt_tx_buffer *tx_buffer = tx_context->tx_buffer;
- union vnt_tx_head *tx_head = &tx_buffer->tx_head;
- struct vnt_rrv_time_ab *buf = &tx_head->tx_ab.ab;
- union vnt_tx_data_head *head = &tx_head->tx_ab.tx.head;
-
- buf->rrv_time = vnt_rxtx_rsvtime_le16(tx_context);
-
- if (info->control.hw_key) {
- if (vnt_fill_txkey(tx_buffer, tx_context->skb))
- head = &tx_head->tx_ab.tx.mic.head;
- }
-
- if (info->control.use_rts) {
- buf->rts_rrv_time = vnt_get_rts_duration(tx_context);
-
- vnt_rxtx_rts_ab_head(tx_context, &head->rts_ab);
-
- return;
- }
-
- vnt_rxtx_datahead_ab(tx_context, &head->data_head_ab);
-}
-
-static void vnt_generate_tx_parameter(struct vnt_usb_send_context *tx_context)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_context->skb);
-
- if (info->control.use_cts_prot) {
- if (info->control.use_rts) {
- vnt_rxtx_rts(tx_context);
-
- return;
- }
-
- vnt_rxtx_cts(tx_context);
-
- return;
- }
-
- vnt_rxtx_ab(tx_context);
-}
-
-static u16 vnt_get_hdr_size(struct ieee80211_tx_info *info)
-{
- u16 size = sizeof(struct vnt_tx_datahead_ab);
-
- if (info->control.use_cts_prot) {
- if (info->control.use_rts)
- size = sizeof(struct vnt_rts_g);
- else
- size = sizeof(struct vnt_cts);
- } else if (info->control.use_rts) {
- size = sizeof(struct vnt_rts_ab);
- }
-
- if (info->control.hw_key) {
- if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP)
- size += sizeof(struct vnt_mic_hdr);
- }
-
- /* Get rrv_time header */
- if (info->control.use_cts_prot) {
- if (info->control.use_rts)
- size += sizeof(struct vnt_rrv_time_rts);
- else
- size += sizeof(struct vnt_rrv_time_cts);
- } else {
- size += sizeof(struct vnt_rrv_time_ab);
- }
-
- size += sizeof(struct vnt_tx_fifo_head);
-
- return size;
-}
-
-int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_tx_rate *tx_rate = &info->control.rates[0];
- struct ieee80211_rate *rate;
- struct ieee80211_hdr *hdr;
- struct vnt_tx_buffer *tx_buffer;
- struct vnt_tx_fifo_head *tx_buffer_head;
- struct vnt_usb_send_context *tx_context;
- unsigned long flags;
- u8 pkt_type;
-
- hdr = (struct ieee80211_hdr *)(skb->data);
-
- rate = ieee80211_get_tx_rate(priv->hw, info);
-
- if (rate->hw_value > RATE_11M) {
- if (info->band == NL80211_BAND_5GHZ) {
- pkt_type = PK_TYPE_11A;
- } else {
- if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
- if (priv->basic_rates & VNT_B_RATES)
- pkt_type = PK_TYPE_11GB;
- else
- pkt_type = PK_TYPE_11GA;
- } else {
- pkt_type = PK_TYPE_11A;
- }
- }
- } else {
- pkt_type = PK_TYPE_11B;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
-
- tx_context = vnt_get_free_context(priv);
- if (!tx_context) {
- dev_dbg(&priv->usb->dev, "%s No free context\n", __func__);
- spin_unlock_irqrestore(&priv->lock, flags);
- return -ENOMEM;
- }
-
- tx_context->pkt_type = pkt_type;
- tx_context->frame_len = skb->len + 4;
- tx_context->tx_rate = rate->hw_value;
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- tx_context->skb = skb_clone(skb, GFP_ATOMIC);
- if (!tx_context->skb) {
- tx_context->in_use = false;
- return -ENOMEM;
- }
-
- tx_buffer = skb_push(skb, vnt_get_hdr_size(info));
- tx_context->tx_buffer = tx_buffer;
- tx_buffer_head = &tx_buffer->fifo_head;
-
- tx_context->type = CONTEXT_DATA_PACKET;
-
- /*Set fifo controls */
- if (pkt_type == PK_TYPE_11A)
- tx_buffer_head->fifo_ctl = 0;
- else if (pkt_type == PK_TYPE_11B)
- tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11B);
- else if (pkt_type == PK_TYPE_11GB)
- tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GB);
- else if (pkt_type == PK_TYPE_11GA)
- tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GA);
-
- if (!ieee80211_is_data(hdr->frame_control)) {
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT |
- FIFOCTL_ISDMA0);
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_TMOEN);
-
- tx_buffer_head->time_stamp =
- cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
- } else {
- tx_buffer_head->time_stamp =
- cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);
- }
-
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_NEEDACK);
-
- if (ieee80211_has_retry(hdr->frame_control))
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LRETRY);
-
- if (info->control.use_rts)
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_RTS);
-
- if (ieee80211_has_a4(hdr->frame_control))
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LHEAD);
-
- tx_buffer_head->frag_ctl =
- cpu_to_le16(ieee80211_hdrlen(hdr->frame_control) << 10);
-
- if (info->control.hw_key)
- tx_context->frame_len += info->control.hw_key->icv_len;
-
- tx_buffer_head->current_rate = cpu_to_le16(rate->hw_value);
-
- vnt_generate_tx_parameter(tx_context);
-
- tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG);
-
- priv->seq_counter = (le16_to_cpu(hdr->seq_ctrl) &
- IEEE80211_SCTL_SEQ) >> 4;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- if (vnt_tx_context(priv, tx_context, skb)) {
- dev_kfree_skb(tx_context->skb);
- spin_unlock_irqrestore(&priv->lock, flags);
- return -EIO;
- }
-
- dev_kfree_skb(skb);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-static int vnt_beacon_xmit(struct vnt_private *priv, struct sk_buff *skb)
-{
- struct vnt_tx_short_buf_head *short_head;
- struct ieee80211_tx_info *info;
- struct vnt_usb_send_context *context;
- struct ieee80211_mgmt *mgmt_hdr;
- unsigned long flags;
- u32 frame_size = skb->len + 4;
- u16 current_rate;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- context = vnt_get_free_context(priv);
- if (!context) {
- dev_dbg(&priv->usb->dev, "%s No free context!\n", __func__);
- spin_unlock_irqrestore(&priv->lock, flags);
- return -ENOMEM;
- }
-
- context->skb = skb;
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- mgmt_hdr = (struct ieee80211_mgmt *)skb->data;
- short_head = skb_push(skb, sizeof(*short_head));
-
- if (priv->bb_type == BB_TYPE_11A) {
- current_rate = RATE_6M;
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, frame_size, current_rate,
- PK_TYPE_11A, &short_head->ab);
-
- /* Get TimeStampOff */
- short_head->time_stamp_off =
- vnt_time_stamp_off(priv, current_rate);
- } else {
- current_rate = RATE_1M;
- short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_11B);
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, frame_size, current_rate,
- PK_TYPE_11B, &short_head->ab);
-
- /* Get TimeStampOff */
- short_head->time_stamp_off =
- vnt_time_stamp_off(priv, current_rate);
- }
-
- /* Get Duration */
- short_head->duration = mgmt_hdr->duration;
-
- /* time stamp always 0 */
- mgmt_hdr->u.beacon.timestamp = 0;
-
- info = IEEE80211_SKB_CB(skb);
- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)mgmt_hdr;
-
- hdr->duration_id = 0;
- hdr->seq_ctrl = cpu_to_le16(priv->seq_counter << 4);
- }
-
- priv->seq_counter++;
- if (priv->seq_counter > 0x0fff)
- priv->seq_counter = 0;
-
- context->type = CONTEXT_BEACON_PACKET;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- if (vnt_tx_context(priv, context, skb))
- ieee80211_free_txskb(priv->hw, context->skb);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif)
-{
- struct sk_buff *beacon;
-
- beacon = ieee80211_beacon_get(priv->hw, vif, 0);
- if (!beacon)
- return -ENOMEM;
-
- if (vnt_beacon_xmit(priv, beacon)) {
- ieee80211_free_txskb(priv->hw, beacon);
- return -ENODEV;
- }
-
- return 0;
-}
-
-int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf)
-{
- vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
-
- vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
-
- vnt_mac_set_beacon_interval(priv, conf->beacon_int);
-
- vnt_clear_current_tsf(priv);
-
- vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
-
- vnt_reset_next_tbtt(priv, conf->beacon_int);
-
- return vnt_beacon_make(priv, vif);
-}
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
deleted file mode 100644
index b9df0854b4b0..000000000000
--- a/drivers/staging/vt6656/rxtx.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:
- *
- * Author: Jerry Chen
- *
- * Date: Jun. 27, 2002
- *
- */
-
-#ifndef __RXTX_H__
-#define __RXTX_H__
-
-#include "device.h"
-#include "wcmd.h"
-#include "baseband.h"
-
-#define DEFAULT_MGN_LIFETIME_RES_64us 125 /* 64us */
-#define DEFAULT_MSDU_LIFETIME_RES_64us 8000
-
-/* Length, Service, and Signal fields of Phy for Tx */
-struct vnt_phy_field {
- u8 signal;
- u8 service;
- __le16 len;
-} __packed;
-
-/* MIC HDR data header */
-struct vnt_mic_hdr {
- u8 id;
- u8 tx_priority;
- u8 mic_addr2[6];
- u8 ccmp_pn[IEEE80211_CCMP_PN_LEN];
- __be16 payload_len;
- __be16 hlen;
- __le16 frame_control;
- u8 addr1[6];
- u8 addr2[6];
- u8 addr3[6];
- __le16 seq_ctrl;
- u8 addr4[6];
- u16 packing; /* packing to 48 bytes */
-} __packed;
-
-/* RsvTime buffer header */
-struct vnt_rrv_time_rts {
- __le16 rts_rrv_time_ba;
- __le16 rts_rrv_time_aa;
- __le16 rts_rrv_time_bb;
- u16 wReserved;
- __le16 rrv_time_b;
- __le16 rrv_time_a;
-} __packed;
-
-struct vnt_rrv_time_cts {
- __le16 cts_rrv_time_ba;
- u16 wReserved;
- __le16 rrv_time_b;
- __le16 rrv_time_a;
-} __packed;
-
-struct vnt_rrv_time_ab {
- __le16 rts_rrv_time;
- __le16 rrv_time;
-} __packed;
-
-/* TX data header */
-struct vnt_tx_datahead_g {
- struct vnt_phy_field b;
- struct vnt_phy_field a;
- __le16 duration_b;
- __le16 duration_a;
- __le16 time_stamp_off_b;
- __le16 time_stamp_off_a;
-} __packed;
-
-struct vnt_tx_datahead_ab {
- struct vnt_phy_field ab;
- __le16 duration;
- __le16 time_stamp_off;
-} __packed;
-
-/* RTS buffer header */
-struct vnt_rts_g {
- struct vnt_phy_field b;
- struct vnt_phy_field a;
- __le16 duration_ba;
- __le16 duration_aa;
- __le16 duration_bb;
- u16 wReserved;
- struct ieee80211_rts data;
- struct vnt_tx_datahead_g data_head;
-} __packed __aligned(2);
-
-struct vnt_rts_ab {
- struct vnt_phy_field ab;
- __le16 duration;
- u16 wReserved;
- struct ieee80211_rts data;
- struct vnt_tx_datahead_ab data_head;
-} __packed __aligned(2);
-
-/* CTS buffer header */
-struct vnt_cts {
- struct vnt_phy_field b;
- __le16 duration_ba;
- u16 wReserved;
- struct ieee80211_cts data;
- u16 reserved2;
- struct vnt_tx_datahead_g data_head;
-} __packed __aligned(2);
-
-union vnt_tx_data_head {
- /* rts g */
- struct vnt_rts_g rts_g;
- /* rts a/b */
- struct vnt_rts_ab rts_ab;
- /* cts g */
- struct vnt_cts cts_g;
- /* no rts/cts */
- struct vnt_tx_datahead_ab data_head_ab;
-};
-
-struct vnt_tx_mic_hdr {
- struct vnt_mic_hdr hdr;
- union vnt_tx_data_head head;
-} __packed;
-
-union vnt_tx {
- struct vnt_tx_mic_hdr mic;
- union vnt_tx_data_head head;
-};
-
-union vnt_tx_head {
- struct {
- struct vnt_rrv_time_rts rts;
- union vnt_tx tx;
- } __packed tx_rts;
- struct {
- struct vnt_rrv_time_cts cts;
- union vnt_tx tx;
- } __packed tx_cts;
- struct {
- struct vnt_rrv_time_ab ab;
- union vnt_tx tx;
- } __packed tx_ab;
-};
-
-struct vnt_tx_fifo_head {
- u8 tx_key[WLAN_KEY_LEN_CCMP];
- __le16 fifo_ctl;
- __le16 time_stamp;
- __le16 frag_ctl;
- __le16 current_rate;
-} __packed;
-
-struct vnt_tx_buffer {
- struct vnt_tx_fifo_head fifo_head;
- union vnt_tx_head tx_head;
-} __packed;
-
-struct vnt_tx_short_buf_head {
- __le16 fifo_ctl;
- u16 time_stamp;
- struct vnt_phy_field ab;
- __le16 duration;
- __le16 time_stamp_off;
-} __packed;
-
-int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb);
-int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif);
-int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf);
-
-#endif /* __RXTX_H__ */
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
deleted file mode 100644
index d505b4b69ba4..000000000000
--- a/drivers/staging/vt6656/usbpipe.c
+++ /dev/null
@@ -1,506 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handle USB control endpoint
- *
- * Author: Warren Hsu
- *
- * Date: Mar. 29, 2005
- *
- * Functions:
- * vnt_control_out - Write variable length bytes to MEM/BB/MAC/EEPROM
- * vnt_control_in - Read variable length bytes from MEM/BB/MAC/EEPROM
- * vnt_control_out_u8 - Write one byte to MEM/BB/MAC/EEPROM
- * vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM
- *
- * Revision History:
- * 04-05-2004 Jerry Chen: Initial release
- * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,
- * ControlvMaskByte
- *
- */
-
-#include "rxtx.h"
-#include "desc.h"
-#include "device.h"
-#include "usbpipe.h"
-#include "mac.h"
-#include "rf.h"
-
-#define USB_CTL_WAIT 500 /* ms */
-
-int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
- u16 index, u16 length, const u8 *buffer)
-{
- int ret = 0;
- u8 *usb_buffer;
-
- if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
- ret = -EINVAL;
- goto end;
- }
-
- mutex_lock(&priv->usb_lock);
-
- usb_buffer = kmemdup(buffer, length, GFP_KERNEL);
- if (!usb_buffer) {
- ret = -ENOMEM;
- goto end_unlock;
- }
-
- ret = usb_control_msg(priv->usb,
- usb_sndctrlpipe(priv->usb, 0),
- request, 0x40, value,
- index, usb_buffer, length, USB_CTL_WAIT);
-
- kfree(usb_buffer);
-
- if (ret == (int)length)
- ret = 0;
- else
- ret = -EIO;
-
-end_unlock:
- mutex_unlock(&priv->usb_lock);
-end:
- return ret;
-}
-
-int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
-{
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE,
- reg_off, reg, sizeof(u8), &data);
-}
-
-int vnt_control_out_blocks(struct vnt_private *priv,
- u16 block, u8 reg, u16 length, const u8 *data)
-{
- int ret = 0, i;
-
- for (i = 0; i < length; i += block) {
- u16 len = min_t(int, length - i, block);
-
- ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE,
- i, reg, len, data + i);
- if (ret)
- goto end;
- }
-end:
- return ret;
-}
-
-int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
- u16 index, u16 length, u8 *buffer)
-{
- int ret = 0;
- u8 *usb_buffer;
-
- if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
- ret = -EINVAL;
- goto end;
- }
-
- mutex_lock(&priv->usb_lock);
-
- usb_buffer = kmalloc(length, GFP_KERNEL);
- if (!usb_buffer) {
- ret = -ENOMEM;
- goto end_unlock;
- }
-
- ret = usb_control_msg(priv->usb,
- usb_rcvctrlpipe(priv->usb, 0),
- request, 0xc0, value,
- index, usb_buffer, length, USB_CTL_WAIT);
-
- if (ret == length)
- memcpy(buffer, usb_buffer, length);
-
- kfree(usb_buffer);
-
- if (ret == (int)length)
- ret = 0;
- else
- ret = -EIO;
-
-end_unlock:
- mutex_unlock(&priv->usb_lock);
-end:
- return ret;
-}
-
-int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data)
-{
- return vnt_control_in(priv, MESSAGE_TYPE_READ,
- reg_off, reg, sizeof(u8), data);
-}
-
-static int vnt_int_report_rate(struct vnt_private *priv, u8 pkt_no, u8 tsr)
-{
- struct vnt_usb_send_context *context;
- struct ieee80211_tx_info *info;
- u8 tx_retry = (tsr & 0xf0) >> 4;
- s8 idx;
-
- if (pkt_no >= priv->num_tx_context)
- return -EINVAL;
-
- context = priv->tx_context[pkt_no];
-
- if (!context->skb)
- return -EINVAL;
-
- info = IEEE80211_SKB_CB(context->skb);
- idx = info->control.rates[0].idx;
-
- ieee80211_tx_info_clear_status(info);
-
- info->status.rates[0].count = tx_retry;
-
- if (!(tsr & TSR_TMO)) {
- info->status.rates[0].idx = idx;
-
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
- info->flags |= IEEE80211_TX_STAT_ACK;
- }
-
- ieee80211_tx_status_irqsafe(priv->hw, context->skb);
-
- context->in_use = false;
-
- return 0;
-}
-
-static void vnt_int_process_data(struct vnt_private *priv)
-{
- struct vnt_interrupt_data *int_data;
- struct ieee80211_low_level_stats *low_stats = &priv->low_stats;
-
- dev_dbg(&priv->usb->dev, "---->s_nsInterruptProcessData\n");
-
- int_data = (struct vnt_interrupt_data *)priv->int_buf.data_buf;
-
- if (int_data->tsr0 & TSR_VALID)
- vnt_int_report_rate(priv, int_data->pkt0, int_data->tsr0);
-
- if (int_data->tsr1 & TSR_VALID)
- vnt_int_report_rate(priv, int_data->pkt1, int_data->tsr1);
-
- if (int_data->tsr2 & TSR_VALID)
- vnt_int_report_rate(priv, int_data->pkt2, int_data->tsr2);
-
- if (int_data->tsr3 & TSR_VALID)
- vnt_int_report_rate(priv, int_data->pkt3, int_data->tsr3);
-
- if (!int_data->isr0)
- return;
-
- if (int_data->isr0 & ISR_BNTX && priv->op_mode == NL80211_IFTYPE_AP)
- vnt_schedule_command(priv, WLAN_CMD_BECON_SEND);
-
- priv->current_tsf = le64_to_cpu(int_data->tsf);
-
- low_stats->dot11RTSSuccessCount += int_data->rts_success;
- low_stats->dot11RTSFailureCount += int_data->rts_fail;
- low_stats->dot11ACKFailureCount += int_data->ack_fail;
- low_stats->dot11FCSErrorCount += int_data->fcs_err;
-}
-
-static void vnt_start_interrupt_urb_complete(struct urb *urb)
-{
- struct vnt_private *priv = urb->context;
- int status = urb->status;
-
- switch (status) {
- case 0:
- case -ETIMEDOUT:
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- return;
- default:
- break;
- }
-
- if (status)
- dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status);
- else
- vnt_int_process_data(priv);
-
- if (!test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
- status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
-
- if (status)
- dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
-}
-
-int vnt_start_interrupt_urb(struct vnt_private *priv)
-{
- int ret = 0;
-
- dev_dbg(&priv->usb->dev, "---->Interrupt Polling Thread\n");
-
- usb_fill_int_urb(priv->interrupt_urb,
- priv->usb,
- usb_rcvintpipe(priv->usb, 1),
- priv->int_buf.data_buf,
- MAX_INTERRUPT_SIZE,
- vnt_start_interrupt_urb_complete,
- priv,
- priv->int_interval);
-
- ret = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
- if (ret)
- dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", ret);
-
- return ret;
-}
-
-static int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb,
- unsigned long bytes_received)
-{
- struct ieee80211_hw *hw = priv->hw;
- struct ieee80211_supported_band *sband;
- struct sk_buff *skb;
- struct ieee80211_rx_status *rx_status;
- struct vnt_rx_header *head;
- struct vnt_rx_tail *tail;
- u32 frame_size;
- int ii;
- u16 rx_bitrate, pay_load_with_padding;
- u8 rate_idx = 0;
- long rx_dbm;
-
- skb = ptr_rcb->skb;
- rx_status = IEEE80211_SKB_RXCB(skb);
-
- /* [31:16]RcvByteCount ( not include 4-byte Status ) */
- head = (struct vnt_rx_header *)skb->data;
- frame_size = head->wbk_status >> 16;
- frame_size += 4;
-
- if (bytes_received != frame_size) {
- dev_dbg(&priv->usb->dev, "------- WRONG Length 1\n");
- return false;
- }
-
- if ((bytes_received > 2372) || (bytes_received <= 40)) {
- /* Frame Size error drop this packet.*/
- dev_dbg(&priv->usb->dev, "------ WRONG Length 2\n");
- return false;
- }
-
- /* real Frame Size = USBframe_size -4WbkStatus - 4RxStatus */
- /* -8TSF - 4RSR - 4SQ3 - ?Padding */
-
- /* if SQ3 the range is 24~27, if no SQ3 the range is 20~23 */
-
- /*Fix hardware bug => PLCP_Length error */
- if (((bytes_received - head->pay_load_len) > 27) ||
- ((bytes_received - head->pay_load_len) < 24) ||
- (bytes_received < head->pay_load_len)) {
- dev_dbg(&priv->usb->dev, "Wrong PLCP Length %x\n",
- head->pay_load_len);
- return false;
- }
-
- sband = hw->wiphy->bands[hw->conf.chandef.chan->band];
- rx_bitrate = head->rx_rate * 5; /* rx_rate * 5 */
-
- for (ii = 0; ii < sband->n_bitrates; ii++) {
- if (sband->bitrates[ii].bitrate == rx_bitrate) {
- rate_idx = ii;
- break;
- }
- }
-
- if (ii == sband->n_bitrates) {
- dev_dbg(&priv->usb->dev, "Wrong Rx Bit Rate %d\n", rx_bitrate);
- return false;
- }
-
- pay_load_with_padding = ((head->pay_load_len / 4) +
- ((head->pay_load_len % 4) ? 1 : 0)) * 4;
-
- tail = (struct vnt_rx_tail *)(skb->data +
- sizeof(*head) + pay_load_with_padding);
- priv->tsf_time = le64_to_cpu(tail->tsf_time);
-
- if (tail->rsr & (RSR_IVLDTYP | RSR_IVLDLEN))
- return false;
-
- vnt_rf_rssi_to_dbm(priv, tail->rssi, &rx_dbm);
-
- priv->bb_pre_ed_rssi = (u8)-rx_dbm + 1;
- priv->current_rssi = priv->bb_pre_ed_rssi;
-
- skb_pull(skb, sizeof(*head));
- skb_trim(skb, head->pay_load_len);
-
- rx_status->mactime = priv->tsf_time;
- rx_status->band = hw->conf.chandef.chan->band;
- rx_status->signal = rx_dbm;
- rx_status->flag = 0;
- rx_status->freq = hw->conf.chandef.chan->center_freq;
-
- if (!(tail->rsr & RSR_CRCOK))
- rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-
- rx_status->rate_idx = rate_idx;
-
- if (tail->new_rsr & NEWRSR_DECRYPTOK)
- rx_status->flag |= RX_FLAG_DECRYPTED;
-
- ieee80211_rx_irqsafe(priv->hw, skb);
-
- return true;
-}
-
-static void vnt_submit_rx_urb_complete(struct urb *urb)
-{
- struct vnt_rcb *rcb = urb->context;
- struct vnt_private *priv = rcb->priv;
-
- switch (urb->status) {
- case 0:
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- return;
- case -ETIMEDOUT:
- default:
- dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status);
- break;
- }
-
- if (urb->actual_length) {
- if (vnt_rx_data(priv, rcb, urb->actual_length)) {
- rcb->skb = dev_alloc_skb(priv->rx_buf_sz);
- if (!rcb->skb)
- return;
- } else {
- skb_push(rcb->skb, skb_headroom(rcb->skb));
- skb_trim(rcb->skb, 0);
- }
-
- urb->transfer_buffer = skb_put(rcb->skb,
- skb_tailroom(rcb->skb));
- }
-
- if (usb_submit_urb(urb, GFP_ATOMIC))
- dev_dbg(&priv->usb->dev, "Failed to re submit rx skb\n");
-}
-
-int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb)
-{
- int ret = 0;
- struct urb *urb = rcb->urb;
-
- if (!rcb->skb) {
- dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
- ret = -EINVAL;
- goto end;
- }
-
- usb_fill_bulk_urb(urb,
- priv->usb,
- usb_rcvbulkpipe(priv->usb, 2),
- skb_put(rcb->skb, skb_tailroom(rcb->skb)),
- MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
- vnt_submit_rx_urb_complete,
- rcb);
-
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret)
- dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", ret);
-end:
- return ret;
-}
-
-static void vnt_tx_context_complete(struct urb *urb)
-{
- struct vnt_usb_send_context *context = urb->context;
- struct vnt_private *priv = context->priv;
-
- switch (urb->status) {
- case 0:
- dev_dbg(&priv->usb->dev,
- "Write %d bytes\n", urb->actual_length);
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- context->in_use = false;
- return;
- case -ETIMEDOUT:
- default:
- dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status);
- break;
- }
-
- if (context->type == CONTEXT_DATA_PACKET)
- ieee80211_wake_queues(priv->hw);
-
- if (urb->status || context->type == CONTEXT_BEACON_PACKET) {
- if (context->skb)
- ieee80211_free_txskb(priv->hw, context->skb);
-
- context->in_use = false;
- }
-}
-
-int vnt_tx_context(struct vnt_private *priv,
- struct vnt_usb_send_context *context,
- struct sk_buff *skb)
-{
- struct vnt_tx_usb_header *usb;
- struct urb *urb;
- int status;
- u16 count = skb->len;
-
- usb = skb_push(skb, sizeof(*usb));
- usb->tx_byte_count = cpu_to_le16(count);
- usb->pkt_no = context->pkt_no;
- usb->type = context->type;
-
- if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
- context->in_use = false;
- return -ENODEV;
- }
-
- if (skb->len > MAX_TOTAL_SIZE_WITH_ALL_HEADERS) {
- context->in_use = false;
- return -E2BIG;
- }
-
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb) {
- context->in_use = false;
- return -ENOMEM;
- }
-
- usb_fill_bulk_urb(urb,
- priv->usb,
- usb_sndbulkpipe(priv->usb, 3),
- skb->data,
- skb->len,
- vnt_tx_context_complete,
- context);
-
- usb_anchor_urb(urb, &priv->tx_submitted);
-
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status) {
- dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status);
- usb_unanchor_urb(urb);
- context->in_use = false;
- }
-
- usb_free_urb(urb);
-
- return status;
-}
diff --git a/drivers/staging/vt6656/usbpipe.h b/drivers/staging/vt6656/usbpipe.h
deleted file mode 100644
index 922312e299bf..000000000000
--- a/drivers/staging/vt6656/usbpipe.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:
- *
- * Author: Warren Hsu
- *
- * Date: Mar. 30, 2005
- *
- */
-
-#ifndef __USBPIPE_H__
-#define __USBPIPE_H__
-
-#include "device.h"
-
-struct vnt_interrupt_data {
- u8 tsr0;
- u8 pkt0;
- u16 time0;
- u8 tsr1;
- u8 pkt1;
- u16 time1;
- u8 tsr2;
- u8 pkt2;
- u16 time2;
- u8 tsr3;
- u8 pkt3;
- u16 time3;
- __le64 tsf;
- u8 isr0;
- u8 isr1;
- u8 rts_success;
- u8 rts_fail;
- u8 ack_fail;
- u8 fcs_err;
- u8 sw[2];
-} __packed;
-
-struct vnt_tx_usb_header {
- u8 type;
- u8 pkt_no;
- __le16 tx_byte_count;
-} __packed;
-
-#define VNT_REG_BLOCK_SIZE 64
-
-int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
- u16 index, u16 length, const u8 *buffer);
-int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
- u16 index, u16 length, u8 *buffer);
-
-int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 ref_off, u8 data);
-int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data);
-
-int vnt_control_out_blocks(struct vnt_private *priv,
- u16 block, u8 reg, u16 len, const u8 *data);
-
-int vnt_start_interrupt_urb(struct vnt_private *priv);
-int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb);
-int vnt_tx_context(struct vnt_private *priv,
- struct vnt_usb_send_context *context,
- struct sk_buff *skb);
-
-#endif /* __USBPIPE_H__ */
diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c
deleted file mode 100644
index 14b8aa587119..000000000000
--- a/drivers/staging/vt6656/wcmd.c
+++ /dev/null
@@ -1,185 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handles the management command interface functions
- *
- * Author: Lyndon Chen
- *
- * Date: May 8, 2003
- *
- * Functions:
- * vnt_cmd_complete - Command Complete function
- * vnt_schedule_command - Push Command and wait Command Scheduler to do
- * vnt_cmd_timer_wait- Call back timer
- *
- * Revision History:
- *
- */
-
-#include "device.h"
-#include "mac.h"
-#include "wcmd.h"
-#include "power.h"
-#include "usbpipe.h"
-#include "rxtx.h"
-#include "rf.h"
-
-static void vnt_cmd_timer_wait(struct vnt_private *priv, unsigned long msecs)
-{
- schedule_delayed_work(&priv->run_command_work, msecs_to_jiffies(msecs));
-}
-
-static u32 add_one_with_wrap_around(u32 var, u8 modulo)
-{
- if (var >= (modulo - 1))
- var = 0;
- else
- var++;
- return var;
-}
-
-static int vnt_cmd_complete(struct vnt_private *priv)
-{
- priv->command_state = WLAN_CMD_IDLE;
- if (priv->free_cmd_queue == CMD_Q_SIZE) {
- /* Command Queue Empty */
- priv->cmd_running = false;
- return true;
- }
-
- priv->command = priv->cmd_queue[priv->cmd_dequeue_idx];
-
- priv->cmd_dequeue_idx = add_one_with_wrap_around(priv->cmd_dequeue_idx, CMD_Q_SIZE);
- priv->free_cmd_queue++;
- priv->cmd_running = true;
-
- switch (priv->command) {
- case WLAN_CMD_INIT_MAC80211:
- priv->command_state = WLAN_CMD_INIT_MAC80211_START;
- break;
-
- case WLAN_CMD_TBTT_WAKEUP:
- priv->command_state = WLAN_CMD_TBTT_WAKEUP_START;
- break;
-
- case WLAN_CMD_BECON_SEND:
- priv->command_state = WLAN_CMD_BECON_SEND_START;
- break;
-
- case WLAN_CMD_SETPOWER:
- priv->command_state = WLAN_CMD_SETPOWER_START;
- break;
-
- case WLAN_CMD_CHANGE_ANTENNA:
- priv->command_state = WLAN_CMD_CHANGE_ANTENNA_START;
- break;
-
- default:
- break;
- }
-
- vnt_cmd_timer_wait(priv, 0);
-
- return true;
-}
-
-void vnt_run_command(struct work_struct *work)
-{
- struct vnt_private *priv =
- container_of(work, struct vnt_private, run_command_work.work);
-
- if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
- return;
-
- if (!priv->cmd_running)
- return;
-
- switch (priv->command_state) {
- case WLAN_CMD_INIT_MAC80211_START:
- if (priv->mac_hw)
- break;
-
- dev_info(&priv->usb->dev, "Starting mac80211\n");
-
- if (vnt_init(priv)) {
- /* If fail all ends TODO retry */
- dev_err(&priv->usb->dev, "failed to start\n");
- usb_set_intfdata(priv->intf, NULL);
- ieee80211_free_hw(priv->hw);
- return;
- }
-
- break;
-
- case WLAN_CMD_TBTT_WAKEUP_START:
- vnt_next_tbtt_wakeup(priv);
- break;
-
- case WLAN_CMD_BECON_SEND_START:
- if (!priv->vif)
- break;
-
- vnt_beacon_make(priv, priv->vif);
-
- vnt_mac_reg_bits_on(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
-
- break;
-
- case WLAN_CMD_SETPOWER_START:
-
- vnt_rf_setpower(priv, priv->hw->conf.chandef.chan);
-
- break;
-
- case WLAN_CMD_CHANGE_ANTENNA_START:
- dev_dbg(&priv->usb->dev, "Change from Antenna%d to",
- priv->rx_antenna_sel);
-
- if (priv->rx_antenna_sel == 0) {
- priv->rx_antenna_sel = 1;
- if (priv->tx_rx_ant_inv)
- vnt_set_antenna_mode(priv, ANT_RXA);
- else
- vnt_set_antenna_mode(priv, ANT_RXB);
- } else {
- priv->rx_antenna_sel = 0;
- if (priv->tx_rx_ant_inv)
- vnt_set_antenna_mode(priv, ANT_RXB);
- else
- vnt_set_antenna_mode(priv, ANT_RXA);
- }
- break;
-
- default:
- break;
- }
-
- vnt_cmd_complete(priv);
-}
-
-int vnt_schedule_command(struct vnt_private *priv, enum vnt_cmd command)
-{
- if (priv->free_cmd_queue == 0)
- return false;
-
- priv->cmd_queue[priv->cmd_enqueue_idx] = command;
-
- priv->cmd_enqueue_idx = add_one_with_wrap_around(priv->cmd_enqueue_idx, CMD_Q_SIZE);
- priv->free_cmd_queue--;
-
- if (!priv->cmd_running)
- vnt_cmd_complete(priv);
-
- return true;
-}
-
-void vnt_reset_command_timer(struct vnt_private *priv)
-{
- priv->free_cmd_queue = CMD_Q_SIZE;
- priv->cmd_dequeue_idx = 0;
- priv->cmd_enqueue_idx = 0;
- priv->command_state = WLAN_CMD_IDLE;
- priv->cmd_running = false;
-}
diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h
deleted file mode 100644
index a62924671b17..000000000000
--- a/drivers/staging/vt6656/wcmd.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handles the management command interface functions
- *
- * Author: Lyndon Chen
- *
- * Date: May 8, 2002
- *
- */
-
-#ifndef __WCMD_H__
-#define __WCMD_H__
-
-#include "device.h"
-
-/* Command code */
-enum vnt_cmd {
- WLAN_CMD_INIT_MAC80211,
- WLAN_CMD_SETPOWER,
- WLAN_CMD_TBTT_WAKEUP,
- WLAN_CMD_BECON_SEND,
- WLAN_CMD_CHANGE_ANTENNA
-};
-
-#define CMD_Q_SIZE 32
-
-/* Command state */
-enum vnt_cmd_state {
- WLAN_CMD_INIT_MAC80211_START,
- WLAN_CMD_SETPOWER_START,
- WLAN_CMD_TBTT_WAKEUP_START,
- WLAN_CMD_BECON_SEND_START,
- WLAN_CMD_CHANGE_ANTENNA_START,
- WLAN_CMD_IDLE
-};
-
-struct vnt_private;
-
-void vnt_reset_command_timer(struct vnt_private *priv);
-
-int vnt_schedule_command(struct vnt_private *priv, enum vnt_cmd);
-
-void vnt_run_command(struct work_struct *work);
-
-#endif /* __WCMD_H__ */
diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c
index ac6fa6b8f99f..3b644de3292e 100644
--- a/drivers/thermal/gov_power_allocator.c
+++ b/drivers/thermal/gov_power_allocator.c
@@ -588,10 +588,15 @@ static void allow_maximum_power(struct thermal_zone_device *tz)
static int check_power_actors(struct thermal_zone_device *tz,
struct power_allocator_params *params)
{
- const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max);
+ const struct thermal_trip_desc *td;
struct thermal_instance *instance;
int ret = 0;
+ if (!params->trip_max)
+ return 0;
+
+ td = trip_to_trip_desc(params->trip_max);
+
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
if (!cdev_is_power_actor(instance->cdev)) {
dev_warn(&tz->device, "power_allocator: %s is not a power actor\n",
diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
index b2fc02c3a767..8660ef2175be 100644
--- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
@@ -75,11 +75,6 @@ struct odvp_attr {
static BIN_ATTR_SIMPLE_RO(data_vault);
-static struct bin_attribute *data_attributes[] = {
- &bin_attr_data_vault,
- NULL,
-};
-
static ssize_t imok_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -108,10 +103,6 @@ static const struct attribute_group imok_attribute_group = {
.attrs = imok_attr,
};
-static const struct attribute_group data_attribute_group = {
- .bin_attrs = data_attributes,
-};
-
static ssize_t available_uuids_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -137,7 +128,7 @@ static ssize_t current_uuid_show(struct device *dev,
struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
int i, length = 0;
- if (priv->current_uuid_index > 0)
+ if (priv->current_uuid_index >= 0)
return sprintf(buf, "%s\n",
int3400_thermal_uuids[priv->current_uuid_index]);
@@ -624,8 +615,7 @@ static int int3400_thermal_probe(struct platform_device *pdev)
}
if (!ZERO_OR_NULL_PTR(priv->data_vault)) {
- result = sysfs_create_group(&pdev->dev.kobj,
- &data_attribute_group);
+ result = device_create_bin_file(&pdev->dev, &bin_attr_data_vault);
if (result)
goto free_uuid;
}
@@ -648,7 +638,7 @@ free_notify:
free_sysfs:
cleanup_odvp(priv);
if (!ZERO_OR_NULL_PTR(priv->data_vault)) {
- sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group);
+ device_remove_bin_file(&pdev->dev, &bin_attr_data_vault);
kfree(priv->data_vault);
}
free_uuid:
@@ -683,7 +673,7 @@ static void int3400_thermal_remove(struct platform_device *pdev)
acpi_thermal_rel_misc_device_remove(priv->adev->handle);
if (!ZERO_OR_NULL_PTR(priv->data_vault))
- sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group);
+ device_remove_bin_file(&pdev->dev, &bin_attr_data_vault);
sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group);
sysfs_remove_group(&pdev->dev.kobj, &imok_attribute_group);
thermal_zone_device_unregister(priv->thermal);
diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
index 5e94a45eba3e..d7f2e6ca92c2 100644
--- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
+++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
@@ -938,7 +938,6 @@ static const struct adc_tm5_data adc_tm5_gen2_data_pmic = {
static int adc_tm5_get_dt_data(struct adc_tm5_chip *adc_tm, struct device_node *node)
{
struct adc_tm5_channel *channels;
- struct device_node *child;
u32 value;
int ret;
struct device *dev = adc_tm->dev;
@@ -982,12 +981,10 @@ static int adc_tm5_get_dt_data(struct adc_tm5_chip *adc_tm, struct device_node *
adc_tm->avg_samples = VADC_DEF_AVG_SAMPLES;
}
- for_each_available_child_of_node(node, child) {
+ for_each_available_child_of_node_scoped(node, child) {
ret = adc_tm5_get_dt_channel_data(adc_tm, channels, child);
- if (ret) {
- of_node_put(child);
+ if (ret)
return ret;
- }
channels++;
}
diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 3203d8bd13a8..22674790629a 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -9,6 +9,7 @@
*/
#include <linux/bitmap.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/interrupt.h>
@@ -348,19 +349,18 @@ static void sun8i_ths_reset_control_assert(void *data)
static struct regmap *sun8i_ths_get_sram_regmap(struct device_node *node)
{
- struct device_node *sram_node;
struct platform_device *sram_pdev;
struct regmap *regmap = NULL;
- sram_node = of_parse_phandle(node, "allwinner,sram", 0);
+ struct device_node *sram_node __free(device_node) =
+ of_parse_phandle(node, "allwinner,sram", 0);
if (!sram_node)
return ERR_PTR(-ENODEV);
sram_pdev = of_find_device_by_node(sram_node);
if (!sram_pdev) {
/* platform device might not be probed yet */
- regmap = ERR_PTR(-EPROBE_DEFER);
- goto out_put_node;
+ return ERR_PTR(-EPROBE_DEFER);
}
/* If no regmap is found then the other device driver is at fault */
@@ -369,8 +369,7 @@ static struct regmap *sun8i_ths_get_sram_regmap(struct device_node *node)
regmap = ERR_PTR(-EINVAL);
platform_device_put(sram_pdev);
-out_put_node:
- of_node_put(sram_node);
+
return regmap;
}
diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c
index 6f1501e3fcc4..2c5ddf0db40c 100644
--- a/drivers/thermal/tegra/soctherm.c
+++ b/drivers/thermal/tegra/soctherm.c
@@ -1651,7 +1651,7 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct tegra_soctherm *ts = dev_get_drvdata(dev);
- struct device_node *np_stc, *np_stcc;
+ struct device_node *np_stc;
const char *name;
int i;
@@ -1668,7 +1668,7 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
return;
}
- for_each_child_of_node(np_stc, np_stcc) {
+ for_each_child_of_node_scoped(np_stc, np_stcc) {
struct soctherm_throt_cfg *stc;
struct thermal_cooling_device *tcd;
int err;
@@ -1683,7 +1683,6 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
if (stc->init) {
dev_err(dev, "throttle-cfg: %s: redefined!\n", name);
- of_node_put(np_stcc);
break;
}
diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c
index 07e09897165f..fab11b98ca49 100644
--- a/drivers/thermal/thermal_of.c
+++ b/drivers/thermal/thermal_of.c
@@ -95,13 +95,11 @@ static int thermal_of_populate_trip(struct device_node *np,
static struct thermal_trip *thermal_of_trips_init(struct device_node *np, int *ntrips)
{
- struct thermal_trip *tt;
- struct device_node *trips;
int ret, count;
*ntrips = 0;
- trips = of_get_child_by_name(np, "trips");
+ struct device_node *trips __free(device_node) = of_get_child_by_name(np, "trips");
if (!trips)
return NULL;
@@ -109,39 +107,27 @@ static struct thermal_trip *thermal_of_trips_init(struct device_node *np, int *n
if (!count)
return NULL;
- tt = kzalloc(sizeof(*tt) * count, GFP_KERNEL);
- if (!tt) {
- ret = -ENOMEM;
- goto out_of_node_put;
- }
-
- *ntrips = count;
+ struct thermal_trip *tt __free(kfree) = kzalloc(sizeof(*tt) * count, GFP_KERNEL);
+ if (!tt)
+ return ERR_PTR(-ENOMEM);
count = 0;
for_each_child_of_node_scoped(trips, trip) {
ret = thermal_of_populate_trip(trip, &tt[count++]);
if (ret)
- goto out_kfree;
+ return ERR_PTR(ret);
}
- of_node_put(trips);
-
- return tt;
-
-out_kfree:
- kfree(tt);
-out_of_node_put:
- of_node_put(trips);
+ *ntrips = count;
- return ERR_PTR(ret);
+ return no_free_ptr(tt);
}
static struct device_node *of_thermal_zone_find(struct device_node *sensor, int id)
{
- struct device_node *np, *tz;
struct of_phandle_args sensor_specs;
- np = of_find_node_by_name(NULL, "thermal-zones");
+ struct device_node *np __free(device_node) = of_find_node_by_name(NULL, "thermal-zones");
if (!np) {
pr_debug("No thermal zones description\n");
return ERR_PTR(-ENODEV);
@@ -159,8 +145,7 @@ static struct device_node *of_thermal_zone_find(struct device_node *sensor, int
"#thermal-sensor-cells");
if (count <= 0) {
pr_err("%pOFn: missing thermal sensor\n", child);
- tz = ERR_PTR(-EINVAL);
- goto out;
+ return ERR_PTR(-EINVAL);
}
for (i = 0; i < count; i++) {
@@ -172,22 +157,18 @@ static struct device_node *of_thermal_zone_find(struct device_node *sensor, int
i, &sensor_specs);
if (ret < 0) {
pr_err("%pOFn: Failed to read thermal-sensors cells: %d\n", child, ret);
- tz = ERR_PTR(ret);
- goto out;
+ return ERR_PTR(ret);
}
if ((sensor == sensor_specs.np) && id == (sensor_specs.args_count ?
sensor_specs.args[0] : 0)) {
pr_debug("sensor %pOFn id=%d belongs to %pOFn\n", sensor, id, child);
- tz = no_free_ptr(child);
- goto out;
+ return no_free_ptr(child);
}
}
}
- tz = ERR_PTR(-ENODEV);
-out:
- of_node_put(np);
- return tz;
+
+ return ERR_PTR(-ENODEV);
}
static int thermal_of_monitor_init(struct device_node *np, int *delay, int *pdelay)
@@ -297,7 +278,7 @@ static bool thermal_of_should_bind(struct thermal_zone_device *tz,
struct thermal_cooling_device *cdev,
struct cooling_spec *c)
{
- struct device_node *tz_np, *cm_np, *child;
+ struct device_node *tz_np, *cm_np;
bool result = false;
tz_np = thermal_of_zone_get_by_name(tz);
@@ -311,7 +292,7 @@ static bool thermal_of_should_bind(struct thermal_zone_device *tz,
goto out;
/* Look up the trip and the cdev in the cooling maps. */
- for_each_child_of_node(cm_np, child) {
+ for_each_child_of_node_scoped(cm_np, child) {
struct device_node *tr_np;
int count, i;
@@ -330,7 +311,6 @@ static bool thermal_of_should_bind(struct thermal_zone_device *tz,
break;
}
- of_node_put(child);
break;
}
diff --git a/drivers/thunderbolt/debugfs.c b/drivers/thunderbolt/debugfs.c
index 350310bd0fee..a1d0d8a33f20 100644
--- a/drivers/thunderbolt/debugfs.c
+++ b/drivers/thunderbolt/debugfs.c
@@ -7,6 +7,7 @@
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
+#include <linux/array_size.h>
#include <linux/bitfield.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
@@ -43,6 +44,24 @@
#define MAX_DWELL_TIME 500 /* ms */
#define DWELL_SAMPLE_INTERVAL 10
+enum usb4_margin_cap_voltage_indp {
+ USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_MIN,
+ USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_HL,
+ USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_BOTH,
+ USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_4_MIN,
+ USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_4_BOTH,
+ USB4_MARGIN_CAP_VOLTAGE_INDP_UNKNOWN,
+};
+
+enum usb4_margin_cap_time_indp {
+ USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_MIN,
+ USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_LR,
+ USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_BOTH,
+ USB4_MARGIN_CAP_TIME_INDP_GEN_4_MIN,
+ USB4_MARGIN_CAP_TIME_INDP_GEN_4_BOTH,
+ USB4_MARGIN_CAP_TIME_INDP_UNKNOWN,
+};
+
/* Sideband registers and their sizes as defined in the USB4 spec */
struct sb_reg {
unsigned int reg;
@@ -395,6 +414,8 @@ out:
* @target: Sideband target
* @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER
* @dev: Pointer to the device that is the target (USB4 port or retimer)
+ * @gen: Link generation
+ * @asym_rx: %true% if @port supports asymmetric link with 3 Rx
* @caps: Port lane margining capabilities
* @results: Last lane margining results
* @lanes: %0, %1 or %7 (all)
@@ -416,15 +437,19 @@ out:
* @time: %true if time margining is used instead of voltage
* @right_high: %false if left/low margin test is performed, %true if
* right/high
+ * @upper_eye: %false if the lower PAM3 eye is used, %true if the upper
+ * eye is used
*/
struct tb_margining {
struct tb_port *port;
enum usb4_sb_target target;
u8 index;
struct device *dev;
- u32 caps[2];
- u32 results[2];
- unsigned int lanes;
+ unsigned int gen;
+ bool asym_rx;
+ u32 caps[3];
+ u32 results[3];
+ enum usb4_margining_lane lanes;
unsigned int min_ber_level;
unsigned int max_ber_level;
unsigned int ber_level;
@@ -441,6 +466,7 @@ struct tb_margining {
bool software;
bool time;
bool right_high;
+ bool upper_eye;
};
static int margining_modify_error_counter(struct tb_margining *margining,
@@ -463,35 +489,75 @@ static int margining_modify_error_counter(struct tb_margining *margining,
static bool supports_software(const struct tb_margining *margining)
{
- return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_SW;
+ if (margining->gen < 4)
+ return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_SW;
+ return margining->caps[2] & USB4_MARGIN_CAP_2_MODES_SW;
}
static bool supports_hardware(const struct tb_margining *margining)
{
- return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_HW;
+ if (margining->gen < 4)
+ return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_HW;
+ return margining->caps[2] & USB4_MARGIN_CAP_2_MODES_HW;
}
-static bool both_lanes(const struct tb_margining *margining)
+static bool all_lanes(const struct tb_margining *margining)
{
- return margining->caps[0] & USB4_MARGIN_CAP_0_2_LANES;
+ return margining->caps[0] & USB4_MARGIN_CAP_0_ALL_LANES;
}
-static unsigned int
+static enum usb4_margin_cap_voltage_indp
independent_voltage_margins(const struct tb_margining *margining)
{
- return FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_INDP_MASK, margining->caps[0]);
+ if (margining->gen < 4) {
+ switch (FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_INDP_MASK, margining->caps[0])) {
+ case USB4_MARGIN_CAP_0_VOLTAGE_MIN:
+ return USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_MIN;
+ case USB4_MARGIN_CAP_0_VOLTAGE_HL:
+ return USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_HL;
+ case USB4_MARGIN_CAP_1_TIME_BOTH:
+ return USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_BOTH;
+ }
+ } else {
+ switch (FIELD_GET(USB4_MARGIN_CAP_2_VOLTAGE_INDP_MASK, margining->caps[2])) {
+ case USB4_MARGIN_CAP_2_VOLTAGE_MIN:
+ return USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_4_MIN;
+ case USB4_MARGIN_CAP_2_VOLTAGE_BOTH:
+ return USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_4_BOTH;
+ }
+ }
+ return USB4_MARGIN_CAP_VOLTAGE_INDP_UNKNOWN;
}
static bool supports_time(const struct tb_margining *margining)
{
- return margining->caps[0] & USB4_MARGIN_CAP_0_TIME;
+ if (margining->gen < 4)
+ return margining->caps[0] & USB4_MARGIN_CAP_0_TIME;
+ return margining->caps[2] & USB4_MARGIN_CAP_2_TIME;
}
/* Only applicable if supports_time() returns true */
-static unsigned int
+static enum usb4_margin_cap_time_indp
independent_time_margins(const struct tb_margining *margining)
{
- return FIELD_GET(USB4_MARGIN_CAP_1_TIME_INDP_MASK, margining->caps[1]);
+ if (margining->gen < 4) {
+ switch (FIELD_GET(USB4_MARGIN_CAP_1_TIME_INDP_MASK, margining->caps[1])) {
+ case USB4_MARGIN_CAP_1_TIME_MIN:
+ return USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_MIN;
+ case USB4_MARGIN_CAP_1_TIME_LR:
+ return USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_LR;
+ case USB4_MARGIN_CAP_1_TIME_BOTH:
+ return USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_BOTH;
+ }
+ } else {
+ switch (FIELD_GET(USB4_MARGIN_CAP_2_TIME_INDP_MASK, margining->caps[2])) {
+ case USB4_MARGIN_CAP_2_TIME_MIN:
+ return USB4_MARGIN_CAP_TIME_INDP_GEN_4_MIN;
+ case USB4_MARGIN_CAP_2_TIME_BOTH:
+ return USB4_MARGIN_CAP_TIME_INDP_GEN_4_BOTH;
+ }
+ }
+ return USB4_MARGIN_CAP_TIME_INDP_UNKNOWN;
}
static bool
@@ -570,16 +636,14 @@ static int margining_caps_show(struct seq_file *s, void *not_used)
{
struct tb_margining *margining = s->private;
struct tb *tb = margining->port->sw->tb;
- u32 cap0, cap1;
+ int ret = 0;
if (mutex_lock_interruptible(&tb->lock))
return -ERESTARTSYS;
/* Dump the raw caps first */
- cap0 = margining->caps[0];
- seq_printf(s, "0x%08x\n", cap0);
- cap1 = margining->caps[1];
- seq_printf(s, "0x%08x\n", cap1);
+ for (int i = 0; i < ARRAY_SIZE(margining->caps); i++)
+ seq_printf(s, "0x%08x\n", margining->caps[i]);
seq_printf(s, "# software margining: %s\n",
supports_software(margining) ? "yes" : "no");
@@ -593,8 +657,8 @@ static int margining_caps_show(struct seq_file *s, void *not_used)
seq_puts(s, "# hardware margining: no\n");
}
- seq_printf(s, "# both lanes simultaneously: %s\n",
- both_lanes(margining) ? "yes" : "no");
+ seq_printf(s, "# all lanes simultaneously: %s\n",
+ str_yes_no(all_lanes(margining)));
seq_printf(s, "# voltage margin steps: %u\n",
margining->voltage_steps);
seq_printf(s, "# maximum voltage offset: %u mV\n",
@@ -609,32 +673,54 @@ static int margining_caps_show(struct seq_file *s, void *not_used)
}
switch (independent_voltage_margins(margining)) {
- case USB4_MARGIN_CAP_0_VOLTAGE_MIN:
+ case USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_MIN:
seq_puts(s, "# returns minimum between high and low voltage margins\n");
break;
- case USB4_MARGIN_CAP_0_VOLTAGE_HL:
+ case USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_HL:
seq_puts(s, "# returns high or low voltage margin\n");
break;
- case USB4_MARGIN_CAP_0_VOLTAGE_BOTH:
+ case USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_BOTH:
seq_puts(s, "# returns both high and low margins\n");
break;
+ case USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_4_MIN:
+ seq_puts(s, "# returns minimum between high and low voltage margins in both lower and upper eye\n");
+ break;
+ case USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_4_BOTH:
+ seq_puts(s, "# returns both high and low margins of both upper and lower eye\n");
+ break;
+ case USB4_MARGIN_CAP_VOLTAGE_INDP_UNKNOWN:
+ tb_port_warn(margining->port,
+ "failed to parse independent voltage margining capabilities\n");
+ ret = -EIO;
+ goto out;
}
if (supports_time(margining)) {
seq_puts(s, "# time margining: yes\n");
seq_printf(s, "# time margining is destructive: %s\n",
- cap1 & USB4_MARGIN_CAP_1_TIME_DESTR ? "yes" : "no");
+ str_yes_no(margining->caps[1] & USB4_MARGIN_CAP_1_TIME_DESTR));
switch (independent_time_margins(margining)) {
- case USB4_MARGIN_CAP_1_TIME_MIN:
+ case USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_MIN:
seq_puts(s, "# returns minimum between left and right time margins\n");
break;
- case USB4_MARGIN_CAP_1_TIME_LR:
+ case USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_LR:
seq_puts(s, "# returns left or right margin\n");
break;
- case USB4_MARGIN_CAP_1_TIME_BOTH:
+ case USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_BOTH:
seq_puts(s, "# returns both left and right margins\n");
break;
+ case USB4_MARGIN_CAP_TIME_INDP_GEN_4_MIN:
+ seq_puts(s, "# returns minimum between left and right time margins in both lower and upper eye\n");
+ break;
+ case USB4_MARGIN_CAP_TIME_INDP_GEN_4_BOTH:
+ seq_puts(s, "# returns both left and right margins of both upper and lower eye\n");
+ break;
+ case USB4_MARGIN_CAP_TIME_INDP_UNKNOWN:
+ tb_port_warn(margining->port,
+ "failed to parse independent time margining capabilities\n");
+ ret = -EIO;
+ goto out;
}
seq_printf(s, "# time margin steps: %u\n",
@@ -645,19 +731,43 @@ static int margining_caps_show(struct seq_file *s, void *not_used)
seq_puts(s, "# time margining: no\n");
}
+out:
mutex_unlock(&tb->lock);
- return 0;
+ return ret;
}
DEBUGFS_ATTR_RO(margining_caps);
+static const struct {
+ enum usb4_margining_lane lane;
+ const char *name;
+} lane_names[] = {
+ {
+ .lane = USB4_MARGINING_LANE_RX0,
+ .name = "0",
+ },
+ {
+ .lane = USB4_MARGINING_LANE_RX1,
+ .name = "1",
+ },
+ {
+ .lane = USB4_MARGINING_LANE_RX2,
+ .name = "2",
+ },
+ {
+ .lane = USB4_MARGINING_LANE_ALL,
+ .name = "all",
+ },
+};
+
static ssize_t
margining_lanes_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct tb_margining *margining = s->private;
- struct tb *tb = margining->port->sw->tb;
- int ret = 0;
+ struct tb_port *port = margining->port;
+ struct tb *tb = port->sw->tb;
+ int lane = -1;
char *buf;
buf = validate_and_copy_from_user(user_buf, &count);
@@ -666,57 +776,60 @@ margining_lanes_write(struct file *file, const char __user *user_buf,
buf[count - 1] = '\0';
- if (mutex_lock_interruptible(&tb->lock)) {
- ret = -ERESTARTSYS;
- goto out_free;
+ for (int i = 0; i < ARRAY_SIZE(lane_names); i++) {
+ if (!strcmp(buf, lane_names[i].name)) {
+ lane = lane_names[i].lane;
+ break;
+ }
}
- if (!strcmp(buf, "0")) {
- margining->lanes = 0;
- } else if (!strcmp(buf, "1")) {
- margining->lanes = 1;
- } else if (!strcmp(buf, "all")) {
- /* Needs to be supported */
- if (both_lanes(margining))
- margining->lanes = 7;
- else
- ret = -EINVAL;
- } else {
- ret = -EINVAL;
- }
+ free_page((unsigned long)buf);
- mutex_unlock(&tb->lock);
+ if (lane == -1)
+ return -EINVAL;
-out_free:
- free_page((unsigned long)buf);
- return ret < 0 ? ret : count;
+ scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &tb->lock) {
+ if (lane == USB4_MARGINING_LANE_ALL && !all_lanes(margining))
+ return -EINVAL;
+ /*
+ * Enabling on RX2 requires that it is supported by the
+ * USB4 port.
+ */
+ if (lane == USB4_MARGINING_LANE_RX2 && !margining->asym_rx)
+ return -EINVAL;
+
+ margining->lanes = lane;
+ }
+
+ return count;
}
static int margining_lanes_show(struct seq_file *s, void *not_used)
{
struct tb_margining *margining = s->private;
- struct tb *tb = margining->port->sw->tb;
- unsigned int lanes;
-
- if (mutex_lock_interruptible(&tb->lock))
- return -ERESTARTSYS;
+ struct tb_port *port = margining->port;
+ struct tb *tb = port->sw->tb;
- lanes = margining->lanes;
- if (both_lanes(margining)) {
- if (!lanes)
- seq_puts(s, "[0] 1 all\n");
- else if (lanes == 1)
- seq_puts(s, "0 [1] all\n");
- else
- seq_puts(s, "0 1 [all]\n");
- } else {
- if (!lanes)
- seq_puts(s, "[0] 1\n");
- else
- seq_puts(s, "0 [1]\n");
+ scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &tb->lock) {
+ for (int i = 0; i < ARRAY_SIZE(lane_names); i++) {
+ if (lane_names[i].lane == USB4_MARGINING_LANE_ALL &&
+ !all_lanes(margining))
+ continue;
+ if (lane_names[i].lane == USB4_MARGINING_LANE_RX2 &&
+ !margining->asym_rx)
+ continue;
+
+ if (i != 0)
+ seq_putc(s, ' ');
+
+ if (lane_names[i].lane == margining->lanes)
+ seq_printf(s, "[%s]", lane_names[i].name);
+ else
+ seq_printf(s, "%s", lane_names[i].name);
+ }
+ seq_puts(s, "\n");
}
- mutex_unlock(&tb->lock);
return 0;
}
DEBUGFS_ATTR_RW(margining_lanes);
@@ -1004,13 +1117,16 @@ static int margining_run_sw(struct tb_margining *margining,
if (ret)
break;
- if (margining->lanes == USB4_MARGIN_SW_LANE_0)
+ if (margining->lanes == USB4_MARGINING_LANE_RX0)
errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_0_MASK,
margining->results[1]);
- else if (margining->lanes == USB4_MARGIN_SW_LANE_1)
+ else if (margining->lanes == USB4_MARGINING_LANE_RX1)
errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_1_MASK,
margining->results[1]);
- else if (margining->lanes == USB4_MARGIN_SW_ALL_LANES)
+ else if (margining->lanes == USB4_MARGINING_LANE_RX2)
+ errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_2_MASK,
+ margining->results[1]);
+ else if (margining->lanes == USB4_MARGINING_LANE_ALL)
errors = margining->results[1];
/* Any errors stop the test */
@@ -1030,6 +1146,31 @@ out_stop:
return ret;
}
+static int validate_margining(struct tb_margining *margining)
+{
+ /*
+ * For running on RX2 the link must be asymmetric with 3
+ * receivers. Because this is can change dynamically, check it
+ * here before we start the margining and report back error if
+ * expectations are not met.
+ */
+ if (margining->lanes == USB4_MARGINING_LANE_RX2) {
+ int ret;
+
+ ret = tb_port_get_link_width(margining->port);
+ if (ret < 0)
+ return ret;
+ if (ret != TB_LINK_WIDTH_ASYM_RX) {
+ tb_port_warn(margining->port, "link is %s expected %s",
+ tb_width_name(ret),
+ tb_width_name(TB_LINK_WIDTH_ASYM_RX));
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int margining_run_write(void *data, u64 val)
{
struct tb_margining *margining = data;
@@ -1050,6 +1191,10 @@ static int margining_run_write(void *data, u64 val)
goto out_rpm_put;
}
+ ret = validate_margining(margining);
+ if (ret)
+ goto out_unlock;
+
if (tb_is_upstream_port(port))
down_sw = sw;
else if (port->remote)
@@ -1080,6 +1225,7 @@ static int margining_run_write(void *data, u64 val)
.time = margining->time,
.voltage_time_offset = margining->voltage_time_offset,
.right_high = margining->right_high,
+ .upper_eye = margining->upper_eye,
.optional_voltage_offset_range = margining->optional_voltage_offset_range,
};
@@ -1095,6 +1241,7 @@ static int margining_run_write(void *data, u64 val)
.lanes = margining->lanes,
.time = margining->time,
.right_high = margining->right_high,
+ .upper_eye = margining->upper_eye,
.optional_voltage_offset_range = margining->optional_voltage_offset_range,
};
@@ -1104,7 +1251,7 @@ static int margining_run_write(void *data, u64 val)
margining->lanes);
ret = usb4_port_hw_margin(port, margining->target, margining->index, &params,
- margining->results);
+ margining->results, ARRAY_SIZE(margining->results));
}
if (down_sw)
@@ -1132,13 +1279,12 @@ static ssize_t margining_results_write(struct file *file,
return -ERESTARTSYS;
/* Just clear the results */
- margining->results[0] = 0;
- margining->results[1] = 0;
+ memset(margining->results, 0, sizeof(margining->results));
if (margining->software) {
/* Clear the error counters */
margining_modify_error_counter(margining,
- USB4_MARGIN_SW_ALL_LANES,
+ USB4_MARGINING_LANE_ALL,
USB4_MARGIN_SW_ERROR_COUNTER_CLEAR);
}
@@ -1151,10 +1297,10 @@ static void voltage_margin_show(struct seq_file *s,
{
unsigned int tmp, voltage;
- tmp = FIELD_GET(USB4_MARGIN_HW_RES_1_MARGIN_MASK, val);
+ tmp = FIELD_GET(USB4_MARGIN_HW_RES_MARGIN_MASK, val);
voltage = tmp * margining->max_voltage_offset / margining->voltage_steps;
seq_printf(s, "%u mV (%u)", voltage, tmp);
- if (val & USB4_MARGIN_HW_RES_1_EXCEEDS)
+ if (val & USB4_MARGIN_HW_RES_EXCEEDS)
seq_puts(s, " exceeds maximum");
seq_puts(s, "\n");
if (margining->optional_voltage_offset_range)
@@ -1166,14 +1312,55 @@ static void time_margin_show(struct seq_file *s,
{
unsigned int tmp, interval;
- tmp = FIELD_GET(USB4_MARGIN_HW_RES_1_MARGIN_MASK, val);
+ tmp = FIELD_GET(USB4_MARGIN_HW_RES_MARGIN_MASK, val);
interval = tmp * margining->max_time_offset / margining->time_steps;
seq_printf(s, "%u mUI (%u)", interval, tmp);
- if (val & USB4_MARGIN_HW_RES_1_EXCEEDS)
+ if (val & USB4_MARGIN_HW_RES_EXCEEDS)
seq_puts(s, " exceeds maximum");
seq_puts(s, "\n");
}
+static u8 margining_hw_result_val(const u32 *results,
+ enum usb4_margining_lane lane,
+ bool right_high)
+{
+ u32 val;
+
+ if (lane == USB4_MARGINING_LANE_RX0)
+ val = results[1];
+ else if (lane == USB4_MARGINING_LANE_RX1)
+ val = results[1] >> USB4_MARGIN_HW_RES_LANE_SHIFT;
+ else if (lane == USB4_MARGINING_LANE_RX2)
+ val = results[2];
+ else
+ val = 0;
+
+ return right_high ? val : val >> USB4_MARGIN_HW_RES_LL_SHIFT;
+}
+
+static void margining_hw_result_format(struct seq_file *s,
+ const struct tb_margining *margining,
+ enum usb4_margining_lane lane)
+{
+ u8 val;
+
+ if (margining->time) {
+ val = margining_hw_result_val(margining->results, lane, true);
+ seq_printf(s, "# lane %u right time margin: ", lane);
+ time_margin_show(s, margining, val);
+ val = margining_hw_result_val(margining->results, lane, false);
+ seq_printf(s, "# lane %u left time margin: ", lane);
+ time_margin_show(s, margining, val);
+ } else {
+ val = margining_hw_result_val(margining->results, lane, true);
+ seq_printf(s, "# lane %u high voltage margin: ", lane);
+ voltage_margin_show(s, margining, val);
+ val = margining_hw_result_val(margining->results, lane, false);
+ seq_printf(s, "# lane %u low voltage margin: ", lane);
+ voltage_margin_show(s, margining, val);
+ }
+}
+
static int margining_results_show(struct seq_file *s, void *not_used)
{
struct tb_margining *margining = s->private;
@@ -1186,69 +1373,46 @@ static int margining_results_show(struct seq_file *s, void *not_used)
seq_printf(s, "0x%08x\n", margining->results[0]);
/* Only the hardware margining has two result dwords */
if (!margining->software) {
- unsigned int val;
-
- seq_printf(s, "0x%08x\n", margining->results[1]);
-
- if (margining->time) {
- if (!margining->lanes || margining->lanes == 7) {
- val = margining->results[1];
- seq_puts(s, "# lane 0 right time margin: ");
- time_margin_show(s, margining, val);
- val = margining->results[1] >>
- USB4_MARGIN_HW_RES_1_L0_LL_MARGIN_SHIFT;
- seq_puts(s, "# lane 0 left time margin: ");
- time_margin_show(s, margining, val);
- }
- if (margining->lanes == 1 || margining->lanes == 7) {
- val = margining->results[1] >>
- USB4_MARGIN_HW_RES_1_L1_RH_MARGIN_SHIFT;
- seq_puts(s, "# lane 1 right time margin: ");
- time_margin_show(s, margining, val);
- val = margining->results[1] >>
- USB4_MARGIN_HW_RES_1_L1_LL_MARGIN_SHIFT;
- seq_puts(s, "# lane 1 left time margin: ");
- time_margin_show(s, margining, val);
- }
+ for (int i = 1; i < ARRAY_SIZE(margining->results); i++)
+ seq_printf(s, "0x%08x\n", margining->results[i]);
+
+ if (margining->lanes == USB4_MARGINING_LANE_ALL) {
+ margining_hw_result_format(s, margining,
+ USB4_MARGINING_LANE_RX0);
+ margining_hw_result_format(s, margining,
+ USB4_MARGINING_LANE_RX1);
+ if (margining->asym_rx)
+ margining_hw_result_format(s, margining,
+ USB4_MARGINING_LANE_RX2);
} else {
- if (!margining->lanes || margining->lanes == 7) {
- val = margining->results[1];
- seq_puts(s, "# lane 0 high voltage margin: ");
- voltage_margin_show(s, margining, val);
- val = margining->results[1] >>
- USB4_MARGIN_HW_RES_1_L0_LL_MARGIN_SHIFT;
- seq_puts(s, "# lane 0 low voltage margin: ");
- voltage_margin_show(s, margining, val);
- }
- if (margining->lanes == 1 || margining->lanes == 7) {
- val = margining->results[1] >>
- USB4_MARGIN_HW_RES_1_L1_RH_MARGIN_SHIFT;
- seq_puts(s, "# lane 1 high voltage margin: ");
- voltage_margin_show(s, margining, val);
- val = margining->results[1] >>
- USB4_MARGIN_HW_RES_1_L1_LL_MARGIN_SHIFT;
- seq_puts(s, "# lane 1 low voltage margin: ");
- voltage_margin_show(s, margining, val);
- }
+ margining_hw_result_format(s, margining,
+ margining->lanes);
}
} else {
u32 lane_errors, result;
seq_printf(s, "0x%08x\n", margining->results[1]);
- result = FIELD_GET(USB4_MARGIN_SW_LANES_MASK, margining->results[0]);
- if (result == USB4_MARGIN_SW_LANE_0 ||
- result == USB4_MARGIN_SW_ALL_LANES) {
+ result = FIELD_GET(USB4_MARGIN_SW_LANES_MASK, margining->results[0]);
+ if (result == USB4_MARGINING_LANE_RX0 ||
+ result == USB4_MARGINING_LANE_ALL) {
lane_errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_0_MASK,
margining->results[1]);
seq_printf(s, "# lane 0 errors: %u\n", lane_errors);
}
- if (result == USB4_MARGIN_SW_LANE_1 ||
- result == USB4_MARGIN_SW_ALL_LANES) {
+ if (result == USB4_MARGINING_LANE_RX1 ||
+ result == USB4_MARGINING_LANE_ALL) {
lane_errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_1_MASK,
margining->results[1]);
seq_printf(s, "# lane 1 errors: %u\n", lane_errors);
}
+ if (margining->asym_rx &&
+ (result == USB4_MARGINING_LANE_RX2 ||
+ result == USB4_MARGINING_LANE_ALL)) {
+ lane_errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_2_MASK,
+ margining->results[1]);
+ seq_printf(s, "# lane 2 errors: %u\n", lane_errors);
+ }
}
mutex_unlock(&tb->lock);
@@ -1382,6 +1546,55 @@ static int margining_margin_show(struct seq_file *s, void *not_used)
}
DEBUGFS_ATTR_RW(margining_margin);
+static ssize_t margining_eye_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *s = file->private_data;
+ struct tb_port *port = s->private;
+ struct usb4_port *usb4 = port->usb4;
+ struct tb *tb = port->sw->tb;
+ int ret = 0;
+ char *buf;
+
+ buf = validate_and_copy_from_user(user_buf, &count);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
+ buf[count - 1] = '\0';
+
+ scoped_cond_guard(mutex_intr, ret = -ERESTARTSYS, &tb->lock) {
+ if (!strcmp(buf, "lower"))
+ usb4->margining->upper_eye = false;
+ else if (!strcmp(buf, "upper"))
+ usb4->margining->upper_eye = true;
+ else
+ ret = -EINVAL;
+ }
+
+ free_page((unsigned long)buf);
+ return ret ? ret : count;
+}
+
+static int margining_eye_show(struct seq_file *s, void *not_used)
+{
+ struct tb_port *port = s->private;
+ struct usb4_port *usb4 = port->usb4;
+ struct tb *tb = port->sw->tb;
+
+ scoped_guard(mutex_intr, &tb->lock) {
+ if (usb4->margining->upper_eye)
+ seq_puts(s, "lower [upper]\n");
+ else
+ seq_puts(s, "[lower] upper\n");
+
+ return 0;
+ }
+
+ return -ERESTARTSYS;
+}
+DEBUGFS_ATTR_RW(margining_eye);
+
static struct tb_margining *margining_alloc(struct tb_port *port,
struct device *dev,
enum usb4_sb_target target,
@@ -1392,6 +1605,12 @@ static struct tb_margining *margining_alloc(struct tb_port *port,
unsigned int val;
int ret;
+ ret = tb_port_get_link_generation(port);
+ if (ret < 0) {
+ tb_port_warn(port, "failed to read link generation\n");
+ return NULL;
+ }
+
margining = kzalloc(sizeof(*margining), GFP_KERNEL);
if (!margining)
return NULL;
@@ -1400,8 +1619,11 @@ static struct tb_margining *margining_alloc(struct tb_port *port,
margining->target = target;
margining->index = index;
margining->dev = dev;
+ margining->gen = ret;
+ margining->asym_rx = tb_port_width_supported(port, TB_LINK_WIDTH_ASYM_RX);
- ret = usb4_port_margining_caps(port, target, index, margining->caps);
+ ret = usb4_port_margining_caps(port, target, index, margining->caps,
+ ARRAY_SIZE(margining->caps));
if (ret) {
kfree(margining);
return NULL;
@@ -1411,10 +1633,17 @@ static struct tb_margining *margining_alloc(struct tb_port *port,
if (supports_software(margining))
margining->software = true;
- val = FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_STEPS_MASK, margining->caps[0]);
- margining->voltage_steps = val;
- val = FIELD_GET(USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_MASK, margining->caps[0]);
- margining->max_voltage_offset = 74 + val * 2;
+ if (margining->gen < 4) {
+ val = FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_STEPS_MASK, margining->caps[0]);
+ margining->voltage_steps = val;
+ val = FIELD_GET(USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_MASK, margining->caps[0]);
+ margining->max_voltage_offset = 74 + val * 2;
+ } else {
+ val = FIELD_GET(USB4_MARGIN_CAP_2_VOLTAGE_STEPS_MASK, margining->caps[2]);
+ margining->voltage_steps = val;
+ val = FIELD_GET(USB4_MARGIN_CAP_2_MAX_VOLTAGE_OFFSET_MASK, margining->caps[2]);
+ margining->max_voltage_offset = 74 + val * 2;
+ }
if (supports_optional_voltage_offset_range(margining)) {
val = FIELD_GET(USB4_MARGIN_CAP_0_VOLT_STEPS_OPT_MASK,
@@ -1456,11 +1685,10 @@ static struct tb_margining *margining_alloc(struct tb_port *port,
debugfs_create_file("results", 0600, dir, margining,
&margining_results_fops);
debugfs_create_file("test", 0600, dir, margining, &margining_test_fops);
- if (independent_voltage_margins(margining) == USB4_MARGIN_CAP_0_VOLTAGE_HL ||
+ if (independent_voltage_margins(margining) == USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_HL ||
(supports_time(margining) &&
- independent_time_margins(margining) == USB4_MARGIN_CAP_1_TIME_LR))
- debugfs_create_file("margin", 0600, dir, margining,
- &margining_margin_fops);
+ independent_time_margins(margining) == USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_LR))
+ debugfs_create_file("margin", 0600, dir, margining, &margining_margin_fops);
margining->error_counter = USB4_MARGIN_SW_ERROR_COUNTER_CLEAR;
margining->dwell_time = MIN_DWELL_TIME;
@@ -1477,6 +1705,10 @@ static struct tb_margining *margining_alloc(struct tb_port *port,
debugfs_create_file("dwell_time", DEBUGFS_MODE, dir, margining,
&margining_dwell_time_fops);
}
+
+ if (margining->gen >= 4)
+ debugfs_create_file("eye", 0600, dir, port, &margining_eye_fops);
+
return margining;
}
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index 7af2642b97cb..1257dd3ce7e6 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -1340,18 +1340,18 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (res)
return dev_err_probe(dev, res, "cannot enable PCI device, aborting\n");
- res = pcim_iomap_regions(pdev, 1 << 0, "thunderbolt");
- if (res)
- return dev_err_probe(dev, res, "cannot obtain PCI resources, aborting\n");
-
nhi = devm_kzalloc(&pdev->dev, sizeof(*nhi), GFP_KERNEL);
if (!nhi)
return -ENOMEM;
nhi->pdev = pdev;
nhi->ops = (const struct tb_nhi_ops *)id->driver_data;
- /* cannot fail - table is allocated in pcim_iomap_regions */
- nhi->iobase = pcim_iomap_table(pdev)[0];
+
+ nhi->iobase = pcim_iomap_region(pdev, 0, "thunderbolt");
+ res = PTR_ERR_OR_ZERO(nhi->iobase);
+ if (res)
+ return dev_err_probe(dev, res, "cannot obtain PCI resources, aborting\n");
+
nhi->hop_count = ioread32(nhi->iobase + REG_CAPS) & 0x3ff;
dev_dbg(dev, "total paths: %d\n", nhi->hop_count);
diff --git a/drivers/thunderbolt/sb_regs.h b/drivers/thunderbolt/sb_regs.h
index dbcad25ead50..5391502a4b87 100644
--- a/drivers/thunderbolt/sb_regs.h
+++ b/drivers/thunderbolt/sb_regs.h
@@ -49,7 +49,7 @@ enum usb4_sb_opcode {
/* USB4_SB_OPCODE_READ_LANE_MARGINING_CAP */
#define USB4_MARGIN_CAP_0_MODES_HW BIT(0)
#define USB4_MARGIN_CAP_0_MODES_SW BIT(1)
-#define USB4_MARGIN_CAP_0_2_LANES BIT(2)
+#define USB4_MARGIN_CAP_0_ALL_LANES BIT(2)
#define USB4_MARGIN_CAP_0_VOLTAGE_INDP_MASK GENMASK(4, 3)
#define USB4_MARGIN_CAP_0_VOLTAGE_MIN 0x0
#define USB4_MARGIN_CAP_0_VOLTAGE_HL 0x1
@@ -69,34 +69,44 @@ enum usb4_sb_opcode {
#define USB4_MARGIN_CAP_1_TIME_OFFSET_MASK GENMASK(20, 16)
#define USB4_MARGIN_CAP_1_MIN_BER_MASK GENMASK(25, 21)
#define USB4_MARGIN_CAP_1_MAX_BER_MASK GENMASK(30, 26)
+#define USB4_MARGIN_CAP_2_MODES_HW BIT(0)
+#define USB4_MARGIN_CAP_2_MODES_SW BIT(1)
+#define USB4_MARGIN_CAP_2_TIME BIT(2)
+#define USB4_MARGIN_CAP_2_MAX_VOLTAGE_OFFSET_MASK GENMASK(8, 3)
+#define USB4_MARGIN_CAP_2_VOLTAGE_STEPS_MASK GENMASK(15, 9)
+#define USB4_MARGIN_CAP_2_VOLTAGE_INDP_MASK GENMASK(17, 16)
+#define USB4_MARGIN_CAP_2_VOLTAGE_MIN 0x0
+#define USB4_MARGIN_CAP_2_VOLTAGE_BOTH 0x1
+#define USB4_MARGIN_CAP_2_TIME_INDP_MASK GENMASK(19, 18)
+#define USB4_MARGIN_CAP_2_TIME_MIN 0x0
+#define USB4_MARGIN_CAP_2_TIME_BOTH 0x1
/* USB4_SB_OPCODE_RUN_HW_LANE_MARGINING */
#define USB4_MARGIN_HW_TIME BIT(3)
-#define USB4_MARGIN_HW_RH BIT(4)
+#define USB4_MARGIN_HW_RHU BIT(4)
#define USB4_MARGIN_HW_BER_MASK GENMASK(9, 5)
#define USB4_MARGIN_HW_BER_SHIFT 5
#define USB4_MARGIN_HW_OPT_VOLTAGE BIT(10)
/* Applicable to all margin values */
-#define USB4_MARGIN_HW_RES_1_MARGIN_MASK GENMASK(6, 0)
-#define USB4_MARGIN_HW_RES_1_EXCEEDS BIT(7)
-/* Different lane margin shifts */
-#define USB4_MARGIN_HW_RES_1_L0_LL_MARGIN_SHIFT 8
-#define USB4_MARGIN_HW_RES_1_L1_RH_MARGIN_SHIFT 16
-#define USB4_MARGIN_HW_RES_1_L1_LL_MARGIN_SHIFT 24
+#define USB4_MARGIN_HW_RES_MARGIN_MASK GENMASK(6, 0)
+#define USB4_MARGIN_HW_RES_EXCEEDS BIT(7)
+
+/* Shifts for parsing the lane results */
+#define USB4_MARGIN_HW_RES_LANE_SHIFT 16
+#define USB4_MARGIN_HW_RES_LL_SHIFT 8
/* USB4_SB_OPCODE_RUN_SW_LANE_MARGINING */
#define USB4_MARGIN_SW_LANES_MASK GENMASK(2, 0)
-#define USB4_MARGIN_SW_LANE_0 0x0
-#define USB4_MARGIN_SW_LANE_1 0x1
-#define USB4_MARGIN_SW_ALL_LANES 0x7
#define USB4_MARGIN_SW_TIME BIT(3)
#define USB4_MARGIN_SW_RH BIT(4)
#define USB4_MARGIN_SW_OPT_VOLTAGE BIT(5)
#define USB4_MARGIN_SW_VT_MASK GENMASK(12, 6)
#define USB4_MARGIN_SW_COUNTER_MASK GENMASK(14, 13)
+#define USB4_MARGIN_SW_UPPER_EYE BIT(15)
#define USB4_MARGIN_SW_ERR_COUNTER_LANE_0_MASK GENMASK(3, 0)
#define USB4_MARGIN_SW_ERR_COUNTER_LANE_1_MASK GENMASK(7, 4)
+#define USB4_MARGIN_SW_ERR_COUNTER_LANE_2_MASK GENMASK(11, 8)
#endif
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 6737188f2581..ddbf0cd78377 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -1367,11 +1367,18 @@ enum usb4_margin_sw_error_counter {
USB4_MARGIN_SW_ERROR_COUNTER_STOP,
};
+enum usb4_margining_lane {
+ USB4_MARGINING_LANE_RX0 = 0,
+ USB4_MARGINING_LANE_RX1 = 1,
+ USB4_MARGINING_LANE_RX2 = 2,
+ USB4_MARGINING_LANE_ALL = 7,
+};
+
/**
* struct usb4_port_margining_params - USB4 margining parameters
* @error_counter: Error counter operation for software margining
* @ber_level: Current BER level contour value
- * @lanes: %0, %1 or %7 (all)
+ * @lanes: Lanes to enable for the margining operation
* @voltage_time_offset: Offset for voltage / time for software margining
* @optional_voltage_offset_range: Enable optional extended voltage range
* @right_high: %false if left/low margin test is performed, %true if right/high
@@ -1380,18 +1387,19 @@ enum usb4_margin_sw_error_counter {
struct usb4_port_margining_params {
enum usb4_margin_sw_error_counter error_counter;
u32 ber_level;
- u32 lanes;
+ enum usb4_margining_lane lanes;
u32 voltage_time_offset;
bool optional_voltage_offset_range;
bool right_high;
+ bool upper_eye;
bool time;
};
int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
- u8 index, u32 *caps);
+ u8 index, u32 *caps, size_t ncaps);
int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, const struct usb4_port_margining_params *params,
- u32 *results);
+ u32 *results, size_t nresults);
int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, const struct usb4_port_margining_params *params,
u32 *results);
diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c
index 402fdf8b1cde..e51d01671d8e 100644
--- a/drivers/thunderbolt/usb4.c
+++ b/drivers/thunderbolt/usb4.c
@@ -1631,11 +1631,12 @@ int usb4_port_asym_start(struct tb_port *port)
* @target: Sideband target
* @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER
* @caps: Array with at least two elements to hold the results
+ * @ncaps: Number of elements in the caps array
*
* Reads the USB4 port lane margining capabilities into @caps.
*/
int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
- u8 index, u32 *caps)
+ u8 index, u32 *caps, size_t ncaps)
{
int ret;
@@ -1645,7 +1646,7 @@ int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
return ret;
return usb4_port_sb_read(port, target, index, USB4_SB_DATA, caps,
- sizeof(*caps) * 2);
+ sizeof(*caps) * ncaps);
}
/**
@@ -1654,14 +1655,15 @@ int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
* @target: Sideband target
* @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER
* @params: Parameters for USB4 hardware margining
- * @results: Array with at least two elements to hold the results
+ * @results: Array to hold the results
+ * @nresults: Number of elements in the results array
*
* Runs hardware lane margining on USB4 port and returns the result in
* @results.
*/
int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, const struct usb4_port_margining_params *params,
- u32 *results)
+ u32 *results, size_t nresults)
{
u32 val;
int ret;
@@ -1672,8 +1674,8 @@ int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
val = params->lanes;
if (params->time)
val |= USB4_MARGIN_HW_TIME;
- if (params->right_high)
- val |= USB4_MARGIN_HW_RH;
+ if (params->right_high || params->upper_eye)
+ val |= USB4_MARGIN_HW_RHU;
if (params->ber_level)
val |= FIELD_PREP(USB4_MARGIN_HW_BER_MASK, params->ber_level);
if (params->optional_voltage_offset_range)
@@ -1690,7 +1692,7 @@ int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
return ret;
return usb4_port_sb_read(port, target, index, USB4_SB_DATA, results,
- sizeof(*results) * 2);
+ sizeof(*results) * nresults);
}
/**
@@ -1722,6 +1724,8 @@ int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target,
val |= USB4_MARGIN_SW_OPT_VOLTAGE;
if (params->right_high)
val |= USB4_MARGIN_SW_RH;
+ if (params->upper_eye)
+ val |= USB4_MARGIN_SW_UPPER_EYE;
val |= FIELD_PREP(USB4_MARGIN_SW_COUNTER_MASK, params->error_counter);
val |= FIELD_PREP(USB4_MARGIN_SW_VT_MASK, params->voltage_time_offset);
diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
index 25c201cfb91e..e5da9ce26006 100644
--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
+++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
@@ -569,7 +569,7 @@ static struct platform_driver aspeed_vuart_driver = {
.of_match_table = aspeed_vuart_table,
},
.probe = aspeed_vuart_probe,
- .remove_new = aspeed_vuart_remove,
+ .remove = aspeed_vuart_remove,
};
module_platform_driver(aspeed_vuart_driver);
diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c
index d7a0f271263a..fdb53b54e99e 100644
--- a/drivers/tty/serial/8250/8250_bcm2835aux.c
+++ b/drivers/tty/serial/8250/8250_bcm2835aux.c
@@ -267,7 +267,7 @@ static struct platform_driver bcm2835aux_serial_driver = {
.pm = pm_ptr(&bcm2835aux_dev_pm_ops),
},
.probe = bcm2835aux_serial_probe,
- .remove_new = bcm2835aux_serial_remove,
+ .remove = bcm2835aux_serial_remove,
};
module_platform_driver(bcm2835aux_serial_driver);
diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c
index 2569ca69223f..d0b18358859e 100644
--- a/drivers/tty/serial/8250/8250_bcm7271.c
+++ b/drivers/tty/serial/8250/8250_bcm7271.c
@@ -812,7 +812,7 @@ static int brcmuart_handle_irq(struct uart_port *p)
/*
* if Receive Data Interrupt is enabled and
* we're uing hardware flow control, deassert
- * RTS and wait for any chars in the pipline to
+ * RTS and wait for any chars in the pipeline to
* arrive and then check for DR again.
*/
if ((ier & UART_IER_RDI) && (up->mcr & UART_MCR_AFE)) {
@@ -1204,7 +1204,7 @@ static struct platform_driver brcmuart_platform_driver = {
.of_match_table = brcmuart_dt_ids,
},
.probe = brcmuart_probe,
- .remove_new = brcmuart_remove,
+ .remove = brcmuart_remove,
};
static int __init brcmuart_init(void)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index ab9e7f204260..6afcf27db3b8 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -750,7 +750,7 @@ static const struct dw8250_platform_data dw8250_renesas_rzn1_data = {
.quirks = DW_UART_QUIRK_CPR_VALUE | DW_UART_QUIRK_IS_DMA_FC,
};
-static const struct dw8250_platform_data dw8250_starfive_jh7100_data = {
+static const struct dw8250_platform_data dw8250_skip_set_rate_data = {
.usr_reg = DW_UART_USR,
.quirks = DW_UART_QUIRK_SKIP_SET_RATE,
};
@@ -760,7 +760,8 @@ static const struct of_device_id dw8250_of_match[] = {
{ .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
{ .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data },
{ .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
- { .compatible = "starfive,jh7100-uart", .data = &dw8250_starfive_jh7100_data },
+ { .compatible = "sophgo,sg2044-uart", .data = &dw8250_skip_set_rate_data },
+ { .compatible = "starfive,jh7100-uart", .data = &dw8250_skip_set_rate_data },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, dw8250_of_match);
@@ -796,7 +797,7 @@ static struct platform_driver dw8250_platform_driver = {
.acpi_match_table = dw8250_acpi_match,
},
.probe = dw8250_probe,
- .remove_new = dw8250_remove,
+ .remove = dw8250_remove,
};
module_platform_driver(dw8250_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
index a754755100ff..35094f884492 100644
--- a/drivers/tty/serial/8250/8250_em.c
+++ b/drivers/tty/serial/8250/8250_em.c
@@ -219,7 +219,7 @@ static struct platform_driver serial8250_em_platform_driver = {
.of_match_table = serial8250_em_dt_ids,
},
.probe = serial8250_em_probe,
- .remove_new = serial8250_em_remove,
+ .remove = serial8250_em_remove,
};
module_platform_driver(serial8250_em_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index b7a75db15249..fc5203446267 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -11,6 +11,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dmi.h>
+#include <linux/eeprom_93cx6.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/math.h>
@@ -135,8 +136,6 @@
#define UART_EXAR_REGB_EECS BIT(5)
#define UART_EXAR_REGB_EEDI BIT(6)
#define UART_EXAR_REGB_EEDO BIT(7)
-#define UART_EXAR_REGB_EE_ADDR_SIZE 6
-#define UART_EXAR_REGB_EE_DATA_SIZE 16
#define UART_EXAR_XR17C15X_PORT_OFFSET 0x200
#define UART_EXAR_XR17V25X_PORT_OFFSET 0x200
@@ -179,18 +178,19 @@
/* CTI EEPROM offsets */
#define CTI_EE_OFF_XR17C15X_OSC_FREQ 0x04 /* 2 words */
-#define CTI_EE_OFF_XR17V25X_OSC_FREQ 0x08 /* 2 words */
#define CTI_EE_OFF_XR17C15X_PART_NUM 0x0A /* 4 words */
-#define CTI_EE_OFF_XR17V25X_PART_NUM 0x0E /* 4 words */
#define CTI_EE_OFF_XR17C15X_SERIAL_NUM 0x0E /* 1 word */
+
+#define CTI_EE_OFF_XR17V25X_OSC_FREQ 0x08 /* 2 words */
+#define CTI_EE_OFF_XR17V25X_PART_NUM 0x0E /* 4 words */
#define CTI_EE_OFF_XR17V25X_SERIAL_NUM 0x12 /* 1 word */
+
#define CTI_EE_OFF_XR17V35X_SERIAL_NUM 0x11 /* 2 word */
#define CTI_EE_OFF_XR17V35X_BRD_FLAGS 0x13 /* 1 word */
#define CTI_EE_OFF_XR17V35X_PORT_FLAGS 0x14 /* 1 word */
#define CTI_EE_MASK_PORT_FLAGS_TYPE GENMASK(7, 0)
-#define CTI_EE_MASK_OSC_FREQ_LOWER GENMASK(15, 0)
-#define CTI_EE_MASK_OSC_FREQ_UPPER GENMASK(31, 16)
+#define CTI_EE_MASK_OSC_FREQ GENMASK(31, 0)
#define CTI_FPGA_RS485_IO_REG 0x2008
#define CTI_FPGA_CFG_INT_EN_REG 0x48
@@ -252,6 +252,7 @@ struct exar8250 {
unsigned int nr;
unsigned int osc_freq;
struct exar8250_board *board;
+ struct eeprom_93cx6 eeprom;
void __iomem *virt;
int line[];
};
@@ -267,92 +268,37 @@ static inline u8 exar_read_reg(struct exar8250 *priv, unsigned int reg)
return readb(priv->virt + reg);
}
-static inline void exar_ee_select(struct exar8250 *priv)
-{
- // Set chip select pin high to enable EEPROM reads/writes
- exar_write_reg(priv, UART_EXAR_REGB, UART_EXAR_REGB_EECS);
- // Min ~500ns delay needed between CS assert and EEPROM access
- udelay(1);
-}
-
-static inline void exar_ee_deselect(struct exar8250 *priv)
-{
- exar_write_reg(priv, UART_EXAR_REGB, 0x00);
-}
-
-static inline void exar_ee_write_bit(struct exar8250 *priv, u8 bit)
+static void exar_eeprom_93cx6_reg_read(struct eeprom_93cx6 *eeprom)
{
- u8 value = UART_EXAR_REGB_EECS;
+ struct exar8250 *priv = eeprom->data;
+ u8 regb = exar_read_reg(priv, UART_EXAR_REGB);
- if (bit)
- value |= UART_EXAR_REGB_EEDI;
-
- // Clock out the bit on the EEPROM interface
- exar_write_reg(priv, UART_EXAR_REGB, value);
- // 2us delay = ~500khz clock speed
- udelay(2);
-
- value |= UART_EXAR_REGB_EECK;
-
- exar_write_reg(priv, UART_EXAR_REGB, value);
- udelay(2);
+ /* EECK and EECS always read 0 from REGB so only set EEDO */
+ eeprom->reg_data_out = regb & UART_EXAR_REGB_EEDO;
}
-static inline u8 exar_ee_read_bit(struct exar8250 *priv)
+static void exar_eeprom_93cx6_reg_write(struct eeprom_93cx6 *eeprom)
{
- u8 regb;
- u8 value = UART_EXAR_REGB_EECS;
-
- // Clock in the bit on the EEPROM interface
- exar_write_reg(priv, UART_EXAR_REGB, value);
- // 2us delay = ~500khz clock speed
- udelay(2);
+ struct exar8250 *priv = eeprom->data;
+ u8 regb = 0;
- value |= UART_EXAR_REGB_EECK;
+ if (eeprom->reg_data_in)
+ regb |= UART_EXAR_REGB_EEDI;
+ if (eeprom->reg_data_clock)
+ regb |= UART_EXAR_REGB_EECK;
+ if (eeprom->reg_chip_select)
+ regb |= UART_EXAR_REGB_EECS;
- exar_write_reg(priv, UART_EXAR_REGB, value);
- udelay(2);
-
- regb = exar_read_reg(priv, UART_EXAR_REGB);
-
- return (regb & UART_EXAR_REGB_EEDO ? 1 : 0);
+ exar_write_reg(priv, UART_EXAR_REGB, regb);
}
-/**
- * exar_ee_read() - Read a word from the EEPROM
- * @priv: Device's private structure
- * @ee_addr: Offset of EEPROM to read word from
- *
- * Read a single 16bit word from an Exar UART's EEPROM.
- * The type of the EEPROM is AT93C46D.
- *
- * Return: EEPROM word
- */
-static u16 exar_ee_read(struct exar8250 *priv, u8 ee_addr)
+static void exar_eeprom_init(struct exar8250 *priv)
{
- int i;
- u16 data = 0;
-
- exar_ee_select(priv);
-
- // Send read command (opcode 110)
- exar_ee_write_bit(priv, 1);
- exar_ee_write_bit(priv, 1);
- exar_ee_write_bit(priv, 0);
-
- // Send address to read from
- for (i = UART_EXAR_REGB_EE_ADDR_SIZE - 1; i >= 0; i--)
- exar_ee_write_bit(priv, ee_addr & BIT(i));
-
- // Read data 1 bit at a time starting with a dummy bit
- for (i = UART_EXAR_REGB_EE_DATA_SIZE; i >= 0; i--) {
- if (exar_ee_read_bit(priv))
- data |= BIT(i);
- }
-
- exar_ee_deselect(priv);
-
- return data;
+ priv->eeprom.data = priv;
+ priv->eeprom.register_read = exar_eeprom_93cx6_reg_read;
+ priv->eeprom.register_write = exar_eeprom_93cx6_reg_write;
+ priv->eeprom.width = PCI_EEPROM_WIDTH_93C46;
+ priv->eeprom.quirks |= PCI_EEPROM_QUIRK_EXTRA_READ_CYCLE;
}
/**
@@ -360,7 +306,7 @@ static u16 exar_ee_read(struct exar8250 *priv, u8 ee_addr)
* @priv: Device's private structure
* @mpio_num: MPIO number/offset to configure
*
- * Configure a single MPIO as an output and disable tristate. It is reccomended
+ * Configure a single MPIO as an output and disable tristate. It is recommended
* to set the level with exar_mpio_set_high()/exar_mpio_set_low() prior to
* calling this function to ensure default MPIO pin state.
*
@@ -516,7 +462,7 @@ static int xr17v35x_startup(struct uart_port *port)
serial_port_out(port, UART_XR_EFR, UART_EFR_ECB);
/*
- * Make sure all interrups are masked until initialization is
+ * Make sure all interrupts are masked until initialization is
* complete and the FIFOs are cleared
*
* Synchronize UART_IER access against the console.
@@ -696,20 +642,16 @@ static int cti_plx_int_enable(struct exar8250 *priv)
*/
static int cti_read_osc_freq(struct exar8250 *priv, u8 eeprom_offset)
{
- u16 lower_word;
- u16 upper_word;
+ __le16 ee_words[2];
+ u32 osc_freq;
- lower_word = exar_ee_read(priv, eeprom_offset);
- // Check if EEPROM word was blank
- if (lower_word == 0xFFFF)
- return -EIO;
+ eeprom_93cx6_multiread(&priv->eeprom, eeprom_offset, ee_words, ARRAY_SIZE(ee_words));
- upper_word = exar_ee_read(priv, (eeprom_offset + 1));
- if (upper_word == 0xFFFF)
+ osc_freq = le16_to_cpu(ee_words[0]) | (le16_to_cpu(ee_words[1]) << 16);
+ if (osc_freq == CTI_EE_MASK_OSC_FREQ)
return -EIO;
- return FIELD_PREP(CTI_EE_MASK_OSC_FREQ_LOWER, lower_word) |
- FIELD_PREP(CTI_EE_MASK_OSC_FREQ_UPPER, upper_word);
+ return osc_freq;
}
/**
@@ -833,7 +775,7 @@ static enum cti_port_type cti_get_port_type_xr17v35x(struct exar8250 *priv,
u8 offset;
offset = CTI_EE_OFF_XR17V35X_PORT_FLAGS + port_num;
- port_flags = exar_ee_read(priv, offset);
+ eeprom_93cx6_read(&priv->eeprom, offset, &port_flags);
port_type = FIELD_GET(CTI_EE_MASK_PORT_FLAGS_TYPE, port_flags);
if (CTI_PORT_TYPE_VALID(port_type))
@@ -1551,6 +1493,8 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
if (rc)
return rc;
+ exar_eeprom_init(priv);
+
for (i = 0; i < nr_ports && i < maxnr; i++) {
rc = board->setup(priv, pcidev, &uart, i);
if (rc) {
diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c
index e2aa2a1a02dd..b4461a89b8d0 100644
--- a/drivers/tty/serial/8250/8250_fintek.c
+++ b/drivers/tty/serial/8250/8250_fintek.c
@@ -21,6 +21,7 @@
#define CHIP_ID_F81866 0x1010
#define CHIP_ID_F81966 0x0215
#define CHIP_ID_F81216AD 0x1602
+#define CHIP_ID_F81216E 0x1617
#define CHIP_ID_F81216H 0x0501
#define CHIP_ID_F81216 0x0802
#define VENDOR_ID1 0x23
@@ -125,7 +126,7 @@ static int fintek_8250_enter_key(u16 base_port, u8 key)
if (!request_muxed_region(base_port, 2, "8250_fintek"))
return -EBUSY;
- /* Force to deactive all SuperIO in this base_port */
+ /* Force to deactivate all SuperIO in this base_port */
outb(EXIT_KEY, base_port + ADDR_PORT);
outb(key, base_port + ADDR_PORT);
@@ -158,6 +159,7 @@ static int fintek_8250_check_id(struct fintek_8250 *pdata)
case CHIP_ID_F81866:
case CHIP_ID_F81966:
case CHIP_ID_F81216AD:
+ case CHIP_ID_F81216E:
case CHIP_ID_F81216H:
case CHIP_ID_F81216:
break;
@@ -181,6 +183,7 @@ static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min,
return 0;
case CHIP_ID_F81216AD:
+ case CHIP_ID_F81216E:
case CHIP_ID_F81216H:
case CHIP_ID_F81216:
*min = F81216_LDN_LOW;
@@ -250,6 +253,7 @@ static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level)
break;
case CHIP_ID_F81216AD:
+ case CHIP_ID_F81216E:
case CHIP_ID_F81216H:
case CHIP_ID_F81216:
sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_SHARE,
@@ -263,7 +267,8 @@ static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level)
static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata)
{
switch (pdata->pid) {
- case CHIP_ID_F81216H: /* 128Bytes FIFO */
+ case CHIP_ID_F81216E: /* 128Bytes FIFO */
+ case CHIP_ID_F81216H:
case CHIP_ID_F81966:
case CHIP_ID_F81866:
sio_write_mask_reg(pdata, FIFO_CTRL,
@@ -297,6 +302,7 @@ static void fintek_8250_set_termios(struct uart_port *port,
goto exit;
switch (pdata->pid) {
+ case CHIP_ID_F81216E:
case CHIP_ID_F81216H:
reg = RS485;
break;
@@ -346,6 +352,7 @@ static void fintek_8250_set_termios_handler(struct uart_8250_port *uart)
struct fintek_8250 *pdata = uart->port.private_data;
switch (pdata->pid) {
+ case CHIP_ID_F81216E:
case CHIP_ID_F81216H:
case CHIP_ID_F81966:
case CHIP_ID_F81866:
@@ -438,6 +445,11 @@ static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart)
uart->port.rs485_supported = fintek_8250_rs485_supported;
break;
+ case CHIP_ID_F81216E: /* F81216E does not support RS485 delays */
+ uart->port.rs485_config = fintek_8250_rs485_config;
+ uart->port.rs485_supported = fintek_8250_rs485_supported;
+ break;
+
default: /* No RS485 Auto direction functional */
break;
}
diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c
index b4ed442082a8..1b7bd55619c6 100644
--- a/drivers/tty/serial/8250/8250_fsl.c
+++ b/drivers/tty/serial/8250/8250_fsl.c
@@ -179,7 +179,7 @@ static struct platform_driver fsl8250_platform_driver = {
.acpi_match_table = ACPI_PTR(fsl_8250_acpi_id),
},
.probe = fsl8250_acpi_probe,
- .remove_new = fsl8250_acpi_remove,
+ .remove = fsl8250_acpi_remove,
};
module_platform_driver(fsl8250_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
index a2783e38a2e3..a73dd3773640 100644
--- a/drivers/tty/serial/8250/8250_ingenic.c
+++ b/drivers/tty/serial/8250/8250_ingenic.c
@@ -361,7 +361,7 @@ static struct platform_driver ingenic_uart_platform_driver = {
.of_match_table = of_match,
},
.probe = ingenic_uart_probe,
- .remove_new = ingenic_uart_remove,
+ .remove = ingenic_uart_remove,
};
module_platform_driver(ingenic_uart_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_ioc3.c b/drivers/tty/serial/8250/8250_ioc3.c
index 50c77c3dacf2..499e80aa4cf9 100644
--- a/drivers/tty/serial/8250/8250_ioc3.c
+++ b/drivers/tty/serial/8250/8250_ioc3.c
@@ -84,7 +84,7 @@ static void serial8250_ioc3_remove(struct platform_device *pdev)
static struct platform_driver serial8250_ioc3_driver = {
.probe = serial8250_ioc3_probe,
- .remove_new = serial8250_ioc3_remove,
+ .remove = serial8250_ioc3_remove,
.driver = {
.name = "ioc3-serial8250",
}
diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c
index 47e1a056a60c..d52445948da0 100644
--- a/drivers/tty/serial/8250/8250_lpc18xx.c
+++ b/drivers/tty/serial/8250/8250_lpc18xx.c
@@ -195,7 +195,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_serial_match);
static struct platform_driver lpc18xx_serial_driver = {
.probe = lpc18xx_serial_probe,
- .remove_new = lpc18xx_serial_remove,
+ .remove = lpc18xx_serial_remove,
.driver = {
.name = "lpc18xx-uart",
.of_match_table = lpc18xx_serial_match,
diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index b9cca210e171..b44de2ed7413 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -346,8 +346,8 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
/*
* Mediatek UARTs use an extra highspeed register (MTK_UART_HIGHS)
*
- * We need to recalcualte the quot register, as the claculation depends
- * on the vaule in the highspeed register.
+ * We need to recalculate the quot register, as the calculation depends
+ * on the value in the highspeed register.
*
* Some baudrates are not supported by the chip, so we use the next
* lower rate supported and update termios c_flag.
@@ -654,7 +654,7 @@ static struct platform_driver mtk8250_platform_driver = {
.of_match_table = mtk8250_of_match,
},
.probe = mtk8250_probe,
- .remove_new = mtk8250_remove,
+ .remove = mtk8250_remove,
};
module_platform_driver(mtk8250_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index e14f47ef1172..64aed7efc569 100644
--- a/drivers/tty/serial/8250/8250_of.c
+++ b/drivers/tty/serial/8250/8250_of.c
@@ -352,7 +352,7 @@ static struct platform_driver of_platform_serial_driver = {
.pm = &of_serial_pm_ops,
},
.probe = of_platform_serial_probe,
- .remove_new = of_platform_serial_remove,
+ .remove = of_platform_serial_remove,
};
module_platform_driver(of_platform_serial_driver);
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 88b58f44e4e9..9eb9aa766811 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -776,12 +776,12 @@ static void omap_8250_shutdown(struct uart_port *port)
struct uart_8250_port *up = up_to_u8250p(port);
struct omap8250_priv *priv = port->private_data;
+ pm_runtime_get_sync(port->dev);
+
flush_work(&priv->qos_work);
if (up->dma)
omap_8250_rx_dma_flush(up);
- pm_runtime_get_sync(port->dev);
-
serial_out(up, UART_OMAP_WER, 0);
if (priv->habit & UART_HAS_EFR2)
serial_out(up, UART_OMAP_EFR2, 0x0);
@@ -1304,7 +1304,7 @@ static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir,
/*
* This is mostly serial8250_handle_irq(). We have a slightly different DMA
- * hoook for RX/TX and need different logic for them in the ISR. Therefore we
+ * hook for RX/TX and need different logic for them in the ISR. Therefore we
* use the default routine in the non-DMA case and this one for with DMA.
*/
static int omap_8250_dma_handle_irq(struct uart_port *port)
@@ -1338,7 +1338,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
serial8250_tx_chars(up);
} else {
/*
- * try again due to an earlier failer which
+ * try again due to an earlier failure which
* might have been resolved by now.
*/
if (omap_8250_tx_dma(up))
@@ -1867,7 +1867,7 @@ static struct platform_driver omap8250_platform_driver = {
.of_match_table = omap8250_dt_ids,
},
.probe = omap8250_probe,
- .remove_new = omap8250_remove,
+ .remove = omap8250_remove,
};
module_platform_driver(omap8250_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c
index be7ff07cbdd0..8bdc1879d952 100644
--- a/drivers/tty/serial/8250/8250_platform.c
+++ b/drivers/tty/serial/8250/8250_platform.c
@@ -285,7 +285,7 @@ MODULE_DEVICE_TABLE(acpi, acpi_platform_serial_table);
static struct platform_driver serial8250_isa_driver = {
.probe = serial8250_probe,
- .remove_new = serial8250_remove,
+ .remove = serial8250_remove,
.suspend = serial8250_suspend,
.resume = serial8250_resume,
.driver = {
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
index 96dd6126296c..6dd0190b4843 100644
--- a/drivers/tty/serial/8250/8250_pxa.c
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -154,7 +154,7 @@ static void serial_pxa_remove(struct platform_device *pdev)
static struct platform_driver serial_pxa_driver = {
.probe = serial_pxa_probe,
- .remove_new = serial_pxa_remove,
+ .remove = serial_pxa_remove,
.driver = {
.name = "pxa2xx-uart",
diff --git a/drivers/tty/serial/8250/8250_tegra.c b/drivers/tty/serial/8250/8250_tegra.c
index 60a80d00d251..2f3b0075763f 100644
--- a/drivers/tty/serial/8250/8250_tegra.c
+++ b/drivers/tty/serial/8250/8250_tegra.c
@@ -182,7 +182,7 @@ static struct platform_driver tegra_uart_driver = {
.acpi_match_table = ACPI_PTR(tegra_uart_acpi_match),
},
.probe = tegra_uart_probe,
- .remove_new = tegra_uart_remove,
+ .remove = tegra_uart_remove,
};
module_platform_driver(tegra_uart_driver);
diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c
index 670d2ca0f757..4874a9632db3 100644
--- a/drivers/tty/serial/8250/8250_uniphier.c
+++ b/drivers/tty/serial/8250/8250_uniphier.c
@@ -282,7 +282,7 @@ MODULE_DEVICE_TABLE(of, uniphier_uart_match);
static struct platform_driver uniphier_uart_platform_driver = {
.probe = uniphier_uart_probe,
- .remove_new = uniphier_uart_remove,
+ .remove = uniphier_uart_remove,
.driver = {
.name = "uniphier-uart",
.of_match_table = uniphier_uart_match,
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 1eb20350fcf4..55d26d16df9b 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -150,6 +150,7 @@ config SERIAL_8250_EXAR
tristate "8250/16550 Exar/Commtech PCI/PCIe device support"
depends on SERIAL_8250 && PCI
select SERIAL_8250_PCILIB
+ select EEPROM_93CX6
default SERIAL_8250
help
This builds support for XR17C1xx, XR17V3xx and some Commtech
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index effcba71ea77..b9c3c3bed0c1 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -175,8 +175,8 @@ static int altera_jtaguart_startup(struct uart_port *port)
ret = request_irq(port->irq, altera_jtaguart_interrupt, 0,
DRV_NAME, port);
if (ret) {
- pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d "
- "interrupt vector=%d\n", port->line, port->irq);
+ dev_err(port->dev, "unable to attach Altera JTAG UART %d interrupt vector=%d\n",
+ port->line, port->irq);
return ret;
}
@@ -449,7 +449,7 @@ MODULE_DEVICE_TABLE(of, altera_jtaguart_match);
static struct platform_driver altera_jtaguart_platform_driver = {
.probe = altera_jtaguart_probe,
- .remove_new = altera_jtaguart_remove,
+ .remove = altera_jtaguart_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(altera_jtaguart_match),
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 897f0995b2fe..c94655453c33 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -307,8 +307,8 @@ static int altera_uart_startup(struct uart_port *port)
ret = request_irq(port->irq, altera_uart_interrupt, 0,
dev_name(port->dev), port);
if (ret) {
- pr_err(DRV_NAME ": unable to attach Altera UART %d "
- "interrupt vector=%d\n", port->line, port->irq);
+ dev_err(port->dev, "unable to attach Altera UART %d interrupt vector=%d\n",
+ port->line, port->irq);
return ret;
}
}
@@ -617,7 +617,7 @@ MODULE_DEVICE_TABLE(of, altera_uart_match);
static struct platform_driver altera_uart_platform_driver = {
.probe = altera_uart_probe,
- .remove_new = altera_uart_remove,
+ .remove = altera_uart_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(altera_uart_match),
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 1c60850030b1..69b7a3e1e418 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1819,6 +1819,13 @@ static void pl011_unthrottle_rx(struct uart_port *port)
pl011_write(uap->im, uap, REG_IMSC);
+#ifdef CONFIG_DMA_ENGINE
+ if (uap->using_rx_dma) {
+ uap->dmacr |= UART011_RXDMAE;
+ pl011_write(uap->dmacr, uap, REG_DMACR);
+ }
+#endif
+
uart_port_unlock_irqrestore(&uap->port, flags);
}
@@ -2937,7 +2944,7 @@ MODULE_DEVICE_TABLE(acpi, sbsa_uart_acpi_match);
static struct platform_driver arm_sbsa_uart_platform_driver = {
.probe = sbsa_uart_probe,
- .remove_new = sbsa_uart_remove,
+ .remove = sbsa_uart_remove,
.driver = {
.name = "sbsa-uart",
.pm = &pl011_dev_pm_ops,
diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
index 47889a557119..8bb33556b312 100644
--- a/drivers/tty/serial/ar933x_uart.c
+++ b/drivers/tty/serial/ar933x_uart.c
@@ -832,7 +832,7 @@ MODULE_DEVICE_TABLE(of, ar933x_uart_of_ids);
static struct platform_driver ar933x_uart_platform_driver = {
.probe = ar933x_uart_probe,
- .remove_new = ar933x_uart_remove,
+ .remove = ar933x_uart_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(ar933x_uart_of_ids),
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 09b246c9e389..0cf05ac18993 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -1166,7 +1166,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
port->icount.rx += count;
}
- /* USART retreives ownership of RX DMA buffer */
+ /* USART retrieves ownership of RX DMA buffer */
dma_sync_single_for_device(port->dev, atmel_port->rx_phys,
ATMEL_SERIAL_RX_SIZE, DMA_FROM_DEVICE);
@@ -2419,17 +2419,11 @@ static void atmel_release_port(struct uart_port *port)
static int atmel_request_port(struct uart_port *port)
{
struct platform_device *mpdev = to_platform_device(port->dev->parent);
- int size = resource_size(mpdev->resource);
-
- if (!request_mem_region(port->mapbase, size, "atmel_serial"))
- return -EBUSY;
if (port->flags & UPF_IOREMAP) {
- port->membase = ioremap(port->mapbase, size);
- if (port->membase == NULL) {
- release_mem_region(port->mapbase, size);
- return -ENOMEM;
- }
+ port->membase = devm_platform_ioremap_resource(mpdev, 0);
+ if (IS_ERR(port->membase))
+ return PTR_ERR(port->membase);
}
return 0;
@@ -3017,7 +3011,7 @@ static SIMPLE_DEV_PM_OPS(atmel_serial_pm_ops, atmel_serial_suspend,
static struct platform_driver atmel_serial_driver = {
.probe = atmel_serial_probe,
- .remove_new = atmel_serial_remove,
+ .remove = atmel_serial_remove,
.driver = {
.name = "atmel_usart_serial",
.of_match_table = of_match_ptr(atmel_serial_dt_ids),
diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
index b88cc28c94e3..51df9d2d8bfc 100644
--- a/drivers/tty/serial/bcm63xx_uart.c
+++ b/drivers/tty/serial/bcm63xx_uart.c
@@ -884,7 +884,7 @@ MODULE_DEVICE_TABLE(of, bcm63xx_of_match);
*/
static struct platform_driver bcm_uart_platform_driver = {
.probe = bcm_uart_probe,
- .remove_new = bcm_uart_remove,
+ .remove = bcm_uart_remove,
.driver = {
.name = "bcm63xx_uart",
.of_match_table = bcm63xx_of_match,
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index 30425a3d19fb..83186bf50002 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -529,7 +529,7 @@ static struct platform_driver clps711x_uart_platform = {
.of_match_table = of_match_ptr(clps711x_uart_dt_ids),
},
.probe = uart_clps711x_probe,
- .remove_new = uart_clps711x_remove,
+ .remove = uart_clps711x_remove,
};
static int __init uart_clps711x_init(void)
diff --git a/drivers/tty/serial/cpm_uart.c b/drivers/tty/serial/cpm_uart.c
index 6eb8625de435..b778a20ec9b1 100644
--- a/drivers/tty/serial/cpm_uart.c
+++ b/drivers/tty/serial/cpm_uart.c
@@ -1573,7 +1573,7 @@ static struct platform_driver cpm_uart_driver = {
.of_match_table = cpm_uart_match,
},
.probe = cpm_uart_probe,
- .remove_new = cpm_uart_remove,
+ .remove = cpm_uart_remove,
};
static int __init cpm_uart_init(void)
diff --git a/drivers/tty/serial/digicolor-usart.c b/drivers/tty/serial/digicolor-usart.c
index 2ccd13cc0a89..d2482df5cb9b 100644
--- a/drivers/tty/serial/digicolor-usart.c
+++ b/drivers/tty/serial/digicolor-usart.c
@@ -522,7 +522,7 @@ static struct platform_driver digicolor_uart_platform = {
.of_match_table = of_match_ptr(digicolor_uart_dt_ids),
},
.probe = digicolor_uart_probe,
- .remove_new = digicolor_uart_remove,
+ .remove = digicolor_uart_remove,
};
static int __init digicolor_uart_init(void)
diff --git a/drivers/tty/serial/esp32_acm.c b/drivers/tty/serial/esp32_acm.c
index 85eb0392e379..bb7cc65427f0 100644
--- a/drivers/tty/serial/esp32_acm.c
+++ b/drivers/tty/serial/esp32_acm.c
@@ -423,7 +423,7 @@ static void esp32s3_acm_remove(struct platform_device *pdev)
static struct platform_driver esp32s3_acm_driver = {
.probe = esp32s3_acm_probe,
- .remove_new = esp32s3_acm_remove,
+ .remove = esp32s3_acm_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = esp32s3_acm_dt_ids,
diff --git a/drivers/tty/serial/esp32_uart.c b/drivers/tty/serial/esp32_uart.c
index 8c86cf9cb763..667c2198a03a 100644
--- a/drivers/tty/serial/esp32_uart.c
+++ b/drivers/tty/serial/esp32_uart.c
@@ -743,7 +743,7 @@ static void esp32_uart_remove(struct platform_device *pdev)
static struct platform_driver esp32_uart_driver = {
.probe = esp32_uart_probe,
- .remove_new = esp32_uart_remove,
+ .remove = esp32_uart_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = esp32_uart_dt_ids,
diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c
index e972df4b188d..e70a56de1fce 100644
--- a/drivers/tty/serial/fsl_linflexuart.c
+++ b/drivers/tty/serial/fsl_linflexuart.c
@@ -882,7 +882,7 @@ static SIMPLE_DEV_PM_OPS(linflex_pm_ops, linflex_suspend, linflex_resume);
static struct platform_driver linflex_driver = {
.probe = linflex_probe,
- .remove_new = linflex_remove,
+ .remove = linflex_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = linflex_dt_ids,
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 77efa7ee6eda..57b0632a3db6 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -184,6 +184,7 @@
#define UARTCTRL_SBK 0x00010000
#define UARTCTRL_MA1IE 0x00008000
#define UARTCTRL_MA2IE 0x00004000
+#define UARTCTRL_M7 0x00000800
#define UARTCTRL_IDLECFG GENMASK(10, 8)
#define UARTCTRL_LOOPS 0x00000080
#define UARTCTRL_DOZEEN 0x00000040
@@ -2222,8 +2223,9 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
modem = lpuart32_read(&sport->port, UARTMODIR);
sport->is_cs7 = false;
/*
- * only support CS8 and CS7, and for CS7 must enable PE.
+ * only support CS8 and CS7
* supported mode:
+ * - (7,n,1) (imx only)
* - (7,e/o,1)
* - (8,n,1)
* - (8,m/s,1)
@@ -2238,7 +2240,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
if ((termios->c_cflag & CSIZE) == CS8 ||
(termios->c_cflag & CSIZE) == CS7)
- ctrl = old_ctrl & ~UARTCTRL_M;
+ ctrl = old_ctrl & ~(UARTCTRL_M | UARTCTRL_M7);
if (termios->c_cflag & CMSPAR) {
if ((termios->c_cflag & CSIZE) != CS8) {
@@ -2265,9 +2267,18 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
else
bd &= ~UARTBAUD_SBNS;
- /* parity must be enabled when CS7 to match 8-bits format */
- if ((termios->c_cflag & CSIZE) == CS7)
- termios->c_cflag |= PARENB;
+ /*
+ * imx support 7-bits format, no limitation on parity when CS7
+ * for layerscape, parity must be enabled when CS7 to match 8-bits format
+ */
+ if ((termios->c_cflag & CSIZE) == CS7 && !(termios->c_cflag & PARENB)) {
+ if (is_imx7ulp_lpuart(sport) ||
+ is_imx8ulp_lpuart(sport) ||
+ is_imx8qxp_lpuart(sport))
+ ctrl |= UARTCTRL_M7;
+ else
+ termios->c_cflag |= PARENB;
+ }
if ((termios->c_cflag & PARENB)) {
if (termios->c_cflag & CMSPAR) {
@@ -3206,7 +3217,7 @@ static const struct dev_pm_ops lpuart_pm_ops = {
static struct platform_driver lpuart_driver = {
.probe = lpuart_probe,
- .remove_new = lpuart_remove,
+ .remove = lpuart_remove,
.driver = {
.name = "fsl-lpuart",
.of_match_table = lpuart_dt_ids,
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 90974d338f3c..17f70e4bee43 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -230,6 +230,8 @@ struct imx_port {
unsigned int saved_reg[10];
bool context_saved;
+ bool last_putchar_was_newline;
+
enum imx_tx_state tx_state;
struct hrtimer trigger_start_tx;
struct hrtimer trigger_stop_tx;
@@ -370,6 +372,7 @@ static void imx_uart_soft_reset(struct imx_port *sport)
sport->idle_counter = 0;
}
+/* called with port.lock taken and irqs off */
static void imx_uart_disable_loopback_rs485(struct imx_port *sport)
{
unsigned int uts;
@@ -470,6 +473,7 @@ static void imx_uart_stop_tx(struct uart_port *port)
}
}
+/* called with port.lock taken and irqs off */
static void imx_uart_stop_rx_with_loopback_ctrl(struct uart_port *port, bool loopback)
{
struct imx_port *sport = to_imx_port(port);
@@ -818,6 +822,8 @@ static irqreturn_t imx_uart_txint(int irq, void *dev_id)
* issuing soft reset to the UART (just stop/start of RX does not help). Note
* that what we do here is sending isolated start bit about 2.4 times shorter
* than it is to be on UART configured baud rate.
+ *
+ * Called with port.lock taken and irqs off.
*/
static void imx_uart_check_flood(struct imx_port *sport, u32 usr2)
{
@@ -853,6 +859,7 @@ static void imx_uart_check_flood(struct imx_port *sport, u32 usr2)
}
}
+/* called with port.lock taken and irqs off */
static irqreturn_t __imx_uart_rxint(int irq, void *dev_id)
{
struct imx_port *sport = dev_id;
@@ -931,6 +938,7 @@ static void imx_uart_clear_rx_errors(struct imx_port *sport);
/*
* We have a modem side uart, so the meanings of RTS and CTS are inverted.
*/
+/* called with port.lock taken and irqs off */
static unsigned int imx_uart_get_hwmctrl(struct imx_port *sport)
{
unsigned int tmp = TIOCM_DSR;
@@ -953,6 +961,8 @@ static unsigned int imx_uart_get_hwmctrl(struct imx_port *sport)
/*
* Handle any change of modem status signal since we were last called.
+ *
+ * Called with port.lock taken and irqs off.
*/
static void imx_uart_mctrl_check(struct imx_port *sport)
{
@@ -1292,6 +1302,7 @@ static int imx_uart_start_rx_dma(struct imx_port *sport)
return 0;
}
+/* called with port.lock taken and irqs off */
static void imx_uart_clear_rx_errors(struct imx_port *sport)
{
struct tty_port *port = &sport->port.state->port;
@@ -1422,6 +1433,7 @@ err:
return ret;
}
+/* called with port.lock taken and irqs off */
static void imx_uart_enable_dma(struct imx_port *sport)
{
u32 ucr1;
@@ -2069,26 +2081,34 @@ static void imx_uart_console_putchar(struct uart_port *port, unsigned char ch)
barrier();
imx_uart_writel(sport, ch, URTX0);
+
+ sport->last_putchar_was_newline = (ch == '\n');
}
-/*
- * Interrupts are disabled on entering
- */
-static void
-imx_uart_console_write(struct console *co, const char *s, unsigned int count)
+static void imx_uart_console_device_lock(struct console *co, unsigned long *flags)
+{
+ struct uart_port *up = &imx_uart_ports[co->index]->port;
+
+ return __uart_port_lock_irqsave(up, flags);
+}
+
+static void imx_uart_console_device_unlock(struct console *co, unsigned long flags)
+{
+ struct uart_port *up = &imx_uart_ports[co->index]->port;
+
+ return __uart_port_unlock_irqrestore(up, flags);
+}
+
+static void imx_uart_console_write_atomic(struct console *co,
+ struct nbcon_write_context *wctxt)
{
struct imx_port *sport = imx_uart_ports[co->index];
+ struct uart_port *port = &sport->port;
struct imx_port_ucrs old_ucr;
- unsigned long flags;
unsigned int ucr1, usr2;
- int locked = 1;
- if (sport->port.sysrq)
- locked = 0;
- else if (oops_in_progress)
- locked = uart_port_trylock_irqsave(&sport->port, &flags);
- else
- uart_port_lock_irqsave(&sport->port, &flags);
+ if (!nbcon_enter_unsafe(wctxt))
+ return;
/*
* First, save UCR1/2/3 and then disable interrupts
@@ -2102,10 +2122,12 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN);
imx_uart_writel(sport, ucr1, UCR1);
-
imx_uart_writel(sport, old_ucr.ucr2 | UCR2_TXEN, UCR2);
- uart_console_write(&sport->port, s, count, imx_uart_console_putchar);
+ if (!sport->last_putchar_was_newline)
+ uart_console_write(port, "\n", 1, imx_uart_console_putchar);
+ uart_console_write(port, wctxt->outbuf, wctxt->len,
+ imx_uart_console_putchar);
/*
* Finally, wait for transmitter to become empty
@@ -2115,8 +2137,73 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
0, USEC_PER_SEC, false, sport, USR2);
imx_uart_ucrs_restore(sport, &old_ucr);
- if (locked)
- uart_port_unlock_irqrestore(&sport->port, flags);
+ nbcon_exit_unsafe(wctxt);
+}
+
+static void imx_uart_console_write_thread(struct console *co,
+ struct nbcon_write_context *wctxt)
+{
+ struct imx_port *sport = imx_uart_ports[co->index];
+ struct uart_port *port = &sport->port;
+ struct imx_port_ucrs old_ucr;
+ unsigned int ucr1, usr2;
+
+ if (!nbcon_enter_unsafe(wctxt))
+ return;
+
+ /*
+ * First, save UCR1/2/3 and then disable interrupts
+ */
+ imx_uart_ucrs_save(sport, &old_ucr);
+ ucr1 = old_ucr.ucr1;
+
+ if (imx_uart_is_imx1(sport))
+ ucr1 |= IMX1_UCR1_UARTCLKEN;
+ ucr1 |= UCR1_UARTEN;
+ ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN);
+
+ imx_uart_writel(sport, ucr1, UCR1);
+ imx_uart_writel(sport, old_ucr.ucr2 | UCR2_TXEN, UCR2);
+
+ if (nbcon_exit_unsafe(wctxt)) {
+ int len = READ_ONCE(wctxt->len);
+ int i;
+
+ /*
+ * Write out the message. Toggle unsafe for each byte in order
+ * to give another (higher priority) context the opportunity
+ * for a friendly takeover. If such a takeover occurs, this
+ * context must reacquire ownership in order to perform final
+ * actions (such as re-enabling the interrupts).
+ *
+ * IMPORTANT: wctxt->outbuf and wctxt->len are no longer valid
+ * after a reacquire so writing the message must be
+ * aborted.
+ */
+ for (i = 0; i < len; i++) {
+ if (!nbcon_enter_unsafe(wctxt))
+ break;
+
+ uart_console_write(port, wctxt->outbuf + i, 1,
+ imx_uart_console_putchar);
+
+ if (!nbcon_exit_unsafe(wctxt))
+ break;
+ }
+ }
+
+ while (!nbcon_enter_unsafe(wctxt))
+ nbcon_reacquire_nobuf(wctxt);
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore UCR1/2/3
+ */
+ read_poll_timeout(imx_uart_readl, usr2, usr2 & USR2_TXDC,
+ 0, USEC_PER_SEC, false, sport, USR2);
+ imx_uart_ucrs_restore(sport, &old_ucr);
+
+ nbcon_exit_unsafe(wctxt);
}
/*
@@ -2208,6 +2295,8 @@ imx_uart_console_setup(struct console *co, char *options)
if (retval)
goto error_console;
+ sport->last_putchar_was_newline = true;
+
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else
@@ -2244,11 +2333,14 @@ imx_uart_console_exit(struct console *co)
static struct uart_driver imx_uart_uart_driver;
static struct console imx_uart_console = {
.name = DEV_NAME,
- .write = imx_uart_console_write,
+ .write_atomic = imx_uart_console_write_atomic,
+ .write_thread = imx_uart_console_write_thread,
+ .device_lock = imx_uart_console_device_lock,
+ .device_unlock = imx_uart_console_device_unlock,
+ .flags = CON_PRINTBUFFER | CON_NBCON,
.device = uart_console_device,
.setup = imx_uart_console_setup,
.exit = imx_uart_console_exit,
- .flags = CON_PRINTBUFFER,
.index = -1,
.data = &imx_uart_uart_driver,
};
@@ -2595,10 +2687,13 @@ static void imx_uart_save_context(struct imx_port *sport)
uart_port_unlock_irqrestore(&sport->port, flags);
}
+/* called with irq off */
static void imx_uart_enable_wakeup(struct imx_port *sport, bool on)
{
u32 ucr3;
+ uart_port_lock(&sport->port);
+
ucr3 = imx_uart_readl(sport, UCR3);
if (on) {
imx_uart_writel(sport, USR1_AWAKE, USR1);
@@ -2618,6 +2713,8 @@ static void imx_uart_enable_wakeup(struct imx_port *sport, bool on)
}
imx_uart_writel(sport, ucr1, UCR1);
}
+
+ uart_port_unlock(&sport->port);
}
static int imx_uart_suspend_noirq(struct device *dev)
@@ -2717,7 +2814,7 @@ static const struct dev_pm_ops imx_uart_pm_ops = {
static struct platform_driver imx_uart_platform_driver = {
.probe = imx_uart_probe,
- .remove_new = imx_uart_remove,
+ .remove = imx_uart_remove,
.driver = {
.name = "imx-uart",
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index a0731773ce75..58a3ab030d67 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -915,7 +915,7 @@ MODULE_DEVICE_TABLE(of, ltq_asc_match);
static struct platform_driver lqasc_driver = {
.probe = lqasc_probe,
- .remove_new = lqasc_remove,
+ .remove = lqasc_remove,
.driver = {
.name = DRVNAME,
.of_match_table = ltq_asc_match,
diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c
index 3ce369f76349..6c13cf1ab646 100644
--- a/drivers/tty/serial/liteuart.c
+++ b/drivers/tty/serial/liteuart.c
@@ -353,7 +353,7 @@ MODULE_DEVICE_TABLE(of, liteuart_of_match);
static struct platform_driver liteuart_platform_driver = {
.probe = liteuart_probe,
- .remove_new = liteuart_remove,
+ .remove = liteuart_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = liteuart_of_match,
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index 3e4ac46de1bc..42c5f9bc18b7 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -695,7 +695,7 @@ MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids);
static struct platform_driver serial_hs_lpc32xx_driver = {
.probe = serial_hs_lpc32xx_probe,
- .remove_new = serial_hs_lpc32xx_remove,
+ .remove = serial_hs_lpc32xx_remove,
.suspend = serial_hs_lpc32xx_suspend,
.resume = serial_hs_lpc32xx_resume,
.driver = {
diff --git a/drivers/tty/serial/ma35d1_serial.c b/drivers/tty/serial/ma35d1_serial.c
index 3b4206e815fe..8dcad52eedfd 100644
--- a/drivers/tty/serial/ma35d1_serial.c
+++ b/drivers/tty/serial/ma35d1_serial.c
@@ -794,7 +794,7 @@ static int ma35d1serial_resume(struct platform_device *dev)
static struct platform_driver ma35d1serial_driver = {
.probe = ma35d1serial_probe,
- .remove_new = ma35d1serial_remove,
+ .remove = ma35d1serial_remove,
.suspend = ma35d1serial_suspend,
.resume = ma35d1serial_resume,
.driver = {
diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c
index 58858dd352c5..93e7dda4d39a 100644
--- a/drivers/tty/serial/mcf.c
+++ b/drivers/tty/serial/mcf.c
@@ -616,7 +616,7 @@ static void mcf_remove(struct platform_device *pdev)
static struct platform_driver mcf_platform_driver = {
.probe = mcf_probe,
- .remove_new = mcf_remove,
+ .remove = mcf_remove,
.driver = {
.name = "mcfuart",
},
diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
index 8eb586ac3b0d..a6cb2a535f9d 100644
--- a/drivers/tty/serial/meson_uart.c
+++ b/drivers/tty/serial/meson_uart.c
@@ -842,7 +842,7 @@ MODULE_DEVICE_TABLE(of, meson_uart_dt_match);
static struct platform_driver meson_uart_platform_driver = {
.probe = meson_uart_probe,
- .remove_new = meson_uart_remove,
+ .remove = meson_uart_remove,
.driver = {
.name = "meson_uart",
.of_match_table = meson_uart_dt_match,
diff --git a/drivers/tty/serial/milbeaut_usio.c b/drivers/tty/serial/milbeaut_usio.c
index fb082ee73d5b..059bea18dbab 100644
--- a/drivers/tty/serial/milbeaut_usio.c
+++ b/drivers/tty/serial/milbeaut_usio.c
@@ -570,7 +570,7 @@ MODULE_DEVICE_TABLE(of, mlb_usio_dt_ids);
static struct platform_driver mlb_usio_driver = {
.probe = mlb_usio_probe,
- .remove_new = mlb_usio_remove,
+ .remove = mlb_usio_remove,
.driver = {
.name = USIO_NAME,
.of_match_table = mlb_usio_dt_ids,
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 95dae5e27b28..f55aa353aed9 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1843,7 +1843,7 @@ MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match);
static struct platform_driver mpc52xx_uart_of_driver = {
.probe = mpc52xx_uart_of_probe,
- .remove_new = mpc52xx_uart_of_remove,
+ .remove = mpc52xx_uart_of_remove,
#ifdef CONFIG_PM
.suspend = mpc52xx_uart_of_suspend,
.resume = mpc52xx_uart_of_resume,
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 0a9c5219df88..1b137e068444 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -1894,7 +1894,7 @@ static const struct dev_pm_ops msm_serial_dev_pm_ops = {
};
static struct platform_driver msm_platform_driver = {
- .remove_new = msm_serial_remove,
+ .remove = msm_serial_remove,
.probe = msm_serial_probe,
.driver = {
.name = "msm_serial",
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index a1c76565c399..cc65c9fb6446 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1704,7 +1704,7 @@ static void mxs_auart_remove(struct platform_device *pdev)
static struct platform_driver mxs_auart_driver = {
.probe = mxs_auart_probe,
- .remove_new = mxs_auart_remove,
+ .remove = mxs_auart_remove,
.driver = {
.name = "mxs-auart",
.of_match_table = mxs_auart_dt_ids,
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index d7e172eeaab1..0b85f47ff19e 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1802,7 +1802,7 @@ MODULE_DEVICE_TABLE(of, omap_serial_of_match);
static struct platform_driver serial_omap_driver = {
.probe = serial_omap_probe,
- .remove_new = serial_omap_remove,
+ .remove = serial_omap_remove,
.driver = {
.name = OMAP_SERIAL_DRIVER_NAME,
.pm = &serial_omap_dev_pm_ops,
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c
index ecec483d4d59..0542882cfbbe 100644
--- a/drivers/tty/serial/owl-uart.c
+++ b/drivers/tty/serial/owl-uart.c
@@ -730,7 +730,7 @@ static void owl_uart_remove(struct platform_device *pdev)
static struct platform_driver owl_uart_platform_driver = {
.probe = owl_uart_probe,
- .remove_new = owl_uart_remove,
+ .remove = owl_uart_remove,
.driver = {
.name = "owl-uart",
.of_match_table = owl_uart_dt_matches,
diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c
index 261c8115a700..14d50bd7f1bd 100644
--- a/drivers/tty/serial/pic32_uart.c
+++ b/drivers/tty/serial/pic32_uart.c
@@ -956,7 +956,7 @@ MODULE_DEVICE_TABLE(of, pic32_serial_dt_ids);
static struct platform_driver pic32_uart_platform_driver = {
.probe = pic32_uart_probe,
- .remove_new = pic32_uart_remove,
+ .remove = pic32_uart_remove,
.driver = {
.name = PIC32_DEV_NAME,
.of_match_table = of_match_ptr(pic32_serial_dt_ids),
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index 8969b11cc0a9..e3a919328695 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -1776,7 +1776,7 @@ static struct macio_driver pmz_driver = {
static struct platform_driver pmz_driver = {
.probe = pmz_attach,
- .remove_new = pmz_detach,
+ .remove = pmz_detach,
.driver = {
.name = "scc",
},
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 5dfe4e599ad6..a80ce7aaf309 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -1839,7 +1839,7 @@ static const struct of_device_id qcom_geni_serial_match_table[] = {
MODULE_DEVICE_TABLE(of, qcom_geni_serial_match_table);
static struct platform_driver qcom_geni_serial_platform_driver = {
- .remove_new = qcom_geni_serial_remove,
+ .remove = qcom_geni_serial_remove,
.probe = qcom_geni_serial_probe,
.driver = {
.name = "qcom_geni_serial",
diff --git a/drivers/tty/serial/rda-uart.c b/drivers/tty/serial/rda-uart.c
index 663e35e424bd..87fa30d68687 100644
--- a/drivers/tty/serial/rda-uart.c
+++ b/drivers/tty/serial/rda-uart.c
@@ -777,7 +777,7 @@ static void rda_uart_remove(struct platform_device *pdev)
static struct platform_driver rda_uart_platform_driver = {
.probe = rda_uart_probe,
- .remove_new = rda_uart_remove,
+ .remove = rda_uart_remove,
.driver = {
.name = "rda-uart",
.of_match_table = rda_uart_dt_matches,
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
index 79c794fa6545..3c34027687d2 100644
--- a/drivers/tty/serial/sa1100.c
+++ b/drivers/tty/serial/sa1100.c
@@ -880,7 +880,7 @@ static void sa1100_serial_remove(struct platform_device *pdev)
static struct platform_driver sa11x0_serial_driver = {
.probe = sa1100_serial_probe,
- .remove_new = sa1100_serial_remove,
+ .remove = sa1100_serial_remove,
.suspend = sa1100_serial_suspend,
.resume = sa1100_serial_resume,
.driver = {
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index 0d184ee2f9ce..210fff7164c1 100644
--- a/drivers/tty/serial/samsung_tty.c
+++ b/drivers/tty/serial/samsung_tty.c
@@ -2498,6 +2498,12 @@ static const struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
.fifosize = { 256, 64, 64, 64 },
};
+static const struct s3c24xx_serial_drv_data exynos8895_serial_drv_data = {
+ EXYNOS_COMMON_SERIAL_DRV_DATA,
+ /* samsung,uart-fifosize must be specified in the device tree. */
+ .fifosize = { 0 },
+};
+
static const struct s3c24xx_serial_drv_data gs101_serial_drv_data = {
.info = {
.name = "Google GS101 UART",
@@ -2528,12 +2534,14 @@ static const struct s3c24xx_serial_drv_data gs101_serial_drv_data = {
#define EXYNOS4210_SERIAL_DRV_DATA (&exynos4210_serial_drv_data)
#define EXYNOS5433_SERIAL_DRV_DATA (&exynos5433_serial_drv_data)
#define EXYNOS850_SERIAL_DRV_DATA (&exynos850_serial_drv_data)
+#define EXYNOS8895_SERIAL_DRV_DATA (&exynos8895_serial_drv_data)
#define GS101_SERIAL_DRV_DATA (&gs101_serial_drv_data)
#else
#define EXYNOS4210_SERIAL_DRV_DATA NULL
#define EXYNOS5433_SERIAL_DRV_DATA NULL
#define EXYNOS850_SERIAL_DRV_DATA NULL
+#define EXYNOS8895_SERIAL_DRV_DATA NULL
#define GS101_SERIAL_DRV_DATA NULL
#endif
@@ -2623,6 +2631,9 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
}, {
.name = "gs101-uart",
.driver_data = (kernel_ulong_t)GS101_SERIAL_DRV_DATA,
+ }, {
+ .name = "exynos8895-uart",
+ .driver_data = (kernel_ulong_t)EXYNOS8895_SERIAL_DRV_DATA,
},
{ },
};
@@ -2646,6 +2657,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[] = {
.data = ARTPEC8_SERIAL_DRV_DATA },
{ .compatible = "google,gs101-uart",
.data = GS101_SERIAL_DRV_DATA },
+ { .compatible = "samsung,exynos8895-uart",
+ .data = EXYNOS8895_SERIAL_DRV_DATA },
{},
};
MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
@@ -2653,7 +2666,7 @@ MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
static struct platform_driver samsung_serial_driver = {
.probe = s3c24xx_serial_probe,
- .remove_new = s3c24xx_serial_remove,
+ .remove = s3c24xx_serial_remove,
.id_table = s3c24xx_serial_driver_ids,
.driver = {
.name = "samsung-uart",
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index ad88a33a504f..9d0c971e49f5 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1473,7 +1473,7 @@ static int sc16is7xx_setup_mctrl_ports(struct sc16is7xx_port *s,
}
static const struct serial_rs485 sc16is7xx_rs485_supported = {
- .flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND,
+ .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND,
.delay_rts_before_send = 1,
.delay_rts_after_send = 1, /* Not supported but keep returning -EINVAL */
};
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
index 6d1d142fd216..4c851dae6624 100644
--- a/drivers/tty/serial/sccnxp.c
+++ b/drivers/tty/serial/sccnxp.c
@@ -1052,7 +1052,7 @@ static struct platform_driver sccnxp_uart_driver = {
.name = SCCNXP_NAME,
},
.probe = sccnxp_probe,
- .remove_new = sccnxp_remove,
+ .remove = sccnxp_remove,
.id_table = sccnxp_id_table,
};
module_platform_driver(sccnxp_uart_driver);
diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c
index 1183ca54ab92..8004fc00fb9c 100644
--- a/drivers/tty/serial/serial-tegra.c
+++ b/drivers/tty/serial/serial-tegra.c
@@ -1648,7 +1648,7 @@ static const struct dev_pm_ops tegra_uart_pm_ops = {
static struct platform_driver tegra_uart_platform_driver = {
.probe = tegra_uart_probe,
- .remove_new = tegra_uart_remove,
+ .remove = tegra_uart_remove,
.driver = {
.name = "serial-tegra",
.of_match_table = tegra_uart_of_match,
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index abba39722958..436a559234df 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -1097,7 +1097,7 @@ static int serial_txx9_resume(struct platform_device *dev)
static struct platform_driver serial_txx9_plat_driver = {
.probe = serial_txx9_probe,
- .remove_new = serial_txx9_remove,
+ .remove = serial_txx9_remove,
#ifdef CONFIG_PM
.suspend = serial_txx9_suspend,
.resume = serial_txx9_resume,
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index b80e9a528e17..df523c744423 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -3505,7 +3505,7 @@ static SIMPLE_DEV_PM_OPS(sci_dev_pm_ops, sci_suspend, sci_resume);
static struct platform_driver sci_driver = {
.probe = sci_probe,
- .remove_new = sci_remove,
+ .remove = sci_remove,
.driver = {
.name = "sh-sci",
.pm = &sci_dev_pm_ops,
diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c
index cbfce65c9d22..5904a2d4cefa 100644
--- a/drivers/tty/serial/sifive.c
+++ b/drivers/tty/serial/sifive.c
@@ -1040,7 +1040,7 @@ MODULE_DEVICE_TABLE(of, sifive_serial_of_match);
static struct platform_driver sifive_serial_platform_driver = {
.probe = sifive_serial_probe,
- .remove_new = sifive_serial_remove,
+ .remove = sifive_serial_remove,
.driver = {
.name = SIFIVE_SERIAL_NAME,
.pm = pm_sleep_ptr(&sifive_uart_pm_ops),
diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
index 3fc54cc02a1f..8c9366321f8e 100644
--- a/drivers/tty/serial/sprd_serial.c
+++ b/drivers/tty/serial/sprd_serial.c
@@ -53,10 +53,12 @@
#define SPRD_IEN_TX_EMPTY BIT(1)
#define SPRD_IEN_BREAK_DETECT BIT(7)
#define SPRD_IEN_TIMEOUT BIT(13)
+#define SPRD_IEN_DATA_TIMEOUT BIT(17)
/* interrupt clear register */
#define SPRD_ICLR 0x0014
#define SPRD_ICLR_TIMEOUT BIT(13)
+#define SPRD_ICLR_DATA_TIMEOUT BIT(17)
/* line control register */
#define SPRD_LCR 0x0018
@@ -102,6 +104,7 @@
#define SPRD_IMSR_TX_FIFO_EMPTY BIT(1)
#define SPRD_IMSR_BREAK_DETECT BIT(7)
#define SPRD_IMSR_TIMEOUT BIT(13)
+#define SPRD_IMSR_DATA_TIMEOUT BIT(17)
#define SPRD_DEFAULT_SOURCE_CLK 26000000
#define SPRD_RX_DMA_STEP 1
@@ -118,6 +121,12 @@ struct sprd_uart_dma {
bool enable;
};
+struct sprd_uart_data {
+ unsigned int timeout_ien;
+ unsigned int timeout_iclr;
+ unsigned int timeout_imsr;
+};
+
struct sprd_uart_port {
struct uart_port port;
char name[16];
@@ -126,6 +135,7 @@ struct sprd_uart_port {
struct sprd_uart_dma rx_dma;
dma_addr_t pos;
unsigned char *rx_buf_tail;
+ const struct sprd_uart_data *pdata;
};
static struct sprd_uart_port *sprd_port[UART_NR_MAX];
@@ -134,6 +144,18 @@ static int sprd_ports_num;
static int sprd_start_dma_rx(struct uart_port *port);
static int sprd_tx_dma_config(struct uart_port *port);
+static const struct sprd_uart_data sc9836_data = {
+ .timeout_ien = SPRD_IEN_TIMEOUT,
+ .timeout_iclr = SPRD_ICLR_TIMEOUT,
+ .timeout_imsr = SPRD_IMSR_TIMEOUT,
+};
+
+static const struct sprd_uart_data sc9632_data = {
+ .timeout_ien = SPRD_IEN_DATA_TIMEOUT,
+ .timeout_iclr = SPRD_ICLR_DATA_TIMEOUT,
+ .timeout_imsr = SPRD_IMSR_DATA_TIMEOUT,
+};
+
static inline unsigned int serial_in(struct uart_port *port,
unsigned int offset)
{
@@ -637,6 +659,8 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
unsigned int ims;
+ struct sprd_uart_port *sp =
+ container_of(port, struct sprd_uart_port, port);
uart_port_lock(port);
@@ -647,14 +671,14 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
return IRQ_NONE;
}
- if (ims & SPRD_IMSR_TIMEOUT)
- serial_out(port, SPRD_ICLR, SPRD_ICLR_TIMEOUT);
+ if (ims & sp->pdata->timeout_imsr)
+ serial_out(port, SPRD_ICLR, sp->pdata->timeout_iclr);
if (ims & SPRD_IMSR_BREAK_DETECT)
serial_out(port, SPRD_ICLR, SPRD_IMSR_BREAK_DETECT);
if (ims & (SPRD_IMSR_RX_FIFO_FULL | SPRD_IMSR_BREAK_DETECT |
- SPRD_IMSR_TIMEOUT))
+ sp->pdata->timeout_imsr))
sprd_rx(port);
if (ims & SPRD_IMSR_TX_FIFO_EMPTY)
@@ -729,7 +753,7 @@ static int sprd_startup(struct uart_port *port)
/* enable interrupt */
uart_port_lock_irqsave(port, &flags);
ien = serial_in(port, SPRD_IEN);
- ien |= SPRD_IEN_BREAK_DETECT | SPRD_IEN_TIMEOUT;
+ ien |= SPRD_IEN_BREAK_DETECT | sp->pdata->timeout_ien;
if (!sp->rx_dma.enable)
ien |= SPRD_IEN_RX_FULL;
serial_out(port, SPRD_IEN, ien);
@@ -1184,6 +1208,12 @@ static int sprd_probe(struct platform_device *pdev)
up->mapbase = res->start;
+ sport->pdata = of_device_get_match_data(&pdev->dev);
+ if (!sport->pdata) {
+ dev_err(&pdev->dev, "get match data failed!\n");
+ return -EINVAL;
+ }
+
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
@@ -1248,14 +1278,15 @@ static int sprd_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(sprd_pm_ops, sprd_suspend, sprd_resume);
static const struct of_device_id serial_ids[] = {
- {.compatible = "sprd,sc9836-uart",},
+ {.compatible = "sprd,sc9836-uart", .data = &sc9836_data},
+ {.compatible = "sprd,sc9632-uart", .data = &sc9632_data},
{}
};
MODULE_DEVICE_TABLE(of, serial_ids);
static struct platform_driver sprd_platform_driver = {
.probe = sprd_probe,
- .remove_new = sprd_remove,
+ .remove = sprd_remove,
.driver = {
.name = "sprd_serial",
.of_match_table = serial_ids,
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
index 8aea59f8ca13..6ed9a327702b 100644
--- a/drivers/tty/serial/st-asc.c
+++ b/drivers/tty/serial/st-asc.c
@@ -934,7 +934,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(asc_serial_pm_ops, asc_serial_suspend,
static struct platform_driver asc_serial_driver = {
.probe = asc_serial_probe,
- .remove_new = asc_serial_remove,
+ .remove = asc_serial_remove,
.driver = {
.name = DRIVER_NAME,
.pm = pm_sleep_ptr(&asc_serial_pm_ops),
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index e1e7bc04c579..7dc254546075 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -2188,7 +2188,7 @@ static const struct dev_pm_ops stm32_serial_pm_ops = {
static struct platform_driver stm32_serial_driver = {
.probe = stm32_usart_serial_probe,
- .remove_new = stm32_usart_serial_remove,
+ .remove = stm32_usart_serial_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &stm32_serial_pm_ops,
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
index 7f60679fdde1..2b3ec65d595d 100644
--- a/drivers/tty/serial/sunhv.c
+++ b/drivers/tty/serial/sunhv.c
@@ -633,7 +633,7 @@ static struct platform_driver hv_driver = {
.of_match_table = hv_match,
},
.probe = hv_probe,
- .remove_new = hv_remove,
+ .remove = hv_remove,
};
static int __init sunhv_init(void)
diff --git a/drivers/tty/serial/sunplus-uart.c b/drivers/tty/serial/sunplus-uart.c
index abf7c449308d..38deee571b0d 100644
--- a/drivers/tty/serial/sunplus-uart.c
+++ b/drivers/tty/serial/sunplus-uart.c
@@ -697,7 +697,7 @@ MODULE_DEVICE_TABLE(of, sp_uart_of_match);
static struct platform_driver sunplus_uart_platform_driver = {
.probe = sunplus_uart_probe,
- .remove_new = sunplus_uart_remove,
+ .remove = sunplus_uart_remove,
.driver = {
.name = "sunplus_uart",
.of_match_table = sp_uart_of_match,
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
index 1acbe2fba746..df906ccf2e8a 100644
--- a/drivers/tty/serial/sunsab.c
+++ b/drivers/tty/serial/sunsab.c
@@ -1100,7 +1100,7 @@ static struct platform_driver sab_driver = {
.of_match_table = sab_match,
},
.probe = sab_probe,
- .remove_new = sab_remove,
+ .remove = sab_remove,
};
static int __init sunsab_init(void)
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 0f463da5e7ce..7f0fef07e141 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -1549,7 +1549,7 @@ static struct platform_driver su_driver = {
.of_match_table = su_match,
},
.probe = su_probe,
- .remove_new = su_remove,
+ .remove = su_remove,
};
static int __init sunsu_init(void)
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
index 71758ad4241c..0551c24c06f5 100644
--- a/drivers/tty/serial/sunzilog.c
+++ b/drivers/tty/serial/sunzilog.c
@@ -1538,7 +1538,7 @@ static struct platform_driver zs_driver = {
.of_match_table = zs_match,
},
.probe = zs_probe,
- .remove_new = zs_remove,
+ .remove = zs_remove,
};
static int __init sunzilog_init(void)
diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c
index 21ca5fcadf49..7033dbfe8ba1 100644
--- a/drivers/tty/serial/tegra-tcu.c
+++ b/drivers/tty/serial/tegra-tcu.c
@@ -293,7 +293,7 @@ static struct platform_driver tegra_tcu_driver = {
.of_match_table = tegra_tcu_match,
},
.probe = tegra_tcu_probe,
- .remove_new = tegra_tcu_remove,
+ .remove = tegra_tcu_remove,
};
module_platform_driver(tegra_tcu_driver);
diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c
index 43fa0938b5e3..6fa93c3872a7 100644
--- a/drivers/tty/serial/timbuart.c
+++ b/drivers/tty/serial/timbuart.c
@@ -485,7 +485,7 @@ static struct platform_driver timbuart_platform_driver = {
.name = "timb-uart",
},
.probe = timbuart_probe,
- .remove_new = timbuart_remove,
+ .remove = timbuart_remove,
};
module_platform_driver(timbuart_platform_driver);
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 68357ac8ffe3..a41e7fc373b7 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -915,7 +915,7 @@ MODULE_ALIAS("platform:uartlite");
static struct platform_driver ulite_platform_driver = {
.probe = ulite_probe,
- .remove_new = ulite_remove,
+ .remove = ulite_remove,
.driver = {
.name = "uartlite",
.of_match_table = of_match_ptr(ulite_of_match),
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index 4eed909468ff..0613f8c11ab1 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -1484,7 +1484,7 @@ static struct platform_driver ucc_uart_of_driver = {
.of_match_table = ucc_uart_match,
},
.probe = ucc_uart_probe,
- .remove_new = ucc_uart_remove,
+ .remove = ucc_uart_remove,
};
static int __init ucc_uart_init(void)
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index 777392914819..beb151be4d32 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -1903,7 +1903,7 @@ static void cdns_uart_remove(struct platform_device *pdev)
static struct platform_driver cdns_uart_platform_driver = {
.probe = cdns_uart_probe,
- .remove_new = cdns_uart_remove,
+ .remove = cdns_uart_remove,
.driver = {
.name = CDNS_UART_NAME,
.of_match_table = cdns_uart_of_match,
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 9771072da177..dcb1769c3625 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3631,7 +3631,7 @@ static struct ctl_table tty_table[] = {
.data = &tty_ldisc_autoload,
.maxlen = sizeof(tty_ldisc_autoload),
.mode = 0644,
- .proc_handler = proc_dointvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c
index 13cc35ab5d29..c70dd81bfc61 100644
--- a/drivers/uio/uio_dmem_genirq.c
+++ b/drivers/uio/uio_dmem_genirq.c
@@ -210,8 +210,6 @@ static int uio_dmem_genirq_probe(struct platform_device *pdev)
}
if (uioinfo->irq) {
- struct irq_data *irq_data = irq_get_irq_data(uioinfo->irq);
-
/*
* If a level interrupt, dont do lazy disable. Otherwise the
* irq will fire again since clearing of the actual cause, on
@@ -219,8 +217,7 @@ static int uio_dmem_genirq_probe(struct platform_device *pdev)
* irqd_is_level_type() isn't used since isn't valid until
* irq is configured.
*/
- if (irq_data &&
- irqd_get_trigger_type(irq_data) & IRQ_TYPE_LEVEL_MASK) {
+ if (irq_get_trigger_type(uioinfo->irq) & IRQ_TYPE_LEVEL_MASK) {
dev_dbg(&pdev->dev, "disable lazy unmask\n");
irq_set_status_flags(uioinfo->irq, IRQ_DISABLE_UNLAZY);
}
diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
index 870409599411..3976360d0096 100644
--- a/drivers/uio/uio_hv_generic.c
+++ b/drivers/uio/uio_hv_generic.c
@@ -135,7 +135,7 @@ static void hv_uio_rescind(struct vmbus_channel *channel)
* The ring buffer is allocated as contiguous memory by vmbus_open
*/
static int hv_uio_ring_mmap(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct vmbus_channel *channel
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index 796f5be0a086..2ec7d25e8264 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -173,8 +173,6 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
}
if (uioinfo->irq) {
- struct irq_data *irq_data = irq_get_irq_data(uioinfo->irq);
-
/*
* If a level interrupt, dont do lazy disable. Otherwise the
* irq will fire again since clearing of the actual cause, on
@@ -182,8 +180,7 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
* irqd_is_level_type() isn't used since isn't valid until
* irq is configured.
*/
- if (irq_data &&
- irqd_get_trigger_type(irq_data) & IRQ_TYPE_LEVEL_MASK) {
+ if (irq_get_trigger_type(uioinfo->irq) & IRQ_TYPE_LEVEL_MASK) {
dev_dbg(&pdev->dev, "disable lazy unmask\n");
irq_set_status_flags(uioinfo->irq, IRQ_DISABLE_UNLAZY);
}
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index e8e43c38aa1b..cd0f7b4bd82a 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -808,7 +808,7 @@ static int check_dsp_e4(const u8 *dsp, int len)
if (l > len)
return 1;
- /* zero is zero regardless endianes */
+ /* zero is zero regardless endianness */
} while (blockidx->NotLastBlock);
}
@@ -1276,7 +1276,7 @@ static void uea_set_bulk_timeout(struct uea_softc *sc, u32 dsrate)
sc->stats.phy.dsrate == dsrate)
return;
- /* Original timming (1Mbit/s) from ADI (used in windows driver) */
+ /* Original timing (1Mbit/s) from ADI (used in windows driver) */
timeout = (dsrate <= 1024*1024) ? 0 : 1;
ret = uea_request(sc, UEA_SET_TIMEOUT, timeout, 0, NULL);
uea_info(INS_TO_USBDEV(sc), "setting new timeout %d%s\n",
@@ -1972,7 +1972,7 @@ static void uea_dispatch_cmv_e1(struct uea_softc *sc, struct intr_pkt *intr)
if (cmv->bDirection != E1_MODEMTOHOST)
goto bad1;
- /* FIXME : ADI930 reply wrong preambule (func = 2, sub = 2) to
+ /* FIXME : ADI930 reply wrong preamble (func = 2, sub = 2) to
* the first MEMACCESS cmv. Ignore it...
*/
if (cmv->bFunction != dsc->function) {
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 2da6615fbb6f..d1e622bb1406 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -1158,7 +1158,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
if (i >= num_rcv_urbs)
list_add_tail(&urb->urb_list, &channel->list);
- vdbg(&intf->dev, "%s: alloced buffer 0x%p buf size %u urb 0x%p",
+ vdbg(&intf->dev, "%s: allocated buffer 0x%p buf size %u urb 0x%p",
__func__, urb->transfer_buffer, urb->transfer_buffer_length, urb);
}
diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
index bb9d5d7ffefc..8f38e2c5369a 100644
--- a/drivers/usb/c67x00/c67x00-drv.c
+++ b/drivers/usb/c67x00/c67x00-drv.c
@@ -201,7 +201,7 @@ static void c67x00_drv_remove(struct platform_device *pdev)
static struct platform_driver c67x00_driver = {
.probe = c67x00_drv_probe,
- .remove_new = c67x00_drv_remove,
+ .remove = c67x00_drv_remove,
.driver = {
.name = "c67x00",
},
diff --git a/drivers/usb/cdns3/cdns3-imx.c b/drivers/usb/cdns3/cdns3-imx.c
index 281de47e2a3b..a2f041e1707c 100644
--- a/drivers/usb/cdns3/cdns3-imx.c
+++ b/drivers/usb/cdns3/cdns3-imx.c
@@ -422,7 +422,7 @@ MODULE_DEVICE_TABLE(of, cdns_imx_of_match);
static struct platform_driver cdns_imx_driver = {
.probe = cdns_imx_probe,
- .remove_new = cdns_imx_remove,
+ .remove = cdns_imx_remove,
.driver = {
.name = "cdns3-imx",
.of_match_table = cdns_imx_of_match,
diff --git a/drivers/usb/cdns3/cdns3-pci-wrap.c b/drivers/usb/cdns3/cdns3-pci-wrap.c
index 591d149de8f3..3b3b3dc75f35 100644
--- a/drivers/usb/cdns3/cdns3-pci-wrap.c
+++ b/drivers/usb/cdns3/cdns3-pci-wrap.c
@@ -37,8 +37,6 @@ struct cdns3_wrap {
#define PCI_DRIVER_NAME "cdns3-pci-usbss"
#define PLAT_DRIVER_NAME "cdns-usb3"
-#define PCI_DEVICE_ID_CDNS_USB3 0x0100
-
static struct pci_dev *cdns3_get_second_fun(struct pci_dev *pdev)
{
struct pci_dev *func;
@@ -189,7 +187,7 @@ static void cdns3_pci_remove(struct pci_dev *pdev)
}
static const struct pci_device_id cdns3_pci_ids[] = {
- { PCI_VDEVICE(CDNS, PCI_DEVICE_ID_CDNS_USB3) },
+ { PCI_VDEVICE(CDNS, PCI_DEVICE_ID_CDNS_USBSS) },
{ 0, }
};
diff --git a/drivers/usb/cdns3/cdns3-plat.c b/drivers/usb/cdns3/cdns3-plat.c
index 3ef8e3c872a3..59ec505e198a 100644
--- a/drivers/usb/cdns3/cdns3-plat.c
+++ b/drivers/usb/cdns3/cdns3-plat.c
@@ -327,7 +327,7 @@ MODULE_DEVICE_TABLE(of, of_cdns3_match);
static struct platform_driver cdns3_driver = {
.probe = cdns3_plat_probe,
- .remove_new = cdns3_plat_remove,
+ .remove = cdns3_plat_remove,
.driver = {
.name = "cdns-usb3",
.of_match_table = of_match_ptr(of_cdns3_match),
diff --git a/drivers/usb/cdns3/cdns3-starfive.c b/drivers/usb/cdns3/cdns3-starfive.c
index c04d196abd87..2ff7f2b48cc2 100644
--- a/drivers/usb/cdns3/cdns3-starfive.c
+++ b/drivers/usb/cdns3/cdns3-starfive.c
@@ -230,7 +230,7 @@ MODULE_DEVICE_TABLE(of, cdns_starfive_of_match);
static struct platform_driver cdns_starfive_driver = {
.probe = cdns_starfive_probe,
- .remove_new = cdns_starfive_remove,
+ .remove = cdns_starfive_remove,
.driver = {
.name = "cdns3-starfive",
.of_match_table = cdns_starfive_of_match,
diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c
index cfabc12ee0e3..040bb91e9c01 100644
--- a/drivers/usb/cdns3/cdns3-ti.c
+++ b/drivers/usb/cdns3/cdns3-ti.c
@@ -233,7 +233,7 @@ MODULE_DEVICE_TABLE(of, cdns_ti_of_match);
static struct platform_driver cdns_ti_driver = {
.probe = cdns_ti_probe,
- .remove_new = cdns_ti_remove,
+ .remove = cdns_ti_remove,
.driver = {
.name = "cdns3-ti",
.of_match_table = cdns_ti_of_match,
diff --git a/drivers/usb/cdns3/cdnsp-pci.c b/drivers/usb/cdns3/cdnsp-pci.c
index 2d05368a6745..a51144504ff3 100644
--- a/drivers/usb/cdns3/cdnsp-pci.c
+++ b/drivers/usb/cdns3/cdnsp-pci.c
@@ -28,12 +28,6 @@
#define PCI_DRIVER_NAME "cdns-pci-usbssp"
#define PLAT_DRIVER_NAME "cdns-usbssp"
-#define PCI_DEVICE_ID_CDNS_USB3 0x0100
-#define PCI_DEVICE_ID_CDNS_UDC 0x0200
-
-#define PCI_CLASS_SERIAL_USB_CDNS_USB3 (PCI_CLASS_SERIAL_USB << 8 | 0x80)
-#define PCI_CLASS_SERIAL_USB_CDNS_UDC PCI_CLASS_SERIAL_USB_DEVICE
-
static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev)
{
/*
@@ -41,10 +35,10 @@ static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev)
* Platform has two function. The fist keeps resources for
* Host/Device while the secon keeps resources for DRD/OTG.
*/
- if (pdev->device == PCI_DEVICE_ID_CDNS_UDC)
- return pci_get_device(pdev->vendor, PCI_DEVICE_ID_CDNS_USB3, NULL);
- if (pdev->device == PCI_DEVICE_ID_CDNS_USB3)
- return pci_get_device(pdev->vendor, PCI_DEVICE_ID_CDNS_UDC, NULL);
+ if (pdev->device == PCI_DEVICE_ID_CDNS_USBSSP)
+ return pci_get_device(pdev->vendor, PCI_DEVICE_ID_CDNS_USBSS, NULL);
+ if (pdev->device == PCI_DEVICE_ID_CDNS_USBSS)
+ return pci_get_device(pdev->vendor, PCI_DEVICE_ID_CDNS_USBSSP, NULL);
return NULL;
}
@@ -221,12 +215,12 @@ static const struct dev_pm_ops cdnsp_pci_pm_ops = {
};
static const struct pci_device_id cdnsp_pci_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_UDC),
- .class = PCI_CLASS_SERIAL_USB_CDNS_UDC },
- { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_UDC),
- .class = PCI_CLASS_SERIAL_USB_CDNS_USB3 },
- { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USB3),
- .class = PCI_CLASS_SERIAL_USB_CDNS_USB3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USBSSP),
+ .class = PCI_CLASS_SERIAL_USB_DEVICE },
+ { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USBSSP),
+ .class = PCI_CLASS_SERIAL_USB_CDNS },
+ { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USBSS),
+ .class = PCI_CLASS_SERIAL_USB_CDNS },
{ 0, }
};
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 2a38e1eb6546..97437de52ef6 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -25,6 +25,7 @@
#define TD_PAGE_COUNT 5
#define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */
#define ENDPT_MAX 32
+#define CI_MAX_REQ_SIZE (4 * CI_HDRC_PAGE_SIZE)
#define CI_MAX_BUF_SIZE (TD_PAGE_COUNT * CI_HDRC_PAGE_SIZE)
/******************************************************************************
@@ -260,6 +261,7 @@ struct ci_hdrc {
bool b_sess_valid_event;
bool imx28_write_fix;
bool has_portsc_pec_bug;
+ bool has_short_pkt_limit;
bool supports_runtime_pm;
bool in_lpm;
bool wakeup_int;
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index c64ab0e07ea0..f2801700be8e 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -342,6 +342,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
struct ci_hdrc_platform_data pdata = {
.name = dev_name(&pdev->dev),
.capoffset = DEF_CAPOFFSET,
+ .flags = CI_HDRC_HAS_SHORT_PKT_LIMIT,
.notify_event = ci_hdrc_imx_notify_event,
};
int ret;
@@ -675,7 +676,7 @@ static const struct dev_pm_ops ci_hdrc_imx_pm_ops = {
};
static struct platform_driver ci_hdrc_imx_driver = {
.probe = ci_hdrc_imx_probe,
- .remove_new = ci_hdrc_imx_remove,
+ .remove = ci_hdrc_imx_remove,
.shutdown = ci_hdrc_imx_shutdown,
.driver = {
.name = "imx_usb",
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index 1661639cd2eb..3ab3daa78e34 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -292,7 +292,7 @@ MODULE_DEVICE_TABLE(of, msm_ci_dt_match);
static struct platform_driver ci_hdrc_msm_driver = {
.probe = ci_hdrc_msm_probe,
- .remove_new = ci_hdrc_msm_remove,
+ .remove = ci_hdrc_msm_remove,
.driver = {
.name = "msm_hsusb",
.of_match_table = msm_ci_dt_match,
diff --git a/drivers/usb/chipidea/ci_hdrc_npcm.c b/drivers/usb/chipidea/ci_hdrc_npcm.c
index 3e5e05dbda89..e52a2b05cbe2 100644
--- a/drivers/usb/chipidea/ci_hdrc_npcm.c
+++ b/drivers/usb/chipidea/ci_hdrc_npcm.c
@@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(of, npcm_udc_dt_match);
static struct platform_driver npcm_udc_driver = {
.probe = npcm_udc_probe,
- .remove_new = npcm_udc_remove,
+ .remove = npcm_udc_remove,
.driver = {
.name = "npcm_udc",
.of_match_table = npcm_udc_dt_match,
diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c b/drivers/usb/chipidea/ci_hdrc_tegra.c
index 9538d425f0a0..372788f0f970 100644
--- a/drivers/usb/chipidea/ci_hdrc_tegra.c
+++ b/drivers/usb/chipidea/ci_hdrc_tegra.c
@@ -406,7 +406,7 @@ static struct platform_driver tegra_usb_driver = {
.pm = pm_ptr(&tegra_usb_pm),
},
.probe = tegra_usb_probe,
- .remove_new = tegra_usb_remove,
+ .remove = tegra_usb_remove,
};
module_platform_driver(tegra_usb_driver);
diff --git a/drivers/usb/chipidea/ci_hdrc_usb2.c b/drivers/usb/chipidea/ci_hdrc_usb2.c
index 97379f653b06..8ffa1e95d8e8 100644
--- a/drivers/usb/chipidea/ci_hdrc_usb2.c
+++ b/drivers/usb/chipidea/ci_hdrc_usb2.c
@@ -116,7 +116,7 @@ static void ci_hdrc_usb2_remove(struct platform_device *pdev)
static struct platform_driver ci_hdrc_usb2_driver = {
.probe = ci_hdrc_usb2_probe,
- .remove_new = ci_hdrc_usb2_remove,
+ .remove = ci_hdrc_usb2_remove,
.driver = {
.name = "chipidea-usb2",
.of_match_table = ci_hdrc_usb2_of_match,
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 835bf2428dc6..694b4a8e4e1d 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -765,7 +765,7 @@ static int ci_get_platdata(struct device *dev,
ext_id = ERR_PTR(-ENODEV);
ext_vbus = ERR_PTR(-ENODEV);
- if (of_property_read_bool(dev->of_node, "extcon")) {
+ if (of_property_present(dev->of_node, "extcon")) {
/* Each one of them is not mandatory */
ext_vbus = extcon_get_edev_by_phandle(dev, 0);
if (IS_ERR(ext_vbus) && PTR_ERR(ext_vbus) != -ENODEV)
@@ -1076,6 +1076,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
CI_HDRC_SUPPORTS_RUNTIME_PM);
ci->has_portsc_pec_bug = !!(ci->platdata->flags &
CI_HDRC_HAS_PORTSC_PEC_MISSED);
+ ci->has_short_pkt_limit = !!(ci->platdata->flags &
+ CI_HDRC_HAS_SHORT_PKT_LIMIT);
platform_set_drvdata(pdev, ci);
ret = hw_device_init(ci, base);
@@ -1495,7 +1497,7 @@ static const struct dev_pm_ops ci_pm_ops = {
static struct platform_driver ci_hdrc_driver = {
.probe = ci_hdrc_probe,
- .remove_new = ci_hdrc_remove,
+ .remove = ci_hdrc_remove,
.driver = {
.name = "ci_hdrc",
.pm = &ci_pm_ops,
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 69ef3cd8d4f8..8a9b31fd5c89 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -10,6 +10,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dmapool.h>
+#include <linux/dma-direct.h>
#include <linux/err.h>
#include <linux/irqreturn.h>
#include <linux/kernel.h>
@@ -540,6 +541,126 @@ static int prepare_td_for_sg(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
return ret;
}
+/*
+ * Verify if the scatterlist is valid by iterating each sg entry.
+ * Return invalid sg entry index which is less than num_sgs.
+ */
+static int sglist_get_invalid_entry(struct device *dma_dev, u8 dir,
+ struct usb_request *req)
+{
+ int i;
+ struct scatterlist *s = req->sg;
+
+ if (req->num_sgs == 1)
+ return 1;
+
+ dir = dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+ for (i = 0; i < req->num_sgs; i++, s = sg_next(s)) {
+ /* Only small sg (generally last sg) may be bounced. If
+ * that happens. we can't ensure the addr is page-aligned
+ * after dma map.
+ */
+ if (dma_kmalloc_needs_bounce(dma_dev, s->length, dir))
+ break;
+
+ /* Make sure each sg start address (except first sg) is
+ * page-aligned and end address (except last sg) is also
+ * page-aligned.
+ */
+ if (i == 0) {
+ if (!IS_ALIGNED(s->offset + s->length,
+ CI_HDRC_PAGE_SIZE))
+ break;
+ } else {
+ if (s->offset)
+ break;
+ if (!sg_is_last(s) && !IS_ALIGNED(s->length,
+ CI_HDRC_PAGE_SIZE))
+ break;
+ }
+ }
+
+ return i;
+}
+
+static int sglist_do_bounce(struct ci_hw_req *hwreq, int index,
+ bool copy, unsigned int *bounced)
+{
+ void *buf;
+ int i, ret, nents, num_sgs;
+ unsigned int rest, rounded;
+ struct scatterlist *sg, *src, *dst;
+
+ nents = index + 1;
+ ret = sg_alloc_table(&hwreq->sgt, nents, GFP_KERNEL);
+ if (ret)
+ return ret;
+
+ sg = src = hwreq->req.sg;
+ num_sgs = hwreq->req.num_sgs;
+ rest = hwreq->req.length;
+ dst = hwreq->sgt.sgl;
+
+ for (i = 0; i < index; i++) {
+ memcpy(dst, src, sizeof(*src));
+ rest -= src->length;
+ src = sg_next(src);
+ dst = sg_next(dst);
+ }
+
+ /* create one bounce buffer */
+ rounded = round_up(rest, CI_HDRC_PAGE_SIZE);
+ buf = kmalloc(rounded, GFP_KERNEL);
+ if (!buf) {
+ sg_free_table(&hwreq->sgt);
+ return -ENOMEM;
+ }
+
+ sg_set_buf(dst, buf, rounded);
+
+ hwreq->req.sg = hwreq->sgt.sgl;
+ hwreq->req.num_sgs = nents;
+ hwreq->sgt.sgl = sg;
+ hwreq->sgt.nents = num_sgs;
+
+ if (copy)
+ sg_copy_to_buffer(src, num_sgs - index, buf, rest);
+
+ *bounced = rest;
+
+ return 0;
+}
+
+static void sglist_do_debounce(struct ci_hw_req *hwreq, bool copy)
+{
+ void *buf;
+ int i, nents, num_sgs;
+ struct scatterlist *sg, *src, *dst;
+
+ sg = hwreq->req.sg;
+ num_sgs = hwreq->req.num_sgs;
+ src = sg_last(sg, num_sgs);
+ buf = sg_virt(src);
+
+ if (copy) {
+ dst = hwreq->sgt.sgl;
+ for (i = 0; i < num_sgs - 1; i++)
+ dst = sg_next(dst);
+
+ nents = hwreq->sgt.nents - num_sgs + 1;
+ sg_copy_from_buffer(dst, nents, buf, sg_dma_len(src));
+ }
+
+ hwreq->req.sg = hwreq->sgt.sgl;
+ hwreq->req.num_sgs = hwreq->sgt.nents;
+ hwreq->sgt.sgl = sg;
+ hwreq->sgt.nents = num_sgs;
+
+ kfree(buf);
+ sg_free_table(&hwreq->sgt);
+}
+
/**
* _hardware_enqueue: configures a request at hardware level
* @hwep: endpoint
@@ -552,6 +673,8 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
struct ci_hdrc *ci = hwep->ci;
int ret = 0;
struct td_node *firstnode, *lastnode;
+ unsigned int bounced_size;
+ struct scatterlist *sg;
/* don't queue twice */
if (hwreq->req.status == -EALREADY)
@@ -559,11 +682,29 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
hwreq->req.status = -EALREADY;
+ if (hwreq->req.num_sgs && hwreq->req.length &&
+ ci->has_short_pkt_limit) {
+ ret = sglist_get_invalid_entry(ci->dev->parent, hwep->dir,
+ &hwreq->req);
+ if (ret < hwreq->req.num_sgs) {
+ ret = sglist_do_bounce(hwreq, ret, hwep->dir == TX,
+ &bounced_size);
+ if (ret)
+ return ret;
+ }
+ }
+
ret = usb_gadget_map_request_by_dev(ci->dev->parent,
&hwreq->req, hwep->dir);
if (ret)
return ret;
+ if (hwreq->sgt.sgl) {
+ /* We've mapped a bigger buffer, now recover the actual size */
+ sg = sg_last(hwreq->req.sg, hwreq->req.num_sgs);
+ sg_dma_len(sg) = min(sg_dma_len(sg), bounced_size);
+ }
+
if (hwreq->req.num_mapped_sgs)
ret = prepare_td_for_sg(hwep, hwreq);
else
@@ -612,10 +753,17 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
do {
hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n));
- } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW));
+ } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW) && tmp_stat);
hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0);
if (tmp_stat)
goto done;
+
+ /* OP_ENDPTSTAT will be clear by HW when the endpoint met
+ * err. This dTD don't push to dQH if current dTD point is
+ * not the last one in previous request.
+ */
+ if (hwep->qh.ptr->curr != cpu_to_le32(prevlastnode->dma))
+ goto done;
}
/* QH configuration */
@@ -676,6 +824,7 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
unsigned remaining_length;
unsigned actual = hwreq->req.length;
struct ci_hdrc *ci = hwep->ci;
+ bool is_isoc = hwep->type == USB_ENDPOINT_XFER_ISOC;
if (hwreq->req.status != -EALREADY)
return -EINVAL;
@@ -689,7 +838,7 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
int n = hw_ep_bit(hwep->num, hwep->dir);
if (ci->rev == CI_REVISION_24 ||
- ci->rev == CI_REVISION_22)
+ ci->rev == CI_REVISION_22 || is_isoc)
if (!hw_read(ci, OP_ENDPTSTAT, BIT(n)))
reprime_dtd(ci, hwep, node);
hwreq->req.status = -EALREADY;
@@ -708,11 +857,15 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
hwreq->req.status = -EPROTO;
break;
} else if ((TD_STATUS_TR_ERR & hwreq->req.status)) {
- hwreq->req.status = -EILSEQ;
- break;
+ if (is_isoc) {
+ hwreq->req.status = 0;
+ } else {
+ hwreq->req.status = -EILSEQ;
+ break;
+ }
}
- if (remaining_length) {
+ if (remaining_length && !is_isoc) {
if (hwep->dir == TX) {
hwreq->req.status = -EPROTO;
break;
@@ -733,6 +886,10 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
usb_gadget_unmap_request_by_dev(hwep->ci->dev->parent,
&hwreq->req, hwep->dir);
+ /* sglist bounced */
+ if (hwreq->sgt.sgl)
+ sglist_do_debounce(hwreq, hwep->dir == RX);
+
hwreq->req.actual += actual;
if (hwreq->req.status)
@@ -960,6 +1117,12 @@ static int _ep_queue(struct usb_ep *ep, struct usb_request *req,
return -EMSGSIZE;
}
+ if (ci->has_short_pkt_limit &&
+ hwreq->req.length > CI_MAX_REQ_SIZE) {
+ dev_err(hwep->ci->dev, "request length too big (max 16KB)\n");
+ return -EMSGSIZE;
+ }
+
/* first nuke then test link, e.g. previous status has not sent */
if (!list_empty(&hwreq->queue)) {
dev_err(hwep->ci->dev, "request already in queue\n");
@@ -1574,6 +1737,9 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
usb_gadget_unmap_request(&hwep->ci->gadget, req, hwep->dir);
+ if (hwreq->sgt.sgl)
+ sglist_do_debounce(hwreq, false);
+
req->status = -ECONNRESET;
if (hwreq->req.complete != NULL) {
@@ -2063,7 +2229,7 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci)
}
}
- if (USBi_UI & intr)
+ if ((USBi_UI | USBi_UEI) & intr)
isr_tr_complete_handler(ci);
if ((USBi_SLI & intr) && !(ci->suspended)) {
diff --git a/drivers/usb/chipidea/udc.h b/drivers/usb/chipidea/udc.h
index 5193df1e18c7..c8a47389a46b 100644
--- a/drivers/usb/chipidea/udc.h
+++ b/drivers/usb/chipidea/udc.h
@@ -69,11 +69,13 @@ struct td_node {
* @req: request structure for gadget drivers
* @queue: link to QH list
* @tds: link to TD list
+ * @sgt: hold original sglist when bounce sglist
*/
struct ci_hw_req {
struct usb_request req;
struct list_head queue;
struct list_head tds;
+ struct sg_table sgt;
};
#ifdef CONFIG_USB_CHIPIDEA_UDC
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index 173c78afd502..1394881fde5f 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -1285,6 +1285,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
.compatible = "fsl,imx7ulp-usbmisc",
.data = &imx7ulp_usbmisc_ops,
},
+ {
+ .compatible = "fsl,imx8ulp-usbmisc",
+ .data = &imx7ulp_usbmisc_ops,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index b7bea1015d7c..871cf199b6bf 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -415,6 +415,9 @@ EXPORT_SYMBOL_GPL(usb_of_get_companion_dev);
struct dentry *usb_debug_root;
EXPORT_SYMBOL_GPL(usb_debug_root);
+DEFINE_MUTEX(usb_dynids_lock);
+EXPORT_SYMBOL_GPL(usb_dynids_lock);
+
static int __init usb_common_init(void)
{
usb_debug_root = debugfs_create_dir("usb", NULL);
diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c
index 501e8bc9738e..c84b4a700084 100644
--- a/drivers/usb/common/usb-conn-gpio.c
+++ b/drivers/usb/common/usb-conn-gpio.c
@@ -340,7 +340,7 @@ MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
static struct platform_driver usb_conn_driver = {
.probe = usb_conn_probe,
- .remove_new = usb_conn_remove,
+ .remove = usb_conn_remove,
.driver = {
.name = "usb-conn-gpio",
.pm = &usb_conn_pm_ops,
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 880d52c0949d..25a00f974934 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -924,7 +924,7 @@ int usb_get_configuration(struct usb_device *dev)
result = -EINVAL;
goto err;
}
- length = max((int) le16_to_cpu(desc->wTotalLength),
+ length = max_t(int, le16_to_cpu(desc->wTotalLength),
USB_DT_CONFIG_SIZE);
/* Now that we know the length, get the whole thing */
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 3beb6a862e80..f6ce6e26e0d4 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -238,6 +238,9 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
dma_addr_t dma_handle = DMA_MAPPING_ERROR;
int ret;
+ if (!(file->f_mode & FMODE_WRITE))
+ return -EPERM;
+
ret = usbfs_increase_memory_usage(size + sizeof(struct usb_memory));
if (ret)
goto error;
@@ -1295,7 +1298,7 @@ static int do_proc_bulk(struct usb_dev_state *ps,
return ret;
len1 = bulk->len;
- if (len1 < 0 || len1 >= (INT_MAX - sizeof(struct urb)))
+ if (len1 >= (INT_MAX - sizeof(struct urb)))
return -EINVAL;
if (bulk->ep & USB_DIR_IN)
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 0c3f12daac79..f203fdbfb6f6 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -95,9 +95,9 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
}
}
- spin_lock(&dynids->lock);
+ mutex_lock(&usb_dynids_lock);
list_add_tail(&dynid->node, &dynids->list);
- spin_unlock(&dynids->lock);
+ mutex_unlock(&usb_dynids_lock);
retval = driver_attach(driver);
@@ -116,6 +116,7 @@ ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf)
struct usb_dynid *dynid;
size_t count = 0;
+ guard(mutex)(&usb_dynids_lock);
list_for_each_entry(dynid, &dynids->list, node)
if (dynid->id.bInterfaceClass != 0)
count += scnprintf(&buf[count], PAGE_SIZE - count, "%04x %04x %02x\n",
@@ -160,7 +161,7 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf,
if (fields < 2)
return -EINVAL;
- spin_lock(&usb_driver->dynids.lock);
+ guard(mutex)(&usb_dynids_lock);
list_for_each_entry_safe(dynid, n, &usb_driver->dynids.list, node) {
struct usb_device_id *id = &dynid->id;
@@ -171,7 +172,6 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf,
break;
}
}
- spin_unlock(&usb_driver->dynids.lock);
return count;
}
@@ -220,27 +220,24 @@ static void usb_free_dynids(struct usb_driver *usb_drv)
{
struct usb_dynid *dynid, *n;
- spin_lock(&usb_drv->dynids.lock);
+ guard(mutex)(&usb_dynids_lock);
list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) {
list_del(&dynid->node);
kfree(dynid);
}
- spin_unlock(&usb_drv->dynids.lock);
}
static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
- struct usb_driver *drv)
+ const struct usb_driver *drv)
{
struct usb_dynid *dynid;
- spin_lock(&drv->dynids.lock);
+ guard(mutex)(&usb_dynids_lock);
list_for_each_entry(dynid, &drv->dynids.list, node) {
if (usb_match_one_id(intf, &dynid->id)) {
- spin_unlock(&drv->dynids.lock);
return &dynid->id;
}
}
- spin_unlock(&drv->dynids.lock);
return NULL;
}
@@ -853,7 +850,7 @@ const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
EXPORT_SYMBOL_GPL(usb_device_match_id);
bool usb_driver_applicable(struct usb_device *udev,
- struct usb_device_driver *udrv)
+ const struct usb_device_driver *udrv)
{
if (udrv->id_table && udrv->match)
return usb_device_match_id(udev, udrv->id_table) != NULL &&
@@ -873,7 +870,7 @@ static int usb_device_match(struct device *dev, const struct device_driver *drv)
/* devices and interfaces are handled separately */
if (is_usb_device(dev)) {
struct usb_device *udev;
- struct usb_device_driver *udrv;
+ const struct usb_device_driver *udrv;
/* interface drivers never match devices */
if (!is_usb_device_driver(drv))
@@ -893,7 +890,7 @@ static int usb_device_match(struct device *dev, const struct device_driver *drv)
} else if (is_usb_interface(dev)) {
struct usb_interface *intf;
- struct usb_driver *usb_drv;
+ const struct usb_driver *usb_drv;
const struct usb_device_id *id;
/* device drivers never match interfaces */
@@ -1076,7 +1073,6 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
new_driver->driver.owner = owner;
new_driver->driver.mod_name = mod_name;
new_driver->driver.dev_groups = new_driver->dev_groups;
- spin_lock_init(&new_driver->dynids.lock);
INIT_LIST_HEAD(&new_driver->dynids.list);
retval = driver_register(&new_driver->driver);
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 4b38b87a1343..e48399401608 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/usb.h>
#include "usb.h"
@@ -39,7 +40,7 @@ static ssize_t field##_show(struct device *dev, \
char *buf) \
{ \
struct ep_device *ep = to_ep_device(dev); \
- return sprintf(buf, format_string, ep->desc->field); \
+ return sysfs_emit(buf, format_string, ep->desc->field); \
} \
static DEVICE_ATTR_RO(field)
@@ -52,7 +53,7 @@ static ssize_t wMaxPacketSize_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ep_device *ep = to_ep_device(dev);
- return sprintf(buf, "%04x\n", usb_endpoint_maxp(ep->desc));
+ return sysfs_emit(buf, "%04x\n", usb_endpoint_maxp(ep->desc));
}
static DEVICE_ATTR_RO(wMaxPacketSize);
@@ -76,7 +77,7 @@ static ssize_t type_show(struct device *dev, struct device_attribute *attr,
type = "Interrupt";
break;
}
- return sprintf(buf, "%s\n", type);
+ return sysfs_emit(buf, "%s\n", type);
}
static DEVICE_ATTR_RO(type);
@@ -95,7 +96,7 @@ static ssize_t interval_show(struct device *dev, struct device_attribute *attr,
interval /= 1000;
}
- return sprintf(buf, "%d%cs\n", interval, unit);
+ return sysfs_emit(buf, "%d%cs\n", interval, unit);
}
static DEVICE_ATTR_RO(interval);
@@ -111,7 +112,7 @@ static ssize_t direction_show(struct device *dev, struct device_attribute *attr,
direction = "in";
else
direction = "out";
- return sprintf(buf, "%s\n", direction);
+ return sysfs_emit(buf, "%s\n", direction);
}
static DEVICE_ATTR_RO(direction);
diff --git a/drivers/usb/core/ledtrig-usbport.c b/drivers/usb/core/ledtrig-usbport.c
index 85c999f71ad7..5e3c515991f3 100644
--- a/drivers/usb/core/ledtrig-usbport.c
+++ b/drivers/usb/core/ledtrig-usbport.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/usb.h>
#include <linux/usb/of.h>
@@ -87,7 +88,7 @@ static ssize_t usbport_trig_port_show(struct device *dev,
struct usbport_trig_port,
attr);
- return sprintf(buf, "%d\n", port->observed) + 1;
+ return sysfs_emit(buf, "%d\n", port->observed) + 1;
}
static ssize_t usbport_trig_port_store(struct device *dev,
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index e7da2fca11a4..45d7af00f8d1 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -9,6 +9,7 @@
#include <linux/kstrtox.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/pm_qos.h>
#include <linux/component.h>
#include <linux/usb/of.h>
@@ -166,7 +167,7 @@ static ssize_t location_show(struct device *dev,
{
struct usb_port *port_dev = to_usb_port(dev);
- return sprintf(buf, "0x%08x\n", port_dev->location);
+ return sysfs_emit(buf, "0x%08x\n", port_dev->location);
}
static DEVICE_ATTR_RO(location);
@@ -191,7 +192,7 @@ static ssize_t connect_type_show(struct device *dev,
break;
}
- return sprintf(buf, "%s\n", result);
+ return sysfs_emit(buf, "%s\n", result);
}
static DEVICE_ATTR_RO(connect_type);
@@ -210,7 +211,7 @@ static ssize_t over_current_count_show(struct device *dev,
{
struct usb_port *port_dev = to_usb_port(dev);
- return sprintf(buf, "%u\n", port_dev->over_current_count);
+ return sysfs_emit(buf, "%u\n", port_dev->over_current_count);
}
static DEVICE_ATTR_RO(over_current_count);
@@ -219,7 +220,7 @@ static ssize_t quirks_show(struct device *dev,
{
struct usb_port *port_dev = to_usb_port(dev);
- return sprintf(buf, "%08x\n", port_dev->quirks);
+ return sysfs_emit(buf, "%08x\n", port_dev->quirks);
}
static ssize_t quirks_store(struct device *dev, struct device_attribute *attr,
@@ -254,7 +255,7 @@ static ssize_t usb3_lpm_permit_show(struct device *dev,
p = "0";
}
- return sprintf(buf, "%s\n", p);
+ return sysfs_emit(buf, "%s\n", p);
}
static ssize_t usb3_lpm_permit_store(struct device *dev,
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 61b6d978892c..b4cba23831ac 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -925,7 +925,7 @@ static struct bin_attribute *dev_bin_attrs[] = {
};
static umode_t dev_bin_attrs_are_visible(struct kobject *kobj,
- struct bin_attribute *a, int n)
+ const struct bin_attribute *a, int n)
{
struct device *dev = kobj_to_dev(kobj);
struct usb_device *udev = to_usb_device(dev);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index b8324ea05b20..a9b37aeb515b 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -75,7 +75,7 @@ extern int usb_match_device(struct usb_device *dev,
extern const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
const struct usb_device_id *id);
extern bool usb_driver_applicable(struct usb_device *udev,
- struct usb_device_driver *udrv);
+ const struct usb_device_driver *udrv);
extern void usb_forced_unbind_intf(struct usb_interface *intf);
extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev);
diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig
index c131719367ec..d7af55a8eced 100644
--- a/drivers/usb/dwc2/Kconfig
+++ b/drivers/usb/dwc2/Kconfig
@@ -21,7 +21,7 @@ config USB_DWC2
if USB_DWC2
choice
- bool "DWC2 Mode Selection"
+ prompt "DWC2 Mode Selection"
default USB_DWC2_DUAL_ROLE if (USB && USB_GADGET)
default USB_DWC2_HOST if (USB && !USB_GADGET)
default USB_DWC2_PERIPHERAL if (!USB && USB_GADGET)
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index c1b7209b9483..91c80a92d9b8 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -756,7 +756,7 @@ static struct platform_driver dwc2_platform_driver = {
.pm = &dwc2_dev_pm_ops,
},
.probe = dwc2_driver_probe,
- .remove_new = dwc2_driver_remove,
+ .remove = dwc2_driver_remove,
.shutdown = dwc2_driver_shutdown,
};
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 31078f3d41b8..310d182e10b5 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -23,7 +23,7 @@ config USB_DWC3_ULPI
controller.
choice
- bool "DWC3 Mode Selection"
+ prompt "DWC3 Mode Selection"
default USB_DWC3_DUAL_ROLE if (USB && USB_GADGET)
default USB_DWC3_HOST if (USB && !USB_GADGET)
default USB_DWC3_GADGET if (!USB && USB_GADGET)
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 98114c2827c0..f219c82e9619 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1409,7 +1409,7 @@ static int dwc3_core_init(struct dwc3 *dwc)
/*
* When configured in HOST mode, after issuing U3/L2 exit controller
- * fails to send proper CRC checksum in CRC5 feild. Because of this
+ * fails to send proper CRC checksum in CRC5 field. Because of this
* behaviour Transaction Error is generated, resulting in reset and
* re-enumeration of usb device attached. All the termsel, xcvrsel,
* opmode becomes 0 during end of resume. Enabling bit 10 of GUCTL1
@@ -1470,9 +1470,13 @@ static int dwc3_core_init(struct dwc3 *dwc)
if (hw_mode != DWC3_GHWPARAMS0_MODE_GADGET &&
(DWC3_IP_IS(DWC31)) &&
dwc->maximum_speed == USB_SPEED_SUPER) {
- reg = dwc3_readl(dwc->regs, DWC3_LLUCTL);
- reg |= DWC3_LLUCTL_FORCE_GEN1;
- dwc3_writel(dwc->regs, DWC3_LLUCTL, reg);
+ int i;
+
+ for (i = 0; i < dwc->num_usb3_ports; i++) {
+ reg = dwc3_readl(dwc->regs, DWC3_LLUCTL(i));
+ reg |= DWC3_LLUCTL_FORCE_GEN1;
+ dwc3_writel(dwc->regs, DWC3_LLUCTL(i), reg);
+ }
}
return 0;
@@ -1941,7 +1945,7 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
struct extcon_dev *edev = NULL;
const char *name;
- if (device_property_read_bool(dev, "extcon"))
+ if (device_property_present(dev, "extcon"))
return extcon_get_edev_by_phandle(dev, 0);
/*
@@ -2651,7 +2655,7 @@ MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match);
static struct platform_driver dwc3_driver = {
.probe = dwc3_probe,
- .remove_new = dwc3_remove,
+ .remove = dwc3_remove,
.driver = {
.name = "dwc3",
.of_match_table = of_match_ptr(of_dwc3_match),
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index eab81dfdcc35..ee73789326bc 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -81,7 +81,7 @@
#define DWC3_GSNPSREV_MASK 0xffff
#define DWC3_GSNPS_ID(p) (((p) & DWC3_GSNPSID_MASK) >> 16)
-/* DWC3 registers memory space boundries */
+/* DWC3 registers memory space boundaries */
#define DWC3_XHCI_REGS_START 0x0
#define DWC3_XHCI_REGS_END 0x7fff
#define DWC3_GLOBALS_REGS_START 0xc100
@@ -179,7 +179,7 @@
#define DWC3_OEVTEN 0xcc0C
#define DWC3_OSTS 0xcc10
-#define DWC3_LLUCTL 0xd024
+#define DWC3_LLUCTL(n) (0xd024 + ((n) * 0x80))
/* Bit fields */
@@ -915,6 +915,7 @@ struct dwc3_hwparams {
#define DWC3_MODE(n) ((n) & 0x7)
/* HWPARAMS1 */
+#define DWC3_SPRAM_TYPE(n) (((n) >> 23) & 1)
#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15)
/* HWPARAMS3 */
@@ -925,6 +926,9 @@ struct dwc3_hwparams {
#define DWC3_NUM_IN_EPS(p) (((p)->hwparams3 & \
(DWC3_NUM_IN_EPS_MASK)) >> 18)
+/* HWPARAMS6 */
+#define DWC3_RAM0_DEPTH(n) (((n) & (0xffff0000)) >> 16)
+
/* HWPARAMS7 */
#define DWC3_RAM1_DEPTH(n) ((n) & 0xffff)
@@ -937,18 +941,14 @@ struct dwc3_hwparams {
* @request: struct usb_request to be transferred
* @list: a list_head used for request queueing
* @dep: struct dwc3_ep owning this request
- * @sg: pointer to first incomplete sg
* @start_sg: pointer to the sg which should be queued next
* @num_pending_sgs: counter to pending sgs
- * @num_queued_sgs: counter to the number of sgs which already got queued
* @remaining: amount of data remaining
* @status: internal dwc3 request status tracking
* @epnum: endpoint number to which this request refers
* @trb: pointer to struct dwc3_trb
* @trb_dma: DMA address of @trb
* @num_trbs: number of TRBs used by this request
- * @needs_extra_trb: true when request needs one extra TRB (either due to ZLP
- * or unaligned OUT)
* @direction: IN or OUT direction flag
* @mapped: true when request has been dma-mapped
*/
@@ -960,7 +960,6 @@ struct dwc3_request {
struct scatterlist *start_sg;
unsigned int num_pending_sgs;
- unsigned int num_queued_sgs;
unsigned int remaining;
unsigned int status;
@@ -978,7 +977,6 @@ struct dwc3_request {
unsigned int num_trbs;
- unsigned int needs_extra_trb:1;
unsigned int direction:1;
unsigned int mapped:1;
};
diff --git a/drivers/usb/dwc3/dwc3-am62.c b/drivers/usb/dwc3/dwc3-am62.c
index fad151e78fd6..5e3d1741701f 100644
--- a/drivers/usb/dwc3/dwc3-am62.c
+++ b/drivers/usb/dwc3/dwc3-am62.c
@@ -377,7 +377,7 @@ MODULE_DEVICE_TABLE(of, dwc3_ti_of_match);
static struct platform_driver dwc3_ti_driver = {
.probe = dwc3_ti_probe,
- .remove_new = dwc3_ti_remove,
+ .remove = dwc3_ti_remove,
.driver = {
.name = "dwc3-am62",
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index 9a6e988d165a..f5d963fae9e0 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -243,7 +243,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(dwc3_exynos_dev_pm_ops,
static struct platform_driver dwc3_exynos_driver = {
.probe = dwc3_exynos_probe,
- .remove_new = dwc3_exynos_remove,
+ .remove = dwc3_exynos_remove,
.driver = {
.name = "exynos-dwc3",
.of_match_table = exynos_dwc3_match,
diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c
index 64c0cd1995aa..356812cbcd88 100644
--- a/drivers/usb/dwc3/dwc3-imx8mp.c
+++ b/drivers/usb/dwc3/dwc3-imx8mp.c
@@ -400,7 +400,7 @@ MODULE_DEVICE_TABLE(of, dwc3_imx8mp_of_match);
static struct platform_driver dwc3_imx8mp_driver = {
.probe = dwc3_imx8mp_probe,
- .remove_new = dwc3_imx8mp_remove,
+ .remove = dwc3_imx8mp_remove,
.driver = {
.name = "imx8mp-dwc3",
.pm = pm_ptr(&dwc3_imx8mp_dev_pm_ops),
diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c
index 8899348b6276..7ee1610162b9 100644
--- a/drivers/usb/dwc3/dwc3-keystone.c
+++ b/drivers/usb/dwc3/dwc3-keystone.c
@@ -208,7 +208,7 @@ MODULE_DEVICE_TABLE(of, kdwc3_of_match);
static struct platform_driver kdwc3_driver = {
.probe = kdwc3_probe,
- .remove_new = kdwc3_remove,
+ .remove = kdwc3_remove,
.driver = {
.name = "keystone-dwc3",
.of_match_table = kdwc3_of_match,
diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
index 2c07c038b584..7d80bf7b18b0 100644
--- a/drivers/usb/dwc3/dwc3-meson-g12a.c
+++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
@@ -968,7 +968,7 @@ MODULE_DEVICE_TABLE(of, dwc3_meson_g12a_match);
static struct platform_driver dwc3_meson_g12a_driver = {
.probe = dwc3_meson_g12a_probe,
- .remove_new = dwc3_meson_g12a_remove,
+ .remove = dwc3_meson_g12a_remove,
.driver = {
.name = "dwc3-meson-g12a",
.of_match_table = dwc3_meson_g12a_match,
diff --git a/drivers/usb/dwc3/dwc3-octeon.c b/drivers/usb/dwc3/dwc3-octeon.c
index 1a3b205367fd..42bfc14ae0c4 100644
--- a/drivers/usb/dwc3/dwc3-octeon.c
+++ b/drivers/usb/dwc3/dwc3-octeon.c
@@ -520,7 +520,7 @@ MODULE_DEVICE_TABLE(of, dwc3_octeon_of_match);
static struct platform_driver dwc3_octeon_driver = {
.probe = dwc3_octeon_probe,
- .remove_new = dwc3_octeon_remove,
+ .remove = dwc3_octeon_remove,
.driver = {
.name = "dwc3-octeon",
.of_match_table = dwc3_octeon_of_match,
diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c
index be7be00ecb34..a4954a21be93 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -180,7 +180,7 @@ MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
static struct platform_driver dwc3_of_simple_driver = {
.probe = dwc3_of_simple_probe,
- .remove_new = dwc3_of_simple_remove,
+ .remove = dwc3_of_simple_remove,
.shutdown = dwc3_of_simple_shutdown,
.driver = {
.name = "dwc3-of-simple",
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 2a11fc0ee84f..b261c46124c6 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -416,7 +416,7 @@ static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
struct device_node *node = omap->dev->of_node;
struct extcon_dev *edev;
- if (of_property_read_bool(node, "extcon")) {
+ if (of_property_present(node, "extcon")) {
edev = extcon_get_edev_by_phandle(omap->dev, 0);
if (IS_ERR(edev)) {
dev_vdbg(omap->dev, "couldn't get extcon device\n");
@@ -611,7 +611,7 @@ static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
static struct platform_driver dwc3_omap_driver = {
.probe = dwc3_omap_probe,
- .remove_new = dwc3_omap_remove,
+ .remove = dwc3_omap_remove,
.driver = {
.name = "omap-dwc3",
.of_match_table = of_dwc3_match,
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index c1d4b52f25b0..58683bb672e9 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -161,7 +161,7 @@ static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom)
struct extcon_dev *host_edev;
int ret;
- if (!of_property_read_bool(dev->of_node, "extcon"))
+ if (!of_property_present(dev->of_node, "extcon"))
return 0;
qcom->edev = extcon_get_edev_by_phandle(dev, 0);
@@ -921,7 +921,7 @@ MODULE_DEVICE_TABLE(of, dwc3_qcom_of_match);
static struct platform_driver dwc3_qcom_driver = {
.probe = dwc3_qcom_probe,
- .remove_new = dwc3_qcom_remove,
+ .remove = dwc3_qcom_remove,
.driver = {
.name = "dwc3-qcom",
.pm = &dwc3_qcom_dev_pm_ops,
diff --git a/drivers/usb/dwc3/dwc3-rtk.c b/drivers/usb/dwc3/dwc3-rtk.c
index e9c8b032c72c..56c53e0c0257 100644
--- a/drivers/usb/dwc3/dwc3-rtk.c
+++ b/drivers/usb/dwc3/dwc3-rtk.c
@@ -441,7 +441,7 @@ static const struct dev_pm_ops dwc3_rtk_dev_pm_ops = {
static struct platform_driver dwc3_rtk_driver = {
.probe = dwc3_rtk_probe,
- .remove_new = dwc3_rtk_remove,
+ .remove = dwc3_rtk_remove,
.driver = {
.name = "rtk-dwc3",
.of_match_table = rtk_dwc3_match,
diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c
index 2841021f3557..e16c3237180e 100644
--- a/drivers/usb/dwc3/dwc3-st.c
+++ b/drivers/usb/dwc3/dwc3-st.c
@@ -356,7 +356,7 @@ MODULE_DEVICE_TABLE(of, st_dwc3_match);
static struct platform_driver st_dwc3_driver = {
.probe = st_dwc3_probe,
- .remove_new = st_dwc3_remove,
+ .remove = st_dwc3_remove,
.driver = {
.name = "usb-st-dwc3",
.of_match_table = st_dwc3_match,
diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index b5e5be424ce9..e3738e1610db 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -420,7 +420,7 @@ static const struct dev_pm_ops dwc3_xlnx_dev_pm_ops = {
static struct platform_driver dwc3_xlnx_driver = {
.probe = dwc3_xlnx_probe,
- .remove_new = dwc3_xlnx_remove,
+ .remove = dwc3_xlnx_remove,
.driver = {
.name = "dwc3-xilinx",
.of_match_table = dwc3_xlnx_of_match,
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index c9533a99e47c..666ac432f52d 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -145,7 +145,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
* Unfortunately we have uncovered a limitation wrt the Data Phase.
*
* Section 9.4 says we can wait for the XferNotReady(DATA) event to
- * come before issueing Start Transfer command, but if we do, we will
+ * come before issuing Start Transfer command, but if we do, we will
* miss situations where the host starts another SETUP phase instead of
* the DATA phase. Such cases happen at least on TD.7.6 of the Link
* Layer Compliance Suite.
@@ -232,7 +232,7 @@ void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
/* stall is always issued on EP0 */
dep = dwc->eps[0];
__dwc3_gadget_ep_set_halt(dep, 1, false);
- dep->flags &= DWC3_EP_RESOURCE_ALLOCATED;
+ dep->flags &= DWC3_EP_RESOURCE_ALLOCATED | DWC3_EP_TRANSFER_STARTED;
dep->flags |= DWC3_EP_ENABLED;
dwc->delayed_status = false;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 4959c26d3b71..83dc7304d701 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -197,7 +197,6 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
list_del(&req->list);
req->remaining = 0;
- req->needs_extra_trb = false;
req->num_trbs = 0;
if (req->request.status == -EINPROGRESS)
@@ -688,6 +687,44 @@ static int dwc3_gadget_calc_tx_fifo_size(struct dwc3 *dwc, int mult)
}
/**
+ * dwc3_gadget_calc_ram_depth - calculates the ram depth for txfifo
+ * @dwc: pointer to the DWC3 context
+ */
+static int dwc3_gadget_calc_ram_depth(struct dwc3 *dwc)
+{
+ int ram_depth;
+ int fifo_0_start;
+ bool is_single_port_ram;
+
+ /* Check supporting RAM type by HW */
+ is_single_port_ram = DWC3_SPRAM_TYPE(dwc->hwparams.hwparams1);
+
+ /*
+ * If a single port RAM is utilized, then allocate TxFIFOs from
+ * RAM0. otherwise, allocate them from RAM1.
+ */
+ ram_depth = is_single_port_ram ? DWC3_RAM0_DEPTH(dwc->hwparams.hwparams6) :
+ DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
+
+ /*
+ * In a single port RAM configuration, the available RAM is shared
+ * between the RX and TX FIFOs. This means that the txfifo can begin
+ * at a non-zero address.
+ */
+ if (is_single_port_ram) {
+ u32 reg;
+
+ /* Check if TXFIFOs start at non-zero addr */
+ reg = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
+ fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(reg);
+
+ ram_depth -= (fifo_0_start >> 16);
+ }
+
+ return ram_depth;
+}
+
+/**
* dwc3_gadget_clear_tx_fifos - Clears txfifo allocation
* @dwc: pointer to the DWC3 context
*
@@ -753,7 +790,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
{
struct dwc3 *dwc = dep->dwc;
int fifo_0_start;
- int ram1_depth;
+ int ram_depth;
int fifo_size;
int min_depth;
int num_in_ep;
@@ -773,17 +810,32 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
if (dep->flags & DWC3_EP_TXFIFO_RESIZED)
return 0;
- ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
+ ram_depth = dwc3_gadget_calc_ram_depth(dwc);
- if ((dep->endpoint.maxburst > 1 &&
- usb_endpoint_xfer_bulk(dep->endpoint.desc)) ||
- usb_endpoint_xfer_isoc(dep->endpoint.desc))
- num_fifos = 3;
-
- if (dep->endpoint.maxburst > 6 &&
- (usb_endpoint_xfer_bulk(dep->endpoint.desc) ||
- usb_endpoint_xfer_isoc(dep->endpoint.desc)) && DWC3_IP_IS(DWC31))
- num_fifos = dwc->tx_fifo_resize_max_num;
+ switch (dwc->gadget->speed) {
+ case USB_SPEED_SUPER_PLUS:
+ case USB_SPEED_SUPER:
+ if (usb_endpoint_xfer_bulk(dep->endpoint.desc) ||
+ usb_endpoint_xfer_isoc(dep->endpoint.desc))
+ num_fifos = min_t(unsigned int,
+ dep->endpoint.maxburst,
+ dwc->tx_fifo_resize_max_num);
+ break;
+ case USB_SPEED_HIGH:
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+ num_fifos = min_t(unsigned int,
+ usb_endpoint_maxp_mult(dep->endpoint.desc) + 1,
+ dwc->tx_fifo_resize_max_num);
+ break;
+ }
+ fallthrough;
+ case USB_SPEED_FULL:
+ if (usb_endpoint_xfer_bulk(dep->endpoint.desc))
+ num_fifos = 2;
+ break;
+ default:
+ break;
+ }
/* FIFO size for a single buffer */
fifo = dwc3_gadget_calc_tx_fifo_size(dwc, 1);
@@ -794,7 +846,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
/* Reserve at least one FIFO for the number of IN EPs */
min_depth = num_in_ep * (fifo + 1);
- remaining = ram1_depth - min_depth - dwc->last_fifo_depth;
+ remaining = ram_depth - min_depth - dwc->last_fifo_depth;
remaining = max_t(int, 0, remaining);
/*
* We've already reserved 1 FIFO per EP, so check what we can fit in
@@ -820,9 +872,9 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
dwc->last_fifo_depth += DWC31_GTXFIFOSIZ_TXFDEP(fifo_size);
/* Check fifo size allocation doesn't exceed available RAM size. */
- if (dwc->last_fifo_depth >= ram1_depth) {
+ if (dwc->last_fifo_depth >= ram_depth) {
dev_err(dwc->dev, "Fifosize(%d) > RAM size(%d) %s depth:%d\n",
- dwc->last_fifo_depth, ram1_depth,
+ dwc->last_fifo_depth, ram_depth,
dep->endpoint.name, fifo_size);
if (DWC3_IP_IS(DWC3))
fifo_size = DWC3_GTXFIFOSIZ_TXFDEP(fifo_size);
@@ -1177,11 +1229,14 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
* pending to be processed by the driver.
*/
if (dep->trb_enqueue == dep->trb_dequeue) {
+ struct dwc3_request *req;
+
/*
- * If there is any request remained in the started_list at
- * this point, that means there is no TRB available.
+ * If there is any request remained in the started_list with
+ * active TRBs at this point, then there is no TRB available.
*/
- if (!list_empty(&dep->started_list))
+ req = next_request(&dep->started_list);
+ if (req && req->num_trbs)
return 0;
return DWC3_TRB_NUM - 1;
@@ -1384,6 +1439,7 @@ static int dwc3_prepare_last_sg(struct dwc3_ep *dep,
unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
unsigned int rem = req->request.length % maxp;
unsigned int num_trbs = 1;
+ bool needs_extra_trb;
if (dwc3_needs_extra_trb(dep, req))
num_trbs++;
@@ -1391,15 +1447,15 @@ static int dwc3_prepare_last_sg(struct dwc3_ep *dep,
if (dwc3_calc_trbs_left(dep) < num_trbs)
return 0;
- req->needs_extra_trb = num_trbs > 1;
+ needs_extra_trb = num_trbs > 1;
/* Prepare a normal TRB */
if (req->direction || req->request.length)
dwc3_prepare_one_trb(dep, req, entry_length,
- req->needs_extra_trb, node, false, false);
+ needs_extra_trb, node, false, false);
/* Prepare extra TRBs for ZLP and MPS OUT transfer alignment */
- if ((!req->direction && !req->request.length) || req->needs_extra_trb)
+ if ((!req->direction && !req->request.length) || needs_extra_trb)
dwc3_prepare_one_trb(dep, req,
req->direction ? 0 : maxp - rem,
false, 1, true, false);
@@ -1414,8 +1470,8 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
struct scatterlist *s;
int i;
unsigned int length = req->request.length;
- unsigned int remaining = req->request.num_mapped_sgs
- - req->num_queued_sgs;
+ unsigned int remaining = req->num_pending_sgs;
+ unsigned int num_queued_sgs = req->request.num_mapped_sgs - remaining;
unsigned int num_trbs = req->num_trbs;
bool needs_extra_trb = dwc3_needs_extra_trb(dep, req);
@@ -1423,7 +1479,7 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
* If we resume preparing the request, then get the remaining length of
* the request and resume where we left off.
*/
- for_each_sg(req->request.sg, s, req->num_queued_sgs, i)
+ for_each_sg(req->request.sg, s, num_queued_sgs, i)
length -= sg_dma_len(s);
for_each_sg(sg, s, remaining, i) {
@@ -1488,7 +1544,6 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
if (!last_sg)
req->start_sg = sg_next(s);
- req->num_queued_sgs++;
req->num_pending_sgs--;
/*
@@ -1569,9 +1624,7 @@ static int dwc3_prepare_trbs(struct dwc3_ep *dep)
if (ret)
return ret;
- req->sg = req->request.sg;
- req->start_sg = req->sg;
- req->num_queued_sgs = 0;
+ req->start_sg = req->request.sg;
req->num_pending_sgs = req->request.num_mapped_sgs;
if (req->num_pending_sgs > 0) {
@@ -3075,7 +3128,7 @@ static int dwc3_gadget_check_config(struct usb_gadget *g)
struct dwc3 *dwc = gadget_to_dwc(g);
struct usb_ep *ep;
int fifo_size = 0;
- int ram1_depth;
+ int ram_depth;
int ep_num = 0;
if (!dwc->do_fifo_resize)
@@ -3098,8 +3151,8 @@ static int dwc3_gadget_check_config(struct usb_gadget *g)
fifo_size += dwc->max_cfg_eps;
/* Check if we can fit a single fifo per endpoint */
- ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
- if (fifo_size > ram1_depth)
+ ram_depth = dwc3_gadget_calc_ram_depth(dwc);
+ if (fifo_size > ram_depth)
return -ENOMEM;
return 0;
@@ -3416,20 +3469,16 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep,
int status)
{
struct dwc3_trb *trb;
- struct scatterlist *sg = req->sg;
- struct scatterlist *s;
- unsigned int num_queued = req->num_queued_sgs;
+ unsigned int num_completed_trbs = req->num_trbs;
unsigned int i;
int ret = 0;
- for_each_sg(sg, s, num_queued, i) {
+ for (i = 0; i < num_completed_trbs; i++) {
trb = &dep->trb_pool[dep->trb_dequeue];
- req->sg = sg_next(s);
- req->num_queued_sgs--;
-
ret = dwc3_gadget_ep_reclaim_completed_trb(dep, req,
- trb, event, status, true);
+ trb, event, status,
+ !!(trb->ctrl & DWC3_TRB_CTRL_CHN));
if (ret)
break;
}
@@ -3437,19 +3486,9 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep,
return ret;
}
-static int dwc3_gadget_ep_reclaim_trb_linear(struct dwc3_ep *dep,
- struct dwc3_request *req, const struct dwc3_event_depevt *event,
- int status)
-{
- struct dwc3_trb *trb = &dep->trb_pool[dep->trb_dequeue];
-
- return dwc3_gadget_ep_reclaim_completed_trb(dep, req, trb,
- event, status, false);
-}
-
static bool dwc3_gadget_ep_request_completed(struct dwc3_request *req)
{
- return req->num_pending_sgs == 0 && req->num_queued_sgs == 0;
+ return req->num_pending_sgs == 0 && req->num_trbs == 0;
}
static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
@@ -3459,24 +3498,13 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
int request_status;
int ret;
- if (req->request.num_mapped_sgs)
- ret = dwc3_gadget_ep_reclaim_trb_sg(dep, req, event,
- status);
- else
- ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
- status);
+ ret = dwc3_gadget_ep_reclaim_trb_sg(dep, req, event, status);
req->request.actual = req->request.length - req->remaining;
if (!dwc3_gadget_ep_request_completed(req))
goto out;
- if (req->needs_extra_trb) {
- ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
- status);
- req->needs_extra_trb = false;
- }
-
/*
* The event status only reflects the status of the TRB with IOC set.
* For the requests that don't set interrupt on completion, the driver
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index e0533cee6870..b48e108fc8fe 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -35,7 +35,7 @@ static void dwc3_power_off_all_roothub_ports(struct dwc3 *dwc)
u32 reg;
int i;
- /* xhci regs is not mapped yet, do it temperary here */
+ /* xhci regs are not mapped yet, do it temporarily here */
if (dwc->xhci_resources[0].start) {
xhci_regs = ioremap(dwc->xhci_resources[0].start, DWC3_XHCI_REGS_END);
if (!xhci_regs) {
diff --git a/drivers/usb/fotg210/fotg210-core.c b/drivers/usb/fotg210/fotg210-core.c
index 0655afe7f977..49f25a70b32e 100644
--- a/drivers/usb/fotg210/fotg210-core.c
+++ b/drivers/usb/fotg210/fotg210-core.c
@@ -195,7 +195,7 @@ static struct platform_driver fotg210_driver = {
.of_match_table = of_match_ptr(fotg210_of_match),
},
.probe = fotg210_probe,
- .remove_new = fotg210_remove,
+ .remove = fotg210_remove,
};
static int __init fotg210_init(void)
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index f25dd2cb5d03..bdda8c74602d 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1844,7 +1844,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
cdev->desc.bcdUSB = cpu_to_le16(0x0200);
}
- value = min(w_length, (u16) sizeof cdev->desc);
+ value = min_t(u16, w_length, sizeof(cdev->desc));
memcpy(req->buf, &cdev->desc, value);
break;
case USB_DT_DEVICE_QUALIFIER:
@@ -1863,19 +1863,19 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_DT_CONFIG:
value = config_desc(cdev, w_value);
if (value >= 0)
- value = min(w_length, (u16) value);
+ value = min_t(u16, w_length, value);
break;
case USB_DT_STRING:
value = get_string(cdev, req->buf,
w_index, w_value & 0xff);
if (value >= 0)
- value = min(w_length, (u16) value);
+ value = min_t(u16, w_length, value);
break;
case USB_DT_BOS:
if (gadget_is_superspeed(gadget) ||
gadget->lpm_capable || cdev->use_webusb) {
value = bos_desc(cdev);
- value = min(w_length, (u16) value);
+ value = min_t(u16, w_length, value);
}
break;
case USB_DT_OTG:
@@ -1930,7 +1930,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
*(u8 *)req->buf = cdev->config->bConfigurationValue;
else
*(u8 *)req->buf = 0;
- value = min(w_length, (u16) 1);
+ value = min_t(u16, w_length, 1);
break;
/* function drivers must handle get/set altsetting */
@@ -1976,7 +1976,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (value < 0)
break;
*((u8 *)req->buf) = value;
- value = min(w_length, (u16) 1);
+ value = min_t(u16, w_length, 1);
break;
case USB_REQ_GET_STATUS:
if (gadget_is_otg(gadget) && gadget->hnp_polling_support &&
@@ -2111,8 +2111,20 @@ unknown:
memset(buf, 0, w_length);
buf[5] = 0x01;
switch (ctrl->bRequestType & USB_RECIP_MASK) {
+ /*
+ * The Microsoft CompatID OS Descriptor Spec(w_index = 0x4) and
+ * Extended Prop OS Desc Spec(w_index = 0x5) state that the
+ * HighByte of wValue is the InterfaceNumber and the LowByte is
+ * the PageNumber. This high/low byte ordering is incorrectly
+ * documented in the Spec. USB analyzer output on the below
+ * request packets show the high/low byte inverted i.e LowByte
+ * is the InterfaceNumber and the HighByte is the PageNumber.
+ * Since we dont support >64KB CompatID/ExtendedProp descriptors,
+ * PageNumber is set to 0. Hence verify that the HighByte is 0
+ * for below two cases.
+ */
case USB_RECIP_DEVICE:
- if (w_index != 0x4 || (w_value & 0xff))
+ if (w_index != 0x4 || (w_value >> 8))
break;
buf[6] = w_index;
/* Number of ext compat interfaces */
@@ -2128,9 +2140,9 @@ unknown:
}
break;
case USB_RECIP_INTERFACE:
- if (w_index != 0x5 || (w_value & 0xff))
+ if (w_index != 0x5 || (w_value >> 8))
break;
- interface = w_value >> 8;
+ interface = w_value & 0xFF;
if (interface >= MAX_CONFIG_INTERFACES ||
!os_desc_cfg->interface[interface])
break;
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index b1f625245713..95f144a54ed9 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -57,11 +57,11 @@ EXPORT_SYMBOL_GPL(usb_descriptor_fillbuf);
* usb_gadget_config_buf - builts a complete configuration descriptor
* @config: Header for the descriptor, including characteristics such
* as power requirements and number of interfaces.
- * @desc: Null-terminated vector of pointers to the descriptors (interface,
- * endpoint, etc) defining all functions in this device configuration.
* @buf: Buffer for the resulting configuration descriptor.
* @length: Length of buffer. If this is not big enough to hold the
* entire configuration descriptor, an error code will be returned.
+ * @desc: Null-terminated vector of pointers to the descriptors (interface,
+ * endpoint, etc) defining all functions in this device configuration.
*
* This copies descriptors into the response buffer, building a descriptor
* for that configuration. It returns the buffer length or a negative
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index c82a6a0fba93..6499a88d346c 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1184,7 +1184,7 @@ static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page,
struct gadget_info *gi = os_desc_item_to_gadget_info(item);
int res, l;
- l = min((int)len, OS_STRING_QW_SIGN_LEN >> 1);
+ l = min_t(int, len, OS_STRING_QW_SIGN_LEN >> 1);
if (page[l - 1] == '\n')
--l;
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
index 87917a7d4a9b..7ce1637276f0 100644
--- a/drivers/usb/gadget/function/Makefile
+++ b/drivers/usb/gadget/function/Makefile
@@ -41,6 +41,10 @@ obj-$(CONFIG_USB_F_UAC1_LEGACY) += usb_f_uac1_legacy.o
usb_f_uac2-y := f_uac2.o
obj-$(CONFIG_USB_F_UAC2) += usb_f_uac2.o
usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_configfs.o
+ifneq ($(CONFIG_TRACING),)
+ CFLAGS_uvc_trace.o := -I$(src)
+ usb_f_uvc-y += uvc_trace.o
+endif
obj-$(CONFIG_USB_F_UVC) += usb_f_uvc.o
usb_f_midi-y := f_midi.o
obj-$(CONFIG_USB_F_MIDI) += usb_f_midi.o
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 2920f8000bbd..2ccf7f4e4db1 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -456,7 +456,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
}
/* FFS_SETUP_PENDING and not stall */
- len = min(len, (size_t)le16_to_cpu(ffs->ev.setup.wLength));
+ len = min_t(size_t, len, le16_to_cpu(ffs->ev.setup.wLength));
spin_unlock_irq(&ffs->ev.waitq.lock);
@@ -590,7 +590,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
/* unlocks spinlock */
return __ffs_ep0_read_events(ffs, buf,
- min(n, (size_t)ffs->ev.count));
+ min_t(size_t, n, ffs->ev.count));
case FFS_SETUP_PENDING:
if (ffs->ev.setup.bRequestType & USB_DIR_IN) {
@@ -599,7 +599,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
goto done_mutex;
}
- len = min(len, (size_t)le16_to_cpu(ffs->ev.setup.wLength));
+ len = min_t(size_t, len, le16_to_cpu(ffs->ev.setup.wLength));
spin_unlock_irq(&ffs->ev.waitq.lock);
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index 08e0d1c511e8..2eae8fc2e0db 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -500,7 +500,7 @@ static int fsg_setup(struct usb_function *f,
*(u8 *)req->buf = _fsg_common_get_max_lun(fsg->common);
/* Respond with data/status */
- req->length = min((u16)1, w_length);
+ req->length = min_t(u16, 1, w_length);
return ep0_queue(fsg->common);
}
@@ -655,7 +655,7 @@ static int do_read(struct fsg_common *common)
* And don't try to read past the end of the file.
*/
amount = min(amount_left, FSG_BUFLEN);
- amount = min((loff_t)amount,
+ amount = min_t(loff_t, amount,
curlun->file_length - file_offset);
/* Wait for the next buffer to become available */
@@ -1005,7 +1005,7 @@ static int do_verify(struct fsg_common *common)
* And don't try to read past the end of the file.
*/
amount = min(amount_left, FSG_BUFLEN);
- amount = min((loff_t)amount,
+ amount = min_t(loff_t, amount,
curlun->file_length - file_offset);
if (amount == 0) {
curlun->sense_data =
@@ -2167,7 +2167,7 @@ unknown_cmnd:
if (reply == -EINVAL)
reply = 0; /* Error reply length */
if (reply >= 0 && common->data_dir == DATA_DIR_TO_HOST) {
- reply = min((u32)reply, common->data_size_from_cmnd);
+ reply = min_t(u32, reply, common->data_size_from_cmnd);
bh->inreq->length = reply;
bh->state = BUF_STATE_FULL;
common->residue -= reply;
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 1067847cc079..837fcdfa3840 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -819,9 +819,9 @@ static int f_midi_register_card(struct f_midi *midi)
goto fail;
}
- strcpy(card->driver, f_midi_longname);
- strcpy(card->longname, f_midi_longname);
- strcpy(card->shortname, f_midi_shortname);
+ strscpy(card->driver, f_midi_longname);
+ strscpy(card->longname, f_midi_longname);
+ strscpy(card->shortname, f_midi_shortname);
/* Set up rawmidi */
snd_component_add(card, "MIDI");
@@ -833,7 +833,7 @@ static int f_midi_register_card(struct f_midi *midi)
}
midi->rmidi = rmidi;
midi->in_last_port = 0;
- strcpy(rmidi->name, card->shortname);
+ strscpy(rmidi->name, card->shortname);
rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
SNDRV_RAWMIDI_INFO_INPUT |
SNDRV_RAWMIDI_INFO_DUPLEX;
diff --git a/drivers/usb/gadget/function/f_midi2.c b/drivers/usb/gadget/function/f_midi2.c
index 8285df9ed6fd..ee3d9e3578f7 100644
--- a/drivers/usb/gadget/function/f_midi2.c
+++ b/drivers/usb/gadget/function/f_midi2.c
@@ -1285,10 +1285,8 @@ static int f_midi2_set_alt(struct usb_function *fn, unsigned int intf,
if (alt == 0)
op_mode = MIDI_OP_MODE_MIDI1;
- else if (alt == 1)
- op_mode = MIDI_OP_MODE_MIDI2;
else
- op_mode = MIDI_OP_MODE_UNSET;
+ op_mode = MIDI_OP_MODE_MIDI2;
if (midi2->operation_mode == op_mode)
return 0;
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index 40187b7112e7..aa6ab666741a 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -465,7 +465,7 @@ uvc_register_video(struct uvc_device *uvc)
memcpy(mem, desc, (desc)->bLength); \
*(dst)++ = mem; \
mem += (desc)->bLength; \
- } while (0);
+ } while (0)
#define UVC_COPY_DESCRIPTORS(mem, dst, src) \
do { \
@@ -991,6 +991,8 @@ static void uvc_function_unbind(struct usb_configuration *c,
uvcg_info(f, "%s()\n", __func__);
+ kthread_cancel_work_sync(&video->hw_submit);
+
if (video->async_wq)
destroy_workqueue(video->async_wq);
diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h
index cb35687b11e7..6f44dd732315 100644
--- a/drivers/usb/gadget/function/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
@@ -71,6 +71,11 @@ extern unsigned int uvc_gadget_trace_param;
#define UVCG_REQUEST_HEADER_LEN 12
+#define UVCG_REQ_MAX_INT_COUNT 16
+#define UVCG_REQ_MAX_ZERO_COUNT (2 * UVCG_REQ_MAX_INT_COUNT)
+
+#define UVCG_STREAMING_MIN_BUFFERS 2
+
/* ------------------------------------------------------------------------
* Structures
*/
@@ -91,16 +96,24 @@ struct uvc_video {
struct work_struct pump;
struct workqueue_struct *async_wq;
+ struct kthread_worker *kworker;
+ struct kthread_work hw_submit;
+
+ atomic_t queued;
+
/* Frame parameters */
u8 bpp;
u32 fcc;
unsigned int width;
unsigned int height;
unsigned int imagesize;
+ unsigned int interval;
struct mutex mutex; /* protects frame parameters */
unsigned int uvc_num_requests;
+ unsigned int reqs_per_frame;
+
/* Requests */
bool is_enabled; /* tracks whether video stream is enabled */
unsigned int req_size;
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 6fac696ea846..f131943254a4 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -1566,11 +1566,13 @@ static const struct uvcg_config_group_type uvcg_control_grp_type = {
/* -----------------------------------------------------------------------------
* streaming/uncompressed
* streaming/mjpeg
+ * streaming/framebased
*/
static const char * const uvcg_format_names[] = {
"uncompressed",
"mjpeg",
+ "framebased",
};
static struct uvcg_color_matching *
@@ -1777,6 +1779,9 @@ static int uvcg_streaming_header_allow_link(struct config_item *src,
target_fmt = container_of(to_config_group(target), struct uvcg_format,
group);
+ if (!target_fmt)
+ goto out;
+
uvcg_format_set_indices(to_config_group(target));
format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
@@ -1816,6 +1821,9 @@ static void uvcg_streaming_header_drop_link(struct config_item *src,
target_fmt = container_of(to_config_group(target), struct uvcg_format,
group);
+ if (!target_fmt)
+ goto out;
+
list_for_each_entry_safe(format_ptr, tmp, &src_hdr->formats, entry)
if (format_ptr->fmt == target_fmt) {
list_del(&format_ptr->entry);
@@ -1826,6 +1834,7 @@ static void uvcg_streaming_header_drop_link(struct config_item *src,
--target_fmt->linked;
+out:
mutex_unlock(&opts->lock);
mutex_unlock(su_mutex);
}
@@ -2022,6 +2031,7 @@ UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, 32);
UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, 32);
UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, 32);
UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, 32);
+UVCG_FRAME_ATTR(dw_bytes_perline, dwBytesPerLine, 32);
#undef UVCG_FRAME_ATTR
@@ -2035,7 +2045,7 @@ static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
int result, i;
char *pg = page;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
opts_item = frm->item.ci_parent->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -2105,7 +2115,7 @@ end:
UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
-static struct configfs_attribute *uvcg_frame_attrs[] = {
+static struct configfs_attribute *uvcg_frame_attrs1[] = {
&uvcg_frame_attr_b_frame_index,
&uvcg_frame_attr_bm_capabilities,
&uvcg_frame_attr_w_width,
@@ -2118,12 +2128,31 @@ static struct configfs_attribute *uvcg_frame_attrs[] = {
NULL,
};
-static const struct config_item_type uvcg_frame_type = {
+static struct configfs_attribute *uvcg_frame_attrs2[] = {
+ &uvcg_frame_attr_b_frame_index,
+ &uvcg_frame_attr_bm_capabilities,
+ &uvcg_frame_attr_w_width,
+ &uvcg_frame_attr_w_height,
+ &uvcg_frame_attr_dw_min_bit_rate,
+ &uvcg_frame_attr_dw_max_bit_rate,
+ &uvcg_frame_attr_dw_default_frame_interval,
+ &uvcg_frame_attr_dw_frame_interval,
+ &uvcg_frame_attr_dw_bytes_perline,
+ NULL,
+};
+
+static const struct config_item_type uvcg_frame_type1 = {
.ct_item_ops = &uvcg_config_item_ops,
- .ct_attrs = uvcg_frame_attrs,
+ .ct_attrs = uvcg_frame_attrs1,
.ct_owner = THIS_MODULE,
};
+static const struct config_item_type uvcg_frame_type2 = {
+ .ct_item_ops = &uvcg_config_item_ops,
+ .ct_attrs = uvcg_frame_attrs2,
+ .ct_owner = THIS_MODULE,
+};
+
static struct config_item *uvcg_frame_make(struct config_group *group,
const char *name)
{
@@ -2145,6 +2174,7 @@ static struct config_item *uvcg_frame_make(struct config_group *group,
h->frame.dw_max_bit_rate = 55296000;
h->frame.dw_max_video_frame_buffer_size = 460800;
h->frame.dw_default_frame_interval = 666666;
+ h->frame.dw_bytes_perline = 0;
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -2157,6 +2187,9 @@ static struct config_item *uvcg_frame_make(struct config_group *group,
} else if (fmt->type == UVCG_MJPEG) {
h->frame.b_descriptor_subtype = UVC_VS_FRAME_MJPEG;
h->fmt_type = UVCG_MJPEG;
+ } else if (fmt->type == UVCG_FRAMEBASED) {
+ h->frame.b_descriptor_subtype = UVC_VS_FRAME_FRAME_BASED;
+ h->fmt_type = UVCG_FRAMEBASED;
} else {
mutex_unlock(&opts->lock);
kfree(h);
@@ -2175,7 +2208,10 @@ static struct config_item *uvcg_frame_make(struct config_group *group,
++fmt->num_frames;
mutex_unlock(&opts->lock);
- config_item_init_type_name(&h->item, name, &uvcg_frame_type);
+ if (fmt->type == UVCG_FRAMEBASED)
+ config_item_init_type_name(&h->item, name, &uvcg_frame_type2);
+ else
+ config_item_init_type_name(&h->item, name, &uvcg_frame_type1);
return &h->item;
}
@@ -2215,9 +2251,6 @@ static void uvcg_format_set_indices(struct config_group *fmt)
list_for_each_entry(ci, &fmt->cg_children, ci_entry) {
struct uvcg_frame *frm;
- if (ci->ci_type != &uvcg_frame_type)
- continue;
-
frm = to_uvcg_frame(ci);
frm->frame.b_frame_index = i++;
}
@@ -2678,6 +2711,251 @@ static const struct uvcg_config_group_type uvcg_mjpeg_grp_type = {
};
/* -----------------------------------------------------------------------------
+ * streaming/framebased/<NAME>
+ */
+
+static struct configfs_group_operations uvcg_framebased_group_ops = {
+ .make_item = uvcg_frame_make,
+ .drop_item = uvcg_frame_drop,
+};
+
+#define UVCG_FRAMEBASED_ATTR_RO(cname, aname, bits) \
+static ssize_t uvcg_framebased_##cname##_show(struct config_item *item, \
+ char *page) \
+{ \
+ struct uvcg_framebased *u = to_uvcg_framebased(item); \
+ struct f_uvc_opts *opts; \
+ struct config_item *opts_item; \
+ struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
+ int result; \
+ \
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
+ \
+ opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
+ opts = to_f_uvc_opts(opts_item); \
+ \
+ mutex_lock(&opts->lock); \
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
+ mutex_unlock(&opts->lock); \
+ \
+ mutex_unlock(su_mutex); \
+ return result; \
+} \
+ \
+UVC_ATTR_RO(uvcg_framebased_, cname, aname)
+
+#define UVCG_FRAMEBASED_ATTR(cname, aname, bits) \
+static ssize_t uvcg_framebased_##cname##_show(struct config_item *item, \
+ char *page) \
+{ \
+ struct uvcg_framebased *u = to_uvcg_framebased(item); \
+ struct f_uvc_opts *opts; \
+ struct config_item *opts_item; \
+ struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
+ int result; \
+ \
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
+ \
+ opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
+ opts = to_f_uvc_opts(opts_item); \
+ \
+ mutex_lock(&opts->lock); \
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
+ mutex_unlock(&opts->lock); \
+ \
+ mutex_unlock(su_mutex); \
+ return result; \
+} \
+ \
+static ssize_t \
+uvcg_framebased_##cname##_store(struct config_item *item, \
+ const char *page, size_t len) \
+{ \
+ struct uvcg_framebased *u = to_uvcg_framebased(item); \
+ struct f_uvc_opts *opts; \
+ struct config_item *opts_item; \
+ struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
+ int ret; \
+ u8 num; \
+ \
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
+ \
+ opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
+ opts = to_f_uvc_opts(opts_item); \
+ \
+ mutex_lock(&opts->lock); \
+ if (u->fmt.linked || opts->refcnt) { \
+ ret = -EBUSY; \
+ goto end; \
+ } \
+ \
+ ret = kstrtou8(page, 0, &num); \
+ if (ret) \
+ goto end; \
+ \
+ if (num > 255) { \
+ ret = -EINVAL; \
+ goto end; \
+ } \
+ u->desc.aname = num; \
+ ret = len; \
+end: \
+ mutex_unlock(&opts->lock); \
+ mutex_unlock(su_mutex); \
+ return ret; \
+} \
+ \
+UVC_ATTR(uvcg_framebased_, cname, aname)
+
+UVCG_FRAMEBASED_ATTR_RO(b_format_index, bFormatIndex, 8);
+UVCG_FRAMEBASED_ATTR_RO(b_bits_per_pixel, bBitsPerPixel, 8);
+UVCG_FRAMEBASED_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
+UVCG_FRAMEBASED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
+UVCG_FRAMEBASED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
+UVCG_FRAMEBASED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8);
+
+#undef UVCG_FRAMEBASED_ATTR
+#undef UVCG_FRAMEBASED_ATTR_RO
+
+static ssize_t uvcg_framebased_guid_format_show(struct config_item *item,
+ char *page)
+{
+ struct uvcg_framebased *ch = to_uvcg_framebased(item);
+ struct f_uvc_opts *opts;
+ struct config_item *opts_item;
+ struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
+
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+ opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
+ memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat));
+ mutex_unlock(&opts->lock);
+
+ mutex_unlock(su_mutex);
+
+ return sizeof(ch->desc.guidFormat);
+}
+
+static ssize_t uvcg_framebased_guid_format_store(struct config_item *item,
+ const char *page, size_t len)
+{
+ struct uvcg_framebased *ch = to_uvcg_framebased(item);
+ struct f_uvc_opts *opts;
+ struct config_item *opts_item;
+ struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
+ int ret;
+
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+ opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
+ if (ch->fmt.linked || opts->refcnt) {
+ ret = -EBUSY;
+ goto end;
+ }
+
+ memcpy(ch->desc.guidFormat, page,
+ min(sizeof(ch->desc.guidFormat), len));
+ ret = sizeof(ch->desc.guidFormat);
+
+end:
+ mutex_unlock(&opts->lock);
+ mutex_unlock(su_mutex);
+ return ret;
+}
+
+UVC_ATTR(uvcg_framebased_, guid_format, guidFormat);
+
+static inline ssize_t
+uvcg_framebased_bma_controls_show(struct config_item *item, char *page)
+{
+ struct uvcg_framebased *u = to_uvcg_framebased(item);
+
+ return uvcg_format_bma_controls_show(&u->fmt, page);
+}
+
+static inline ssize_t
+uvcg_framebased_bma_controls_store(struct config_item *item,
+ const char *page, size_t len)
+{
+ struct uvcg_framebased *u = to_uvcg_framebased(item);
+
+ return uvcg_format_bma_controls_store(&u->fmt, page, len);
+}
+
+UVC_ATTR(uvcg_framebased_, bma_controls, bmaControls);
+
+static struct configfs_attribute *uvcg_framebased_attrs[] = {
+ &uvcg_framebased_attr_b_format_index,
+ &uvcg_framebased_attr_b_default_frame_index,
+ &uvcg_framebased_attr_b_bits_per_pixel,
+ &uvcg_framebased_attr_b_aspect_ratio_x,
+ &uvcg_framebased_attr_b_aspect_ratio_y,
+ &uvcg_framebased_attr_bm_interface_flags,
+ &uvcg_framebased_attr_bma_controls,
+ &uvcg_framebased_attr_guid_format,
+ NULL,
+};
+
+static const struct config_item_type uvcg_framebased_type = {
+ .ct_item_ops = &uvcg_config_item_ops,
+ .ct_group_ops = &uvcg_framebased_group_ops,
+ .ct_attrs = uvcg_framebased_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *uvcg_framebased_make(struct config_group *group,
+ const char *name)
+{
+ static char guid[] = { /*Declear frame based as H264 format*/
+ 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
+ };
+ struct uvcg_framebased *h;
+
+ h = kzalloc(sizeof(*h), GFP_KERNEL);
+ if (!h)
+ return ERR_PTR(-ENOMEM);
+
+ h->desc.bLength = UVC_DT_FORMAT_FRAMEBASED_SIZE;
+ h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
+ h->desc.bDescriptorSubType = UVC_VS_FORMAT_FRAME_BASED;
+ memcpy(h->desc.guidFormat, guid, sizeof(guid));
+ h->desc.bBitsPerPixel = 0;
+ h->desc.bDefaultFrameIndex = 1;
+ h->desc.bAspectRatioX = 0;
+ h->desc.bAspectRatioY = 0;
+ h->desc.bmInterfaceFlags = 0;
+ h->desc.bCopyProtect = 0;
+ h->desc.bVariableSize = 1;
+
+ INIT_LIST_HEAD(&h->fmt.frames);
+ h->fmt.type = UVCG_FRAMEBASED;
+ config_group_init_type_name(&h->fmt.group, name,
+ &uvcg_framebased_type);
+
+ return &h->fmt.group;
+}
+
+static struct configfs_group_operations uvcg_framebased_grp_ops = {
+ .make_group = uvcg_framebased_make,
+};
+
+static const struct uvcg_config_group_type uvcg_framebased_grp_type = {
+ .type = {
+ .ct_item_ops = &uvcg_config_item_ops,
+ .ct_group_ops = &uvcg_framebased_grp_ops,
+ .ct_owner = THIS_MODULE,
+ },
+ .name = "framebased",
+};
+
+/* -----------------------------------------------------------------------------
* streaming/color_matching/default
*/
@@ -2912,6 +3190,7 @@ static int __uvcg_iter_strm_cls(struct uvcg_streaming_header *h,
if (ret)
return ret;
grp = &f->fmt->group;
+ j = 0;
list_for_each_entry(item, &grp->cg_children, ci_entry) {
frm = to_uvcg_frame(item);
ret = fun(frm, priv2, priv3, j++, UVCG_FRAME);
@@ -2965,6 +3244,11 @@ static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
container_of(fmt, struct uvcg_mjpeg, fmt);
*size += sizeof(m->desc);
+ } else if (fmt->type == UVCG_FRAMEBASED) {
+ struct uvcg_framebased *f =
+ container_of(fmt, struct uvcg_framebased, fmt);
+
+ *size += sizeof(f->desc);
} else {
return -EINVAL;
}
@@ -2975,6 +3259,11 @@ static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
int sz = sizeof(frm->dw_frame_interval);
*size += sizeof(frm->frame);
+ /*
+ * framebased has duplicate member with uncompressed and
+ * mjpeg, so minus it
+ */
+ *size -= sizeof(u32);
*size += frm->frame.b_frame_interval_type * sz;
}
break;
@@ -2991,6 +3280,27 @@ static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
return 0;
}
+static int __uvcg_copy_framebased_desc(void *dest, struct uvcg_frame *frm,
+ int sz)
+{
+ struct uvc_frame_framebased *desc = dest;
+
+ desc->bLength = frm->frame.b_length;
+ desc->bDescriptorType = frm->frame.b_descriptor_type;
+ desc->bDescriptorSubType = frm->frame.b_descriptor_subtype;
+ desc->bFrameIndex = frm->frame.b_frame_index;
+ desc->bmCapabilities = frm->frame.bm_capabilities;
+ desc->wWidth = frm->frame.w_width;
+ desc->wHeight = frm->frame.w_height;
+ desc->dwMinBitRate = frm->frame.dw_min_bit_rate;
+ desc->dwMaxBitRate = frm->frame.dw_max_bit_rate;
+ desc->dwDefaultFrameInterval = frm->frame.dw_default_frame_interval;
+ desc->bFrameIntervalType = frm->frame.b_frame_interval_type;
+ desc->dwBytesPerLine = frm->frame.dw_bytes_perline;
+
+ return 0;
+}
+
/*
* Fill an array of streaming descriptors.
*
@@ -3045,6 +3355,15 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
m->desc.bNumFrameDescriptors = fmt->num_frames;
memcpy(*dest, &m->desc, sizeof(m->desc));
*dest += sizeof(m->desc);
+ } else if (fmt->type == UVCG_FRAMEBASED) {
+ struct uvcg_framebased *f =
+ container_of(fmt, struct uvcg_framebased,
+ fmt);
+
+ f->desc.bFormatIndex = n + 1;
+ f->desc.bNumFrameDescriptors = fmt->num_frames;
+ memcpy(*dest, &f->desc, sizeof(f->desc));
+ *dest += sizeof(f->desc);
} else {
return -EINVAL;
}
@@ -3054,8 +3373,11 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
struct uvcg_frame *frm = priv1;
struct uvc_descriptor_header *h = *dest;
- sz = sizeof(frm->frame);
- memcpy(*dest, &frm->frame, sz);
+ sz = sizeof(frm->frame) - 4;
+ if (frm->fmt_type != UVCG_FRAMEBASED)
+ memcpy(*dest, &frm->frame, sz);
+ else
+ __uvcg_copy_framebased_desc(*dest, frm, sz);
*dest += sz;
sz = frm->frame.b_frame_interval_type *
sizeof(*frm->dw_frame_interval);
@@ -3066,7 +3388,10 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
frm->frame.b_frame_interval_type);
else if (frm->fmt_type == UVCG_MJPEG)
h->bLength = UVC_DT_FRAME_MJPEG_SIZE(
- frm->frame.b_frame_interval_type);
+ frm->frame.b_frame_interval_type);
+ else if (frm->fmt_type == UVCG_FRAMEBASED)
+ h->bLength = UVC_DT_FRAME_FRAMEBASED_SIZE(
+ frm->frame.b_frame_interval_type);
}
break;
case UVCG_COLOR_MATCHING: {
@@ -3285,6 +3610,7 @@ static const struct uvcg_config_group_type uvcg_streaming_grp_type = {
&uvcg_streaming_header_grp_type,
&uvcg_uncompressed_grp_type,
&uvcg_mjpeg_grp_type,
+ &uvcg_framebased_grp_type,
&uvcg_color_matching_grp_type,
&uvcg_streaming_class_grp_type,
NULL,
diff --git a/drivers/usb/gadget/function/uvc_configfs.h b/drivers/usb/gadget/function/uvc_configfs.h
index c6a690158138..2f78cd4f396f 100644
--- a/drivers/usb/gadget/function/uvc_configfs.h
+++ b/drivers/usb/gadget/function/uvc_configfs.h
@@ -49,6 +49,7 @@ container_of(group_ptr, struct uvcg_color_matching, group)
enum uvcg_format_type {
UVCG_UNCOMPRESSED = 0,
UVCG_MJPEG,
+ UVCG_FRAMEBASED,
};
struct uvcg_format {
@@ -105,6 +106,7 @@ struct uvcg_frame {
u32 dw_max_video_frame_buffer_size;
u32 dw_default_frame_interval;
u8 b_frame_interval_type;
+ u32 dw_bytes_perline;
} __attribute__((packed)) frame;
u32 *dw_frame_interval;
};
@@ -143,6 +145,20 @@ static inline struct uvcg_mjpeg *to_uvcg_mjpeg(struct config_item *item)
}
/* -----------------------------------------------------------------------------
+ * streaming/framebased/<NAME>
+ */
+
+struct uvcg_framebased {
+ struct uvcg_format fmt;
+ struct uvc_format_framebased desc;
+};
+
+static inline struct uvcg_framebased *to_uvcg_framebased(struct config_item *item)
+{
+ return container_of(to_uvcg_format(item), struct uvcg_framebased, fmt);
+}
+
+/* -----------------------------------------------------------------------------
* control/extensions/<NAME>
*/
diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c
index 0aa3d7e1f3cc..5eaeae3e2441 100644
--- a/drivers/usb/gadget/function/uvc_queue.c
+++ b/drivers/usb/gadget/function/uvc_queue.c
@@ -21,6 +21,7 @@
#include <media/videobuf2-vmalloc.h>
#include "uvc.h"
+#include "uvc_video.h"
/* ------------------------------------------------------------------------
* Video buffers queue management.
@@ -44,33 +45,23 @@ static int uvc_queue_setup(struct vb2_queue *vq,
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
struct uvc_video *video = container_of(queue, struct uvc_video, queue);
- unsigned int req_size;
- unsigned int nreq;
if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
*nbuffers = UVC_MAX_VIDEO_BUFFERS;
+ if (*nbuffers < UVCG_STREAMING_MIN_BUFFERS)
+ *nbuffers = UVCG_STREAMING_MIN_BUFFERS;
*nplanes = 1;
sizes[0] = video->imagesize;
- req_size = video->ep->maxpacket
- * max_t(unsigned int, video->ep->maxburst, 1)
- * (video->ep->mult);
-
- /* We divide by two, to increase the chance to run
- * into fewer requests for smaller framesizes.
- */
- nreq = DIV_ROUND_UP(DIV_ROUND_UP(sizes[0], 2), req_size);
- nreq = clamp(nreq, 4U, 64U);
- video->uvc_num_requests = nreq;
-
return 0;
}
static int uvc_buffer_prepare(struct vb2_buffer *vb)
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+ struct uvc_video *video = container_of(queue, struct uvc_video, queue);
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
@@ -91,10 +82,15 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
buf->mem = vb2_plane_vaddr(vb, 0);
}
buf->length = vb2_plane_size(vb, 0);
- if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
buf->bytesused = 0;
- else
+ } else {
buf->bytesused = vb2_get_plane_payload(vb, 0);
+ buf->req_payload_size =
+ DIV_ROUND_UP(buf->bytesused +
+ (video->reqs_per_frame * UVCG_REQUEST_HEADER_LEN),
+ video->reqs_per_frame);
+ }
return 0;
}
diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h
index 41f87b917f6b..b54becc570a3 100644
--- a/drivers/usb/gadget/function/uvc_queue.h
+++ b/drivers/usb/gadget/function/uvc_queue.h
@@ -39,6 +39,8 @@ struct uvc_buffer {
unsigned int offset;
unsigned int length;
unsigned int bytesused;
+ /* req_payload_size: only used with isoc */
+ unsigned int req_payload_size;
};
#define UVC_QUEUE_DISCONNECTED (1 << 0)
diff --git a/drivers/usb/gadget/function/uvc_trace.c b/drivers/usb/gadget/function/uvc_trace.c
new file mode 100644
index 000000000000..d384f6d8221a
--- /dev/null
+++ b/drivers/usb/gadget/function/uvc_trace.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * trace.c - USB UVC Gadget Trace Support
+ *
+ * Copyright (C) 2024 Pengutronix e.K.
+ *
+ * Author: Michael Grzeschik <m.grzeschik@pengutronix.de>
+ */
+
+#define CREATE_TRACE_POINTS
+#include "uvc_trace.h"
diff --git a/drivers/usb/gadget/function/uvc_trace.h b/drivers/usb/gadget/function/uvc_trace.h
new file mode 100644
index 000000000000..04c33cf43cc2
--- /dev/null
+++ b/drivers/usb/gadget/function/uvc_trace.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * trace.h - USB UVC Gadget Trace Support
+ *
+ * Copyright (C) 2024 Pengutronix e.K.
+ *
+ * Author: Michael Grzeschik <m.grzeschik@pengutronix.de>
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM uvcg
+
+#if !defined(__UVCG_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __UVCG_TRACE_H
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+#include <linux/usb/gadget.h>
+#include <asm/byteorder.h>
+
+DECLARE_EVENT_CLASS(uvcg_video_req,
+ TP_PROTO(struct usb_request *req, u32 queued),
+ TP_ARGS(req, queued),
+ TP_STRUCT__entry(
+ __field(struct usb_request *, req)
+ __field(u32, length)
+ __field(u32, queued)
+ ),
+ TP_fast_assign(
+ __entry->req = req;
+ __entry->length = req->length;
+ __entry->queued = queued;
+ ),
+ TP_printk("req %p length %u queued %u",
+ __entry->req,
+ __entry->length,
+ __entry->queued)
+);
+
+DEFINE_EVENT(uvcg_video_req, uvcg_video_complete,
+ TP_PROTO(struct usb_request *req, u32 queued),
+ TP_ARGS(req, queued)
+);
+
+DEFINE_EVENT(uvcg_video_req, uvcg_video_queue,
+ TP_PROTO(struct usb_request *req, u32 queued),
+ TP_ARGS(req, queued)
+);
+
+#endif /* __UVCG_TRACE_H */
+
+/* this part has to be here */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE uvc_trace
+
+#include <trace/define_trace.h>
diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c
index de1736f834e6..fc9a8d31a1e9 100644
--- a/drivers/usb/gadget/function/uvc_v4l2.c
+++ b/drivers/usb/gadget/function/uvc_v4l2.c
@@ -31,14 +31,23 @@ static const struct uvc_format_desc *to_uvc_format(struct uvcg_format *uformat)
{
char guid[16] = UVC_GUID_FORMAT_MJPEG;
const struct uvc_format_desc *format;
- struct uvcg_uncompressed *unc;
if (uformat->type == UVCG_UNCOMPRESSED) {
+ struct uvcg_uncompressed *unc;
+
unc = to_uvcg_uncompressed(&uformat->group.cg_item);
if (!unc)
return ERR_PTR(-EINVAL);
memcpy(guid, unc->desc.guidFormat, sizeof(guid));
+ } else if (uformat->type == UVCG_FRAMEBASED) {
+ struct uvcg_framebased *unc;
+
+ unc = to_uvcg_framebased(&uformat->group.cg_item);
+ if (!unc)
+ return ERR_PTR(-EINVAL);
+
+ memcpy(guid, unc->desc.guidFormat, sizeof(guid));
}
format = uvc_format_by_guid(guid);
@@ -314,6 +323,56 @@ uvc_v4l2_set_format(struct file *file, void *fh, struct v4l2_format *fmt)
return ret;
}
+static int uvc_v4l2_g_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *parm)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct uvc_device *uvc = video_get_drvdata(vdev);
+ struct uvc_video *video = &uvc->video;
+ struct v4l2_fract timeperframe;
+
+ if (!V4L2_TYPE_IS_OUTPUT(parm->type))
+ return -EINVAL;
+
+ /* Return the actual frame period. */
+ timeperframe.numerator = video->interval;
+ timeperframe.denominator = 10000000;
+ v4l2_simplify_fraction(&timeperframe.numerator,
+ &timeperframe.denominator, 8, 333);
+
+ uvcg_dbg(&uvc->func, "Getting frame interval of %u/%u (%u)\n",
+ timeperframe.numerator, timeperframe.denominator,
+ video->interval);
+
+ parm->parm.output.timeperframe = timeperframe;
+ parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+
+ return 0;
+}
+
+static int uvc_v4l2_s_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *parm)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct uvc_device *uvc = video_get_drvdata(vdev);
+ struct uvc_video *video = &uvc->video;
+ struct v4l2_fract timeperframe;
+
+ if (!V4L2_TYPE_IS_OUTPUT(parm->type))
+ return -EINVAL;
+
+ timeperframe = parm->parm.output.timeperframe;
+
+ video->interval = v4l2_fraction_to_interval(timeperframe.numerator,
+ timeperframe.denominator);
+
+ uvcg_dbg(&uvc->func, "Setting frame interval to %u/%u (%u)\n",
+ timeperframe.numerator, timeperframe.denominator,
+ video->interval);
+
+ return 0;
+}
+
static int
uvc_v4l2_enum_frameintervals(struct file *file, void *fh,
struct v4l2_frmivalenum *fival)
@@ -496,6 +555,9 @@ uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
if (ret < 0)
return ret;
+ if (uvc->state != UVC_STATE_STREAMING)
+ return 0;
+
uvc->state = UVC_STATE_CONNECTED;
uvc_function_setup_continue(uvc, 1);
return 0;
@@ -587,6 +649,8 @@ const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops = {
.vidioc_dqbuf = uvc_v4l2_dqbuf,
.vidioc_streamon = uvc_v4l2_streamon,
.vidioc_streamoff = uvc_v4l2_streamoff,
+ .vidioc_s_parm = uvc_v4l2_s_parm,
+ .vidioc_g_parm = uvc_v4l2_g_parm,
.vidioc_subscribe_event = uvc_v4l2_subscribe_event,
.vidioc_unsubscribe_event = uvc_v4l2_unsubscribe_event,
.vidioc_default = uvc_v4l2_ioctl_default,
diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c
index 57a851151225..79e223713d8b 100644
--- a/drivers/usb/gadget/function/uvc_video.c
+++ b/drivers/usb/gadget/function/uvc_video.c
@@ -19,6 +19,7 @@
#include "uvc.h"
#include "uvc_queue.h"
#include "uvc_video.h"
+#include "uvc_trace.h"
/* --------------------------------------------------------------------------
* Video codecs
@@ -78,7 +79,7 @@ uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf,
/* Copy video data to the USB buffer. */
mem = buf->mem + queue->buf_used;
- nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
+ nbytes = min_t(unsigned int, len, buf->bytesused - queue->buf_used);
memcpy(data, mem, nbytes);
queue->buf_used += nbytes;
@@ -104,7 +105,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
}
/* Process video data. */
- len = min((int)(video->max_payload_size - video->payload_size), len);
+ len = min_t(int, video->max_payload_size - video->payload_size, len);
ret = uvc_video_encode_data(video, buf, mem, len);
video->payload_size += ret;
@@ -136,7 +137,7 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video,
unsigned int pending = buf->bytesused - video->queue.buf_used;
struct uvc_request *ureq = req->context;
struct scatterlist *sg, *iter;
- unsigned int len = video->req_size;
+ unsigned int len = buf->req_payload_size;
unsigned int sg_left, part = 0;
unsigned int i;
int header_len;
@@ -146,15 +147,15 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video,
/* Init the header. */
header_len = uvc_video_encode_header(video, buf, ureq->header,
- video->req_size);
+ buf->req_payload_size);
sg_set_buf(sg, ureq->header, header_len);
len -= header_len;
if (pending <= len)
len = pending;
- req->length = (len == pending) ?
- len + header_len : video->req_size;
+ req->length = (len == pending) ? len + header_len :
+ buf->req_payload_size;
/* Init the pending sgs with payload */
sg = sg_next(sg);
@@ -202,7 +203,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
{
void *mem = req->buf;
struct uvc_request *ureq = req->context;
- int len = video->req_size;
+ int len = buf->req_payload_size;
int ret;
/* Add the header. */
@@ -214,7 +215,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
ret = uvc_video_encode_data(video, buf, mem, len);
len -= ret;
- req->length = video->req_size - len;
+ req->length = buf->req_payload_size - len;
if (buf->bytesused == video->queue.buf_used ||
video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) {
@@ -269,6 +270,10 @@ static int uvcg_video_ep_queue(struct uvc_video *video, struct usb_request *req)
}
}
+ atomic_inc(&video->queued);
+
+ trace_uvcg_video_queue(req, atomic_read(&video->queued));
+
return ret;
}
@@ -304,7 +309,7 @@ static int uvcg_video_usb_req_queue(struct uvc_video *video,
*/
if (list_empty(&video->req_free) || ureq->last_buf ||
!(video->req_int_count %
- DIV_ROUND_UP(video->uvc_num_requests, 4))) {
+ min(DIV_ROUND_UP(video->uvc_num_requests, 4), UVCG_REQ_MAX_INT_COUNT))) {
video->req_int_count = 0;
req->no_interrupt = 0;
} else {
@@ -322,50 +327,6 @@ static int uvcg_video_usb_req_queue(struct uvc_video *video,
return 0;
}
-/*
- * Must only be called from uvcg_video_enable - since after that we only want to
- * queue requests to the endpoint from the uvc_video_complete complete handler.
- * This function is needed in order to 'kick start' the flow of requests from
- * gadget driver to the usb controller.
- */
-static void uvc_video_ep_queue_initial_requests(struct uvc_video *video)
-{
- struct usb_request *req = NULL;
- unsigned long flags = 0;
- unsigned int count = 0;
- int ret = 0;
-
- /*
- * We only queue half of the free list since we still want to have
- * some free usb_requests in the free list for the video_pump async_wq
- * thread to encode uvc buffers into. Otherwise we could get into a
- * situation where the free list does not have any usb requests to
- * encode into - we always end up queueing 0 length requests to the
- * end point.
- */
- unsigned int half_list_size = video->uvc_num_requests / 2;
-
- spin_lock_irqsave(&video->req_lock, flags);
- /*
- * Take these requests off the free list and queue them all to the
- * endpoint. Since we queue 0 length requests with the req_lock held,
- * there isn't any 'data' race involved here with the complete handler.
- */
- while (count < half_list_size) {
- req = list_first_entry(&video->req_free, struct usb_request,
- list);
- list_del(&req->list);
- req->length = 0;
- ret = uvcg_video_ep_queue(video, req);
- if (ret < 0) {
- uvcg_queue_cancel(&video->queue, 0);
- break;
- }
- count++;
- }
- spin_unlock_irqrestore(&video->req_lock, flags);
-}
-
static void
uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
{
@@ -373,12 +334,10 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
struct uvc_video *video = ureq->video;
struct uvc_video_queue *queue = &video->queue;
struct uvc_buffer *last_buf;
- struct usb_request *to_queue = req;
unsigned long flags;
- bool is_bulk = video->max_payload_size;
- int ret = 0;
spin_lock_irqsave(&video->req_lock, flags);
+ atomic_dec(&video->queued);
if (!video->is_enabled) {
/*
* When is_enabled is false, uvcg_video_disable() ensures
@@ -438,51 +397,87 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
return;
}
+ list_add_tail(&req->list, &video->req_free);
/*
- * Here we check whether any request is available in the ready
- * list. If it is, queue it to the ep and add the current
- * usb_request to the req_free list - for video_pump to fill in.
- * Otherwise, just use the current usb_request to queue a 0
- * length request to the ep. Since we always add to the req_free
- * list if we dequeue from the ready list, there will never
- * be a situation where the req_free list is completely out of
- * requests and cannot recover.
+ * Queue work to the wq as well since it is possible that a
+ * buffer may not have been completely encoded with the set of
+ * in-flight usb requests for whih the complete callbacks are
+ * firing.
+ * In that case, if we do not queue work to the worker thread,
+ * the buffer will never be marked as complete - and therefore
+ * not be returned to userpsace. As a result,
+ * dequeue -> queue -> dequeue flow of uvc buffers will not
+ * happen. Since there are is a new free request wake up the pump.
*/
- to_queue->length = 0;
- if (!list_empty(&video->req_ready)) {
- to_queue = list_first_entry(&video->req_ready,
- struct usb_request, list);
- list_del(&to_queue->list);
- list_add_tail(&req->list, &video->req_free);
+ queue_work(video->async_wq, &video->pump);
+
+ trace_uvcg_video_complete(req, atomic_read(&video->queued));
+
+ spin_unlock_irqrestore(&video->req_lock, flags);
+
+ kthread_queue_work(video->kworker, &video->hw_submit);
+}
+
+static void uvcg_video_hw_submit(struct kthread_work *work)
+{
+ struct uvc_video *video = container_of(work, struct uvc_video, hw_submit);
+ bool is_bulk = video->max_payload_size;
+ unsigned long flags;
+ struct usb_request *req;
+ int ret = 0;
+
+ while (true) {
+ if (!video->ep->enabled)
+ return;
+ spin_lock_irqsave(&video->req_lock, flags);
/*
- * Queue work to the wq as well since it is possible that a
- * buffer may not have been completely encoded with the set of
- * in-flight usb requests for whih the complete callbacks are
- * firing.
- * In that case, if we do not queue work to the worker thread,
- * the buffer will never be marked as complete - and therefore
- * not be returned to userpsace. As a result,
- * dequeue -> queue -> dequeue flow of uvc buffers will not
- * happen.
+ * Here we check whether any request is available in the ready
+ * list. If it is, queue it to the ep and add the current
+ * usb_request to the req_free list - for video_pump to fill in.
+ * Otherwise, just use the current usb_request to queue a 0
+ * length request to the ep. Since we always add to the req_free
+ * list if we dequeue from the ready list, there will never
+ * be a situation where the req_free list is completely out of
+ * requests and cannot recover.
*/
- queue_work(video->async_wq, &video->pump);
- }
- /*
- * Queue to the endpoint. The actual queueing to ep will
- * only happen on one thread - the async_wq for bulk endpoints
- * and this thread for isoc endpoints.
- */
- ret = uvcg_video_usb_req_queue(video, to_queue, !is_bulk);
- if (ret < 0) {
+ if (!list_empty(&video->req_ready)) {
+ req = list_first_entry(&video->req_ready,
+ struct usb_request, list);
+ } else {
+ if (list_empty(&video->req_free) ||
+ (atomic_read(&video->queued) > UVCG_REQ_MAX_ZERO_COUNT)) {
+ spin_unlock_irqrestore(&video->req_lock, flags);
+
+ return;
+ }
+ req = list_first_entry(&video->req_free, struct usb_request,
+ list);
+ req->length = 0;
+ }
+ list_del(&req->list);
+
/*
- * Endpoint error, but the stream is still enabled.
- * Put request back in req_free for it to be cleaned
- * up later.
+ * Queue to the endpoint. The actual queueing to ep will
+ * only happen on one thread - the async_wq for bulk endpoints
+ * and this thread for isoc endpoints.
*/
- list_add_tail(&to_queue->list, &video->req_free);
- }
+ ret = uvcg_video_usb_req_queue(video, req, !is_bulk);
+ if (ret < 0) {
+ /*
+ * Endpoint error, but the stream is still enabled.
+ * Put request back in req_free for it to be cleaned
+ * up later.
+ */
+ list_add_tail(&req->list, &video->req_free);
+ /*
+ * There is a new free request - wake up the pump.
+ */
+ queue_work(video->async_wq, &video->pump);
- spin_unlock_irqrestore(&video->req_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&video->req_lock, flags);
+ }
}
static int
@@ -496,23 +491,71 @@ uvc_video_free_requests(struct uvc_video *video)
INIT_LIST_HEAD(&video->ureqs);
INIT_LIST_HEAD(&video->req_free);
INIT_LIST_HEAD(&video->req_ready);
- video->req_size = 0;
return 0;
}
+static void
+uvc_video_prep_requests(struct uvc_video *video)
+{
+ struct uvc_device *uvc = container_of(video, struct uvc_device, video);
+ struct usb_composite_dev *cdev = uvc->func.config->cdev;
+ unsigned int interval_duration = video->ep->desc->bInterval * 1250;
+ unsigned int max_req_size, req_size, header_size;
+ unsigned int nreq;
+
+ max_req_size = video->ep->maxpacket
+ * max_t(unsigned int, video->ep->maxburst, 1)
+ * (video->ep->mult);
+
+ if (!usb_endpoint_xfer_isoc(video->ep->desc)) {
+ video->req_size = max_req_size;
+ video->reqs_per_frame = video->uvc_num_requests =
+ DIV_ROUND_UP(video->imagesize, max_req_size);
+
+ return;
+ }
+
+ if (cdev->gadget->speed < USB_SPEED_HIGH)
+ interval_duration = video->ep->desc->bInterval * 10000;
+
+ nreq = DIV_ROUND_UP(video->interval, interval_duration);
+
+ header_size = nreq * UVCG_REQUEST_HEADER_LEN;
+
+ req_size = DIV_ROUND_UP(video->imagesize + header_size, nreq);
+
+ if (req_size > max_req_size) {
+ /* The prepared interval length and expected buffer size
+ * is not possible to stream with the currently configured
+ * isoc bandwidth. Fallback to the maximum.
+ */
+ req_size = max_req_size;
+ }
+ video->req_size = req_size;
+
+ /* We need to compensate the amount of requests to be
+ * allocated with the maximum amount of zero length requests.
+ * Since it is possible that hw_submit will initially
+ * enqueue some zero length requests and we then will not be
+ * able to fully encode one frame.
+ */
+ video->uvc_num_requests = nreq + UVCG_REQ_MAX_ZERO_COUNT;
+ video->reqs_per_frame = nreq;
+}
+
static int
uvc_video_alloc_requests(struct uvc_video *video)
{
struct uvc_request *ureq;
- unsigned int req_size;
unsigned int i;
int ret = -ENOMEM;
- BUG_ON(video->req_size);
-
- req_size = video->ep->maxpacket
- * max_t(unsigned int, video->ep->maxburst, 1)
- * (video->ep->mult);
+ /*
+ * calculate in uvc_video_prep_requests
+ * - video->uvc_num_requests
+ * - video->req_size
+ */
+ uvc_video_prep_requests(video);
for (i = 0; i < video->uvc_num_requests; i++) {
ureq = kzalloc(sizeof(struct uvc_request), GFP_KERNEL);
@@ -523,7 +566,7 @@ uvc_video_alloc_requests(struct uvc_video *video)
list_add_tail(&ureq->list, &video->ureqs);
- ureq->req_buffer = kmalloc(req_size, GFP_KERNEL);
+ ureq->req_buffer = kmalloc(video->req_size, GFP_KERNEL);
if (ureq->req_buffer == NULL)
goto error;
@@ -541,12 +584,10 @@ uvc_video_alloc_requests(struct uvc_video *video)
list_add_tail(&ureq->req->list, &video->req_free);
/* req_size/PAGE_SIZE + 1 for overruns and + 1 for header */
sg_alloc_table(&ureq->sgt,
- DIV_ROUND_UP(req_size - UVCG_REQUEST_HEADER_LEN,
+ DIV_ROUND_UP(video->req_size - UVCG_REQUEST_HEADER_LEN,
PAGE_SIZE) + 2, GFP_KERNEL);
}
- video->req_size = req_size;
-
return 0;
error:
@@ -699,7 +740,6 @@ uvcg_video_disable(struct uvc_video *video)
INIT_LIST_HEAD(&video->ureqs);
INIT_LIST_HEAD(&video->req_free);
INIT_LIST_HEAD(&video->req_ready);
- video->req_size = 0;
spin_unlock_irqrestore(&video->req_lock, flags);
/*
@@ -752,7 +792,9 @@ int uvcg_video_enable(struct uvc_video *video)
video->req_int_count = 0;
- uvc_video_ep_queue_initial_requests(video);
+ atomic_set(&video->queued, 0);
+
+ kthread_queue_work(video->kworker, &video->hw_submit);
queue_work(video->async_wq, &video->pump);
return ret;
@@ -775,12 +817,24 @@ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc)
if (!video->async_wq)
return -EINVAL;
+ /* Allocate a kthread for asynchronous hw submit handler. */
+ video->kworker = kthread_create_worker(0, "UVCG");
+ if (IS_ERR(video->kworker)) {
+ uvcg_err(&video->uvc->func, "failed to create UVCG kworker\n");
+ return PTR_ERR(video->kworker);
+ }
+
+ kthread_init_work(&video->hw_submit, uvcg_video_hw_submit);
+
+ sched_set_fifo(video->kworker->task);
+
video->uvc = uvc;
video->fcc = V4L2_PIX_FMT_YUYV;
video->bpp = 16;
video->width = 320;
video->height = 240;
video->imagesize = 320 * 240 * 2;
+ video->interval = 666666;
/* Initialize the video buffers queue. */
uvcg_queue_init(&video->queue, uvc->v4l2_dev.dev->parent,
diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c
index 4ca67b2f8f24..3684546e8801 100644
--- a/drivers/usb/gadget/legacy/hid.c
+++ b/drivers/usb/gadget/legacy/hid.c
@@ -261,7 +261,7 @@ static struct usb_composite_driver hidg_driver = {
};
static struct platform_driver hidg_plat_driver = {
- .remove_new = hidg_plat_driver_remove,
+ .remove = hidg_plat_driver_remove,
.driver = {
.name = "hidg",
},
diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c
index 112fd18d8c99..20165e1582d9 100644
--- a/drivers/usb/gadget/legacy/raw_gadget.c
+++ b/drivers/usb/gadget/legacy/raw_gadget.c
@@ -782,7 +782,7 @@ static int raw_ioctl_ep0_read(struct raw_dev *dev, unsigned long value)
if (ret < 0)
goto free;
- length = min(io.length, (unsigned int)ret);
+ length = min_t(unsigned int, io.length, ret);
if (copy_to_user((void __user *)(value + sizeof(io)), data, length))
ret = -EFAULT;
else
@@ -1168,7 +1168,7 @@ static int raw_ioctl_ep_read(struct raw_dev *dev, unsigned long value)
if (ret < 0)
goto free;
- length = min(io.length, (unsigned int)ret);
+ length = min_t(unsigned int, io.length, ret);
if (copy_to_user((void __user *)(value + sizeof(io)), data, length))
ret = -EFAULT;
else
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c
index f60a019bb173..f2685f89b3e5 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/core.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c
@@ -428,7 +428,7 @@ MODULE_DEVICE_TABLE(of, ast_vhub_dt_ids);
static struct platform_driver ast_vhub_driver = {
.probe = ast_vhub_probe,
- .remove_new = ast_vhub_remove,
+ .remove = ast_vhub_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = ast_vhub_dt_ids,
diff --git a/drivers/usb/gadget/udc/aspeed_udc.c b/drivers/usb/gadget/udc/aspeed_udc.c
index f4781e611aaa..353bfb1ff0a1 100644
--- a/drivers/usb/gadget/udc/aspeed_udc.c
+++ b/drivers/usb/gadget/udc/aspeed_udc.c
@@ -156,7 +156,7 @@
#define AST_EP_DMA_DESC_PID_DATA1 (2 << 14)
#define AST_EP_DMA_DESC_PID_MDATA (3 << 14)
#define EP_DESC1_IN_LEN(x) ((x) & 0x1fff)
-#define AST_EP_DMA_DESC_MAX_LEN (7680) /* Max packet length for trasmit in 1 desc */
+#define AST_EP_DMA_DESC_MAX_LEN (7680) /* Max packet length for transmit in 1 desc */
struct ast_udc_request {
struct usb_request req;
@@ -1590,7 +1590,7 @@ MODULE_DEVICE_TABLE(of, ast_udc_of_dt_ids);
static struct platform_driver ast_udc_driver = {
.probe = ast_udc_probe,
- .remove_new = ast_udc_remove,
+ .remove = ast_udc_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = ast_udc_of_dt_ids,
diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c
index e3bf17a98b38..e3af4ec3794e 100644
--- a/drivers/usb/gadget/udc/at91_udc.c
+++ b/drivers/usb/gadget/udc/at91_udc.c
@@ -2002,7 +2002,7 @@ static int at91udc_resume(struct platform_device *pdev)
static struct platform_driver at91_udc_driver = {
.probe = at91udc_probe,
- .remove_new = at91udc_remove,
+ .remove = at91udc_remove,
.shutdown = at91udc_shutdown,
.suspend = at91udc_suspend,
.resume = at91udc_resume,
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index 4928eba19327..0c6f2ad81d37 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -2444,7 +2444,7 @@ static SIMPLE_DEV_PM_OPS(usba_udc_pm_ops, usba_udc_suspend, usba_udc_resume);
static struct platform_driver udc_driver = {
.probe = usba_udc_probe,
- .remove_new = usba_udc_remove,
+ .remove = usba_udc_remove,
.driver = {
.name = "atmel_usba_udc",
.pm = &usba_udc_pm_ops,
diff --git a/drivers/usb/gadget/udc/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c
index da7011d906e0..502612a5650e 100644
--- a/drivers/usb/gadget/udc/bcm63xx_udc.c
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
@@ -2367,7 +2367,7 @@ static void bcm63xx_udc_remove(struct platform_device *pdev)
static struct platform_driver bcm63xx_udc_driver = {
.probe = bcm63xx_udc_probe,
- .remove_new = bcm63xx_udc_remove,
+ .remove = bcm63xx_udc_remove,
.driver = {
.name = DRV_MODULE_NAME,
},
diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c
index 5149e2b7f050..5c3d8b64c0e7 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_core.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_core.c
@@ -648,7 +648,7 @@ static struct platform_driver bdc_driver = {
.of_match_table = bdc_of_match,
},
.probe = bdc_probe,
- .remove_new = bdc_remove,
+ .remove = bdc_remove,
};
module_platform_driver(bdc_driver);
diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-pci.c b/drivers/usb/gadget/udc/cdns2/cdns2-pci.c
index b1a8f772467c..e589593b4cbf 100644
--- a/drivers/usb/gadget/udc/cdns2/cdns2-pci.c
+++ b/drivers/usb/gadget/udc/cdns2/cdns2-pci.c
@@ -15,7 +15,6 @@
#include "cdns2-gadget.h"
#define PCI_DRIVER_NAME "cdns-pci-usbhs"
-#define PCI_DEVICE_ID_CDNS_USB2 0x0120
#define PCI_BAR_DEV 0
#define PCI_DEV_FN_DEVICE 0
@@ -113,7 +112,7 @@ static const struct dev_pm_ops cdns2_pci_pm_ops = {
};
static const struct pci_device_id cdns2_pci_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USB2),
+ { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USB),
.class = PCI_CLASS_SERIAL_USB_DEVICE },
{ 0, }
};
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index 081ac7683c0b..a7e8fa45776b 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -80,7 +80,7 @@ module_param_named(num, mod_data.num, uint, S_IRUGO);
MODULE_PARM_DESC(num, "number of emulated controllers");
/*-------------------------------------------------------------------------*/
-/* gadget side driver data structres */
+/* gadget side driver data structures */
struct dummy_ep {
struct list_head queue;
unsigned long last_io; /* jiffies timestamp */
@@ -1152,7 +1152,7 @@ static int dummy_udc_resume(struct platform_device *pdev)
static struct platform_driver dummy_udc_driver = {
.probe = dummy_udc_probe,
- .remove_new = dummy_udc_remove,
+ .remove = dummy_udc_remove,
.suspend = dummy_udc_suspend,
.resume = dummy_udc_resume,
.driver = {
@@ -2769,7 +2769,7 @@ static int dummy_hcd_resume(struct platform_device *pdev)
static struct platform_driver dummy_hcd_driver = {
.probe = dummy_hcd_probe,
- .remove_new = dummy_hcd_remove,
+ .remove = dummy_hcd_remove,
.suspend = dummy_hcd_suspend,
.resume = dummy_hcd_resume,
.driver = {
diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
index 4e88681a79b6..aacfde06387c 100644
--- a/drivers/usb/gadget/udc/fsl_qe_udc.c
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -511,7 +511,7 @@ static int qe_ep_register_init(struct qe_udc *udc, unsigned char pipe_num)
out_8(&epparam->tbmr, rtfcr);
tmp = (u16)(ep->ep.maxpacket + USB_CRC_SIZE);
- /* MRBLR must be divisble by 4 */
+ /* MRBLR must be divisible by 4 */
tmp = (u16)(((tmp >> 2) << 2) + 4);
out_be16(&epparam->mrblr, tmp);
@@ -1413,7 +1413,7 @@ static int ep_txframe_handle(struct qe_ep *ep)
return 0;
}
-/* confirm the already trainsmited bd */
+/* confirm the already transmitted bd */
static int qe_ep_txconf(struct qe_ep *ep)
{
struct qe_bd __iomem *bd;
@@ -2196,7 +2196,7 @@ static int tx_irq(struct qe_udc *udc)
}
-/* setup packect's rx is handle in the function too */
+/* setup packet's rx is handle in the function too */
static void rx_irq(struct qe_udc *udc)
{
struct qe_ep *ep;
@@ -2704,7 +2704,7 @@ static struct platform_driver udc_driver = {
.of_match_table = qe_udc_match,
},
.probe = qe_udc_probe,
- .remove_new = qe_udc_remove,
+ .remove = qe_udc_remove,
#ifdef CONFIG_PM
.suspend = qe_udc_suspend,
.resume = qe_udc_resume,
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
index 0cabd4eee6ac..8b7f7f961774 100644
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -2685,7 +2685,7 @@ MODULE_DEVICE_TABLE(of, fsl_udc_dt_ids);
static struct platform_driver udc_driver = {
.probe = fsl_udc_probe,
- .remove_new = fsl_udc_remove,
+ .remove = fsl_udc_remove,
.id_table = fsl_udc_devtype,
/* these suspend and resume are not usb suspend and resume */
.suspend = fsl_udc_suspend,
diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c
index 873265634ccc..5e94a99b3e53 100644
--- a/drivers/usb/gadget/udc/fusb300_udc.c
+++ b/drivers/usb/gadget/udc/fusb300_udc.c
@@ -1297,7 +1297,7 @@ static void init_controller(struct fusb300 *fusb300)
reg |= val;
iowrite32(reg, fusb300->reg + FUSB300_OFFSET_HSCR);
- /*set u1 u2 timmer*/
+ /*set u1 u2 timer*/
fusb300_set_u2_timeout(fusb300, 0xff);
fusb300_set_u1_timeout(fusb300, 0xff);
@@ -1507,7 +1507,7 @@ clean_up:
static struct platform_driver fusb300_driver = {
.probe = fusb300_probe,
- .remove_new = fusb300_remove,
+ .remove = fusb300_remove,
.driver = {
.name = udc_name,
},
diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c
index fb901be5dac1..bf5b3c964c18 100644
--- a/drivers/usb/gadget/udc/gr_udc.c
+++ b/drivers/usb/gadget/udc/gr_udc.c
@@ -2249,7 +2249,7 @@ static struct platform_driver gr_driver = {
.of_match_table = gr_match,
},
.probe = gr_probe,
- .remove_new = gr_remove,
+ .remove = gr_remove,
};
module_platform_driver(gr_driver);
diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index 3bfd889ed56a..89d6daf2bda7 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -3249,7 +3249,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_udc_of_match);
static struct platform_driver lpc32xx_udc_driver = {
.probe = lpc32xx_udc_probe,
- .remove_new = lpc32xx_udc_remove,
+ .remove = lpc32xx_udc_remove,
.shutdown = lpc32xx_udc_shutdown,
.suspend = lpc32xx_udc_suspend,
.resume = lpc32xx_udc_resume,
diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c
index bfaa5291e6c8..a938b2af0944 100644
--- a/drivers/usb/gadget/udc/m66592-udc.c
+++ b/drivers/usb/gadget/udc/m66592-udc.c
@@ -1688,7 +1688,7 @@ clean_up:
/*-------------------------------------------------------------------------*/
static struct platform_driver m66592_driver = {
.probe = m66592_probe,
- .remove_new = m66592_remove,
+ .remove = m66592_remove,
.driver = {
.name = udc_name,
},
diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c
index e1dd5cf25d08..062f43e146aa 100644
--- a/drivers/usb/gadget/udc/mv_u3d_core.c
+++ b/drivers/usb/gadget/udc/mv_u3d_core.c
@@ -2047,7 +2047,7 @@ static void mv_u3d_shutdown(struct platform_device *dev)
static struct platform_driver mv_u3d_driver = {
.probe = mv_u3d_probe,
- .remove_new = mv_u3d_remove,
+ .remove = mv_u3d_remove,
.shutdown = mv_u3d_shutdown,
.driver = {
.name = "mv-u3d",
diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c
index 71012b282891..ff103e6b3048 100644
--- a/drivers/usb/gadget/udc/mv_udc_core.c
+++ b/drivers/usb/gadget/udc/mv_udc_core.c
@@ -2409,7 +2409,7 @@ static void mv_udc_shutdown(struct platform_device *pdev)
static struct platform_driver udc_driver = {
.probe = mv_udc_probe,
- .remove_new = mv_udc_remove,
+ .remove = mv_udc_remove,
.shutdown = mv_udc_shutdown,
.driver = {
.name = "mv-udc",
diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c
index 9230db57dab7..7ecddbf5c90d 100644
--- a/drivers/usb/gadget/udc/net2272.c
+++ b/drivers/usb/gadget/udc/net2272.c
@@ -2097,7 +2097,7 @@ static irqreturn_t net2272_irq(int irq, void *_dev)
}
/* check dma interrupts */
#endif
- /* Platform/devcice interrupt handler */
+ /* Platform/device interrupt handler */
#if !defined(PLX_PCI_RDK)
net2272_handle_stat1_irqs(dev, net2272_read(dev, IRQSTAT1));
net2272_handle_stat0_irqs(dev, net2272_read(dev, IRQSTAT0));
@@ -2685,7 +2685,7 @@ net2272_plat_remove(struct platform_device *pdev)
static struct platform_driver net2272_plat_driver = {
.probe = net2272_plat_probe,
- .remove_new = net2272_plat_remove,
+ .remove = net2272_plat_remove,
.driver = {
.name = driver_name,
},
diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c
index 61a45e4657d5..698463bf697b 100644
--- a/drivers/usb/gadget/udc/omap_udc.c
+++ b/drivers/usb/gadget/udc/omap_udc.c
@@ -576,13 +576,13 @@ static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status)
static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
{
- unsigned packets = req->req.length - req->req.actual;
+ unsigned int packets = req->req.length - req->req.actual;
int dma_trigger = 0;
u16 w;
/* set up this DMA transfer, enable the fifo, start */
packets /= ep->ep.maxpacket;
- packets = min(packets, (unsigned)UDC_RXN_TC + 1);
+ packets = min_t(unsigned int, packets, UDC_RXN_TC + 1);
req->dma_bytes = packets * ep->ep.maxpacket;
omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
ep->ep.maxpacket >> 1, packets,
@@ -2980,7 +2980,7 @@ static int omap_udc_resume(struct platform_device *dev)
static struct platform_driver udc_driver = {
.probe = omap_udc_probe,
- .remove_new = omap_udc_remove,
+ .remove = omap_udc_remove,
.suspend = omap_udc_suspend,
.resume = omap_udc_resume,
.driver = {
diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c
index 7c96fc9f680f..1e9998024aaa 100644
--- a/drivers/usb/gadget/udc/pxa25x_udc.c
+++ b/drivers/usb/gadget/udc/pxa25x_udc.c
@@ -2474,7 +2474,7 @@ static int pxa25x_udc_resume(struct platform_device *dev)
static struct platform_driver udc_driver = {
.shutdown = pxa25x_udc_shutdown,
.probe = pxa25x_udc_probe,
- .remove_new = pxa25x_udc_remove,
+ .remove = pxa25x_udc_remove,
.suspend = pxa25x_udc_suspend,
.resume = pxa25x_udc_resume,
.driver = {
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c
index ea79f85f8e0b..f9a55d4f189f 100644
--- a/drivers/usb/gadget/udc/pxa27x_udc.c
+++ b/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -2539,7 +2539,7 @@ static struct platform_driver udc_driver = {
.of_match_table = of_match_ptr(udc_pxa_dt_ids),
},
.probe = pxa_udc_probe,
- .remove_new = pxa_udc_remove,
+ .remove = pxa_udc_remove,
.shutdown = pxa_udc_shutdown,
#ifdef CONFIG_PM
.suspend = pxa_udc_suspend,
diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c
index db4a10a979f9..ff6f846b1d41 100644
--- a/drivers/usb/gadget/udc/r8a66597-udc.c
+++ b/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1965,7 +1965,7 @@ clean_up2:
/*-------------------------------------------------------------------------*/
static struct platform_driver r8a66597_driver = {
.probe = r8a66597_probe,
- .remove_new = r8a66597_remove,
+ .remove = r8a66597_remove,
.driver = {
.name = udc_name,
},
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index 3b01734ce1b7..fce5c41d9f29 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -3013,7 +3013,7 @@ static SIMPLE_DEV_PM_OPS(renesas_usb3_pm_ops, renesas_usb3_suspend,
static struct platform_driver renesas_usb3_driver = {
.probe = renesas_usb3_probe,
- .remove_new = renesas_usb3_remove,
+ .remove = renesas_usb3_remove,
.driver = {
.name = udc_name,
.pm = &renesas_usb3_pm_ops,
diff --git a/drivers/usb/gadget/udc/renesas_usbf.c b/drivers/usb/gadget/udc/renesas_usbf.c
index 657f265ac7cc..14f4b2cf05a4 100644
--- a/drivers/usb/gadget/udc/renesas_usbf.c
+++ b/drivers/usb/gadget/udc/renesas_usbf.c
@@ -2482,7 +2482,7 @@ static int usbf_handle_ep0_setup(struct usbf_ep *ep0)
ep0->delayed_status = 0;
if ((crq.ctrlreq.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD) {
- /* This is not a USB standard request -> delelate */
+ /* This is not a USB standard request -> delegate */
goto delegate;
}
@@ -3381,7 +3381,7 @@ static struct platform_driver udc_driver = {
.of_match_table = usbf_match,
},
.probe = usbf_probe,
- .remove_new = usbf_remove,
+ .remove = usbf_remove,
};
module_platform_driver(udc_driver);
diff --git a/drivers/usb/gadget/udc/rzv2m_usb3drd.c b/drivers/usb/gadget/udc/rzv2m_usb3drd.c
index 36f4ff00d22f..4692eae89f44 100644
--- a/drivers/usb/gadget/udc/rzv2m_usb3drd.c
+++ b/drivers/usb/gadget/udc/rzv2m_usb3drd.c
@@ -127,7 +127,7 @@ static struct platform_driver rzv2m_usb3drd_driver = {
.of_match_table = rzv2m_usb3drd_of_match,
},
.probe = rzv2m_usb3drd_probe,
- .remove_new = rzv2m_usb3drd_remove,
+ .remove = rzv2m_usb3drd_remove,
};
module_platform_driver(rzv2m_usb3drd_driver);
diff --git a/drivers/usb/gadget/udc/snps_udc_core.c b/drivers/usb/gadget/udc/snps_udc_core.c
index cd89532adec2..1f8a99d2a643 100644
--- a/drivers/usb/gadget/udc/snps_udc_core.c
+++ b/drivers/usb/gadget/udc/snps_udc_core.c
@@ -2707,7 +2707,7 @@ static irqreturn_t udc_control_in_isr(struct udc *dev)
/* write fifo */
udc_txfifo_write(ep, &req->req);
- /* lengh bytes transferred */
+ /* length bytes transferred */
len = req->req.length - req->req.actual;
if (len > ep->ep.maxpacket)
len = ep->ep.maxpacket;
diff --git a/drivers/usb/gadget/udc/snps_udc_plat.c b/drivers/usb/gadget/udc/snps_udc_plat.c
index ba5a06690507..db842a6de643 100644
--- a/drivers/usb/gadget/udc/snps_udc_plat.c
+++ b/drivers/usb/gadget/udc/snps_udc_plat.c
@@ -309,7 +309,7 @@ MODULE_DEVICE_TABLE(of, of_udc_match);
static struct platform_driver udc_plat_driver = {
.probe = udc_plat_probe,
- .remove_new = udc_plat_remove,
+ .remove = udc_plat_remove,
.driver = {
.name = "snps-udc-plat",
.of_match_table = of_udc_match,
diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
index 7aa46d426f31..c7fdbc55fb0b 100644
--- a/drivers/usb/gadget/udc/tegra-xudc.c
+++ b/drivers/usb/gadget/udc/tegra-xudc.c
@@ -4071,7 +4071,7 @@ static const struct dev_pm_ops tegra_xudc_pm_ops = {
static struct platform_driver tegra_xudc_driver = {
.probe = tegra_xudc_probe,
- .remove_new = tegra_xudc_remove,
+ .remove = tegra_xudc_remove,
.driver = {
.name = "tegra-xudc",
.pm = &tegra_xudc_pm_ops,
diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c
index ebc45565c33e..ae2aeb271897 100644
--- a/drivers/usb/gadget/udc/udc-xilinx.c
+++ b/drivers/usb/gadget/udc/udc-xilinx.c
@@ -2258,7 +2258,7 @@ static struct platform_driver xudc_driver = {
.pm = &xudc_pm_ops,
},
.probe = xudc_probe,
- .remove_new = xudc_remove,
+ .remove = xudc_remove,
};
module_platform_driver(xudc_driver);
diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
index 75f6f99f8173..37a2f1b61cba 100644
--- a/drivers/usb/gadget/usbstring.c
+++ b/drivers/usb/gadget/usbstring.c
@@ -55,7 +55,7 @@ usb_gadget_get_string (const struct usb_gadget_strings *table, int id, u8 *buf)
return -EINVAL;
/* string descriptors have length, tag, then UTF16-LE text */
- len = min((size_t)USB_MAX_STRING_LEN, strlen(s->s));
+ len = min_t(size_t, USB_MAX_STRING_LEN, strlen(s->s));
len = utf8s_to_utf16s(s->s, len, UTF16_LITTLE_ENDIAN,
(wchar_t *) &buf[2], USB_MAX_STRING_LEN);
if (len < 0)
diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c
index 7558cc4d90cc..519386255886 100644
--- a/drivers/usb/host/bcma-hcd.c
+++ b/drivers/usb/host/bcma-hcd.c
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/usb/ehci_pdriver.h>
#include <linux/usb/ohci_pdriver.h>
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 6a6e1c510b28..65747270fd88 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -220,7 +220,7 @@ static SIMPLE_DEV_PM_OPS(ehci_atmel_pm_ops, ehci_atmel_drv_suspend,
static struct platform_driver ehci_atmel_driver = {
.probe = ehci_atmel_drv_probe,
- .remove_new = ehci_atmel_drv_remove,
+ .remove = ehci_atmel_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "atmel-ehci",
diff --git a/drivers/usb/host/ehci-brcm.c b/drivers/usb/host/ehci-brcm.c
index 68cad0620f1a..888e8f6670d2 100644
--- a/drivers/usb/host/ehci-brcm.c
+++ b/drivers/usb/host/ehci-brcm.c
@@ -250,7 +250,7 @@ MODULE_DEVICE_TABLE(of, brcm_ehci_of_match);
static struct platform_driver ehci_brcm_driver = {
.probe = ehci_brcm_probe,
- .remove_new = ehci_brcm_remove,
+ .remove = ehci_brcm_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ehci-brcm",
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index e3a961d3f5fc..d2a5bedf736a 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -288,7 +288,7 @@ MODULE_DEVICE_TABLE(of, exynos_ehci_match);
static struct platform_driver exynos_ehci_driver = {
.probe = exynos_ehci_probe,
- .remove_new = exynos_ehci_remove,
+ .remove = exynos_ehci_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "exynos-ehci",
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 5b1ce394a417..26f13278d4d6 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -706,7 +706,7 @@ static void fsl_ehci_drv_remove(struct platform_device *pdev)
static struct platform_driver ehci_fsl_driver = {
.probe = fsl_ehci_drv_probe,
- .remove_new = fsl_ehci_drv_remove,
+ .remove = fsl_ehci_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
index 14150e4d3382..bd9762eaa135 100644
--- a/drivers/usb/host/ehci-grlib.c
+++ b/drivers/usb/host/ehci-grlib.c
@@ -168,7 +168,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_grlib_of_match);
static struct platform_driver ehci_grlib_driver = {
.probe = ehci_hcd_grlib_probe,
- .remove_new = ehci_hcd_grlib_remove,
+ .remove = ehci_hcd_grlib_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "grlib-ehci",
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index cbc0b86fcc36..6de79ac5e6a4 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -547,7 +547,7 @@ static int ehci_init(struct usb_hcd *hcd)
* make problems: throughput reduction (!), data errors...
*/
if (park) {
- park = min(park, (unsigned) 3);
+ park = min_t(unsigned int, park, 3);
temp |= CMD_PARK;
temp |= park << 8;
}
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index 2f1fc7eb8b72..cbabbe107172 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -279,7 +279,7 @@ static const struct of_device_id ehci_mv_dt_ids[] = {
static struct platform_driver ehci_mv_driver = {
.probe = mv_ehci_probe,
- .remove_new = mv_ehci_remove,
+ .remove = mv_ehci_remove,
.shutdown = mv_ehci_shutdown,
.driver = {
.name = "mv-ehci",
diff --git a/drivers/usb/host/ehci-npcm7xx.c b/drivers/usb/host/ehci-npcm7xx.c
index 3d3317a1a0b3..f1c7034c1e80 100644
--- a/drivers/usb/host/ehci-npcm7xx.c
+++ b/drivers/usb/host/ehci-npcm7xx.c
@@ -122,7 +122,7 @@ MODULE_DEVICE_TABLE(of, npcm7xx_ehci_id_table);
static struct platform_driver npcm7xx_ehci_hcd_driver = {
.probe = npcm7xx_ehci_hcd_drv_probe,
- .remove_new = npcm7xx_ehci_hcd_drv_remove,
+ .remove = npcm7xx_ehci_hcd_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "npcm7xx-ehci",
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index b24f371a46f3..db4a1acb27da 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -264,7 +264,7 @@ MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids);
static struct platform_driver ehci_hcd_omap_driver = {
.probe = ehci_hcd_omap_probe,
- .remove_new = ehci_hcd_omap_remove,
+ .remove = ehci_hcd_omap_remove,
.shutdown = usb_hcd_platform_shutdown,
/*.suspend = ehci_hcd_omap_suspend, */
/*.resume = ehci_hcd_omap_resume, */
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index ad145a54ca74..34abff8669f8 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -352,7 +352,7 @@ MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids);
static struct platform_driver ehci_orion_driver = {
.probe = ehci_orion_drv_probe,
- .remove_new = ehci_orion_drv_remove,
+ .remove = ehci_orion_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "orion-ehci",
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 98b073185e1c..cdf41886e8ca 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -508,7 +508,7 @@ static SIMPLE_DEV_PM_OPS(ehci_platform_pm_ops, ehci_platform_suspend,
static struct platform_driver ehci_platform_driver = {
.id_table = ehci_platform_table,
.probe = ehci_platform_probe,
- .remove_new = ehci_platform_remove,
+ .remove = ehci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ehci-platform",
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index 7fd83e806ae4..8063b9d3aebd 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -230,7 +230,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
static struct platform_driver ehci_hcd_ppc_of_driver = {
.probe = ehci_hcd_ppc_of_probe,
- .remove_new = ehci_hcd_ppc_of_remove,
+ .remove = ehci_hcd_ppc_of_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ppc-of-ehci",
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
index d31d9506e41a..5d0d972fb7b1 100644
--- a/drivers/usb/host/ehci-sh.c
+++ b/drivers/usb/host/ehci-sh.c
@@ -169,7 +169,7 @@ static void ehci_hcd_sh_shutdown(struct platform_device *pdev)
static struct platform_driver ehci_hcd_sh_driver = {
.probe = ehci_hcd_sh_probe,
- .remove_new = ehci_hcd_sh_remove,
+ .remove = ehci_hcd_sh_remove,
.shutdown = ehci_hcd_sh_shutdown,
.driver = {
.name = "sh_ehci",
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index d0e94e4c9fe2..e96710192d6b 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -105,7 +105,9 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
/* registers start at offset 0x0 */
hcd_to_ehci(hcd)->caps = hcd->regs;
- clk_prepare_enable(sehci->clk);
+ retval = clk_prepare_enable(sehci->clk);
+ if (retval)
+ goto err_put_hcd;
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (retval)
goto err_stop_ehci;
@@ -130,8 +132,7 @@ static void spear_ehci_hcd_drv_remove(struct platform_device *pdev)
usb_remove_hcd(hcd);
- if (sehci->clk)
- clk_disable_unprepare(sehci->clk);
+ clk_disable_unprepare(sehci->clk);
usb_put_hcd(hcd);
}
@@ -143,7 +144,7 @@ MODULE_DEVICE_TABLE(of, spear_ehci_id_table);
static struct platform_driver spear_ehci_hcd_driver = {
.probe = spear_ehci_hcd_drv_probe,
- .remove_new = spear_ehci_hcd_drv_remove,
+ .remove = spear_ehci_hcd_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "spear-ehci",
diff --git a/drivers/usb/host/ehci-st.c b/drivers/usb/host/ehci-st.c
index 2dbb0d86daaa..58867d816af7 100644
--- a/drivers/usb/host/ehci-st.c
+++ b/drivers/usb/host/ehci-st.c
@@ -320,7 +320,7 @@ MODULE_DEVICE_TABLE(of, st_ehci_ids);
static struct platform_driver ehci_platform_driver = {
.probe = st_ehci_platform_probe,
- .remove_new = st_ehci_platform_remove,
+ .remove = st_ehci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "st-ehci",
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index a2112c28f631..1d16cfefabd7 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -220,7 +220,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_xilinx_of_match);
static struct platform_driver ehci_hcd_xilinx_of_driver = {
.probe = ehci_hcd_xilinx_of_probe,
- .remove_new = ehci_hcd_xilinx_of_remove,
+ .remove = ehci_hcd_xilinx_of_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "xilinx-of-ehci",
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
index 9a1b5224f239..22a0942f0bce 100644
--- a/drivers/usb/host/fhci-hcd.c
+++ b/drivers/usb/host/fhci-hcd.c
@@ -791,7 +791,7 @@ static struct platform_driver of_fhci_driver = {
.of_match_table = of_fhci_match,
},
.probe = of_fhci_probe,
- .remove_new = of_fhci_remove,
+ .remove = of_fhci_remove,
};
module_platform_driver(of_fhci_driver);
diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c
index a45ede80edfc..c3acd410ce94 100644
--- a/drivers/usb/host/fhci-sched.c
+++ b/drivers/usb/host/fhci-sched.c
@@ -158,7 +158,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td)
struct packet *pkt;
u8 *data = NULL;
- /* calcalate data address,len and toggle and then add the transaction */
+ /* calculate data address,len and toggle and then add the transaction */
if (td->toggle == USB_TD_TOGGLE_CARRY)
td->toggle = ed->toggle_carry;
@@ -679,7 +679,7 @@ static void process_done_list(unsigned long data)
DECLARE_TASKLET_OLD(fhci_tasklet, process_done_list);
-/* transfer complted callback */
+/* transfer completed callback */
u32 fhci_transfer_confirm_callback(struct fhci_hcd *fhci)
{
if (!fhci->process_done_task->state)
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 6cdc3d805c32..4e67b9471986 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -362,7 +362,7 @@ static struct platform_driver fsl_usb2_mph_dr_driver = {
.of_match_table = fsl_usb2_mph_dr_of_match,
},
.probe = fsl_usb2_mph_dr_of_probe,
- .remove_new = fsl_usb2_mph_dr_of_remove,
+ .remove = fsl_usb2_mph_dr_of_remove,
};
module_platform_driver(fsl_usb2_mph_dr_driver);
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index a82d8926e922..71c22c4bd163 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1684,7 +1684,7 @@ MODULE_ALIAS("platform:isp116x-hcd");
static struct platform_driver isp116x_driver = {
.probe = isp116x_probe,
- .remove_new = isp116x_remove,
+ .remove = isp116x_remove,
.suspend = isp116x_suspend,
.resume = isp116x_resume,
.driver = {
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 31059c8f94e6..2d3a082cb52f 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2757,7 +2757,7 @@ static int isp1362_resume(struct platform_device *pdev)
static struct platform_driver isp1362_driver = {
.probe = isp1362_probe,
- .remove_new = isp1362_remove,
+ .remove = isp1362_remove,
.suspend = isp1362_suspend,
.resume = isp1362_resume,
diff --git a/drivers/usb/host/octeon-hcd.c b/drivers/usb/host/octeon-hcd.c
index 19d5777f5db2..361d33b0c4d2 100644
--- a/drivers/usb/host/octeon-hcd.c
+++ b/drivers/usb/host/octeon-hcd.c
@@ -3346,7 +3346,7 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break;
case USB_PORT_FEAT_INDICATOR:
dev_dbg(dev, " INDICATOR\n");
- /* Port inidicator not supported */
+ /* Port indicator not supported */
break;
case USB_PORT_FEAT_C_CONNECTION:
dev_dbg(dev, " C_CONNECTION\n");
@@ -3711,8 +3711,8 @@ static struct platform_driver octeon_usb_driver = {
.name = "octeon-hcd",
.of_match_table = octeon_usb_match,
},
- .probe = octeon_usb_probe,
- .remove_new = octeon_usb_remove,
+ .probe = octeon_usb_probe,
+ .remove = octeon_usb_remove,
};
static int __init octeon_usb_driver_init(void)
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index f691cd98a574..5df793dcb25d 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -685,7 +685,7 @@ static SIMPLE_DEV_PM_OPS(ohci_hcd_at91_pm_ops, ohci_hcd_at91_drv_suspend,
static struct platform_driver ohci_hcd_at91_driver = {
.probe = ohci_hcd_at91_drv_probe,
- .remove_new = ohci_hcd_at91_drv_remove,
+ .remove = ohci_hcd_at91_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "at91_ohci",
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index d2b67da76762..3c5ca2d7c92e 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -531,7 +531,7 @@ static const struct ohci_driver_overrides da8xx_overrides __initconst = {
*/
static struct platform_driver ohci_hcd_da8xx_driver = {
.probe = ohci_da8xx_probe,
- .remove_new = ohci_da8xx_remove,
+ .remove = ohci_da8xx_remove,
.shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_da8xx_suspend,
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 1379e03644b2..cc5cb0900988 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -262,7 +262,7 @@ MODULE_DEVICE_TABLE(of, exynos_ohci_match);
static struct platform_driver exynos_ohci_driver = {
.probe = exynos_ohci_probe,
- .remove_new = exynos_ohci_remove,
+ .remove = exynos_ohci_remove,
.shutdown = exynos_ohci_shutdown,
.driver = {
.name = "exynos-ohci",
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index 5b775e1ea527..24d5a1dc5056 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -254,7 +254,7 @@ static struct platform_driver ohci_hcd_nxp_driver = {
.of_match_table = of_match_ptr(ohci_hcd_nxp_match),
},
.probe = ohci_hcd_nxp_probe,
- .remove_new = ohci_hcd_nxp_remove,
+ .remove = ohci_hcd_nxp_remove,
};
static int __init ohci_nxp_init(void)
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 21a6f6c55e07..f6e56c4b9914 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -152,7 +152,7 @@ static int ohci_omap_reset(struct usb_hcd *hcd)
rh &= ~RH_A_NOCP;
- /* gpio9 for overcurrent detction */
+ /* gpio9 for overcurrent detection */
omap_cfg_reg(W8_1610_GPIO9);
/* for paranoia's sake: disable USB.PUEN */
@@ -390,7 +390,7 @@ static int ohci_omap_resume(struct platform_device *dev)
*/
static struct platform_driver ohci_hcd_omap_driver = {
.probe = ohci_hcd_omap_probe,
- .remove_new = ohci_hcd_omap_remove,
+ .remove = ohci_hcd_omap_remove,
.shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_omap_suspend,
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index 4a75507325dd..f47ae12cde6a 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -344,7 +344,7 @@ static const struct dev_pm_ops ohci_platform_pm_ops = {
static struct platform_driver ohci_platform_driver = {
.id_table = ohci_platform_table,
.probe = ohci_platform_probe,
- .remove_new = ohci_platform_remove,
+ .remove = ohci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ohci-platform",
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index a6be061f8653..acd0a0e398a4 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -219,7 +219,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match);
static struct platform_driver ohci_hcd_ppc_of_driver = {
.probe = ohci_hcd_ppc_of_probe,
- .remove_new = ohci_hcd_ppc_of_remove,
+ .remove = ohci_hcd_ppc_of_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ppc-of-ohci",
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 3348c25ddb18..45d026e85168 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -569,7 +569,7 @@ static const struct dev_pm_ops ohci_hcd_pxa27x_pm_ops = {
static struct platform_driver ohci_hcd_pxa27x_driver = {
.probe = ohci_hcd_pxa27x_probe,
- .remove_new = ohci_hcd_pxa27x_remove,
+ .remove = ohci_hcd_pxa27x_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "pxa27x-ohci",
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index c5c9b4cbcb9a..66d970854357 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -457,7 +457,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_s3c2410_dt_ids);
static struct platform_driver ohci_hcd_s3c2410_driver = {
.probe = ohci_hcd_s3c2410_probe,
- .remove_new = ohci_hcd_s3c2410_remove,
+ .remove = ohci_hcd_s3c2410_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "s3c2410-ohci",
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index 4b39e9d6f33a..843a5378764e 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -252,7 +252,7 @@ static int ohci_sm501_resume(struct platform_device *pdev)
*/
static struct platform_driver ohci_hcd_sm501_driver = {
.probe = ohci_hcd_sm501_drv_probe,
- .remove_new = ohci_hcd_sm501_drv_remove,
+ .remove = ohci_hcd_sm501_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.suspend = ohci_sm501_suspend,
.resume = ohci_sm501_resume,
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index 993f347c5c28..d7131e5a4477 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -157,7 +157,7 @@ MODULE_DEVICE_TABLE(of, spear_ohci_id_table);
/* Driver definition to register with the platform bus */
static struct platform_driver spear_ohci_hcd_driver = {
.probe = spear_ohci_hcd_drv_probe,
- .remove_new = spear_ohci_hcd_drv_remove,
+ .remove = spear_ohci_hcd_drv_remove,
#ifdef CONFIG_PM
.suspend = spear_ohci_hcd_drv_suspend,
.resume = spear_ohci_hcd_drv_resume,
diff --git a/drivers/usb/host/ohci-st.c b/drivers/usb/host/ohci-st.c
index 214342013f7e..d1656fce5400 100644
--- a/drivers/usb/host/ohci-st.c
+++ b/drivers/usb/host/ohci-st.c
@@ -298,7 +298,7 @@ MODULE_DEVICE_TABLE(of, st_ohci_platform_ids);
static struct platform_driver ohci_platform_driver = {
.probe = st_ohci_platform_probe,
- .remove_new = st_ohci_platform_remove,
+ .remove = st_ohci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "st-ohci",
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index ca3859463ba1..a6c20facf945 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -885,7 +885,7 @@ static int oxu_buf_alloc(struct oxu_hcd *oxu, struct ehci_qtd *qtd, int len)
int a_blocks; /* blocks allocated */
int i, j;
- /* Don't allocte bigger than supported */
+ /* Don't allocate bigger than supported */
if (len > BUFFER_SIZE * BUFFER_NUM) {
oxu_err(oxu, "buffer too big (%d)\n", len);
return -ENOMEM;
@@ -902,7 +902,7 @@ static int oxu_buf_alloc(struct oxu_hcd *oxu, struct ehci_qtd *qtd, int len)
/* Find a suitable available data buffer */
for (i = 0; i < BUFFER_NUM;
- i += max(a_blocks, (int)oxu->db_used[i])) {
+ i += max_t(int, a_blocks, oxu->db_used[i])) {
/* Check all the required blocks are available */
for (j = 0; j < a_blocks; j++)
@@ -3040,7 +3040,7 @@ static int oxu_hcd_init(struct usb_hcd *hcd)
* make problems: throughput reduction (!), data errors...
*/
if (park) {
- park = min(park, (unsigned) 3);
+ park = min_t(unsigned int, park, 3);
temp |= CMD_PARK;
temp |= park << 8;
}
@@ -4289,7 +4289,7 @@ static int oxu_drv_resume(struct device *dev)
static struct platform_driver oxu_driver = {
.probe = oxu_drv_probe,
- .remove_new = oxu_drv_remove,
+ .remove = oxu_drv_remove,
.shutdown = oxu_drv_shutdown,
.suspend = oxu_drv_suspend,
.resume = oxu_drv_resume,
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 6576515a29cd..a44992e2561b 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -759,7 +759,7 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
struct r8a66597_pipe_info *info = &pipe->info;
unsigned short mbw = mbw_value(r8a66597);
- /* pipe dma is only for external controlles */
+ /* pipe dma is only for external controllers */
if (r8a66597->pdata->on_chip)
return;
@@ -1336,7 +1336,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
buf = (void *)urb->transfer_buffer + urb->actual_length;
urb_len = urb->transfer_buffer_length - urb->actual_length;
}
- bufsize = min(urb_len, (int) td->maxpacket);
+ bufsize = min_t(int, urb_len, td->maxpacket);
if (rcv_len <= bufsize) {
size = rcv_len;
} else {
@@ -2510,7 +2510,7 @@ clean_up:
static struct platform_driver r8a66597_driver = {
.probe = r8a66597_probe,
- .remove_new = r8a66597_remove,
+ .remove = r8a66597_remove,
.driver = {
.name = hcd_name,
.pm = R8A66597_DEV_PM_OPS,
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 92f2d1238448..036f5fd6d159 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1784,7 +1784,7 @@ sl811h_resume(struct platform_device *dev)
/* this driver is exported so sl811_cs can depend on it */
struct platform_driver sl811h_driver = {
.probe = sl811h_probe,
- .remove_new = sl811h_remove,
+ .remove = sl811h_remove,
.suspend = sl811h_suspend,
.resume = sl811h_resume,
diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c
index cfebb833668e..8a1f6d1b5b56 100644
--- a/drivers/usb/host/uhci-grlib.c
+++ b/drivers/usb/host/uhci-grlib.c
@@ -184,7 +184,7 @@ MODULE_DEVICE_TABLE(of, uhci_hcd_grlib_of_match);
static struct platform_driver uhci_grlib_driver = {
.probe = uhci_hcd_grlib_probe,
- .remove_new = uhci_hcd_grlib_remove,
+ .remove = uhci_hcd_grlib_remove,
.shutdown = uhci_hcd_grlib_shutdown,
.driver = {
.name = "grlib-uhci",
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index 3dec5dd3a0d5..a7c934404ebc 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -184,7 +184,7 @@ MODULE_DEVICE_TABLE(of, platform_uhci_ids);
static struct platform_driver uhci_platform_driver = {
.probe = uhci_hcd_platform_probe,
- .remove_new = uhci_hcd_platform_remove,
+ .remove = uhci_hcd_platform_remove,
.shutdown = uhci_hcd_platform_shutdown,
.driver = {
.name = "platform-uhci",
diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c
index 241d7aa1fbc2..227e513867dd 100644
--- a/drivers/usb/host/xhci-dbgcap.c
+++ b/drivers/usb/host/xhci-dbgcap.c
@@ -248,8 +248,9 @@ xhci_dbc_queue_trb(struct xhci_ring *ring, u32 field1,
trb->generic.field[2] = cpu_to_le32(field3);
trb->generic.field[3] = cpu_to_le32(field4);
- trace_xhci_dbc_gadget_ep_queue(ring, &trb->generic);
-
+ trace_xhci_dbc_gadget_ep_queue(ring, &trb->generic,
+ xhci_trb_virt_to_dma(ring->enq_seg,
+ ring->enqueue));
ring->num_trbs_free--;
next = ++(ring->enqueue);
if (TRB_TYPE_LINK_LE32(next->link.control)) {
@@ -471,7 +472,7 @@ xhci_dbc_ring_alloc(struct device *dev, enum xhci_ring_type type, gfp_t flags)
trb->link.control = cpu_to_le32(LINK_TOGGLE | TRB_TYPE(TRB_LINK));
}
INIT_LIST_HEAD(&ring->td_list);
- xhci_initialize_ring_info(ring, 1);
+ xhci_initialize_ring_info(ring);
return ring;
dma_fail:
kfree(seg);
@@ -747,7 +748,7 @@ static void dbc_handle_xfer_event(struct xhci_dbc *dbc, union xhci_trb *event)
return;
}
- trace_xhci_dbc_handle_transfer(ring, &req->trb->generic);
+ trace_xhci_dbc_handle_transfer(ring, &req->trb->generic, req->trb_dma);
switch (comp_code) {
case COMP_SUCCESS:
@@ -898,7 +899,9 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc)
*/
rmb();
- trace_xhci_dbc_handle_event(dbc->ring_evt, &evt->generic);
+ trace_xhci_dbc_handle_event(dbc->ring_evt, &evt->generic,
+ xhci_trb_virt_to_dma(dbc->ring_evt->deq_seg,
+ dbc->ring_evt->dequeue));
switch (le32_to_cpu(evt->event_cmd.flags) & TRB_TYPE_BITMASK) {
case TRB_TYPE(TRB_PORT_STATUS):
diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c
index f8ba15e7c225..4f0c1b96e208 100644
--- a/drivers/usb/host/xhci-debugfs.c
+++ b/drivers/usb/host/xhci-debugfs.c
@@ -214,14 +214,11 @@ static void xhci_ring_dump_segment(struct seq_file *s,
static int xhci_ring_trb_show(struct seq_file *s, void *unused)
{
- int i;
struct xhci_ring *ring = *(struct xhci_ring **)s->private;
struct xhci_segment *seg = ring->first_seg;
- for (i = 0; i < ring->num_segs; i++) {
+ xhci_for_each_ring_seg(ring->first_seg, seg)
xhci_ring_dump_segment(s, seg);
- seg = seg->next;
- }
return 0;
}
@@ -291,12 +288,13 @@ static int xhci_endpoint_context_show(struct seq_file *s, void *unused)
for (ep_index = 0; ep_index < 31; ep_index++) {
ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
dma = dev->out_ctx->dma + (ep_index + 1) * CTX_SIZE(xhci->hcc_params);
- seq_printf(s, "%pad: %s\n", &dma,
+ seq_printf(s, "%pad: %s, virt_state:%#x\n", &dma,
xhci_decode_ep_context(str,
le32_to_cpu(ep_ctx->ep_info),
le32_to_cpu(ep_ctx->ep_info2),
le64_to_cpu(ep_ctx->deq),
- le32_to_cpu(ep_ctx->tx_info)));
+ le32_to_cpu(ep_ctx->tx_info)),
+ dev->eps[ep_index].ep_state);
}
return 0;
diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c
index f9a4a4b0eb57..8a7d46dae62c 100644
--- a/drivers/usb/host/xhci-histb.c
+++ b/drivers/usb/host/xhci-histb.c
@@ -373,7 +373,7 @@ MODULE_DEVICE_TABLE(of, histb_xhci_of_match);
static struct platform_driver histb_xhci_driver = {
.probe = xhci_histb_probe,
- .remove_new = xhci_histb_remove,
+ .remove = xhci_histb_remove,
.driver = {
.name = "xhci-histb",
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 8d774f19271e..9693464c0520 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -946,9 +946,9 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
}
/* did port event handler already start resume timing? */
if (!port->resume_timestamp) {
- /* If not, maybe we are in a host initated resume? */
+ /* If not, maybe we are in a host initiated resume? */
if (test_bit(wIndex, &bus_state->resuming_ports)) {
- /* Host initated resume doesn't time the resume
+ /* Host initiated resume doesn't time the resume
* signalling using resume_done[].
* It manually sets RESUME state, sleeps 20ms
* and sets U0 state. This should probably be
@@ -1924,7 +1924,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
/* resume already initiated */
break;
default:
- /* not in a resumeable state, ignore it */
+ /* not in a resumable state, ignore it */
clear_bit(port_index,
&bus_state->bus_suspended);
break;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index d2900197a49e..15db90c54a45 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -27,14 +27,12 @@
* "All components of all Command and Transfer TRBs shall be initialized to '0'"
*/
static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,
- unsigned int cycle_state,
unsigned int max_packet,
unsigned int num,
gfp_t flags)
{
struct xhci_segment *seg;
dma_addr_t dma;
- int i;
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
seg = kzalloc_node(sizeof(*seg), flags, dev_to_node(dev));
@@ -56,11 +54,6 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,
return NULL;
}
}
- /* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */
- if (cycle_state == 0) {
- for (i = 0; i < TRBS_PER_SEGMENT; i++)
- seg->trbs[i].link.control = cpu_to_le32(TRB_CYCLE);
- }
seg->num = num;
seg->dma = dma;
seg->next = NULL;
@@ -78,82 +71,104 @@ static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg)
kfree(seg);
}
-static void xhci_free_segments_for_ring(struct xhci_hcd *xhci,
- struct xhci_segment *first)
+static void xhci_ring_segments_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
{
- struct xhci_segment *seg;
+ struct xhci_segment *seg, *next;
+
+ ring->last_seg->next = NULL;
+ seg = ring->first_seg;
- seg = first->next;
- while (seg && seg != first) {
- struct xhci_segment *next = seg->next;
+ while (seg) {
+ next = seg->next;
xhci_segment_free(xhci, seg);
seg = next;
}
- xhci_segment_free(xhci, first);
}
/*
- * Make the prev segment point to the next segment.
+ * Only for transfer and command rings where driver is the producer, not for
+ * event rings.
*
- * Change the last TRB in the prev segment to be a Link TRB which points to the
+ * Change the last TRB in the segment to be a Link TRB which points to the
* DMA address of the next segment. The caller needs to set any Link TRB
* related flags, such as End TRB, Toggle Cycle, and no snoop.
*/
-static void xhci_link_segments(struct xhci_segment *prev,
- struct xhci_segment *next,
- enum xhci_ring_type type, bool chain_links)
+static void xhci_set_link_trb(struct xhci_segment *seg, bool chain_links)
{
+ union xhci_trb *trb;
u32 val;
- if (!prev || !next)
+ if (!seg || !seg->next)
return;
- prev->next = next;
- if (type != TYPE_EVENT) {
- prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
- cpu_to_le64(next->dma);
- /* Set the last TRB in the segment to have a TRB type ID of Link TRB */
- val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control);
- val &= ~TRB_TYPE_BITMASK;
- val |= TRB_TYPE(TRB_LINK);
- if (chain_links)
- val |= TRB_CHAIN;
- prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val);
- }
+ trb = &seg->trbs[TRBS_PER_SEGMENT - 1];
+
+ /* Set the last TRB in the segment to have a TRB type ID of Link TRB */
+ val = le32_to_cpu(trb->link.control);
+ val &= ~TRB_TYPE_BITMASK;
+ val |= TRB_TYPE(TRB_LINK);
+ if (chain_links)
+ val |= TRB_CHAIN;
+ trb->link.control = cpu_to_le32(val);
+ trb->link.segment_ptr = cpu_to_le64(seg->next->dma);
+}
+
+static void xhci_initialize_ring_segments(struct xhci_hcd *xhci, struct xhci_ring *ring)
+{
+ struct xhci_segment *seg;
+ bool chain_links;
+
+ if (ring->type == TYPE_EVENT)
+ return;
+
+ chain_links = xhci_link_chain_quirk(xhci, ring->type);
+ xhci_for_each_ring_seg(ring->first_seg, seg)
+ xhci_set_link_trb(seg, chain_links);
+
+ /* See section 4.9.2.1 and 6.4.4.1 */
+ ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |= cpu_to_le32(LINK_TOGGLE);
}
/*
- * Link the ring to the new segments.
+ * Link the src ring segments to the dst ring.
* Set Toggle Cycle for the new ring if needed.
*/
-static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring,
- struct xhci_segment *first, struct xhci_segment *last,
- unsigned int num_segs)
+static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *src, struct xhci_ring *dst)
{
- struct xhci_segment *next, *seg;
+ struct xhci_segment *seg;
bool chain_links;
- if (!ring || !first || !last)
+ if (!src || !dst)
return;
- chain_links = xhci_link_chain_quirk(xhci, ring->type);
+ /* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */
+ if (dst->cycle_state == 0) {
+ xhci_for_each_ring_seg(src->first_seg, seg) {
+ for (int i = 0; i < TRBS_PER_SEGMENT; i++)
+ seg->trbs[i].link.control |= cpu_to_le32(TRB_CYCLE);
+ }
+ }
- next = ring->enq_seg->next;
- xhci_link_segments(ring->enq_seg, first, ring->type, chain_links);
- xhci_link_segments(last, next, ring->type, chain_links);
- ring->num_segs += num_segs;
+ src->last_seg->next = dst->enq_seg->next;
+ dst->enq_seg->next = src->first_seg;
+ if (dst->type != TYPE_EVENT) {
+ chain_links = xhci_link_chain_quirk(xhci, dst->type);
+ xhci_set_link_trb(dst->enq_seg, chain_links);
+ xhci_set_link_trb(src->last_seg, chain_links);
+ }
+ dst->num_segs += src->num_segs;
- if (ring->enq_seg == ring->last_seg) {
- if (ring->type != TYPE_EVENT) {
- ring->last_seg->trbs[TRBS_PER_SEGMENT-1].link.control
+ if (dst->enq_seg == dst->last_seg) {
+ if (dst->type != TYPE_EVENT)
+ dst->last_seg->trbs[TRBS_PER_SEGMENT-1].link.control
&= ~cpu_to_le32(LINK_TOGGLE);
- last->trbs[TRBS_PER_SEGMENT-1].link.control
- |= cpu_to_le32(LINK_TOGGLE);
- }
- ring->last_seg = last;
+
+ dst->last_seg = src->last_seg;
+ } else if (dst->type != TYPE_EVENT) {
+ src->last_seg->trbs[TRBS_PER_SEGMENT-1].link.control &= ~cpu_to_le32(LINK_TOGGLE);
}
- for (seg = ring->enq_seg; seg != ring->last_seg; seg = seg->next)
+ for (seg = dst->enq_seg; seg != dst->last_seg; seg = seg->next)
seg->next->num = seg->num + 1;
}
@@ -224,7 +239,6 @@ static int xhci_update_stream_segment_mapping(
struct radix_tree_root *trb_address_map,
struct xhci_ring *ring,
struct xhci_segment *first_seg,
- struct xhci_segment *last_seg,
gfp_t mem_flags)
{
struct xhci_segment *seg;
@@ -234,28 +248,22 @@ static int xhci_update_stream_segment_mapping(
if (WARN_ON_ONCE(trb_address_map == NULL))
return 0;
- seg = first_seg;
- do {
+ xhci_for_each_ring_seg(first_seg, seg) {
ret = xhci_insert_segment_mapping(trb_address_map,
ring, seg, mem_flags);
if (ret)
goto remove_streams;
- if (seg == last_seg)
- return 0;
- seg = seg->next;
- } while (seg != first_seg);
+ }
return 0;
remove_streams:
failed_seg = seg;
- seg = first_seg;
- do {
+ xhci_for_each_ring_seg(first_seg, seg) {
xhci_remove_segment_mapping(trb_address_map, seg);
if (seg == failed_seg)
return ret;
- seg = seg->next;
- } while (seg != first_seg);
+ }
return ret;
}
@@ -267,17 +275,14 @@ static void xhci_remove_stream_mapping(struct xhci_ring *ring)
if (WARN_ON_ONCE(ring->trb_address_map == NULL))
return;
- seg = ring->first_seg;
- do {
+ xhci_for_each_ring_seg(ring->first_seg, seg)
xhci_remove_segment_mapping(ring->trb_address_map, seg);
- seg = seg->next;
- } while (seg != ring->first_seg);
}
static int xhci_update_stream_mapping(struct xhci_ring *ring, gfp_t mem_flags)
{
return xhci_update_stream_segment_mapping(ring->trb_address_map, ring,
- ring->first_seg, ring->last_seg, mem_flags);
+ ring->first_seg, mem_flags);
}
/* XXX: Do we need the hcd structure in all these functions? */
@@ -291,14 +296,13 @@ void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
if (ring->first_seg) {
if (ring->type == TYPE_STREAM)
xhci_remove_stream_mapping(ring);
- xhci_free_segments_for_ring(xhci, ring->first_seg);
+ xhci_ring_segments_free(xhci, ring);
}
kfree(ring);
}
-void xhci_initialize_ring_info(struct xhci_ring *ring,
- unsigned int cycle_state)
+void xhci_initialize_ring_info(struct xhci_ring *ring)
{
/* The ring is empty, so the enqueue pointer == dequeue pointer */
ring->enqueue = ring->first_seg->trbs;
@@ -312,7 +316,7 @@ void xhci_initialize_ring_info(struct xhci_ring *ring,
* New rings are initialized with cycle state equal to 1; if we are
* handling ring expansion, set the cycle state equal to the old ring.
*/
- ring->cycle_state = cycle_state;
+ ring->cycle_state = 1;
/*
* Each segment has a link TRB, and leave an extra TRB for SW
@@ -323,46 +327,36 @@ void xhci_initialize_ring_info(struct xhci_ring *ring,
EXPORT_SYMBOL_GPL(xhci_initialize_ring_info);
/* Allocate segments and link them for a ring */
-static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
- struct xhci_segment **first,
- struct xhci_segment **last,
- unsigned int num_segs,
- unsigned int cycle_state,
- enum xhci_ring_type type,
- unsigned int max_packet,
- gfp_t flags)
+static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, gfp_t flags)
{
struct xhci_segment *prev;
unsigned int num = 0;
- bool chain_links;
-
- chain_links = xhci_link_chain_quirk(xhci, type);
- prev = xhci_segment_alloc(xhci, cycle_state, max_packet, num, flags);
+ prev = xhci_segment_alloc(xhci, ring->bounce_buf_len, num, flags);
if (!prev)
return -ENOMEM;
num++;
- *first = prev;
- while (num < num_segs) {
+ ring->first_seg = prev;
+ while (num < ring->num_segs) {
struct xhci_segment *next;
- next = xhci_segment_alloc(xhci, cycle_state, max_packet, num,
- flags);
+ next = xhci_segment_alloc(xhci, ring->bounce_buf_len, num, flags);
if (!next)
goto free_segments;
- xhci_link_segments(prev, next, type, chain_links);
+ prev->next = next;
prev = next;
num++;
}
- xhci_link_segments(prev, *first, type, chain_links);
- *last = prev;
+ ring->last_seg = prev;
+ ring->last_seg->next = ring->first_seg;
return 0;
free_segments:
- xhci_free_segments_for_ring(xhci, *first);
+ ring->last_seg = prev;
+ xhci_ring_segments_free(xhci, ring);
return -ENOMEM;
}
@@ -373,9 +367,8 @@ free_segments:
* Set the end flag and the cycle toggle bit on the last segment.
* See section 4.9.1 and figures 15 and 16.
*/
-struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
- unsigned int num_segs, unsigned int cycle_state,
- enum xhci_ring_type type, unsigned int max_packet, gfp_t flags)
+struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, unsigned int num_segs,
+ enum xhci_ring_type type, unsigned int max_packet, gfp_t flags)
{
struct xhci_ring *ring;
int ret;
@@ -392,18 +385,12 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
if (num_segs == 0)
return ring;
- ret = xhci_alloc_segments_for_ring(xhci, &ring->first_seg, &ring->last_seg, num_segs,
- cycle_state, type, max_packet, flags);
+ ret = xhci_alloc_segments_for_ring(xhci, ring, flags);
if (ret)
goto fail;
- /* Only event ring does not use link TRB */
- if (type != TYPE_EVENT) {
- /* See section 4.9.2.1 and 6.4.4.1 */
- ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |=
- cpu_to_le32(LINK_TOGGLE);
- }
- xhci_initialize_ring_info(ring, cycle_state);
+ xhci_initialize_ring_segments(xhci, ring);
+ xhci_initialize_ring_info(ring);
trace_xhci_ring_alloc(ring);
return ring;
@@ -427,23 +414,29 @@ void xhci_free_endpoint_ring(struct xhci_hcd *xhci,
int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
unsigned int num_new_segs, gfp_t flags)
{
- struct xhci_segment *first;
- struct xhci_segment *last;
- int ret;
+ struct xhci_ring new_ring;
+ int ret;
+
+ if (num_new_segs == 0)
+ return 0;
- ret = xhci_alloc_segments_for_ring(xhci, &first, &last, num_new_segs, ring->cycle_state,
- ring->type, ring->bounce_buf_len, flags);
+ new_ring.num_segs = num_new_segs;
+ new_ring.bounce_buf_len = ring->bounce_buf_len;
+ new_ring.type = ring->type;
+ ret = xhci_alloc_segments_for_ring(xhci, &new_ring, flags);
if (ret)
return -ENOMEM;
+ xhci_initialize_ring_segments(xhci, &new_ring);
+
if (ring->type == TYPE_STREAM) {
- ret = xhci_update_stream_segment_mapping(ring->trb_address_map,
- ring, first, last, flags);
+ ret = xhci_update_stream_segment_mapping(ring->trb_address_map, ring,
+ new_ring.first_seg, flags);
if (ret)
goto free_segments;
}
- xhci_link_rings(xhci, ring, first, last, num_new_segs);
+ xhci_link_rings(xhci, ring, &new_ring);
trace_xhci_ring_expansion(ring);
xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion,
"ring expansion succeed, now has %d segments",
@@ -452,7 +445,7 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
return 0;
free_segments:
- xhci_free_segments_for_ring(xhci, first);
+ xhci_ring_segments_free(xhci, &new_ring);
return ret;
}
@@ -642,8 +635,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
for (cur_stream = 1; cur_stream < num_streams; cur_stream++) {
stream_info->stream_rings[cur_stream] =
- xhci_ring_alloc(xhci, 2, 1, TYPE_STREAM, max_packet,
- mem_flags);
+ xhci_ring_alloc(xhci, 2, TYPE_STREAM, max_packet, mem_flags);
cur_ring = stream_info->stream_rings[cur_stream];
if (!cur_ring)
goto cleanup_rings;
@@ -658,6 +650,8 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
xhci_dbg(xhci, "Setting stream %d ring ptr to 0x%08llx\n", cur_stream, addr);
ret = xhci_update_stream_mapping(cur_ring, mem_flags);
+
+ trace_xhci_alloc_stream_info_ctx(stream_info, cur_stream);
if (ret) {
xhci_ring_free(xhci, cur_ring);
stream_info->stream_rings[cur_stream] = NULL;
@@ -984,7 +978,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
}
/* Allocate endpoint 0 ring */
- dev->eps[0].ring = xhci_ring_alloc(xhci, 2, 1, TYPE_CTRL, 0, flags);
+ dev->eps[0].ring = xhci_ring_alloc(xhci, 2, TYPE_CTRL, 0, flags);
if (!dev->eps[0].ring)
goto fail;
@@ -1461,7 +1455,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
/* Set up the endpoint ring */
virt_dev->eps[ep_index].new_ring =
- xhci_ring_alloc(xhci, 2, 1, ring_type, max_packet, mem_flags);
+ xhci_ring_alloc(xhci, 2, ring_type, max_packet, mem_flags);
if (!virt_dev->eps[ep_index].new_ring)
return -ENOMEM;
@@ -2271,7 +2265,7 @@ xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int segs, gfp_t flags)
if (!ir)
return NULL;
- ir->event_ring = xhci_ring_alloc(xhci, segs, 1, TYPE_EVENT, 0, flags);
+ ir->event_ring = xhci_ring_alloc(xhci, segs, TYPE_EVENT, 0, flags);
if (!ir->event_ring) {
xhci_warn(xhci, "Failed to allocate interrupter event ring\n");
kfree(ir);
@@ -2473,7 +2467,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
goto fail;
/* Set up the command ring to have one segments for now. */
- xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, 0, flags);
+ xhci->cmd_ring = xhci_ring_alloc(xhci, 1, TYPE_COMMAND, 0, flags);
if (!xhci->cmd_ring)
goto fail;
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
@@ -2518,11 +2512,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
ir->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX;
- /*
- * XXX: Might need to set the Interrupter Moderation Register to
- * something other than the default (~1ms minimum between interrupts).
- * See section 5.5.1.2.
- */
for (i = 0; i < MAX_HC_SLOTS; i++)
xhci->devs[i] = NULL;
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 3252e3d2d79c..904831344440 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -853,7 +853,7 @@ MODULE_DEVICE_TABLE(of, mtk_xhci_of_match);
static struct platform_driver mtk_xhci_driver = {
.probe = xhci_mtk_probe,
- .remove_new = xhci_mtk_remove,
+ .remove = xhci_mtk_remove,
.driver = {
.name = "xhci-mtk",
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index cb07cee9ed0c..b21474e81482 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -28,18 +28,18 @@
#define SPARSE_CNTL_ENABLE 0xC12C
/* Device for a quirk */
-#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
-#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
+#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
+#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1009 0x1009
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1100 0x1100
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400 0x1400
-#define PCI_VENDOR_ID_ETRON 0x1b6f
-#define PCI_DEVICE_ID_EJ168 0x7023
-#define PCI_DEVICE_ID_EJ188 0x7052
+#define PCI_VENDOR_ID_ETRON 0x1b6f
+#define PCI_DEVICE_ID_ETRON_EJ168 0x7023
+#define PCI_DEVICE_ID_ETRON_EJ188 0x7052
-#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
-#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI 0x9cb1
#define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f
@@ -82,9 +82,6 @@
#define PCI_DEVICE_ID_ASMEDIA_3042_XHCI 0x3042
#define PCI_DEVICE_ID_ASMEDIA_3242_XHCI 0x3242
-#define PCI_DEVICE_ID_CADENCE 0x17CD
-#define PCI_DEVICE_ID_CADENCE_SSP 0x0200
-
static const char hcd_name[] = "xhci_hcd";
static struct hc_driver __read_mostly xhci_pci_hc_driver;
@@ -150,14 +147,11 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
hcd->irq = 0;
/*
- * calculate number of MSI-X vectors supported.
- * - HCS_MAX_INTRS: the max number of interrupts the host can handle,
- * with max number of interrupters based on the xhci HCSPARAMS1.
- * - num_online_cpus: maximum MSI-X vectors per CPUs core.
- * Add additional 1 vector to ensure always available interrupt.
+ * Calculate number of MSI/MSI-X vectors supported.
+ * - max_interrupters: the max number of interrupts requested, capped to xhci HCSPARAMS1.
+ * - num_online_cpus: one vector per CPUs core, with at least one overall.
*/
- xhci->nvecs = min(num_online_cpus() + 1,
- HCS_MAX_INTRS(xhci->hcs_params1));
+ xhci->nvecs = min(num_online_cpus() + 1, xhci->max_interrupters);
/* TODO: Check with MSI Soc for sysdev */
xhci->nvecs = pci_alloc_irq_vectors(pdev, 1, xhci->nvecs,
@@ -395,14 +389,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
- pdev->device == PCI_DEVICE_ID_EJ168) {
- xhci->quirks |= XHCI_RESET_ON_RESUME;
- xhci->quirks |= XHCI_BROKEN_STREAMS;
- }
- if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
- pdev->device == PCI_DEVICE_ID_EJ188) {
+ (pdev->device == PCI_DEVICE_ID_ETRON_EJ168 ||
+ pdev->device == PCI_DEVICE_ID_ETRON_EJ188)) {
+ xhci->quirks |= XHCI_ETRON_HOST;
xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci->quirks |= XHCI_BROKEN_STREAMS;
+ xhci->quirks |= XHCI_NO_SOFT_RETRY;
}
if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
@@ -482,8 +474,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH;
}
- if (pdev->vendor == PCI_DEVICE_ID_CADENCE &&
- pdev->device == PCI_DEVICE_ID_CADENCE_SSP)
+ if (pdev->vendor == PCI_VENDOR_ID_CDNS &&
+ pdev->device == PCI_DEVICE_ID_CDNS_USBSSP)
xhci->quirks |= XHCI_CDNS_SCTX_QUIRK;
/* xHC spec requires PCI devices to support D3hot and D3cold */
@@ -646,6 +638,9 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
dma_set_max_seg_size(&dev->dev, UINT_MAX);
+ if (device_property_read_bool(&dev->dev, "ti,pwron-active-high"))
+ pci_clear_and_set_config_dword(dev, 0xE0, 0, 1 << 22);
+
return 0;
put_usb3_hcd:
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index ecaa75718e59..e6c9006bd568 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -573,7 +573,7 @@ MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);
static struct platform_driver usb_generic_xhci_driver = {
.probe = xhci_generic_plat_probe,
- .remove_new = xhci_plat_remove,
+ .remove = xhci_plat_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "xhci-hcd",
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index 8b357647728c..1cc082a3b793 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -274,7 +274,7 @@ static int xhci_renesas_probe(struct platform_device *pdev)
static struct platform_driver usb_xhci_renesas_driver = {
.probe = xhci_renesas_probe,
- .remove_new = xhci_plat_remove,
+ .remove = xhci_plat_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "xhci-renesas-hcd",
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 928b93ad1ee8..4cf5363875c7 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -52,6 +52,7 @@
* endpoint rings; it generates events on the event ring for these.
*/
+#include <linux/jiffies.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
@@ -145,10 +146,8 @@ static void trb_to_noop(union xhci_trb *trb, u32 noop_type)
* TRB is in a new segment. This does not skip over link TRBs, and it does not
* effect the ring dequeue or enqueue pointers.
*/
-static void next_trb(struct xhci_hcd *xhci,
- struct xhci_ring *ring,
- struct xhci_segment **seg,
- union xhci_trb **trb)
+static void next_trb(struct xhci_segment **seg,
+ union xhci_trb **trb)
{
if (trb_is_link(*trb) || last_trb_on_seg(*seg, *trb)) {
*seg = (*seg)->next;
@@ -169,13 +168,16 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
if (ring->type == TYPE_EVENT) {
if (!last_trb_on_seg(ring->deq_seg, ring->dequeue)) {
ring->dequeue++;
- goto out;
+ return;
}
if (last_trb_on_ring(ring, ring->deq_seg, ring->dequeue))
ring->cycle_state ^= 1;
ring->deq_seg = ring->deq_seg->next;
ring->dequeue = ring->deq_seg->trbs;
- goto out;
+
+ trace_xhci_inc_deq(ring);
+
+ return;
}
/* All other rings have link trbs */
@@ -190,14 +192,13 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
ring->deq_seg = ring->deq_seg->next;
ring->dequeue = ring->deq_seg->trbs;
+ trace_xhci_inc_deq(ring);
+
if (link_trb_count++ > ring->num_segs) {
xhci_warn(xhci, "Ring is an endless link TRB loop\n");
break;
}
}
-out:
- trace_xhci_inc_deq(ring);
-
return;
}
@@ -266,13 +267,13 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
ring->enqueue = ring->enq_seg->trbs;
next = ring->enqueue;
+ trace_xhci_inc_enq(ring);
+
if (link_trb_count++ > ring->num_segs) {
xhci_warn(xhci, "%s: Ring link TRB loop\n", __func__);
break;
}
}
-
- trace_xhci_inc_enq(ring);
}
/*
@@ -426,7 +427,7 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
}
}
-/* Must be called with xhci->lock held, releases and aquires lock back */
+/* Must be called with xhci->lock held, releases and acquires lock back */
static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
{
struct xhci_segment *new_seg = xhci->cmd_ring->deq_seg;
@@ -446,9 +447,9 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
* avoiding corrupting the command ring pointer in case the command ring
* is stopped by the time the upper dword is written.
*/
- next_trb(xhci, NULL, &new_seg, &new_deq);
+ next_trb(&new_seg, &new_deq);
if (trb_is_link(new_deq))
- next_trb(xhci, NULL, &new_seg, &new_deq);
+ next_trb(&new_seg, &new_deq);
crcr = xhci_trb_virt_to_dma(new_seg, new_deq);
xhci_write_64(xhci, crcr | CMD_RING_ABORT, &xhci->op_regs->cmd_ring);
@@ -660,8 +661,8 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci,
/*
* We want to find the pointer, segment and cycle state of the new trb
- * (the one after current TD's last_trb). We know the cycle state at
- * hw_dequeue, so walk the ring until both hw_dequeue and last_trb are
+ * (the one after current TD's end_trb). We know the cycle state at
+ * hw_dequeue, so walk the ring until both hw_dequeue and end_trb are
* found.
*/
do {
@@ -671,14 +672,14 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci,
if (td_last_trb_found)
break;
}
- if (new_deq == td->last_trb)
+ if (new_deq == td->end_trb)
td_last_trb_found = true;
if (cycle_found && trb_is_link(new_deq) &&
link_trb_toggles_cycle(new_deq))
new_cycle ^= 0x1;
- next_trb(xhci, ep_ring, &new_seg, &new_deq);
+ next_trb(&new_seg, &new_deq);
/* Search wrapped around, bail out */
if (new_deq == ep->ring->dequeue) {
@@ -740,23 +741,22 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci,
* (The last TRB actually points to the ring enqueue pointer, which is not part
* of this TD.) This is used to remove partially enqueued isoc TDs from a ring.
*/
-static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
- struct xhci_td *td, bool flip_cycle)
+static void td_to_noop(struct xhci_td *td, bool flip_cycle)
{
struct xhci_segment *seg = td->start_seg;
- union xhci_trb *trb = td->first_trb;
+ union xhci_trb *trb = td->start_trb;
while (1) {
trb_to_noop(trb, TRB_TR_NOOP);
/* flip cycle if asked to */
- if (flip_cycle && trb != td->first_trb && trb != td->last_trb)
+ if (flip_cycle && trb != td->start_trb && trb != td->end_trb)
trb->generic.field[3] ^= cpu_to_le32(TRB_CYCLE);
- if (trb == td->last_trb)
+ if (trb == td->end_trb)
break;
- next_trb(xhci, ep_ring, &seg, &trb);
+ next_trb(&seg, &trb);
}
}
@@ -799,7 +799,7 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
DMA_FROM_DEVICE);
- /* for in tranfers we need to copy the data from bounce to sg */
+ /* for in transfers we need to copy the data from bounce to sg */
if (urb->num_sgs) {
len = sg_pcopy_from_buffer(urb->sg, urb->num_sgs, seg->bounce_buf,
seg->bounce_len, seg->bounce_offs);
@@ -814,8 +814,8 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
seg->bounce_offs = 0;
}
-static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
- struct xhci_ring *ep_ring, int status)
+static void xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
+ struct xhci_ring *ep_ring, int status)
{
struct urb *urb = NULL;
@@ -858,10 +858,18 @@ static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
status = 0;
xhci_giveback_urb_in_irq(xhci, td, status);
}
-
- return 0;
}
+/* Give back previous TD and move on to the next TD. */
+static void xhci_dequeue_td(struct xhci_hcd *xhci, struct xhci_td *td, struct xhci_ring *ring,
+ u32 status)
+{
+ ring->dequeue = td->end_trb;
+ ring->deq_seg = td->end_seg;
+ inc_deq(xhci, ring);
+
+ xhci_td_cleanup(xhci, td, ring, status);
+}
/* Complete the cancelled URBs we unlinked from td_list. */
static void xhci_giveback_invalidated_tds(struct xhci_virt_ep *ep)
@@ -972,13 +980,20 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
unsigned int slot_id = ep->vdev->slot_id;
int err;
+ /*
+ * This is not going to work if the hardware is changing its dequeue
+ * pointers as we look at them. Completion handler will call us later.
+ */
+ if (ep->ep_state & SET_DEQ_PENDING)
+ return 0;
+
xhci = ep->xhci;
list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) {
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Removing canceled TD starting at 0x%llx (dma) in stream %u URB %p",
(unsigned long long)xhci_trb_virt_to_dma(
- td->start_seg, td->first_trb),
+ td->start_seg, td->start_trb),
td->urb->stream_id, td->urb);
list_del_init(&td->td_list);
ring = xhci_urb_to_transfer_ring(xhci, td->urb);
@@ -1020,16 +1035,16 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
"Found multiple active URBs %p and %p in stream %u?\n",
td->urb, cached_td->urb,
td->urb->stream_id);
- td_to_noop(xhci, ring, cached_td, false);
+ td_to_noop(cached_td, false);
cached_td->cancel_status = TD_CLEARED;
}
- td_to_noop(xhci, ring, td, false);
+ td_to_noop(td, false);
td->cancel_status = TD_CLEARING_CACHE;
cached_td = td;
break;
}
} else {
- td_to_noop(xhci, ring, td, false);
+ td_to_noop(td, false);
td->cancel_status = TD_CLEARED;
}
}
@@ -1054,7 +1069,7 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
continue;
xhci_warn(xhci, "Failed to clear cancelled cached URB %p, mark clear anyway\n",
td->urb);
- td_to_noop(xhci, ring, td, false);
+ td_to_noop(td, false);
td->cancel_status = TD_CLEARED;
}
}
@@ -1062,6 +1077,19 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
}
/*
+ * Erase queued TDs from transfer ring(s) and give back those the xHC didn't
+ * stop on. If necessary, queue commands to move the xHC off cancelled TDs it
+ * stopped on. Those will be given back later when the commands complete.
+ *
+ * Call under xhci->lock on a stopped endpoint.
+ */
+void xhci_process_cancelled_tds(struct xhci_virt_ep *ep)
+{
+ xhci_invalidate_cancelled_tds(ep);
+ xhci_giveback_invalidated_tds(ep);
+}
+
+/*
* Returns the TD the endpoint ring halted on.
* Only call for non-running rings without streams.
*/
@@ -1151,16 +1179,35 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
return;
case EP_STATE_STOPPED:
/*
- * NEC uPD720200 sometimes sets this state and fails with
- * Context Error while continuing to process TRBs.
- * Be conservative and trust EP_CTX_STATE on other chips.
+ * Per xHCI 4.6.9, Stop Endpoint command on a Stopped
+ * EP is a Context State Error, and EP stays Stopped.
+ *
+ * But maybe it failed on Halted, and somebody ran Reset
+ * Endpoint later. EP state is now Stopped and EP_HALTED
+ * still set because Reset EP handler will run after us.
+ */
+ if (ep->ep_state & EP_HALTED)
+ break;
+ /*
+ * On some HCs EP state remains Stopped for some tens of
+ * us to a few ms or more after a doorbell ring, and any
+ * new Stop Endpoint fails without aborting the restart.
+ * This handler may run quickly enough to still see this
+ * Stopped state, but it will soon change to Running.
+ *
+ * Assume this bug on unexpected Stop Endpoint failures.
+ * Keep retrying until the EP starts and stops again, on
+ * chips where this is known to help. Wait for 100ms.
*/
if (!(xhci->quirks & XHCI_NEC_HOST))
break;
+ if (time_is_before_jiffies(ep->stop_time + msecs_to_jiffies(100)))
+ break;
fallthrough;
case EP_STATE_RUNNING:
/* Race, HW handled stop ep cmd before ep was running */
- xhci_dbg(xhci, "Stop ep completion ctx error, ep is running\n");
+ xhci_dbg(xhci, "Stop ep completion ctx error, ctx_state %d\n",
+ GET_EP_CTX_STATE(ep_ctx));
command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
if (!command) {
@@ -1338,8 +1385,8 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
struct xhci_virt_ep *ep;
struct xhci_ep_ctx *ep_ctx;
struct xhci_slot_ctx *slot_ctx;
+ struct xhci_stream_ctx *stream_ctx;
struct xhci_td *td, *tmp_td;
- bool deferred = false;
ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2]));
@@ -1360,6 +1407,11 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
trace_xhci_handle_cmd_set_deq(slot_ctx);
trace_xhci_handle_cmd_set_deq_ep(ep_ctx);
+ if (ep->ep_state & EP_HAS_STREAMS) {
+ stream_ctx = &ep->stream_info->stream_ctx_array[stream_id];
+ trace_xhci_handle_cmd_set_deq_stream(ep->stream_info, stream_id);
+ }
+
if (cmd_comp_code != COMP_SUCCESS) {
unsigned int ep_state;
unsigned int slot_state;
@@ -1396,9 +1448,7 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
u64 deq;
/* 4.6.10 deq ptr is written to the stream ctx for streams */
if (ep->ep_state & EP_HAS_STREAMS) {
- struct xhci_stream_ctx *ctx =
- &ep->stream_info->stream_ctx_array[stream_id];
- deq = le64_to_cpu(ctx->stream_ring) & SCTX_DEQ_MASK;
+ deq = le64_to_cpu(stream_ctx->stream_ring) & SCTX_DEQ_MASK;
/*
* Cadence xHCI controllers store some endpoint state
@@ -1410,8 +1460,8 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
* To fix this issue driver must clear Rsvd0 field.
*/
if (xhci->quirks & XHCI_CDNS_SCTX_QUIRK) {
- ctx->reserved[0] = 0;
- ctx->reserved[1] = 0;
+ stream_ctx->reserved[0] = 0;
+ stream_ctx->reserved[1] = 0;
}
} else {
deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK;
@@ -1440,8 +1490,6 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
xhci_dbg(ep->xhci, "%s: Giveback cancelled URB %p TD\n",
__func__, td->urb);
xhci_td_cleanup(ep->xhci, td, ep_ring, td->status);
- } else if (td->cancel_status == TD_CLEARING_CACHE_DEFERRED) {
- deferred = true;
} else {
xhci_dbg(ep->xhci, "%s: Keep cancelled URB %p TD as cancel_status is %d\n",
__func__, td->urb, td->cancel_status);
@@ -1452,11 +1500,15 @@ cleanup:
ep->queued_deq_seg = NULL;
ep->queued_deq_ptr = NULL;
- if (deferred) {
- /* We have more streams to clear */
+ /* Check for deferred or newly cancelled TDs */
+ if (!list_empty(&ep->cancelled_td_list)) {
xhci_dbg(ep->xhci, "%s: Pending TDs to clear, continuing with invalidation\n",
__func__);
xhci_invalidate_cancelled_tds(ep);
+ /* Try to restart the endpoint if all is done */
+ ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
+ /* Start giving back any TDs invalidated above */
+ xhci_giveback_invalidated_tds(ep);
} else {
/* Restart any rings with pending URBs */
xhci_dbg(ep->xhci, "%s: All TDs cleared, ring doorbell\n", __func__);
@@ -1716,7 +1768,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
cmd_dma = le64_to_cpu(event->cmd_trb);
cmd_trb = xhci->cmd_ring->dequeue;
- trace_xhci_handle_command(xhci->cmd_ring, &cmd_trb->generic);
+ trace_xhci_handle_command(xhci->cmd_ring, &cmd_trb->generic, cmd_dma);
cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
@@ -2074,7 +2126,7 @@ struct xhci_segment *trb_in_td(struct xhci_hcd *xhci, struct xhci_td *td, dma_ad
dma_addr_t end_trb_dma;
struct xhci_segment *cur_seg;
- start_dma = xhci_trb_virt_to_dma(td->start_seg, td->first_trb);
+ start_dma = xhci_trb_virt_to_dma(td->start_seg, td->start_trb);
cur_seg = td->start_seg;
do {
@@ -2084,7 +2136,7 @@ struct xhci_segment *trb_in_td(struct xhci_hcd *xhci, struct xhci_td *td, dma_ad
end_seg_dma = xhci_trb_virt_to_dma(cur_seg,
&cur_seg->trbs[TRBS_PER_SEGMENT - 1]);
/* If the end TRB isn't in this segment, this is set to 0 */
- end_trb_dma = xhci_trb_virt_to_dma(cur_seg, td->last_trb);
+ end_trb_dma = xhci_trb_virt_to_dma(cur_seg, td->end_trb);
if (debug)
xhci_warn(xhci,
@@ -2184,9 +2236,9 @@ int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code)
return 0;
}
-static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
- struct xhci_ring *ep_ring, struct xhci_td *td,
- u32 trb_comp_code)
+static void finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+ struct xhci_ring *ep_ring, struct xhci_td *td,
+ u32 trb_comp_code)
{
struct xhci_ep_ctx *ep_ctx;
@@ -2201,7 +2253,7 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
* stopped TDs. A stopped TD may be restarted, so don't update
* the ring dequeue pointer or take this TD off any lists yet.
*/
- return 0;
+ return;
case COMP_USB_TRANSACTION_ERROR:
case COMP_BABBLE_DETECTED_ERROR:
case COMP_SPLIT_TRANSACTION_ERROR:
@@ -2226,8 +2278,8 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
!list_empty(&td->cancelled_td_list)) {
xhci_dbg(xhci, "Already resolving halted ep for 0x%llx\n",
(unsigned long long)xhci_trb_virt_to_dma(
- td->start_seg, td->first_trb));
- return 0;
+ td->start_seg, td->start_trb));
+ return;
}
/* endpoint not halted, don't reset it */
break;
@@ -2235,7 +2287,7 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
/* Almost same procedure as for STALL_ERROR below */
xhci_clear_hub_tt_buffer(xhci, td, ep);
xhci_handle_halted_endpoint(xhci, ep, td, EP_HARD_RESET);
- return 0;
+ return;
case COMP_STALL_ERROR:
/*
* xhci internal endpoint state will go to a "halt" state for
@@ -2252,28 +2304,22 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
xhci_handle_halted_endpoint(xhci, ep, td, EP_HARD_RESET);
- return 0; /* xhci_handle_halted_endpoint marked td cancelled */
+ return; /* xhci_handle_halted_endpoint marked td cancelled */
default:
break;
}
- /* Update ring dequeue pointer */
- ep_ring->dequeue = td->last_trb;
- ep_ring->deq_seg = td->last_trb_seg;
- inc_deq(xhci, ep_ring);
-
- return xhci_td_cleanup(xhci, td, ep_ring, td->status);
+ xhci_dequeue_td(xhci, td, ep_ring, td->status);
}
-/* sum trb lengths from ring dequeue up to stop_trb, _excluding_ stop_trb */
-static int sum_trb_lengths(struct xhci_hcd *xhci, struct xhci_ring *ring,
- union xhci_trb *stop_trb)
+/* sum trb lengths from the first trb up to stop_trb, _excluding_ stop_trb */
+static u32 sum_trb_lengths(struct xhci_td *td, union xhci_trb *stop_trb)
{
u32 sum;
- union xhci_trb *trb = ring->dequeue;
- struct xhci_segment *seg = ring->deq_seg;
+ union xhci_trb *trb = td->start_trb;
+ struct xhci_segment *seg = td->start_seg;
- for (sum = 0; trb != stop_trb; next_trb(xhci, ring, &seg, &trb)) {
+ for (sum = 0; trb != stop_trb; next_trb(&seg, &trb)) {
if (!trb_is_noop(trb) && !trb_is_link(trb))
sum += TRB_LEN(le32_to_cpu(trb->generic.field[2]));
}
@@ -2283,9 +2329,9 @@ static int sum_trb_lengths(struct xhci_hcd *xhci, struct xhci_ring *ring,
/*
* Process control tds, update urb status and actual_length.
*/
-static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
- struct xhci_ring *ep_ring, struct xhci_td *td,
- union xhci_trb *ep_trb, struct xhci_transfer_event *event)
+static void process_ctrl_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+ struct xhci_ring *ep_ring, struct xhci_td *td,
+ union xhci_trb *ep_trb, struct xhci_transfer_event *event)
{
struct xhci_ep_ctx *ep_ctx;
u32 trb_comp_code;
@@ -2364,7 +2410,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
td->urb_length_set = true;
td->urb->actual_length = requested - remaining;
xhci_dbg(xhci, "Waiting for status stage event\n");
- return 0;
+ return;
}
/* at status stage */
@@ -2372,15 +2418,15 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
td->urb->actual_length = requested;
finish_td:
- return finish_td(xhci, ep, ep_ring, td, trb_comp_code);
+ finish_td(xhci, ep, ep_ring, td, trb_comp_code);
}
/*
* Process isochronous tds, update urb packet status and actual_length.
*/
-static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
- struct xhci_ring *ep_ring, struct xhci_td *td,
- union xhci_trb *ep_trb, struct xhci_transfer_event *event)
+static void process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+ struct xhci_ring *ep_ring, struct xhci_td *td,
+ union xhci_trb *ep_trb, struct xhci_transfer_event *event)
{
struct urb_priv *urb_priv;
int idx;
@@ -2425,7 +2471,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
fallthrough;
case COMP_ISOCH_BUFFER_OVERRUN:
frame->status = -EOVERFLOW;
- if (ep_trb != td->last_trb)
+ if (ep_trb != td->end_trb)
td->error_mid_td = true;
break;
case COMP_INCOMPATIBLE_DEVICE_ERROR:
@@ -2435,14 +2481,14 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
case COMP_USB_TRANSACTION_ERROR:
frame->status = -EPROTO;
sum_trbs_for_length = true;
- if (ep_trb != td->last_trb)
+ if (ep_trb != td->end_trb)
td->error_mid_td = true;
break;
case COMP_STOPPED:
sum_trbs_for_length = true;
break;
case COMP_STOPPED_SHORT_PACKET:
- /* field normally containing residue now contains tranferred */
+ /* field normally containing residue now contains transferred */
frame->status = short_framestatus;
requested = remaining;
break;
@@ -2462,7 +2508,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
goto finish_td;
if (sum_trbs_for_length)
- frame->actual_length = sum_trb_lengths(xhci, ep->ring, ep_trb) +
+ frame->actual_length = sum_trb_lengths(td, ep_trb) +
ep_trb_len - remaining;
else
frame->actual_length = requested;
@@ -2471,17 +2517,16 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
finish_td:
/* Don't give back TD yet if we encountered an error mid TD */
- if (td->error_mid_td && ep_trb != td->last_trb) {
+ if (td->error_mid_td && ep_trb != td->end_trb) {
xhci_dbg(xhci, "Error mid isoc TD, wait for final completion event\n");
td->urb_length_set = true;
- return 0;
+ return;
}
-
- return finish_td(xhci, ep, ep_ring, td, trb_comp_code);
+ finish_td(xhci, ep, ep_ring, td, trb_comp_code);
}
-static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
- struct xhci_virt_ep *ep, int status)
+static void skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ struct xhci_virt_ep *ep, int status)
{
struct urb_priv *urb_priv;
struct usb_iso_packet_descriptor *frame;
@@ -2497,20 +2542,15 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
/* calc actual length */
frame->actual_length = 0;
- /* Update ring dequeue pointer */
- ep->ring->dequeue = td->last_trb;
- ep->ring->deq_seg = td->last_trb_seg;
- inc_deq(xhci, ep->ring);
-
- return xhci_td_cleanup(xhci, td, ep->ring, status);
+ xhci_dequeue_td(xhci, td, ep->ring, status);
}
/*
* Process bulk and interrupt tds, update urb status and actual_length.
*/
-static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
- struct xhci_ring *ep_ring, struct xhci_td *td,
- union xhci_trb *ep_trb, struct xhci_transfer_event *event)
+static void process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+ struct xhci_ring *ep_ring, struct xhci_td *td,
+ union xhci_trb *ep_trb, struct xhci_transfer_event *event)
{
struct xhci_slot_ctx *slot_ctx;
u32 trb_comp_code;
@@ -2526,7 +2566,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
case COMP_SUCCESS:
ep->err_count = 0;
/* handle success with untransferred data as short packet */
- if (ep_trb != td->last_trb || remaining) {
+ if (ep_trb != td->end_trb || remaining) {
xhci_warn(xhci, "WARN Successful completion on short TX\n");
xhci_dbg(xhci, "ep %#x - asked for %d bytes, %d bytes untransferred\n",
td->urb->ep->desc.bEndpointAddress,
@@ -2542,7 +2582,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
goto finish_td;
case COMP_STOPPED_LENGTH_INVALID:
/* stopped on ep trb with invalid length, exclude it */
- td->urb->actual_length = sum_trb_lengths(xhci, ep_ring, ep_trb);
+ td->urb->actual_length = sum_trb_lengths(td, ep_trb);
goto finish_td;
case COMP_USB_TRANSACTION_ERROR:
if (xhci->quirks & XHCI_NO_SOFT_RETRY ||
@@ -2553,17 +2593,17 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
td->status = 0;
xhci_handle_halted_endpoint(xhci, ep, td, EP_SOFT_RESET);
- return 0;
+ return;
default:
/* do nothing */
break;
}
- if (ep_trb == td->last_trb)
+ if (ep_trb == td->end_trb)
td->urb->actual_length = requested - remaining;
else
td->urb->actual_length =
- sum_trb_lengths(xhci, ep_ring, ep_trb) +
+ sum_trb_lengths(td, ep_trb) +
ep_trb_len - remaining;
finish_td:
if (remaining > requested) {
@@ -2572,7 +2612,7 @@ finish_td:
td->urb->actual_length = 0;
}
- return finish_td(xhci, ep, ep_ring, td, trb_comp_code);
+ finish_td(xhci, ep, ep_ring, td, trb_comp_code);
}
/* Transfer events which don't point to a transfer TRB, see xhci 4.17.4 */
@@ -2792,10 +2832,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (td && td->error_mid_td && !trb_in_td(xhci, td, ep_trb_dma, false)) {
xhci_dbg(xhci, "Missing TD completion event after mid TD error\n");
- ep_ring->dequeue = td->last_trb;
- ep_ring->deq_seg = td->last_trb_seg;
- inc_deq(xhci, ep_ring);
- xhci_td_cleanup(xhci, td, ep_ring, td->status);
+ xhci_dequeue_td(xhci, td, ep_ring, td->status);
}
if (list_empty(&ep_ring->td_list)) {
@@ -2889,7 +2926,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep_ring->last_td_was_short = false;
ep_trb = &ep_seg->trbs[(ep_trb_dma - ep_seg->dma) / sizeof(*ep_trb)];
- trace_xhci_handle_transfer(ep_ring, (struct xhci_generic_trb *) ep_trb);
+ trace_xhci_handle_transfer(ep_ring, (struct xhci_generic_trb *) ep_trb, ep_trb_dma);
/*
* No-op TRB could trigger interrupts in a case where a URB was killed
@@ -2939,7 +2976,9 @@ static int xhci_handle_event_trb(struct xhci_hcd *xhci, struct xhci_interrupter
{
u32 trb_type;
- trace_xhci_handle_event(ir->event_ring, &event->generic);
+ trace_xhci_handle_event(ir->event_ring, &event->generic,
+ xhci_trb_virt_to_dma(ir->event_ring->deq_seg,
+ ir->event_ring->dequeue));
/*
* Barrier between reading the TRB_CYCLE (valid) flag before, and any
@@ -3162,7 +3201,8 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
wmb();
trb->field[3] = cpu_to_le32(field4);
- trace_xhci_queue_trb(ring, trb);
+ trace_xhci_queue_trb(ring, trb,
+ xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue));
inc_enq(xhci, ring, more_trbs_coming);
}
@@ -3302,7 +3342,7 @@ static int prepare_transfer(struct xhci_hcd *xhci,
/* Add this TD to the tail of the endpoint ring's TD list */
list_add_tail(&td->td_list, &ep_ring->td_list);
td->start_seg = ep_ring->enq_seg;
- td->first_trb = ep_ring->enqueue;
+ td->start_trb = ep_ring->enqueue;
return 0;
}
@@ -3641,8 +3681,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
field &= ~TRB_CHAIN;
field |= TRB_IOC;
more_trbs_coming = false;
- td->last_trb = ring->enqueue;
- td->last_trb_seg = ring->enq_seg;
+ td->end_trb = ring->enqueue;
+ td->end_seg = ring->enq_seg;
if (xhci_urb_suitable_for_idt(urb)) {
memcpy(&send_addr, urb->transfer_buffer,
trb_buff_len);
@@ -3690,8 +3730,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
ret = prepare_transfer(xhci, xhci->devs[slot_id],
ep_index, urb->stream_id,
1, urb, 1, mem_flags);
- urb_priv->td[1].last_trb = ring->enqueue;
- urb_priv->td[1].last_trb_seg = ring->enq_seg;
+ urb_priv->td[1].end_trb = ring->enqueue;
+ urb_priv->td[1].end_seg = ring->enq_seg;
field = TRB_TYPE(TRB_NORMAL) | ring->cycle_state | TRB_IOC;
queue_trb(xhci, ring, 0, 0, 0, TRB_INTR_TARGET(0), field);
}
@@ -3727,6 +3767,20 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (!urb->setup_packet)
return -EINVAL;
+ if ((xhci->quirks & XHCI_ETRON_HOST) &&
+ urb->dev->speed >= USB_SPEED_SUPER) {
+ /*
+ * If next available TRB is the Link TRB in the ring segment then
+ * enqueue a No Op TRB, this can prevent the Setup and Data Stage
+ * TRB to be breaked by the Link TRB.
+ */
+ if (trb_is_link(ep_ring->enqueue + 1)) {
+ field = TRB_TYPE(TRB_TR_NOOP) | ep_ring->cycle_state;
+ queue_trb(xhci, ep_ring, false, 0, 0,
+ TRB_INTR_TARGET(0), field);
+ }
+ }
+
/* 1 TRB for setup, 1 for status */
num_trbs = 2;
/*
@@ -3815,8 +3869,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
}
/* Save the DMA address of the last TRB in the TD */
- td->last_trb = ep_ring->enqueue;
- td->last_trb_seg = ep_ring->enq_seg;
+ td->end_trb = ep_ring->enqueue;
+ td->end_seg = ep_ring->enq_seg;
/* Queue status TRB - see Table 7 and sections 4.11.2.2 and 6.4.1.2.3 */
/* If the device sent data, the status stage is an OUT transfer */
@@ -4101,8 +4155,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
field |= TRB_CHAIN;
} else {
more_trbs_coming = false;
- td->last_trb = ep_ring->enqueue;
- td->last_trb_seg = ep_ring->enq_seg;
+ td->end_trb = ep_ring->enqueue;
+ td->end_seg = ep_ring->enq_seg;
field |= TRB_IOC;
if (trb_block_event_intr(xhci, num_tds, i, ir))
field |= TRB_BEI;
@@ -4168,14 +4222,14 @@ cleanup:
/* Use the first TD as a temporary variable to turn the TDs we've queued
* into No-ops with a software-owned cycle bit. That way the hardware
* won't accidentally start executing bogus TDs when we partially
- * overwrite them. td->first_trb and td->start_seg are already set.
+ * overwrite them. td->start_trb and td->start_seg are already set.
*/
- urb_priv->td[0].last_trb = ep_ring->enqueue;
+ urb_priv->td[0].end_trb = ep_ring->enqueue;
/* Every TRB except the first & last will have its cycle bit flipped. */
- td_to_noop(xhci, ep_ring, &urb_priv->td[0], true);
+ td_to_noop(&urb_priv->td[0], true);
/* Reset the ring enqueue back to the first TRB and its cycle bit. */
- ep_ring->enqueue = urb_priv->td[0].first_trb;
+ ep_ring->enqueue = urb_priv->td[0].start_trb;
ep_ring->enq_seg = urb_priv->td[0].start_seg;
ep_ring->cycle_state = start_cycle;
usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 76f228e7443c..06ae193ec874 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -2664,7 +2664,7 @@ MODULE_DEVICE_TABLE(of, tegra_xusb_of_match);
static struct platform_driver tegra_xusb_driver = {
.probe = tegra_xusb_probe,
- .remove_new = tegra_xusb_remove,
+ .remove = tegra_xusb_remove,
.shutdown = tegra_xusb_shutdown,
.driver = {
.name = "tegra-xusb",
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
index 24405315ffe6..bfb5c5c17012 100644
--- a/drivers/usb/host/xhci-trace.h
+++ b/drivers/usb/host/xhci-trace.h
@@ -108,9 +108,10 @@ DEFINE_EVENT(xhci_log_ctx, xhci_address_ctx,
);
DECLARE_EVENT_CLASS(xhci_log_trb,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb),
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma),
TP_STRUCT__entry(
+ __field(dma_addr_t, dma)
__field(u32, type)
__field(u32, field0)
__field(u32, field1)
@@ -118,51 +119,54 @@ DECLARE_EVENT_CLASS(xhci_log_trb,
__field(u32, field3)
),
TP_fast_assign(
+ __entry->dma = dma;
__entry->type = ring->type;
__entry->field0 = le32_to_cpu(trb->field[0]);
__entry->field1 = le32_to_cpu(trb->field[1]);
__entry->field2 = le32_to_cpu(trb->field[2]);
__entry->field3 = le32_to_cpu(trb->field[3]);
),
- TP_printk("%s: %s", xhci_ring_type_string(__entry->type),
+ TP_printk("%s: @%pad %s",
+ xhci_ring_type_string(__entry->type), &__entry->dma,
xhci_decode_trb(__get_buf(XHCI_MSG_MAX), XHCI_MSG_MAX, __entry->field0,
__entry->field1, __entry->field2, __entry->field3)
)
);
DEFINE_EVENT(xhci_log_trb, xhci_handle_event,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
);
DEFINE_EVENT(xhci_log_trb, xhci_handle_command,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
);
DEFINE_EVENT(xhci_log_trb, xhci_handle_transfer,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
);
DEFINE_EVENT(xhci_log_trb, xhci_queue_trb,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
+
);
DEFINE_EVENT(xhci_log_trb, xhci_dbc_handle_event,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
);
DEFINE_EVENT(xhci_log_trb, xhci_dbc_handle_transfer,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
);
DEFINE_EVENT(xhci_log_trb, xhci_dbc_gadget_ep_queue,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
);
DECLARE_EVENT_CLASS(xhci_log_free_virt_dev,
@@ -310,6 +314,37 @@ DEFINE_EVENT(xhci_log_urb, xhci_urb_dequeue,
TP_ARGS(urb)
);
+DECLARE_EVENT_CLASS(xhci_log_stream_ctx,
+ TP_PROTO(struct xhci_stream_info *info, unsigned int stream_id),
+ TP_ARGS(info, stream_id),
+ TP_STRUCT__entry(
+ __field(unsigned int, stream_id)
+ __field(u64, stream_ring)
+ __field(dma_addr_t, ctx_array_dma)
+
+ ),
+ TP_fast_assign(
+ __entry->stream_id = stream_id;
+ __entry->stream_ring = le64_to_cpu(info->stream_ctx_array[stream_id].stream_ring);
+ __entry->ctx_array_dma = info->ctx_array_dma + stream_id * 16;
+
+ ),
+ TP_printk("stream %u ctx @%pad: SCT %llu deq %llx", __entry->stream_id,
+ &__entry->ctx_array_dma, CTX_TO_SCT(__entry->stream_ring),
+ __entry->stream_ring
+ )
+);
+
+DEFINE_EVENT(xhci_log_stream_ctx, xhci_alloc_stream_info_ctx,
+ TP_PROTO(struct xhci_stream_info *info, unsigned int stream_id),
+ TP_ARGS(info, stream_id)
+);
+
+DEFINE_EVENT(xhci_log_stream_ctx, xhci_handle_cmd_set_deq_stream,
+ TP_PROTO(struct xhci_stream_info *info, unsigned int stream_id),
+ TP_ARGS(info, stream_id)
+);
+
DECLARE_EVENT_CLASS(xhci_log_ep_ctx,
TP_PROTO(struct xhci_ep_ctx *ctx),
TP_ARGS(ctx),
@@ -454,8 +489,6 @@ DECLARE_EVENT_CLASS(xhci_log_ring,
__field(void *, ring)
__field(dma_addr_t, enq)
__field(dma_addr_t, deq)
- __field(dma_addr_t, enq_seg)
- __field(dma_addr_t, deq_seg)
__field(unsigned int, num_segs)
__field(unsigned int, stream_id)
__field(unsigned int, cycle_state)
@@ -466,17 +499,15 @@ DECLARE_EVENT_CLASS(xhci_log_ring,
__entry->type = ring->type;
__entry->num_segs = ring->num_segs;
__entry->stream_id = ring->stream_id;
- __entry->enq_seg = ring->enq_seg->dma;
- __entry->deq_seg = ring->deq_seg->dma;
__entry->cycle_state = ring->cycle_state;
__entry->bounce_buf_len = ring->bounce_buf_len;
__entry->enq = xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue);
__entry->deq = xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue);
),
- TP_printk("%s %p: enq %pad(%pad) deq %pad(%pad) segs %d stream %d bounce %d cycle %d",
+ TP_printk("%s %p: enq %pad deq %pad segs %d stream %d bounce %d cycle %d",
xhci_ring_type_string(__entry->type), __entry->ring,
- &__entry->enq, &__entry->enq_seg,
- &__entry->deq, &__entry->deq_seg,
+ &__entry->enq,
+ &__entry->deq,
__entry->num_segs,
__entry->stream_id,
__entry->bounce_buf_len,
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 899c0effb5d3..5ebde8cae4fc 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -8,6 +8,7 @@
* Some code borrowed from the Linux EHCI driver.
*/
+#include <linux/jiffies.h>
#include <linux/pci.h>
#include <linux/iommu.h>
#include <linux/iopoll.h>
@@ -40,15 +41,15 @@ MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default");
static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
{
- struct xhci_segment *seg = ring->first_seg;
+ struct xhci_segment *seg;
if (!td || !td->start_seg)
return false;
- do {
+
+ xhci_for_each_ring_seg(ring->first_seg, seg) {
if (seg == td->start_seg)
return true;
- seg = seg->next;
- } while (seg && seg != ring->first_seg);
+ }
return false;
}
@@ -473,14 +474,7 @@ static int xhci_init(struct usb_hcd *hcd)
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xhci_init");
spin_lock_init(&xhci->lock);
- if (xhci->hci_version == 0x95 && link_quirk) {
- xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
- "QUIRK: Not clearing Link TRB chain bits.");
- xhci->quirks |= XHCI_LINK_TRB_QUIRK;
- } else {
- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
- "xHCI doesn't need link TRB QUIRK");
- }
+
retval = xhci_mem_init(xhci, GFP_KERNEL);
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Finished xhci_init");
@@ -785,16 +779,10 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
struct xhci_segment *seg;
ring = xhci->cmd_ring;
- seg = ring->deq_seg;
- do {
- memset(seg->trbs, 0,
- sizeof(union xhci_trb) * (TRBS_PER_SEGMENT - 1));
- seg->trbs[TRBS_PER_SEGMENT - 1].link.control &=
- cpu_to_le32(~TRB_CYCLE);
- seg = seg->next;
- } while (seg != ring->deq_seg);
-
- xhci_initialize_ring_info(ring, 1);
+ xhci_for_each_ring_seg(ring->first_seg, seg)
+ memset(seg->trbs, 0, sizeof(union xhci_trb) * (TRBS_PER_SEGMENT - 1));
+
+ xhci_initialize_ring_info(ring);
/*
* Reset the hardware dequeue pointer.
* Yes, this will need to be re-written after resume, but we're paranoid
@@ -1756,7 +1744,7 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
urb->ep->desc.bEndpointAddress,
(unsigned long long) xhci_trb_virt_to_dma(
urb_priv->td[i].start_seg,
- urb_priv->td[i].first_trb));
+ urb_priv->td[i].start_trb));
for (; i < urb_priv->num_tds; i++) {
td = &urb_priv->td[i];
@@ -1768,15 +1756,27 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
}
}
- /* Queue a stop endpoint command, but only if this is
- * the first cancellation to be handled.
- */
- if (!(ep->ep_state & EP_STOP_CMD_PENDING)) {
+ /* These completion handlers will sort out cancelled TDs for us */
+ if (ep->ep_state & (EP_STOP_CMD_PENDING | EP_HALTED | SET_DEQ_PENDING)) {
+ xhci_dbg(xhci, "Not queuing Stop Endpoint on slot %d ep %d in state 0x%x\n",
+ urb->dev->slot_id, ep_index, ep->ep_state);
+ goto done;
+ }
+
+ /* In this case no commands are pending but the endpoint is stopped */
+ if (ep->ep_state & EP_CLEARING_TT) {
+ /* and cancelled TDs can be given back right away */
+ xhci_dbg(xhci, "Invalidating TDs instantly on slot %d ep %d in state 0x%x\n",
+ urb->dev->slot_id, ep_index, ep->ep_state);
+ xhci_process_cancelled_tds(ep);
+ } else {
+ /* Otherwise, queue a new Stop Endpoint command */
command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
if (!command) {
ret = -ENOMEM;
goto done;
}
+ ep->stop_time = jiffies;
ep->ep_state |= EP_STOP_CMD_PENDING;
xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id,
ep_index, 0);
@@ -2794,6 +2794,51 @@ static int xhci_reserve_bandwidth(struct xhci_hcd *xhci,
return -ENOMEM;
}
+/*
+ * Synchronous XHCI stop endpoint helper. Issues the stop endpoint command and
+ * waits for the command completion before returning. This does not call
+ * xhci_handle_cmd_stop_ep(), which has additional handling for 'context error'
+ * cases, along with transfer ring cleanup.
+ *
+ * xhci_stop_endpoint_sync() is intended to be utilized by clients that manage
+ * their own transfer ring, such as offload situations.
+ */
+int xhci_stop_endpoint_sync(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, int suspend,
+ gfp_t gfp_flags)
+{
+ struct xhci_command *command;
+ unsigned long flags;
+ int ret;
+
+ command = xhci_alloc_command(xhci, true, gfp_flags);
+ if (!command)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&xhci->lock, flags);
+ ret = xhci_queue_stop_endpoint(xhci, command, ep->vdev->slot_id,
+ ep->ep_index, suspend);
+ if (ret < 0) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ goto out;
+ }
+
+ xhci_ring_cmd_db(xhci);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+
+ wait_for_completion(command->completion);
+
+ /* No handling for COMP_CONTEXT_STATE_ERROR done at command completion*/
+ if (command->status == COMP_COMMAND_ABORTED ||
+ command->status == COMP_COMMAND_RING_STOPPED) {
+ xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n");
+ ret = -ETIME;
+ }
+out:
+ xhci_free_command(xhci, command);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(xhci_stop_endpoint_sync);
/* Issue a configure endpoint command or evaluate context command
* and wait for it to finish.
@@ -3692,6 +3737,8 @@ void xhci_free_device_endpoint_resources(struct xhci_hcd *xhci,
xhci->num_active_eps);
}
+static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev);
+
/*
* This submits a Reset Device Command, which will set the device state to 0,
* set the device address to 0, and disable all the endpoints except the default
@@ -3762,6 +3809,23 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd,
SLOT_STATE_DISABLED)
return 0;
+ if (xhci->quirks & XHCI_ETRON_HOST) {
+ /*
+ * Obtaining a new device slot to inform the xHCI host that
+ * the USB device has been reset.
+ */
+ ret = xhci_disable_slot(xhci, udev->slot_id);
+ xhci_free_virt_device(xhci, udev->slot_id);
+ if (!ret) {
+ ret = xhci_alloc_dev(hcd, udev);
+ if (ret == 1)
+ ret = 0;
+ else
+ ret = -EINVAL;
+ }
+ return ret;
+ }
+
trace_xhci_discover_or_reset_device(slot_ctx);
xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id);
@@ -5251,6 +5315,11 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
if (xhci->hci_version > 0x96)
xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
+ if (xhci->hci_version == 0x95 && link_quirk) {
+ xhci_dbg(xhci, "QUIRK: Not clearing Link TRB chain bits");
+ xhci->quirks |= XHCI_LINK_TRB_QUIRK;
+ }
+
/* Make sure the HC is halted. */
retval = xhci_halt(xhci);
if (retval)
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index f0fb696d5619..4914f0a10cff 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -554,6 +554,7 @@ struct xhci_stream_ctx {
/* Stream Context Types (section 6.4.1) - bits 3:1 of stream ctx deq ptr */
#define SCT_FOR_CTX(p) (((p) & 0x7) << 1)
+#define CTX_TO_SCT(p) (((p) >> 1) & 0x7)
/* Secondary stream array type, dequeue pointer is to a transfer ring */
#define SCT_SEC_TR 0
/* Primary stream array type, dequeue pointer is to a transfer ring */
@@ -690,6 +691,7 @@ struct xhci_virt_ep {
/* Bandwidth checking storage */
struct xhci_bw_info bw_info;
struct list_head bw_endpoint_list;
+ unsigned long stop_time;
/* Isoch Frame ID checking storage */
int next_frame_id;
/* Use new Isoch TRB layout needed for extended TBC support */
@@ -1023,9 +1025,6 @@ enum xhci_setup_dev {
/* Interrupter Target - which MSI-X vector to target the completion event at */
#define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22)
#define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff)
-/* Total burst count field, Rsvdz on xhci 1.1 with Extended TBC enabled (ETE) */
-#define TRB_TBC(p) (((p) & 0x3) << 7)
-#define TRB_TLBPC(p) (((p) & 0xf) << 16)
/* Cycle bit - indicates TRB ownership by HC or HCD */
#define TRB_CYCLE (1<<0)
@@ -1059,6 +1058,12 @@ enum xhci_setup_dev {
/* Isochronous TRB specific fields */
#define TRB_SIA (1<<31)
#define TRB_FRAME_ID(p) (((p) & 0x7ff) << 20)
+#define GET_FRAME_ID(p) (((p) >> 20) & 0x7ff)
+/* Total burst count field, Rsvdz on xhci 1.1 with Extended TBC enabled (ETE) */
+#define TRB_TBC(p) (((p) & 0x3) << 7)
+#define GET_TBC(p) (((p) >> 7) & 0x3)
+#define TRB_TLBPC(p) (((p) & 0xf) << 16)
+#define GET_TLBPC(p) (((p) >> 16) & 0xf)
/* TRB cache size for xHC with TRB cache */
#define TRB_CACHE_SIZE_HS 8
@@ -1259,6 +1264,9 @@ static inline const char *xhci_trb_type_string(u8 type)
#define AVOID_BEI_INTERVAL_MIN 8
#define AVOID_BEI_INTERVAL_MAX 32
+#define xhci_for_each_ring_seg(head, seg) \
+ for (seg = head; seg != NULL; seg = (seg->next != head ? seg->next : NULL))
+
struct xhci_segment {
union xhci_trb *trbs;
/* private to HCD */
@@ -1287,9 +1295,9 @@ struct xhci_td {
enum xhci_cancelled_td_status cancel_status;
struct urb *urb;
struct xhci_segment *start_seg;
- union xhci_trb *first_trb;
- union xhci_trb *last_trb;
- struct xhci_segment *last_trb_seg;
+ union xhci_trb *start_trb;
+ struct xhci_segment *end_seg;
+ union xhci_trb *end_trb;
struct xhci_segment *bounce_seg;
/* actual_length of the URB has already been set */
bool urb_length_set;
@@ -1624,6 +1632,7 @@ struct xhci_hcd {
#define XHCI_ZHAOXIN_HOST BIT_ULL(46)
#define XHCI_WRITE_64_HI_LO BIT_ULL(47)
#define XHCI_CDNS_SCTX_QUIRK BIT_ULL(48)
+#define XHCI_ETRON_HOST BIT_ULL(49)
unsigned int num_active_eps;
unsigned int limit_active_eps;
@@ -1788,14 +1797,12 @@ void xhci_slot_copy(struct xhci_hcd *xhci,
int xhci_endpoint_init(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev,
struct usb_device *udev, struct usb_host_endpoint *ep,
gfp_t mem_flags);
-struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
- unsigned int num_segs, unsigned int cycle_state,
+struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, unsigned int num_segs,
enum xhci_ring_type type, unsigned int max_packet, gfp_t flags);
void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring);
int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
unsigned int num_trbs, gfp_t flags);
-void xhci_initialize_ring_info(struct xhci_ring *ring,
- unsigned int cycle_state);
+void xhci_initialize_ring_info(struct xhci_ring *ring);
void xhci_free_endpoint_ring(struct xhci_hcd *xhci,
struct xhci_virt_device *virt_dev,
unsigned int ep_index);
@@ -1913,6 +1920,9 @@ void xhci_ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
void xhci_cleanup_command_queue(struct xhci_hcd *xhci);
void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring);
unsigned int count_trbs(u64 addr, u64 len);
+int xhci_stop_endpoint_sync(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+ int suspend, gfp_t gfp_flags);
+void xhci_process_cancelled_tds(struct xhci_virt_ep *ep);
/* xHCI roothub code */
void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,
@@ -2070,7 +2080,6 @@ static inline const char *xhci_decode_trb(char *str, size_t size,
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_NORMAL:
- case TRB_ISOC:
case TRB_EVENT_DATA:
case TRB_TR_NOOP:
snprintf(str, size,
@@ -2087,7 +2096,25 @@ static inline const char *xhci_decode_trb(char *str, size_t size,
field3 & TRB_ENT ? 'E' : 'e',
field3 & TRB_CYCLE ? 'C' : 'c');
break;
-
+ case TRB_ISOC:
+ snprintf(str, size,
+ "Buffer %08x%08x length %d TD size/TBC %d intr %d type '%s' TBC %u TLBPC %u frame_id %u flags %c:%c:%c:%c:%c:%c:%c:%c:%c",
+ field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2),
+ GET_INTR_TARGET(field2),
+ xhci_trb_type_string(type),
+ GET_TBC(field3),
+ GET_TLBPC(field3),
+ GET_FRAME_ID(field3),
+ field3 & TRB_SIA ? 'S' : 's',
+ field3 & TRB_BEI ? 'B' : 'b',
+ field3 & TRB_IDT ? 'I' : 'i',
+ field3 & TRB_IOC ? 'I' : 'i',
+ field3 & TRB_CHAIN ? 'C' : 'c',
+ field3 & TRB_NO_SNOOP ? 'S' : 's',
+ field3 & TRB_ISP ? 'I' : 'i',
+ field3 & TRB_ENT ? 'E' : 'e',
+ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
case TRB_CMD_NOOP:
case TRB_ENABLE_SLOT:
snprintf(str, size,
diff --git a/drivers/usb/isp1760/Kconfig b/drivers/usb/isp1760/Kconfig
index 2ed2b73291d1..e19178f3cdd3 100644
--- a/drivers/usb/isp1760/Kconfig
+++ b/drivers/usb/isp1760/Kconfig
@@ -26,7 +26,7 @@ config USB_ISP1761_UDC
if USB_ISP1760
choice
- bool "ISP1760 Mode Selection"
+ prompt "ISP1760 Mode Selection"
default USB_ISP1760_DUAL_ROLE if (USB && USB_GADGET)
default USB_ISP1760_HOST_ROLE if (USB && !USB_GADGET)
default USB_ISP1760_GADGET_ROLE if (!USB && USB_GADGET)
diff --git a/drivers/usb/isp1760/isp1760-if.c b/drivers/usb/isp1760/isp1760-if.c
index fe1e3985419a..a64190addba6 100644
--- a/drivers/usb/isp1760/isp1760-if.c
+++ b/drivers/usb/isp1760/isp1760-if.c
@@ -263,7 +263,7 @@ MODULE_DEVICE_TABLE(of, isp1760_of_match);
static struct platform_driver isp1760_plat_driver = {
.probe = isp1760_plat_probe,
- .remove_new = isp1760_plat_remove,
+ .remove = isp1760_plat_remove,
.driver = {
.name = "isp1760",
.of_match_table = of_match_ptr(isp1760_of_match),
diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
index 6fb5140e29b9..225863321dc4 100644
--- a/drivers/usb/misc/chaoskey.c
+++ b/drivers/usb/misc/chaoskey.c
@@ -27,6 +27,8 @@ static struct usb_class_driver chaoskey_class;
static int chaoskey_rng_read(struct hwrng *rng, void *data,
size_t max, bool wait);
+static DEFINE_MUTEX(chaoskey_list_lock);
+
#define usb_dbg(usb_if, format, arg...) \
dev_dbg(&(usb_if)->dev, format, ## arg)
@@ -233,6 +235,7 @@ static void chaoskey_disconnect(struct usb_interface *interface)
usb_deregister_dev(interface, &chaoskey_class);
usb_set_intfdata(interface, NULL);
+ mutex_lock(&chaoskey_list_lock);
mutex_lock(&dev->lock);
dev->present = false;
@@ -244,6 +247,7 @@ static void chaoskey_disconnect(struct usb_interface *interface)
} else
mutex_unlock(&dev->lock);
+ mutex_unlock(&chaoskey_list_lock);
usb_dbg(interface, "disconnect done");
}
@@ -251,6 +255,7 @@ static int chaoskey_open(struct inode *inode, struct file *file)
{
struct chaoskey *dev;
struct usb_interface *interface;
+ int rv = 0;
/* get the interface from minor number and driver information */
interface = usb_find_interface(&chaoskey_driver, iminor(inode));
@@ -266,18 +271,23 @@ static int chaoskey_open(struct inode *inode, struct file *file)
}
file->private_data = dev;
+ mutex_lock(&chaoskey_list_lock);
mutex_lock(&dev->lock);
- ++dev->open;
+ if (dev->present)
+ ++dev->open;
+ else
+ rv = -ENODEV;
mutex_unlock(&dev->lock);
+ mutex_unlock(&chaoskey_list_lock);
- usb_dbg(interface, "open success");
- return 0;
+ return rv;
}
static int chaoskey_release(struct inode *inode, struct file *file)
{
struct chaoskey *dev = file->private_data;
struct usb_interface *interface;
+ int rv = 0;
if (dev == NULL)
return -ENODEV;
@@ -286,14 +296,15 @@ static int chaoskey_release(struct inode *inode, struct file *file)
usb_dbg(interface, "release");
+ mutex_lock(&chaoskey_list_lock);
mutex_lock(&dev->lock);
usb_dbg(interface, "open count at release is %d", dev->open);
if (dev->open <= 0) {
usb_dbg(interface, "invalid open count (%d)", dev->open);
- mutex_unlock(&dev->lock);
- return -ENODEV;
+ rv = -ENODEV;
+ goto bail;
}
--dev->open;
@@ -302,13 +313,15 @@ static int chaoskey_release(struct inode *inode, struct file *file)
if (dev->open == 0) {
mutex_unlock(&dev->lock);
chaoskey_free(dev);
- } else
- mutex_unlock(&dev->lock);
- } else
- mutex_unlock(&dev->lock);
-
+ goto destruction;
+ }
+ }
+bail:
+ mutex_unlock(&dev->lock);
+destruction:
+ mutex_unlock(&chaoskey_list_lock);
usb_dbg(interface, "release success");
- return 0;
+ return rv;
}
static void chaos_read_callback(struct urb *urb)
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 6d28467ce352..365c10069345 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -277,28 +277,45 @@ static ssize_t iowarrior_read(struct file *file, char __user *buffer,
struct iowarrior *dev;
int read_idx;
int offset;
+ int retval;
dev = file->private_data;
+ if (file->f_flags & O_NONBLOCK) {
+ retval = mutex_trylock(&dev->mutex);
+ if (!retval)
+ return -EAGAIN;
+ } else {
+ retval = mutex_lock_interruptible(&dev->mutex);
+ if (retval)
+ return -ERESTARTSYS;
+ }
+
/* verify that the device wasn't unplugged */
- if (!dev || !dev->present)
- return -ENODEV;
+ if (!dev->present) {
+ retval = -ENODEV;
+ goto exit;
+ }
dev_dbg(&dev->interface->dev, "minor %d, count = %zd\n",
dev->minor, count);
/* read count must be packet size (+ time stamp) */
if ((count != dev->report_size)
- && (count != (dev->report_size + 1)))
- return -EINVAL;
+ && (count != (dev->report_size + 1))) {
+ retval = -EINVAL;
+ goto exit;
+ }
/* repeat until no buffer overrun in callback handler occur */
do {
atomic_set(&dev->overflow_flag, 0);
if ((read_idx = read_index(dev)) == -1) {
/* queue empty */
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ goto exit;
+ }
else {
//next line will return when there is either new data, or the device is unplugged
int r = wait_event_interruptible(dev->read_wait,
@@ -309,28 +326,37 @@ static ssize_t iowarrior_read(struct file *file, char __user *buffer,
-1));
if (r) {
//we were interrupted by a signal
- return -ERESTART;
+ retval = -ERESTART;
+ goto exit;
}
if (!dev->present) {
//The device was unplugged
- return -ENODEV;
+ retval = -ENODEV;
+ goto exit;
}
if (read_idx == -1) {
// Can this happen ???
- return 0;
+ retval = 0;
+ goto exit;
}
}
}
offset = read_idx * (dev->report_size + 1);
if (copy_to_user(buffer, dev->read_queue + offset, count)) {
- return -EFAULT;
+ retval = -EFAULT;
+ goto exit;
}
} while (atomic_read(&dev->overflow_flag));
read_idx = ++read_idx == MAX_INTERRUPT_BUFFER ? 0 : read_idx;
atomic_set(&dev->read_idx, read_idx);
+ mutex_unlock(&dev->mutex);
return count;
+
+exit:
+ mutex_unlock(&dev->mutex);
+ return retval;
}
/*
@@ -885,7 +911,6 @@ error:
static void iowarrior_disconnect(struct usb_interface *interface)
{
struct iowarrior *dev = usb_get_intfdata(interface);
- int minor = dev->minor;
usb_deregister_dev(interface, &iowarrior_class);
@@ -909,9 +934,6 @@ static void iowarrior_disconnect(struct usb_interface *interface)
mutex_unlock(&dev->mutex);
iowarrior_delete(dev);
}
-
- dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",
- minor - IOWARRIOR_MINOR_BASE);
}
/* usb specific object needed to register this driver with the usb subsystem */
diff --git a/drivers/usb/misc/onboard_usb_dev.c b/drivers/usb/misc/onboard_usb_dev.c
index 75dfdca04ff1..36b11127280f 100644
--- a/drivers/usb/misc/onboard_usb_dev.c
+++ b/drivers/usb/misc/onboard_usb_dev.c
@@ -473,7 +473,7 @@ static const struct dev_pm_ops __maybe_unused onboard_dev_pm_ops = {
static struct platform_driver onboard_dev_driver = {
.probe = onboard_dev_probe,
- .remove_new = onboard_dev_remove,
+ .remove = onboard_dev_remove,
.driver = {
.name = "onboard-usb-dev",
diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c
index 19906301a4eb..83079c414b4f 100644
--- a/drivers/usb/misc/qcom_eud.c
+++ b/drivers/usb/misc/qcom_eud.c
@@ -239,7 +239,7 @@ MODULE_DEVICE_TABLE(of, eud_dt_match);
static struct platform_driver eud_driver = {
.probe = eud_probe,
- .remove_new = eud_remove,
+ .remove = eud_remove,
.driver = {
.name = "qcom_eud",
.dev_groups = eud_groups,
diff --git a/drivers/usb/misc/usb-ljca.c b/drivers/usb/misc/usb-ljca.c
index 01ceafc4ab78..d9c21f783055 100644
--- a/drivers/usb/misc/usb-ljca.c
+++ b/drivers/usb/misc/usb-ljca.c
@@ -332,14 +332,11 @@ static int ljca_send(struct ljca_adapter *adap, u8 type, u8 cmd,
ret = usb_bulk_msg(adap->usb_dev, adap->tx_pipe, header,
msg_len, &transferred, LJCA_WRITE_TIMEOUT_MS);
-
- usb_autopm_put_interface(adap->intf);
-
if (ret < 0)
- goto out;
+ goto out_put;
if (transferred != msg_len) {
ret = -EIO;
- goto out;
+ goto out_put;
}
if (ack) {
@@ -347,11 +344,14 @@ static int ljca_send(struct ljca_adapter *adap, u8 type, u8 cmd,
timeout);
if (!ret) {
ret = -ETIMEDOUT;
- goto out;
+ goto out_put;
}
}
ret = adap->actual_length;
+out_put:
+ usb_autopm_put_interface(adap->intf);
+
out:
spin_lock_irqsave(&adap->lock, flags);
adap->ex_buf = NULL;
@@ -811,6 +811,14 @@ static int ljca_probe(struct usb_interface *interface,
if (ret)
goto err_free;
+ /*
+ * This works around problems with ov2740 initialization on some
+ * Lenovo platforms. The autosuspend delay, has to be smaller than
+ * the delay after setting the reset_gpio line in ov2740_resume().
+ * Otherwise the sensor randomly fails to initialize.
+ */
+ pm_runtime_set_autosuspend_delay(&usb_dev->dev, 10);
+
usb_enable_autosuspend(usb_dev);
return 0;
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index 3b33e4878c60..322e59381b78 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -423,7 +423,7 @@ static struct platform_driver usb3503_platform_driver = {
.pm = pm_ptr(&usb3503_platform_pm_ops),
},
.probe = usb3503_platform_probe,
- .remove_new = usb3503_platform_remove,
+ .remove = usb3503_platform_remove,
};
static int __init usb3503_init(void)
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index caf65f8294db..8d379ae835bc 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -2021,7 +2021,8 @@ static struct urb *iso_alloc_urb(
for (i = 0; i < packets; i++) {
/* here, only the last packet will be short */
- urb->iso_frame_desc[i].length = min((unsigned) bytes, maxp);
+ urb->iso_frame_desc[i].length = min_t(unsigned int,
+ bytes, maxp);
bytes -= urb->iso_frame_desc[i].length;
urb->iso_frame_desc[i].offset = maxp * i;
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
index 6aebc736a80c..70dff0db5354 100644
--- a/drivers/usb/misc/yurex.c
+++ b/drivers/usb/misc/yurex.c
@@ -441,7 +441,10 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer,
if (count == 0)
goto error;
- mutex_lock(&dev->io_mutex);
+ retval = mutex_lock_interruptible(&dev->io_mutex);
+ if (retval < 0)
+ return -EINTR;
+
if (dev->disconnected) { /* already disconnected */
mutex_unlock(&dev->io_mutex);
retval = -ENODEV;
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index afb71c18415d..c93b43f5bc46 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -823,7 +823,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
ep = MON_OFF2HDR(rp, rp->b_out);
if (rp->b_read < hdrbytes) {
- step_len = min(nbytes, (size_t)(hdrbytes - rp->b_read));
+ step_len = min_t(size_t, nbytes, hdrbytes - rp->b_read);
ptr = ((char *)ep) + rp->b_read;
if (step_len && copy_to_user(buf, ptr, step_len)) {
mutex_unlock(&rp->fetch_lock);
diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig
index bf98fd36341d..d281da1cdbcc 100644
--- a/drivers/usb/mtu3/Kconfig
+++ b/drivers/usb/mtu3/Kconfig
@@ -21,7 +21,7 @@ config USB_MTU3
if USB_MTU3
choice
- bool "MTU3 Mode Selection"
+ prompt "MTU3 Mode Selection"
default USB_MTU3_DUAL_ROLE if (USB && USB_GADGET)
default USB_MTU3_HOST if (USB && !USB_GADGET)
default USB_MTU3_GADGET if (!USB && USB_GADGET)
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index 6858ed9fc3b2..7b5a431acb56 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -307,7 +307,7 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
if (otg_sx->role_sw_used || otg_sx->manual_drd_enabled)
goto out;
- if (of_property_read_bool(node, "extcon")) {
+ if (of_property_present(node, "extcon")) {
otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0);
if (IS_ERR(otg_sx->edev)) {
return dev_err_probe(dev, PTR_ERR(otg_sx->edev),
@@ -621,7 +621,7 @@ MODULE_DEVICE_TABLE(of, mtu3_of_match);
static struct platform_driver mtu3_driver = {
.probe = mtu3_probe,
- .remove_new = mtu3_remove,
+ .remove = mtu3_remove,
.driver = {
.name = MTU3_DRIVER_NAME,
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 9a8cf3de0617..9e45d12b81d3 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -29,7 +29,7 @@ config USB_MUSB_HDRC
if USB_MUSB_HDRC
choice
- bool "MUSB Mode Selection"
+ prompt "MUSB Mode Selection"
default USB_MUSB_DUAL_ROLE if (USB && USB_GADGET)
default USB_MUSB_HOST if (USB && !USB_GADGET)
default USB_MUSB_GADGET if (!USB && USB_GADGET)
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 953094c1930c..f772aa272bea 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -633,7 +633,7 @@ MODULE_DEVICE_TABLE(of, da8xx_id_table);
static struct platform_driver da8xx_driver = {
.probe = da8xx_probe,
- .remove_new = da8xx_remove,
+ .remove = da8xx_remove,
.driver = {
.name = "musb-da8xx",
.pm = &da8xx_pm_ops,
diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c
index b38df9226278..acdeb1117cd3 100644
--- a/drivers/usb/musb/jz4740.c
+++ b/drivers/usb/musb/jz4740.c
@@ -325,7 +325,7 @@ MODULE_DEVICE_TABLE(of, jz4740_musb_of_match);
static struct platform_driver jz4740_driver = {
.probe = jz4740_probe,
- .remove_new = jz4740_remove,
+ .remove = jz4740_remove,
.driver = {
.name = "musb-jz4740",
.of_match_table = jz4740_musb_of_match,
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
index 63c86c046b98..aa988d74b58d 100644
--- a/drivers/usb/musb/mediatek.c
+++ b/drivers/usb/musb/mediatek.c
@@ -523,7 +523,7 @@ MODULE_DEVICE_TABLE(of, mtk_musb_match);
static struct platform_driver mtk_musb_driver = {
.probe = mtk_musb_probe,
- .remove_new = mtk_musb_remove,
+ .remove = mtk_musb_remove,
.driver = {
.name = "musb-mtk",
.of_match_table = of_match_ptr(mtk_musb_match),
diff --git a/drivers/usb/musb/mpfs.c b/drivers/usb/musb/mpfs.c
index 00e13214aa76..7edc8429b274 100644
--- a/drivers/usb/musb/mpfs.c
+++ b/drivers/usb/musb/mpfs.c
@@ -369,7 +369,7 @@ MODULE_DEVICE_TABLE(of, mpfs_id_table);
static struct platform_driver mpfs_musb_driver = {
.probe = mpfs_probe,
- .remove_new = mpfs_remove,
+ .remove = mpfs_remove,
.driver = {
.name = "mpfs-musb",
.of_match_table = of_match_ptr(mpfs_id_table)
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index b24adb5b399f..03b1154a6014 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -1387,7 +1387,7 @@ fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep,
/* expect hw_ep has already been zero-initialized */
- size = ffs(max(maxpacket, (u16) 8)) - 1;
+ size = ffs(max_t(u16, maxpacket, 8)) - 1;
maxpacket = 1 << size;
c_size = size - 3;
@@ -2953,7 +2953,7 @@ static struct platform_driver musb_driver = {
.dev_groups = musb_groups,
},
.probe = musb_probe,
- .remove_new = musb_remove,
+ .remove = musb_remove,
};
module_platform_driver(musb_driver);
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 9c7a8bbc0542..2542239ec64e 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -1032,7 +1032,7 @@ static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
static struct platform_driver dsps_usbss_driver = {
.probe = dsps_probe,
- .remove_new = dsps_remove,
+ .remove = dsps_remove,
.driver = {
.name = "musb-dsps",
.pm = &dsps_pm_ops,
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index bdf13911a1e5..c6076df0d50c 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1161,12 +1161,19 @@ void musb_free_request(struct usb_ep *ep, struct usb_request *req)
*/
void musb_ep_restart(struct musb *musb, struct musb_request *req)
{
+ u16 csr;
+ void __iomem *epio = req->ep->hw_ep->regs;
+
trace_musb_req_start(req);
musb_ep_select(musb->mregs, req->epnum);
- if (req->tx)
+ if (req->tx) {
txstate(musb, req);
- else
- rxstate(musb, req);
+ } else {
+ csr = musb_readw(epio, MUSB_RXCSR);
+ csr |= MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_P_WZC_BITS;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
}
static int musb_ep_restart_resume_work(struct musb *musb, void *data)
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index 6d7336727388..f0786f8fbb25 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -533,7 +533,7 @@ static void ep0_txstate(struct musb *musb)
/* load the data */
fifo_src = (u8 *) request->buf + request->actual;
- fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE,
+ fifo_count = min_t(unsigned, MUSB_EP0_FIFOSIZE,
request->length - request->actual);
musb_write_fifo(&musb->endpoints[0], fifo_count, fifo_src);
request->actual += fifo_count;
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index bc4507781167..732ba981e607 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -798,10 +798,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
}
if (can_bulk_split(musb, qh->type))
- load_count = min((u32) hw_ep->max_packet_sz_tx,
- len);
+ load_count = min_t(u32, hw_ep->max_packet_sz_tx, len);
else
- load_count = min((u32) packet_sz, len);
+ load_count = min_t(u32, packet_sz, len);
if (dma_channel && musb_tx_dma_program(dma_controller,
hw_ep, qh, urb, offset, len))
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index b4a4c1df4e0d..2970967a4fd2 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -608,7 +608,7 @@ MODULE_DEVICE_TABLE(of, omap2430_id_table);
static struct platform_driver omap2430_driver = {
.probe = omap2430_probe,
- .remove_new = omap2430_remove,
+ .remove = omap2430_remove,
.driver = {
.name = "musb-omap2430",
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index 05b6e7e52e02..eac1cde86be3 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -857,7 +857,7 @@ MODULE_DEVICE_TABLE(of, sunxi_musb_match);
static struct platform_driver sunxi_musb_driver = {
.probe = sunxi_musb_probe,
- .remove_new = sunxi_musb_remove,
+ .remove = sunxi_musb_remove,
.driver = {
.name = "musb-sunxi",
.of_match_table = sunxi_musb_match,
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 461587629bf2..90b760a95e4e 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1290,7 +1290,7 @@ static void tusb_remove(struct platform_device *pdev)
static struct platform_driver tusb_driver = {
.probe = tusb_probe,
- .remove_new = tusb_remove,
+ .remove = tusb_remove,
.driver = {
.name = "musb-tusb",
},
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index c8d9d2a1d2f0..8c2a43d992f5 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -355,7 +355,7 @@ MODULE_DEVICE_TABLE(of, ux500_match);
static struct platform_driver ux500_driver = {
.probe = ux500_probe,
- .remove_new = ux500_remove,
+ .remove = ux500_remove,
.driver = {
.name = "musb-ux500",
.pm = &ux500_pm_ops,
diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 408f47e39025..6a98aeeeae31 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -987,7 +987,7 @@ MODULE_DEVICE_TABLE(platform, ab8500_usb_devtype);
static struct platform_driver ab8500_usb_driver = {
.probe = ab8500_usb_probe,
- .remove_new = ab8500_usb_remove,
+ .remove = ab8500_usb_remove,
.id_table = ab8500_usb_devtype,
.driver = {
.name = "abx5x0-usb",
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
index 6db88e00f127..ca9353dad71a 100644
--- a/drivers/usb/phy/phy-am335x.c
+++ b/drivers/usb/phy/phy-am335x.c
@@ -133,7 +133,7 @@ MODULE_DEVICE_TABLE(of, am335x_phy_ids);
static struct platform_driver am335x_phy_driver = {
.probe = am335x_phy_probe,
- .remove_new = am335x_phy_remove,
+ .remove = am335x_phy_remove,
.driver = {
.name = "am335x-phy-driver",
.pm = &am335x_pm_ops,
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index c5c6b818998e..42c42e193232 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -1002,7 +1002,7 @@ static void fsl_otg_remove(struct platform_device *pdev)
struct platform_driver fsl_otg_driver = {
.probe = fsl_otg_probe,
- .remove_new = fsl_otg_remove,
+ .remove = fsl_otg_remove,
.driver = {
.name = driver_name,
},
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index e7d50e0a1612..6c3ececf9137 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -345,7 +345,7 @@ MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids);
static struct platform_driver usb_phy_generic_driver = {
.probe = usb_phy_generic_probe,
- .remove_new = usb_phy_generic_remove,
+ .remove = usb_phy_generic_remove,
.driver = {
.name = "usb_phy_generic",
.of_match_table = nop_xceiv_dt_ids,
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index 5428b2b67de1..ce09e789afd8 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -385,7 +385,7 @@ static struct platform_driver gpio_vbus_driver = {
.of_match_table = gpio_vbus_of_match,
},
.probe = gpio_vbus_probe,
- .remove_new = gpio_vbus_remove,
+ .remove = gpio_vbus_remove,
};
module_platform_driver(gpio_vbus_driver);
diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c
index 993d7525a102..f9b5c411aee4 100644
--- a/drivers/usb/phy/phy-isp1301.c
+++ b/drivers/usb/phy/phy-isp1301.c
@@ -25,7 +25,7 @@ struct isp1301 {
#define phy_to_isp(p) (container_of((p), struct isp1301, phy))
static const struct i2c_device_id isp1301_id[] = {
- { "isp1301", 0 },
+ { "isp1301" },
{ }
};
MODULE_DEVICE_TABLE(i2c, isp1301_id);
diff --git a/drivers/usb/phy/phy-keystone.c b/drivers/usb/phy/phy-keystone.c
index bd9a98ad1b30..51155c5513d3 100644
--- a/drivers/usb/phy/phy-keystone.c
+++ b/drivers/usb/phy/phy-keystone.c
@@ -103,7 +103,7 @@ MODULE_DEVICE_TABLE(of, keystone_usbphy_ids);
static struct platform_driver keystone_usbphy_driver = {
.probe = keystone_usbphy_probe,
- .remove_new = keystone_usbphy_remove,
+ .remove = keystone_usbphy_remove,
.driver = {
.name = "keystone-usbphy",
.of_match_table = keystone_usbphy_ids,
diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c
index df7c27474a75..a7a102f2e163 100644
--- a/drivers/usb/phy/phy-mv-usb.c
+++ b/drivers/usb/phy/phy-mv-usb.c
@@ -867,7 +867,7 @@ static int mv_otg_resume(struct platform_device *pdev)
static struct platform_driver mv_otg_driver = {
.probe = mv_otg_probe,
- .remove_new = mv_otg_remove,
+ .remove = mv_otg_remove,
.driver = {
.name = driver_name,
.dev_groups = mv_otg_groups,
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index cc4156c1b148..7490f1798b46 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -952,7 +952,7 @@ static SIMPLE_DEV_PM_OPS(mxs_phy_pm, mxs_phy_system_suspend,
static struct platform_driver mxs_phy_driver = {
.probe = mxs_phy_probe,
- .remove_new = mxs_phy_remove,
+ .remove = mxs_phy_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = mxs_phy_dt_ids,
diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c
index 5cac31c6029b..ae7bf3ff89ee 100644
--- a/drivers/usb/phy/phy-tahvo.c
+++ b/drivers/usb/phy/phy-tahvo.c
@@ -424,7 +424,7 @@ static void tahvo_usb_remove(struct platform_device *pdev)
static struct platform_driver tahvo_usb_driver = {
.probe = tahvo_usb_probe,
- .remove_new = tahvo_usb_remove,
+ .remove = tahvo_usb_remove,
.driver = {
.name = "tahvo-usb",
.dev_groups = tahvo_groups,
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 4ea47e6f835b..bee222967f6b 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -1495,7 +1495,7 @@ static void tegra_usb_phy_remove(struct platform_device *pdev)
static struct platform_driver tegra_usb_phy_driver = {
.probe = tegra_usb_phy_probe,
- .remove_new = tegra_usb_phy_remove,
+ .remove = tegra_usb_phy_remove,
.driver = {
.name = "tegra-phy",
.of_match_table = tegra_usb_phy_id_table,
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index da09cff55abc..49d79c1257f3 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -432,7 +432,7 @@ MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
static struct platform_driver twl6030_usb_driver = {
.probe = twl6030_usb_probe,
- .remove_new = twl6030_usb_remove,
+ .remove = twl6030_usb_remove,
.driver = {
.name = "twl6030_usb",
.of_match_table = of_match_ptr(twl6030_usb_id_table),
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
index 06f789097989..1ce134505cee 100644
--- a/drivers/usb/phy/phy.c
+++ b/drivers/usb/phy/phy.c
@@ -365,7 +365,7 @@ static int usb_add_extcon(struct usb_phy *x)
{
int ret;
- if (of_property_read_bool(x->dev->of_node, "extcon")) {
+ if (of_property_present(x->dev->of_node, "extcon")) {
x->edev = extcon_get_edev_by_phandle(x->dev, 0);
if (IS_ERR(x->edev))
return PTR_ERR(x->edev);
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index edc43f169d49..935fc496fe94 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -632,7 +632,7 @@ static int usbhs_probe(struct platform_device *pdev)
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
- if (of_property_read_bool(dev_of_node(dev), "extcon")) {
+ if (of_property_present(dev_of_node(dev), "extcon")) {
priv->edev = extcon_get_edev_by_phandle(dev, 0);
if (IS_ERR(priv->edev))
return PTR_ERR(priv->edev);
@@ -835,7 +835,7 @@ static struct platform_driver renesas_usbhs_driver = {
.of_match_table = usbhs_of_match,
},
.probe = usbhs_probe,
- .remove_new = usbhs_remove,
+ .remove = usbhs_remove,
};
module_platform_driver(renesas_usbhs_driver);
diff --git a/drivers/usb/roles/intel-xhci-usb-role-switch.c b/drivers/usb/roles/intel-xhci-usb-role-switch.c
index e5c6c413a075..cd2e026dcb22 100644
--- a/drivers/usb/roles/intel-xhci-usb-role-switch.c
+++ b/drivers/usb/roles/intel-xhci-usb-role-switch.c
@@ -217,7 +217,7 @@ static struct platform_driver intel_xhci_usb_driver = {
},
.id_table = intel_xhci_usb_table,
.probe = intel_xhci_usb_probe,
- .remove_new = intel_xhci_usb_remove,
+ .remove = intel_xhci_usb_remove,
};
module_platform_driver(intel_xhci_usb_driver);
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index d200e2c29a8f..2fea1b1db4a2 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -136,12 +136,11 @@ static void free_dynids(struct usb_serial_driver *drv)
{
struct usb_dynid *dynid, *n;
- spin_lock(&drv->dynids.lock);
+ guard(mutex)(&usb_dynids_lock);
list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
list_del(&dynid->node);
kfree(dynid);
}
- spin_unlock(&drv->dynids.lock);
}
const struct bus_type usb_serial_bus_type = {
@@ -157,7 +156,6 @@ int usb_serial_bus_register(struct usb_serial_driver *driver)
int retval;
driver->driver.bus = &usb_serial_bus_type;
- spin_lock_init(&driver->dynids.lock);
INIT_LIST_HEAD(&driver->dynids.list);
retval = driver_register(&driver->driver);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c6f17d732b95..e07c5e3eb18c 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1443,9 +1443,11 @@ static void get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
+ mutex_lock(&priv->cfg_lock);
ss->flags = priv->flags;
ss->baud_base = priv->baud_base;
ss->custom_divisor = priv->custom_divisor;
+ mutex_unlock(&priv->cfg_lock);
}
static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 28c71d99e857..1fffda7647f9 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1129,7 +1129,7 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
spin_lock_irqsave(&edge_port->ep_lock, flags);
/* calculate number of bytes to put in fifo */
- copySize = min((unsigned int)count,
+ copySize = min_t(unsigned int, count,
(edge_port->txCredits - fifo->count));
dev_dbg(&port->dev, "%s of %d byte(s) Fifo room %d -- will copy %d bytes\n",
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index ad41363e3cea..010688dd9e49 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -31,6 +31,7 @@
#define PL2303_QUIRK_UART_STATE_IDX0 BIT(0)
#define PL2303_QUIRK_LEGACY BIT(1)
#define PL2303_QUIRK_ENDPOINT_HACK BIT(2)
+#define PL2303_QUIRK_NO_BREAK_GETLINE BIT(3)
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID),
@@ -467,6 +468,25 @@ static int pl2303_detect_type(struct usb_serial *serial)
return -ENODEV;
}
+static bool pl2303_is_hxd_clone(struct usb_serial *serial)
+{
+ struct usb_device *udev = serial->dev;
+ unsigned char *buf;
+ int ret;
+
+ buf = kmalloc(7, GFP_KERNEL);
+ if (!buf)
+ return false;
+
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
+ 0, 0, buf, 7, 100);
+
+ kfree(buf);
+
+ return ret == -EPIPE;
+}
+
static int pl2303_startup(struct usb_serial *serial)
{
struct pl2303_serial_private *spriv;
@@ -489,6 +509,9 @@ static int pl2303_startup(struct usb_serial *serial)
spriv->quirks = (unsigned long)usb_get_serial_data(serial);
spriv->quirks |= spriv->type->quirks;
+ if (type == TYPE_HXD && pl2303_is_hxd_clone(serial))
+ spriv->quirks |= PL2303_QUIRK_NO_BREAK_GETLINE;
+
usb_set_serial_data(serial, spriv);
if (type != TYPE_HXN) {
@@ -725,9 +748,18 @@ static void pl2303_encode_baud_rate(struct tty_struct *tty,
static int pl2303_get_line_request(struct usb_serial_port *port,
unsigned char buf[7])
{
- struct usb_device *udev = port->serial->dev;
+ struct usb_serial *serial = port->serial;
+ struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
+ struct usb_device *udev = serial->dev;
int ret;
+ if (spriv->quirks & PL2303_QUIRK_NO_BREAK_GETLINE) {
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+
+ memcpy(buf, priv->line_settings, 7);
+ return 0;
+ }
+
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
0, 0, buf, 7, 100);
@@ -1064,9 +1096,13 @@ static int pl2303_carrier_raised(struct usb_serial_port *port)
static int pl2303_set_break(struct usb_serial_port *port, bool enable)
{
struct usb_serial *serial = port->serial;
+ struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
u16 state;
int result;
+ if (spriv->quirks & PL2303_QUIRK_NO_BREAK_GETLINE)
+ return -ENOTTY;
+
if (enable)
state = BREAK_ON;
else
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 64a2e0bb5723..741e68e46139 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -421,7 +421,7 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
unsigned long flags;
unsigned char *buffer;
struct urb *urb;
- size_t writesize = min((size_t)count, (size_t)MAX_TRANSFER);
+ size_t writesize = min_t(size_t, count, MAX_TRANSFER);
int retval = 0;
/* verify that we actually have some data to write */
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index df6a2ae0bf42..7266558d823a 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -706,14 +706,12 @@ static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
{
struct usb_dynid *dynid;
- spin_lock(&drv->dynids.lock);
+ guard(mutex)(&usb_dynids_lock);
list_for_each_entry(dynid, &drv->dynids.list, node) {
if (usb_match_one_id(intf, &dynid->id)) {
- spin_unlock(&drv->dynids.lock);
return &dynid->id;
}
}
- spin_unlock(&drv->dynids.lock);
return NULL;
}
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
index a4bfbecbf16c..fd46e81388d2 100644
--- a/drivers/usb/storage/ene_ub6250.c
+++ b/drivers/usb/storage/ene_ub6250.c
@@ -737,7 +737,7 @@ static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = blenByte;
- bcb->Flags = 0x00;
+ bcb->Flags = US_BULK_FLAG_OUT;
bcb->CDB[0] = 0xF0;
bcb->CDB[5] = (unsigned char)(bnByte);
bcb->CDB[4] = (unsigned char)(bnByte>>8);
@@ -1163,7 +1163,7 @@ static int ms_read_copyblock(struct us_data *us, u16 oldphy, u16 newphy,
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x200*len;
- bcb->Flags = 0x00;
+ bcb->Flags = US_BULK_FLAG_OUT;
bcb->CDB[0] = 0xF0;
bcb->CDB[1] = 0x08;
bcb->CDB[4] = (unsigned char)(oldphy);
@@ -1759,7 +1759,7 @@ static int ms_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = blenByte;
- bcb->Flags = 0x00;
+ bcb->Flags = US_BULK_FLAG_OUT;
bcb->CDB[0] = 0xF0;
bcb->CDB[1] = 0x04;
bcb->CDB[5] = (unsigned char)(bn);
@@ -1931,7 +1931,7 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = sd_fw->size;
- bcb->Flags = 0x00;
+ bcb->Flags = US_BULK_FLAG_OUT;
bcb->CDB[0] = 0xEF;
result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0);
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index 0c423916d7bf..54ffff86c6fa 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -212,7 +212,7 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun,
/* set up the command wrapper */
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(buf_len);
- bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0;
+ bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : US_BULK_FLAG_OUT;
bcb->Tag = ++us->tag;
bcb->Lun = lun;
bcb->Length = cmd_len;
@@ -301,7 +301,7 @@ static int rts51x_bulk_transport_special(struct us_data *us, u8 lun,
/* set up the command wrapper */
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(buf_len);
- bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0;
+ bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : US_BULK_FLAG_OUT;
bcb->Tag = ++us->tag;
bcb->Lun = lun;
bcb->Length = cmd_len;
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 03d1b9c69ea1..30ee76cfef05 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -752,7 +752,7 @@ sddr09_read_data(struct us_data *us,
// a bounce buffer and move the data a piece at a time between the
// bounce buffer and the actual transfer buffer.
- len = min(sectors, (unsigned int) info->blocksize) * info->pagesize;
+ len = min_t(unsigned int, sectors, info->blocksize) * info->pagesize;
buffer = kmalloc(len, GFP_NOIO);
if (!buffer)
return -ENOMEM;
@@ -997,7 +997,7 @@ sddr09_write_data(struct us_data *us,
* at a time between the bounce buffer and the actual transfer buffer.
*/
- len = min(sectors, (unsigned int) info->blocksize) * info->pagesize;
+ len = min_t(unsigned int, sectors, info->blocksize) * info->pagesize;
buffer = kmalloc(len, GFP_NOIO);
if (!buffer) {
kfree(blockbuffer);
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index b8227478a7ad..a37fc505c57f 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -206,7 +206,7 @@ static int sddr55_read_data(struct us_data *us,
// a bounce buffer and move the data a piece at a time between the
// bounce buffer and the actual transfer buffer.
- len = min((unsigned int) sectors, (unsigned int) info->blocksize >>
+ len = min_t(unsigned int, sectors, info->blocksize >>
info->smallpageshift) * PAGESIZE;
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
@@ -224,7 +224,7 @@ static int sddr55_read_data(struct us_data *us,
// Read as many sectors as possible in this block
- pages = min((unsigned int) sectors << info->smallpageshift,
+ pages = min_t(unsigned int, sectors << info->smallpageshift,
info->blocksize - page);
len = pages << info->pageshift;
@@ -333,7 +333,7 @@ static int sddr55_write_data(struct us_data *us,
// a bounce buffer and move the data a piece at a time between the
// bounce buffer and the actual transfer buffer.
- len = min((unsigned int) sectors, (unsigned int) info->blocksize >>
+ len = min_t(unsigned int, sectors, info->blocksize >>
info->smallpageshift) * PAGESIZE;
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
@@ -351,7 +351,7 @@ static int sddr55_write_data(struct us_data *us,
// Write as many sectors as possible in this block
- pages = min((unsigned int) sectors << info->smallpageshift,
+ pages = min_t(unsigned int, sectors << info->smallpageshift,
info->blocksize - page);
len = pages << info->pageshift;
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 7449e379077a..9d767f6bf722 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1133,7 +1133,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(transfer_length);
bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ?
- US_BULK_FLAG_IN : 0;
+ US_BULK_FLAG_IN : US_BULK_FLAG_OUT;
bcb->Tag = ++us->tag;
bcb->Lun = srb->device->lun;
if (us->fflags & US_FL_SCM_MULT_TARG)
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index 92cc1b136120..2f03190a9873 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -729,7 +729,7 @@ int dp_altmode_probe(struct typec_altmode *alt)
/* FIXME: Port can only be DFP_U. */
- /* Make sure we have compatiple pin configurations */
+ /* Make sure we have compatible pin configurations */
if (!(DP_CAP_PIN_ASSIGN_DFP_D(port->vdo) &
DP_CAP_PIN_ASSIGN_UFP_D(alt->vdo)) &&
!(DP_CAP_PIN_ASSIGN_UFP_D(port->vdo) &
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index 58f40156de56..4b3047e055a3 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -219,6 +219,13 @@ static ssize_t usb_power_delivery_revision_show(struct device *dev,
char *buf);
static DEVICE_ATTR_RO(usb_power_delivery_revision);
+static const char * const usb_modes[] = {
+ [USB_MODE_NONE] = "none",
+ [USB_MODE_USB2] = "usb2",
+ [USB_MODE_USB3] = "usb3",
+ [USB_MODE_USB4] = "usb4"
+};
+
/* ------------------------------------------------------------------------- */
/* Alternate Modes */
@@ -614,6 +621,75 @@ EXPORT_SYMBOL_GPL(typec_unregister_altmode);
/* ------------------------------------------------------------------------- */
/* Type-C Partners */
+/**
+ * typec_partner_set_usb_mode - Assign active USB Mode for the partner
+ * @partner: USB Type-C partner
+ * @mode: USB Mode (USB2, USB3 or USB4)
+ *
+ * The port drivers can use this function to assign the active USB Mode to
+ * @partner. The USB Mode can change for example due to Data Reset.
+ */
+void typec_partner_set_usb_mode(struct typec_partner *partner, enum usb_mode mode)
+{
+ if (!partner || partner->usb_mode == mode)
+ return;
+
+ partner->usb_capability |= BIT(mode - 1);
+ partner->usb_mode = mode;
+ sysfs_notify(&partner->dev.kobj, NULL, "usb_mode");
+}
+EXPORT_SYMBOL_GPL(typec_partner_set_usb_mode);
+
+static ssize_t
+usb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct typec_partner *partner = to_typec_partner(dev);
+ int len = 0;
+ int i;
+
+ for (i = USB_MODE_USB2; i < USB_MODE_USB4 + 1; i++) {
+ if (!(BIT(i - 1) & partner->usb_capability))
+ continue;
+
+ if (i == partner->usb_mode)
+ len += sysfs_emit_at(buf, len, "[%s] ", usb_modes[i]);
+ else
+ len += sysfs_emit_at(buf, len, "%s ", usb_modes[i]);
+ }
+
+ sysfs_emit_at(buf, len - 1, "\n");
+
+ return len;
+}
+
+static ssize_t usb_mode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct typec_partner *partner = to_typec_partner(dev);
+ struct typec_port *port = to_typec_port(dev->parent);
+ int mode;
+ int ret;
+
+ if (!port->ops || !port->ops->enter_usb_mode)
+ return -EOPNOTSUPP;
+
+ mode = sysfs_match_string(usb_modes, buf);
+ if (mode < 0)
+ return mode;
+
+ if (mode == partner->usb_mode)
+ return size;
+
+ ret = port->ops->enter_usb_mode(port, mode);
+ if (ret)
+ return ret;
+
+ typec_partner_set_usb_mode(partner, mode);
+
+ return size;
+}
+static DEVICE_ATTR_RW(usb_mode);
+
static ssize_t accessory_mode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -660,6 +736,7 @@ static struct attribute *typec_partner_attrs[] = {
&dev_attr_supports_usb_power_delivery.attr,
&dev_attr_number_of_alternate_modes.attr,
&dev_attr_type.attr,
+ &dev_attr_usb_mode.attr,
&dev_attr_usb_power_delivery_revision.attr,
NULL
};
@@ -667,6 +744,14 @@ static struct attribute *typec_partner_attrs[] = {
static umode_t typec_partner_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
{
struct typec_partner *partner = to_typec_partner(kobj_to_dev(kobj));
+ struct typec_port *port = to_typec_port(partner->dev.parent);
+
+ if (attr == &dev_attr_usb_mode.attr) {
+ if (!partner->usb_capability)
+ return 0;
+ if (!port->ops || !port->ops->enter_usb_mode)
+ return 0444;
+ }
if (attr == &dev_attr_number_of_alternate_modes.attr) {
if (partner->num_altmodes < 0)
@@ -740,10 +825,33 @@ static void typec_partner_unlink_device(struct typec_partner *partner, struct de
*/
int typec_partner_set_identity(struct typec_partner *partner)
{
- if (!partner->identity)
+ u8 usb_capability = partner->usb_capability;
+ struct device *dev = &partner->dev;
+ struct usb_pd_identity *id;
+
+ id = get_pd_identity(dev);
+ if (!id)
return -EINVAL;
- typec_report_identity(&partner->dev);
+ if (to_typec_port(dev->parent)->data_role == TYPEC_HOST) {
+ u32 devcap = PD_VDO_UFP_DEVCAP(id->vdo[0]);
+
+ if (devcap & (DEV_USB2_CAPABLE | DEV_USB2_BILLBOARD))
+ usb_capability |= USB_CAPABILITY_USB2;
+ if (devcap & DEV_USB3_CAPABLE)
+ usb_capability |= USB_CAPABILITY_USB3;
+ if (devcap & DEV_USB4_CAPABLE)
+ usb_capability |= USB_CAPABILITY_USB4;
+ } else {
+ usb_capability = PD_VDO_DFP_HOSTCAP(id->vdo[0]);
+ }
+
+ if (partner->usb_capability != usb_capability) {
+ partner->usb_capability = usb_capability;
+ sysfs_notify(&dev->kobj, NULL, "usb_mode");
+ }
+
+ typec_report_identity(dev);
return 0;
}
EXPORT_SYMBOL_GPL(typec_partner_set_identity);
@@ -913,6 +1021,7 @@ struct typec_partner *typec_register_partner(struct typec_port *port,
partner->usb_pd = desc->usb_pd;
partner->accessory = desc->accessory;
partner->num_altmodes = -1;
+ partner->usb_capability = desc->usb_capability;
partner->pd_revision = desc->pd_revision;
partner->svdm_version = port->cap->svdm_version;
partner->attach = desc->attach;
@@ -932,6 +1041,15 @@ struct typec_partner *typec_register_partner(struct typec_port *port,
partner->dev.type = &typec_partner_dev_type;
dev_set_name(&partner->dev, "%s-partner", dev_name(&port->dev));
+ if (port->usb2_dev) {
+ partner->usb_capability |= USB_CAPABILITY_USB2;
+ partner->usb_mode = USB_MODE_USB2;
+ }
+ if (port->usb3_dev) {
+ partner->usb_capability |= USB_CAPABILITY_USB2 | USB_CAPABILITY_USB3;
+ partner->usb_mode = USB_MODE_USB3;
+ }
+
ret = device_register(&partner->dev);
if (ret) {
dev_err(&port->dev, "failed to register partner (%d)\n", ret);
@@ -1293,6 +1411,67 @@ EXPORT_SYMBOL_GPL(typec_unregister_cable);
/* USB Type-C ports */
/**
+ * typec_port_set_usb_mode - Set the operational USB mode for the port
+ * @port: USB Type-C port
+ * @mode: USB Mode (USB2, USB3 or USB4)
+ *
+ * @mode will be used with the next Enter_USB message. Existing connections are
+ * not affected.
+ */
+void typec_port_set_usb_mode(struct typec_port *port, enum usb_mode mode)
+{
+ port->usb_mode = mode;
+}
+EXPORT_SYMBOL_GPL(typec_port_set_usb_mode);
+
+static ssize_t
+usb_capability_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct typec_port *port = to_typec_port(dev);
+ int len = 0;
+ int i;
+
+ for (i = USB_MODE_USB2; i < USB_MODE_USB4 + 1; i++) {
+ if (!(BIT(i - 1) & port->cap->usb_capability))
+ continue;
+
+ if (i == port->usb_mode)
+ len += sysfs_emit_at(buf, len, "[%s] ", usb_modes[i]);
+ else
+ len += sysfs_emit_at(buf, len, "%s ", usb_modes[i]);
+ }
+
+ sysfs_emit_at(buf, len - 1, "\n");
+
+ return len;
+}
+
+static ssize_t
+usb_capability_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct typec_port *port = to_typec_port(dev);
+ int ret = 0;
+ int mode;
+
+ if (!port->ops || !port->ops->default_usb_mode_set)
+ return -EOPNOTSUPP;
+
+ mode = sysfs_match_string(usb_modes, buf);
+ if (mode < 0)
+ return mode;
+
+ ret = port->ops->default_usb_mode_set(port, mode);
+ if (ret)
+ return ret;
+
+ port->usb_mode = mode;
+
+ return size;
+}
+static DEVICE_ATTR_RW(usb_capability);
+
+/**
* typec_port_set_usb_power_delivery - Assign USB PD for port.
* @port: USB Type-C port.
* @pd: USB PD instance.
@@ -1760,6 +1939,7 @@ static struct attribute *typec_attrs[] = {
&dev_attr_vconn_source.attr,
&dev_attr_port_type.attr,
&dev_attr_orientation.attr,
+ &dev_attr_usb_capability.attr,
NULL,
};
@@ -1793,6 +1973,11 @@ static umode_t typec_attr_is_visible(struct kobject *kobj,
if (port->cap->orientation_aware)
return 0444;
return 0;
+ } else if (attr == &dev_attr_usb_capability.attr) {
+ if (!port->cap->usb_capability)
+ return 0;
+ if (!port->ops || !port->ops->default_usb_mode_set)
+ return 0444;
}
return attr->mode;
@@ -1864,13 +2049,18 @@ static void typec_partner_attach(struct typec_connector *con, struct device *dev
struct typec_port *port = container_of(con, struct typec_port, con);
struct typec_partner *partner = typec_get_partner(port);
struct usb_device *udev = to_usb_device(dev);
+ enum usb_mode usb_mode;
- if (udev->speed < USB_SPEED_SUPER)
+ if (udev->speed < USB_SPEED_SUPER) {
+ usb_mode = USB_MODE_USB2;
port->usb2_dev = dev;
- else
+ } else {
+ usb_mode = USB_MODE_USB3;
port->usb3_dev = dev;
+ }
if (partner) {
+ typec_partner_set_usb_mode(partner, usb_mode);
typec_partner_link_device(partner, dev);
put_device(&partner->dev);
}
@@ -2433,6 +2623,13 @@ struct typec_port *typec_register_port(struct device *parent,
port->con.attach = typec_partner_attach;
port->con.deattach = typec_partner_deattach;
+ if (cap->usb_capability & USB_CAPABILITY_USB4)
+ port->usb_mode = USB_MODE_USB4;
+ else if (cap->usb_capability & USB_CAPABILITY_USB3)
+ port->usb_mode = USB_MODE_USB3;
+ else if (cap->usb_capability & USB_CAPABILITY_USB2)
+ port->usb_mode = USB_MODE_USB2;
+
device_initialize(&port->dev);
port->dev.class = &typec_class;
port->dev.parent = parent;
diff --git a/drivers/usb/typec/class.h b/drivers/usb/typec/class.h
index 7485cdb9dd20..b3076a24ad2e 100644
--- a/drivers/usb/typec/class.h
+++ b/drivers/usb/typec/class.h
@@ -35,6 +35,8 @@ struct typec_partner {
int num_altmodes;
u16 pd_revision; /* 0300H = "3.0" */
enum usb_pd_svdm_ver svdm_version;
+ enum usb_mode usb_mode;
+ u8 usb_capability;
struct usb_power_delivery *pd;
@@ -55,6 +57,7 @@ struct typec_port {
enum typec_role vconn_role;
enum typec_pwr_opmode pwr_opmode;
enum typec_port_type port_type;
+ enum usb_mode usb_mode;
struct mutex port_type_lock;
enum typec_orientation orientation;
diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig
index ce7db6ad3057..67381b4ef4f6 100644
--- a/drivers/usb/typec/mux/Kconfig
+++ b/drivers/usb/typec/mux/Kconfig
@@ -66,6 +66,15 @@ config TYPEC_MUX_PTN36502
Say Y or M if your system has a NXP PTN36502 Type-C redriver chip
found on some devices with a Type-C port.
+config TYPEC_MUX_TUSB1046
+ tristate "TI TUSB1046 Type-C crosspoint switch driver"
+ depends on I2C
+ help
+ Driver for the Texas Instruments TUSB1046-DCI crosspoint switch.
+ Supports flipping USB-C SuperSpeed lanes to adapt to orientation
+ changes, as well as muxing DisplayPort and sideband signals to a
+ common Type-C connector.
+
config TYPEC_MUX_WCD939X_USBSS
tristate "Qualcomm WCD939x USBSS Analog Audio Switch driver"
depends on I2C
diff --git a/drivers/usb/typec/mux/Makefile b/drivers/usb/typec/mux/Makefile
index bb96f30267af..60879446da93 100644
--- a/drivers/usb/typec/mux/Makefile
+++ b/drivers/usb/typec/mux/Makefile
@@ -7,4 +7,5 @@ obj-$(CONFIG_TYPEC_MUX_INTEL_PMC) += intel_pmc_mux.o
obj-$(CONFIG_TYPEC_MUX_IT5205) += it5205.o
obj-$(CONFIG_TYPEC_MUX_NB7VPQ904M) += nb7vpq904m.o
obj-$(CONFIG_TYPEC_MUX_PTN36502) += ptn36502.o
+obj-$(CONFIG_TYPEC_MUX_TUSB1046) += tusb1046.o
obj-$(CONFIG_TYPEC_MUX_WCD939X_USBSS) += wcd939x-usbss.o
diff --git a/drivers/usb/typec/mux/gpio-sbu-mux.c b/drivers/usb/typec/mux/gpio-sbu-mux.c
index 8902102c05a8..1834f1a2dd9d 100644
--- a/drivers/usb/typec/mux/gpio-sbu-mux.c
+++ b/drivers/usb/typec/mux/gpio-sbu-mux.c
@@ -159,7 +159,7 @@ MODULE_DEVICE_TABLE(of, gpio_sbu_mux_match);
static struct platform_driver gpio_sbu_mux_driver = {
.probe = gpio_sbu_mux_probe,
- .remove_new = gpio_sbu_mux_remove,
+ .remove = gpio_sbu_mux_remove,
.driver = {
.name = "gpio_sbu_mux",
.of_match_table = gpio_sbu_mux_match,
diff --git a/drivers/usb/typec/mux/intel_pmc_mux.c b/drivers/usb/typec/mux/intel_pmc_mux.c
index 46b4c5c3a6be..5dfe95754394 100644
--- a/drivers/usb/typec/mux/intel_pmc_mux.c
+++ b/drivers/usb/typec/mux/intel_pmc_mux.c
@@ -828,7 +828,7 @@ static struct platform_driver pmc_usb_driver = {
.acpi_match_table = ACPI_PTR(pmc_usb_acpi_ids),
},
.probe = pmc_usb_probe,
- .remove_new = pmc_usb_remove,
+ .remove = pmc_usb_remove,
};
static int __init pmc_usb_init(void)
diff --git a/drivers/usb/typec/mux/tusb1046.c b/drivers/usb/typec/mux/tusb1046.c
new file mode 100644
index 000000000000..b4f45c217b59
--- /dev/null
+++ b/drivers/usb/typec/mux/tusb1046.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for the TUSB1046-DCI USB Type-C crosspoint switch
+ *
+ * Copyright (C) 2024 Bootlin
+ */
+
+#include <linux/bits.h>
+#include <linux/i2c.h>
+#include <linux/usb/typec_mux.h>
+#include <linux/usb/typec_dp.h>
+#include <linux/usb/typec_altmode.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/err.h>
+#include <linux/of_device.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+#define TUSB1046_REG_GENERAL 0xa
+
+/* General register bits */
+#define TUSB1046_GENERAL_FLIPSEL BIT(2)
+#define TUSB1046_GENERAL_CTLSEL GENMASK(1, 0)
+
+/* Mux modes */
+#define TUSB1046_CTLSEL_DISABLED 0x0
+#define TUSB1046_CTLSEL_USB3 0x1
+#define TUSB1046_CTLSEL_4LANE_DP 0x2
+#define TUSB1046_CTLSEL_USB3_AND_2LANE_DP 0x3
+
+struct tusb1046_priv {
+ struct i2c_client *client;
+ struct typec_switch_dev *sw;
+ struct typec_mux_dev *mux;
+
+ /* Lock General register during accesses */
+ struct mutex general_reg_lock;
+};
+
+static int tusb1046_mux_set(struct typec_mux_dev *mux,
+ struct typec_mux_state *state)
+{
+ struct tusb1046_priv *priv = typec_mux_get_drvdata(mux);
+ struct i2c_client *client = priv->client;
+ struct device *dev = &client->dev;
+ int mode, val, ret = 0;
+
+ if (state->mode >= TYPEC_STATE_MODAL &&
+ state->alt->svid != USB_TYPEC_DP_SID)
+ return -EINVAL;
+
+ dev_dbg(dev, "mux mode requested: %lu\n", state->mode);
+
+ mutex_lock(&priv->general_reg_lock);
+
+ val = i2c_smbus_read_byte_data(client, TUSB1046_REG_GENERAL);
+ if (val < 0) {
+ dev_err(dev, "failed to read ctlsel status, err %d\n", val);
+ ret = val;
+ goto out_unlock;
+ }
+
+ switch (state->mode) {
+ case TYPEC_STATE_USB:
+ mode = TUSB1046_CTLSEL_USB3;
+ break;
+ case TYPEC_DP_STATE_C:
+ case TYPEC_DP_STATE_E:
+ mode = TUSB1046_CTLSEL_4LANE_DP;
+ break;
+ case TYPEC_DP_STATE_D:
+ mode = TUSB1046_CTLSEL_USB3_AND_2LANE_DP;
+ break;
+ case TYPEC_STATE_SAFE:
+ default:
+ mode = TUSB1046_CTLSEL_DISABLED;
+ break;
+ }
+
+ val &= ~TUSB1046_GENERAL_CTLSEL;
+ val |= mode;
+
+ ret = i2c_smbus_write_byte_data(client, TUSB1046_REG_GENERAL, val);
+
+out_unlock:
+ mutex_unlock(&priv->general_reg_lock);
+ return ret;
+}
+
+static int tusb1046_switch_set(struct typec_switch_dev *sw,
+ enum typec_orientation orientation)
+{
+ struct tusb1046_priv *priv = typec_switch_get_drvdata(sw);
+ struct i2c_client *client = priv->client;
+ struct device *dev = &client->dev;
+ int val, ret = 0;
+
+ dev_dbg(dev, "setting USB3.0 lane flip for orientation %d\n", orientation);
+
+ mutex_lock(&priv->general_reg_lock);
+
+ val = i2c_smbus_read_byte_data(client, TUSB1046_REG_GENERAL);
+ if (val < 0) {
+ dev_err(dev, "failed to read flipsel status, err %d\n", val);
+ ret = val;
+ goto out_unlock;
+ }
+
+ if (orientation == TYPEC_ORIENTATION_REVERSE)
+ val |= TUSB1046_GENERAL_FLIPSEL;
+ else
+ val &= ~TUSB1046_GENERAL_FLIPSEL;
+
+ ret = i2c_smbus_write_byte_data(client, TUSB1046_REG_GENERAL, val);
+
+out_unlock:
+ mutex_unlock(&priv->general_reg_lock);
+ return ret;
+}
+
+static int tusb1046_i2c_probe(struct i2c_client *client)
+{
+ struct typec_switch_desc sw_desc = { };
+ struct typec_mux_desc mux_desc = { };
+ struct device *dev = &client->dev;
+ struct tusb1046_priv *priv;
+ int ret = 0;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return dev_err_probe(dev, -ENOMEM, "failed to allocate driver data\n");
+
+ priv->client = client;
+
+ mutex_init(&priv->general_reg_lock);
+
+ sw_desc.drvdata = priv;
+ sw_desc.fwnode = dev_fwnode(dev);
+ sw_desc.set = tusb1046_switch_set;
+
+ priv->sw = typec_switch_register(dev, &sw_desc);
+ if (IS_ERR(priv->sw)) {
+ ret = dev_err_probe(dev, PTR_ERR(priv->sw), "failed to register type-c switch\n");
+ goto err_destroy_mutex;
+ }
+
+ mux_desc.drvdata = priv;
+ mux_desc.fwnode = dev_fwnode(dev);
+ mux_desc.set = tusb1046_mux_set;
+
+ priv->mux = typec_mux_register(dev, &mux_desc);
+ if (IS_ERR(priv->mux)) {
+ ret = dev_err_probe(dev, PTR_ERR(priv->mux), "failed to register type-c mux\n");
+ goto err_unregister_switch;
+ }
+
+ i2c_set_clientdata(client, priv);
+
+ return 0;
+
+err_unregister_switch:
+ typec_switch_unregister(priv->sw);
+err_destroy_mutex:
+ mutex_destroy(&priv->general_reg_lock);
+ return ret;
+}
+
+static void tusb1046_i2c_remove(struct i2c_client *client)
+{
+ struct tusb1046_priv *priv = i2c_get_clientdata(client);
+
+ typec_switch_unregister(priv->sw);
+ typec_mux_unregister(priv->mux);
+ mutex_destroy(&priv->general_reg_lock);
+}
+
+static const struct of_device_id tusb1046_match_table[] = {
+ {.compatible = "ti,tusb1046"},
+ {},
+};
+
+static struct i2c_driver tusb1046_driver = {
+ .driver = {
+ .name = "tusb1046",
+ .of_match_table = tusb1046_match_table,
+ },
+ .probe = tusb1046_i2c_probe,
+ .remove = tusb1046_i2c_remove,
+};
+
+module_i2c_driver(tusb1046_driver);
+
+MODULE_DESCRIPTION("TUSB1046 USB Type-C switch driver");
+MODULE_AUTHOR("Romain Gantois <romain.gantois@bootlin.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/typec/stusb160x.c b/drivers/usb/typec/stusb160x.c
index f3140fc04c12..6d85b25b40bc 100644
--- a/drivers/usb/typec/stusb160x.c
+++ b/drivers/usb/typec/stusb160x.c
@@ -633,9 +633,8 @@ MODULE_DEVICE_TABLE(of, stusb160x_of_match);
static int stusb160x_probe(struct i2c_client *client)
{
+ const struct regmap_config *regmap_config;
struct stusb160x *chip;
- const struct of_device_id *match;
- struct regmap_config *regmap_config;
struct fwnode_handle *fwnode;
int ret;
@@ -645,8 +644,8 @@ static int stusb160x_probe(struct i2c_client *client)
i2c_set_clientdata(client, chip);
- match = i2c_of_match_device(stusb160x_of_match, client);
- regmap_config = (struct regmap_config *)match->data;
+ regmap_config = i2c_get_match_data(client);
+
chip->regmap = devm_regmap_init_i2c(client, regmap_config);
if (IS_ERR(chip->regmap)) {
ret = PTR_ERR(chip->regmap);
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
index b80eb2d78d88..3766790c1548 100644
--- a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
@@ -163,7 +163,7 @@ static struct platform_driver qcom_pmic_typec_driver = {
.of_match_table = qcom_pmic_typec_table,
},
.probe = qcom_pmic_typec_probe,
- .remove_new = qcom_pmic_typec_remove,
+ .remove = qcom_pmic_typec_remove,
};
module_platform_driver(qcom_pmic_typec_driver);
diff --git a/drivers/usb/typec/tcpm/tcpci_mt6360.c b/drivers/usb/typec/tcpm/tcpci_mt6360.c
index 02b7fd302265..881ffacbfd77 100644
--- a/drivers/usb/typec/tcpm/tcpci_mt6360.c
+++ b/drivers/usb/typec/tcpm/tcpci_mt6360.c
@@ -221,7 +221,7 @@ static struct platform_driver mt6360_tcpc_driver = {
.of_match_table = mt6360_tcpc_of_id,
},
.probe = mt6360_tcpc_probe,
- .remove_new = mt6360_tcpc_remove,
+ .remove = mt6360_tcpc_remove,
};
module_platform_driver(mt6360_tcpc_driver);
diff --git a/drivers/usb/typec/tcpm/tcpci_mt6370.c b/drivers/usb/typec/tcpm/tcpci_mt6370.c
index 9cda1005ef01..1479f961772d 100644
--- a/drivers/usb/typec/tcpm/tcpci_mt6370.c
+++ b/drivers/usb/typec/tcpm/tcpci_mt6370.c
@@ -196,7 +196,7 @@ static struct platform_driver mt6370_tcpc_driver = {
.of_match_table = mt6370_tcpc_devid_table,
},
.probe = mt6370_tcpc_probe,
- .remove_new = mt6370_tcpc_remove,
+ .remove = mt6370_tcpc_remove,
};
module_platform_driver(mt6370_tcpc_driver);
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 7ae341a40342..6021eeb903fe 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -310,6 +310,18 @@ struct pd_data {
unsigned int operating_snk_mw;
};
+/*
+ * @sink_wait_cap_time: Deadline (in ms) for tTypeCSinkWaitCap timer
+ * @ps_src_wait_off_time: Deadline (in ms) for tPSSourceOff timer
+ * @cc_debounce_time: Deadline (in ms) for tCCDebounce timer
+ */
+struct pd_timings {
+ u32 sink_wait_cap_time;
+ u32 ps_src_off_time;
+ u32 cc_debounce_time;
+ u32 snk_bc12_cmpletion_time;
+};
+
struct tcpm_port {
struct device *dev;
@@ -552,6 +564,9 @@ struct tcpm_port {
*/
unsigned int message_id_prime;
unsigned int rx_msgid_prime;
+
+ /* Timer deadline values configured at runtime */
+ struct pd_timings timings;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
struct mutex logbuffer_lock; /* log buffer access lock */
@@ -4640,15 +4655,15 @@ static void run_state_machine(struct tcpm_port *port)
case SRC_ATTACH_WAIT:
if (tcpm_port_is_debug(port))
tcpm_set_state(port, DEBUG_ACC_ATTACHED,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
else if (tcpm_port_is_audio(port))
tcpm_set_state(port, AUDIO_ACC_ATTACHED,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
else if (tcpm_port_is_source(port) && port->vbus_vsafe0v)
tcpm_set_state(port,
tcpm_try_snk(port) ? SNK_TRY
: SRC_ATTACHED,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
break;
case SNK_TRY:
@@ -4699,7 +4714,7 @@ static void run_state_machine(struct tcpm_port *port)
}
break;
case SRC_TRYWAIT_DEBOUNCE:
- tcpm_set_state(port, SRC_ATTACHED, PD_T_CC_DEBOUNCE);
+ tcpm_set_state(port, SRC_ATTACHED, port->timings.cc_debounce_time);
break;
case SRC_TRYWAIT_UNATTACHED:
tcpm_set_state(port, SNK_UNATTACHED, 0);
@@ -4902,7 +4917,7 @@ static void run_state_machine(struct tcpm_port *port)
(port->cc1 != TYPEC_CC_OPEN &&
port->cc2 == TYPEC_CC_OPEN))
tcpm_set_state(port, SNK_DEBOUNCED,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
else if (tcpm_port_is_disconnected(port))
tcpm_set_state(port, SNK_UNATTACHED,
PD_T_PD_DEBOUNCE);
@@ -4942,7 +4957,7 @@ static void run_state_machine(struct tcpm_port *port)
break;
case SNK_TRYWAIT:
tcpm_set_cc(port, TYPEC_CC_RD);
- tcpm_set_state(port, SNK_TRYWAIT_VBUS, PD_T_CC_DEBOUNCE);
+ tcpm_set_state(port, SNK_TRYWAIT_VBUS, port->timings.cc_debounce_time);
break;
case SNK_TRYWAIT_VBUS:
/*
@@ -4965,7 +4980,16 @@ static void run_state_machine(struct tcpm_port *port)
if (ret < 0)
tcpm_set_state(port, SNK_UNATTACHED, 0);
else
- tcpm_set_state(port, SNK_STARTUP, 0);
+ /*
+ * For Type C port controllers that use Battery Charging
+ * Detection (based on BCv1.2 spec) to detect USB
+ * charger type, add a delay of "snk_bc12_cmpletion_time"
+ * before transitioning to SNK_STARTUP to allow BC1.2
+ * detection to complete before PD is eventually enabled
+ * in later states.
+ */
+ tcpm_set_state(port, SNK_STARTUP,
+ port->timings.snk_bc12_cmpletion_time);
break;
case SNK_STARTUP:
opmode = tcpm_get_pwr_opmode(port->polarity ?
@@ -5015,7 +5039,7 @@ static void run_state_machine(struct tcpm_port *port)
break;
case SNK_DISCOVERY_DEBOUNCE:
tcpm_set_state(port, SNK_DISCOVERY_DEBOUNCE_DONE,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
break;
case SNK_DISCOVERY_DEBOUNCE_DONE:
if (!tcpm_port_is_disconnected(port) &&
@@ -5042,13 +5066,14 @@ static void run_state_machine(struct tcpm_port *port)
if (port->vbus_never_low) {
port->vbus_never_low = false;
tcpm_set_state(port, SNK_SOFT_RESET,
- PD_T_SINK_WAIT_CAP);
+ port->timings.sink_wait_cap_time);
} else {
if (!port->self_powered)
upcoming_state = SNK_WAIT_CAPABILITIES_TIMEOUT;
else
upcoming_state = hard_reset_state(port);
- tcpm_set_state(port, upcoming_state, PD_T_SINK_WAIT_CAP);
+ tcpm_set_state(port, SNK_WAIT_CAPABILITIES_TIMEOUT,
+ port->timings.sink_wait_cap_time);
}
break;
case SNK_WAIT_CAPABILITIES_TIMEOUT:
@@ -5070,7 +5095,8 @@ static void run_state_machine(struct tcpm_port *port)
if (tcpm_pd_send_control(port, PD_CTRL_GET_SOURCE_CAP, TCPC_TX_SOP))
tcpm_set_state_cond(port, hard_reset_state(port), 0);
else
- tcpm_set_state(port, hard_reset_state(port), PD_T_SINK_WAIT_CAP);
+ tcpm_set_state(port, hard_reset_state(port),
+ port->timings.sink_wait_cap_time);
break;
case SNK_NEGOTIATE_CAPABILITIES:
port->pd_capable = true;
@@ -5207,7 +5233,7 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state(port, ACC_UNATTACHED, 0);
break;
case AUDIO_ACC_DEBOUNCE:
- tcpm_set_state(port, ACC_UNATTACHED, PD_T_CC_DEBOUNCE);
+ tcpm_set_state(port, ACC_UNATTACHED, port->timings.cc_debounce_time);
break;
/* Hard_Reset states */
@@ -5274,7 +5300,7 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state(port, SRC_UNATTACHED, PD_T_PS_SOURCE_ON);
break;
case SNK_HARD_RESET_SINK_OFF:
- /* Do not discharge/disconnect during hard reseet */
+ /* Do not discharge/disconnect during hard reset */
tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, false, 0);
memset(&port->pps_data, 0, sizeof(port->pps_data));
tcpm_set_vconn(port, false);
@@ -5424,7 +5450,7 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state(port, ERROR_RECOVERY, 0);
break;
case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF:
- tcpm_set_state(port, ERROR_RECOVERY, PD_T_PS_SOURCE_OFF);
+ tcpm_set_state(port, ERROR_RECOVERY, port->timings.ps_src_off_time);
break;
case FR_SWAP_SNK_SRC_NEW_SINK_READY:
if (port->vbus_source)
@@ -5479,7 +5505,7 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_cc(port, TYPEC_CC_RD);
/* allow CC debounce */
tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
break;
case PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED:
/*
@@ -5514,7 +5540,7 @@ static void run_state_machine(struct tcpm_port *port)
port->pps_data.active, 0);
tcpm_set_charge(port, false);
tcpm_set_state(port, hard_reset_state(port),
- PD_T_PS_SOURCE_OFF);
+ port->timings.ps_src_off_time);
break;
case PR_SWAP_SNK_SRC_SOURCE_ON:
tcpm_enable_auto_vbus_discharge(port, true);
@@ -5670,7 +5696,7 @@ static void run_state_machine(struct tcpm_port *port)
case PORT_RESET_WAIT_OFF:
tcpm_set_state(port,
tcpm_default_state(port),
- port->vbus_present ? PD_T_PS_SOURCE_OFF : 0);
+ port->vbus_present ? port->timings.ps_src_off_time : 0);
break;
/* AMS intermediate state */
@@ -6070,7 +6096,7 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
break;
case SNK_ATTACH_WAIT:
case SNK_DEBOUNCED:
- /* Do nothing, as TCPM is still waiting for vbus to reaach VSAFE5V to connect */
+ /* Do nothing, as TCPM is still waiting for vbus to reach VSAFE5V to connect */
break;
case SNK_NEGOTIATE_CAPABILITIES:
@@ -6161,7 +6187,7 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
case SRC_ATTACH_WAIT:
if (tcpm_port_is_source(port))
tcpm_set_state(port, tcpm_try_snk(port) ? SNK_TRY : SRC_ATTACHED,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
break;
case SRC_STARTUP:
case SRC_SEND_CAPABILITIES:
@@ -7057,6 +7083,34 @@ err_unregister:
return ret;
}
+static void tcpm_fw_get_timings(struct tcpm_port *port, struct fwnode_handle *fwnode)
+{
+ int ret;
+ u32 val;
+
+ ret = fwnode_property_read_u32(fwnode, "sink-wait-cap-time-ms", &val);
+ if (!ret)
+ port->timings.sink_wait_cap_time = val;
+ else
+ port->timings.sink_wait_cap_time = PD_T_SINK_WAIT_CAP;
+
+ ret = fwnode_property_read_u32(fwnode, "ps-source-off-time-ms", &val);
+ if (!ret)
+ port->timings.ps_src_off_time = val;
+ else
+ port->timings.ps_src_off_time = PD_T_PS_SOURCE_OFF;
+
+ ret = fwnode_property_read_u32(fwnode, "cc-debounce-time-ms", &val);
+ if (!ret)
+ port->timings.cc_debounce_time = val;
+ else
+ port->timings.cc_debounce_time = PD_T_CC_DEBOUNCE;
+
+ ret = fwnode_property_read_u32(fwnode, "sink-bc12-completion-time-ms", &val);
+ if (!ret)
+ port->timings.snk_bc12_cmpletion_time = val;
+}
+
static int tcpm_fw_get_caps(struct tcpm_port *port, struct fwnode_handle *fwnode)
{
struct fwnode_handle *capabilities, *child, *caps = NULL;
@@ -7371,7 +7425,7 @@ static int tcpm_psy_get_input_power_limit(struct tcpm_port *port,
src_mv = pdo_fixed_voltage(pdo);
src_ma = pdo_max_current(pdo);
tmp = src_mv * src_ma;
- max_src_uw = tmp > max_src_uw ? tmp : max_src_uw;
+ max_src_uw = max(tmp, max_src_uw);
}
}
@@ -7614,6 +7668,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
if (err < 0)
goto out_destroy_wq;
+ tcpm_fw_get_timings(port, tcpc->fwnode);
+
port->try_role = port->typec_caps.prefer_role;
port->typec_caps.revision = 0x0120; /* Type-C spec release 1.2 */
diff --git a/drivers/usb/typec/tcpm/wcove.c b/drivers/usb/typec/tcpm/wcove.c
index 60b2766a69bf..759c982bb16a 100644
--- a/drivers/usb/typec/tcpm/wcove.c
+++ b/drivers/usb/typec/tcpm/wcove.c
@@ -687,7 +687,7 @@ static struct platform_driver wcove_typec_driver = {
.name = "bxt_wcove_usbc",
},
.probe = wcove_typec_probe,
- .remove_new = wcove_typec_remove,
+ .remove = wcove_typec_remove,
};
module_platform_driver(wcove_typec_driver);
diff --git a/drivers/usb/typec/ucsi/debugfs.c b/drivers/usb/typec/ucsi/debugfs.c
index f67733cecfdf..83ff23086d79 100644
--- a/drivers/usb/typec/ucsi/debugfs.c
+++ b/drivers/usb/typec/ucsi/debugfs.c
@@ -32,6 +32,7 @@ static int ucsi_cmd(void *data, u64 val)
case UCSI_SET_UOR:
case UCSI_SET_PDR:
case UCSI_CONNECTOR_RESET:
+ case UCSI_SET_SINK_PATH:
ret = ucsi_send_command(ucsi, val, NULL, 0);
break;
case UCSI_GET_CAPABILITY:
diff --git a/drivers/usb/typec/ucsi/psy.c b/drivers/usb/typec/ucsi/psy.c
index 1c631c7855a9..62ac69730405 100644
--- a/drivers/usb/typec/ucsi/psy.c
+++ b/drivers/usb/typec/ucsi/psy.c
@@ -55,8 +55,8 @@ static int ucsi_psy_get_online(struct ucsi_connector *con,
union power_supply_propval *val)
{
val->intval = UCSI_PSY_OFFLINE;
- if (con->status.flags & UCSI_CONSTAT_CONNECTED &&
- (con->status.flags & UCSI_CONSTAT_PWR_DIR) == TYPEC_SINK)
+ if (UCSI_CONSTAT(con, CONNECTED) &&
+ (UCSI_CONSTAT(con, PWR_DIR) == TYPEC_SINK))
val->intval = UCSI_PSY_FIXED_ONLINE;
return 0;
}
@@ -66,7 +66,7 @@ static int ucsi_psy_get_voltage_min(struct ucsi_connector *con,
{
u32 pdo;
- switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
case UCSI_CONSTAT_PWR_OPMODE_PD:
pdo = con->src_pdos[0];
val->intval = pdo_fixed_voltage(pdo) * 1000;
@@ -89,7 +89,7 @@ static int ucsi_psy_get_voltage_max(struct ucsi_connector *con,
{
u32 pdo;
- switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
case UCSI_CONSTAT_PWR_OPMODE_PD:
if (con->num_pdos > 0) {
pdo = con->src_pdos[con->num_pdos - 1];
@@ -117,7 +117,7 @@ static int ucsi_psy_get_voltage_now(struct ucsi_connector *con,
int index;
u32 pdo;
- switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
case UCSI_CONSTAT_PWR_OPMODE_PD:
index = rdo_index(con->rdo);
if (index > 0) {
@@ -145,7 +145,7 @@ static int ucsi_psy_get_current_max(struct ucsi_connector *con,
{
u32 pdo;
- switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
case UCSI_CONSTAT_PWR_OPMODE_PD:
if (con->num_pdos > 0) {
pdo = con->src_pdos[con->num_pdos - 1];
@@ -173,9 +173,7 @@ static int ucsi_psy_get_current_max(struct ucsi_connector *con,
static int ucsi_psy_get_current_now(struct ucsi_connector *con,
union power_supply_propval *val)
{
- u16 flags = con->status.flags;
-
- if (UCSI_CONSTAT_PWR_OPMODE(flags) == UCSI_CONSTAT_PWR_OPMODE_PD)
+ if (UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD)
val->intval = rdo_op_current(con->rdo) * 1000;
else
val->intval = 0;
@@ -185,11 +183,9 @@ static int ucsi_psy_get_current_now(struct ucsi_connector *con,
static int ucsi_psy_get_usb_type(struct ucsi_connector *con,
union power_supply_propval *val)
{
- u16 flags = con->status.flags;
-
val->intval = POWER_SUPPLY_USB_TYPE_C;
- if (flags & UCSI_CONSTAT_CONNECTED &&
- UCSI_CONSTAT_PWR_OPMODE(flags) == UCSI_CONSTAT_PWR_OPMODE_PD)
+ if (UCSI_CONSTAT(con, CONNECTED) &&
+ UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD)
val->intval = POWER_SUPPLY_USB_TYPE_PD;
return 0;
@@ -197,18 +193,18 @@ static int ucsi_psy_get_usb_type(struct ucsi_connector *con,
static int ucsi_psy_get_charge_type(struct ucsi_connector *con, union power_supply_propval *val)
{
- if (!(con->status.flags & UCSI_CONSTAT_CONNECTED)) {
+ if (!(UCSI_CONSTAT(con, CONNECTED))) {
val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
return 0;
}
/* The Battery Charging Cabability Status field is only valid in sink role. */
- if ((con->status.flags & UCSI_CONSTAT_PWR_DIR) != TYPEC_SINK) {
+ if (UCSI_CONSTAT(con, PWR_DIR) != TYPEC_SINK) {
val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
return 0;
}
- switch (UCSI_CONSTAT_BC_STATUS(con->status.pwr_status)) {
+ switch (UCSI_CONSTAT(con, BC_STATUS)) {
case UCSI_CONSTAT_BC_NOMINAL_CHARGING:
val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
break;
diff --git a/drivers/usb/typec/ucsi/trace.h b/drivers/usb/typec/ucsi/trace.h
index a0d3a934d3d9..41701dee7056 100644
--- a/drivers/usb/typec/ucsi/trace.h
+++ b/drivers/usb/typec/ucsi/trace.h
@@ -40,8 +40,8 @@ DEFINE_EVENT(ucsi_log_command, ucsi_reset_ppm,
);
DECLARE_EVENT_CLASS(ucsi_log_connector_status,
- TP_PROTO(int port, struct ucsi_connector_status *status),
- TP_ARGS(port, status),
+ TP_PROTO(int port, struct ucsi_connector *con),
+ TP_ARGS(port, con),
TP_STRUCT__entry(
__field(int, port)
__field(u16, change)
@@ -55,14 +55,14 @@ DECLARE_EVENT_CLASS(ucsi_log_connector_status,
),
TP_fast_assign(
__entry->port = port - 1;
- __entry->change = status->change;
- __entry->opmode = UCSI_CONSTAT_PWR_OPMODE(status->flags);
- __entry->connected = !!(status->flags & UCSI_CONSTAT_CONNECTED);
- __entry->pwr_dir = !!(status->flags & UCSI_CONSTAT_PWR_DIR);
- __entry->partner_flags = UCSI_CONSTAT_PARTNER_FLAGS(status->flags);
- __entry->partner_type = UCSI_CONSTAT_PARTNER_TYPE(status->flags);
- __entry->request_data_obj = status->request_data_obj;
- __entry->bc_status = UCSI_CONSTAT_BC_STATUS(status->pwr_status);
+ __entry->change = UCSI_CONSTAT(con, CHANGE);
+ __entry->opmode = UCSI_CONSTAT(con, PWR_OPMODE);
+ __entry->connected = UCSI_CONSTAT(con, CONNECTED);
+ __entry->pwr_dir = UCSI_CONSTAT(con, PWR_DIR);
+ __entry->partner_flags = UCSI_CONSTAT(con, PARTNER_FLAGS);
+ __entry->partner_type = UCSI_CONSTAT(con, PARTNER_TYPE);
+ __entry->request_data_obj = UCSI_CONSTAT(con, RDO);
+ __entry->bc_status = UCSI_CONSTAT(con, BC_STATUS);
),
TP_printk("port%d status: change=%04x, opmode=%x, connected=%d, "
"sourcing=%d, partner_flags=%x, partner_type=%x, "
@@ -73,13 +73,13 @@ DECLARE_EVENT_CLASS(ucsi_log_connector_status,
);
DEFINE_EVENT(ucsi_log_connector_status, ucsi_connector_change,
- TP_PROTO(int port, struct ucsi_connector_status *status),
- TP_ARGS(port, status)
+ TP_PROTO(int port, struct ucsi_connector *con),
+ TP_ARGS(port, con)
);
DEFINE_EVENT(ucsi_log_connector_status, ucsi_register_port,
- TP_PROTO(int port, struct ucsi_connector_status *status),
- TP_ARGS(port, status)
+ TP_PROTO(int port, struct ucsi_connector *con),
+ TP_ARGS(port, con)
);
DECLARE_EVENT_CLASS(ucsi_log_register_altmode,
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index e0f3925e401b..c435c0835744 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -648,6 +648,17 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient)
}
}
+static int ucsi_get_connector_status(struct ucsi_connector *con, bool conn_ack)
+{
+ u64 command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
+ size_t size = min(UCSI_GET_CONNECTOR_STATUS_SIZE, UCSI_MAX_DATA_LENGTH(con->ucsi));
+ int ret;
+
+ ret = ucsi_send_command_common(con->ucsi, command, &con->status, size, conn_ack);
+
+ return ret < 0 ? ret : 0;
+}
+
static int ucsi_read_pdos(struct ucsi_connector *con,
enum typec_role role, int is_partner,
u32 *pdos, int offset, int num_pdos)
@@ -658,8 +669,7 @@ static int ucsi_read_pdos(struct ucsi_connector *con,
if (is_partner &&
ucsi->quirks & UCSI_NO_PARTNER_PDOS &&
- ((con->status.flags & UCSI_CONSTAT_PWR_DIR) ||
- !is_source(role)))
+ (UCSI_CONSTAT(con, PWR_DIR) || !is_source(role)))
return 0;
command = UCSI_COMMAND(UCSI_GET_PDOS) | UCSI_CONNECTOR_NUMBER(con->num);
@@ -973,6 +983,7 @@ static void ucsi_unregister_cable(struct ucsi_connector *con)
static int ucsi_check_connector_capability(struct ucsi_connector *con)
{
+ u64 pd_revision;
u64 command;
int ret;
@@ -986,17 +997,17 @@ static int ucsi_check_connector_capability(struct ucsi_connector *con)
return ret;
}
- typec_partner_set_pd_revision(con->partner,
- UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags));
+ pd_revision = UCSI_CONCAP(con, PARTNER_PD_REVISION_V2_1);
+ typec_partner_set_pd_revision(con->partner, UCSI_SPEC_REVISION_TO_BCD(pd_revision));
return ret;
}
static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
{
- switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
case UCSI_CONSTAT_PWR_OPMODE_PD:
- con->rdo = con->status.request_data_obj;
+ con->rdo = UCSI_CONSTAT(con, RDO);
typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_PD);
ucsi_partner_task(con, ucsi_get_src_pdos, 30, 0);
ucsi_partner_task(con, ucsi_check_altmodes, 30, HZ);
@@ -1020,7 +1031,7 @@ static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
static int ucsi_register_partner(struct ucsi_connector *con)
{
- u8 pwr_opmode = UCSI_CONSTAT_PWR_OPMODE(con->status.flags);
+ u8 pwr_opmode = UCSI_CONSTAT(con, PWR_OPMODE);
struct typec_partner_desc desc;
struct typec_partner *partner;
@@ -1029,7 +1040,7 @@ static int ucsi_register_partner(struct ucsi_connector *con)
memset(&desc, 0, sizeof(desc));
- switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
case UCSI_CONSTAT_PARTNER_TYPE_DEBUG:
desc.accessory = TYPEC_ACCESSORY_DEBUG;
break;
@@ -1047,6 +1058,11 @@ static int ucsi_register_partner(struct ucsi_connector *con)
desc.identity = &con->partner_identity;
desc.usb_pd = pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD;
+ if (con->ucsi->version >= UCSI_VERSION_2_1) {
+ u64 pd_revision = UCSI_CONCAP(con, PARTNER_PD_REVISION_V2_1);
+ desc.pd_revision = UCSI_SPEC_REVISION_TO_BCD(pd_revision);
+ }
+
partner = typec_register_partner(con->port, &desc);
if (IS_ERR(partner)) {
dev_err(con->ucsi->dev,
@@ -1057,6 +1073,13 @@ static int ucsi_register_partner(struct ucsi_connector *con)
con->partner = partner;
+ if (con->ucsi->version >= UCSI_VERSION_3_0 &&
+ UCSI_CONSTAT(con, PARTNER_FLAG_USB4_GEN4))
+ typec_partner_set_usb_mode(partner, USB_MODE_USB4);
+ else if (con->ucsi->version >= UCSI_VERSION_2_0 &&
+ UCSI_CONSTAT(con, PARTNER_FLAG_USB4_GEN3))
+ typec_partner_set_usb_mode(partner, USB_MODE_USB4);
+
return 0;
}
@@ -1081,7 +1104,7 @@ static void ucsi_partner_change(struct ucsi_connector *con)
enum usb_role u_role = USB_ROLE_NONE;
int ret;
- switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
case UCSI_CONSTAT_PARTNER_TYPE_UFP:
case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP:
u_role = USB_ROLE_HOST;
@@ -1097,8 +1120,8 @@ static void ucsi_partner_change(struct ucsi_connector *con)
break;
}
- if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
- switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
+ if (UCSI_CONSTAT(con, CONNECTED)) {
+ switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
case UCSI_CONSTAT_PARTNER_TYPE_DEBUG:
typec_set_mode(con->port, TYPEC_MODE_DEBUG);
break;
@@ -1106,14 +1129,13 @@ static void ucsi_partner_change(struct ucsi_connector *con)
typec_set_mode(con->port, TYPEC_MODE_AUDIO);
break;
default:
- if (UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) ==
- UCSI_CONSTAT_PARTNER_FLAG_USB)
+ if (UCSI_CONSTAT(con, PARTNER_FLAG_USB))
typec_set_mode(con->port, TYPEC_STATE_USB);
}
}
/* Only notify USB controller if partner supports USB data */
- if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB))
+ if (!(UCSI_CONSTAT(con, PARTNER_FLAG_USB)))
u_role = USB_ROLE_NONE;
ret = usb_role_switch_set_role(con->usb_role_sw, u_role);
@@ -1124,21 +1146,18 @@ static void ucsi_partner_change(struct ucsi_connector *con)
static int ucsi_check_connection(struct ucsi_connector *con)
{
- u8 prev_flags = con->status.flags;
- u64 command;
+ u8 prev_state = UCSI_CONSTAT(con, CONNECTED);
int ret;
- command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
- ret = ucsi_send_command(con->ucsi, command, &con->status, sizeof(con->status));
- if (ret < 0) {
+ ret = ucsi_get_connector_status(con, false);
+ if (ret) {
dev_err(con->ucsi->dev, "GET_CONNECTOR_STATUS failed (%d)\n", ret);
return ret;
}
- if (con->status.flags == prev_flags)
- return 0;
-
- if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
+ if (UCSI_CONSTAT(con, CONNECTED)) {
+ if (prev_state)
+ return 0;
ucsi_register_partner(con);
ucsi_pwr_opmode_change(con);
ucsi_partner_change(con);
@@ -1194,7 +1213,7 @@ static void ucsi_handle_connector_change(struct work_struct *work)
work);
struct ucsi *ucsi = con->ucsi;
enum typec_role role;
- u64 command;
+ u16 change;
int ret;
mutex_lock(&con->lock);
@@ -1203,25 +1222,23 @@ static void ucsi_handle_connector_change(struct work_struct *work)
dev_err_once(ucsi->dev, "%s entered without EVENT_PENDING\n",
__func__);
- command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
-
- ret = ucsi_send_command_common(ucsi, command, &con->status,
- sizeof(con->status), true);
- if (ret < 0) {
+ ret = ucsi_get_connector_status(con, true);
+ if (ret) {
dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n",
__func__, ret);
clear_bit(EVENT_PENDING, &con->ucsi->flags);
goto out_unlock;
}
- trace_ucsi_connector_change(con->num, &con->status);
+ trace_ucsi_connector_change(con->num, con);
if (ucsi->ops->connector_status)
ucsi->ops->connector_status(con);
- role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
+ change = UCSI_CONSTAT(con, CHANGE);
+ role = UCSI_CONSTAT(con, PWR_DIR);
- if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) {
+ if (change & UCSI_CONSTAT_POWER_DIR_CHANGE) {
typec_set_pwr_role(con->port, role);
/* Complete pending power role swap */
@@ -1229,12 +1246,12 @@ static void ucsi_handle_connector_change(struct work_struct *work)
complete(&con->complete);
}
- if (con->status.change & UCSI_CONSTAT_CONNECT_CHANGE) {
+ if (change & UCSI_CONSTAT_CONNECT_CHANGE) {
typec_set_pwr_role(con->port, role);
ucsi_port_psy_changed(con);
ucsi_partner_change(con);
- if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
+ if (UCSI_CONSTAT(con, CONNECTED)) {
ucsi_register_partner(con);
ucsi_partner_task(con, ucsi_check_connection, 1, HZ);
if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE)
@@ -1242,8 +1259,7 @@ static void ucsi_handle_connector_change(struct work_struct *work)
if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS)
ucsi_partner_task(con, ucsi_check_cable, 1, HZ);
- if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
- UCSI_CONSTAT_PWR_OPMODE_PD) {
+ if (UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD) {
ucsi_partner_task(con, ucsi_register_partner_pdos, 1, HZ);
ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ);
}
@@ -1252,11 +1268,10 @@ static void ucsi_handle_connector_change(struct work_struct *work)
}
}
- if (con->status.change & UCSI_CONSTAT_POWER_OPMODE_CHANGE ||
- con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE)
+ if (change & (UCSI_CONSTAT_POWER_OPMODE_CHANGE | UCSI_CONSTAT_POWER_LEVEL_CHANGE))
ucsi_pwr_opmode_change(con);
- if (con->partner && con->status.change & UCSI_CONSTAT_PARTNER_CHANGE) {
+ if (con->partner && (change & UCSI_CONSTAT_PARTNER_CHANGE)) {
ucsi_partner_change(con);
/* Complete pending data role swap */
@@ -1264,10 +1279,10 @@ static void ucsi_handle_connector_change(struct work_struct *work)
complete(&con->complete);
}
- if (con->status.change & UCSI_CONSTAT_CAM_CHANGE)
+ if (change & UCSI_CONSTAT_CAM_CHANGE)
ucsi_partner_task(con, ucsi_check_altmodes, 1, HZ);
- if (con->status.change & UCSI_CONSTAT_BC_CHANGE)
+ if (change & UCSI_CONSTAT_BC_CHANGE)
ucsi_port_psy_changed(con);
out_unlock:
@@ -1427,7 +1442,7 @@ static int ucsi_dr_swap(struct typec_port *port, enum typec_data_role role)
goto out_unlock;
}
- partner_type = UCSI_CONSTAT_PARTNER_TYPE(con->status.flags);
+ partner_type = UCSI_CONSTAT(con, PARTNER_TYPE);
if ((partner_type == UCSI_CONSTAT_PARTNER_TYPE_DFP &&
role == TYPEC_DEVICE) ||
(partner_type == UCSI_CONSTAT_PARTNER_TYPE_UFP &&
@@ -1471,7 +1486,7 @@ static int ucsi_pr_swap(struct typec_port *port, enum typec_role role)
goto out_unlock;
}
- cur_role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
+ cur_role = UCSI_CONSTAT(con, PWR_DIR);
if (cur_role == role)
goto out_unlock;
@@ -1494,8 +1509,7 @@ static int ucsi_pr_swap(struct typec_port *port, enum typec_role role)
mutex_lock(&con->lock);
/* Something has gone wrong while swapping the role */
- if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) !=
- UCSI_CONSTAT_PWR_OPMODE_PD) {
+ if (UCSI_CONSTAT(con, PWR_OPMODE) != UCSI_CONSTAT_PWR_OPMODE_PD) {
ucsi_reset_connector(con, true);
ret = -EPROTO;
}
@@ -1563,19 +1577,18 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
if (ret < 0)
goto out_unlock;
- if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP)
+ if (UCSI_CONCAP(con, OPMODE_DRP))
cap->data = TYPEC_PORT_DRD;
- else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DFP)
+ else if (UCSI_CONCAP(con, OPMODE_DFP))
cap->data = TYPEC_PORT_DFP;
- else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_UFP)
+ else if (UCSI_CONCAP(con, OPMODE_UFP))
cap->data = TYPEC_PORT_UFP;
- if ((con->cap.flags & UCSI_CONCAP_FLAG_PROVIDER) &&
- (con->cap.flags & UCSI_CONCAP_FLAG_CONSUMER))
+ if (UCSI_CONCAP(con, PROVIDER) && UCSI_CONCAP(con, CONSUMER))
cap->type = TYPEC_PORT_DRP;
- else if (con->cap.flags & UCSI_CONCAP_FLAG_PROVIDER)
+ else if (UCSI_CONCAP(con, PROVIDER))
cap->type = TYPEC_PORT_SRC;
- else if (con->cap.flags & UCSI_CONCAP_FLAG_CONSUMER)
+ else if (UCSI_CONCAP(con, CONSUMER))
cap->type = TYPEC_PORT_SNK;
cap->revision = ucsi->cap.typec_version;
@@ -1583,11 +1596,18 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
cap->svdm_version = SVDM_VER_2_0;
cap->prefer_role = TYPEC_NO_PREFERRED_ROLE;
- if (con->cap.op_mode & UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY)
+ if (UCSI_CONCAP(con, OPMODE_AUDIO_ACCESSORY))
*accessory++ = TYPEC_ACCESSORY_AUDIO;
- if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY)
+ if (UCSI_CONCAP(con, OPMODE_DEBUG_ACCESSORY))
*accessory = TYPEC_ACCESSORY_DEBUG;
+ if (UCSI_CONCAP_USB2_SUPPORT(con))
+ cap->usb_capability |= USB_CAPABILITY_USB2;
+ if (UCSI_CONCAP_USB3_SUPPORT(con))
+ cap->usb_capability |= USB_CAPABILITY_USB3;
+ if (UCSI_CONCAP_USB4_SUPPORT(con))
+ cap->usb_capability |= USB_CAPABILITY_USB4;
+
cap->driver_data = con;
cap->ops = &ucsi_ops;
@@ -1617,19 +1637,16 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
}
/* Get the status */
- command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
- ret = ucsi_send_command(ucsi, command, &con->status, sizeof(con->status));
- if (ret < 0) {
+ ret = ucsi_get_connector_status(con, false);
+ if (ret) {
dev_err(ucsi->dev, "con%d: failed to get status\n", con->num);
- ret = 0;
goto out;
}
- ret = 0; /* ucsi_send_command() returns length on success */
if (ucsi->ops->connector_status)
ucsi->ops->connector_status(con);
- switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
case UCSI_CONSTAT_PARTNER_TYPE_UFP:
case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP:
u_role = USB_ROLE_HOST;
@@ -1646,9 +1663,8 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
}
/* Check if there is already something connected */
- if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
- typec_set_pwr_role(con->port,
- !!(con->status.flags & UCSI_CONSTAT_PWR_DIR));
+ if (UCSI_CONSTAT(con, CONNECTED)) {
+ typec_set_pwr_role(con->port, UCSI_CONSTAT(con, PWR_DIR));
ucsi_register_partner(con);
ucsi_pwr_opmode_change(con);
ucsi_port_psy_changed(con);
@@ -1659,7 +1675,7 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
}
/* Only notify USB controller if partner supports USB data */
- if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB))
+ if (!(UCSI_CONSTAT(con, PARTNER_FLAG_USB)))
u_role = USB_ROLE_NONE;
ret = usb_role_switch_set_role(con->usb_role_sw, u_role);
@@ -1669,16 +1685,14 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
ret = 0;
}
- if (con->partner &&
- UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
- UCSI_CONSTAT_PWR_OPMODE_PD) {
+ if (con->partner && UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD) {
ucsi_register_device_pdos(con);
ucsi_get_src_pdos(con);
ucsi_check_altmodes(con);
ucsi_check_connector_capability(con);
}
- trace_ucsi_register_port(con->num, &con->status);
+ trace_ucsi_register_port(con->num, con);
out:
fwnode_handle_put(cap->fwnode);
@@ -1761,7 +1775,8 @@ static int ucsi_init(struct ucsi *ucsi)
/* Get PPM capabilities */
command = UCSI_GET_CAPABILITY;
- ret = ucsi_send_command(ucsi, command, &ucsi->cap, sizeof(ucsi->cap));
+ ret = ucsi_send_command(ucsi, command, &ucsi->cap,
+ BITS_TO_BYTES(UCSI_GET_CAPABILITY_SIZE));
if (ret < 0)
goto err_reset;
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 1cf5aad4c23a..5ff369c24a2f 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -4,6 +4,7 @@
#define __DRIVER_USB_TYPEC_UCSI_H
#include <linux/bitops.h>
+#include <linux/bitmap.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/power_supply.h>
@@ -95,26 +96,31 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
/* -------------------------------------------------------------------------- */
/* Commands */
-#define UCSI_PPM_RESET 0x01
-#define UCSI_CANCEL 0x02
-#define UCSI_CONNECTOR_RESET 0x03
-#define UCSI_ACK_CC_CI 0x04
-#define UCSI_SET_NOTIFICATION_ENABLE 0x05
-#define UCSI_GET_CAPABILITY 0x06
-#define UCSI_GET_CONNECTOR_CAPABILITY 0x07
-#define UCSI_SET_UOM 0x08
-#define UCSI_SET_UOR 0x09
-#define UCSI_SET_PDM 0x0a
-#define UCSI_SET_PDR 0x0b
-#define UCSI_GET_ALTERNATE_MODES 0x0c
-#define UCSI_GET_CAM_SUPPORTED 0x0d
-#define UCSI_GET_CURRENT_CAM 0x0e
-#define UCSI_SET_NEW_CAM 0x0f
-#define UCSI_GET_PDOS 0x10
-#define UCSI_GET_CABLE_PROPERTY 0x11
-#define UCSI_GET_CONNECTOR_STATUS 0x12
-#define UCSI_GET_ERROR_STATUS 0x13
-#define UCSI_GET_PD_MESSAGE 0x15
+#define UCSI_PPM_RESET 0x01
+#define UCSI_CANCEL 0x02
+#define UCSI_CONNECTOR_RESET 0x03
+#define UCSI_ACK_CC_CI 0x04
+#define UCSI_SET_NOTIFICATION_ENABLE 0x05
+#define UCSI_GET_CAPABILITY 0x06
+#define UCSI_GET_CAPABILITY_SIZE 128
+#define UCSI_GET_CONNECTOR_CAPABILITY 0x07
+#define UCSI_GET_CONNECTOR_CAPABILITY_SIZE 32
+#define UCSI_SET_UOM 0x08
+#define UCSI_SET_UOR 0x09
+#define UCSI_SET_PDM 0x0a
+#define UCSI_SET_PDR 0x0b
+#define UCSI_GET_ALTERNATE_MODES 0x0c
+#define UCSI_GET_CAM_SUPPORTED 0x0d
+#define UCSI_GET_CURRENT_CAM 0x0e
+#define UCSI_SET_NEW_CAM 0x0f
+#define UCSI_GET_PDOS 0x10
+#define UCSI_GET_CABLE_PROPERTY 0x11
+#define UCSI_GET_CABLE_PROPERTY_SIZE 64
+#define UCSI_GET_CONNECTOR_STATUS 0x12
+#define UCSI_GET_CONNECTOR_STATUS_SIZE 152
+#define UCSI_GET_ERROR_STATUS 0x13
+#define UCSI_GET_PD_MESSAGE 0x15
+#define UCSI_SET_SINK_PATH 0x1c
#define UCSI_CONNECTOR_NUMBER(_num_) ((u64)(_num_) << 16)
#define UCSI_COMMAND(_cmd_) ((_cmd_) & 0xff)
@@ -126,7 +132,6 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
#define UCSI_CONNECTOR_RESET_HARD_VER_1_0 BIT(23) /* Deprecated in v1.1 */
#define UCSI_CONNECTOR_RESET_DATA_VER_2_0 BIT(23) /* Redefined in v2.0 */
-
/* ACK_CC_CI bits */
#define UCSI_ACK_CONNECTOR_CHANGE BIT(16)
#define UCSI_ACK_COMMAND_COMPLETE BIT(17)
@@ -250,42 +255,6 @@ struct ucsi_capability {
u16 typec_version;
} __packed;
-/* Data structure filled by PPM in response to GET_CONNECTOR_CAPABILITY cmd. */
-struct ucsi_connector_capability {
- u8 op_mode;
-#define UCSI_CONCAP_OPMODE_DFP BIT(0)
-#define UCSI_CONCAP_OPMODE_UFP BIT(1)
-#define UCSI_CONCAP_OPMODE_DRP BIT(2)
-#define UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY BIT(3)
-#define UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY BIT(4)
-#define UCSI_CONCAP_OPMODE_USB2 BIT(5)
-#define UCSI_CONCAP_OPMODE_USB3 BIT(6)
-#define UCSI_CONCAP_OPMODE_ALT_MODE BIT(7)
- u32 flags;
-#define UCSI_CONCAP_FLAG_PROVIDER BIT(0)
-#define UCSI_CONCAP_FLAG_CONSUMER BIT(1)
-#define UCSI_CONCAP_FLAG_SWAP_TO_DFP BIT(2)
-#define UCSI_CONCAP_FLAG_SWAP_TO_UFP BIT(3)
-#define UCSI_CONCAP_FLAG_SWAP_TO_SRC BIT(4)
-#define UCSI_CONCAP_FLAG_SWAP_TO_SINK BIT(5)
-#define UCSI_CONCAP_FLAG_EX_OP_MODE(_f_) \
- (((_f_) & GENMASK(13, 6)) >> 6)
-#define UCSI_CONCAP_EX_OP_MODE_USB4_GEN2 BIT(0)
-#define UCSI_CONCAP_EX_OP_MODE_EPR_SRC BIT(1)
-#define UCSI_CONCAP_EX_OP_MODE_EPR_SINK BIT(2)
-#define UCSI_CONCAP_EX_OP_MODE_USB4_GEN3 BIT(3)
-#define UCSI_CONCAP_EX_OP_MODE_USB4_GEN4 BIT(4)
-#define UCSI_CONCAP_FLAG_MISC_CAPS(_f_) \
- (((_f_) & GENMASK(17, 14)) >> 14)
-#define UCSI_CONCAP_MISC_CAP_FW_UPDATE BIT(0)
-#define UCSI_CONCAP_MISC_CAP_SECURITY BIT(1)
-#define UCSI_CONCAP_FLAG_REV_CURR_PROT_SUPPORT BIT(18)
-#define UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV(_f_) \
- (((_f_) & GENMASK(20, 19)) >> 19)
-#define UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(_f_) \
- UCSI_SPEC_REVISION_TO_BCD(UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV(_f_))
-} __packed;
-
struct ucsi_altmode {
u16 svid;
u32 mid;
@@ -311,49 +280,143 @@ struct ucsi_cable_property {
u8 latency;
} __packed;
-/* Data structure filled by PPM in response to GET_CONNECTOR_STATUS command. */
-struct ucsi_connector_status {
- u16 change;
-#define UCSI_CONSTAT_EXT_SUPPLY_CHANGE BIT(1)
-#define UCSI_CONSTAT_POWER_OPMODE_CHANGE BIT(2)
-#define UCSI_CONSTAT_PDOS_CHANGE BIT(5)
-#define UCSI_CONSTAT_POWER_LEVEL_CHANGE BIT(6)
-#define UCSI_CONSTAT_PD_RESET_COMPLETE BIT(7)
-#define UCSI_CONSTAT_CAM_CHANGE BIT(8)
-#define UCSI_CONSTAT_BC_CHANGE BIT(9)
-#define UCSI_CONSTAT_PARTNER_CHANGE BIT(11)
-#define UCSI_CONSTAT_POWER_DIR_CHANGE BIT(12)
-#define UCSI_CONSTAT_CONNECT_CHANGE BIT(14)
-#define UCSI_CONSTAT_ERROR BIT(15)
- u16 flags;
-#define UCSI_CONSTAT_PWR_OPMODE(_f_) ((_f_) & GENMASK(2, 0))
+/* Get Connector Capability Fields. */
+#define UCSI_CONCAP_OPMODE UCSI_DECLARE_BITFIELD(0, 0, 8)
+#define UCSI_CONCAP_OPMODE_DFP UCSI_DECLARE_BITFIELD(0, 0, 1)
+#define UCSI_CONCAP_OPMODE_UFP UCSI_DECLARE_BITFIELD(0, 1, 1)
+#define UCSI_CONCAP_OPMODE_DRP UCSI_DECLARE_BITFIELD(0, 2, 1)
+#define UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY UCSI_DECLARE_BITFIELD(0, 3, 1)
+#define UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY UCSI_DECLARE_BITFIELD(0, 4, 1)
+#define UCSI_CONCAP_OPMODE_USB2 UCSI_DECLARE_BITFIELD(0, 5, 1)
+#define UCSI_CONCAP_OPMODE_USB3 UCSI_DECLARE_BITFIELD(0, 6, 1)
+#define UCSI_CONCAP_OPMODE_ALT_MODE UCSI_DECLARE_BITFIELD(0, 7, 1)
+#define UCSI_CONCAP_PROVIDER UCSI_DECLARE_BITFIELD(0, 8, 1)
+#define UCSI_CONCAP_CONSUMER UCSI_DECLARE_BITFIELD(0, 9, 1)
+#define UCSI_CONCAP_SWAP_TO_DFP_V1_1 UCSI_DECLARE_BITFIELD_V1_1(10, 1)
+#define UCSI_CONCAP_SWAP_TO_UFP_V1_1 UCSI_DECLARE_BITFIELD_V1_1(11, 1)
+#define UCSI_CONCAP_SWAP_TO_SRC_V1_1 UCSI_DECLARE_BITFIELD_V1_1(12, 1)
+#define UCSI_CONCAP_SWAP_TO_SNK_V1_1 UCSI_DECLARE_BITFIELD_V1_1(13, 1)
+#define UCSI_CONCAP_EXT_OPMODE_V2_0 UCSI_DECLARE_BITFIELD_V2_0(14, 8)
+#define UCSI_CONCAP_EXT_OPMODE_USB4_GEN2_V2_0 UCSI_DECLARE_BITFIELD_V2_0(14, 1)
+#define UCSI_CONCAP_EXT_OPMODE_EPR_SRC_V2_0 UCSI_DECLARE_BITFIELD_V2_0(15, 1)
+#define UCSI_CONCAP_EXT_OPMODE_EPR_SINK_V2_0 UCSI_DECLARE_BITFIELD_V2_0(16, 1)
+#define UCSI_CONCAP_EXT_OPMODE_USB4_GEN3_V2_0 UCSI_DECLARE_BITFIELD_V2_0(17, 1)
+#define UCSI_CONCAP_EXT_OPMODE_USB4_GEN4_V2_0 UCSI_DECLARE_BITFIELD_V2_0(18, 1)
+#define UCSI_CONCAP_MISC_V2_0 UCSI_DECLARE_BITFIELD_V2_0(22, 4)
+#define UCSI_CONCAP_MISC_FW_UPDATE_V2_0 UCSI_DECLARE_BITFIELD_V2_0(22, 1)
+#define UCSI_CONCAP_MISC_SECURITY_V2_0 UCSI_DECLARE_BITFIELD_V2_0(23, 1)
+#define UCSI_CONCAP_REV_CURR_PROT_SUPPORT_V2_0 UCSI_DECLARE_BITFIELD_V2_0(26, 1)
+#define UCSI_CONCAP_PARTNER_PD_REVISION_V2_1 UCSI_DECLARE_BITFIELD_V2_1(27, 2)
+
+/* Helpers for USB capability checks. */
+#define UCSI_CONCAP_USB2_SUPPORT(_con_) UCSI_CONCAP((_con_), OPMODE_USB2)
+#define UCSI_CONCAP_USB3_SUPPORT(_con_) UCSI_CONCAP((_con_), OPMODE_USB3)
+#define UCSI_CONCAP_USB4_SUPPORT(_con_) \
+ ((_con_)->ucsi->version >= UCSI_VERSION_2_0 && \
+ (UCSI_CONCAP((_con_), EXT_OPMODE_USB4_GEN2_V2_0) | \
+ UCSI_CONCAP((_con_), EXT_OPMODE_USB4_GEN3_V2_0) | \
+ UCSI_CONCAP((_con_), EXT_OPMODE_USB4_GEN4_V2_0)))
+
+/* Get Connector Status Fields. */
+#define UCSI_CONSTAT_CHANGE UCSI_DECLARE_BITFIELD(0, 0, 16)
+#define UCSI_CONSTAT_PWR_OPMODE UCSI_DECLARE_BITFIELD(0, 16, 3)
#define UCSI_CONSTAT_PWR_OPMODE_NONE 0
#define UCSI_CONSTAT_PWR_OPMODE_DEFAULT 1
#define UCSI_CONSTAT_PWR_OPMODE_BC 2
#define UCSI_CONSTAT_PWR_OPMODE_PD 3
#define UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5 4
#define UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0 5
-#define UCSI_CONSTAT_CONNECTED BIT(3)
-#define UCSI_CONSTAT_PWR_DIR BIT(4)
-#define UCSI_CONSTAT_PARTNER_FLAGS(_f_) (((_f_) & GENMASK(12, 5)) >> 5)
-#define UCSI_CONSTAT_PARTNER_FLAG_USB 1
-#define UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE 2
-#define UCSI_CONSTAT_PARTNER_TYPE(_f_) (((_f_) & GENMASK(15, 13)) >> 13)
+#define UCSI_CONSTAT_CONNECTED UCSI_DECLARE_BITFIELD(0, 19, 1)
+#define UCSI_CONSTAT_PWR_DIR UCSI_DECLARE_BITFIELD(0, 20, 1)
+#define UCSI_CONSTAT_PARTNER_FLAGS UCSI_DECLARE_BITFIELD(0, 21, 8)
+#define UCSI_CONSTAT_PARTNER_FLAG_USB UCSI_DECLARE_BITFIELD(0, 21, 1)
+#define UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE UCSI_DECLARE_BITFIELD(0, 22, 1)
+#define UCSI_CONSTAT_PARTNER_FLAG_USB4_GEN3 UCSI_DECLARE_BITFIELD(0, 23, 1)
+#define UCSI_CONSTAT_PARTNER_FLAG_USB4_GEN4 UCSI_DECLARE_BITFIELD(0, 24, 1)
+#define UCSI_CONSTAT_PARTNER_TYPE UCSI_DECLARE_BITFIELD(0, 29, 3)
#define UCSI_CONSTAT_PARTNER_TYPE_DFP 1
#define UCSI_CONSTAT_PARTNER_TYPE_UFP 2
-#define UCSI_CONSTAT_PARTNER_TYPE_CABLE 3 /* Powered Cable */
-#define UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP 4 /* Powered Cable */
+#define UCSI_CONSTAT_PARTNER_TYPE_CABLE 3 /* Powered Cable */
+#define UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP 4 /* Powered Cable */
#define UCSI_CONSTAT_PARTNER_TYPE_DEBUG 5
#define UCSI_CONSTAT_PARTNER_TYPE_AUDIO 6
- u32 request_data_obj;
-
- u8 pwr_status;
-#define UCSI_CONSTAT_BC_STATUS(_p_) ((_p_) & GENMASK(1, 0))
+#define UCSI_CONSTAT_RDO UCSI_DECLARE_BITFIELD(0, 32, 32)
+#define UCSI_CONSTAT_BC_STATUS UCSI_DECLARE_BITFIELD(0, 64, 2)
#define UCSI_CONSTAT_BC_NOT_CHARGING 0
#define UCSI_CONSTAT_BC_NOMINAL_CHARGING 1
#define UCSI_CONSTAT_BC_SLOW_CHARGING 2
#define UCSI_CONSTAT_BC_TRICKLE_CHARGING 3
-} __packed;
+#define UCSI_CONSTAT_PD_VERSION_V1_2 UCSI_DECLARE_BITFIELD_V1_2(70, 16)
+
+/* Connector Status Change Bits. */
+#define UCSI_CONSTAT_EXT_SUPPLY_CHANGE BIT(1)
+#define UCSI_CONSTAT_POWER_OPMODE_CHANGE BIT(2)
+#define UCSI_CONSTAT_PDOS_CHANGE BIT(5)
+#define UCSI_CONSTAT_POWER_LEVEL_CHANGE BIT(6)
+#define UCSI_CONSTAT_PD_RESET_COMPLETE BIT(7)
+#define UCSI_CONSTAT_CAM_CHANGE BIT(8)
+#define UCSI_CONSTAT_BC_CHANGE BIT(9)
+#define UCSI_CONSTAT_PARTNER_CHANGE BIT(11)
+#define UCSI_CONSTAT_POWER_DIR_CHANGE BIT(12)
+#define UCSI_CONSTAT_CONNECT_CHANGE BIT(14)
+#define UCSI_CONSTAT_ERROR BIT(15)
+
+#define UCSI_DECLARE_BITFIELD_V1_1(_offset_, _size_) \
+ UCSI_DECLARE_BITFIELD(UCSI_VERSION_1_1, (_offset_), (_size_))
+#define UCSI_DECLARE_BITFIELD_V1_2(_offset_, _size_) \
+ UCSI_DECLARE_BITFIELD(UCSI_VERSION_1_2, (_offset_), (_size_))
+#define UCSI_DECLARE_BITFIELD_V2_0(_offset_, _size_) \
+ UCSI_DECLARE_BITFIELD(UCSI_VERSION_2_0, (_offset_), (_size_))
+#define UCSI_DECLARE_BITFIELD_V2_1(_offset_, _size_) \
+ UCSI_DECLARE_BITFIELD(UCSI_VERSION_2_1, (_offset_), (_size_))
+#define UCSI_DECLARE_BITFIELD_V3_0(_offset_, _size_) \
+ UCSI_DECLARE_BITFIELD(UCSI_VERSION_3_0, (_offset_), (_size_))
+
+#define UCSI_DECLARE_BITFIELD(_ver_, _offset_, _size_) \
+(struct ucsi_bitfield) { \
+ .version = _ver_, \
+ .offset = _offset_, \
+ .size = _size_, \
+}
+
+struct ucsi_bitfield {
+ const u16 version;
+ const u8 offset;
+ const u8 size;
+};
+
+/**
+ * ucsi_bitfield_read - Read a field from UCSI command response
+ * @_map_: UCSI command response
+ * @_field_: The field offset in the response data structure
+ * @_ver_: UCSI version where the field was introduced
+ *
+ * Reads the fields in the command responses by first checking that the field is
+ * valid with the UCSI interface version that is used in the system.
+ * @_ver_ is the minimum UCSI version for the @_field_. If the UCSI interface is
+ * older than @_ver_, a warning is generated.
+ *
+ * Caveats:
+ * - Removed fields are not checked - @_ver_ is just the minimum UCSI version.
+ *
+ * Returns the value of @_field_, or 0 when the UCSI interface is older than
+ * @_ver_.
+ */
+#define ucsi_bitfield_read(_map_, _field_, _ver_) \
+({ \
+ struct ucsi_bitfield f = (_field_); \
+ WARN((_ver_) < f.version, \
+ "Access to unsupported field at offset 0x%x (need version %04x)", \
+ f.offset, f.version) ? 0 : \
+ bitmap_read((_map_), f.offset, f.size); \
+})
+
+/* Helpers to access cached command responses. */
+#define UCSI_CONCAP(_con_, _field_) \
+ ucsi_bitfield_read((_con_)->cap, UCSI_CONCAP_##_field_, (_con_)->ucsi->version)
+
+#define UCSI_CONSTAT(_con_, _field_) \
+ ucsi_bitfield_read((_con_)->status, UCSI_CONSTAT_##_field_, (_con_)->ucsi->version)
/* -------------------------------------------------------------------------- */
@@ -433,8 +496,10 @@ struct ucsi_connector {
struct typec_capability typec_cap;
- struct ucsi_connector_status status;
- struct ucsi_connector_capability cap;
+ /* Cached command responses. */
+ DECLARE_BITMAP(cap, UCSI_GET_CONNECTOR_CAPABILITY_SIZE);
+ DECLARE_BITMAP(status, UCSI_GET_CONNECTOR_STATUS_SIZE);
+
struct power_supply *psy;
struct power_supply_desc psy_desc;
u32 rdo;
diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c
index 7a5dff8d9cc6..5c5515551963 100644
--- a/drivers/usb/typec/ucsi/ucsi_acpi.c
+++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
@@ -61,9 +61,11 @@ static int ucsi_acpi_read_cci(struct ucsi *ucsi, u32 *cci)
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
int ret;
- ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
- if (ret)
- return ret;
+ if (UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) {
+ ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
+ if (ret)
+ return ret;
+ }
memcpy(cci, ua->base + UCSI_CCI, sizeof(*cci));
@@ -73,11 +75,6 @@ static int ucsi_acpi_read_cci(struct ucsi *ucsi, u32 *cci)
static int ucsi_acpi_read_message_in(struct ucsi *ucsi, void *val, size_t val_len)
{
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
- int ret;
-
- ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
- if (ret)
- return ret;
memcpy(val, ua->base + UCSI_MESSAGE_IN, val_len);
@@ -102,48 +99,11 @@ static const struct ucsi_operations ucsi_acpi_ops = {
.async_control = ucsi_acpi_async_control
};
-static int
-ucsi_zenbook_read_cci(struct ucsi *ucsi, u32 *cci)
-{
- struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
- int ret;
-
- if (UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) {
- ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
- if (ret)
- return ret;
- }
-
- memcpy(cci, ua->base + UCSI_CCI, sizeof(*cci));
-
- return 0;
-}
-
-static int
-ucsi_zenbook_read_message_in(struct ucsi *ucsi, void *val, size_t val_len)
-{
- struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
-
- /* UCSI_MESSAGE_IN is never read for PPM_RESET, return stored data */
- memcpy(val, ua->base + UCSI_MESSAGE_IN, val_len);
-
- return 0;
-}
-
-static const struct ucsi_operations ucsi_zenbook_ops = {
- .read_version = ucsi_acpi_read_version,
- .read_cci = ucsi_zenbook_read_cci,
- .read_message_in = ucsi_zenbook_read_message_in,
- .sync_control = ucsi_sync_control_common,
- .async_control = ucsi_acpi_async_control
-};
-
static int ucsi_gram_read_message_in(struct ucsi *ucsi, void *val, size_t val_len)
{
u16 bogus_change = UCSI_CONSTAT_POWER_LEVEL_CHANGE |
UCSI_CONSTAT_PDOS_CHANGE;
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
- struct ucsi_connector_status *status;
int ret;
ret = ucsi_acpi_read_message_in(ucsi, val, val_len);
@@ -152,11 +112,9 @@ static int ucsi_gram_read_message_in(struct ucsi *ucsi, void *val, size_t val_le
if (UCSI_COMMAND(ua->cmd) == UCSI_GET_CONNECTOR_STATUS &&
ua->check_bogus_event) {
- status = (struct ucsi_connector_status *)val;
-
/* Clear the bogus change */
- if (status->change == bogus_change)
- status->change = 0;
+ if (*(u16 *)val == bogus_change)
+ *(u16 *)val = 0;
ua->check_bogus_event = false;
}
@@ -192,13 +150,6 @@ static const struct ucsi_operations ucsi_gram_ops = {
static const struct dmi_system_id ucsi_acpi_quirks[] = {
{
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"),
- },
- .driver_data = (void *)&ucsi_zenbook_ops,
- },
- {
- .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
DMI_MATCH(DMI_PRODUCT_FAMILY, "LG gram PC"),
DMI_MATCH(DMI_PRODUCT_NAME, "90Q"),
@@ -320,7 +271,7 @@ static struct platform_driver ucsi_acpi_platform_driver = {
.acpi_match_table = ACPI_PTR(ucsi_acpi_match),
},
.probe = ucsi_acpi_probe,
- .remove_new = ucsi_acpi_remove,
+ .remove = ucsi_acpi_remove,
};
module_platform_driver(ucsi_acpi_platform_driver);
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index bccfc03b5986..fcb8e61136cf 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -644,6 +644,10 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command)
uc->has_multiple_dp) {
con_index = (uc->last_cmd_sent >> 16) &
UCSI_CMD_CONNECTOR_MASK;
+ if (con_index == 0) {
+ ret = -EINVAL;
+ goto unlock;
+ }
con = &uc->ucsi->connector[con_index - 1];
ucsi_ccg_update_set_new_cam_cmd(uc, con, &command);
}
@@ -651,6 +655,7 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command)
ret = ucsi_sync_control_common(ucsi, command);
pm_runtime_put_sync(uc->dev);
+unlock:
mutex_unlock(&uc->lock);
return ret;
diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c
index 03c0fa8edc8d..90948cd6d297 100644
--- a/drivers/usb/typec/ucsi/ucsi_glink.c
+++ b/drivers/usb/typec/ucsi/ucsi_glink.c
@@ -172,12 +172,12 @@ static int pmic_glink_ucsi_async_control(struct ucsi *__ucsi, u64 command)
static void pmic_glink_ucsi_update_connector(struct ucsi_connector *con)
{
struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(con->ucsi);
- int i;
- for (i = 0; i < PMIC_GLINK_MAX_PORTS; i++) {
- if (ucsi->port_orientation[i])
- con->typec_cap.orientation_aware = true;
- }
+ if (con->num > PMIC_GLINK_MAX_PORTS ||
+ !ucsi->port_orientation[con->num - 1])
+ return;
+
+ con->typec_cap.orientation_aware = true;
}
static void pmic_glink_ucsi_connector_status(struct ucsi_connector *con)
@@ -185,7 +185,7 @@ static void pmic_glink_ucsi_connector_status(struct ucsi_connector *con)
struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(con->ucsi);
int orientation;
- if (con->num >= PMIC_GLINK_MAX_PORTS ||
+ if (con->num > PMIC_GLINK_MAX_PORTS ||
!ucsi->port_orientation[con->num - 1])
return;
@@ -322,7 +322,6 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
struct pmic_glink_ucsi *ucsi;
struct device *dev = &adev->dev;
const struct of_device_id *match;
- struct fwnode_handle *fwnode;
int ret;
ucsi = devm_kzalloc(dev, sizeof(*ucsi), GFP_KERNEL);
@@ -354,14 +353,13 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
ucsi_set_drvdata(ucsi->ucsi, ucsi);
- device_for_each_child_node(dev, fwnode) {
+ device_for_each_child_node_scoped(dev, fwnode) {
struct gpio_desc *desc;
u32 port;
ret = fwnode_property_read_u32(fwnode, "reg", &port);
if (ret < 0) {
dev_err(dev, "missing reg property of %pOFn\n", fwnode);
- fwnode_handle_put(fwnode);
return ret;
}
@@ -376,11 +374,10 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
if (!desc)
continue;
- if (IS_ERR(desc)) {
- fwnode_handle_put(fwnode);
+ if (IS_ERR(desc))
return dev_err_probe(dev, PTR_ERR(desc),
"unable to acquire orientation gpio\n");
- }
+
ucsi->port_orientation[port] = desc;
}
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index 8dac1edc74d4..b03e5021c25b 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -1487,7 +1487,7 @@ static int vhci_hcd_resume(struct platform_device *pdev)
static struct platform_driver vhci_driver = {
.probe = vhci_hcd_probe,
- .remove_new = vhci_hcd_remove,
+ .remove = vhci_hcd_remove,
.suspend = vhci_hcd_suspend,
.resume = vhci_hcd_resume,
.driver = {
diff --git a/drivers/usb/usbip/vudc_main.c b/drivers/usb/usbip/vudc_main.c
index 8bee553e4894..993e721cb840 100644
--- a/drivers/usb/usbip/vudc_main.c
+++ b/drivers/usb/usbip/vudc_main.c
@@ -19,7 +19,7 @@ MODULE_PARM_DESC(num, "number of emulated controllers");
static struct platform_driver vudc_driver = {
.probe = vudc_probe,
- .remove_new = vudc_remove,
+ .remove = vudc_remove,
.driver = {
.name = GADGET_NAME,
.dev_groups = vudc_groups,
diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c
index 7d0c83b5b071..8455f08f5d40 100644
--- a/drivers/vdpa/mlx5/core/mr.c
+++ b/drivers/vdpa/mlx5/core/mr.c
@@ -368,7 +368,6 @@ static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr
unsigned long lgcd = 0;
int log_entity_size;
unsigned long size;
- u64 start = 0;
int err;
struct page *pg;
unsigned int nsg;
@@ -379,10 +378,9 @@ static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr
struct device *dma = mvdev->vdev.dma_dev;
for (map = vhost_iotlb_itree_first(iotlb, mr->start, mr->end - 1);
- map; map = vhost_iotlb_itree_next(map, start, mr->end - 1)) {
+ map; map = vhost_iotlb_itree_next(map, mr->start, mr->end - 1)) {
size = maplen(map, mr);
lgcd = gcd(lgcd, size);
- start += size;
}
log_entity_size = ilog2(lgcd);
diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
index 0d632ba5d2a3..451c639299eb 100644
--- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
+++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
@@ -486,31 +486,11 @@ static int vf_qm_load_data(struct hisi_acc_vf_core_device *hisi_acc_vdev,
return 0;
}
-static int vf_qm_state_save(struct hisi_acc_vf_core_device *hisi_acc_vdev,
- struct hisi_acc_vf_migration_file *migf)
+static int vf_qm_read_data(struct hisi_qm *vf_qm, struct acc_vf_data *vf_data)
{
- struct acc_vf_data *vf_data = &migf->vf_data;
- struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
struct device *dev = &vf_qm->pdev->dev;
int ret;
- if (unlikely(qm_wait_dev_not_ready(vf_qm))) {
- /* Update state and return with match data */
- vf_data->vf_qm_state = QM_NOT_READY;
- hisi_acc_vdev->vf_qm_state = vf_data->vf_qm_state;
- migf->total_length = QM_MATCH_SIZE;
- return 0;
- }
-
- vf_data->vf_qm_state = QM_READY;
- hisi_acc_vdev->vf_qm_state = vf_data->vf_qm_state;
-
- ret = vf_qm_cache_wb(vf_qm);
- if (ret) {
- dev_err(dev, "failed to writeback QM Cache!\n");
- return ret;
- }
-
ret = qm_get_regs(vf_qm, vf_data);
if (ret)
return -EINVAL;
@@ -536,6 +516,38 @@ static int vf_qm_state_save(struct hisi_acc_vf_core_device *hisi_acc_vdev,
return -EINVAL;
}
+ return 0;
+}
+
+static int vf_qm_state_save(struct hisi_acc_vf_core_device *hisi_acc_vdev,
+ struct hisi_acc_vf_migration_file *migf)
+{
+ struct acc_vf_data *vf_data = &migf->vf_data;
+ struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
+ struct device *dev = &vf_qm->pdev->dev;
+ int ret;
+
+ if (unlikely(qm_wait_dev_not_ready(vf_qm))) {
+ /* Update state and return with match data */
+ vf_data->vf_qm_state = QM_NOT_READY;
+ hisi_acc_vdev->vf_qm_state = vf_data->vf_qm_state;
+ migf->total_length = QM_MATCH_SIZE;
+ return 0;
+ }
+
+ vf_data->vf_qm_state = QM_READY;
+ hisi_acc_vdev->vf_qm_state = vf_data->vf_qm_state;
+
+ ret = vf_qm_cache_wb(vf_qm);
+ if (ret) {
+ dev_err(dev, "failed to writeback QM Cache!\n");
+ return ret;
+ }
+
+ ret = vf_qm_read_data(vf_qm, vf_data);
+ if (ret)
+ return -EINVAL;
+
migf->total_length = sizeof(struct acc_vf_data);
return 0;
}
@@ -615,21 +627,43 @@ static void hisi_acc_vf_disable_fd(struct hisi_acc_vf_migration_file *migf)
mutex_unlock(&migf->lock);
}
+static void
+hisi_acc_debug_migf_copy(struct hisi_acc_vf_core_device *hisi_acc_vdev,
+ struct hisi_acc_vf_migration_file *src_migf)
+{
+ struct hisi_acc_vf_migration_file *dst_migf = hisi_acc_vdev->debug_migf;
+
+ if (!dst_migf)
+ return;
+
+ dst_migf->total_length = src_migf->total_length;
+ memcpy(&dst_migf->vf_data, &src_migf->vf_data,
+ sizeof(struct acc_vf_data));
+}
+
static void hisi_acc_vf_disable_fds(struct hisi_acc_vf_core_device *hisi_acc_vdev)
{
if (hisi_acc_vdev->resuming_migf) {
+ hisi_acc_debug_migf_copy(hisi_acc_vdev, hisi_acc_vdev->resuming_migf);
hisi_acc_vf_disable_fd(hisi_acc_vdev->resuming_migf);
fput(hisi_acc_vdev->resuming_migf->filp);
hisi_acc_vdev->resuming_migf = NULL;
}
if (hisi_acc_vdev->saving_migf) {
+ hisi_acc_debug_migf_copy(hisi_acc_vdev, hisi_acc_vdev->saving_migf);
hisi_acc_vf_disable_fd(hisi_acc_vdev->saving_migf);
fput(hisi_acc_vdev->saving_migf->filp);
hisi_acc_vdev->saving_migf = NULL;
}
}
+static struct hisi_acc_vf_core_device *hisi_acc_get_vf_dev(struct vfio_device *vdev)
+{
+ return container_of(vdev, struct hisi_acc_vf_core_device,
+ core_device.vdev);
+}
+
static void hisi_acc_vf_reset(struct hisi_acc_vf_core_device *hisi_acc_vdev)
{
hisi_acc_vdev->vf_qm_state = QM_NOT_READY;
@@ -1031,8 +1065,7 @@ static struct file *
hisi_acc_vfio_pci_set_device_state(struct vfio_device *vdev,
enum vfio_device_mig_state new_state)
{
- struct hisi_acc_vf_core_device *hisi_acc_vdev = container_of(vdev,
- struct hisi_acc_vf_core_device, core_device.vdev);
+ struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(vdev);
enum vfio_device_mig_state next_state;
struct file *res = NULL;
int ret;
@@ -1073,8 +1106,7 @@ static int
hisi_acc_vfio_pci_get_device_state(struct vfio_device *vdev,
enum vfio_device_mig_state *curr_state)
{
- struct hisi_acc_vf_core_device *hisi_acc_vdev = container_of(vdev,
- struct hisi_acc_vf_core_device, core_device.vdev);
+ struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(vdev);
mutex_lock(&hisi_acc_vdev->state_mutex);
*curr_state = hisi_acc_vdev->mig_state;
@@ -1276,10 +1308,132 @@ static long hisi_acc_vfio_pci_ioctl(struct vfio_device *core_vdev, unsigned int
return vfio_pci_core_ioctl(core_vdev, cmd, arg);
}
+static int hisi_acc_vf_debug_check(struct seq_file *seq, struct vfio_device *vdev)
+{
+ struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(vdev);
+ struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
+ int ret;
+
+ lockdep_assert_held(&hisi_acc_vdev->open_mutex);
+ /*
+ * When the device is not opened, the io_base is not mapped.
+ * The driver cannot perform device read and write operations.
+ */
+ if (!hisi_acc_vdev->dev_opened) {
+ seq_puts(seq, "device not opened!\n");
+ return -EINVAL;
+ }
+
+ ret = qm_wait_dev_not_ready(vf_qm);
+ if (ret) {
+ seq_puts(seq, "VF device not ready!\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int hisi_acc_vf_debug_cmd(struct seq_file *seq, void *data)
+{
+ struct device *vf_dev = seq->private;
+ struct vfio_pci_core_device *core_device = dev_get_drvdata(vf_dev);
+ struct vfio_device *vdev = &core_device->vdev;
+ struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(vdev);
+ struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
+ u64 value;
+ int ret;
+
+ mutex_lock(&hisi_acc_vdev->open_mutex);
+ ret = hisi_acc_vf_debug_check(seq, vdev);
+ if (ret) {
+ mutex_unlock(&hisi_acc_vdev->open_mutex);
+ return ret;
+ }
+
+ value = readl(vf_qm->io_base + QM_MB_CMD_SEND_BASE);
+ if (value == QM_MB_CMD_NOT_READY) {
+ mutex_unlock(&hisi_acc_vdev->open_mutex);
+ seq_puts(seq, "mailbox cmd channel not ready!\n");
+ return -EINVAL;
+ }
+ mutex_unlock(&hisi_acc_vdev->open_mutex);
+ seq_puts(seq, "mailbox cmd channel ready!\n");
+
+ return 0;
+}
+
+static int hisi_acc_vf_dev_read(struct seq_file *seq, void *data)
+{
+ struct device *vf_dev = seq->private;
+ struct vfio_pci_core_device *core_device = dev_get_drvdata(vf_dev);
+ struct vfio_device *vdev = &core_device->vdev;
+ struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(vdev);
+ size_t vf_data_sz = offsetofend(struct acc_vf_data, padding);
+ struct acc_vf_data *vf_data;
+ int ret;
+
+ mutex_lock(&hisi_acc_vdev->open_mutex);
+ ret = hisi_acc_vf_debug_check(seq, vdev);
+ if (ret) {
+ mutex_unlock(&hisi_acc_vdev->open_mutex);
+ return ret;
+ }
+
+ mutex_lock(&hisi_acc_vdev->state_mutex);
+ vf_data = kzalloc(sizeof(*vf_data), GFP_KERNEL);
+ if (!vf_data) {
+ ret = -ENOMEM;
+ goto mutex_release;
+ }
+
+ vf_data->vf_qm_state = hisi_acc_vdev->vf_qm_state;
+ ret = vf_qm_read_data(&hisi_acc_vdev->vf_qm, vf_data);
+ if (ret)
+ goto migf_err;
+
+ seq_hex_dump(seq, "Dev Data:", DUMP_PREFIX_OFFSET, 16, 1,
+ (const void *)vf_data, vf_data_sz, false);
+
+ seq_printf(seq,
+ "guest driver load: %u\n"
+ "data size: %lu\n",
+ hisi_acc_vdev->vf_qm_state,
+ sizeof(struct acc_vf_data));
+
+migf_err:
+ kfree(vf_data);
+mutex_release:
+ mutex_unlock(&hisi_acc_vdev->state_mutex);
+ mutex_unlock(&hisi_acc_vdev->open_mutex);
+
+ return ret;
+}
+
+static int hisi_acc_vf_migf_read(struct seq_file *seq, void *data)
+{
+ struct device *vf_dev = seq->private;
+ struct vfio_pci_core_device *core_device = dev_get_drvdata(vf_dev);
+ struct vfio_device *vdev = &core_device->vdev;
+ struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(vdev);
+ size_t vf_data_sz = offsetofend(struct acc_vf_data, padding);
+ struct hisi_acc_vf_migration_file *debug_migf = hisi_acc_vdev->debug_migf;
+
+ /* Check whether the live migration operation has been performed */
+ if (debug_migf->total_length < QM_MATCH_SIZE) {
+ seq_puts(seq, "device not migrated!\n");
+ return -EAGAIN;
+ }
+
+ seq_hex_dump(seq, "Mig Data:", DUMP_PREFIX_OFFSET, 16, 1,
+ (const void *)&debug_migf->vf_data, vf_data_sz, false);
+ seq_printf(seq, "migrate data length: %lu\n", debug_migf->total_length);
+
+ return 0;
+}
+
static int hisi_acc_vfio_pci_open_device(struct vfio_device *core_vdev)
{
- struct hisi_acc_vf_core_device *hisi_acc_vdev = container_of(core_vdev,
- struct hisi_acc_vf_core_device, core_device.vdev);
+ struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(core_vdev);
struct vfio_pci_core_device *vdev = &hisi_acc_vdev->core_device;
int ret;
@@ -1288,12 +1442,16 @@ static int hisi_acc_vfio_pci_open_device(struct vfio_device *core_vdev)
return ret;
if (core_vdev->mig_ops) {
+ mutex_lock(&hisi_acc_vdev->open_mutex);
ret = hisi_acc_vf_qm_init(hisi_acc_vdev);
if (ret) {
+ mutex_unlock(&hisi_acc_vdev->open_mutex);
vfio_pci_core_disable(vdev);
return ret;
}
hisi_acc_vdev->mig_state = VFIO_DEVICE_STATE_RUNNING;
+ hisi_acc_vdev->dev_opened = true;
+ mutex_unlock(&hisi_acc_vdev->open_mutex);
}
vfio_pci_core_finish_enable(vdev);
@@ -1302,11 +1460,13 @@ static int hisi_acc_vfio_pci_open_device(struct vfio_device *core_vdev)
static void hisi_acc_vfio_pci_close_device(struct vfio_device *core_vdev)
{
- struct hisi_acc_vf_core_device *hisi_acc_vdev = container_of(core_vdev,
- struct hisi_acc_vf_core_device, core_device.vdev);
+ struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(core_vdev);
struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
+ mutex_lock(&hisi_acc_vdev->open_mutex);
+ hisi_acc_vdev->dev_opened = false;
iounmap(vf_qm->io_base);
+ mutex_unlock(&hisi_acc_vdev->open_mutex);
vfio_pci_core_close_device(core_vdev);
}
@@ -1318,8 +1478,7 @@ static const struct vfio_migration_ops hisi_acc_vfio_pci_migrn_state_ops = {
static int hisi_acc_vfio_pci_migrn_init_dev(struct vfio_device *core_vdev)
{
- struct hisi_acc_vf_core_device *hisi_acc_vdev = container_of(core_vdev,
- struct hisi_acc_vf_core_device, core_device.vdev);
+ struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(core_vdev);
struct pci_dev *pdev = to_pci_dev(core_vdev->dev);
struct hisi_qm *pf_qm = hisi_acc_get_pf_qm(pdev);
@@ -1327,6 +1486,7 @@ static int hisi_acc_vfio_pci_migrn_init_dev(struct vfio_device *core_vdev)
hisi_acc_vdev->pf_qm = pf_qm;
hisi_acc_vdev->vf_dev = pdev;
mutex_init(&hisi_acc_vdev->state_mutex);
+ mutex_init(&hisi_acc_vdev->open_mutex);
core_vdev->migration_flags = VFIO_MIGRATION_STOP_COPY | VFIO_MIGRATION_PRE_COPY;
core_vdev->mig_ops = &hisi_acc_vfio_pci_migrn_state_ops;
@@ -1372,6 +1532,47 @@ static const struct vfio_device_ops hisi_acc_vfio_pci_ops = {
.detach_ioas = vfio_iommufd_physical_detach_ioas,
};
+static void hisi_acc_vfio_debug_init(struct hisi_acc_vf_core_device *hisi_acc_vdev)
+{
+ struct vfio_device *vdev = &hisi_acc_vdev->core_device.vdev;
+ struct hisi_acc_vf_migration_file *migf;
+ struct dentry *vfio_dev_migration;
+ struct dentry *vfio_hisi_acc;
+ struct device *dev = vdev->dev;
+
+ if (!debugfs_initialized() ||
+ !IS_ENABLED(CONFIG_VFIO_DEBUGFS))
+ return;
+
+ if (vdev->ops != &hisi_acc_vfio_pci_migrn_ops)
+ return;
+
+ vfio_dev_migration = debugfs_lookup("migration", vdev->debug_root);
+ if (!vfio_dev_migration) {
+ dev_err(dev, "failed to lookup migration debugfs file!\n");
+ return;
+ }
+
+ migf = kzalloc(sizeof(*migf), GFP_KERNEL);
+ if (!migf)
+ return;
+ hisi_acc_vdev->debug_migf = migf;
+
+ vfio_hisi_acc = debugfs_create_dir("hisi_acc", vfio_dev_migration);
+ debugfs_create_devm_seqfile(dev, "dev_data", vfio_hisi_acc,
+ hisi_acc_vf_dev_read);
+ debugfs_create_devm_seqfile(dev, "migf_data", vfio_hisi_acc,
+ hisi_acc_vf_migf_read);
+ debugfs_create_devm_seqfile(dev, "cmd_state", vfio_hisi_acc,
+ hisi_acc_vf_debug_cmd);
+}
+
+static void hisi_acc_vf_debugfs_exit(struct hisi_acc_vf_core_device *hisi_acc_vdev)
+{
+ kfree(hisi_acc_vdev->debug_migf);
+ hisi_acc_vdev->debug_migf = NULL;
+}
+
static int hisi_acc_vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct hisi_acc_vf_core_device *hisi_acc_vdev;
@@ -1398,6 +1599,8 @@ static int hisi_acc_vfio_pci_probe(struct pci_dev *pdev, const struct pci_device
ret = vfio_pci_core_register_device(&hisi_acc_vdev->core_device);
if (ret)
goto out_put_vdev;
+
+ hisi_acc_vfio_debug_init(hisi_acc_vdev);
return 0;
out_put_vdev:
@@ -1410,6 +1613,7 @@ static void hisi_acc_vfio_pci_remove(struct pci_dev *pdev)
struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_drvdata(pdev);
vfio_pci_core_unregister_device(&hisi_acc_vdev->core_device);
+ hisi_acc_vf_debugfs_exit(hisi_acc_vdev);
vfio_put_device(&hisi_acc_vdev->core_device.vdev);
}
diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h
index 5bab46602fad..245d7537b2bc 100644
--- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h
+++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h
@@ -32,6 +32,7 @@
#define QM_SQC_VFT_BASE_MASK_V2 GENMASK(15, 0)
#define QM_SQC_VFT_NUM_SHIFT_V2 45
#define QM_SQC_VFT_NUM_MASK_V2 GENMASK(9, 0)
+#define QM_MB_CMD_NOT_READY 0xffffffff
/* RW regs */
#define QM_REGS_MAX_LEN 7
@@ -99,6 +100,13 @@ struct hisi_acc_vf_migration_file {
struct hisi_acc_vf_core_device {
struct vfio_pci_core_device core_device;
u8 match_done;
+ /*
+ * io_base is only valid when dev_opened is true,
+ * which is protected by open_mutex.
+ */
+ bool dev_opened;
+ /* Ensure the accuracy of dev_opened operation */
+ struct mutex open_mutex;
/* For migration state */
struct mutex state_mutex;
@@ -107,9 +115,20 @@ struct hisi_acc_vf_core_device {
struct pci_dev *vf_dev;
struct hisi_qm *pf_qm;
struct hisi_qm vf_qm;
+ /*
+ * vf_qm_state represents the QM_VF_STATE register value.
+ * It is set by Guest driver for the ACC VF dev indicating
+ * the driver has loaded and configured the dev correctly.
+ */
u32 vf_qm_state;
int vf_id;
struct hisi_acc_vf_migration_file *resuming_migf;
struct hisi_acc_vf_migration_file *saving_migf;
+
+ /*
+ * It holds migration data corresponding to the last migration
+ * and is used by the debugfs interface to report it.
+ */
+ struct hisi_acc_vf_migration_file *debug_migf;
};
#endif /* HISI_ACC_VFIO_PCI_H */
diff --git a/drivers/vfio/pci/mlx5/cmd.c b/drivers/vfio/pci/mlx5/cmd.c
index 41a4b0cf4297..7527e277c898 100644
--- a/drivers/vfio/pci/mlx5/cmd.c
+++ b/drivers/vfio/pci/mlx5/cmd.c
@@ -423,6 +423,7 @@ static int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf,
unsigned long filled;
unsigned int to_fill;
int ret;
+ int i;
to_fill = min_t(unsigned int, npages, PAGE_SIZE / sizeof(*page_list));
page_list = kvzalloc(to_fill * sizeof(*page_list), GFP_KERNEL_ACCOUNT);
@@ -443,7 +444,7 @@ static int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf,
GFP_KERNEL_ACCOUNT);
if (ret)
- goto err;
+ goto err_append;
buf->allocated_length += filled * PAGE_SIZE;
/* clean input for another bulk allocation */
memset(page_list, 0, filled * sizeof(*page_list));
@@ -454,6 +455,9 @@ static int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf,
kvfree(page_list);
return 0;
+err_append:
+ for (i = filled - 1; i >= 0; i--)
+ __free_page(page_list[i]);
err:
kvfree(page_list);
return ret;
diff --git a/drivers/vfio/pci/mlx5/main.c b/drivers/vfio/pci/mlx5/main.c
index 242c23eef452..8833e60d42f5 100644
--- a/drivers/vfio/pci/mlx5/main.c
+++ b/drivers/vfio/pci/mlx5/main.c
@@ -640,14 +640,11 @@ mlx5vf_pci_save_device_data(struct mlx5vf_pci_core_device *mvdev, bool track)
O_RDONLY);
if (IS_ERR(migf->filp)) {
ret = PTR_ERR(migf->filp);
- goto end;
+ kfree(migf);
+ return ERR_PTR(ret);
}
migf->mvdev = mvdev;
- ret = mlx5vf_cmd_alloc_pd(migf);
- if (ret)
- goto out_free;
-
stream_open(migf->filp->f_inode, migf->filp);
mutex_init(&migf->lock);
init_waitqueue_head(&migf->poll_wait);
@@ -663,6 +660,11 @@ mlx5vf_pci_save_device_data(struct mlx5vf_pci_core_device *mvdev, bool track)
INIT_LIST_HEAD(&migf->buf_list);
INIT_LIST_HEAD(&migf->avail_list);
spin_lock_init(&migf->list_lock);
+
+ ret = mlx5vf_cmd_alloc_pd(migf);
+ if (ret)
+ goto out;
+
ret = mlx5vf_cmd_query_vhca_migration_state(mvdev, &length, &full_size, 0);
if (ret)
goto out_pd;
@@ -692,10 +694,8 @@ out_save:
mlx5vf_free_data_buffer(buf);
out_pd:
mlx5fv_cmd_clean_migf_resources(migf);
-out_free:
+out:
fput(migf->filp);
-end:
- kfree(migf);
return ERR_PTR(ret);
}
@@ -1016,13 +1016,19 @@ mlx5vf_pci_resume_device_data(struct mlx5vf_pci_core_device *mvdev)
O_WRONLY);
if (IS_ERR(migf->filp)) {
ret = PTR_ERR(migf->filp);
- goto end;
+ kfree(migf);
+ return ERR_PTR(ret);
}
+ stream_open(migf->filp->f_inode, migf->filp);
+ mutex_init(&migf->lock);
+ INIT_LIST_HEAD(&migf->buf_list);
+ INIT_LIST_HEAD(&migf->avail_list);
+ spin_lock_init(&migf->list_lock);
migf->mvdev = mvdev;
ret = mlx5vf_cmd_alloc_pd(migf);
if (ret)
- goto out_free;
+ goto out;
buf = mlx5vf_alloc_data_buffer(migf, 0, DMA_TO_DEVICE);
if (IS_ERR(buf)) {
@@ -1041,20 +1047,13 @@ mlx5vf_pci_resume_device_data(struct mlx5vf_pci_core_device *mvdev)
migf->buf_header[0] = buf;
migf->load_state = MLX5_VF_LOAD_STATE_READ_HEADER;
- stream_open(migf->filp->f_inode, migf->filp);
- mutex_init(&migf->lock);
- INIT_LIST_HEAD(&migf->buf_list);
- INIT_LIST_HEAD(&migf->avail_list);
- spin_lock_init(&migf->list_lock);
return migf;
out_buf:
mlx5vf_free_data_buffer(migf->buf[0]);
out_pd:
mlx5vf_cmd_dealloc_pd(migf);
-out_free:
+out:
fput(migf->filp);
-end:
- kfree(migf);
return ERR_PTR(ret);
}
diff --git a/drivers/vfio/pci/nvgrace-gpu/main.c b/drivers/vfio/pci/nvgrace-gpu/main.c
index a7fd018aa548..a467085038f0 100644
--- a/drivers/vfio/pci/nvgrace-gpu/main.c
+++ b/drivers/vfio/pci/nvgrace-gpu/main.c
@@ -866,6 +866,8 @@ static const struct pci_device_id nvgrace_gpu_vfio_pci_table[] = {
{ PCI_DRIVER_OVERRIDE_DEVICE_VFIO(PCI_VENDOR_ID_NVIDIA, 0x2342) },
/* GH200 480GB */
{ PCI_DRIVER_OVERRIDE_DEVICE_VFIO(PCI_VENDOR_ID_NVIDIA, 0x2345) },
+ /* GH200 SKU */
+ { PCI_DRIVER_OVERRIDE_DEVICE_VFIO(PCI_VENDOR_ID_NVIDIA, 0x2348) },
{}
};
diff --git a/drivers/vfio/pci/qat/main.c b/drivers/vfio/pci/qat/main.c
index be3644ced17b..c78cb6de9390 100644
--- a/drivers/vfio/pci/qat/main.c
+++ b/drivers/vfio/pci/qat/main.c
@@ -304,7 +304,7 @@ static ssize_t qat_vf_resume_write(struct file *filp, const char __user *buf,
offs = &filp->f_pos;
if (*offs < 0 ||
- check_add_overflow((loff_t)len, *offs, &end))
+ check_add_overflow(len, *offs, &end))
return -EOVERFLOW;
if (end > mig_dev->state_size)
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index 97422aafaa7b..ea2745c1ac5e 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -313,6 +313,10 @@ static int vfio_virt_config_read(struct vfio_pci_core_device *vdev, int pos,
return count;
}
+static struct perm_bits direct_ro_perms = {
+ .readfn = vfio_direct_config_read,
+};
+
/* Default capability regions to read-only, no-virtualization */
static struct perm_bits cap_perms[PCI_CAP_ID_MAX + 1] = {
[0 ... PCI_CAP_ID_MAX] = { .readfn = vfio_direct_config_read }
@@ -1897,9 +1901,17 @@ static ssize_t vfio_config_do_rw(struct vfio_pci_core_device *vdev, char __user
cap_start = *ppos;
} else {
if (*ppos >= PCI_CFG_SPACE_SIZE) {
- WARN_ON(cap_id > PCI_EXT_CAP_ID_MAX);
+ /*
+ * We can get a cap_id that exceeds PCI_EXT_CAP_ID_MAX
+ * if we're hiding an unknown capability at the start
+ * of the extended capability list. Use default, ro
+ * access, which will virtualize the id and next values.
+ */
+ if (cap_id > PCI_EXT_CAP_ID_MAX)
+ perm = &direct_ro_perms;
+ else
+ perm = &ecap_perms[cap_id];
- perm = &ecap_perms[cap_id];
cap_start = vfio_find_cap_start(vdev, *ppos);
} else {
WARN_ON(cap_id > PCI_CAP_ID_MAX);
diff --git a/drivers/vfio/pci/virtio/Kconfig b/drivers/vfio/pci/virtio/Kconfig
index bd80eca4a196..2770f7eb702c 100644
--- a/drivers/vfio/pci/virtio/Kconfig
+++ b/drivers/vfio/pci/virtio/Kconfig
@@ -1,15 +1,31 @@
# SPDX-License-Identifier: GPL-2.0-only
config VIRTIO_VFIO_PCI
- tristate "VFIO support for VIRTIO NET PCI devices"
- depends on VIRTIO_PCI && VIRTIO_PCI_ADMIN_LEGACY
- select VFIO_PCI_CORE
- help
- This provides support for exposing VIRTIO NET VF devices which support
- legacy IO access, using the VFIO framework that can work with a legacy
- virtio driver in the guest.
- Based on PCIe spec, VFs do not support I/O Space.
- As of that this driver emulates I/O BAR in software to let a VF be
- seen as a transitional device by its users and let it work with
- a legacy driver.
-
- If you don't know what to do here, say N.
+ tristate "VFIO support for VIRTIO NET PCI VF devices"
+ depends on VIRTIO_PCI
+ select VFIO_PCI_CORE
+ help
+ This provides migration support for VIRTIO NET PCI VF devices
+ using the VFIO framework. Migration support requires the
+ SR-IOV PF device to support specific VIRTIO extensions,
+ otherwise this driver provides no additional functionality
+ beyond vfio-pci.
+
+ Migration support in this driver relies on dirty page tracking
+ provided by the IOMMU hardware and exposed through IOMMUFD, any
+ other use cases are dis-recommended.
+
+ If you don't know what to do here, say N.
+
+config VIRTIO_VFIO_PCI_ADMIN_LEGACY
+ bool "Legacy I/O support for VIRTIO NET PCI VF devices"
+ depends on VIRTIO_VFIO_PCI && VIRTIO_PCI_ADMIN_LEGACY
+ default y
+ help
+ This extends the virtio-vfio-pci driver to support legacy I/O
+ access, allowing use of legacy virtio drivers with VIRTIO NET
+ PCI VF devices. Legacy I/O support requires the SR-IOV PF
+ device to support and enable specific VIRTIO extensions,
+ otherwise this driver provides no additional functionality
+ beyond vfio-pci.
+
+ If you don't know what to do here, say N.
diff --git a/drivers/vfio/pci/virtio/Makefile b/drivers/vfio/pci/virtio/Makefile
index 7171105baf33..d9b0bb40d6b3 100644
--- a/drivers/vfio/pci/virtio/Makefile
+++ b/drivers/vfio/pci/virtio/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_VIRTIO_VFIO_PCI) += virtio-vfio-pci.o
-virtio-vfio-pci-y := main.o
+virtio-vfio-pci-y := main.o migrate.o
+virtio-vfio-pci-$(CONFIG_VIRTIO_VFIO_PCI_ADMIN_LEGACY) += legacy_io.o
diff --git a/drivers/vfio/pci/virtio/common.h b/drivers/vfio/pci/virtio/common.h
new file mode 100644
index 000000000000..c7d7e27af386
--- /dev/null
+++ b/drivers/vfio/pci/virtio/common.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef VIRTIO_VFIO_COMMON_H
+#define VIRTIO_VFIO_COMMON_H
+
+#include <linux/kernel.h>
+#include <linux/virtio.h>
+#include <linux/vfio_pci_core.h>
+#include <linux/virtio_pci.h>
+
+enum virtiovf_migf_state {
+ VIRTIOVF_MIGF_STATE_ERROR = 1,
+ VIRTIOVF_MIGF_STATE_PRECOPY = 2,
+ VIRTIOVF_MIGF_STATE_COMPLETE = 3,
+};
+
+enum virtiovf_load_state {
+ VIRTIOVF_LOAD_STATE_READ_HEADER,
+ VIRTIOVF_LOAD_STATE_PREP_HEADER_DATA,
+ VIRTIOVF_LOAD_STATE_READ_HEADER_DATA,
+ VIRTIOVF_LOAD_STATE_PREP_CHUNK,
+ VIRTIOVF_LOAD_STATE_READ_CHUNK,
+ VIRTIOVF_LOAD_STATE_LOAD_CHUNK,
+};
+
+struct virtiovf_data_buffer {
+ struct sg_append_table table;
+ loff_t start_pos;
+ u64 length;
+ u64 allocated_length;
+ struct list_head buf_elm;
+ u8 include_header_object:1;
+ struct virtiovf_migration_file *migf;
+ /* Optimize virtiovf_get_migration_page() for sequential access */
+ struct scatterlist *last_offset_sg;
+ unsigned int sg_last_entry;
+ unsigned long last_offset;
+};
+
+enum virtiovf_migf_header_flags {
+ VIRTIOVF_MIGF_HEADER_FLAGS_TAG_MANDATORY = 0,
+ VIRTIOVF_MIGF_HEADER_FLAGS_TAG_OPTIONAL = 1 << 0,
+};
+
+enum virtiovf_migf_header_tag {
+ VIRTIOVF_MIGF_HEADER_TAG_DEVICE_DATA = 0,
+};
+
+struct virtiovf_migration_header {
+ __le64 record_size;
+ /* For future use in case we may need to change the kernel protocol */
+ __le32 flags; /* Use virtiovf_migf_header_flags */
+ __le32 tag; /* Use virtiovf_migf_header_tag */
+ __u8 data[]; /* Its size is given in the record_size */
+};
+
+struct virtiovf_migration_file {
+ struct file *filp;
+ /* synchronize access to the file state */
+ struct mutex lock;
+ loff_t max_pos;
+ u64 pre_copy_initial_bytes;
+ struct ratelimit_state pre_copy_rl_state;
+ u64 record_size;
+ u32 record_tag;
+ u8 has_obj_id:1;
+ u32 obj_id;
+ enum virtiovf_migf_state state;
+ enum virtiovf_load_state load_state;
+ /* synchronize access to the lists */
+ spinlock_t list_lock;
+ struct list_head buf_list;
+ struct list_head avail_list;
+ struct virtiovf_data_buffer *buf;
+ struct virtiovf_data_buffer *buf_header;
+ struct virtiovf_pci_core_device *virtvdev;
+};
+
+struct virtiovf_pci_core_device {
+ struct vfio_pci_core_device core_device;
+#ifdef CONFIG_VIRTIO_VFIO_PCI_ADMIN_LEGACY
+ u8 *bar0_virtual_buf;
+ /* synchronize access to the virtual buf */
+ struct mutex bar_mutex;
+ void __iomem *notify_addr;
+ u64 notify_offset;
+ __le32 pci_base_addr_0;
+ __le16 pci_cmd;
+ u8 bar0_virtual_buf_size;
+ u8 notify_bar;
+#endif
+
+ /* LM related */
+ u8 migrate_cap:1;
+ u8 deferred_reset:1;
+ /* protect migration state */
+ struct mutex state_mutex;
+ enum vfio_device_mig_state mig_state;
+ /* protect the reset_done flow */
+ spinlock_t reset_lock;
+ struct virtiovf_migration_file *resuming_migf;
+ struct virtiovf_migration_file *saving_migf;
+};
+
+void virtiovf_set_migratable(struct virtiovf_pci_core_device *virtvdev);
+void virtiovf_open_migration(struct virtiovf_pci_core_device *virtvdev);
+void virtiovf_close_migration(struct virtiovf_pci_core_device *virtvdev);
+void virtiovf_migration_reset_done(struct pci_dev *pdev);
+
+#ifdef CONFIG_VIRTIO_VFIO_PCI_ADMIN_LEGACY
+int virtiovf_open_legacy_io(struct virtiovf_pci_core_device *virtvdev);
+long virtiovf_vfio_pci_core_ioctl(struct vfio_device *core_vdev,
+ unsigned int cmd, unsigned long arg);
+int virtiovf_pci_ioctl_get_region_info(struct vfio_device *core_vdev,
+ unsigned int cmd, unsigned long arg);
+ssize_t virtiovf_pci_core_write(struct vfio_device *core_vdev,
+ const char __user *buf, size_t count,
+ loff_t *ppos);
+ssize_t virtiovf_pci_core_read(struct vfio_device *core_vdev, char __user *buf,
+ size_t count, loff_t *ppos);
+bool virtiovf_support_legacy_io(struct pci_dev *pdev);
+int virtiovf_init_legacy_io(struct virtiovf_pci_core_device *virtvdev);
+void virtiovf_release_legacy_io(struct virtiovf_pci_core_device *virtvdev);
+void virtiovf_legacy_io_reset_done(struct pci_dev *pdev);
+#endif
+
+#endif /* VIRTIO_VFIO_COMMON_H */
diff --git a/drivers/vfio/pci/virtio/legacy_io.c b/drivers/vfio/pci/virtio/legacy_io.c
new file mode 100644
index 000000000000..20382ee15fac
--- /dev/null
+++ b/drivers/vfio/pci/virtio/legacy_io.c
@@ -0,0 +1,418 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/vfio.h>
+#include <linux/vfio_pci_core.h>
+#include <linux/virtio_pci.h>
+#include <linux/virtio_net.h>
+#include <linux/virtio_pci_admin.h>
+
+#include "common.h"
+
+static int
+virtiovf_issue_legacy_rw_cmd(struct virtiovf_pci_core_device *virtvdev,
+ loff_t pos, char __user *buf,
+ size_t count, bool read)
+{
+ bool msix_enabled =
+ (virtvdev->core_device.irq_type == VFIO_PCI_MSIX_IRQ_INDEX);
+ struct pci_dev *pdev = virtvdev->core_device.pdev;
+ u8 *bar0_buf = virtvdev->bar0_virtual_buf;
+ bool common;
+ u8 offset;
+ int ret;
+
+ common = pos < VIRTIO_PCI_CONFIG_OFF(msix_enabled);
+ /* offset within the relevant configuration area */
+ offset = common ? pos : pos - VIRTIO_PCI_CONFIG_OFF(msix_enabled);
+ mutex_lock(&virtvdev->bar_mutex);
+ if (read) {
+ if (common)
+ ret = virtio_pci_admin_legacy_common_io_read(pdev, offset,
+ count, bar0_buf + pos);
+ else
+ ret = virtio_pci_admin_legacy_device_io_read(pdev, offset,
+ count, bar0_buf + pos);
+ if (ret)
+ goto out;
+ if (copy_to_user(buf, bar0_buf + pos, count))
+ ret = -EFAULT;
+ } else {
+ if (copy_from_user(bar0_buf + pos, buf, count)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (common)
+ ret = virtio_pci_admin_legacy_common_io_write(pdev, offset,
+ count, bar0_buf + pos);
+ else
+ ret = virtio_pci_admin_legacy_device_io_write(pdev, offset,
+ count, bar0_buf + pos);
+ }
+out:
+ mutex_unlock(&virtvdev->bar_mutex);
+ return ret;
+}
+
+static int
+virtiovf_pci_bar0_rw(struct virtiovf_pci_core_device *virtvdev,
+ loff_t pos, char __user *buf,
+ size_t count, bool read)
+{
+ struct vfio_pci_core_device *core_device = &virtvdev->core_device;
+ struct pci_dev *pdev = core_device->pdev;
+ u16 queue_notify;
+ int ret;
+
+ if (!(le16_to_cpu(virtvdev->pci_cmd) & PCI_COMMAND_IO))
+ return -EIO;
+
+ if (pos + count > virtvdev->bar0_virtual_buf_size)
+ return -EINVAL;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret) {
+ pci_info_ratelimited(pdev, "runtime resume failed %d\n", ret);
+ return -EIO;
+ }
+
+ switch (pos) {
+ case VIRTIO_PCI_QUEUE_NOTIFY:
+ if (count != sizeof(queue_notify)) {
+ ret = -EINVAL;
+ goto end;
+ }
+ if (read) {
+ ret = vfio_pci_core_ioread16(core_device, true, &queue_notify,
+ virtvdev->notify_addr);
+ if (ret)
+ goto end;
+ if (copy_to_user(buf, &queue_notify,
+ sizeof(queue_notify))) {
+ ret = -EFAULT;
+ goto end;
+ }
+ } else {
+ if (copy_from_user(&queue_notify, buf, count)) {
+ ret = -EFAULT;
+ goto end;
+ }
+ ret = vfio_pci_core_iowrite16(core_device, true, queue_notify,
+ virtvdev->notify_addr);
+ }
+ break;
+ default:
+ ret = virtiovf_issue_legacy_rw_cmd(virtvdev, pos, buf, count,
+ read);
+ }
+
+end:
+ pm_runtime_put(&pdev->dev);
+ return ret ? ret : count;
+}
+
+static ssize_t virtiovf_pci_read_config(struct vfio_device *core_vdev,
+ char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct virtiovf_pci_core_device *virtvdev = container_of(
+ core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
+ loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
+ size_t register_offset;
+ loff_t copy_offset;
+ size_t copy_count;
+ __le32 val32;
+ __le16 val16;
+ u8 val8;
+ int ret;
+
+ ret = vfio_pci_core_read(core_vdev, buf, count, ppos);
+ if (ret < 0)
+ return ret;
+
+ if (vfio_pci_core_range_intersect_range(pos, count, PCI_DEVICE_ID,
+ sizeof(val16), &copy_offset,
+ &copy_count, &register_offset)) {
+ val16 = cpu_to_le16(VIRTIO_TRANS_ID_NET);
+ if (copy_to_user(buf + copy_offset, (void *)&val16 + register_offset, copy_count))
+ return -EFAULT;
+ }
+
+ if ((le16_to_cpu(virtvdev->pci_cmd) & PCI_COMMAND_IO) &&
+ vfio_pci_core_range_intersect_range(pos, count, PCI_COMMAND,
+ sizeof(val16), &copy_offset,
+ &copy_count, &register_offset)) {
+ if (copy_from_user((void *)&val16 + register_offset, buf + copy_offset,
+ copy_count))
+ return -EFAULT;
+ val16 |= cpu_to_le16(PCI_COMMAND_IO);
+ if (copy_to_user(buf + copy_offset, (void *)&val16 + register_offset,
+ copy_count))
+ return -EFAULT;
+ }
+
+ if (vfio_pci_core_range_intersect_range(pos, count, PCI_REVISION_ID,
+ sizeof(val8), &copy_offset,
+ &copy_count, &register_offset)) {
+ /* Transional needs to have revision 0 */
+ val8 = 0;
+ if (copy_to_user(buf + copy_offset, &val8, copy_count))
+ return -EFAULT;
+ }
+
+ if (vfio_pci_core_range_intersect_range(pos, count, PCI_BASE_ADDRESS_0,
+ sizeof(val32), &copy_offset,
+ &copy_count, &register_offset)) {
+ u32 bar_mask = ~(virtvdev->bar0_virtual_buf_size - 1);
+ u32 pci_base_addr_0 = le32_to_cpu(virtvdev->pci_base_addr_0);
+
+ val32 = cpu_to_le32((pci_base_addr_0 & bar_mask) | PCI_BASE_ADDRESS_SPACE_IO);
+ if (copy_to_user(buf + copy_offset, (void *)&val32 + register_offset, copy_count))
+ return -EFAULT;
+ }
+
+ if (vfio_pci_core_range_intersect_range(pos, count, PCI_SUBSYSTEM_ID,
+ sizeof(val16), &copy_offset,
+ &copy_count, &register_offset)) {
+ /*
+ * Transitional devices use the PCI subsystem device id as
+ * virtio device id, same as legacy driver always did.
+ */
+ val16 = cpu_to_le16(VIRTIO_ID_NET);
+ if (copy_to_user(buf + copy_offset, (void *)&val16 + register_offset,
+ copy_count))
+ return -EFAULT;
+ }
+
+ if (vfio_pci_core_range_intersect_range(pos, count, PCI_SUBSYSTEM_VENDOR_ID,
+ sizeof(val16), &copy_offset,
+ &copy_count, &register_offset)) {
+ val16 = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET);
+ if (copy_to_user(buf + copy_offset, (void *)&val16 + register_offset,
+ copy_count))
+ return -EFAULT;
+ }
+
+ return count;
+}
+
+ssize_t virtiovf_pci_core_read(struct vfio_device *core_vdev, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct virtiovf_pci_core_device *virtvdev = container_of(
+ core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
+ unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
+ loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
+
+ if (!count)
+ return 0;
+
+ if (index == VFIO_PCI_CONFIG_REGION_INDEX)
+ return virtiovf_pci_read_config(core_vdev, buf, count, ppos);
+
+ if (index == VFIO_PCI_BAR0_REGION_INDEX)
+ return virtiovf_pci_bar0_rw(virtvdev, pos, buf, count, true);
+
+ return vfio_pci_core_read(core_vdev, buf, count, ppos);
+}
+
+static ssize_t virtiovf_pci_write_config(struct vfio_device *core_vdev,
+ const char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct virtiovf_pci_core_device *virtvdev = container_of(
+ core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
+ loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
+ size_t register_offset;
+ loff_t copy_offset;
+ size_t copy_count;
+
+ if (vfio_pci_core_range_intersect_range(pos, count, PCI_COMMAND,
+ sizeof(virtvdev->pci_cmd),
+ &copy_offset, &copy_count,
+ &register_offset)) {
+ if (copy_from_user((void *)&virtvdev->pci_cmd + register_offset,
+ buf + copy_offset,
+ copy_count))
+ return -EFAULT;
+ }
+
+ if (vfio_pci_core_range_intersect_range(pos, count, PCI_BASE_ADDRESS_0,
+ sizeof(virtvdev->pci_base_addr_0),
+ &copy_offset, &copy_count,
+ &register_offset)) {
+ if (copy_from_user((void *)&virtvdev->pci_base_addr_0 + register_offset,
+ buf + copy_offset,
+ copy_count))
+ return -EFAULT;
+ }
+
+ return vfio_pci_core_write(core_vdev, buf, count, ppos);
+}
+
+ssize_t virtiovf_pci_core_write(struct vfio_device *core_vdev, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct virtiovf_pci_core_device *virtvdev = container_of(
+ core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
+ unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
+ loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
+
+ if (!count)
+ return 0;
+
+ if (index == VFIO_PCI_CONFIG_REGION_INDEX)
+ return virtiovf_pci_write_config(core_vdev, buf, count, ppos);
+
+ if (index == VFIO_PCI_BAR0_REGION_INDEX)
+ return virtiovf_pci_bar0_rw(virtvdev, pos, (char __user *)buf, count, false);
+
+ return vfio_pci_core_write(core_vdev, buf, count, ppos);
+}
+
+int virtiovf_pci_ioctl_get_region_info(struct vfio_device *core_vdev,
+ unsigned int cmd, unsigned long arg)
+{
+ struct virtiovf_pci_core_device *virtvdev = container_of(
+ core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
+ unsigned long minsz = offsetofend(struct vfio_region_info, offset);
+ void __user *uarg = (void __user *)arg;
+ struct vfio_region_info info = {};
+
+ if (copy_from_user(&info, uarg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ switch (info.index) {
+ case VFIO_PCI_BAR0_REGION_INDEX:
+ info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+ info.size = virtvdev->bar0_virtual_buf_size;
+ info.flags = VFIO_REGION_INFO_FLAG_READ |
+ VFIO_REGION_INFO_FLAG_WRITE;
+ return copy_to_user(uarg, &info, minsz) ? -EFAULT : 0;
+ default:
+ return vfio_pci_core_ioctl(core_vdev, cmd, arg);
+ }
+}
+
+long virtiovf_vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
+ unsigned long arg)
+{
+ switch (cmd) {
+ case VFIO_DEVICE_GET_REGION_INFO:
+ return virtiovf_pci_ioctl_get_region_info(core_vdev, cmd, arg);
+ default:
+ return vfio_pci_core_ioctl(core_vdev, cmd, arg);
+ }
+}
+
+static int virtiovf_set_notify_addr(struct virtiovf_pci_core_device *virtvdev)
+{
+ struct vfio_pci_core_device *core_device = &virtvdev->core_device;
+ int ret;
+
+ /*
+ * Setup the BAR where the 'notify' exists to be used by vfio as well
+ * This will let us mmap it only once and use it when needed.
+ */
+ ret = vfio_pci_core_setup_barmap(core_device,
+ virtvdev->notify_bar);
+ if (ret)
+ return ret;
+
+ virtvdev->notify_addr = core_device->barmap[virtvdev->notify_bar] +
+ virtvdev->notify_offset;
+ return 0;
+}
+
+int virtiovf_open_legacy_io(struct virtiovf_pci_core_device *virtvdev)
+{
+ if (!virtvdev->bar0_virtual_buf)
+ return 0;
+
+ /*
+ * Upon close_device() the vfio_pci_core_disable() is called
+ * and will close all the previous mmaps, so it seems that the
+ * valid life cycle for the 'notify' addr is per open/close.
+ */
+ return virtiovf_set_notify_addr(virtvdev);
+}
+
+static int virtiovf_get_device_config_size(unsigned short device)
+{
+ /* Network card */
+ return offsetofend(struct virtio_net_config, status);
+}
+
+static int virtiovf_read_notify_info(struct virtiovf_pci_core_device *virtvdev)
+{
+ u64 offset;
+ int ret;
+ u8 bar;
+
+ ret = virtio_pci_admin_legacy_io_notify_info(virtvdev->core_device.pdev,
+ VIRTIO_ADMIN_CMD_NOTIFY_INFO_FLAGS_OWNER_MEM,
+ &bar, &offset);
+ if (ret)
+ return ret;
+
+ virtvdev->notify_bar = bar;
+ virtvdev->notify_offset = offset;
+ return 0;
+}
+
+static bool virtiovf_bar0_exists(struct pci_dev *pdev)
+{
+ struct resource *res = pdev->resource;
+
+ return res->flags;
+}
+
+bool virtiovf_support_legacy_io(struct pci_dev *pdev)
+{
+ return virtio_pci_admin_has_legacy_io(pdev) && !virtiovf_bar0_exists(pdev);
+}
+
+int virtiovf_init_legacy_io(struct virtiovf_pci_core_device *virtvdev)
+{
+ struct pci_dev *pdev = virtvdev->core_device.pdev;
+ int ret;
+
+ ret = virtiovf_read_notify_info(virtvdev);
+ if (ret)
+ return ret;
+
+ virtvdev->bar0_virtual_buf_size = VIRTIO_PCI_CONFIG_OFF(true) +
+ virtiovf_get_device_config_size(pdev->device);
+ BUILD_BUG_ON(!is_power_of_2(virtvdev->bar0_virtual_buf_size));
+ virtvdev->bar0_virtual_buf = kzalloc(virtvdev->bar0_virtual_buf_size,
+ GFP_KERNEL);
+ if (!virtvdev->bar0_virtual_buf)
+ return -ENOMEM;
+ mutex_init(&virtvdev->bar_mutex);
+ return 0;
+}
+
+void virtiovf_release_legacy_io(struct virtiovf_pci_core_device *virtvdev)
+{
+ kfree(virtvdev->bar0_virtual_buf);
+}
+
+void virtiovf_legacy_io_reset_done(struct pci_dev *pdev)
+{
+ struct virtiovf_pci_core_device *virtvdev = dev_get_drvdata(&pdev->dev);
+
+ virtvdev->pci_cmd = 0;
+}
diff --git a/drivers/vfio/pci/virtio/main.c b/drivers/vfio/pci/virtio/main.c
index b5d3a8c5bbc9..d534d48c4163 100644
--- a/drivers/vfio/pci/virtio/main.c
+++ b/drivers/vfio/pci/virtio/main.c
@@ -16,347 +16,12 @@
#include <linux/virtio_net.h>
#include <linux/virtio_pci_admin.h>
-struct virtiovf_pci_core_device {
- struct vfio_pci_core_device core_device;
- u8 *bar0_virtual_buf;
- /* synchronize access to the virtual buf */
- struct mutex bar_mutex;
- void __iomem *notify_addr;
- u64 notify_offset;
- __le32 pci_base_addr_0;
- __le16 pci_cmd;
- u8 bar0_virtual_buf_size;
- u8 notify_bar;
-};
-
-static int
-virtiovf_issue_legacy_rw_cmd(struct virtiovf_pci_core_device *virtvdev,
- loff_t pos, char __user *buf,
- size_t count, bool read)
-{
- bool msix_enabled =
- (virtvdev->core_device.irq_type == VFIO_PCI_MSIX_IRQ_INDEX);
- struct pci_dev *pdev = virtvdev->core_device.pdev;
- u8 *bar0_buf = virtvdev->bar0_virtual_buf;
- bool common;
- u8 offset;
- int ret;
-
- common = pos < VIRTIO_PCI_CONFIG_OFF(msix_enabled);
- /* offset within the relevant configuration area */
- offset = common ? pos : pos - VIRTIO_PCI_CONFIG_OFF(msix_enabled);
- mutex_lock(&virtvdev->bar_mutex);
- if (read) {
- if (common)
- ret = virtio_pci_admin_legacy_common_io_read(pdev, offset,
- count, bar0_buf + pos);
- else
- ret = virtio_pci_admin_legacy_device_io_read(pdev, offset,
- count, bar0_buf + pos);
- if (ret)
- goto out;
- if (copy_to_user(buf, bar0_buf + pos, count))
- ret = -EFAULT;
- } else {
- if (copy_from_user(bar0_buf + pos, buf, count)) {
- ret = -EFAULT;
- goto out;
- }
-
- if (common)
- ret = virtio_pci_admin_legacy_common_io_write(pdev, offset,
- count, bar0_buf + pos);
- else
- ret = virtio_pci_admin_legacy_device_io_write(pdev, offset,
- count, bar0_buf + pos);
- }
-out:
- mutex_unlock(&virtvdev->bar_mutex);
- return ret;
-}
-
-static int
-virtiovf_pci_bar0_rw(struct virtiovf_pci_core_device *virtvdev,
- loff_t pos, char __user *buf,
- size_t count, bool read)
-{
- struct vfio_pci_core_device *core_device = &virtvdev->core_device;
- struct pci_dev *pdev = core_device->pdev;
- u16 queue_notify;
- int ret;
-
- if (!(le16_to_cpu(virtvdev->pci_cmd) & PCI_COMMAND_IO))
- return -EIO;
-
- if (pos + count > virtvdev->bar0_virtual_buf_size)
- return -EINVAL;
-
- ret = pm_runtime_resume_and_get(&pdev->dev);
- if (ret) {
- pci_info_ratelimited(pdev, "runtime resume failed %d\n", ret);
- return -EIO;
- }
-
- switch (pos) {
- case VIRTIO_PCI_QUEUE_NOTIFY:
- if (count != sizeof(queue_notify)) {
- ret = -EINVAL;
- goto end;
- }
- if (read) {
- ret = vfio_pci_core_ioread16(core_device, true, &queue_notify,
- virtvdev->notify_addr);
- if (ret)
- goto end;
- if (copy_to_user(buf, &queue_notify,
- sizeof(queue_notify))) {
- ret = -EFAULT;
- goto end;
- }
- } else {
- if (copy_from_user(&queue_notify, buf, count)) {
- ret = -EFAULT;
- goto end;
- }
- ret = vfio_pci_core_iowrite16(core_device, true, queue_notify,
- virtvdev->notify_addr);
- }
- break;
- default:
- ret = virtiovf_issue_legacy_rw_cmd(virtvdev, pos, buf, count,
- read);
- }
-
-end:
- pm_runtime_put(&pdev->dev);
- return ret ? ret : count;
-}
-
-static ssize_t virtiovf_pci_read_config(struct vfio_device *core_vdev,
- char __user *buf, size_t count,
- loff_t *ppos)
-{
- struct virtiovf_pci_core_device *virtvdev = container_of(
- core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
- loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
- size_t register_offset;
- loff_t copy_offset;
- size_t copy_count;
- __le32 val32;
- __le16 val16;
- u8 val8;
- int ret;
-
- ret = vfio_pci_core_read(core_vdev, buf, count, ppos);
- if (ret < 0)
- return ret;
-
- if (vfio_pci_core_range_intersect_range(pos, count, PCI_DEVICE_ID,
- sizeof(val16), &copy_offset,
- &copy_count, &register_offset)) {
- val16 = cpu_to_le16(VIRTIO_TRANS_ID_NET);
- if (copy_to_user(buf + copy_offset, (void *)&val16 + register_offset, copy_count))
- return -EFAULT;
- }
-
- if ((le16_to_cpu(virtvdev->pci_cmd) & PCI_COMMAND_IO) &&
- vfio_pci_core_range_intersect_range(pos, count, PCI_COMMAND,
- sizeof(val16), &copy_offset,
- &copy_count, &register_offset)) {
- if (copy_from_user((void *)&val16 + register_offset, buf + copy_offset,
- copy_count))
- return -EFAULT;
- val16 |= cpu_to_le16(PCI_COMMAND_IO);
- if (copy_to_user(buf + copy_offset, (void *)&val16 + register_offset,
- copy_count))
- return -EFAULT;
- }
-
- if (vfio_pci_core_range_intersect_range(pos, count, PCI_REVISION_ID,
- sizeof(val8), &copy_offset,
- &copy_count, &register_offset)) {
- /* Transional needs to have revision 0 */
- val8 = 0;
- if (copy_to_user(buf + copy_offset, &val8, copy_count))
- return -EFAULT;
- }
-
- if (vfio_pci_core_range_intersect_range(pos, count, PCI_BASE_ADDRESS_0,
- sizeof(val32), &copy_offset,
- &copy_count, &register_offset)) {
- u32 bar_mask = ~(virtvdev->bar0_virtual_buf_size - 1);
- u32 pci_base_addr_0 = le32_to_cpu(virtvdev->pci_base_addr_0);
-
- val32 = cpu_to_le32((pci_base_addr_0 & bar_mask) | PCI_BASE_ADDRESS_SPACE_IO);
- if (copy_to_user(buf + copy_offset, (void *)&val32 + register_offset, copy_count))
- return -EFAULT;
- }
-
- if (vfio_pci_core_range_intersect_range(pos, count, PCI_SUBSYSTEM_ID,
- sizeof(val16), &copy_offset,
- &copy_count, &register_offset)) {
- /*
- * Transitional devices use the PCI subsystem device id as
- * virtio device id, same as legacy driver always did.
- */
- val16 = cpu_to_le16(VIRTIO_ID_NET);
- if (copy_to_user(buf + copy_offset, (void *)&val16 + register_offset,
- copy_count))
- return -EFAULT;
- }
-
- if (vfio_pci_core_range_intersect_range(pos, count, PCI_SUBSYSTEM_VENDOR_ID,
- sizeof(val16), &copy_offset,
- &copy_count, &register_offset)) {
- val16 = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET);
- if (copy_to_user(buf + copy_offset, (void *)&val16 + register_offset,
- copy_count))
- return -EFAULT;
- }
-
- return count;
-}
-
-static ssize_t
-virtiovf_pci_core_read(struct vfio_device *core_vdev, char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct virtiovf_pci_core_device *virtvdev = container_of(
- core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
- unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
- loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
-
- if (!count)
- return 0;
-
- if (index == VFIO_PCI_CONFIG_REGION_INDEX)
- return virtiovf_pci_read_config(core_vdev, buf, count, ppos);
-
- if (index == VFIO_PCI_BAR0_REGION_INDEX)
- return virtiovf_pci_bar0_rw(virtvdev, pos, buf, count, true);
-
- return vfio_pci_core_read(core_vdev, buf, count, ppos);
-}
-
-static ssize_t virtiovf_pci_write_config(struct vfio_device *core_vdev,
- const char __user *buf, size_t count,
- loff_t *ppos)
-{
- struct virtiovf_pci_core_device *virtvdev = container_of(
- core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
- loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
- size_t register_offset;
- loff_t copy_offset;
- size_t copy_count;
-
- if (vfio_pci_core_range_intersect_range(pos, count, PCI_COMMAND,
- sizeof(virtvdev->pci_cmd),
- &copy_offset, &copy_count,
- &register_offset)) {
- if (copy_from_user((void *)&virtvdev->pci_cmd + register_offset,
- buf + copy_offset,
- copy_count))
- return -EFAULT;
- }
-
- if (vfio_pci_core_range_intersect_range(pos, count, PCI_BASE_ADDRESS_0,
- sizeof(virtvdev->pci_base_addr_0),
- &copy_offset, &copy_count,
- &register_offset)) {
- if (copy_from_user((void *)&virtvdev->pci_base_addr_0 + register_offset,
- buf + copy_offset,
- copy_count))
- return -EFAULT;
- }
-
- return vfio_pci_core_write(core_vdev, buf, count, ppos);
-}
-
-static ssize_t
-virtiovf_pci_core_write(struct vfio_device *core_vdev, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct virtiovf_pci_core_device *virtvdev = container_of(
- core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
- unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
- loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
-
- if (!count)
- return 0;
-
- if (index == VFIO_PCI_CONFIG_REGION_INDEX)
- return virtiovf_pci_write_config(core_vdev, buf, count, ppos);
-
- if (index == VFIO_PCI_BAR0_REGION_INDEX)
- return virtiovf_pci_bar0_rw(virtvdev, pos, (char __user *)buf, count, false);
-
- return vfio_pci_core_write(core_vdev, buf, count, ppos);
-}
-
-static int
-virtiovf_pci_ioctl_get_region_info(struct vfio_device *core_vdev,
- unsigned int cmd, unsigned long arg)
-{
- struct virtiovf_pci_core_device *virtvdev = container_of(
- core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
- unsigned long minsz = offsetofend(struct vfio_region_info, offset);
- void __user *uarg = (void __user *)arg;
- struct vfio_region_info info = {};
-
- if (copy_from_user(&info, uarg, minsz))
- return -EFAULT;
-
- if (info.argsz < minsz)
- return -EINVAL;
-
- switch (info.index) {
- case VFIO_PCI_BAR0_REGION_INDEX:
- info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
- info.size = virtvdev->bar0_virtual_buf_size;
- info.flags = VFIO_REGION_INFO_FLAG_READ |
- VFIO_REGION_INFO_FLAG_WRITE;
- return copy_to_user(uarg, &info, minsz) ? -EFAULT : 0;
- default:
- return vfio_pci_core_ioctl(core_vdev, cmd, arg);
- }
-}
-
-static long
-virtiovf_vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
- unsigned long arg)
-{
- switch (cmd) {
- case VFIO_DEVICE_GET_REGION_INFO:
- return virtiovf_pci_ioctl_get_region_info(core_vdev, cmd, arg);
- default:
- return vfio_pci_core_ioctl(core_vdev, cmd, arg);
- }
-}
-
-static int
-virtiovf_set_notify_addr(struct virtiovf_pci_core_device *virtvdev)
-{
- struct vfio_pci_core_device *core_device = &virtvdev->core_device;
- int ret;
-
- /*
- * Setup the BAR where the 'notify' exists to be used by vfio as well
- * This will let us mmap it only once and use it when needed.
- */
- ret = vfio_pci_core_setup_barmap(core_device,
- virtvdev->notify_bar);
- if (ret)
- return ret;
-
- virtvdev->notify_addr = core_device->barmap[virtvdev->notify_bar] +
- virtvdev->notify_offset;
- return 0;
-}
+#include "common.h"
static int virtiovf_pci_open_device(struct vfio_device *core_vdev)
{
- struct virtiovf_pci_core_device *virtvdev = container_of(
- core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
+ struct virtiovf_pci_core_device *virtvdev = container_of(core_vdev,
+ struct virtiovf_pci_core_device, core_device.vdev);
struct vfio_pci_core_device *vdev = &virtvdev->core_device;
int ret;
@@ -364,88 +29,84 @@ static int virtiovf_pci_open_device(struct vfio_device *core_vdev)
if (ret)
return ret;
- if (virtvdev->bar0_virtual_buf) {
- /*
- * Upon close_device() the vfio_pci_core_disable() is called
- * and will close all the previous mmaps, so it seems that the
- * valid life cycle for the 'notify' addr is per open/close.
- */
- ret = virtiovf_set_notify_addr(virtvdev);
- if (ret) {
- vfio_pci_core_disable(vdev);
- return ret;
- }
+#ifdef CONFIG_VIRTIO_VFIO_PCI_ADMIN_LEGACY
+ ret = virtiovf_open_legacy_io(virtvdev);
+ if (ret) {
+ vfio_pci_core_disable(vdev);
+ return ret;
}
+#endif
+ virtiovf_open_migration(virtvdev);
vfio_pci_core_finish_enable(vdev);
return 0;
}
-static int virtiovf_get_device_config_size(unsigned short device)
+static void virtiovf_pci_close_device(struct vfio_device *core_vdev)
{
- /* Network card */
- return offsetofend(struct virtio_net_config, status);
-}
-
-static int virtiovf_read_notify_info(struct virtiovf_pci_core_device *virtvdev)
-{
- u64 offset;
- int ret;
- u8 bar;
+ struct virtiovf_pci_core_device *virtvdev = container_of(core_vdev,
+ struct virtiovf_pci_core_device, core_device.vdev);
- ret = virtio_pci_admin_legacy_io_notify_info(virtvdev->core_device.pdev,
- VIRTIO_ADMIN_CMD_NOTIFY_INFO_FLAGS_OWNER_MEM,
- &bar, &offset);
- if (ret)
- return ret;
-
- virtvdev->notify_bar = bar;
- virtvdev->notify_offset = offset;
- return 0;
+ virtiovf_close_migration(virtvdev);
+ vfio_pci_core_close_device(core_vdev);
}
+#ifdef CONFIG_VIRTIO_VFIO_PCI_ADMIN_LEGACY
static int virtiovf_pci_init_device(struct vfio_device *core_vdev)
{
- struct virtiovf_pci_core_device *virtvdev = container_of(
- core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
- struct pci_dev *pdev;
+ struct virtiovf_pci_core_device *virtvdev = container_of(core_vdev,
+ struct virtiovf_pci_core_device, core_device.vdev);
int ret;
ret = vfio_pci_core_init_dev(core_vdev);
if (ret)
return ret;
- pdev = virtvdev->core_device.pdev;
- ret = virtiovf_read_notify_info(virtvdev);
- if (ret)
- return ret;
-
- virtvdev->bar0_virtual_buf_size = VIRTIO_PCI_CONFIG_OFF(true) +
- virtiovf_get_device_config_size(pdev->device);
- BUILD_BUG_ON(!is_power_of_2(virtvdev->bar0_virtual_buf_size));
- virtvdev->bar0_virtual_buf = kzalloc(virtvdev->bar0_virtual_buf_size,
- GFP_KERNEL);
- if (!virtvdev->bar0_virtual_buf)
- return -ENOMEM;
- mutex_init(&virtvdev->bar_mutex);
- return 0;
+ /*
+ * The vfio_device_ops.init() callback is set to virtiovf_pci_init_device()
+ * only when legacy I/O is supported. Now, let's initialize it.
+ */
+ return virtiovf_init_legacy_io(virtvdev);
}
+#endif
static void virtiovf_pci_core_release_dev(struct vfio_device *core_vdev)
{
- struct virtiovf_pci_core_device *virtvdev = container_of(
- core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
+#ifdef CONFIG_VIRTIO_VFIO_PCI_ADMIN_LEGACY
+ struct virtiovf_pci_core_device *virtvdev = container_of(core_vdev,
+ struct virtiovf_pci_core_device, core_device.vdev);
- kfree(virtvdev->bar0_virtual_buf);
+ virtiovf_release_legacy_io(virtvdev);
+#endif
vfio_pci_core_release_dev(core_vdev);
}
-static const struct vfio_device_ops virtiovf_vfio_pci_tran_ops = {
- .name = "virtio-vfio-pci-trans",
+static const struct vfio_device_ops virtiovf_vfio_pci_lm_ops = {
+ .name = "virtio-vfio-pci-lm",
+ .init = vfio_pci_core_init_dev,
+ .release = virtiovf_pci_core_release_dev,
+ .open_device = virtiovf_pci_open_device,
+ .close_device = virtiovf_pci_close_device,
+ .ioctl = vfio_pci_core_ioctl,
+ .device_feature = vfio_pci_core_ioctl_feature,
+ .read = vfio_pci_core_read,
+ .write = vfio_pci_core_write,
+ .mmap = vfio_pci_core_mmap,
+ .request = vfio_pci_core_request,
+ .match = vfio_pci_core_match,
+ .bind_iommufd = vfio_iommufd_physical_bind,
+ .unbind_iommufd = vfio_iommufd_physical_unbind,
+ .attach_ioas = vfio_iommufd_physical_attach_ioas,
+ .detach_ioas = vfio_iommufd_physical_detach_ioas,
+};
+
+#ifdef CONFIG_VIRTIO_VFIO_PCI_ADMIN_LEGACY
+static const struct vfio_device_ops virtiovf_vfio_pci_tran_lm_ops = {
+ .name = "virtio-vfio-pci-trans-lm",
.init = virtiovf_pci_init_device,
.release = virtiovf_pci_core_release_dev,
.open_device = virtiovf_pci_open_device,
- .close_device = vfio_pci_core_close_device,
+ .close_device = virtiovf_pci_close_device,
.ioctl = virtiovf_vfio_pci_core_ioctl,
.device_feature = vfio_pci_core_ioctl_feature,
.read = virtiovf_pci_core_read,
@@ -458,6 +119,7 @@ static const struct vfio_device_ops virtiovf_vfio_pci_tran_ops = {
.attach_ioas = vfio_iommufd_physical_attach_ioas,
.detach_ioas = vfio_iommufd_physical_detach_ioas,
};
+#endif
static const struct vfio_device_ops virtiovf_vfio_pci_ops = {
.name = "virtio-vfio-pci",
@@ -478,29 +140,34 @@ static const struct vfio_device_ops virtiovf_vfio_pci_ops = {
.detach_ioas = vfio_iommufd_physical_detach_ioas,
};
-static bool virtiovf_bar0_exists(struct pci_dev *pdev)
-{
- struct resource *res = pdev->resource;
-
- return res->flags;
-}
-
static int virtiovf_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
const struct vfio_device_ops *ops = &virtiovf_vfio_pci_ops;
struct virtiovf_pci_core_device *virtvdev;
+ bool sup_legacy_io = false;
+ bool sup_lm = false;
int ret;
- if (pdev->is_virtfn && virtio_pci_admin_has_legacy_io(pdev) &&
- !virtiovf_bar0_exists(pdev))
- ops = &virtiovf_vfio_pci_tran_ops;
+ if (pdev->is_virtfn) {
+#ifdef CONFIG_VIRTIO_VFIO_PCI_ADMIN_LEGACY
+ sup_legacy_io = virtiovf_support_legacy_io(pdev);
+ if (sup_legacy_io)
+ ops = &virtiovf_vfio_pci_tran_lm_ops;
+#endif
+ sup_lm = virtio_pci_admin_has_dev_parts(pdev);
+ if (sup_lm && !sup_legacy_io)
+ ops = &virtiovf_vfio_pci_lm_ops;
+ }
virtvdev = vfio_alloc_device(virtiovf_pci_core_device, core_device.vdev,
&pdev->dev, ops);
if (IS_ERR(virtvdev))
return PTR_ERR(virtvdev);
+ if (sup_lm)
+ virtiovf_set_migratable(virtvdev);
+
dev_set_drvdata(&pdev->dev, &virtvdev->core_device);
ret = vfio_pci_core_register_device(&virtvdev->core_device);
if (ret)
@@ -529,9 +196,10 @@ MODULE_DEVICE_TABLE(pci, virtiovf_pci_table);
static void virtiovf_pci_aer_reset_done(struct pci_dev *pdev)
{
- struct virtiovf_pci_core_device *virtvdev = dev_get_drvdata(&pdev->dev);
-
- virtvdev->pci_cmd = 0;
+#ifdef CONFIG_VIRTIO_VFIO_PCI_ADMIN_LEGACY
+ virtiovf_legacy_io_reset_done(pdev);
+#endif
+ virtiovf_migration_reset_done(pdev);
}
static const struct pci_error_handlers virtiovf_err_handlers = {
diff --git a/drivers/vfio/pci/virtio/migrate.c b/drivers/vfio/pci/virtio/migrate.c
new file mode 100644
index 000000000000..ee54f4c17857
--- /dev/null
+++ b/drivers/vfio/pci/virtio/migrate.c
@@ -0,0 +1,1337 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/vfio.h>
+#include <linux/vfio_pci_core.h>
+#include <linux/virtio_pci.h>
+#include <linux/virtio_net.h>
+#include <linux/virtio_pci_admin.h>
+#include <linux/anon_inodes.h>
+
+#include "common.h"
+
+/* Device specification max parts size */
+#define MAX_LOAD_SIZE (BIT_ULL(BITS_PER_TYPE \
+ (((struct virtio_admin_cmd_dev_parts_metadata_result *)0)->parts_size.size)) - 1)
+
+/* Initial target buffer size */
+#define VIRTIOVF_TARGET_INITIAL_BUF_SIZE SZ_1M
+
+static int
+virtiovf_read_device_context_chunk(struct virtiovf_migration_file *migf,
+ u32 ctx_size);
+
+static struct page *
+virtiovf_get_migration_page(struct virtiovf_data_buffer *buf,
+ unsigned long offset)
+{
+ unsigned long cur_offset = 0;
+ struct scatterlist *sg;
+ unsigned int i;
+
+ /* All accesses are sequential */
+ if (offset < buf->last_offset || !buf->last_offset_sg) {
+ buf->last_offset = 0;
+ buf->last_offset_sg = buf->table.sgt.sgl;
+ buf->sg_last_entry = 0;
+ }
+
+ cur_offset = buf->last_offset;
+
+ for_each_sg(buf->last_offset_sg, sg,
+ buf->table.sgt.orig_nents - buf->sg_last_entry, i) {
+ if (offset < sg->length + cur_offset) {
+ buf->last_offset_sg = sg;
+ buf->sg_last_entry += i;
+ buf->last_offset = cur_offset;
+ return nth_page(sg_page(sg),
+ (offset - cur_offset) / PAGE_SIZE);
+ }
+ cur_offset += sg->length;
+ }
+ return NULL;
+}
+
+static int virtiovf_add_migration_pages(struct virtiovf_data_buffer *buf,
+ unsigned int npages)
+{
+ unsigned int to_alloc = npages;
+ struct page **page_list;
+ unsigned long filled;
+ unsigned int to_fill;
+ int ret;
+ int i;
+
+ to_fill = min_t(unsigned int, npages, PAGE_SIZE / sizeof(*page_list));
+ page_list = kvcalloc(to_fill, sizeof(*page_list), GFP_KERNEL_ACCOUNT);
+ if (!page_list)
+ return -ENOMEM;
+
+ do {
+ filled = alloc_pages_bulk_array(GFP_KERNEL_ACCOUNT, to_fill,
+ page_list);
+ if (!filled) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ to_alloc -= filled;
+ ret = sg_alloc_append_table_from_pages(&buf->table, page_list,
+ filled, 0, filled << PAGE_SHIFT, UINT_MAX,
+ SG_MAX_SINGLE_ALLOC, GFP_KERNEL_ACCOUNT);
+
+ if (ret)
+ goto err_append;
+ buf->allocated_length += filled * PAGE_SIZE;
+ /* clean input for another bulk allocation */
+ memset(page_list, 0, filled * sizeof(*page_list));
+ to_fill = min_t(unsigned int, to_alloc,
+ PAGE_SIZE / sizeof(*page_list));
+ } while (to_alloc > 0);
+
+ kvfree(page_list);
+ return 0;
+
+err_append:
+ for (i = filled - 1; i >= 0; i--)
+ __free_page(page_list[i]);
+err:
+ kvfree(page_list);
+ return ret;
+}
+
+static void virtiovf_free_data_buffer(struct virtiovf_data_buffer *buf)
+{
+ struct sg_page_iter sg_iter;
+
+ /* Undo alloc_pages_bulk_array() */
+ for_each_sgtable_page(&buf->table.sgt, &sg_iter, 0)
+ __free_page(sg_page_iter_page(&sg_iter));
+ sg_free_append_table(&buf->table);
+ kfree(buf);
+}
+
+static struct virtiovf_data_buffer *
+virtiovf_alloc_data_buffer(struct virtiovf_migration_file *migf, size_t length)
+{
+ struct virtiovf_data_buffer *buf;
+ int ret;
+
+ buf = kzalloc(sizeof(*buf), GFP_KERNEL_ACCOUNT);
+ if (!buf)
+ return ERR_PTR(-ENOMEM);
+
+ ret = virtiovf_add_migration_pages(buf,
+ DIV_ROUND_UP_ULL(length, PAGE_SIZE));
+ if (ret)
+ goto end;
+
+ buf->migf = migf;
+ return buf;
+end:
+ virtiovf_free_data_buffer(buf);
+ return ERR_PTR(ret);
+}
+
+static void virtiovf_put_data_buffer(struct virtiovf_data_buffer *buf)
+{
+ spin_lock_irq(&buf->migf->list_lock);
+ list_add_tail(&buf->buf_elm, &buf->migf->avail_list);
+ spin_unlock_irq(&buf->migf->list_lock);
+}
+
+static int
+virtiovf_pci_alloc_obj_id(struct virtiovf_pci_core_device *virtvdev, u8 type,
+ u32 *obj_id)
+{
+ return virtio_pci_admin_obj_create(virtvdev->core_device.pdev,
+ VIRTIO_RESOURCE_OBJ_DEV_PARTS, type, obj_id);
+}
+
+static void
+virtiovf_pci_free_obj_id(struct virtiovf_pci_core_device *virtvdev, u32 obj_id)
+{
+ virtio_pci_admin_obj_destroy(virtvdev->core_device.pdev,
+ VIRTIO_RESOURCE_OBJ_DEV_PARTS, obj_id);
+}
+
+static struct virtiovf_data_buffer *
+virtiovf_get_data_buffer(struct virtiovf_migration_file *migf, size_t length)
+{
+ struct virtiovf_data_buffer *buf, *temp_buf;
+ struct list_head free_list;
+
+ INIT_LIST_HEAD(&free_list);
+
+ spin_lock_irq(&migf->list_lock);
+ list_for_each_entry_safe(buf, temp_buf, &migf->avail_list, buf_elm) {
+ list_del_init(&buf->buf_elm);
+ if (buf->allocated_length >= length) {
+ spin_unlock_irq(&migf->list_lock);
+ goto found;
+ }
+ /*
+ * Prevent holding redundant buffers. Put in a free
+ * list and call at the end not under the spin lock
+ * (&migf->list_lock) to minimize its scope usage.
+ */
+ list_add(&buf->buf_elm, &free_list);
+ }
+ spin_unlock_irq(&migf->list_lock);
+ buf = virtiovf_alloc_data_buffer(migf, length);
+
+found:
+ while ((temp_buf = list_first_entry_or_null(&free_list,
+ struct virtiovf_data_buffer, buf_elm))) {
+ list_del(&temp_buf->buf_elm);
+ virtiovf_free_data_buffer(temp_buf);
+ }
+
+ return buf;
+}
+
+static void virtiovf_clean_migf_resources(struct virtiovf_migration_file *migf)
+{
+ struct virtiovf_data_buffer *entry;
+
+ if (migf->buf) {
+ virtiovf_free_data_buffer(migf->buf);
+ migf->buf = NULL;
+ }
+
+ if (migf->buf_header) {
+ virtiovf_free_data_buffer(migf->buf_header);
+ migf->buf_header = NULL;
+ }
+
+ list_splice(&migf->avail_list, &migf->buf_list);
+
+ while ((entry = list_first_entry_or_null(&migf->buf_list,
+ struct virtiovf_data_buffer, buf_elm))) {
+ list_del(&entry->buf_elm);
+ virtiovf_free_data_buffer(entry);
+ }
+
+ if (migf->has_obj_id)
+ virtiovf_pci_free_obj_id(migf->virtvdev, migf->obj_id);
+}
+
+static void virtiovf_disable_fd(struct virtiovf_migration_file *migf)
+{
+ mutex_lock(&migf->lock);
+ migf->state = VIRTIOVF_MIGF_STATE_ERROR;
+ migf->filp->f_pos = 0;
+ mutex_unlock(&migf->lock);
+}
+
+static void virtiovf_disable_fds(struct virtiovf_pci_core_device *virtvdev)
+{
+ if (virtvdev->resuming_migf) {
+ virtiovf_disable_fd(virtvdev->resuming_migf);
+ virtiovf_clean_migf_resources(virtvdev->resuming_migf);
+ fput(virtvdev->resuming_migf->filp);
+ virtvdev->resuming_migf = NULL;
+ }
+ if (virtvdev->saving_migf) {
+ virtiovf_disable_fd(virtvdev->saving_migf);
+ virtiovf_clean_migf_resources(virtvdev->saving_migf);
+ fput(virtvdev->saving_migf->filp);
+ virtvdev->saving_migf = NULL;
+ }
+}
+
+/*
+ * This function is called in all state_mutex unlock cases to
+ * handle a 'deferred_reset' if exists.
+ */
+static void virtiovf_state_mutex_unlock(struct virtiovf_pci_core_device *virtvdev)
+{
+again:
+ spin_lock(&virtvdev->reset_lock);
+ if (virtvdev->deferred_reset) {
+ virtvdev->deferred_reset = false;
+ spin_unlock(&virtvdev->reset_lock);
+ virtvdev->mig_state = VFIO_DEVICE_STATE_RUNNING;
+ virtiovf_disable_fds(virtvdev);
+ goto again;
+ }
+ mutex_unlock(&virtvdev->state_mutex);
+ spin_unlock(&virtvdev->reset_lock);
+}
+
+void virtiovf_migration_reset_done(struct pci_dev *pdev)
+{
+ struct virtiovf_pci_core_device *virtvdev = dev_get_drvdata(&pdev->dev);
+
+ if (!virtvdev->migrate_cap)
+ return;
+
+ /*
+ * As the higher VFIO layers are holding locks across reset and using
+ * those same locks with the mm_lock we need to prevent ABBA deadlock
+ * with the state_mutex and mm_lock.
+ * In case the state_mutex was taken already we defer the cleanup work
+ * to the unlock flow of the other running context.
+ */
+ spin_lock(&virtvdev->reset_lock);
+ virtvdev->deferred_reset = true;
+ if (!mutex_trylock(&virtvdev->state_mutex)) {
+ spin_unlock(&virtvdev->reset_lock);
+ return;
+ }
+ spin_unlock(&virtvdev->reset_lock);
+ virtiovf_state_mutex_unlock(virtvdev);
+}
+
+static int virtiovf_release_file(struct inode *inode, struct file *filp)
+{
+ struct virtiovf_migration_file *migf = filp->private_data;
+
+ virtiovf_disable_fd(migf);
+ mutex_destroy(&migf->lock);
+ kfree(migf);
+ return 0;
+}
+
+static struct virtiovf_data_buffer *
+virtiovf_get_data_buff_from_pos(struct virtiovf_migration_file *migf,
+ loff_t pos, bool *end_of_data)
+{
+ struct virtiovf_data_buffer *buf;
+ bool found = false;
+
+ *end_of_data = false;
+ spin_lock_irq(&migf->list_lock);
+ if (list_empty(&migf->buf_list)) {
+ *end_of_data = true;
+ goto end;
+ }
+
+ buf = list_first_entry(&migf->buf_list, struct virtiovf_data_buffer,
+ buf_elm);
+ if (pos >= buf->start_pos &&
+ pos < buf->start_pos + buf->length) {
+ found = true;
+ goto end;
+ }
+
+ /*
+ * As we use a stream based FD we may expect having the data always
+ * on first chunk
+ */
+ migf->state = VIRTIOVF_MIGF_STATE_ERROR;
+
+end:
+ spin_unlock_irq(&migf->list_lock);
+ return found ? buf : NULL;
+}
+
+static ssize_t virtiovf_buf_read(struct virtiovf_data_buffer *vhca_buf,
+ char __user **buf, size_t *len, loff_t *pos)
+{
+ unsigned long offset;
+ ssize_t done = 0;
+ size_t copy_len;
+
+ copy_len = min_t(size_t,
+ vhca_buf->start_pos + vhca_buf->length - *pos, *len);
+ while (copy_len) {
+ size_t page_offset;
+ struct page *page;
+ size_t page_len;
+ u8 *from_buff;
+ int ret;
+
+ offset = *pos - vhca_buf->start_pos;
+ page_offset = offset % PAGE_SIZE;
+ offset -= page_offset;
+ page = virtiovf_get_migration_page(vhca_buf, offset);
+ if (!page)
+ return -EINVAL;
+ page_len = min_t(size_t, copy_len, PAGE_SIZE - page_offset);
+ from_buff = kmap_local_page(page);
+ ret = copy_to_user(*buf, from_buff + page_offset, page_len);
+ kunmap_local(from_buff);
+ if (ret)
+ return -EFAULT;
+ *pos += page_len;
+ *len -= page_len;
+ *buf += page_len;
+ done += page_len;
+ copy_len -= page_len;
+ }
+
+ if (*pos >= vhca_buf->start_pos + vhca_buf->length) {
+ spin_lock_irq(&vhca_buf->migf->list_lock);
+ list_del_init(&vhca_buf->buf_elm);
+ list_add_tail(&vhca_buf->buf_elm, &vhca_buf->migf->avail_list);
+ spin_unlock_irq(&vhca_buf->migf->list_lock);
+ }
+
+ return done;
+}
+
+static ssize_t virtiovf_save_read(struct file *filp, char __user *buf, size_t len,
+ loff_t *pos)
+{
+ struct virtiovf_migration_file *migf = filp->private_data;
+ struct virtiovf_data_buffer *vhca_buf;
+ bool first_loop_call = true;
+ bool end_of_data;
+ ssize_t done = 0;
+
+ if (pos)
+ return -ESPIPE;
+ pos = &filp->f_pos;
+
+ mutex_lock(&migf->lock);
+ if (migf->state == VIRTIOVF_MIGF_STATE_ERROR) {
+ done = -ENODEV;
+ goto out_unlock;
+ }
+
+ while (len) {
+ ssize_t count;
+
+ vhca_buf = virtiovf_get_data_buff_from_pos(migf, *pos, &end_of_data);
+ if (first_loop_call) {
+ first_loop_call = false;
+ /* Temporary end of file as part of PRE_COPY */
+ if (end_of_data && migf->state == VIRTIOVF_MIGF_STATE_PRECOPY) {
+ done = -ENOMSG;
+ goto out_unlock;
+ }
+ if (end_of_data && migf->state != VIRTIOVF_MIGF_STATE_COMPLETE) {
+ done = -EINVAL;
+ goto out_unlock;
+ }
+ }
+
+ if (end_of_data)
+ goto out_unlock;
+
+ if (!vhca_buf) {
+ done = -EINVAL;
+ goto out_unlock;
+ }
+
+ count = virtiovf_buf_read(vhca_buf, &buf, &len, pos);
+ if (count < 0) {
+ done = count;
+ goto out_unlock;
+ }
+ done += count;
+ }
+
+out_unlock:
+ mutex_unlock(&migf->lock);
+ return done;
+}
+
+static long virtiovf_precopy_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct virtiovf_migration_file *migf = filp->private_data;
+ struct virtiovf_pci_core_device *virtvdev = migf->virtvdev;
+ struct vfio_precopy_info info = {};
+ loff_t *pos = &filp->f_pos;
+ bool end_of_data = false;
+ unsigned long minsz;
+ u32 ctx_size = 0;
+ int ret;
+
+ if (cmd != VFIO_MIG_GET_PRECOPY_INFO)
+ return -ENOTTY;
+
+ minsz = offsetofend(struct vfio_precopy_info, dirty_bytes);
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ mutex_lock(&virtvdev->state_mutex);
+ if (virtvdev->mig_state != VFIO_DEVICE_STATE_PRE_COPY &&
+ virtvdev->mig_state != VFIO_DEVICE_STATE_PRE_COPY_P2P) {
+ ret = -EINVAL;
+ goto err_state_unlock;
+ }
+
+ /*
+ * The virtio specification does not include a PRE_COPY concept.
+ * Since we can expect the data to remain the same for a certain period,
+ * we use a rate limiter mechanism before making a call to the device.
+ */
+ if (__ratelimit(&migf->pre_copy_rl_state)) {
+
+ ret = virtio_pci_admin_dev_parts_metadata_get(virtvdev->core_device.pdev,
+ VIRTIO_RESOURCE_OBJ_DEV_PARTS, migf->obj_id,
+ VIRTIO_ADMIN_CMD_DEV_PARTS_METADATA_TYPE_SIZE,
+ &ctx_size);
+ if (ret)
+ goto err_state_unlock;
+ }
+
+ mutex_lock(&migf->lock);
+ if (migf->state == VIRTIOVF_MIGF_STATE_ERROR) {
+ ret = -ENODEV;
+ goto err_migf_unlock;
+ }
+
+ if (migf->pre_copy_initial_bytes > *pos) {
+ info.initial_bytes = migf->pre_copy_initial_bytes - *pos;
+ } else {
+ info.dirty_bytes = migf->max_pos - *pos;
+ if (!info.dirty_bytes)
+ end_of_data = true;
+ info.dirty_bytes += ctx_size;
+ }
+
+ if (!end_of_data || !ctx_size) {
+ mutex_unlock(&migf->lock);
+ goto done;
+ }
+
+ mutex_unlock(&migf->lock);
+ /*
+ * We finished transferring the current state and the device has a
+ * dirty state, read a new state.
+ */
+ ret = virtiovf_read_device_context_chunk(migf, ctx_size);
+ if (ret)
+ /*
+ * The machine is running, and context size could be grow, so no reason to mark
+ * the device state as VIRTIOVF_MIGF_STATE_ERROR.
+ */
+ goto err_state_unlock;
+
+done:
+ virtiovf_state_mutex_unlock(virtvdev);
+ if (copy_to_user((void __user *)arg, &info, minsz))
+ return -EFAULT;
+ return 0;
+
+err_migf_unlock:
+ mutex_unlock(&migf->lock);
+err_state_unlock:
+ virtiovf_state_mutex_unlock(virtvdev);
+ return ret;
+}
+
+static const struct file_operations virtiovf_save_fops = {
+ .owner = THIS_MODULE,
+ .read = virtiovf_save_read,
+ .unlocked_ioctl = virtiovf_precopy_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
+ .release = virtiovf_release_file,
+};
+
+static int
+virtiovf_add_buf_header(struct virtiovf_data_buffer *header_buf,
+ u32 data_size)
+{
+ struct virtiovf_migration_file *migf = header_buf->migf;
+ struct virtiovf_migration_header header = {};
+ struct page *page;
+ u8 *to_buff;
+
+ header.record_size = cpu_to_le64(data_size);
+ header.flags = cpu_to_le32(VIRTIOVF_MIGF_HEADER_FLAGS_TAG_MANDATORY);
+ header.tag = cpu_to_le32(VIRTIOVF_MIGF_HEADER_TAG_DEVICE_DATA);
+ page = virtiovf_get_migration_page(header_buf, 0);
+ if (!page)
+ return -EINVAL;
+ to_buff = kmap_local_page(page);
+ memcpy(to_buff, &header, sizeof(header));
+ kunmap_local(to_buff);
+ header_buf->length = sizeof(header);
+ header_buf->start_pos = header_buf->migf->max_pos;
+ migf->max_pos += header_buf->length;
+ spin_lock_irq(&migf->list_lock);
+ list_add_tail(&header_buf->buf_elm, &migf->buf_list);
+ spin_unlock_irq(&migf->list_lock);
+ return 0;
+}
+
+static int
+virtiovf_read_device_context_chunk(struct virtiovf_migration_file *migf,
+ u32 ctx_size)
+{
+ struct virtiovf_data_buffer *header_buf;
+ struct virtiovf_data_buffer *buf;
+ bool unmark_end = false;
+ struct scatterlist *sg;
+ unsigned int i;
+ u32 res_size;
+ int nent;
+ int ret;
+
+ buf = virtiovf_get_data_buffer(migf, ctx_size);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
+ /* Find the total count of SG entries which satisfies the size */
+ nent = sg_nents_for_len(buf->table.sgt.sgl, ctx_size);
+ if (nent <= 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * Iterate to that SG entry and mark it as last (if it's not already)
+ * to let underlay layers iterate only till that entry.
+ */
+ for_each_sg(buf->table.sgt.sgl, sg, nent - 1, i)
+ ;
+
+ if (!sg_is_last(sg)) {
+ unmark_end = true;
+ sg_mark_end(sg);
+ }
+
+ ret = virtio_pci_admin_dev_parts_get(migf->virtvdev->core_device.pdev,
+ VIRTIO_RESOURCE_OBJ_DEV_PARTS,
+ migf->obj_id,
+ VIRTIO_ADMIN_CMD_DEV_PARTS_GET_TYPE_ALL,
+ buf->table.sgt.sgl, &res_size);
+ /* Restore the original SG mark end */
+ if (unmark_end)
+ sg_unmark_end(sg);
+ if (ret)
+ goto out;
+
+ buf->length = res_size;
+ header_buf = virtiovf_get_data_buffer(migf,
+ sizeof(struct virtiovf_migration_header));
+ if (IS_ERR(header_buf)) {
+ ret = PTR_ERR(header_buf);
+ goto out;
+ }
+
+ ret = virtiovf_add_buf_header(header_buf, res_size);
+ if (ret)
+ goto out_header;
+
+ buf->start_pos = buf->migf->max_pos;
+ migf->max_pos += buf->length;
+ spin_lock(&migf->list_lock);
+ list_add_tail(&buf->buf_elm, &migf->buf_list);
+ spin_unlock_irq(&migf->list_lock);
+ return 0;
+
+out_header:
+ virtiovf_put_data_buffer(header_buf);
+out:
+ virtiovf_put_data_buffer(buf);
+ return ret;
+}
+
+static int
+virtiovf_pci_save_device_final_data(struct virtiovf_pci_core_device *virtvdev)
+{
+ struct virtiovf_migration_file *migf = virtvdev->saving_migf;
+ u32 ctx_size;
+ int ret;
+
+ if (migf->state == VIRTIOVF_MIGF_STATE_ERROR)
+ return -ENODEV;
+
+ ret = virtio_pci_admin_dev_parts_metadata_get(virtvdev->core_device.pdev,
+ VIRTIO_RESOURCE_OBJ_DEV_PARTS, migf->obj_id,
+ VIRTIO_ADMIN_CMD_DEV_PARTS_METADATA_TYPE_SIZE,
+ &ctx_size);
+ if (ret)
+ goto err;
+
+ if (!ctx_size) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = virtiovf_read_device_context_chunk(migf, ctx_size);
+ if (ret)
+ goto err;
+
+ migf->state = VIRTIOVF_MIGF_STATE_COMPLETE;
+ return 0;
+
+err:
+ migf->state = VIRTIOVF_MIGF_STATE_ERROR;
+ return ret;
+}
+
+static struct virtiovf_migration_file *
+virtiovf_pci_save_device_data(struct virtiovf_pci_core_device *virtvdev,
+ bool pre_copy)
+{
+ struct virtiovf_migration_file *migf;
+ u32 ctx_size;
+ u32 obj_id;
+ int ret;
+
+ migf = kzalloc(sizeof(*migf), GFP_KERNEL_ACCOUNT);
+ if (!migf)
+ return ERR_PTR(-ENOMEM);
+
+ migf->filp = anon_inode_getfile("virtiovf_mig", &virtiovf_save_fops, migf,
+ O_RDONLY);
+ if (IS_ERR(migf->filp)) {
+ ret = PTR_ERR(migf->filp);
+ kfree(migf);
+ return ERR_PTR(ret);
+ }
+
+ stream_open(migf->filp->f_inode, migf->filp);
+ mutex_init(&migf->lock);
+ INIT_LIST_HEAD(&migf->buf_list);
+ INIT_LIST_HEAD(&migf->avail_list);
+ spin_lock_init(&migf->list_lock);
+ migf->virtvdev = virtvdev;
+
+ lockdep_assert_held(&virtvdev->state_mutex);
+ ret = virtiovf_pci_alloc_obj_id(virtvdev, VIRTIO_RESOURCE_OBJ_DEV_PARTS_TYPE_GET,
+ &obj_id);
+ if (ret)
+ goto out;
+
+ migf->obj_id = obj_id;
+ /* Mark as having a valid obj id which can be even 0 */
+ migf->has_obj_id = true;
+ ret = virtio_pci_admin_dev_parts_metadata_get(virtvdev->core_device.pdev,
+ VIRTIO_RESOURCE_OBJ_DEV_PARTS, obj_id,
+ VIRTIO_ADMIN_CMD_DEV_PARTS_METADATA_TYPE_SIZE,
+ &ctx_size);
+ if (ret)
+ goto out_clean;
+
+ if (!ctx_size) {
+ ret = -EINVAL;
+ goto out_clean;
+ }
+
+ ret = virtiovf_read_device_context_chunk(migf, ctx_size);
+ if (ret)
+ goto out_clean;
+
+ if (pre_copy) {
+ migf->pre_copy_initial_bytes = migf->max_pos;
+ /* Arbitrarily set the pre-copy rate limit to 1-second intervals */
+ ratelimit_state_init(&migf->pre_copy_rl_state, 1 * HZ, 1);
+ /* Prevent any rate messages upon its usage */
+ ratelimit_set_flags(&migf->pre_copy_rl_state,
+ RATELIMIT_MSG_ON_RELEASE);
+ migf->state = VIRTIOVF_MIGF_STATE_PRECOPY;
+ } else {
+ migf->state = VIRTIOVF_MIGF_STATE_COMPLETE;
+ }
+
+ return migf;
+
+out_clean:
+ virtiovf_clean_migf_resources(migf);
+out:
+ fput(migf->filp);
+ return ERR_PTR(ret);
+}
+
+/*
+ * Set the required object header at the beginning of the buffer.
+ * The actual device parts data will be written post of the header offset.
+ */
+static int virtiovf_set_obj_cmd_header(struct virtiovf_data_buffer *vhca_buf)
+{
+ struct virtio_admin_cmd_resource_obj_cmd_hdr obj_hdr = {};
+ struct page *page;
+ u8 *to_buff;
+
+ obj_hdr.type = cpu_to_le16(VIRTIO_RESOURCE_OBJ_DEV_PARTS);
+ obj_hdr.id = cpu_to_le32(vhca_buf->migf->obj_id);
+ page = virtiovf_get_migration_page(vhca_buf, 0);
+ if (!page)
+ return -EINVAL;
+ to_buff = kmap_local_page(page);
+ memcpy(to_buff, &obj_hdr, sizeof(obj_hdr));
+ kunmap_local(to_buff);
+
+ /* Mark the buffer as including the header object data */
+ vhca_buf->include_header_object = 1;
+ return 0;
+}
+
+static int
+virtiovf_append_page_to_mig_buf(struct virtiovf_data_buffer *vhca_buf,
+ const char __user **buf, size_t *len,
+ loff_t *pos, ssize_t *done)
+{
+ unsigned long offset;
+ size_t page_offset;
+ struct page *page;
+ size_t page_len;
+ u8 *to_buff;
+ int ret;
+
+ offset = *pos - vhca_buf->start_pos;
+
+ if (vhca_buf->include_header_object)
+ /* The buffer holds the object header, update the offset accordingly */
+ offset += sizeof(struct virtio_admin_cmd_resource_obj_cmd_hdr);
+
+ page_offset = offset % PAGE_SIZE;
+
+ page = virtiovf_get_migration_page(vhca_buf, offset - page_offset);
+ if (!page)
+ return -EINVAL;
+
+ page_len = min_t(size_t, *len, PAGE_SIZE - page_offset);
+ to_buff = kmap_local_page(page);
+ ret = copy_from_user(to_buff + page_offset, *buf, page_len);
+ kunmap_local(to_buff);
+ if (ret)
+ return -EFAULT;
+
+ *pos += page_len;
+ *done += page_len;
+ *buf += page_len;
+ *len -= page_len;
+ vhca_buf->length += page_len;
+ return 0;
+}
+
+static ssize_t
+virtiovf_resume_read_chunk(struct virtiovf_migration_file *migf,
+ struct virtiovf_data_buffer *vhca_buf,
+ size_t chunk_size, const char __user **buf,
+ size_t *len, loff_t *pos, ssize_t *done,
+ bool *has_work)
+{
+ size_t copy_len, to_copy;
+ int ret;
+
+ to_copy = min_t(size_t, *len, chunk_size - vhca_buf->length);
+ copy_len = to_copy;
+ while (to_copy) {
+ ret = virtiovf_append_page_to_mig_buf(vhca_buf, buf, &to_copy,
+ pos, done);
+ if (ret)
+ return ret;
+ }
+
+ *len -= copy_len;
+ if (vhca_buf->length == chunk_size) {
+ migf->load_state = VIRTIOVF_LOAD_STATE_LOAD_CHUNK;
+ migf->max_pos += chunk_size;
+ *has_work = true;
+ }
+
+ return 0;
+}
+
+static int
+virtiovf_resume_read_header_data(struct virtiovf_migration_file *migf,
+ struct virtiovf_data_buffer *vhca_buf,
+ const char __user **buf, size_t *len,
+ loff_t *pos, ssize_t *done)
+{
+ size_t copy_len, to_copy;
+ size_t required_data;
+ int ret;
+
+ required_data = migf->record_size - vhca_buf->length;
+ to_copy = min_t(size_t, *len, required_data);
+ copy_len = to_copy;
+ while (to_copy) {
+ ret = virtiovf_append_page_to_mig_buf(vhca_buf, buf, &to_copy,
+ pos, done);
+ if (ret)
+ return ret;
+ }
+
+ *len -= copy_len;
+ if (vhca_buf->length == migf->record_size) {
+ switch (migf->record_tag) {
+ default:
+ /* Optional tag */
+ break;
+ }
+
+ migf->load_state = VIRTIOVF_LOAD_STATE_READ_HEADER;
+ migf->max_pos += migf->record_size;
+ vhca_buf->length = 0;
+ }
+
+ return 0;
+}
+
+static int
+virtiovf_resume_read_header(struct virtiovf_migration_file *migf,
+ struct virtiovf_data_buffer *vhca_buf,
+ const char __user **buf,
+ size_t *len, loff_t *pos,
+ ssize_t *done, bool *has_work)
+{
+ struct page *page;
+ size_t copy_len;
+ u8 *to_buff;
+ int ret;
+
+ copy_len = min_t(size_t, *len,
+ sizeof(struct virtiovf_migration_header) - vhca_buf->length);
+ page = virtiovf_get_migration_page(vhca_buf, 0);
+ if (!page)
+ return -EINVAL;
+ to_buff = kmap_local_page(page);
+ ret = copy_from_user(to_buff + vhca_buf->length, *buf, copy_len);
+ if (ret) {
+ ret = -EFAULT;
+ goto end;
+ }
+
+ *buf += copy_len;
+ *pos += copy_len;
+ *done += copy_len;
+ *len -= copy_len;
+ vhca_buf->length += copy_len;
+ if (vhca_buf->length == sizeof(struct virtiovf_migration_header)) {
+ u64 record_size;
+ u32 flags;
+
+ record_size = le64_to_cpup((__le64 *)to_buff);
+ if (record_size > MAX_LOAD_SIZE) {
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ migf->record_size = record_size;
+ flags = le32_to_cpup((__le32 *)(to_buff +
+ offsetof(struct virtiovf_migration_header, flags)));
+ migf->record_tag = le32_to_cpup((__le32 *)(to_buff +
+ offsetof(struct virtiovf_migration_header, tag)));
+ switch (migf->record_tag) {
+ case VIRTIOVF_MIGF_HEADER_TAG_DEVICE_DATA:
+ migf->load_state = VIRTIOVF_LOAD_STATE_PREP_CHUNK;
+ break;
+ default:
+ if (!(flags & VIRTIOVF_MIGF_HEADER_FLAGS_TAG_OPTIONAL)) {
+ ret = -EOPNOTSUPP;
+ goto end;
+ }
+ /* We may read and skip this optional record data */
+ migf->load_state = VIRTIOVF_LOAD_STATE_PREP_HEADER_DATA;
+ }
+
+ migf->max_pos += vhca_buf->length;
+ vhca_buf->length = 0;
+ *has_work = true;
+ }
+end:
+ kunmap_local(to_buff);
+ return ret;
+}
+
+static ssize_t virtiovf_resume_write(struct file *filp, const char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct virtiovf_migration_file *migf = filp->private_data;
+ struct virtiovf_data_buffer *vhca_buf = migf->buf;
+ struct virtiovf_data_buffer *vhca_buf_header = migf->buf_header;
+ unsigned int orig_length;
+ bool has_work = false;
+ ssize_t done = 0;
+ int ret = 0;
+
+ if (pos)
+ return -ESPIPE;
+
+ pos = &filp->f_pos;
+ if (*pos < vhca_buf->start_pos)
+ return -EINVAL;
+
+ mutex_lock(&migf->virtvdev->state_mutex);
+ mutex_lock(&migf->lock);
+ if (migf->state == VIRTIOVF_MIGF_STATE_ERROR) {
+ done = -ENODEV;
+ goto out_unlock;
+ }
+
+ while (len || has_work) {
+ has_work = false;
+ switch (migf->load_state) {
+ case VIRTIOVF_LOAD_STATE_READ_HEADER:
+ ret = virtiovf_resume_read_header(migf, vhca_buf_header, &buf,
+ &len, pos, &done, &has_work);
+ if (ret)
+ goto out_unlock;
+ break;
+ case VIRTIOVF_LOAD_STATE_PREP_HEADER_DATA:
+ if (vhca_buf_header->allocated_length < migf->record_size) {
+ virtiovf_free_data_buffer(vhca_buf_header);
+
+ migf->buf_header = virtiovf_alloc_data_buffer(migf,
+ migf->record_size);
+ if (IS_ERR(migf->buf_header)) {
+ ret = PTR_ERR(migf->buf_header);
+ migf->buf_header = NULL;
+ goto out_unlock;
+ }
+
+ vhca_buf_header = migf->buf_header;
+ }
+
+ vhca_buf_header->start_pos = migf->max_pos;
+ migf->load_state = VIRTIOVF_LOAD_STATE_READ_HEADER_DATA;
+ break;
+ case VIRTIOVF_LOAD_STATE_READ_HEADER_DATA:
+ ret = virtiovf_resume_read_header_data(migf, vhca_buf_header,
+ &buf, &len, pos, &done);
+ if (ret)
+ goto out_unlock;
+ break;
+ case VIRTIOVF_LOAD_STATE_PREP_CHUNK:
+ {
+ u32 cmd_size = migf->record_size +
+ sizeof(struct virtio_admin_cmd_resource_obj_cmd_hdr);
+
+ /*
+ * The DMA map/unmap is managed in virtio layer, we just need to extend
+ * the SG pages to hold the extra required chunk data.
+ */
+ if (vhca_buf->allocated_length < cmd_size) {
+ ret = virtiovf_add_migration_pages(vhca_buf,
+ DIV_ROUND_UP_ULL(cmd_size - vhca_buf->allocated_length,
+ PAGE_SIZE));
+ if (ret)
+ goto out_unlock;
+ }
+
+ vhca_buf->start_pos = migf->max_pos;
+ migf->load_state = VIRTIOVF_LOAD_STATE_READ_CHUNK;
+ break;
+ }
+ case VIRTIOVF_LOAD_STATE_READ_CHUNK:
+ ret = virtiovf_resume_read_chunk(migf, vhca_buf, migf->record_size,
+ &buf, &len, pos, &done, &has_work);
+ if (ret)
+ goto out_unlock;
+ break;
+ case VIRTIOVF_LOAD_STATE_LOAD_CHUNK:
+ /* Mark the last SG entry and set its length */
+ sg_mark_end(vhca_buf->last_offset_sg);
+ orig_length = vhca_buf->last_offset_sg->length;
+ /* Length should include the resource object command header */
+ vhca_buf->last_offset_sg->length = vhca_buf->length +
+ sizeof(struct virtio_admin_cmd_resource_obj_cmd_hdr) -
+ vhca_buf->last_offset;
+ ret = virtio_pci_admin_dev_parts_set(migf->virtvdev->core_device.pdev,
+ vhca_buf->table.sgt.sgl);
+ /* Restore the original SG data */
+ vhca_buf->last_offset_sg->length = orig_length;
+ sg_unmark_end(vhca_buf->last_offset_sg);
+ if (ret)
+ goto out_unlock;
+ migf->load_state = VIRTIOVF_LOAD_STATE_READ_HEADER;
+ /* be ready for reading the next chunk */
+ vhca_buf->length = 0;
+ break;
+ default:
+ break;
+ }
+ }
+
+out_unlock:
+ if (ret)
+ migf->state = VIRTIOVF_MIGF_STATE_ERROR;
+ mutex_unlock(&migf->lock);
+ virtiovf_state_mutex_unlock(migf->virtvdev);
+ return ret ? ret : done;
+}
+
+static const struct file_operations virtiovf_resume_fops = {
+ .owner = THIS_MODULE,
+ .write = virtiovf_resume_write,
+ .release = virtiovf_release_file,
+};
+
+static struct virtiovf_migration_file *
+virtiovf_pci_resume_device_data(struct virtiovf_pci_core_device *virtvdev)
+{
+ struct virtiovf_migration_file *migf;
+ struct virtiovf_data_buffer *buf;
+ u32 obj_id;
+ int ret;
+
+ migf = kzalloc(sizeof(*migf), GFP_KERNEL_ACCOUNT);
+ if (!migf)
+ return ERR_PTR(-ENOMEM);
+
+ migf->filp = anon_inode_getfile("virtiovf_mig", &virtiovf_resume_fops, migf,
+ O_WRONLY);
+ if (IS_ERR(migf->filp)) {
+ ret = PTR_ERR(migf->filp);
+ kfree(migf);
+ return ERR_PTR(ret);
+ }
+
+ stream_open(migf->filp->f_inode, migf->filp);
+ mutex_init(&migf->lock);
+ INIT_LIST_HEAD(&migf->buf_list);
+ INIT_LIST_HEAD(&migf->avail_list);
+ spin_lock_init(&migf->list_lock);
+
+ buf = virtiovf_alloc_data_buffer(migf, VIRTIOVF_TARGET_INITIAL_BUF_SIZE);
+ if (IS_ERR(buf)) {
+ ret = PTR_ERR(buf);
+ goto out;
+ }
+
+ migf->buf = buf;
+
+ buf = virtiovf_alloc_data_buffer(migf,
+ sizeof(struct virtiovf_migration_header));
+ if (IS_ERR(buf)) {
+ ret = PTR_ERR(buf);
+ goto out_clean;
+ }
+
+ migf->buf_header = buf;
+ migf->load_state = VIRTIOVF_LOAD_STATE_READ_HEADER;
+
+ migf->virtvdev = virtvdev;
+ ret = virtiovf_pci_alloc_obj_id(virtvdev, VIRTIO_RESOURCE_OBJ_DEV_PARTS_TYPE_SET,
+ &obj_id);
+ if (ret)
+ goto out_clean;
+
+ migf->obj_id = obj_id;
+ /* Mark as having a valid obj id which can be even 0 */
+ migf->has_obj_id = true;
+ ret = virtiovf_set_obj_cmd_header(migf->buf);
+ if (ret)
+ goto out_clean;
+
+ return migf;
+
+out_clean:
+ virtiovf_clean_migf_resources(migf);
+out:
+ fput(migf->filp);
+ return ERR_PTR(ret);
+}
+
+static struct file *
+virtiovf_pci_step_device_state_locked(struct virtiovf_pci_core_device *virtvdev,
+ u32 new)
+{
+ u32 cur = virtvdev->mig_state;
+ int ret;
+
+ if (cur == VFIO_DEVICE_STATE_RUNNING_P2P && new == VFIO_DEVICE_STATE_STOP) {
+ /* NOP */
+ return NULL;
+ }
+
+ if (cur == VFIO_DEVICE_STATE_STOP && new == VFIO_DEVICE_STATE_RUNNING_P2P) {
+ /* NOP */
+ return NULL;
+ }
+
+ if ((cur == VFIO_DEVICE_STATE_RUNNING && new == VFIO_DEVICE_STATE_RUNNING_P2P) ||
+ (cur == VFIO_DEVICE_STATE_PRE_COPY && new == VFIO_DEVICE_STATE_PRE_COPY_P2P)) {
+ ret = virtio_pci_admin_mode_set(virtvdev->core_device.pdev,
+ BIT(VIRTIO_ADMIN_CMD_DEV_MODE_F_STOPPED));
+ if (ret)
+ return ERR_PTR(ret);
+ return NULL;
+ }
+
+ if ((cur == VFIO_DEVICE_STATE_RUNNING_P2P && new == VFIO_DEVICE_STATE_RUNNING) ||
+ (cur == VFIO_DEVICE_STATE_PRE_COPY_P2P && new == VFIO_DEVICE_STATE_PRE_COPY)) {
+ ret = virtio_pci_admin_mode_set(virtvdev->core_device.pdev, 0);
+ if (ret)
+ return ERR_PTR(ret);
+ return NULL;
+ }
+
+ if (cur == VFIO_DEVICE_STATE_STOP && new == VFIO_DEVICE_STATE_STOP_COPY) {
+ struct virtiovf_migration_file *migf;
+
+ migf = virtiovf_pci_save_device_data(virtvdev, false);
+ if (IS_ERR(migf))
+ return ERR_CAST(migf);
+ get_file(migf->filp);
+ virtvdev->saving_migf = migf;
+ return migf->filp;
+ }
+
+ if ((cur == VFIO_DEVICE_STATE_STOP_COPY && new == VFIO_DEVICE_STATE_STOP) ||
+ (cur == VFIO_DEVICE_STATE_PRE_COPY && new == VFIO_DEVICE_STATE_RUNNING) ||
+ (cur == VFIO_DEVICE_STATE_PRE_COPY_P2P && new == VFIO_DEVICE_STATE_RUNNING_P2P)) {
+ virtiovf_disable_fds(virtvdev);
+ return NULL;
+ }
+
+ if (cur == VFIO_DEVICE_STATE_STOP && new == VFIO_DEVICE_STATE_RESUMING) {
+ struct virtiovf_migration_file *migf;
+
+ migf = virtiovf_pci_resume_device_data(virtvdev);
+ if (IS_ERR(migf))
+ return ERR_CAST(migf);
+ get_file(migf->filp);
+ virtvdev->resuming_migf = migf;
+ return migf->filp;
+ }
+
+ if (cur == VFIO_DEVICE_STATE_RESUMING && new == VFIO_DEVICE_STATE_STOP) {
+ virtiovf_disable_fds(virtvdev);
+ return NULL;
+ }
+
+ if ((cur == VFIO_DEVICE_STATE_RUNNING && new == VFIO_DEVICE_STATE_PRE_COPY) ||
+ (cur == VFIO_DEVICE_STATE_RUNNING_P2P &&
+ new == VFIO_DEVICE_STATE_PRE_COPY_P2P)) {
+ struct virtiovf_migration_file *migf;
+
+ migf = virtiovf_pci_save_device_data(virtvdev, true);
+ if (IS_ERR(migf))
+ return ERR_CAST(migf);
+ get_file(migf->filp);
+ virtvdev->saving_migf = migf;
+ return migf->filp;
+ }
+
+ if (cur == VFIO_DEVICE_STATE_PRE_COPY_P2P && new == VFIO_DEVICE_STATE_STOP_COPY) {
+ ret = virtiovf_pci_save_device_final_data(virtvdev);
+ return ret ? ERR_PTR(ret) : NULL;
+ }
+
+ /*
+ * vfio_mig_get_next_state() does not use arcs other than the above
+ */
+ WARN_ON(true);
+ return ERR_PTR(-EINVAL);
+}
+
+static struct file *
+virtiovf_pci_set_device_state(struct vfio_device *vdev,
+ enum vfio_device_mig_state new_state)
+{
+ struct virtiovf_pci_core_device *virtvdev = container_of(
+ vdev, struct virtiovf_pci_core_device, core_device.vdev);
+ enum vfio_device_mig_state next_state;
+ struct file *res = NULL;
+ int ret;
+
+ mutex_lock(&virtvdev->state_mutex);
+ while (new_state != virtvdev->mig_state) {
+ ret = vfio_mig_get_next_state(vdev, virtvdev->mig_state,
+ new_state, &next_state);
+ if (ret) {
+ res = ERR_PTR(ret);
+ break;
+ }
+ res = virtiovf_pci_step_device_state_locked(virtvdev, next_state);
+ if (IS_ERR(res))
+ break;
+ virtvdev->mig_state = next_state;
+ if (WARN_ON(res && new_state != virtvdev->mig_state)) {
+ fput(res);
+ res = ERR_PTR(-EINVAL);
+ break;
+ }
+ }
+ virtiovf_state_mutex_unlock(virtvdev);
+ return res;
+}
+
+static int virtiovf_pci_get_device_state(struct vfio_device *vdev,
+ enum vfio_device_mig_state *curr_state)
+{
+ struct virtiovf_pci_core_device *virtvdev = container_of(
+ vdev, struct virtiovf_pci_core_device, core_device.vdev);
+
+ mutex_lock(&virtvdev->state_mutex);
+ *curr_state = virtvdev->mig_state;
+ virtiovf_state_mutex_unlock(virtvdev);
+ return 0;
+}
+
+static int virtiovf_pci_get_data_size(struct vfio_device *vdev,
+ unsigned long *stop_copy_length)
+{
+ struct virtiovf_pci_core_device *virtvdev = container_of(
+ vdev, struct virtiovf_pci_core_device, core_device.vdev);
+ bool obj_id_exists;
+ u32 res_size;
+ u32 obj_id;
+ int ret;
+
+ mutex_lock(&virtvdev->state_mutex);
+ obj_id_exists = virtvdev->saving_migf && virtvdev->saving_migf->has_obj_id;
+ if (!obj_id_exists) {
+ ret = virtiovf_pci_alloc_obj_id(virtvdev,
+ VIRTIO_RESOURCE_OBJ_DEV_PARTS_TYPE_GET,
+ &obj_id);
+ if (ret)
+ goto end;
+ } else {
+ obj_id = virtvdev->saving_migf->obj_id;
+ }
+
+ ret = virtio_pci_admin_dev_parts_metadata_get(virtvdev->core_device.pdev,
+ VIRTIO_RESOURCE_OBJ_DEV_PARTS, obj_id,
+ VIRTIO_ADMIN_CMD_DEV_PARTS_METADATA_TYPE_SIZE,
+ &res_size);
+ if (!ret)
+ *stop_copy_length = res_size;
+
+ /*
+ * We can't leave this obj_id alive if didn't exist before, otherwise, it might
+ * stay alive, even without an active migration flow (e.g. migration was cancelled)
+ */
+ if (!obj_id_exists)
+ virtiovf_pci_free_obj_id(virtvdev, obj_id);
+end:
+ virtiovf_state_mutex_unlock(virtvdev);
+ return ret;
+}
+
+static const struct vfio_migration_ops virtvdev_pci_mig_ops = {
+ .migration_set_state = virtiovf_pci_set_device_state,
+ .migration_get_state = virtiovf_pci_get_device_state,
+ .migration_get_data_size = virtiovf_pci_get_data_size,
+};
+
+void virtiovf_set_migratable(struct virtiovf_pci_core_device *virtvdev)
+{
+ virtvdev->migrate_cap = 1;
+ mutex_init(&virtvdev->state_mutex);
+ spin_lock_init(&virtvdev->reset_lock);
+ virtvdev->core_device.vdev.migration_flags =
+ VFIO_MIGRATION_STOP_COPY |
+ VFIO_MIGRATION_P2P |
+ VFIO_MIGRATION_PRE_COPY;
+ virtvdev->core_device.vdev.mig_ops = &virtvdev_pci_mig_ops;
+}
+
+void virtiovf_open_migration(struct virtiovf_pci_core_device *virtvdev)
+{
+ if (!virtvdev->migrate_cap)
+ return;
+
+ virtvdev->mig_state = VFIO_DEVICE_STATE_RUNNING;
+}
+
+void virtiovf_close_migration(struct virtiovf_pci_core_device *virtvdev)
+{
+ if (!virtvdev->migrate_cap)
+ return;
+
+ virtiovf_disable_fds(virtvdev);
+}
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
index 8beecf23ec85..8cd01de27baf 100644
--- a/drivers/virtio/virtio_pci_common.h
+++ b/drivers/virtio/virtio_pci_common.h
@@ -48,6 +48,9 @@ struct virtio_pci_admin_vq {
/* Protects virtqueue access. */
spinlock_t lock;
u64 supported_cmds;
+ u64 supported_caps;
+ u8 max_dev_parts_objects;
+ struct ida dev_parts_ida;
/* Name of the admin queue: avq.$vq_index. */
char name[10];
u16 vq_index;
@@ -167,15 +170,27 @@ struct virtio_device *virtio_pci_vf_get_pf_dev(struct pci_dev *pdev);
BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_DEV_CFG_READ) | \
BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_NOTIFY_INFO))
+#define VIRTIO_DEV_PARTS_ADMIN_CMD_BITMAP \
+ (BIT_ULL(VIRTIO_ADMIN_CMD_CAP_ID_LIST_QUERY) | \
+ BIT_ULL(VIRTIO_ADMIN_CMD_DRIVER_CAP_SET) | \
+ BIT_ULL(VIRTIO_ADMIN_CMD_DEVICE_CAP_GET) | \
+ BIT_ULL(VIRTIO_ADMIN_CMD_RESOURCE_OBJ_CREATE) | \
+ BIT_ULL(VIRTIO_ADMIN_CMD_RESOURCE_OBJ_DESTROY) | \
+ BIT_ULL(VIRTIO_ADMIN_CMD_DEV_PARTS_METADATA_GET) | \
+ BIT_ULL(VIRTIO_ADMIN_CMD_DEV_PARTS_GET) | \
+ BIT_ULL(VIRTIO_ADMIN_CMD_DEV_PARTS_SET) | \
+ BIT_ULL(VIRTIO_ADMIN_CMD_DEV_MODE_SET))
+
/* Unlike modern drivers which support hardware virtio devices, legacy drivers
* assume software-based devices: e.g. they don't use proper memory barriers
* on ARM, use big endian on PPC, etc. X86 drivers are mostly ok though, more
* or less by chance. For now, only support legacy IO on X86.
*/
#ifdef CONFIG_VIRTIO_PCI_ADMIN_LEGACY
-#define VIRTIO_ADMIN_CMD_BITMAP VIRTIO_LEGACY_ADMIN_CMD_BITMAP
+#define VIRTIO_ADMIN_CMD_BITMAP (VIRTIO_LEGACY_ADMIN_CMD_BITMAP | \
+ VIRTIO_DEV_PARTS_ADMIN_CMD_BITMAP)
#else
-#define VIRTIO_ADMIN_CMD_BITMAP 0
+#define VIRTIO_ADMIN_CMD_BITMAP VIRTIO_DEV_PARTS_ADMIN_CMD_BITMAP
#endif
bool vp_is_avq(struct virtio_device *vdev, unsigned int index);
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 4fbcbc7a9ae1..5eaade757860 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -15,6 +15,7 @@
*/
#include <linux/delay.h>
+#include <linux/virtio_pci_admin.h>
#define VIRTIO_PCI_NO_LEGACY
#define VIRTIO_RING_NO_LEGACY
#include "virtio_pci_common.h"
@@ -54,8 +55,10 @@ void vp_modern_avq_done(struct virtqueue *vq)
spin_lock_irqsave(&admin_vq->lock, flags);
do {
virtqueue_disable_cb(vq);
- while ((cmd = virtqueue_get_buf(vq, &len)))
+ while ((cmd = virtqueue_get_buf(vq, &len))) {
+ cmd->result_sg_size = len;
complete(&cmd->completion);
+ }
} while (!virtqueue_enable_cb(vq));
spin_unlock_irqrestore(&admin_vq->lock, flags);
}
@@ -218,12 +221,117 @@ end:
kfree(data);
}
+static void
+virtio_pci_admin_cmd_dev_parts_objects_enable(struct virtio_device *virtio_dev)
+{
+ struct virtio_pci_device *vp_dev = to_vp_device(virtio_dev);
+ struct virtio_admin_cmd_cap_get_data *get_data;
+ struct virtio_admin_cmd_cap_set_data *set_data;
+ struct virtio_dev_parts_cap *result;
+ struct virtio_admin_cmd cmd = {};
+ struct scatterlist result_sg;
+ struct scatterlist data_sg;
+ u8 resource_objects_limit;
+ u16 set_data_size;
+ int ret;
+
+ get_data = kzalloc(sizeof(*get_data), GFP_KERNEL);
+ if (!get_data)
+ return;
+
+ result = kzalloc(sizeof(*result), GFP_KERNEL);
+ if (!result)
+ goto end;
+
+ get_data->id = cpu_to_le16(VIRTIO_DEV_PARTS_CAP);
+ sg_init_one(&data_sg, get_data, sizeof(*get_data));
+ sg_init_one(&result_sg, result, sizeof(*result));
+ cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_DEVICE_CAP_GET);
+ cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
+ cmd.data_sg = &data_sg;
+ cmd.result_sg = &result_sg;
+ ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
+ if (ret)
+ goto err_get;
+
+ set_data_size = sizeof(*set_data) + sizeof(*result);
+ set_data = kzalloc(set_data_size, GFP_KERNEL);
+ if (!set_data)
+ goto err_get;
+
+ set_data->id = cpu_to_le16(VIRTIO_DEV_PARTS_CAP);
+
+ /* Set the limit to the minimum value between the GET and SET values
+ * supported by the device. Since the obj_id for VIRTIO_DEV_PARTS_CAP
+ * is a globally unique value per PF, there is no possibility of
+ * overlap between GET and SET operations.
+ */
+ resource_objects_limit = min(result->get_parts_resource_objects_limit,
+ result->set_parts_resource_objects_limit);
+ result->get_parts_resource_objects_limit = resource_objects_limit;
+ result->set_parts_resource_objects_limit = resource_objects_limit;
+ memcpy(set_data->cap_specific_data, result, sizeof(*result));
+ sg_init_one(&data_sg, set_data, set_data_size);
+ cmd.data_sg = &data_sg;
+ cmd.result_sg = NULL;
+ cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_DRIVER_CAP_SET);
+ ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
+ if (ret)
+ goto err_set;
+
+ /* Allocate IDR to manage the dev caps objects */
+ ida_init(&vp_dev->admin_vq.dev_parts_ida);
+ vp_dev->admin_vq.max_dev_parts_objects = resource_objects_limit;
+
+err_set:
+ kfree(set_data);
+err_get:
+ kfree(result);
+end:
+ kfree(get_data);
+}
+
+static void virtio_pci_admin_cmd_cap_init(struct virtio_device *virtio_dev)
+{
+ struct virtio_pci_device *vp_dev = to_vp_device(virtio_dev);
+ struct virtio_admin_cmd_query_cap_id_result *data;
+ struct virtio_admin_cmd cmd = {};
+ struct scatterlist result_sg;
+ int ret;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return;
+
+ sg_init_one(&result_sg, data, sizeof(*data));
+ cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_CAP_ID_LIST_QUERY);
+ cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
+ cmd.result_sg = &result_sg;
+
+ ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
+ if (ret)
+ goto end;
+
+ /* Max number of caps fits into a single u64 */
+ BUILD_BUG_ON(sizeof(data->supported_caps) > sizeof(u64));
+
+ vp_dev->admin_vq.supported_caps = le64_to_cpu(data->supported_caps[0]);
+
+ if (!(vp_dev->admin_vq.supported_caps & (1 << VIRTIO_DEV_PARTS_CAP)))
+ goto end;
+
+ virtio_pci_admin_cmd_dev_parts_objects_enable(virtio_dev);
+end:
+ kfree(data);
+}
+
static void vp_modern_avq_activate(struct virtio_device *vdev)
{
if (!virtio_has_feature(vdev, VIRTIO_F_ADMIN_VQ))
return;
virtio_pci_admin_cmd_list_init(vdev);
+ virtio_pci_admin_cmd_cap_init(vdev);
}
static void vp_modern_avq_cleanup(struct virtio_device *vdev)
@@ -758,6 +866,353 @@ static bool vp_get_shm_region(struct virtio_device *vdev,
return true;
}
+/*
+ * virtio_pci_admin_has_dev_parts - Checks whether the device parts
+ * functionality is supported
+ * @pdev: VF pci_dev
+ *
+ * Returns true on success.
+ */
+bool virtio_pci_admin_has_dev_parts(struct pci_dev *pdev)
+{
+ struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
+ struct virtio_pci_device *vp_dev;
+
+ if (!virtio_dev)
+ return false;
+
+ if (!virtio_has_feature(virtio_dev, VIRTIO_F_ADMIN_VQ))
+ return false;
+
+ vp_dev = to_vp_device(virtio_dev);
+
+ if (!((vp_dev->admin_vq.supported_cmds & VIRTIO_DEV_PARTS_ADMIN_CMD_BITMAP) ==
+ VIRTIO_DEV_PARTS_ADMIN_CMD_BITMAP))
+ return false;
+
+ return vp_dev->admin_vq.max_dev_parts_objects;
+}
+EXPORT_SYMBOL_GPL(virtio_pci_admin_has_dev_parts);
+
+/*
+ * virtio_pci_admin_mode_set - Sets the mode of a member device
+ * @pdev: VF pci_dev
+ * @flags: device mode's flags
+ *
+ * Note: caller must serialize access for the given device.
+ * Returns 0 on success, or negative on failure.
+ */
+int virtio_pci_admin_mode_set(struct pci_dev *pdev, u8 flags)
+{
+ struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
+ struct virtio_admin_cmd_dev_mode_set_data *data;
+ struct virtio_admin_cmd cmd = {};
+ struct scatterlist data_sg;
+ int vf_id;
+ int ret;
+
+ if (!virtio_dev)
+ return -ENODEV;
+
+ vf_id = pci_iov_vf_id(pdev);
+ if (vf_id < 0)
+ return vf_id;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->flags = flags;
+ sg_init_one(&data_sg, data, sizeof(*data));
+ cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_DEV_MODE_SET);
+ cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
+ cmd.group_member_id = cpu_to_le64(vf_id + 1);
+ cmd.data_sg = &data_sg;
+ ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
+
+ kfree(data);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(virtio_pci_admin_mode_set);
+
+/*
+ * virtio_pci_admin_obj_create - Creates an object for a given type and operation,
+ * following the max objects that can be created for that request.
+ * @pdev: VF pci_dev
+ * @obj_type: Object type
+ * @operation_type: Operation type
+ * @obj_id: Output unique object id
+ *
+ * Note: caller must serialize access for the given device.
+ * Returns 0 on success, or negative on failure.
+ */
+int virtio_pci_admin_obj_create(struct pci_dev *pdev, u16 obj_type, u8 operation_type,
+ u32 *obj_id)
+{
+ struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
+ u16 data_size = sizeof(struct virtio_admin_cmd_resource_obj_create_data);
+ struct virtio_admin_cmd_resource_obj_create_data *obj_create_data;
+ struct virtio_resource_obj_dev_parts obj_dev_parts = {};
+ struct virtio_pci_admin_vq *avq;
+ struct virtio_admin_cmd cmd = {};
+ struct scatterlist data_sg;
+ void *data;
+ int id = -1;
+ int vf_id;
+ int ret;
+
+ if (!virtio_dev)
+ return -ENODEV;
+
+ vf_id = pci_iov_vf_id(pdev);
+ if (vf_id < 0)
+ return vf_id;
+
+ if (obj_type != VIRTIO_RESOURCE_OBJ_DEV_PARTS)
+ return -EOPNOTSUPP;
+
+ if (operation_type != VIRTIO_RESOURCE_OBJ_DEV_PARTS_TYPE_GET &&
+ operation_type != VIRTIO_RESOURCE_OBJ_DEV_PARTS_TYPE_SET)
+ return -EINVAL;
+
+ avq = &to_vp_device(virtio_dev)->admin_vq;
+ if (!avq->max_dev_parts_objects)
+ return -EOPNOTSUPP;
+
+ id = ida_alloc_range(&avq->dev_parts_ida, 0,
+ avq->max_dev_parts_objects - 1, GFP_KERNEL);
+ if (id < 0)
+ return id;
+
+ *obj_id = id;
+ data_size += sizeof(obj_dev_parts);
+ data = kzalloc(data_size, GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ obj_create_data = data;
+ obj_create_data->hdr.type = cpu_to_le16(obj_type);
+ obj_create_data->hdr.id = cpu_to_le32(*obj_id);
+ obj_dev_parts.type = operation_type;
+ memcpy(obj_create_data->resource_obj_specific_data, &obj_dev_parts,
+ sizeof(obj_dev_parts));
+ sg_init_one(&data_sg, data, data_size);
+ cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_RESOURCE_OBJ_CREATE);
+ cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
+ cmd.group_member_id = cpu_to_le64(vf_id + 1);
+ cmd.data_sg = &data_sg;
+ ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
+
+ kfree(data);
+end:
+ if (ret)
+ ida_free(&avq->dev_parts_ida, id);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(virtio_pci_admin_obj_create);
+
+/*
+ * virtio_pci_admin_obj_destroy - Destroys an object of a given type and id
+ * @pdev: VF pci_dev
+ * @obj_type: Object type
+ * @id: Object id
+ *
+ * Note: caller must serialize access for the given device.
+ * Returns 0 on success, or negative on failure.
+ */
+int virtio_pci_admin_obj_destroy(struct pci_dev *pdev, u16 obj_type, u32 id)
+{
+ struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
+ struct virtio_admin_cmd_resource_obj_cmd_hdr *data;
+ struct virtio_pci_device *vp_dev;
+ struct virtio_admin_cmd cmd = {};
+ struct scatterlist data_sg;
+ int vf_id;
+ int ret;
+
+ if (!virtio_dev)
+ return -ENODEV;
+
+ vf_id = pci_iov_vf_id(pdev);
+ if (vf_id < 0)
+ return vf_id;
+
+ if (obj_type != VIRTIO_RESOURCE_OBJ_DEV_PARTS)
+ return -EINVAL;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->type = cpu_to_le16(obj_type);
+ data->id = cpu_to_le32(id);
+ sg_init_one(&data_sg, data, sizeof(*data));
+ cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_RESOURCE_OBJ_DESTROY);
+ cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
+ cmd.group_member_id = cpu_to_le64(vf_id + 1);
+ cmd.data_sg = &data_sg;
+ ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
+ if (!ret) {
+ vp_dev = to_vp_device(virtio_dev);
+ ida_free(&vp_dev->admin_vq.dev_parts_ida, id);
+ }
+
+ kfree(data);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(virtio_pci_admin_obj_destroy);
+
+/*
+ * virtio_pci_admin_dev_parts_metadata_get - Gets the metadata of the device parts
+ * identified by the below attributes.
+ * @pdev: VF pci_dev
+ * @obj_type: Object type
+ * @id: Object id
+ * @metadata_type: Metadata type
+ * @out: Upon success holds the output for 'metadata type size'
+ *
+ * Note: caller must serialize access for the given device.
+ * Returns 0 on success, or negative on failure.
+ */
+int virtio_pci_admin_dev_parts_metadata_get(struct pci_dev *pdev, u16 obj_type,
+ u32 id, u8 metadata_type, u32 *out)
+{
+ struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
+ struct virtio_admin_cmd_dev_parts_metadata_result *result;
+ struct virtio_admin_cmd_dev_parts_metadata_data *data;
+ struct scatterlist data_sg, result_sg;
+ struct virtio_admin_cmd cmd = {};
+ int vf_id;
+ int ret;
+
+ if (!virtio_dev)
+ return -ENODEV;
+
+ if (metadata_type != VIRTIO_ADMIN_CMD_DEV_PARTS_METADATA_TYPE_SIZE)
+ return -EOPNOTSUPP;
+
+ vf_id = pci_iov_vf_id(pdev);
+ if (vf_id < 0)
+ return vf_id;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ result = kzalloc(sizeof(*result), GFP_KERNEL);
+ if (!result) {
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ data->hdr.type = cpu_to_le16(obj_type);
+ data->hdr.id = cpu_to_le32(id);
+ data->type = metadata_type;
+ sg_init_one(&data_sg, data, sizeof(*data));
+ sg_init_one(&result_sg, result, sizeof(*result));
+ cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_DEV_PARTS_METADATA_GET);
+ cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
+ cmd.group_member_id = cpu_to_le64(vf_id + 1);
+ cmd.data_sg = &data_sg;
+ cmd.result_sg = &result_sg;
+ ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
+ if (!ret)
+ *out = le32_to_cpu(result->parts_size.size);
+
+ kfree(result);
+end:
+ kfree(data);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(virtio_pci_admin_dev_parts_metadata_get);
+
+/*
+ * virtio_pci_admin_dev_parts_get - Gets the device parts identified by the below attributes.
+ * @pdev: VF pci_dev
+ * @obj_type: Object type
+ * @id: Object id
+ * @get_type: Get type
+ * @res_sg: Upon success holds the output result data
+ * @res_size: Upon success holds the output result size
+ *
+ * Note: caller must serialize access for the given device.
+ * Returns 0 on success, or negative on failure.
+ */
+int virtio_pci_admin_dev_parts_get(struct pci_dev *pdev, u16 obj_type, u32 id,
+ u8 get_type, struct scatterlist *res_sg,
+ u32 *res_size)
+{
+ struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
+ struct virtio_admin_cmd_dev_parts_get_data *data;
+ struct scatterlist data_sg;
+ struct virtio_admin_cmd cmd = {};
+ int vf_id;
+ int ret;
+
+ if (!virtio_dev)
+ return -ENODEV;
+
+ if (get_type != VIRTIO_ADMIN_CMD_DEV_PARTS_GET_TYPE_ALL)
+ return -EOPNOTSUPP;
+
+ vf_id = pci_iov_vf_id(pdev);
+ if (vf_id < 0)
+ return vf_id;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->hdr.type = cpu_to_le16(obj_type);
+ data->hdr.id = cpu_to_le32(id);
+ data->type = get_type;
+ sg_init_one(&data_sg, data, sizeof(*data));
+ cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_DEV_PARTS_GET);
+ cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
+ cmd.group_member_id = cpu_to_le64(vf_id + 1);
+ cmd.data_sg = &data_sg;
+ cmd.result_sg = res_sg;
+ ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
+ if (!ret)
+ *res_size = cmd.result_sg_size;
+
+ kfree(data);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(virtio_pci_admin_dev_parts_get);
+
+/*
+ * virtio_pci_admin_dev_parts_set - Sets the device parts identified by the below attributes.
+ * @pdev: VF pci_dev
+ * @data_sg: The device parts data, its layout follows struct virtio_admin_cmd_dev_parts_set_data
+ *
+ * Note: caller must serialize access for the given device.
+ * Returns 0 on success, or negative on failure.
+ */
+int virtio_pci_admin_dev_parts_set(struct pci_dev *pdev, struct scatterlist *data_sg)
+{
+ struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
+ struct virtio_admin_cmd cmd = {};
+ int vf_id;
+
+ if (!virtio_dev)
+ return -ENODEV;
+
+ vf_id = pci_iov_vf_id(pdev);
+ if (vf_id < 0)
+ return vf_id;
+
+ cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_DEV_PARTS_SET);
+ cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
+ cmd.group_member_id = cpu_to_le64(vf_id + 1);
+ cmd.data_sg = data_sg;
+ return vp_modern_admin_cmd_exec(virtio_dev, &cmd);
+}
+EXPORT_SYMBOL_GPL(virtio_pci_admin_dev_parts_set);
+
static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
.get = NULL,
.set = NULL,
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 8167be01b400..82a7d2cbc704 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -223,15 +223,6 @@ struct vring_virtqueue {
#endif
};
-static struct virtqueue *__vring_new_virtqueue(unsigned int index,
- struct vring_virtqueue_split *vring_split,
- struct virtio_device *vdev,
- bool weak_barriers,
- bool context,
- bool (*notify)(struct virtqueue *),
- void (*callback)(struct virtqueue *),
- const char *name,
- struct device *dma_dev);
static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
static void vring_free(struct virtqueue *_vq);
@@ -1135,6 +1126,64 @@ static int vring_alloc_queue_split(struct vring_virtqueue_split *vring_split,
return 0;
}
+static struct virtqueue *__vring_new_virtqueue_split(unsigned int index,
+ struct vring_virtqueue_split *vring_split,
+ struct virtio_device *vdev,
+ bool weak_barriers,
+ bool context,
+ bool (*notify)(struct virtqueue *),
+ void (*callback)(struct virtqueue *),
+ const char *name,
+ struct device *dma_dev)
+{
+ struct vring_virtqueue *vq;
+ int err;
+
+ vq = kmalloc(sizeof(*vq), GFP_KERNEL);
+ if (!vq)
+ return NULL;
+
+ vq->packed_ring = false;
+ vq->vq.callback = callback;
+ vq->vq.vdev = vdev;
+ vq->vq.name = name;
+ vq->vq.index = index;
+ vq->vq.reset = false;
+ vq->we_own_ring = false;
+ vq->notify = notify;
+ vq->weak_barriers = weak_barriers;
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
+ vq->broken = true;
+#else
+ vq->broken = false;
+#endif
+ vq->dma_dev = dma_dev;
+ vq->use_dma_api = vring_use_dma_api(vdev);
+
+ vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
+ !context;
+ vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
+
+ if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
+ vq->weak_barriers = false;
+
+ err = vring_alloc_state_extra_split(vring_split);
+ if (err) {
+ kfree(vq);
+ return NULL;
+ }
+
+ virtqueue_vring_init_split(vring_split, vq);
+
+ virtqueue_init(vq, vring_split->vring.num);
+ virtqueue_vring_attach_split(vq, vring_split);
+
+ spin_lock(&vdev->vqs_list_lock);
+ list_add_tail(&vq->vq.list, &vdev->vqs);
+ spin_unlock(&vdev->vqs_list_lock);
+ return &vq->vq;
+}
+
static struct virtqueue *vring_create_virtqueue_split(
unsigned int index,
unsigned int num,
@@ -1157,7 +1206,7 @@ static struct virtqueue *vring_create_virtqueue_split(
if (err)
return NULL;
- vq = __vring_new_virtqueue(index, &vring_split, vdev, weak_barriers,
+ vq = __vring_new_virtqueue_split(index, &vring_split, vdev, weak_barriers,
context, notify, callback, name, dma_dev);
if (!vq) {
vring_free_split(&vring_split, vdev, dma_dev);
@@ -2055,36 +2104,29 @@ static void virtqueue_reinit_packed(struct vring_virtqueue *vq)
virtqueue_vring_init_packed(&vq->packed, !!vq->vq.callback);
}
-static struct virtqueue *vring_create_virtqueue_packed(
- unsigned int index,
- unsigned int num,
- unsigned int vring_align,
- struct virtio_device *vdev,
- bool weak_barriers,
- bool may_reduce_num,
- bool context,
- bool (*notify)(struct virtqueue *),
- void (*callback)(struct virtqueue *),
- const char *name,
- struct device *dma_dev)
+static struct virtqueue *__vring_new_virtqueue_packed(unsigned int index,
+ struct vring_virtqueue_packed *vring_packed,
+ struct virtio_device *vdev,
+ bool weak_barriers,
+ bool context,
+ bool (*notify)(struct virtqueue *),
+ void (*callback)(struct virtqueue *),
+ const char *name,
+ struct device *dma_dev)
{
- struct vring_virtqueue_packed vring_packed = {};
struct vring_virtqueue *vq;
int err;
- if (vring_alloc_queue_packed(&vring_packed, vdev, num, dma_dev))
- goto err_ring;
-
vq = kmalloc(sizeof(*vq), GFP_KERNEL);
if (!vq)
- goto err_vq;
+ return NULL;
vq->vq.callback = callback;
vq->vq.vdev = vdev;
vq->vq.name = name;
vq->vq.index = index;
vq->vq.reset = false;
- vq->we_own_ring = true;
+ vq->we_own_ring = false;
vq->notify = notify;
vq->weak_barriers = weak_barriers;
#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
@@ -2103,26 +2145,52 @@ static struct virtqueue *vring_create_virtqueue_packed(
if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
vq->weak_barriers = false;
- err = vring_alloc_state_extra_packed(&vring_packed);
- if (err)
- goto err_state_extra;
+ err = vring_alloc_state_extra_packed(vring_packed);
+ if (err) {
+ kfree(vq);
+ return NULL;
+ }
- virtqueue_vring_init_packed(&vring_packed, !!callback);
+ virtqueue_vring_init_packed(vring_packed, !!callback);
- virtqueue_init(vq, num);
- virtqueue_vring_attach_packed(vq, &vring_packed);
+ virtqueue_init(vq, vring_packed->vring.num);
+ virtqueue_vring_attach_packed(vq, vring_packed);
spin_lock(&vdev->vqs_list_lock);
list_add_tail(&vq->vq.list, &vdev->vqs);
spin_unlock(&vdev->vqs_list_lock);
return &vq->vq;
+}
-err_state_extra:
- kfree(vq);
-err_vq:
- vring_free_packed(&vring_packed, vdev, dma_dev);
-err_ring:
- return NULL;
+static struct virtqueue *vring_create_virtqueue_packed(
+ unsigned int index,
+ unsigned int num,
+ unsigned int vring_align,
+ struct virtio_device *vdev,
+ bool weak_barriers,
+ bool may_reduce_num,
+ bool context,
+ bool (*notify)(struct virtqueue *),
+ void (*callback)(struct virtqueue *),
+ const char *name,
+ struct device *dma_dev)
+{
+ struct vring_virtqueue_packed vring_packed = {};
+ struct virtqueue *vq;
+
+ if (vring_alloc_queue_packed(&vring_packed, vdev, num, dma_dev))
+ return NULL;
+
+ vq = __vring_new_virtqueue_packed(index, &vring_packed, vdev, weak_barriers,
+ context, notify, callback, name, dma_dev);
+ if (!vq) {
+ vring_free_packed(&vring_packed, vdev, dma_dev);
+ return NULL;
+ }
+
+ to_vvq(vq)->we_own_ring = true;
+
+ return vq;
}
static int virtqueue_resize_packed(struct virtqueue *_vq, u32 num)
@@ -2650,68 +2718,6 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
}
EXPORT_SYMBOL_GPL(vring_interrupt);
-/* Only available for split ring */
-static struct virtqueue *__vring_new_virtqueue(unsigned int index,
- struct vring_virtqueue_split *vring_split,
- struct virtio_device *vdev,
- bool weak_barriers,
- bool context,
- bool (*notify)(struct virtqueue *),
- void (*callback)(struct virtqueue *),
- const char *name,
- struct device *dma_dev)
-{
- struct vring_virtqueue *vq;
- int err;
-
- if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
- return NULL;
-
- vq = kmalloc(sizeof(*vq), GFP_KERNEL);
- if (!vq)
- return NULL;
-
- vq->packed_ring = false;
- vq->vq.callback = callback;
- vq->vq.vdev = vdev;
- vq->vq.name = name;
- vq->vq.index = index;
- vq->vq.reset = false;
- vq->we_own_ring = false;
- vq->notify = notify;
- vq->weak_barriers = weak_barriers;
-#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
- vq->broken = true;
-#else
- vq->broken = false;
-#endif
- vq->dma_dev = dma_dev;
- vq->use_dma_api = vring_use_dma_api(vdev);
-
- vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
- !context;
- vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
-
- if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
- vq->weak_barriers = false;
-
- err = vring_alloc_state_extra_split(vring_split);
- if (err) {
- kfree(vq);
- return NULL;
- }
-
- virtqueue_vring_init_split(vring_split, vq);
-
- virtqueue_init(vq, vring_split->vring.num);
- virtqueue_vring_attach_split(vq, vring_split);
-
- spin_lock(&vdev->vqs_list_lock);
- list_add_tail(&vq->vq.list, &vdev->vqs);
- spin_unlock(&vdev->vqs_list_lock);
- return &vq->vq;
-}
-
struct virtqueue *vring_create_virtqueue(
unsigned int index,
unsigned int num,
@@ -2846,7 +2852,6 @@ int virtqueue_reset(struct virtqueue *_vq,
}
EXPORT_SYMBOL_GPL(virtqueue_reset);
-/* Only available for split ring */
struct virtqueue *vring_new_virtqueue(unsigned int index,
unsigned int num,
unsigned int vring_align,
@@ -2860,11 +2865,19 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
{
struct vring_virtqueue_split vring_split = {};
- if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
- return NULL;
+ if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED)) {
+ struct vring_virtqueue_packed vring_packed = {};
+
+ vring_packed.vring.num = num;
+ vring_packed.vring.desc = pages;
+ return __vring_new_virtqueue_packed(index, &vring_packed,
+ vdev, weak_barriers,
+ context, notify, callback,
+ name, vdev->dev.parent);
+ }
vring_init(&vring_split.vring, num, pages, vring_align);
- return __vring_new_virtqueue(index, &vring_split, vdev, weak_barriers,
+ return __vring_new_virtqueue_split(index, &vring_split, vdev, weak_barriers,
context, notify, callback, name,
vdev->dev.parent);
}
diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
index 7364bd53e38d..1f60c9d5cb18 100644
--- a/drivers/virtio/virtio_vdpa.c
+++ b/drivers/virtio/virtio_vdpa.c
@@ -364,14 +364,13 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
struct vdpa_device *vdpa = vd_get_vdpa(vdev);
const struct vdpa_config_ops *ops = vdpa->config;
- struct irq_affinity default_affd = { 0 };
struct cpumask *masks;
struct vdpa_callback cb;
bool has_affinity = desc && ops->set_vq_affinity;
int i, err, queue_idx = 0;
if (has_affinity) {
- masks = create_affinity_masks(nvqs, desc ? desc : &default_affd);
+ masks = create_affinity_masks(nvqs, desc);
if (!masks)
return -ENOMEM;
}