diff options
author | Lee Jones <lee.jones@linaro.org> | 2013-02-26 05:06:55 -0500 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2013-03-06 23:27:14 -0500 |
commit | 734823462590335cbf5c6a1fa5cae84a881dcb43 (patch) | |
tree | 3085b4de4198728b1da9e32a4be8d5b1fdd4e0ba /drivers/mfd | |
parent | d89cc5aad109d20d10d228ba52d86e0adca62461 (diff) |
mfd: ab8500-gpadc: Add gpadc hw conversion
Add the support of gpacd hw conversion and make the number of
sample configurable.
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@stericsson.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Reviewed-by: Mattias WALLIN <mattias.wallin@stericsson.com>
Tested-by: Michel JAOUEN <michel.jaouen@stericsson.com>
Acked-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/ab8500-debugfs.c | 292 | ||||
-rw-r--r-- | drivers/mfd/ab8500-gpadc.c | 282 |
2 files changed, 473 insertions, 101 deletions
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 45fe3c50eb03..59ecd8c680ed 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c | |||
@@ -101,6 +101,11 @@ static int num_irqs; | |||
101 | static struct device_attribute **dev_attr; | 101 | static struct device_attribute **dev_attr; |
102 | static char **event_name; | 102 | static char **event_name; |
103 | 103 | ||
104 | static u8 avg_sample = SAMPLE_16; | ||
105 | static u8 trig_edge = RISING_EDGE; | ||
106 | static u8 conv_type = ADC_SW; | ||
107 | static u8 trig_timer; | ||
108 | |||
104 | /** | 109 | /** |
105 | * struct ab8500_reg_range | 110 | * struct ab8500_reg_range |
106 | * @first: the first address of the range | 111 | * @first: the first address of the range |
@@ -808,9 +813,10 @@ static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p) | |||
808 | struct ab8500_gpadc *gpadc; | 813 | struct ab8500_gpadc *gpadc; |
809 | 814 | ||
810 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 815 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
811 | bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL); | 816 | bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL, |
817 | avg_sample, trig_edge, trig_timer, conv_type); | ||
812 | bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, | 818 | bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, |
813 | BAT_CTRL, bat_ctrl_raw); | 819 | BAT_CTRL, bat_ctrl_raw); |
814 | 820 | ||
815 | return seq_printf(s, "%d,0x%X\n", | 821 | return seq_printf(s, "%d,0x%X\n", |
816 | bat_ctrl_convert, bat_ctrl_raw); | 822 | bat_ctrl_convert, bat_ctrl_raw); |
@@ -836,9 +842,10 @@ static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p) | |||
836 | struct ab8500_gpadc *gpadc; | 842 | struct ab8500_gpadc *gpadc; |
837 | 843 | ||
838 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 844 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
839 | btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL); | 845 | btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL, |
846 | avg_sample, trig_edge, trig_timer, conv_type); | ||
840 | btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL, | 847 | btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL, |
841 | btemp_ball_raw); | 848 | btemp_ball_raw); |
842 | 849 | ||
843 | return seq_printf(s, | 850 | return seq_printf(s, |
844 | "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw); | 851 | "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw); |
@@ -865,9 +872,10 @@ static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p) | |||
865 | struct ab8500_gpadc *gpadc; | 872 | struct ab8500_gpadc *gpadc; |
866 | 873 | ||
867 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 874 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
868 | main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V); | 875 | main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V, |
876 | avg_sample, trig_edge, trig_timer, conv_type); | ||
869 | main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, | 877 | main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, |
870 | MAIN_CHARGER_V, main_charger_v_raw); | 878 | MAIN_CHARGER_V, main_charger_v_raw); |
871 | 879 | ||
872 | return seq_printf(s, "%d,0x%X\n", | 880 | return seq_printf(s, "%d,0x%X\n", |
873 | main_charger_v_convert, main_charger_v_raw); | 881 | main_charger_v_convert, main_charger_v_raw); |
@@ -895,9 +903,10 @@ static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p) | |||
895 | struct ab8500_gpadc *gpadc; | 903 | struct ab8500_gpadc *gpadc; |
896 | 904 | ||
897 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 905 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
898 | acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1); | 906 | acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1, |
907 | avg_sample, trig_edge, trig_timer, conv_type); | ||
899 | acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1, | 908 | acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1, |
900 | acc_detect1_raw); | 909 | acc_detect1_raw); |
901 | 910 | ||
902 | return seq_printf(s, "%d,0x%X\n", | 911 | return seq_printf(s, "%d,0x%X\n", |
903 | acc_detect1_convert, acc_detect1_raw); | 912 | acc_detect1_convert, acc_detect1_raw); |
@@ -925,9 +934,10 @@ static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p) | |||
925 | struct ab8500_gpadc *gpadc; | 934 | struct ab8500_gpadc *gpadc; |
926 | 935 | ||
927 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 936 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
928 | acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2); | 937 | acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2, |
938 | avg_sample, trig_edge, trig_timer, conv_type); | ||
929 | acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc, | 939 | acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc, |
930 | ACC_DETECT2, acc_detect2_raw); | 940 | ACC_DETECT2, acc_detect2_raw); |
931 | 941 | ||
932 | return seq_printf(s, "%d,0x%X\n", | 942 | return seq_printf(s, "%d,0x%X\n", |
933 | acc_detect2_convert, acc_detect2_raw); | 943 | acc_detect2_convert, acc_detect2_raw); |
@@ -955,9 +965,10 @@ static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p) | |||
955 | struct ab8500_gpadc *gpadc; | 965 | struct ab8500_gpadc *gpadc; |
956 | 966 | ||
957 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 967 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
958 | aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1); | 968 | aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1, |
969 | avg_sample, trig_edge, trig_timer, conv_type); | ||
959 | aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1, | 970 | aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1, |
960 | aux1_raw); | 971 | aux1_raw); |
961 | 972 | ||
962 | return seq_printf(s, "%d,0x%X\n", | 973 | return seq_printf(s, "%d,0x%X\n", |
963 | aux1_convert, aux1_raw); | 974 | aux1_convert, aux1_raw); |
@@ -983,9 +994,10 @@ static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p) | |||
983 | struct ab8500_gpadc *gpadc; | 994 | struct ab8500_gpadc *gpadc; |
984 | 995 | ||
985 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 996 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
986 | aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2); | 997 | aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2, |
998 | avg_sample, trig_edge, trig_timer, conv_type); | ||
987 | aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2, | 999 | aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2, |
988 | aux2_raw); | 1000 | aux2_raw); |
989 | 1001 | ||
990 | return seq_printf(s, "%d,0x%X\n", | 1002 | return seq_printf(s, "%d,0x%X\n", |
991 | aux2_convert, aux2_raw); | 1003 | aux2_convert, aux2_raw); |
@@ -1011,9 +1023,10 @@ static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p) | |||
1011 | struct ab8500_gpadc *gpadc; | 1023 | struct ab8500_gpadc *gpadc; |
1012 | 1024 | ||
1013 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1025 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1014 | main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V); | 1026 | main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V, |
1027 | avg_sample, trig_edge, trig_timer, conv_type); | ||
1015 | main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V, | 1028 | main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V, |
1016 | main_bat_v_raw); | 1029 | main_bat_v_raw); |
1017 | 1030 | ||
1018 | return seq_printf(s, "%d,0x%X\n", | 1031 | return seq_printf(s, "%d,0x%X\n", |
1019 | main_bat_v_convert, main_bat_v_raw); | 1032 | main_bat_v_convert, main_bat_v_raw); |
@@ -1040,9 +1053,10 @@ static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p) | |||
1040 | struct ab8500_gpadc *gpadc; | 1053 | struct ab8500_gpadc *gpadc; |
1041 | 1054 | ||
1042 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1055 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1043 | vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V); | 1056 | vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V, |
1057 | avg_sample, trig_edge, trig_timer, conv_type); | ||
1044 | vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V, | 1058 | vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V, |
1045 | vbus_v_raw); | 1059 | vbus_v_raw); |
1046 | 1060 | ||
1047 | return seq_printf(s, "%d,0x%X\n", | 1061 | return seq_printf(s, "%d,0x%X\n", |
1048 | vbus_v_convert, vbus_v_raw); | 1062 | vbus_v_convert, vbus_v_raw); |
@@ -1068,9 +1082,10 @@ static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p) | |||
1068 | struct ab8500_gpadc *gpadc; | 1082 | struct ab8500_gpadc *gpadc; |
1069 | 1083 | ||
1070 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1084 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1071 | main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C); | 1085 | main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C, |
1086 | avg_sample, trig_edge, trig_timer, conv_type); | ||
1072 | main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, | 1087 | main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, |
1073 | MAIN_CHARGER_C, main_charger_c_raw); | 1088 | MAIN_CHARGER_C, main_charger_c_raw); |
1074 | 1089 | ||
1075 | return seq_printf(s, "%d,0x%X\n", | 1090 | return seq_printf(s, "%d,0x%X\n", |
1076 | main_charger_c_convert, main_charger_c_raw); | 1091 | main_charger_c_convert, main_charger_c_raw); |
@@ -1098,9 +1113,10 @@ static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p) | |||
1098 | struct ab8500_gpadc *gpadc; | 1113 | struct ab8500_gpadc *gpadc; |
1099 | 1114 | ||
1100 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1115 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1101 | usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C); | 1116 | usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C, |
1117 | avg_sample, trig_edge, trig_timer, conv_type); | ||
1102 | usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, | 1118 | usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, |
1103 | USB_CHARGER_C, usb_charger_c_raw); | 1119 | USB_CHARGER_C, usb_charger_c_raw); |
1104 | 1120 | ||
1105 | return seq_printf(s, "%d,0x%X\n", | 1121 | return seq_printf(s, "%d,0x%X\n", |
1106 | usb_charger_c_convert, usb_charger_c_raw); | 1122 | usb_charger_c_convert, usb_charger_c_raw); |
@@ -1128,9 +1144,10 @@ static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p) | |||
1128 | struct ab8500_gpadc *gpadc; | 1144 | struct ab8500_gpadc *gpadc; |
1129 | 1145 | ||
1130 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1146 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1131 | bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V); | 1147 | bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V, |
1148 | avg_sample, trig_edge, trig_timer, conv_type); | ||
1132 | bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, | 1149 | bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, |
1133 | BK_BAT_V, bk_bat_v_raw); | 1150 | BK_BAT_V, bk_bat_v_raw); |
1134 | 1151 | ||
1135 | return seq_printf(s, "%d,0x%X\n", | 1152 | return seq_printf(s, "%d,0x%X\n", |
1136 | bk_bat_v_convert, bk_bat_v_raw); | 1153 | bk_bat_v_convert, bk_bat_v_raw); |
@@ -1156,9 +1173,10 @@ static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p) | |||
1156 | struct ab8500_gpadc *gpadc; | 1173 | struct ab8500_gpadc *gpadc; |
1157 | 1174 | ||
1158 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1175 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1159 | die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP); | 1176 | die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP, |
1177 | avg_sample, trig_edge, trig_timer, conv_type); | ||
1160 | die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP, | 1178 | die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP, |
1161 | die_temp_raw); | 1179 | die_temp_raw); |
1162 | 1180 | ||
1163 | return seq_printf(s, "%d,0x%X\n", | 1181 | return seq_printf(s, "%d,0x%X\n", |
1164 | die_temp_convert, die_temp_raw); | 1182 | die_temp_convert, die_temp_raw); |
@@ -1177,6 +1195,208 @@ static const struct file_operations ab8500_gpadc_die_temp_fops = { | |||
1177 | .owner = THIS_MODULE, | 1195 | .owner = THIS_MODULE, |
1178 | }; | 1196 | }; |
1179 | 1197 | ||
1198 | static int ab8500_gpadc_avg_sample_print(struct seq_file *s, void *p) | ||
1199 | { | ||
1200 | return seq_printf(s, "%d\n", avg_sample); | ||
1201 | } | ||
1202 | |||
1203 | static int ab8500_gpadc_avg_sample_open(struct inode *inode, struct file *file) | ||
1204 | { | ||
1205 | return single_open(file, ab8500_gpadc_avg_sample_print, | ||
1206 | inode->i_private); | ||
1207 | } | ||
1208 | |||
1209 | static ssize_t ab8500_gpadc_avg_sample_write(struct file *file, | ||
1210 | const char __user *user_buf, | ||
1211 | size_t count, loff_t *ppos) | ||
1212 | { | ||
1213 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
1214 | char buf[32]; | ||
1215 | int buf_size; | ||
1216 | unsigned long user_avg_sample; | ||
1217 | int err; | ||
1218 | |||
1219 | /* Get userspace string and assure termination */ | ||
1220 | buf_size = min(count, (sizeof(buf) - 1)); | ||
1221 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1222 | return -EFAULT; | ||
1223 | buf[buf_size] = 0; | ||
1224 | |||
1225 | err = strict_strtoul(buf, 0, &user_avg_sample); | ||
1226 | if (err) | ||
1227 | return -EINVAL; | ||
1228 | if ((user_avg_sample == SAMPLE_1) || (user_avg_sample == SAMPLE_4) | ||
1229 | || (user_avg_sample == SAMPLE_8) | ||
1230 | || (user_avg_sample == SAMPLE_16)) { | ||
1231 | avg_sample = (u8) user_avg_sample; | ||
1232 | } else { | ||
1233 | dev_err(dev, "debugfs error input: " | ||
1234 | "should be egal to 1, 4, 8 or 16\n"); | ||
1235 | return -EINVAL; | ||
1236 | } | ||
1237 | return buf_size; | ||
1238 | } | ||
1239 | |||
1240 | static const struct file_operations ab8500_gpadc_avg_sample_fops = { | ||
1241 | .open = ab8500_gpadc_avg_sample_open, | ||
1242 | .read = seq_read, | ||
1243 | .write = ab8500_gpadc_avg_sample_write, | ||
1244 | .llseek = seq_lseek, | ||
1245 | .release = single_release, | ||
1246 | .owner = THIS_MODULE, | ||
1247 | }; | ||
1248 | |||
1249 | static int ab8500_gpadc_trig_edge_print(struct seq_file *s, void *p) | ||
1250 | { | ||
1251 | return seq_printf(s, "%d\n", trig_edge); | ||
1252 | } | ||
1253 | |||
1254 | static int ab8500_gpadc_trig_edge_open(struct inode *inode, struct file *file) | ||
1255 | { | ||
1256 | return single_open(file, ab8500_gpadc_trig_edge_print, | ||
1257 | inode->i_private); | ||
1258 | } | ||
1259 | |||
1260 | static ssize_t ab8500_gpadc_trig_edge_write(struct file *file, | ||
1261 | const char __user *user_buf, | ||
1262 | size_t count, loff_t *ppos) | ||
1263 | { | ||
1264 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
1265 | char buf[32]; | ||
1266 | int buf_size; | ||
1267 | unsigned long user_trig_edge; | ||
1268 | int err; | ||
1269 | |||
1270 | /* Get userspace string and assure termination */ | ||
1271 | buf_size = min(count, (sizeof(buf) - 1)); | ||
1272 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1273 | return -EFAULT; | ||
1274 | buf[buf_size] = 0; | ||
1275 | |||
1276 | err = strict_strtoul(buf, 0, &user_trig_edge); | ||
1277 | if (err) | ||
1278 | return -EINVAL; | ||
1279 | if ((user_trig_edge == RISING_EDGE) | ||
1280 | || (user_trig_edge == FALLING_EDGE)) { | ||
1281 | trig_edge = (u8) user_trig_edge; | ||
1282 | } else { | ||
1283 | dev_err(dev, "Wrong input:\n" | ||
1284 | "Enter 0. Rising edge\n" | ||
1285 | "Enter 1. Falling edge\n"); | ||
1286 | return -EINVAL; | ||
1287 | } | ||
1288 | return buf_size; | ||
1289 | } | ||
1290 | |||
1291 | static const struct file_operations ab8500_gpadc_trig_edge_fops = { | ||
1292 | .open = ab8500_gpadc_trig_edge_open, | ||
1293 | .read = seq_read, | ||
1294 | .write = ab8500_gpadc_trig_edge_write, | ||
1295 | .llseek = seq_lseek, | ||
1296 | .release = single_release, | ||
1297 | .owner = THIS_MODULE, | ||
1298 | }; | ||
1299 | |||
1300 | static int ab8500_gpadc_trig_timer_print(struct seq_file *s, void *p) | ||
1301 | { | ||
1302 | return seq_printf(s, "%d\n", trig_timer); | ||
1303 | } | ||
1304 | |||
1305 | static int ab8500_gpadc_trig_timer_open(struct inode *inode, struct file *file) | ||
1306 | { | ||
1307 | return single_open(file, ab8500_gpadc_trig_timer_print, | ||
1308 | inode->i_private); | ||
1309 | } | ||
1310 | |||
1311 | static ssize_t ab8500_gpadc_trig_timer_write(struct file *file, | ||
1312 | const char __user *user_buf, | ||
1313 | size_t count, loff_t *ppos) | ||
1314 | { | ||
1315 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
1316 | char buf[32]; | ||
1317 | int buf_size; | ||
1318 | unsigned long user_trig_timer; | ||
1319 | int err; | ||
1320 | |||
1321 | /* Get userspace string and assure termination */ | ||
1322 | buf_size = min(count, (sizeof(buf) - 1)); | ||
1323 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1324 | return -EFAULT; | ||
1325 | buf[buf_size] = 0; | ||
1326 | |||
1327 | err = strict_strtoul(buf, 0, &user_trig_timer); | ||
1328 | if (err) | ||
1329 | return -EINVAL; | ||
1330 | if ((user_trig_timer >= 0) && (user_trig_timer <= 255)) { | ||
1331 | trig_timer = (u8) user_trig_timer; | ||
1332 | } else { | ||
1333 | dev_err(dev, "debugfs error input: " | ||
1334 | "should be beetween 0 to 255\n"); | ||
1335 | return -EINVAL; | ||
1336 | } | ||
1337 | return buf_size; | ||
1338 | } | ||
1339 | |||
1340 | static const struct file_operations ab8500_gpadc_trig_timer_fops = { | ||
1341 | .open = ab8500_gpadc_trig_timer_open, | ||
1342 | .read = seq_read, | ||
1343 | .write = ab8500_gpadc_trig_timer_write, | ||
1344 | .llseek = seq_lseek, | ||
1345 | .release = single_release, | ||
1346 | .owner = THIS_MODULE, | ||
1347 | }; | ||
1348 | |||
1349 | static int ab8500_gpadc_conv_type_print(struct seq_file *s, void *p) | ||
1350 | { | ||
1351 | return seq_printf(s, "%d\n", conv_type); | ||
1352 | } | ||
1353 | |||
1354 | static int ab8500_gpadc_conv_type_open(struct inode *inode, struct file *file) | ||
1355 | { | ||
1356 | return single_open(file, ab8500_gpadc_conv_type_print, | ||
1357 | inode->i_private); | ||
1358 | } | ||
1359 | |||
1360 | static ssize_t ab8500_gpadc_conv_type_write(struct file *file, | ||
1361 | const char __user *user_buf, | ||
1362 | size_t count, loff_t *ppos) | ||
1363 | { | ||
1364 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
1365 | char buf[32]; | ||
1366 | int buf_size; | ||
1367 | unsigned long user_conv_type; | ||
1368 | int err; | ||
1369 | |||
1370 | /* Get userspace string and assure termination */ | ||
1371 | buf_size = min(count, (sizeof(buf) - 1)); | ||
1372 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1373 | return -EFAULT; | ||
1374 | buf[buf_size] = 0; | ||
1375 | |||
1376 | err = strict_strtoul(buf, 0, &user_conv_type); | ||
1377 | if (err) | ||
1378 | return -EINVAL; | ||
1379 | if ((user_conv_type == ADC_SW) | ||
1380 | || (user_conv_type == ADC_HW)) { | ||
1381 | conv_type = (u8) user_conv_type; | ||
1382 | } else { | ||
1383 | dev_err(dev, "Wrong input:\n" | ||
1384 | "Enter 0. ADC SW conversion\n" | ||
1385 | "Enter 1. ADC HW conversion\n"); | ||
1386 | return -EINVAL; | ||
1387 | } | ||
1388 | return buf_size; | ||
1389 | } | ||
1390 | |||
1391 | static const struct file_operations ab8500_gpadc_conv_type_fops = { | ||
1392 | .open = ab8500_gpadc_conv_type_open, | ||
1393 | .read = seq_read, | ||
1394 | .write = ab8500_gpadc_conv_type_write, | ||
1395 | .llseek = seq_lseek, | ||
1396 | .release = single_release, | ||
1397 | .owner = THIS_MODULE, | ||
1398 | }; | ||
1399 | |||
1180 | /* | 1400 | /* |
1181 | * return length of an ASCII numerical value, 0 is string is not a | 1401 | * return length of an ASCII numerical value, 0 is string is not a |
1182 | * numerical value. | 1402 | * numerical value. |
@@ -1722,6 +1942,26 @@ static int ab8500_debug_probe(struct platform_device *plf) | |||
1722 | if (!file) | 1942 | if (!file) |
1723 | goto err; | 1943 | goto err; |
1724 | 1944 | ||
1945 | file = debugfs_create_file("avg_sample", (S_IRUGO | S_IWUGO), | ||
1946 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_avg_sample_fops); | ||
1947 | if (!file) | ||
1948 | goto err; | ||
1949 | |||
1950 | file = debugfs_create_file("trig_edge", (S_IRUGO | S_IWUGO), | ||
1951 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_edge_fops); | ||
1952 | if (!file) | ||
1953 | goto err; | ||
1954 | |||
1955 | file = debugfs_create_file("trig_timer", (S_IRUGO | S_IWUGO), | ||
1956 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_timer_fops); | ||
1957 | if (!file) | ||
1958 | goto err; | ||
1959 | |||
1960 | file = debugfs_create_file("conv_type", (S_IRUGO | S_IWUGO), | ||
1961 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_conv_type_fops); | ||
1962 | if (!file) | ||
1963 | goto err; | ||
1964 | |||
1725 | return 0; | 1965 | return 0; |
1726 | 1966 | ||
1727 | err: | 1967 | err: |
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 7f39479c1afc..8673bf66f7d7 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c | |||
@@ -55,13 +55,18 @@ | |||
55 | #define EN_VTVOUT 0x02 | 55 | #define EN_VTVOUT 0x02 |
56 | #define EN_GPADC 0x01 | 56 | #define EN_GPADC 0x01 |
57 | #define DIS_GPADC 0x00 | 57 | #define DIS_GPADC 0x00 |
58 | #define SW_AVG_16 0x60 | 58 | #define AVG_1 0x00 |
59 | #define AVG_4 0x20 | ||
60 | #define AVG_8 0x40 | ||
61 | #define AVG_16 0x60 | ||
59 | #define ADC_SW_CONV 0x04 | 62 | #define ADC_SW_CONV 0x04 |
60 | #define EN_ICHAR 0x80 | 63 | #define EN_ICHAR 0x80 |
61 | #define BTEMP_PULL_UP 0x08 | 64 | #define BTEMP_PULL_UP 0x08 |
62 | #define EN_BUF 0x40 | 65 | #define EN_BUF 0x40 |
63 | #define DIS_ZERO 0x00 | 66 | #define DIS_ZERO 0x00 |
64 | #define GPADC_BUSY 0x01 | 67 | #define GPADC_BUSY 0x01 |
68 | #define EN_FALLING 0x10 | ||
69 | #define EN_TRIG_EDGE 0x02 | ||
65 | 70 | ||
66 | /* GPADC constants from AB8500 spec, UM0836 */ | 71 | /* GPADC constants from AB8500 spec, UM0836 */ |
67 | #define ADC_RESOLUTION 1024 | 72 | #define ADC_RESOLUTION 1024 |
@@ -116,7 +121,10 @@ struct adc_cal_data { | |||
116 | * the completion of gpadc conversion | 121 | * the completion of gpadc conversion |
117 | * @ab8500_gpadc_lock: structure of type mutex | 122 | * @ab8500_gpadc_lock: structure of type mutex |
118 | * @regu: pointer to the struct regulator | 123 | * @regu: pointer to the struct regulator |
119 | * @irq: interrupt number that is used by gpadc | 124 | * @irq_sw: interrupt number that is used by gpadc for Sw |
125 | * conversion | ||
126 | * @irq_hw: interrupt number that is used by gpadc for Hw | ||
127 | * conversion | ||
120 | * @cal_data array of ADC calibration data structs | 128 | * @cal_data array of ADC calibration data structs |
121 | */ | 129 | */ |
122 | struct ab8500_gpadc { | 130 | struct ab8500_gpadc { |
@@ -126,7 +134,8 @@ struct ab8500_gpadc { | |||
126 | struct completion ab8500_gpadc_complete; | 134 | struct completion ab8500_gpadc_complete; |
127 | struct mutex ab8500_gpadc_lock; | 135 | struct mutex ab8500_gpadc_lock; |
128 | struct regulator *regu; | 136 | struct regulator *regu; |
129 | int irq; | 137 | int irq_sw; |
138 | int irq_hw; | ||
130 | struct adc_cal_data cal_data[NBR_CAL_INPUTS]; | 139 | struct adc_cal_data cal_data[NBR_CAL_INPUTS]; |
131 | }; | 140 | }; |
132 | 141 | ||
@@ -244,30 +253,35 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, | |||
244 | EXPORT_SYMBOL(ab8500_gpadc_ad_to_voltage); | 253 | EXPORT_SYMBOL(ab8500_gpadc_ad_to_voltage); |
245 | 254 | ||
246 | /** | 255 | /** |
247 | * ab8500_gpadc_convert() - gpadc conversion | 256 | * ab8500_gpadc_sw_hw_convert() - gpadc conversion |
248 | * @channel: analog channel to be converted to digital data | 257 | * @channel: analog channel to be converted to digital data |
258 | * @avg_sample: number of ADC sample to average | ||
259 | * @trig_egde: selected ADC trig edge | ||
260 | * @trig_timer: selected ADC trigger delay timer | ||
261 | * @conv_type: selected conversion type (HW or SW conversion) | ||
249 | * | 262 | * |
250 | * This function converts the selected analog i/p to digital | 263 | * This function converts the selected analog i/p to digital |
251 | * data. | 264 | * data. |
252 | */ | 265 | */ |
253 | int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel) | 266 | int ab8500_gpadc_sw_hw_convert(struct ab8500_gpadc *gpadc, u8 channel, |
267 | u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type) | ||
254 | { | 268 | { |
255 | int ad_value; | 269 | int ad_value; |
256 | int voltage; | 270 | int voltage; |
257 | 271 | ||
258 | ad_value = ab8500_gpadc_read_raw(gpadc, channel); | 272 | ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample, |
259 | 273 | trig_edge, trig_timer, conv_type); | |
260 | /* On failure retry a second time */ | 274 | /* On failure retry a second time */ |
261 | if (ad_value < 0) | 275 | if (ad_value < 0) |
262 | ad_value = ab8500_gpadc_read_raw(gpadc, channel); | 276 | ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample, |
263 | 277 | trig_edge, trig_timer, conv_type); | |
264 | if (ad_value < 0) { | 278 | if (ad_value < 0) { |
265 | dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n", channel); | 279 | dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n", |
280 | channel); | ||
266 | return ad_value; | 281 | return ad_value; |
267 | } | 282 | } |
268 | 283 | ||
269 | voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value); | 284 | voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value); |
270 | |||
271 | if (voltage < 0) | 285 | if (voltage < 0) |
272 | dev_err(gpadc->dev, "GPADC to voltage conversion failed ch:" | 286 | dev_err(gpadc->dev, "GPADC to voltage conversion failed ch:" |
273 | " %d AD: 0x%x\n", channel, ad_value); | 287 | " %d AD: 0x%x\n", channel, ad_value); |
@@ -279,11 +293,16 @@ EXPORT_SYMBOL(ab8500_gpadc_convert); | |||
279 | /** | 293 | /** |
280 | * ab8500_gpadc_read_raw() - gpadc read | 294 | * ab8500_gpadc_read_raw() - gpadc read |
281 | * @channel: analog channel to be read | 295 | * @channel: analog channel to be read |
296 | * @avg_sample: number of ADC sample to average | ||
297 | * @trig_edge: selected trig edge | ||
298 | * @trig_timer: selected ADC trigger delay timer | ||
299 | * @conv_type: selected conversion type (HW or SW conversion) | ||
282 | * | 300 | * |
283 | * This function obtains the raw ADC value, this then needs | 301 | * This function obtains the raw ADC value for an hardware conversion, |
284 | * to be converted by calling ab8500_gpadc_ad_to_voltage() | 302 | * this then needs to be converted by calling ab8500_gpadc_ad_to_voltage() |
285 | */ | 303 | */ |
286 | int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | 304 | int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, |
305 | u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type) | ||
287 | { | 306 | { |
288 | int ret; | 307 | int ret; |
289 | int looplimit = 0; | 308 | int looplimit = 0; |
@@ -293,7 +312,6 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
293 | return -ENODEV; | 312 | return -ENODEV; |
294 | 313 | ||
295 | mutex_lock(&gpadc->ab8500_gpadc_lock); | 314 | mutex_lock(&gpadc->ab8500_gpadc_lock); |
296 | |||
297 | /* Enable VTVout LDO this is required for GPADC */ | 315 | /* Enable VTVout LDO this is required for GPADC */ |
298 | pm_runtime_get_sync(gpadc->dev); | 316 | pm_runtime_get_sync(gpadc->dev); |
299 | 317 | ||
@@ -321,9 +339,29 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
321 | goto out; | 339 | goto out; |
322 | } | 340 | } |
323 | 341 | ||
324 | /* Select the channel source and set average samples to 16 */ | 342 | /* Select the channel source and set average samples */ |
325 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 343 | switch (avg_sample) { |
326 | AB8500_GPADC_CTRL2_REG, (channel | SW_AVG_16)); | 344 | case SAMPLE_1: |
345 | val = channel | AVG_1; | ||
346 | break; | ||
347 | case SAMPLE_4: | ||
348 | val = channel | AVG_4; | ||
349 | break; | ||
350 | case SAMPLE_8: | ||
351 | val = channel | AVG_8; | ||
352 | break; | ||
353 | default: | ||
354 | val = channel | AVG_16; | ||
355 | break; | ||
356 | |||
357 | } | ||
358 | |||
359 | if (conv_type == ADC_HW) | ||
360 | ret = abx500_set_register_interruptible(gpadc->dev, | ||
361 | AB8500_GPADC, AB8500_GPADC_CTRL3_REG, val); | ||
362 | else | ||
363 | ret = abx500_set_register_interruptible(gpadc->dev, | ||
364 | AB8500_GPADC, AB8500_GPADC_CTRL2_REG, val); | ||
327 | if (ret < 0) { | 365 | if (ret < 0) { |
328 | dev_err(gpadc->dev, | 366 | dev_err(gpadc->dev, |
329 | "gpadc_conversion: set avg samples failed\n"); | 367 | "gpadc_conversion: set avg samples failed\n"); |
@@ -335,22 +373,43 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
335 | * charging current sense if it needed, ABB 3.0 needs some special | 373 | * charging current sense if it needed, ABB 3.0 needs some special |
336 | * treatment too. | 374 | * treatment too. |
337 | */ | 375 | */ |
376 | if ((conv_type == ADC_HW) && (trig_edge)) { | ||
377 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | ||
378 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
379 | EN_FALLING, EN_FALLING); | ||
380 | |||
381 | } | ||
338 | switch (channel) { | 382 | switch (channel) { |
339 | case MAIN_CHARGER_C: | 383 | case MAIN_CHARGER_C: |
340 | case USB_CHARGER_C: | 384 | case USB_CHARGER_C: |
341 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 385 | if (conv_type == ADC_HW) |
342 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
343 | EN_BUF | EN_ICHAR, | ||
344 | EN_BUF | EN_ICHAR); | ||
345 | break; | ||
346 | case BTEMP_BALL: | ||
347 | if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { | ||
348 | /* Turn on btemp pull-up on ABB 3.0 */ | ||
349 | ret = abx500_mask_and_set_register_interruptible( | 386 | ret = abx500_mask_and_set_register_interruptible( |
350 | gpadc->dev, | 387 | gpadc->dev, |
351 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | 388 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, |
352 | EN_BUF | BTEMP_PULL_UP, | 389 | EN_BUF | EN_ICHAR | EN_TRIG_EDGE, |
353 | EN_BUF | BTEMP_PULL_UP); | 390 | EN_BUF | EN_ICHAR | EN_TRIG_EDGE); |
391 | else | ||
392 | ret = abx500_mask_and_set_register_interruptible( | ||
393 | gpadc->dev, | ||
394 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
395 | EN_BUF | EN_ICHAR, | ||
396 | EN_BUF | EN_ICHAR); | ||
397 | break; | ||
398 | case BTEMP_BALL: | ||
399 | if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { | ||
400 | if (conv_type == ADC_HW) | ||
401 | /* Turn on btemp pull-up on ABB 3.0 */ | ||
402 | ret = abx500_mask_and_set_register_interruptible | ||
403 | (gpadc->dev, | ||
404 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
405 | EN_BUF | BTEMP_PULL_UP | EN_TRIG_EDGE, | ||
406 | EN_BUF | BTEMP_PULL_UP | EN_TRIG_EDGE); | ||
407 | else | ||
408 | ret = abx500_mask_and_set_register_interruptible | ||
409 | (gpadc->dev, | ||
410 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
411 | EN_BUF | BTEMP_PULL_UP, | ||
412 | EN_BUF | BTEMP_PULL_UP); | ||
354 | 413 | ||
355 | /* | 414 | /* |
356 | * Delay might be needed for ABB8500 cut 3.0, if not, remove | 415 | * Delay might be needed for ABB8500 cut 3.0, if not, remove |
@@ -361,8 +420,17 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
361 | } | 420 | } |
362 | /* Intentional fallthrough */ | 421 | /* Intentional fallthrough */ |
363 | default: | 422 | default: |
364 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 423 | if (conv_type == ADC_HW) |
365 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF); | 424 | ret = abx500_mask_and_set_register_interruptible( |
425 | gpadc->dev, | ||
426 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
427 | EN_BUF | EN_TRIG_EDGE, | ||
428 | EN_BUF | EN_TRIG_EDGE); | ||
429 | else | ||
430 | ret = abx500_mask_and_set_register_interruptible( | ||
431 | gpadc->dev, | ||
432 | AB8500_GPADC, | ||
433 | AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF); | ||
366 | break; | 434 | break; |
367 | } | 435 | } |
368 | if (ret < 0) { | 436 | if (ret < 0) { |
@@ -371,36 +439,83 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
371 | goto out; | 439 | goto out; |
372 | } | 440 | } |
373 | 441 | ||
374 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 442 | /* Set trigger delay timer */ |
375 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, ADC_SW_CONV, ADC_SW_CONV); | 443 | if (conv_type == ADC_HW) { |
376 | if (ret < 0) { | 444 | ret = abx500_set_register_interruptible(gpadc->dev, |
377 | dev_err(gpadc->dev, | 445 | AB8500_GPADC, AB8500_GPADC_AUTO_TIMER_REG, trig_timer); |
378 | "gpadc_conversion: start s/w conversion failed\n"); | 446 | if (ret < 0) { |
379 | goto out; | 447 | dev_err(gpadc->dev, |
448 | "gpadc_conversion: trig timer failed\n"); | ||
449 | goto out; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | /* Start SW conversion */ | ||
454 | if (conv_type == ADC_SW) { | ||
455 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | ||
456 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
457 | ADC_SW_CONV, ADC_SW_CONV); | ||
458 | if (ret < 0) { | ||
459 | dev_err(gpadc->dev, | ||
460 | "gpadc_conversion: start s/w conv failed\n"); | ||
461 | goto out; | ||
462 | } | ||
380 | } | 463 | } |
464 | |||
381 | /* wait for completion of conversion */ | 465 | /* wait for completion of conversion */ |
382 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, | 466 | if (conv_type == ADC_HW) { |
383 | msecs_to_jiffies(CONVERSION_TIME))) { | 467 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, |
384 | dev_err(gpadc->dev, | 468 | 2*HZ)) { |
385 | "timeout: didn't receive GPADC conversion interrupt\n"); | 469 | dev_err(gpadc->dev, |
386 | ret = -EINVAL; | 470 | "timeout didn't receive" |
387 | goto out; | 471 | " hw GPADC conv interrupt\n"); |
472 | ret = -EINVAL; | ||
473 | goto out; | ||
474 | } | ||
475 | } else { | ||
476 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, | ||
477 | msecs_to_jiffies(CONVERSION_TIME))) { | ||
478 | dev_err(gpadc->dev, | ||
479 | "timeout didn't receive" | ||
480 | " sw GPADC conv interrupt\n"); | ||
481 | ret = -EINVAL; | ||
482 | goto out; | ||
483 | } | ||
388 | } | 484 | } |
389 | 485 | ||
390 | /* Read the converted RAW data */ | 486 | /* Read the converted RAW data */ |
391 | ret = abx500_get_register_interruptible(gpadc->dev, AB8500_GPADC, | 487 | if (conv_type == ADC_HW) { |
392 | AB8500_GPADC_MANDATAL_REG, &low_data); | 488 | ret = abx500_get_register_interruptible(gpadc->dev, |
393 | if (ret < 0) { | 489 | AB8500_GPADC, AB8500_GPADC_AUTODATAL_REG, &low_data); |
394 | dev_err(gpadc->dev, "gpadc_conversion: read low data failed\n"); | 490 | if (ret < 0) { |
395 | goto out; | 491 | dev_err(gpadc->dev, |
396 | } | 492 | "gpadc_conversion: read hw low data failed\n"); |
493 | goto out; | ||
494 | } | ||
397 | 495 | ||
398 | ret = abx500_get_register_interruptible(gpadc->dev, AB8500_GPADC, | 496 | ret = abx500_get_register_interruptible(gpadc->dev, |
399 | AB8500_GPADC_MANDATAH_REG, &high_data); | 497 | AB8500_GPADC, AB8500_GPADC_AUTODATAH_REG, &high_data); |
400 | if (ret < 0) { | 498 | if (ret < 0) { |
401 | dev_err(gpadc->dev, | 499 | dev_err(gpadc->dev, |
402 | "gpadc_conversion: read high data failed\n"); | 500 | "gpadc_conversion: read hw high data failed\n"); |
403 | goto out; | 501 | goto out; |
502 | } | ||
503 | } else { | ||
504 | ret = abx500_get_register_interruptible(gpadc->dev, | ||
505 | AB8500_GPADC, AB8500_GPADC_MANDATAL_REG, &low_data); | ||
506 | if (ret < 0) { | ||
507 | dev_err(gpadc->dev, | ||
508 | "gpadc_conversion: read sw low data failed\n"); | ||
509 | goto out; | ||
510 | } | ||
511 | |||
512 | ret = abx500_get_register_interruptible(gpadc->dev, | ||
513 | AB8500_GPADC, AB8500_GPADC_MANDATAH_REG, &high_data); | ||
514 | if (ret < 0) { | ||
515 | dev_err(gpadc->dev, | ||
516 | "gpadc_conversion: read sw high data failed\n"); | ||
517 | goto out; | ||
518 | } | ||
404 | } | 519 | } |
405 | 520 | ||
406 | /* Disable GPADC */ | 521 | /* Disable GPADC */ |
@@ -411,6 +526,7 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
411 | goto out; | 526 | goto out; |
412 | } | 527 | } |
413 | 528 | ||
529 | /* Disable VTVout LDO this is required for GPADC */ | ||
414 | pm_runtime_mark_last_busy(gpadc->dev); | 530 | pm_runtime_mark_last_busy(gpadc->dev); |
415 | pm_runtime_put_autosuspend(gpadc->dev); | 531 | pm_runtime_put_autosuspend(gpadc->dev); |
416 | 532 | ||
@@ -427,9 +543,7 @@ out: | |||
427 | */ | 543 | */ |
428 | (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 544 | (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, |
429 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); | 545 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); |
430 | |||
431 | pm_runtime_put(gpadc->dev); | 546 | pm_runtime_put(gpadc->dev); |
432 | |||
433 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | 547 | mutex_unlock(&gpadc->ab8500_gpadc_lock); |
434 | dev_err(gpadc->dev, | 548 | dev_err(gpadc->dev, |
435 | "gpadc_conversion: Failed to AD convert channel %d\n", channel); | 549 | "gpadc_conversion: Failed to AD convert channel %d\n", channel); |
@@ -438,16 +552,16 @@ out: | |||
438 | EXPORT_SYMBOL(ab8500_gpadc_read_raw); | 552 | EXPORT_SYMBOL(ab8500_gpadc_read_raw); |
439 | 553 | ||
440 | /** | 554 | /** |
441 | * ab8500_bm_gpswadcconvend_handler() - isr for s/w gpadc conversion completion | 555 | * ab8500_bm_gpadcconvend_handler() - isr for gpadc conversion completion |
442 | * @irq: irq number | 556 | * @irq: irq number |
443 | * @data: pointer to the data passed during request irq | 557 | * @data: pointer to the data passed during request irq |
444 | * | 558 | * |
445 | * This is a interrupt service routine for s/w gpadc conversion completion. | 559 | * This is a interrupt service routine for gpadc conversion completion. |
446 | * Notifies the gpadc completion is completed and the converted raw value | 560 | * Notifies the gpadc completion is completed and the converted raw value |
447 | * can be read from the registers. | 561 | * can be read from the registers. |
448 | * Returns IRQ status(IRQ_HANDLED) | 562 | * Returns IRQ status(IRQ_HANDLED) |
449 | */ | 563 | */ |
450 | static irqreturn_t ab8500_bm_gpswadcconvend_handler(int irq, void *_gpadc) | 564 | static irqreturn_t ab8500_bm_gpadcconvend_handler(int irq, void *_gpadc) |
451 | { | 565 | { |
452 | struct ab8500_gpadc *gpadc = _gpadc; | 566 | struct ab8500_gpadc *gpadc = _gpadc; |
453 | 567 | ||
@@ -646,11 +760,19 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
646 | return -ENOMEM; | 760 | return -ENOMEM; |
647 | } | 761 | } |
648 | 762 | ||
649 | gpadc->irq = platform_get_irq_byname(pdev, "SW_CONV_END"); | 763 | gpadc->irq_sw = platform_get_irq_byname(pdev, "SW_CONV_END"); |
650 | if (gpadc->irq < 0) { | 764 | if (gpadc->irq_sw < 0) { |
651 | dev_err(&pdev->dev, "failed to get platform irq-%d\n", | 765 | dev_err(gpadc->dev, "failed to get platform irq-%d\n", |
652 | gpadc->irq); | 766 | gpadc->irq_sw); |
653 | ret = gpadc->irq; | 767 | ret = gpadc->irq_sw; |
768 | goto fail; | ||
769 | } | ||
770 | |||
771 | gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END"); | ||
772 | if (gpadc->irq_hw < 0) { | ||
773 | dev_err(gpadc->dev, "failed to get platform irq-%d\n", | ||
774 | gpadc->irq_hw); | ||
775 | ret = gpadc->irq_hw; | ||
654 | goto fail; | 776 | goto fail; |
655 | } | 777 | } |
656 | 778 | ||
@@ -661,14 +783,21 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
661 | /* Initialize completion used to notify completion of conversion */ | 783 | /* Initialize completion used to notify completion of conversion */ |
662 | init_completion(&gpadc->ab8500_gpadc_complete); | 784 | init_completion(&gpadc->ab8500_gpadc_complete); |
663 | 785 | ||
664 | /* Register interrupt - SwAdcComplete */ | 786 | /* Register interrupts */ |
665 | ret = request_threaded_irq(gpadc->irq, NULL, | 787 | ret = request_threaded_irq(gpadc->irq_sw, NULL, |
666 | ab8500_bm_gpswadcconvend_handler, | 788 | ab8500_bm_gpadcconvend_handler, |
667 | IRQF_ONESHOT | IRQF_NO_SUSPEND | IRQF_SHARED, | 789 | IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc-sw", gpadc); |
668 | "ab8500-gpadc", gpadc); | 790 | if (ret < 0) { |
791 | dev_err(gpadc->dev, "Failed to register interrupt, irq: %d\n", | ||
792 | gpadc->irq_sw); | ||
793 | goto fail; | ||
794 | } | ||
795 | ret = request_threaded_irq(gpadc->irq_hw, NULL, | ||
796 | ab8500_bm_gpadcconvend_handler, | ||
797 | IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc-hw", gpadc); | ||
669 | if (ret < 0) { | 798 | if (ret < 0) { |
670 | dev_err(gpadc->dev, "Failed to register interrupt, irq: %d\n", | 799 | dev_err(gpadc->dev, "Failed to register interrupt, irq: %d\n", |
671 | gpadc->irq); | 800 | gpadc->irq_hw); |
672 | goto fail; | 801 | goto fail; |
673 | } | 802 | } |
674 | 803 | ||
@@ -694,7 +823,8 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
694 | dev_dbg(gpadc->dev, "probe success\n"); | 823 | dev_dbg(gpadc->dev, "probe success\n"); |
695 | return 0; | 824 | return 0; |
696 | fail_irq: | 825 | fail_irq: |
697 | free_irq(gpadc->irq, gpadc); | 826 | free_irq(gpadc->irq_sw, gpadc); |
827 | free_irq(gpadc->irq_hw, gpadc); | ||
698 | fail: | 828 | fail: |
699 | kfree(gpadc); | 829 | kfree(gpadc); |
700 | gpadc = NULL; | 830 | gpadc = NULL; |
@@ -708,7 +838,8 @@ static int ab8500_gpadc_remove(struct platform_device *pdev) | |||
708 | /* remove this gpadc entry from the list */ | 838 | /* remove this gpadc entry from the list */ |
709 | list_del(&gpadc->node); | 839 | list_del(&gpadc->node); |
710 | /* remove interrupt - completion of Sw ADC conversion */ | 840 | /* remove interrupt - completion of Sw ADC conversion */ |
711 | free_irq(gpadc->irq, gpadc); | 841 | free_irq(gpadc->irq_sw, gpadc); |
842 | free_irq(gpadc->irq_hw, gpadc); | ||
712 | 843 | ||
713 | pm_runtime_get_sync(gpadc->dev); | 844 | pm_runtime_get_sync(gpadc->dev); |
714 | pm_runtime_disable(gpadc->dev); | 845 | pm_runtime_disable(gpadc->dev); |
@@ -757,6 +888,7 @@ subsys_initcall_sync(ab8500_gpadc_init); | |||
757 | module_exit(ab8500_gpadc_exit); | 888 | module_exit(ab8500_gpadc_exit); |
758 | 889 | ||
759 | MODULE_LICENSE("GPL v2"); | 890 | MODULE_LICENSE("GPL v2"); |
760 | MODULE_AUTHOR("Arun R Murthy, Daniel Willerud, Johan Palsson"); | 891 | MODULE_AUTHOR("Arun R Murthy, Daniel Willerud, Johan Palsson," |
892 | "M'boumba Cedric Madianga"); | ||
761 | MODULE_ALIAS("platform:ab8500_gpadc"); | 893 | MODULE_ALIAS("platform:ab8500_gpadc"); |
762 | MODULE_DESCRIPTION("AB8500 GPADC driver"); | 894 | MODULE_DESCRIPTION("AB8500 GPADC driver"); |