| | |
| | | +dtb-$(CONFIG_ARCH_MXC) += igkboard-imx8mp.dtb |
| | | diff --git a/arch/arm64/boot/dts/freescale/igkboard-imx8mp.dts b/arch/arm64/boot/dts/freescale/igkboard-imx8mp.dts |
| | | new file mode 100644 |
| | | index 000000000..02267ac4d |
| | | index 000000000..8ce653b69 |
| | | --- /dev/null |
| | | +++ b/arch/arm64/boot/dts/freescale/igkboard-imx8mp.dts |
| | | @@ -0,0 +1,531 @@ |
| | | @@ -0,0 +1,712 @@ |
| | | +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| | | +/* |
| | | + * Device Tree Source for LingYun IGKBoard(IoT Gateway Kits Board) - imx8mp |
| | |
| | | + label = "blueled"; |
| | | + gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; |
| | | + default-state = "on"; |
| | | + linux,default-trigger = "timer"; |
| | | + }; |
| | | + }; |
| | | + |
| | |
| | | +}; |
| | | + |
| | | +/*+------------------------+ |
| | | + | Misc Devices | |
| | | + +------------------------+*/ |
| | | + |
| | | +/* Buzzer */ |
| | | +&pwm1 { |
| | | + pinctrl-names = "default"; |
| | | + pinctrl-0 = <&pinctrl_pwm1>; |
| | | + status = "okay"; |
| | | +}; |
| | | + |
| | | +&i2c2 { |
| | | + clock-frequency = <100000>; |
| | | + pinctrl-names = "default"; |
| | | + pinctrl-0 = <&pinctrl_i2c2>; |
| | | + status = "okay"; |
| | | + |
| | | + rtc1208@6f { |
| | | + compatible = "isil,isl1208"; |
| | | + reg = <0x6f>; |
| | | + status = "okay"; |
| | | + }; |
| | | + |
| | | + ms1112@4a { |
| | | + compatible = "ms,ms1112"; |
| | | + reg = <0x4a>; |
| | | + status = "okay"; |
| | | + #address-cells = <1>; |
| | | + #size-cells = <0>; |
| | | + |
| | | + channel@2 { |
| | | + reg = <2>; |
| | | + ti,gain = <0>; |
| | | + ti,datarate = <3>; |
| | | + ti,mode = <1>; |
| | | + }; |
| | | + |
| | | + channel@3{ |
| | | + reg = <3>; |
| | | + ti,gain = <0>; |
| | | + ti,datarate = <3>; |
| | | + ti,mode = <1>; |
| | | + }; |
| | | + }; |
| | | +}; |
| | | + |
| | | +/*+------------------------+ |
| | | + | CAN/RS485 interface | |
| | | + +------------------------+*/ |
| | | +/* RS485 */ |
| | | +&uart3 { |
| | | + pinctrl-names = "default"; |
| | | + pinctrl-0 = <&pinctrl_uart3>; |
| | | + status = "okay"; |
| | | +}; |
| | | + |
| | | +/* CAN */ |
| | | +&flexcan1 { |
| | | + pinctrl-names = "default"; |
| | | + pinctrl-0 = <&pinctrl_flexcan1>; |
| | | + status = "okay"; |
| | | +}; |
| | | + |
| | | +&flexcan2 { |
| | | + pinctrl-names = "default"; |
| | | + pinctrl-0 = <&pinctrl_flexcan2>; |
| | | + status = "okay"; |
| | | +}; |
| | | + |
| | | +/*+------------------------+ |
| | | + | MikroBUS interface | |
| | | + +------------------------+*/ |
| | | + |
| | | +/* Same as RPi 40Pin extend interface: #32 */ |
| | | +&pwm3 { |
| | | + pinctrl-names = "default"; |
| | | + pinctrl-0 = <&pinctrl_pwm3>; |
| | | + status = "okay"; |
| | | +}; |
| | | + |
| | | +/* Same as RPi 40Pin extend interface: #19, #21, #23, #24 */ |
| | | +&uart1 { |
| | | + pinctrl-names = "default"; |
| | | + pinctrl-0 = <&pinctrl_uart1>; |
| | | + assigned-clocks = <&clk IMX8MP_CLK_UART1>; |
| | | + assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_80M>; |
| | | + status = "okay"; |
| | | +}; |
| | | + |
| | | +/* Same as RPi 40Pin extend interface */ |
| | | +&ecspi2 { |
| | | + #address-cells = <1>; |
| | | + #size-cells = <0>; |
| | | + fsl,spi-num-chipselects = <1>; |
| | | + pinctrl-names = "default"; |
| | | + pinctrl-0 = <&pinctrl_ecspi2>; |
| | | + cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>; |
| | | + status = "okay"; |
| | | + |
| | | + spidev@0 { |
| | | + compatible = "fsl,spidev", "semtech,sx1301"; |
| | | + reg = <0>; |
| | | + spi-max-frequency = <2000000>; |
| | | + }; |
| | | +}; |
| | | + |
| | | +/* Same as RPi 40Pin extend interface: #3, #5 */ |
| | | +&i2c5 { |
| | | + clock-frequency = <100000>; |
| | | + pinctrl-names = "default"; |
| | | + pinctrl-0 = <&pinctrl_i2c5>; |
| | | + status = "okay"; |
| | | + |
| | | + hdc1080@40 { |
| | | + compatible = "ti,hdc1080"; |
| | | + reg = <0x40>; |
| | | + status = "okay"; |
| | | + }; |
| | | + |
| | | + eeprom@50 { |
| | | + compatible = "microchip,24c32", "atmel,24c32"; |
| | | + reg = <0x50>; |
| | | + pagesize = <32>; |
| | | + num-addresses = <8>; |
| | | + }; |
| | | +}; |
| | | + |
| | | +/*+------------------------+ |
| | | + | PCA9450CHN PMIC | |
| | | + +------------------------+*/ |
| | | + |
| | | +&i2c1 { |
| | | + clock-frequency = <400000>; |
| | | + pinctrl-names = "default", "gpio"; |
| | | + pinctrl-names = "default"; |
| | | + pinctrl-0 = <&pinctrl_i2c1>; |
| | | + pinctrl-1 = <&pinctrl_i2c1_gpio>; |
| | | + scl-gpios = <&gpio5 14 GPIO_ACTIVE_HIGH>; |
| | | + sda-gpios = <&gpio5 15 GPIO_ACTIVE_HIGH>; |
| | | + status = "okay"; |
| | | + |
| | | + pmic@25 { |
| | |
| | | +&iomuxc { |
| | | + pinctrl-names = "default"; |
| | | + |
| | | + pinctrl_wdog: wdoggrp { |
| | | + fsl,pins = < |
| | | + MX8MP_IOMUXC_GPIO1_IO02__WDOG1_WDOG_B 0xc6 |
| | | + >; |
| | | + }; |
| | | + |
| | | + pinctrl_leds: ledsgrp { |
| | | + fsl,pins = < |
| | | + MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16 0x140 |
| | |
| | | + >; |
| | | + }; |
| | | + |
| | | + pinctrl_wdog: wdoggrp { |
| | | + pinctrl_pwm1: pwm1grp { |
| | | + fsl,pins = < |
| | | + MX8MP_IOMUXC_GPIO1_IO02__WDOG1_WDOG_B 0xc6 |
| | | + MX8MP_IOMUXC_GPIO1_IO08__PWM1_OUT 0x116 |
| | | + >; |
| | | + }; |
| | | + |
| | | + pinctrl_pwm3: pwm3grp { |
| | | + fsl,pins = < |
| | | + MX8MP_IOMUXC_SAI5_RXC__PWM3_OUT 0x116 |
| | | + >; |
| | | + }; |
| | | + |
| | | + pinctrl_uart1: uart1grp { |
| | | + fsl,pins = < |
| | | + MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX 0x140 |
| | | + MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX 0x140 |
| | | + >; |
| | | + }; |
| | | + |
| | |
| | | + >; |
| | | + }; |
| | | + |
| | | + pinctrl_uart3: uart3grp { |
| | | + fsl,pins = < |
| | | + MX8MP_IOMUXC_ECSPI1_SCLK__UART3_DCE_RX 0x82 |
| | | + MX8MP_IOMUXC_ECSPI1_MOSI__UART3_DCE_TX 0x82 |
| | | + >; |
| | | + }; |
| | | + |
| | | + pinctrl_flexcan1: flexcan1grp { |
| | | + fsl,pins = < |
| | | + MX8MP_IOMUXC_SPDIF_TX__CAN1_TX 0x154 |
| | | + MX8MP_IOMUXC_SPDIF_RX__CAN1_RX 0x154 |
| | | + >; |
| | | + }; |
| | | + |
| | | + pinctrl_flexcan2: flexcan2grp { |
| | | + fsl,pins = < |
| | | + MX8MP_IOMUXC_SAI5_MCLK__CAN2_RX 0x154 |
| | | + MX8MP_IOMUXC_SAI5_RXD3__CAN2_TX 0x154 |
| | | + >; |
| | | + }; |
| | | + |
| | | + pinctrl_ecspi2: ecspi2grp { |
| | | + fsl,pins = < |
| | | + MX8MP_IOMUXC_ECSPI2_SCLK__ECSPI2_SCLK 0x82 |
| | | + MX8MP_IOMUXC_ECSPI2_MOSI__ECSPI2_MOSI 0x82 |
| | | + MX8MP_IOMUXC_ECSPI2_MISO__ECSPI2_MISO 0x82 |
| | | + MX8MP_IOMUXC_ECSPI2_SS0__GPIO5_IO13 0x40000 |
| | | + >; |
| | | + }; |
| | | + |
| | | + pinctrl_i2c1: i2c1grp { |
| | | + fsl,pins = < |
| | | + MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL 0x400001c3 |
| | |
| | | + >; |
| | | + }; |
| | | + |
| | | + pinctrl_i2c1_gpio: i2c1grp-gpio { |
| | | + pinctrl_i2c2: i2c2grp { |
| | | + fsl,pins = < |
| | | + MX8MP_IOMUXC_I2C1_SCL__GPIO5_IO14 0x1c3 |
| | | + MX8MP_IOMUXC_I2C1_SDA__GPIO5_IO15 0x1c3 |
| | | + MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001c2 |
| | | + MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA 0x400001c2 |
| | | + >; |
| | | + }; |
| | | + |
| | | + pinctrl_i2c5: i2c5grp { |
| | | + fsl,pins = < |
| | | + MX8MP_IOMUXC_SD1_CMD__I2C5_SDA 0x400001c2 |
| | | + MX8MP_IOMUXC_SD1_CLK__I2C5_SCL 0x400001c2 |
| | | + >; |
| | | + }; |
| | | + |
| | |
| | | +}; |
| | | diff --git a/arch/arm64/configs/igkboard-imx8mp_defconfig b/arch/arm64/configs/igkboard-imx8mp_defconfig |
| | | new file mode 100644 |
| | | index 000000000..6b6fe01d9 |
| | | index 000000000..b0f923742 |
| | | --- /dev/null |
| | | +++ b/arch/arm64/configs/igkboard-imx8mp_defconfig |
| | | @@ -0,0 +1,1118 @@ |
| | | @@ -0,0 +1,1103 @@ |
| | | +CONFIG_SYSVIPC=y |
| | | +CONFIG_POSIX_MQUEUE=y |
| | | +CONFIG_AUDIT=y |
| | |
| | | +CONFIG_CGROUP_CPUACCT=y |
| | | +CONFIG_CGROUP_PERF=y |
| | | +CONFIG_CGROUP_BPF=y |
| | | +CONFIG_NAMESPACES=y |
| | | +CONFIG_USER_NS=y |
| | | +CONFIG_SCHED_AUTOGROUP=y |
| | | +CONFIG_RELAY=y |
| | | +CONFIG_BLK_DEV_INITRD=y |
| | | +CONFIG_EXPERT=y |
| | | +CONFIG_KALLSYMS_ALL=y |
| | | +CONFIG_PROFILING=y |
| | | +CONFIG_ARCH_KEEMBAY=y |
| | |
| | | +CONFIG_QRTR_SMD=m |
| | | +CONFIG_QRTR_TUN=m |
| | | +CONFIG_NET_PKTGEN=m |
| | | +CONFIG_CAN=m |
| | | +CONFIG_CAN=y |
| | | +CONFIG_CAN_ISOTP=y |
| | | +CONFIG_BT=y |
| | | +CONFIG_BT_RFCOMM=y |
| | | +CONFIG_BT_RFCOMM_TTY=y |
| | |
| | | +CONFIG_CFG80211_WEXT=y |
| | | +CONFIG_MAC80211=y |
| | | +CONFIG_MAC80211_LEDS=y |
| | | +CONFIG_NET_9P=y |
| | | +CONFIG_NET_9P_VIRTIO=y |
| | | +CONFIG_NFC=m |
| | | +CONFIG_NFC_NCI=m |
| | | +CONFIG_NFC_S3FWRN5_I2C=m |
| | |
| | | +CONFIG_BLK_DEV_NVME=y |
| | | +CONFIG_SRAM=y |
| | | +CONFIG_PCI_ENDPOINT_TEST=y |
| | | +CONFIG_EEPROM_AT24=m |
| | | +CONFIG_EEPROM_AT25=m |
| | | +CONFIG_EEPROM_AT24=y |
| | | +CONFIG_UACCE=m |
| | | +# CONFIG_SCSI_PROC_FS is not set |
| | | +CONFIG_BLK_DEV_SD=y |
| | |
| | | +CONFIG_REALTEK_PHY=y |
| | | +CONFIG_ROCKCHIP_PHY=y |
| | | +CONFIG_VITESSE_PHY=y |
| | | +CONFIG_CAN_FLEXCAN=m |
| | | +CONFIG_CAN_FLEXCAN=y |
| | | +CONFIG_MDIO_BITBANG=y |
| | | +CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y |
| | | +CONFIG_MDIO_BUS_MUX_MMIOREG=y |
| | |
| | | +CONFIG_PINCTRL_IMX8ULP=y |
| | | +CONFIG_PINCTRL_IMX93=y |
| | | +CONFIG_PINCTRL_S32V234=y |
| | | +CONFIG_GPIO_ALTERA=m |
| | | +CONFIG_GPIO_DWAPB=y |
| | | +CONFIG_GPIO_IMX_RPMSG=y |
| | | +CONFIG_GPIO_MB86S7X=y |
| | | +CONFIG_GPIO_MPC8XXX=y |
| | | +CONFIG_GPIO_SYSFS=y |
| | | +CONFIG_GPIO_MXC=y |
| | | +CONFIG_GPIO_PL061=y |
| | | +CONFIG_GPIO_WCD934X=m |
| | | +CONFIG_GPIO_XGENE=y |
| | | +CONFIG_GPIO_MAX732X=y |
| | | +CONFIG_GPIO_PCA953X=y |
| | | +CONFIG_GPIO_PCA953X_IRQ=y |
| | | +CONFIG_GPIO_ADP5585=y |
| | | +CONFIG_GPIO_BD9571MWV=m |
| | | +CONFIG_GPIO_MAX77620=y |
| | | +CONFIG_GPIO_SL28CPLD=m |
| | | +CONFIG_POWER_RESET_BRCMSTB=y |
| | | +CONFIG_POWER_RESET_XGENE=y |
| | | +CONFIG_POWER_RESET_SYSCON=y |
| | |
| | | +CONFIG_RC_DEVICES=y |
| | | +CONFIG_IR_GPIO_CIR=m |
| | | +CONFIG_MEDIA_SUPPORT=y |
| | | +CONFIG_MEDIA_SUPPORT_FILTER=y |
| | | +CONFIG_MEDIA_CAMERA_SUPPORT=y |
| | | +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y |
| | | +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y |
| | |
| | | +CONFIG_BACKLIGHT_PWM=y |
| | | +CONFIG_BACKLIGHT_LP855X=m |
| | | +CONFIG_BACKLIGHT_GPIO=y |
| | | +CONFIG_FRAMEBUFFER_CONSOLE=y |
| | | +CONFIG_LOGO=y |
| | | +# CONFIG_LOGO_LINUX_MONO is not set |
| | | +# CONFIG_LOGO_LINUX_VGA16 is not set |
| | |
| | | +CONFIG_SND_SOC_LPASS_VA_MACRO=m |
| | | +CONFIG_SND_SIMPLE_CARD=y |
| | | +CONFIG_SND_AUDIO_GRAPH_CARD=y |
| | | +CONFIG_HID_A4TECH=y |
| | | +CONFIG_HID_APPLE=y |
| | | +CONFIG_HID_BELKIN=y |
| | | +CONFIG_HID_CHERRY=y |
| | | +CONFIG_HID_CHICONY=y |
| | | +CONFIG_HID_CYPRESS=y |
| | | +CONFIG_HID_EZKEY=y |
| | | +CONFIG_HID_ITE=y |
| | | +CONFIG_HID_KENSINGTON=y |
| | | +CONFIG_HID_LOGITECH=y |
| | | +CONFIG_HID_REDRAGON=y |
| | | +CONFIG_HID_MICROSOFT=y |
| | | +CONFIG_HID_MONTEREY=y |
| | | +CONFIG_HID_MULTITOUCH=m |
| | | +CONFIG_I2C_HID_ACPI=m |
| | | +CONFIG_I2C_HID_OF=m |
| | |
| | | +CONFIG_EDAC_LAYERSCAPE=m |
| | | +CONFIG_EDAC_SYNOPSYS=y |
| | | +CONFIG_RTC_CLASS=y |
| | | +CONFIG_RTC_DRV_DS1307=m |
| | | +CONFIG_RTC_DRV_HYM8563=m |
| | | +CONFIG_RTC_DRV_MAX77686=y |
| | | +CONFIG_RTC_DRV_RK808=m |
| | | +CONFIG_RTC_DRV_PCF85363=m |
| | | +CONFIG_RTC_DRV_M41T80=m |
| | | +CONFIG_RTC_DRV_RX8581=m |
| | | +CONFIG_RTC_DRV_RV3028=m |
| | | +CONFIG_RTC_DRV_RV8803=m |
| | | +CONFIG_RTC_DRV_S5M=y |
| | | +CONFIG_RTC_DRV_DS3232=y |
| | | +CONFIG_RTC_DRV_PCF2127=m |
| | | +CONFIG_RTC_DRV_PCF2131=m |
| | | +CONFIG_RTC_DRV_EFI=y |
| | | +CONFIG_RTC_DRV_CROS_EC=y |
| | | +CONFIG_RTC_DRV_FSL_FTM_ALARM=m |
| | | +CONFIG_RTC_DRV_PL031=y |
| | | +CONFIG_RTC_DRV_SNVS=y |
| | | +CONFIG_RTC_DRV_BBNSM=y |
| | | +CONFIG_RTC_DRV_IMX_SC=y |
| | | +CONFIG_RTC_DRV_IMX_RPMSG=y |
| | | +CONFIG_RTC_DRV_ISL1208=y |
| | | +CONFIG_DMADEVICES=y |
| | | +CONFIG_BCM_SBA_RAID=m |
| | | +CONFIG_FSL_EDMA=y |
| | | +CONFIG_FSL_QDMA=m |
| | | +CONFIG_FSL_EDMA_V3=y |
| | |
| | | +CONFIG_IIO_ST_ACCEL_3AXIS=m |
| | | +CONFIG_IMX8QXP_ADC=y |
| | | +CONFIG_IMX93_ADC=y |
| | | +CONFIG_MAX9611=m |
| | | +CONFIG_QCOM_SPMI_VADC=m |
| | | +CONFIG_QCOM_SPMI_ADC5=m |
| | | +CONFIG_IIO_CROS_EC_SENSORS_CORE=m |
| | | +CONFIG_IIO_CROS_EC_SENSORS=m |
| | | +CONFIG_FXAS21002C=y |
| | | +CONFIG_MS1112=y |
| | | +CONFIG_BMG160=m |
| | | +CONFIG_IIO_ST_GYRO_3AXIS=m |
| | | +CONFIG_MAX30100=m |
| | | +CONFIG_MAX30102=m |
| | | +CONFIG_DHT11=y |
| | | +CONFIG_HDC100X=y |
| | | +CONFIG_HTS221=y |
| | | +CONFIG_FXOS8700_I2C=y |
| | | +CONFIG_RPMSG_IIO_PEDOMETER=m |
| | | +CONFIG_INV_MPU6050_I2C=m |
| | | +CONFIG_IIO_ST_LSM6DSX=y |
| | | +CONFIG_IIO_CROS_EC_LIGHT_PROX=m |
| | | +CONFIG_SENSORS_ISL29018=y |
| | | +CONFIG_VCNL4000=m |
| | | +CONFIG_VCNL4035=m |
| | | +CONFIG_IIO_ST_MAGN_3AXIS=m |
| | | +CONFIG_IIO_CROS_EC_BARO=m |
| | | +CONFIG_MPL3115=y |
| | | +CONFIG_MS5611=m |
| | | +CONFIG_MS5611_I2C=m |
| | |
| | | +CONFIG_EXT2_FS=y |
| | | +CONFIG_EXT3_FS=y |
| | | +CONFIG_EXT4_FS_POSIX_ACL=y |
| | | +CONFIG_BTRFS_FS=m |
| | | +CONFIG_BTRFS_FS_POSIX_ACL=y |
| | | +CONFIG_FANOTIFY=y |
| | | +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y |
| | | +CONFIG_QUOTA=y |
| | |
| | | +CONFIG_CUSE=m |
| | | +CONFIG_OVERLAY_FS=m |
| | | +CONFIG_VFAT_FS=y |
| | | +CONFIG_EXFAT_FS=y |
| | | +CONFIG_NTFS_FS=y |
| | | +CONFIG_NTFS_RW=y |
| | | +CONFIG_NTFS3_FS=y |
| | | +CONFIG_NTFS3_64BIT_CLUSTER=y |
| | | +CONFIG_NTFS3_LZX_XPRESS=y |
| | | +CONFIG_NTFS3_FS_POSIX_ACL=y |
| | | +CONFIG_TMPFS_POSIX_ACL=y |
| | | +CONFIG_HUGETLBFS=y |
| | | +CONFIG_EFIVAR_FS=y |
| | | +CONFIG_JFFS2_FS=y |
| | | +CONFIG_UBIFS_FS=y |
| | | +CONFIG_SQUASHFS=y |
| | | +CONFIG_SQUASHFS_XZ=y |
| | | +CONFIG_NFS_FS=y |
| | | +CONFIG_NFS_V4=y |
| | | +CONFIG_NFS_V4_1=y |
| | | +CONFIG_NFS_V4_2=y |
| | | +CONFIG_ROOT_NFS=y |
| | | +CONFIG_9P_FS=y |
| | | +CONFIG_NLS_CODEPAGE_437=y |
| | | +CONFIG_NLS_CODEPAGE_936=y |
| | | +CONFIG_NLS_CODEPAGE_950=y |
| | | +CONFIG_NLS_CODEPAGE_874=y |
| | | +CONFIG_NLS_ISO8859_1=y |
| | | +CONFIG_NLS_UTF8=y |
| | | +CONFIG_TRUSTED_KEYS=m |
| | | +# CONFIG_TRUSTED_KEYS_TPM is not set |
| | | +# CONFIG_TRUSTED_KEYS_TEE is not set |
| | |
| | | +CONFIG_CRYPTO_CHACHA20POLY1305=m |
| | | +CONFIG_CRYPTO_ECHAINIV=y |
| | | +CONFIG_CRYPTO_TLS=m |
| | | +CONFIG_CRYPTO_BLAKE2B=m |
| | | +CONFIG_CRYPTO_MD4=m |
| | | +CONFIG_CRYPTO_RMD160=m |
| | | +CONFIG_CRYPTO_STREEBOG=m |
| | | +CONFIG_CRYPTO_VMAC=m |
| | | +CONFIG_CRYPTO_WP512=m |
| | | +CONFIG_CRYPTO_XCBC=m |
| | | +CONFIG_CRYPTO_XXHASH=m |
| | | +CONFIG_CRYPTO_LZO=y |
| | | +CONFIG_CRYPTO_ZSTD=y |
| | | +CONFIG_CRYPTO_ANSI_CPRNG=y |
| | | +CONFIG_CRYPTO_USER_API_HASH=m |
| | | +CONFIG_CRYPTO_USER_API_SKCIPHER=m |
| | |
| | | +CONFIG_CRC8=y |
| | | +CONFIG_CMA_SIZE_MBYTES=32 |
| | | +CONFIG_PRINTK_TIME=y |
| | | +CONFIG_DEBUG_KERNEL=y |
| | | +CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y |
| | | +CONFIG_DEBUG_INFO_REDUCED=y |
| | | +CONFIG_MAGIC_SYSRQ=y |
| | |
| | | +CONFIG_CORESIGHT_CPU_DEBUG=m |
| | | +CONFIG_CORESIGHT_CTI=m |
| | | +CONFIG_MEMTEST=y |
| | | diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig |
| | | index 3946eb595..15278c13c 100644 |
| | | --- a/drivers/iio/adc/Kconfig |
| | | +++ b/drivers/iio/adc/Kconfig |
| | | @@ -1164,6 +1164,18 @@ config TI_ADC161S626 |
| | | This driver can also be built as a module. If so, the module will be |
| | | called ti-adc161s626. |
| | | |
| | | +config MS1112 |
| | | + tristate "Ruimeng Technology MS1112 ADC" |
| | | + depends on I2C |
| | | + select IIO_BUFFER |
| | | + select IIO_TRIGGERED_BUFFER |
| | | + help |
| | | + If you say yes here you get support for Ruimeng Technology ADS1015 |
| | | + ADC chip. |
| | | + |
| | | + This driver can also be built as a module. If so, the module will be |
| | | + called ms1112. |
| | | + |
| | | config TI_ADS1015 |
| | | tristate "Texas Instruments ADS1015 ADC" |
| | | depends on I2C |
| | | diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile |
| | | index 83233c38c..f403164cf 100644 |
| | | --- a/drivers/iio/adc/Makefile |
| | | +++ b/drivers/iio/adc/Makefile |
| | | @@ -104,6 +104,7 @@ obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o |
| | | obj-$(CONFIG_TI_ADC108S102) += ti-adc108s102.o |
| | | obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o |
| | | obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o |
| | | +obj-$(CONFIG_MS1112) += ms1112.o |
| | | obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o |
| | | obj-$(CONFIG_TI_ADS7950) += ti-ads7950.o |
| | | obj-$(CONFIG_TI_ADS8344) += ti-ads8344.o |
| | | diff --git a/drivers/iio/adc/ms1112.c b/drivers/iio/adc/ms1112.c |
| | | new file mode 100644 |
| | | index 000000000..cf8ea5c66 |
| | | --- /dev/null |
| | | +++ b/drivers/iio/adc/ms1112.c |
| | | @@ -0,0 +1,569 @@ |
| | | +// SPDX-License-Identifier: GPL-2.0-only |
| | | +/* |
| | | + * MS1112 - Ruimeng Technology Analog-to-Digital Converter |
| | | + * |
| | | + * Copyright (c) 2024, LingYun IoT System Studio. |
| | | + * |
| | | + * IIO driver for MS1112 ADC 7-bit I2C slave address: 0x4A |
| | | + */ |
| | | + |
| | | +#include <linux/init.h> |
| | | +#include <linux/module.h> |
| | | +#include <linux/errno.h> |
| | | +#include <linux/gpio.h> |
| | | +#include <linux/cdev.h> |
| | | +#include <linux/device.h> |
| | | +#include <linux/of_gpio.h> |
| | | +#include <linux/semaphore.h> |
| | | +#include <linux/timer.h> |
| | | +#include <linux/i2c.h> |
| | | +#include <asm/uaccess.h> |
| | | +#include <asm/io.h> |
| | | +#include <linux/iio/iio.h> |
| | | +#include <linux/iio/driver.h> |
| | | + |
| | | +#define MS1112_DRV_NAME "ms1112" |
| | | + |
| | | +#define MS1112_CONV_REG 0x00 |
| | | +#define MS1112_CFG_REG 0x01 |
| | | +#define MS1112_DEFAULT_CONFIG 0xFC |
| | | + |
| | | +#define MS1112_CHANNELS 4 |
| | | +#define MS1112_CFG_DR_SHIFT 2 |
| | | +#define MS1112_CFG_MOD_SHIFT 4 |
| | | +#define MS1112_CFG_PGA_SHIFT 0 |
| | | +#define MS1112_CFG_MUX_SHIFT 5 |
| | | + |
| | | +#define MS1112_CFG_DR_MASK GENMASK(3, 2) |
| | | +#define MS1112_CFG_MOD_MASK BIT(4) |
| | | +#define MS1112_CFG_PGA_MASK GENMASK(1, 0) |
| | | +#define MS1112_CFG_MUX_MASK GENMASK(6, 5) |
| | | + |
| | | +#define MS1112_DEFAULT_PGA 0 |
| | | +#define MS1112_DEFAULT_DATA_RATE 3 |
| | | +#define MS1112_DEFAULT_CHAN 2 |
| | | +#define MS1112_DEFAULT_MODE 1 |
| | | + |
| | | +#define MS1112_CONTINUOUS 0 |
| | | +#define MS1112_SINGLESHOT 1 |
| | | + |
| | | +struct ms1112_chip_data { |
| | | + struct iio_chan_spec const *channels; |
| | | + int num_channels; |
| | | + const struct iio_info *info; |
| | | + const int *data_rate; |
| | | + const int data_rate_len; |
| | | + const int *scale; |
| | | + const int scale_len; |
| | | + bool has_comparator; |
| | | +}; |
| | | + |
| | | +enum ms1112_channels { |
| | | + MS1112_AIN0_AIN1 = 0, |
| | | + MS1112_AIN2, |
| | | + MS1112_AIN0, |
| | | + MS1112_AIN1, |
| | | + MS1112_TIMESTAMP, |
| | | +}; |
| | | + |
| | | +static const int ms1112_data_rate[] = { |
| | | + 240,60,30,15 |
| | | +}; |
| | | + |
| | | +static const int ms1112_fullscale_range[] = { |
| | | + 2048 |
| | | +}; |
| | | + |
| | | +static const int ms1112_scale[] = { /* 12bit ADC */ |
| | | + 2048,11, |
| | | + 2048,13, |
| | | + 2048,14, |
| | | + 2048,15 |
| | | +}; |
| | | + |
| | | +#define FIT_CHECK(_testbits, _fitbits) \ |
| | | + ( \ |
| | | + (_fitbits) * \ |
| | | + !!sizeof(struct { \ |
| | | + static_assert((_testbits) <= (_fitbits)); \ |
| | | + int pad; \ |
| | | + }) \ |
| | | + ) |
| | | + |
| | | +#define MS1112_V_CHAN(_chan, _addr, _realbits, _shift, _event_spec, _num_event_specs) { \ |
| | | + .type = IIO_VOLTAGE, \ |
| | | + .indexed = 1, \ |
| | | + .address = _addr, \ |
| | | + .channel = _chan, \ |
| | | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
| | | + BIT(IIO_CHAN_INFO_SCALE) | \ |
| | | + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ |
| | | + .info_mask_shared_by_all_available = \ |
| | | + BIT(IIO_CHAN_INFO_SCALE) | \ |
| | | + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ |
| | | + .scan_index = _addr, \ |
| | | + .scan_type = { \ |
| | | + .sign = 's', \ |
| | | + .realbits = (_realbits), \ |
| | | + .storagebits = FIT_CHECK((_realbits) + (_shift), 16), \ |
| | | + .shift = (_shift), \ |
| | | + .endianness = IIO_CPU, \ |
| | | + }, \ |
| | | + .event_spec = (_event_spec), \ |
| | | + .num_event_specs = (_num_event_specs), \ |
| | | + .datasheet_name = "AIN"#_chan, \ |
| | | +} |
| | | + |
| | | +#define MS1112_V_DIFF_CHAN(_chan, _chan2, _addr, _realbits, _shift, _event_spec, _num_event_specs) { \ |
| | | + .type = IIO_VOLTAGE, \ |
| | | + .differential = 1, \ |
| | | + .indexed = 1, \ |
| | | + .address = _addr, \ |
| | | + .channel = _chan, \ |
| | | + .channel2 = _chan2, \ |
| | | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
| | | + BIT(IIO_CHAN_INFO_SCALE) | \ |
| | | + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ |
| | | + .info_mask_shared_by_all_available = \ |
| | | + BIT(IIO_CHAN_INFO_SCALE) | \ |
| | | + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ |
| | | + .scan_index = _addr, \ |
| | | + .scan_type = { \ |
| | | + .sign = 's', \ |
| | | + .realbits = (_realbits), \ |
| | | + .storagebits = FIT_CHECK((_realbits) + (_shift), 16), \ |
| | | + .shift = (_shift), \ |
| | | + .endianness = IIO_CPU, \ |
| | | + }, \ |
| | | + .event_spec = (_event_spec), \ |
| | | + .num_event_specs = (_num_event_specs), \ |
| | | + .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \ |
| | | +} |
| | | + |
| | | +struct ms1112_channel_data { |
| | | + bool enabled; |
| | | + unsigned int pga; |
| | | + unsigned int data_rate; |
| | | + unsigned int mode; |
| | | +}; |
| | | + |
| | | +struct ms1112_thresh_data { |
| | | + int high_thresh; |
| | | + int low_thresh; |
| | | +}; |
| | | + |
| | | +struct ms1112_data { |
| | | + struct ms1112_channel_data channel_data[MS1112_CHANNELS]; |
| | | + struct ms1112_thresh_data thresh_data[MS1112_CHANNELS]; |
| | | + const struct ms1112_chip_data *chip; |
| | | + struct mutex lock; |
| | | + void *private_data; |
| | | + struct i2c_client *client; |
| | | +}; |
| | | + |
| | | +/* MS1112 don't use the register address */ |
| | | +static int ms1112_read_regs(struct ms1112_data *dev, uint8_t reg, void *buf, uint8_t size) |
| | | +{ |
| | | + int ret = 0; |
| | | + struct i2c_msg msg[1]; |
| | | + struct i2c_client *client = dev->client; |
| | | + |
| | | + msg[0].addr = client->addr; |
| | | + msg[0].flags = I2C_M_RD; |
| | | + msg[0].buf = buf; |
| | | + msg[0].len = size; |
| | | + |
| | | + ret = i2c_transfer(client->adapter, msg, 1); |
| | | + if(ret != 1) { |
| | | + dev_err(&dev->client->dev, "%s() i2c_transfer error, ret=%d\n", __func__, ret); |
| | | + ret = -EREMOTEIO; |
| | | + } |
| | | + |
| | | + return ret; |
| | | +} |
| | | + |
| | | +/* MS1112 don't use the register address */ |
| | | +static s32 ms1112_write_regs(struct ms1112_data *dev, uint8_t reg, uint8_t *data, uint8_t bytes) |
| | | +{ |
| | | + int ret = 0; |
| | | + struct i2c_msg msg; |
| | | + struct i2c_client *client = dev->client; |
| | | + |
| | | + msg.addr = client->addr; |
| | | + msg.flags = 0; |
| | | + msg.buf = data; |
| | | + msg.len = bytes; |
| | | + |
| | | + ret = i2c_transfer(client->adapter, &msg, 1); |
| | | + if(ret != 1) { |
| | | + dev_err(&dev->client->dev, "%s() i2c_transfer error, ret=%d\n", __func__, ret); |
| | | + ret = -EREMOTEIO; |
| | | + } |
| | | + |
| | | + return ret; |
| | | +} |
| | | + |
| | | +static int ms1112_readdata(struct ms1112_data *dev,unsigned int *val) |
| | | +{ |
| | | + unsigned char buf[3]; |
| | | + unsigned char rx_data[3]; |
| | | + int rv = 0; |
| | | + |
| | | + rv = ms1112_read_regs(dev, MS1112_CONV_REG, rx_data, 3); |
| | | + if(rv<0) { |
| | | + return rv; |
| | | + } |
| | | + |
| | | + buf[0] = rx_data[0]; |
| | | + buf[1] = rx_data[1]; |
| | | + buf[2] = rx_data[2]; |
| | | + |
| | | + *val = (buf[0]<<8) | buf[1]; |
| | | + return rv; |
| | | +} |
| | | + |
| | | +static int ms1112_get_adc_result(struct ms1112_data *data, int chan, int *val) |
| | | +{ |
| | | + int ret = 0; |
| | | + int pga, dr , mode; |
| | | + uint8_t mask, cfg; |
| | | + |
| | | + if (chan < 0 || chan >= MS1112_CHANNELS) |
| | | + return -EINVAL; |
| | | + |
| | | + mode = data->channel_data[chan].mode; |
| | | + pga = data->channel_data[chan].pga; |
| | | + dr = data->channel_data[chan].data_rate; |
| | | + |
| | | + mask = MS1112_CFG_MUX_MASK | MS1112_CFG_PGA_MASK | |
| | | + MS1112_CFG_DR_MASK | MS1112_CFG_MOD_MASK | MS1112_SINGLESHOT << 7; |
| | | + |
| | | + cfg = chan << MS1112_CFG_MUX_SHIFT | pga << MS1112_CFG_PGA_SHIFT | |
| | | + dr << MS1112_CFG_DR_SHIFT | mode << MS1112_CFG_MOD_SHIFT | MS1112_SINGLESHOT << 7; |
| | | + |
| | | + cfg = (cfg & mask); |
| | | + |
| | | + ms1112_write_regs(data, MS1112_CFG_REG, &cfg, 1); |
| | | + |
| | | + ret = ms1112_readdata(data,val); |
| | | + return ret; |
| | | +} |
| | | + |
| | | +static int ms1112_set_scale(struct ms1112_data *data, struct iio_chan_spec const *chan, |
| | | + int scale, int uscale) |
| | | +{ |
| | | + int i; |
| | | + int fullscale = div_s64((scale * 1000000LL + uscale) << |
| | | + (chan->scan_type.realbits - 1), 1000000); |
| | | + |
| | | + for (i = 0; i < ARRAY_SIZE(ms1112_fullscale_range); i++) { |
| | | + if (ms1112_fullscale_range[i] == fullscale) { |
| | | + data->channel_data[chan->address].pga = i; |
| | | + return 0; |
| | | + } |
| | | + } |
| | | + |
| | | + return -EINVAL; |
| | | +} |
| | | + |
| | | +static int ms1112_set_data_rate(struct ms1112_data *data, int chan, int rate) |
| | | +{ |
| | | + int i; |
| | | + |
| | | + for (i = 0; i < data->chip->data_rate_len; i++) { |
| | | + if (data->chip->data_rate[i] == rate) { |
| | | + data->channel_data[chan].data_rate = i; |
| | | + return 0; |
| | | + } |
| | | + } |
| | | + |
| | | + return -EINVAL; |
| | | +} |
| | | + |
| | | +static int ms1112_read_avail(struct iio_dev *indio_dev, |
| | | + struct iio_chan_spec const *chan, |
| | | + const int **vals, int *type, int *length, |
| | | + long mask) |
| | | +{ |
| | | + struct ms1112_data *data = iio_priv(indio_dev); |
| | | + |
| | | + if (chan->type != IIO_VOLTAGE) |
| | | + return -EINVAL; |
| | | + |
| | | + switch (mask) { |
| | | + case IIO_CHAN_INFO_SCALE: |
| | | + *type = IIO_VAL_FRACTIONAL_LOG2; |
| | | + *vals = data->chip->scale; |
| | | + *length = data->chip->scale_len; |
| | | + return IIO_AVAIL_LIST; |
| | | + case IIO_CHAN_INFO_SAMP_FREQ: |
| | | + *type = IIO_VAL_INT; |
| | | + *vals = data->chip->data_rate; |
| | | + *length = data->chip->data_rate_len; |
| | | + return IIO_AVAIL_LIST; |
| | | + default: |
| | | + return -EINVAL; |
| | | + } |
| | | +} |
| | | + |
| | | +static int ms1112_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) |
| | | +{ |
| | | + int ret, idx; |
| | | + struct ms1112_data *data = iio_priv(indio_dev); |
| | | + |
| | | + mutex_lock(&data->lock); |
| | | + switch (mask) { |
| | | + case IIO_CHAN_INFO_RAW: |
| | | + |
| | | + ret = iio_device_claim_direct_mode(indio_dev); |
| | | + if (ret) |
| | | + break; |
| | | + |
| | | + ret = ms1112_get_adc_result(data, chan->address, val); |
| | | + if (ret < 0) { |
| | | + goto release_direct; |
| | | + } |
| | | + |
| | | + *val = sign_extend32(*val >> chan->scan_type.shift, |
| | | + chan->scan_type.realbits - 1); |
| | | + |
| | | + ret = IIO_VAL_INT; |
| | | +release_direct: |
| | | + iio_device_release_direct_mode(indio_dev); |
| | | + break; |
| | | + |
| | | + case IIO_CHAN_INFO_SCALE: |
| | | + idx = data->channel_data[chan->address].pga; |
| | | + *val = ms1112_fullscale_range[idx]; |
| | | + *val2 = chan->scan_type.realbits - 1; |
| | | + ret = IIO_VAL_FRACTIONAL_LOG2; |
| | | + break; |
| | | + case IIO_CHAN_INFO_SAMP_FREQ: |
| | | + idx = data->channel_data[chan->address].data_rate; |
| | | + *val = data->chip->data_rate[idx]; |
| | | + ret = IIO_VAL_INT; |
| | | + break; |
| | | + default: |
| | | + ret = -EINVAL; |
| | | + break; |
| | | + } |
| | | + mutex_unlock(&data->lock); |
| | | + |
| | | + return ret; |
| | | +} |
| | | + |
| | | +static int ms1112_write_raw(struct iio_dev *indio_dev, |
| | | + struct iio_chan_spec const *chan, int val, |
| | | + int val2, long mask) |
| | | +{ |
| | | + struct ms1112_data *data = iio_priv(indio_dev); |
| | | + int ret; |
| | | + |
| | | + mutex_lock(&data->lock); |
| | | + switch (mask) { |
| | | + case IIO_CHAN_INFO_SCALE: |
| | | + ret = ms1112_set_scale(data, chan, val, val2); |
| | | + break; |
| | | + case IIO_CHAN_INFO_SAMP_FREQ: |
| | | + ret = ms1112_set_data_rate(data, chan->address, val); |
| | | + break; |
| | | + default: |
| | | + ret = -EINVAL; |
| | | + break; |
| | | + } |
| | | + mutex_unlock(&data->lock); |
| | | + |
| | | + return ret; |
| | | +} |
| | | + |
| | | +static const struct iio_info ms1112_info = { |
| | | + .read_raw = ms1112_read_raw, |
| | | + .write_raw = ms1112_write_raw, |
| | | + .read_avail = ms1112_read_avail, |
| | | +}; |
| | | + |
| | | + |
| | | +static const struct iio_chan_spec ms1112_channels[] = { |
| | | + MS1112_V_DIFF_CHAN(0, 1, MS1112_AIN0_AIN1, 16, 0, NULL, 0), |
| | | + MS1112_V_CHAN(2, MS1112_AIN2, 16, 0, NULL, 0), |
| | | + MS1112_V_CHAN(0, MS1112_AIN0, 16, 0, NULL, 0), |
| | | + MS1112_V_CHAN(1, MS1112_AIN1, 16, 0, NULL, 0), |
| | | + IIO_CHAN_SOFT_TIMESTAMP(MS1112_TIMESTAMP), |
| | | +}; |
| | | + |
| | | +static int ms1112_client_get_channels_config(struct i2c_client *client) |
| | | +{ |
| | | + struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| | | + struct ms1112_data *data = iio_priv(indio_dev); |
| | | + struct device *dev = &client->dev; |
| | | + struct fwnode_handle *node; |
| | | + int i = -1; |
| | | + |
| | | + device_for_each_child_node(dev, node) { |
| | | + u32 pval; |
| | | + unsigned int channel; |
| | | + unsigned int pga = MS1112_DEFAULT_PGA; |
| | | + unsigned int data_rate = MS1112_DEFAULT_DATA_RATE; |
| | | + unsigned int mode = MS1112_DEFAULT_MODE; |
| | | + |
| | | + if (fwnode_property_read_u32(node, "reg", &pval)) { |
| | | + dev_err(dev, "invalid reg on %pfw\n", node); |
| | | + continue; |
| | | + } |
| | | + |
| | | + channel = pval; |
| | | + if (channel >= MS1112_CHANNELS) { |
| | | + dev_err(dev, "invalid channel index %d on %pfw\n", |
| | | + channel, node); |
| | | + continue; |
| | | + } |
| | | + |
| | | + if (!fwnode_property_read_u32(node, "ti,gain", &pval)) { |
| | | + pga = pval; |
| | | + if (pga > 3 ) { |
| | | + dev_err(dev, "invalid gain on %pfw\n", node); |
| | | + fwnode_handle_put(node); |
| | | + return -EINVAL; |
| | | + } |
| | | + } |
| | | + |
| | | + if (!fwnode_property_read_u32(node, "ti,datarate", &pval)) { |
| | | + data_rate = pval; |
| | | + if (data_rate > 3) { |
| | | + dev_err(dev, "invalid data_rate on %pfw\n", node); |
| | | + fwnode_handle_put(node); |
| | | + return -EINVAL; |
| | | + } |
| | | + } |
| | | + |
| | | + if (!fwnode_property_read_u32(node, "ti,mode", &pval)) { |
| | | + mode = pval; |
| | | + if (mode > 1) { |
| | | + dev_err(dev, "invalid mode on %pfw\n", node); |
| | | + fwnode_handle_put(node); |
| | | + return -EINVAL; |
| | | + } |
| | | + } |
| | | + |
| | | + |
| | | + data->channel_data[channel].pga = pga; |
| | | + data->channel_data[channel].data_rate = data_rate; |
| | | + data->channel_data[channel].mode = mode; |
| | | + i++; |
| | | + } |
| | | + |
| | | + return i < 0 ? -EINVAL : 0; |
| | | +} |
| | | + |
| | | +static void ms1112_get_channels_config(struct i2c_client *client) |
| | | +{ |
| | | + unsigned int k; |
| | | + |
| | | + struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| | | + struct ms1112_data *data = iio_priv(indio_dev); |
| | | + |
| | | + if (!ms1112_client_get_channels_config(client)) |
| | | + return; |
| | | + |
| | | + /* fallback on default configuration */ |
| | | + for (k = 0; k < MS1112_CHANNELS; ++k) { |
| | | + data->channel_data[k].pga = MS1112_DEFAULT_PGA; |
| | | + data->channel_data[k].data_rate = MS1112_DEFAULT_DATA_RATE; |
| | | + data->channel_data[k].mode = MS1112_DEFAULT_MODE; |
| | | + } |
| | | +} |
| | | + |
| | | +static int ms1112_probe(struct i2c_client *client,const struct i2c_device_id *id) |
| | | +{ |
| | | + struct iio_dev *indio_dev; |
| | | + const struct ms1112_chip_data *chip; |
| | | + struct ms1112_data *data; |
| | | + int ret; |
| | | + int i; |
| | | + |
| | | + chip = device_get_match_data(&client->dev); |
| | | + if (!chip) |
| | | + chip = (const struct ms1112_chip_data *)id->driver_data; |
| | | + if (!chip) |
| | | + return dev_err_probe(&client->dev, -EINVAL, "Unknown chip\n"); |
| | | + |
| | | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*indio_dev)); |
| | | + if (!indio_dev) |
| | | + return -ENOMEM; |
| | | + |
| | | + data = iio_priv(indio_dev); |
| | | + i2c_set_clientdata(client, indio_dev); |
| | | + |
| | | + mutex_init(&data->lock); |
| | | + |
| | | + indio_dev->name = MS1112_DRV_NAME; |
| | | + indio_dev->info = chip->info; |
| | | + indio_dev->modes = INDIO_DIRECT_MODE; |
| | | + indio_dev->channels = chip->channels; |
| | | + indio_dev->num_channels = chip->num_channels; |
| | | + data->chip = chip; |
| | | + data->client = client; |
| | | + |
| | | + for (i = 0; i < MS1112_CHANNELS; i++) { |
| | | + int realbits = indio_dev->channels[i].scan_type.realbits; |
| | | + |
| | | + data->thresh_data[i].low_thresh = -1 << (realbits - 1); |
| | | + data->thresh_data[i].high_thresh = (1 << (realbits - 1)) - 1; |
| | | + } |
| | | + |
| | | + /* we need to keep this ABI the same as used by hwmon ADS1015 driver */ |
| | | + ms1112_get_channels_config(client); |
| | | + |
| | | + ret = iio_device_register(indio_dev); |
| | | + if (ret) |
| | | + dev_err(&client->dev, "Failed to register IIO device\n"); |
| | | + return ret; |
| | | +} |
| | | + |
| | | +static void ms1112_remove(struct i2c_client *client) |
| | | +{ |
| | | + struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| | | + |
| | | + iio_device_unregister(indio_dev); |
| | | + |
| | | +} |
| | | + |
| | | +static const struct ms1112_chip_data ms1112_data = { |
| | | + .channels = ms1112_channels, |
| | | + .num_channels = ARRAY_SIZE(ms1112_channels), |
| | | + .info = &ms1112_info, |
| | | + .data_rate = ms1112_data_rate, |
| | | + .data_rate_len = ARRAY_SIZE(ms1112_data_rate), |
| | | + .scale = ms1112_scale, |
| | | + .scale_len = ARRAY_SIZE(ms1112_scale), |
| | | + .has_comparator = false, |
| | | +}; |
| | | + |
| | | +static const struct i2c_device_id ms1112_id[] = { |
| | | + { "ms1112", (kernel_ulong_t)&ms1112_data }, |
| | | + {} |
| | | +}; |
| | | +MODULE_DEVICE_TABLE(i2c, ms1112_id); |
| | | + |
| | | +static const struct of_device_id ms1112_of_match[] = { |
| | | + { .compatible = "ms,ms1112" }, |
| | | + { }, |
| | | +}; |
| | | +MODULE_DEVICE_TABLE(of, ms1112_of_match); |
| | | + |
| | | +static struct i2c_driver ms1112_driver = { |
| | | + .driver = { |
| | | + .owner = THIS_MODULE, |
| | | + .name = "ms1112", |
| | | + .of_match_table = ms1112_of_match, |
| | | + }, |
| | | + .probe = ms1112_probe, |
| | | + .remove = ms1112_remove, |
| | | + .id_table = ms1112_id, |
| | | +}; |
| | | + |
| | | +module_i2c_driver(ms1112_driver); |
| | | + |
| | | +MODULE_AUTHOR("Tang Junfeng"); |
| | | +MODULE_DESCRIPTION("MS1112 IIO ADC Driver"); |
| | | +MODULE_LICENSE("GPL"); |