55 * Quentin Schulz <quentin.schulz@free-electrons.com>
66 */
77
8+ #include <asm/unaligned.h>
89#include <linux/bitfield.h>
910#include <linux/completion.h>
1011#include <linux/interrupt.h>
3031
3132#define AXP22X_ADC_EN1_MASK (GENMASK(7, 5) | BIT(0))
3233
34+ #define AXP717_ADC_EN1_MASK GENMASK(7, 0)
35+
3336#define AXP192_GPIO30_IN_RANGE_GPIO0 BIT(0)
3437#define AXP192_GPIO30_IN_RANGE_GPIO1 BIT(1)
3538#define AXP192_GPIO30_IN_RANGE_GPIO2 BIT(2)
4346
4447#define AXP22X_ADC_RATE_HZ (x ) ((ilog2((x) / 100) << 6) & AXP20X_ADC_RATE_MASK)
4548
49+ #define AXP717_ADC_DATA_TS 0x00
50+ #define AXP717_ADC_DATA_TEMP 0x01
51+ #define AXP717_ADC_DATA_VMID 0x02
52+ #define AXP717_ADC_DATA_BKUP_BATT 0x03
53+
54+ #define AXP717_ADC_DATA_MASK GENMASK(13, 0)
55+
4656#define AXP813_V_I_ADC_RATE_MASK GENMASK(5, 4)
4757#define AXP813_ADC_RATE_MASK (AXP20X_ADC_RATE_MASK | AXP813_V_I_ADC_RATE_MASK)
4858#define AXP813_TS_GPIO0_ADC_RATE_HZ (x ) AXP20X_ADC_RATE_HZ(x)
@@ -125,6 +135,20 @@ enum axp22x_adc_channel_i {
125135 AXP22X_BATT_DISCHRG_I ,
126136};
127137
138+ enum axp717_adc_channel_v {
139+ AXP717_BATT_V = 0 ,
140+ AXP717_TS_IN ,
141+ AXP717_VBUS_V ,
142+ AXP717_VSYS_V ,
143+ AXP717_DIE_TEMP_V ,
144+ AXP717_VMID_V = 6 ,
145+ AXP717_BKUP_BATT_V ,
146+ };
147+
148+ enum axp717_adc_channel_i {
149+ AXP717_BATT_CHRG_I = 5 ,
150+ };
151+
128152enum axp813_adc_channel_v {
129153 AXP813_TS_IN = 0 ,
130154 AXP813_GPIO0_V ,
@@ -179,6 +203,22 @@ static struct iio_map axp22x_maps[] = {
179203 }, { /* sentinel */ }
180204};
181205
206+ static struct iio_map axp717_maps [] = {
207+ {
208+ .consumer_dev_name = "axp20x-usb-power-supply" ,
209+ .consumer_channel = "vbus_v" ,
210+ .adc_channel_label = "vbus_v" ,
211+ }, {
212+ .consumer_dev_name = "axp20x-battery-power-supply" ,
213+ .consumer_channel = "batt_v" ,
214+ .adc_channel_label = "batt_v" ,
215+ }, {
216+ .consumer_dev_name = "axp20x-battery-power-supply" ,
217+ .consumer_channel = "batt_chrg_i" ,
218+ .adc_channel_label = "batt_chrg_i" ,
219+ },
220+ };
221+
182222/*
183223 * Channels are mapped by physical system. Their channels share the same index.
184224 * i.e. acin_i is in_current0_raw and acin_v is in_voltage0_raw.
@@ -274,6 +314,29 @@ static const struct iio_chan_spec axp22x_adc_channels[] = {
274314 AXP22X_TS_ADC_H ),
275315};
276316
317+ /*
318+ * Scale and offset is unknown for temp, ts, batt_chrg_i, vmid_v, and
319+ * bkup_batt_v channels. Leaving scale and offset undefined for now.
320+ */
321+ static const struct iio_chan_spec axp717_adc_channels [] = {
322+ AXP20X_ADC_CHANNEL (AXP717_BATT_V , "batt_v" , IIO_VOLTAGE ,
323+ AXP717_BATT_V_H ),
324+ AXP20X_ADC_CHANNEL (AXP717_TS_IN , "ts_v" , IIO_VOLTAGE ,
325+ AXP717_ADC_DATA_H ),
326+ AXP20X_ADC_CHANNEL (AXP717_VBUS_V , "vbus_v" , IIO_VOLTAGE ,
327+ AXP717_VBUS_V_H ),
328+ AXP20X_ADC_CHANNEL (AXP717_VSYS_V , "vsys_v" , IIO_VOLTAGE ,
329+ AXP717_VSYS_V_H ),
330+ AXP20X_ADC_CHANNEL (AXP717_DIE_TEMP_V , "pmic_temp" , IIO_TEMP ,
331+ AXP717_ADC_DATA_H ),
332+ AXP20X_ADC_CHANNEL (AXP717_BATT_CHRG_I , "batt_chrg_i" , IIO_CURRENT ,
333+ AXP717_BATT_CHRG_I_H ),
334+ AXP20X_ADC_CHANNEL (AXP717_VMID_V , "vmid_v" , IIO_VOLTAGE ,
335+ AXP717_ADC_DATA_H ),
336+ AXP20X_ADC_CHANNEL (AXP717_BKUP_BATT_V , "bkup_batt_v" , IIO_VOLTAGE ,
337+ AXP717_ADC_DATA_H ),
338+ };
339+
277340static const struct iio_chan_spec axp813_adc_channels [] = {
278341 {
279342 .type = IIO_TEMP ,
@@ -354,6 +417,51 @@ static int axp22x_adc_raw(struct iio_dev *indio_dev,
354417 return IIO_VAL_INT ;
355418}
356419
420+ static int axp717_adc_raw (struct iio_dev * indio_dev ,
421+ struct iio_chan_spec const * chan , int * val )
422+ {
423+ struct axp20x_adc_iio * info = iio_priv (indio_dev );
424+ u8 bulk_reg [2 ];
425+ int ret ;
426+
427+ /*
428+ * A generic "ADC data" channel is used for TS, tdie, vmid,
429+ * and vbackup. This channel must both first be enabled and
430+ * also selected before it can be read.
431+ */
432+ switch (chan -> channel ) {
433+ case AXP717_TS_IN :
434+ regmap_write (info -> regmap , AXP717_ADC_DATA_SEL ,
435+ AXP717_ADC_DATA_TS );
436+ break ;
437+ case AXP717_DIE_TEMP_V :
438+ regmap_write (info -> regmap , AXP717_ADC_DATA_SEL ,
439+ AXP717_ADC_DATA_TEMP );
440+ break ;
441+ case AXP717_VMID_V :
442+ regmap_write (info -> regmap , AXP717_ADC_DATA_SEL ,
443+ AXP717_ADC_DATA_VMID );
444+ break ;
445+ case AXP717_BKUP_BATT_V :
446+ regmap_write (info -> regmap , AXP717_ADC_DATA_SEL ,
447+ AXP717_ADC_DATA_BKUP_BATT );
448+ break ;
449+ default :
450+ break ;
451+ }
452+
453+ /*
454+ * All channels are 14 bits, with the first 2 bits on the high
455+ * register reserved and the remaining bits as the ADC value.
456+ */
457+ ret = regmap_bulk_read (info -> regmap , chan -> address , bulk_reg , 2 );
458+ if (ret < 0 )
459+ return ret ;
460+
461+ * val = FIELD_GET (AXP717_ADC_DATA_MASK , get_unaligned_be16 (bulk_reg ));
462+ return IIO_VAL_INT ;
463+ }
464+
357465static int axp813_adc_raw (struct iio_dev * indio_dev ,
358466 struct iio_chan_spec const * chan , int * val )
359467{
@@ -571,6 +679,27 @@ static int axp22x_adc_scale(struct iio_chan_spec const *chan, int *val,
571679 }
572680}
573681
682+ static int axp717_adc_scale (struct iio_chan_spec const * chan , int * val ,
683+ int * val2 )
684+ {
685+ switch (chan -> type ) {
686+ case IIO_VOLTAGE :
687+ * val = 1 ;
688+ return IIO_VAL_INT ;
689+
690+ case IIO_CURRENT :
691+ * val = 1 ;
692+ return IIO_VAL_INT ;
693+
694+ case IIO_TEMP :
695+ * val = 100 ;
696+ return IIO_VAL_INT ;
697+
698+ default :
699+ return - EINVAL ;
700+ }
701+ }
702+
574703static int axp813_adc_scale (struct iio_chan_spec const * chan , int * val ,
575704 int * val2 )
576705{
@@ -746,6 +875,22 @@ static int axp22x_read_raw(struct iio_dev *indio_dev,
746875 }
747876}
748877
878+ static int axp717_read_raw (struct iio_dev * indio_dev ,
879+ struct iio_chan_spec const * chan , int * val ,
880+ int * val2 , long mask )
881+ {
882+ switch (mask ) {
883+ case IIO_CHAN_INFO_SCALE :
884+ return axp717_adc_scale (chan , val , val2 );
885+
886+ case IIO_CHAN_INFO_RAW :
887+ return axp717_adc_raw (indio_dev , chan , val );
888+
889+ default :
890+ return - EINVAL ;
891+ }
892+ }
893+
749894static int axp813_read_raw (struct iio_dev * indio_dev ,
750895 struct iio_chan_spec const * chan , int * val ,
751896 int * val2 , long mask )
@@ -860,6 +1005,10 @@ static const struct iio_info axp22x_adc_iio_info = {
8601005 .read_raw = axp22x_read_raw ,
8611006};
8621007
1008+ static const struct iio_info axp717_adc_iio_info = {
1009+ .read_raw = axp717_read_raw ,
1010+ };
1011+
8631012static const struct iio_info axp813_adc_iio_info = {
8641013 .read_raw = axp813_read_raw ,
8651014};
@@ -930,6 +1079,15 @@ static const struct axp_data axp22x_data = {
9301079 .maps = axp22x_maps ,
9311080};
9321081
1082+ static const struct axp_data axp717_data = {
1083+ .iio_info = & axp717_adc_iio_info ,
1084+ .num_channels = ARRAY_SIZE (axp717_adc_channels ),
1085+ .channels = axp717_adc_channels ,
1086+ .adc_en1 = AXP717_ADC_CH_EN_CONTROL ,
1087+ .adc_en1_mask = AXP717_ADC_EN1_MASK ,
1088+ .maps = axp717_maps ,
1089+ };
1090+
9331091static const struct axp_data axp813_data = {
9341092 .iio_info = & axp813_adc_iio_info ,
9351093 .num_channels = ARRAY_SIZE (axp813_adc_channels ),
@@ -944,6 +1102,7 @@ static const struct of_device_id axp20x_adc_of_match[] = {
9441102 { .compatible = "x-powers,axp192-adc" , .data = (void * )& axp192_data , },
9451103 { .compatible = "x-powers,axp209-adc" , .data = (void * )& axp20x_data , },
9461104 { .compatible = "x-powers,axp221-adc" , .data = (void * )& axp22x_data , },
1105+ { .compatible = "x-powers,axp717-adc" , .data = (void * )& axp717_data , },
9471106 { .compatible = "x-powers,axp813-adc" , .data = (void * )& axp813_data , },
9481107 { /* sentinel */ }
9491108};
@@ -953,6 +1112,7 @@ static const struct platform_device_id axp20x_adc_id_match[] = {
9531112 { .name = "axp192-adc" , .driver_data = (kernel_ulong_t )& axp192_data , },
9541113 { .name = "axp20x-adc" , .driver_data = (kernel_ulong_t )& axp20x_data , },
9551114 { .name = "axp22x-adc" , .driver_data = (kernel_ulong_t )& axp22x_data , },
1115+ { .name = "axp717-adc" , .driver_data = (kernel_ulong_t )& axp717_data , },
9561116 { .name = "axp813-adc" , .driver_data = (kernel_ulong_t )& axp813_data , },
9571117 { /* sentinel */ },
9581118};
0 commit comments