1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699 |
- /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- #define pr_fmt(fmt) "%s: " fmt, __func__
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/thermal.h>
- #include <linux/interrupt.h>
- #include <linux/workqueue.h>
- #include <linux/delay.h>
- #include <linux/kernel.h>
- #include <linux/io.h>
- #include <linux/slab.h>
- #include <linux/msm_tsens.h>
- #include <linux/err.h>
- #include <linux/of.h>
- #include <mach/msm_iomap.h>
- #define TSENS_DRIVER_NAME "msm-tsens"
- /* TSENS register info */
- #define TSENS_UPPER_LOWER_INTERRUPT_CTRL(n) ((n) + 0x1000)
- #define TSENS_INTERRUPT_EN BIT(0)
- #define TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(n) ((n) + 0x1004)
- #define TSENS_UPPER_STATUS_CLR BIT(21)
- #define TSENS_LOWER_STATUS_CLR BIT(20)
- #define TSENS_UPPER_THRESHOLD_MASK 0xffc00
- #define TSENS_LOWER_THRESHOLD_MASK 0x3ff
- #define TSENS_UPPER_THRESHOLD_SHIFT 10
- #define TSENS_S0_STATUS_ADDR(n) ((n) + 0x1030)
- #define TSENS_SN_ADDR_OFFSET 0x4
- #define TSENS_SN_STATUS_TEMP_MASK 0x3ff
- #define TSENS_SN_STATUS_LOWER_STATUS BIT(11)
- #define TSENS_SN_STATUS_UPPER_STATUS BIT(12)
- #define TSENS_STATUS_ADDR_OFFSET 2
- #define TSENS_TRDY_ADDR(n) ((n) + 0x105c)
- #define TSENS_TRDY_MASK BIT(0)
- #define TSENS_CTRL_ADDR(n) (n)
- #define TSENS_EN BIT(0)
- #define TSENS_SW_RST BIT(1)
- #define TSENS_ADC_CLK_SEL BIT(2)
- #define TSENS_SENSOR0_SHIFT 3
- #define TSENS_62_5_MS_MEAS_PERIOD 1
- #define TSENS_312_5_MS_MEAS_PERIOD 2
- #define TSENS_MEAS_PERIOD_SHIFT 18
- #define TSENS_SN_MIN_MAX_STATUS_CTRL(n) ((n) + 4)
- #define TSENS_GLOBAL_CONFIG(n) ((n) + 0x34)
- #define TSENS_S0_MAIN_CONFIG(n) ((n) + 0x38)
- #define TSENS_SN_REMOTE_CONFIG(n) ((n) + 0x3c)
- #define TSENS_EEPROM(n) ((n) + 0xd0)
- #define TSENS_EEPROM_REDUNDANCY_SEL(n) ((n) + 0x444)
- #define TSENS_EEPROM_BACKUP_REGION(n) ((n) + 0x440)
- #define TSENS_MAIN_CALIB_ADDR_RANGE 6
- #define TSENS_BACKUP_CALIB_ADDR_RANGE 4
- #define TSENS_EEPROM_8X26_1(n) ((n) + 0x1c0)
- #define TSENS_EEPROM_8X26_2(n) ((n) + 0x444)
- #define TSENS_8X26_MAIN_CALIB_ADDR_RANGE 4
- #define TSENS_EEPROM_8X10_1(n) ((n) + 0x1a4)
- #define TSENS_EEPROM_8X10_1_OFFSET 8
- #define TSENS_EEPROM_8X10_2(n) ((n) + 0x1a8)
- #define TSENS_EEPROM_8X10_SPARE_1(n) ((n) + 0xd8)
- #define TSENS_EEPROM_8X10_SPARE_2(n) ((n) + 0xdc)
- /* TSENS calibration Mask data */
- #define TSENS_BASE1_MASK 0xff
- #define TSENS0_POINT1_MASK 0x3f00
- #define TSENS1_POINT1_MASK 0xfc000
- #define TSENS2_POINT1_MASK 0x3f00000
- #define TSENS3_POINT1_MASK 0xfc000000
- #define TSENS4_POINT1_MASK 0x3f
- #define TSENS5_POINT1_MASK 0xfc0
- #define TSENS6_POINT1_MASK 0x3f000
- #define TSENS7_POINT1_MASK 0xfc0000
- #define TSENS8_POINT1_MASK 0x3f000000
- #define TSENS8_POINT1_MASK_BACKUP 0x3f
- #define TSENS9_POINT1_MASK 0x3f
- #define TSENS9_POINT1_MASK_BACKUP 0xfc0
- #define TSENS10_POINT1_MASK 0xfc0
- #define TSENS10_POINT1_MASK_BACKUP 0x3f000
- #define TSENS_CAL_SEL_0_1 0xc0000000
- #define TSENS_CAL_SEL_2 0x40000000
- #define TSENS_CAL_SEL_SHIFT 30
- #define TSENS_CAL_SEL_SHIFT_2 28
- #define TSENS_ONE_POINT_CALIB 0x1
- #define TSENS_ONE_POINT_CALIB_OPTION_2 0x2
- #define TSENS_TWO_POINT_CALIB 0x3
- #define TSENS0_POINT1_SHIFT 8
- #define TSENS1_POINT1_SHIFT 14
- #define TSENS2_POINT1_SHIFT 20
- #define TSENS3_POINT1_SHIFT 26
- #define TSENS5_POINT1_SHIFT 6
- #define TSENS6_POINT1_SHIFT 12
- #define TSENS7_POINT1_SHIFT 18
- #define TSENS8_POINT1_SHIFT 24
- #define TSENS9_POINT1_BACKUP_SHIFT 6
- #define TSENS10_POINT1_SHIFT 6
- #define TSENS10_POINT1_BACKUP_SHIFT 12
- #define TSENS_POINT2_BASE_SHIFT 12
- #define TSENS_POINT2_BASE_BACKUP_SHIFT 18
- #define TSENS0_POINT2_SHIFT 20
- #define TSENS0_POINT2_BACKUP_SHIFT 26
- #define TSENS1_POINT2_SHIFT 26
- #define TSENS2_POINT2_BACKUP_SHIFT 6
- #define TSENS3_POINT2_SHIFT 6
- #define TSENS3_POINT2_BACKUP_SHIFT 12
- #define TSENS4_POINT2_SHIFT 12
- #define TSENS4_POINT2_BACKUP_SHIFT 18
- #define TSENS5_POINT2_SHIFT 18
- #define TSENS5_POINT2_BACKUP_SHIFT 24
- #define TSENS6_POINT2_SHIFT 24
- #define TSENS7_POINT2_BACKUP_SHIFT 6
- #define TSENS8_POINT2_SHIFT 6
- #define TSENS8_POINT2_BACKUP_SHIFT 12
- #define TSENS9_POINT2_SHIFT 12
- #define TSENS9_POINT2_BACKUP_SHIFT 18
- #define TSENS10_POINT2_SHIFT 18
- #define TSENS10_POINT2_BACKUP_SHIFT 24
- #define TSENS_BASE2_MASK 0xff000
- #define TSENS_BASE2_BACKUP_MASK 0xfc0000
- #define TSENS0_POINT2_MASK 0x3f00000
- #define TSENS0_POINT2_BACKUP_MASK 0xfc000000
- #define TSENS1_POINT2_MASK 0xfc000000
- #define TSENS1_POINT2_BACKUP_MASK 0x3f
- #define TSENS2_POINT2_MASK 0x3f
- #define TSENS2_POINT2_BACKUP_MASK 0xfc0
- #define TSENS3_POINT2_MASK 0xfc0
- #define TSENS3_POINT2_BACKUP_MASK 0x3f000
- #define TSENS4_POINT2_MASK 0x3f000
- #define TSENS4_POINT2_BACKUP_MASK 0xfc0000
- #define TSENS5_POINT2_MASK 0xfc0000
- #define TSENS5_POINT2_BACKUP_MASK 0x3f000000
- #define TSENS6_POINT2_MASK 0x3f000000
- #define TSENS6_POINT2_BACKUP_MASK 0x3f
- #define TSENS7_POINT2_MASK 0x3f
- #define TSENS7_POINT2_BACKUP_MASK 0xfc0
- #define TSENS8_POINT2_MASK 0xfc0
- #define TSENS8_POINT2_BACKUP_MASK 0x3f000
- #define TSENS9_POINT2_MASK 0x3f000
- #define TSENS9_POINT2_BACKUP_MASK 0xfc0000
- #define TSENS10_POINT2_MASK 0xfc0000
- #define TSENS10_POINT2_BACKUP_MASK 0x3f000000
- #define TSENS_8X26_BASE0_MASK 0x1fe000
- #define TSENS0_8X26_POINT1_MASK 0x7e00000
- #define TSENS1_8X26_POINT1_MASK 0x3f
- #define TSENS2_8X26_POINT1_MASK 0xfc0
- #define TSENS3_8X26_POINT1_MASK 0x3f000
- #define TSENS4_8X26_POINT1_MASK 0xfc0000
- #define TSENS5_8X26_POINT1_MASK 0x3f000000
- #define TSENS6_8X26_POINT1_MASK 0x3f00000
- #define TSENS_8X26_TSENS_CAL_SEL 0xe0000000
- #define TSENS_8X26_BASE1_MASK 0xff
- #define TSENS0_8X26_POINT2_MASK 0x3f00
- #define TSENS1_8X26_POINT2_MASK 0xfc000
- #define TSENS2_8X26_POINT2_MASK 0x3f00000
- #define TSENS3_8X26_POINT2_MASK 0xfc000000
- #define TSENS4_8X26_POINT2_MASK 0x3f00000
- #define TSENS5_8X26_POINT2_MASK 0xfc000000
- #define TSENS6_8X26_POINT2_MASK 0x7e0000
- #define TSENS_8X26_CAL_SEL_SHIFT 29
- #define TSENS_8X26_BASE0_SHIFT 13
- #define TSENS0_8X26_POINT1_SHIFT 21
- #define TSENS2_8X26_POINT1_SHIFT 6
- #define TSENS3_8X26_POINT1_SHIFT 12
- #define TSENS4_8X26_POINT1_SHIFT 18
- #define TSENS5_8X26_POINT1_SHIFT 24
- #define TSENS6_8X26_POINT1_SHIFT 20
- #define TSENS0_8X26_POINT2_SHIFT 8
- #define TSENS1_8X26_POINT2_SHIFT 14
- #define TSENS2_8X26_POINT2_SHIFT 20
- #define TSENS3_8X26_POINT2_SHIFT 26
- #define TSENS4_8X26_POINT2_SHIFT 20
- #define TSENS5_8X26_POINT2_SHIFT 26
- #define TSENS6_8X26_POINT2_SHIFT 17
- #define TSENS_8X10_CAL_SEL_SHIFT 28
- #define TSENS_8X10_BASE1_SHIFT 8
- #define TSENS0_8X10_POINT1_SHIFT 16
- #define TSENS0_8X10_POINT2_SHIFT 22
- #define TSENS1_8X10_POINT2_SHIFT 6
- #define TSENS_8X10_BASE0_MASK 0xff
- #define TSENS_8X10_BASE1_MASK 0xff00
- #define TSENS0_8X10_POINT1_MASK 0x3f0000
- #define TSENS0_8X10_POINT2_MASK 0xfc00000
- #define TSENS_8X10_TSENS_CAL_SEL 0x70000000
- #define TSENS1_8X10_POINT1_MASK 0x3f
- #define TSENS1_8X10_POINT2_MASK 0xfc0
- #define TSENS_8X10_REDUN_SEL_MASK 0x6000000
- #define TSENS_8X10_REDUN_SEL_SHIFT 25
- #define TSENS_BIT_APPEND 0x3
- #define TSENS_CAL_DEGC_POINT1 30
- #define TSENS_CAL_DEGC_POINT2 120
- #define TSENS_SLOPE_FACTOR 1000
- /* TSENS register data */
- #define TSENS_TRDY_RDY_MIN_TIME 2000
- #define TSENS_TRDY_RDY_MAX_TIME 2100
- #define TSENS_THRESHOLD_MAX_CODE 0x3ff
- #define TSENS_THRESHOLD_MIN_CODE 0x0
- #define TSENS_GLOBAL_INIT_DATA 0x302f16c
- #define TSENS_S0_MAIN_CFG_INIT_DATA 0x1c3
- #define TSENS_SN_MIN_MAX_STATUS_CTRL_DATA 0x3ffc00
- #define TSENS_SN_REMOTE_CFG_DATA 0x11c3
- #define TSENS_QFPROM_BACKUP_SEL 0x3
- #define TSENS_QFPROM_BACKUP_REDUN_SEL 0xe0000000
- #define TSENS_QFPROM_BACKUP_REDUN_SHIFT 29
- enum tsens_calib_fuse_map_type {
- TSENS_CALIB_FUSE_MAP_8974 = 0,
- TSENS_CALIB_FUSE_MAP_8X26,
- TSENS_CALIB_FUSE_MAP_8X10,
- TSENS_CALIB_FUSE_MAP_NUM,
- };
- /* Trips: warm and cool */
- enum tsens_trip_type {
- TSENS_TRIP_WARM = 0,
- TSENS_TRIP_COOL,
- TSENS_TRIP_NUM,
- };
- struct tsens_tm_device_sensor {
- struct thermal_zone_device *tz_dev;
- enum thermal_device_mode mode;
- /* Physical HW sensor number */
- unsigned int sensor_hw_num;
- /* Software index. This is keep track of the HW/SW
- * sensor_ID mapping */
- unsigned int sensor_sw_id;
- struct work_struct work;
- int offset;
- int calib_data_point1;
- int calib_data_point2;
- uint32_t slope_mul_tsens_factor;
- };
- struct tsens_tm_device {
- struct platform_device *pdev;
- struct workqueue_struct *tsens_wq;
- bool prev_reading_avail;
- bool calibration_less_mode;
- bool tsens_local_init;
- int tsens_factor;
- uint32_t tsens_num_sensor;
- int tsens_irq;
- void *tsens_addr;
- void *tsens_calib_addr;
- int tsens_len;
- int calib_len;
- struct resource *res_tsens_mem;
- struct resource *res_calib_mem;
- struct work_struct tsens_work;
- uint32_t calib_mode;
- struct tsens_tm_device_sensor sensor[0];
- };
- struct tsens_tm_device *tmdev;
- int tsens_get_sw_id_mapping(int sensor_hw_num, int *sensor_sw_idx)
- {
- int i = 0;
- bool id_found = false;
- while (i < tmdev->tsens_num_sensor && !id_found) {
- if (sensor_hw_num == tmdev->sensor[i].sensor_hw_num) {
- *sensor_sw_idx = tmdev->sensor[i].sensor_sw_id;
- id_found = true;
- }
- i++;
- }
- if (!id_found)
- return -EINVAL;
- return 0;
- }
- EXPORT_SYMBOL(tsens_get_sw_id_mapping);
- int tsens_get_hw_id_mapping(int sensor_sw_id, int *sensor_hw_num)
- {
- int i = 0;
- bool id_found = false;
- while (i < tmdev->tsens_num_sensor && !id_found) {
- if (sensor_sw_id == tmdev->sensor[i].sensor_sw_id) {
- *sensor_hw_num = tmdev->sensor[i].sensor_hw_num;
- id_found = true;
- }
- i++;
- }
- if (!id_found)
- return -EINVAL;
- return 0;
- }
- EXPORT_SYMBOL(tsens_get_hw_id_mapping);
- static int tsens_tz_code_to_degc(int adc_code, int sensor_sw_id)
- {
- int degc, num, den, idx;
- idx = sensor_sw_id;
- num = ((adc_code * tmdev->tsens_factor) -
- tmdev->sensor[idx].offset);
- den = (int) tmdev->sensor[idx].slope_mul_tsens_factor;
- if (num > 0)
- degc = ((num + (den/2))/den);
- else if (num < 0)
- degc = ((num - (den/2))/den);
- else
- degc = num/den;
- pr_debug("raw_code:0x%x, sensor_num:%d, degc:%d\n",
- adc_code, idx, degc);
- return degc;
- }
- static int tsens_tz_degc_to_code(int degc, int idx)
- {
- int code = ((degc * tmdev->sensor[idx].slope_mul_tsens_factor)
- + tmdev->sensor[idx].offset)/tmdev->tsens_factor;
- if (code > TSENS_THRESHOLD_MAX_CODE)
- code = TSENS_THRESHOLD_MAX_CODE;
- else if (code < TSENS_THRESHOLD_MIN_CODE)
- code = TSENS_THRESHOLD_MIN_CODE;
- pr_debug("raw_code:0x%x, sensor_num:%d, degc:%d\n",
- code, idx, degc);
- return code;
- }
- static void msm_tsens_get_temp(int sensor_hw_num, unsigned long *temp)
- {
- unsigned int code, sensor_addr;
- int sensor_sw_id = -EINVAL, rc = 0;
- if (!tmdev->prev_reading_avail) {
- while (!(readl_relaxed(TSENS_TRDY_ADDR(tmdev->tsens_addr))
- & TSENS_TRDY_MASK))
- usleep_range(TSENS_TRDY_RDY_MIN_TIME,
- TSENS_TRDY_RDY_MAX_TIME);
- tmdev->prev_reading_avail = true;
- }
- sensor_addr =
- (unsigned int)TSENS_S0_STATUS_ADDR(tmdev->tsens_addr);
- code = readl_relaxed(sensor_addr +
- (sensor_hw_num << TSENS_STATUS_ADDR_OFFSET));
- /* Obtain SW index to map the corresponding thermal zone's
- * offset and slope for code to degc conversion. */
- rc = tsens_get_sw_id_mapping(sensor_hw_num, &sensor_sw_id);
- if (rc < 0) {
- pr_err("tsens mapping index not found\n");
- return;
- }
- *temp = tsens_tz_code_to_degc((code & TSENS_SN_STATUS_TEMP_MASK),
- sensor_sw_id);
- }
- static int tsens_tz_get_temp(struct thermal_zone_device *thermal,
- unsigned long *temp)
- {
- struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
- if (!tm_sensor || tm_sensor->mode != THERMAL_DEVICE_ENABLED || !temp)
- return -EINVAL;
- msm_tsens_get_temp(tm_sensor->sensor_hw_num, temp);
- return 0;
- }
- int tsens_get_temp(struct tsens_device *device, unsigned long *temp)
- {
- if (!tmdev)
- return -ENODEV;
- msm_tsens_get_temp(device->sensor_num, temp);
- return 0;
- }
- EXPORT_SYMBOL(tsens_get_temp);
- int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors)
- {
- if (!tmdev)
- return -ENODEV;
- *tsens_num_sensors = tmdev->tsens_num_sensor;
- return 0;
- }
- EXPORT_SYMBOL(tsens_get_max_sensor_num);
- static int tsens_tz_get_mode(struct thermal_zone_device *thermal,
- enum thermal_device_mode *mode)
- {
- struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
- if (!tm_sensor || !mode)
- return -EINVAL;
- *mode = tm_sensor->mode;
- return 0;
- }
- static int tsens_tz_get_trip_type(struct thermal_zone_device *thermal,
- int trip, enum thermal_trip_type *type)
- {
- struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
- if (!tm_sensor || trip < 0 || !type)
- return -EINVAL;
- switch (trip) {
- case TSENS_TRIP_WARM:
- *type = THERMAL_TRIP_CONFIGURABLE_HI;
- break;
- case TSENS_TRIP_COOL:
- *type = THERMAL_TRIP_CONFIGURABLE_LOW;
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
- static int tsens_tz_activate_trip_type(struct thermal_zone_device *thermal,
- int trip, enum thermal_trip_activation_mode mode)
- {
- struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
- unsigned int reg_cntl, code, hi_code, lo_code, mask;
- if (!tm_sensor || trip < 0)
- return -EINVAL;
- lo_code = TSENS_THRESHOLD_MIN_CODE;
- hi_code = TSENS_THRESHOLD_MAX_CODE;
- reg_cntl = readl_relaxed((TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
- (tmdev->tsens_addr) +
- (tm_sensor->sensor_hw_num *
- TSENS_SN_ADDR_OFFSET)));
- switch (trip) {
- case TSENS_TRIP_WARM:
- code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK)
- >> TSENS_UPPER_THRESHOLD_SHIFT;
- mask = TSENS_UPPER_STATUS_CLR;
- if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
- lo_code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK);
- break;
- case TSENS_TRIP_COOL:
- code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK);
- mask = TSENS_LOWER_STATUS_CLR;
- if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
- hi_code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK)
- >> TSENS_UPPER_THRESHOLD_SHIFT;
- break;
- default:
- return -EINVAL;
- }
- if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
- writel_relaxed(reg_cntl | mask,
- (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
- (tmdev->tsens_addr) +
- (tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET)));
- else {
- if (code < lo_code || code > hi_code) {
- pr_err("%s with invalid code %x\n", __func__, code);
- return -EINVAL;
- }
- writel_relaxed(reg_cntl & ~mask,
- (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(tmdev->tsens_addr) +
- (tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET)));
- }
- mb();
- return 0;
- }
- static int tsens_tz_get_trip_temp(struct thermal_zone_device *thermal,
- int trip, unsigned long *temp)
- {
- struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
- unsigned int reg;
- int sensor_sw_id = -EINVAL, rc = 0;
- if (!tm_sensor || trip < 0 || !temp)
- return -EINVAL;
- reg = readl_relaxed(TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
- (tmdev->tsens_addr) +
- (tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET));
- switch (trip) {
- case TSENS_TRIP_WARM:
- reg = (reg & TSENS_UPPER_THRESHOLD_MASK) >>
- TSENS_UPPER_THRESHOLD_SHIFT;
- break;
- case TSENS_TRIP_COOL:
- reg = (reg & TSENS_LOWER_THRESHOLD_MASK);
- break;
- default:
- return -EINVAL;
- }
- rc = tsens_get_sw_id_mapping(tm_sensor->sensor_hw_num, &sensor_sw_id);
- if (rc < 0) {
- pr_err("tsens mapping index not found\n");
- return rc;
- }
- *temp = tsens_tz_code_to_degc(reg, sensor_sw_id);
- return 0;
- }
- static int tsens_tz_notify(struct thermal_zone_device *thermal,
- int count, enum thermal_trip_type type)
- {
- /* Critical temperature threshold are enabled and will
- * shutdown the device once critical thresholds are crossed. */
- pr_debug("%s debug\n", __func__);
- return 1;
- }
- static int tsens_tz_set_trip_temp(struct thermal_zone_device *thermal,
- int trip, long temp)
- {
- struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
- unsigned int reg_cntl;
- int code, hi_code, lo_code, code_err_chk, sensor_sw_id = 0, rc = 0;
- if (!tm_sensor || trip < 0)
- return -EINVAL;
- rc = tsens_get_sw_id_mapping(tm_sensor->sensor_hw_num, &sensor_sw_id);
- if (rc < 0) {
- pr_err("tsens mapping index not found\n");
- return rc;
- }
- code_err_chk = code = tsens_tz_degc_to_code(temp, sensor_sw_id);
- if (!tm_sensor || trip < 0)
- return -EINVAL;
- lo_code = TSENS_THRESHOLD_MIN_CODE;
- hi_code = TSENS_THRESHOLD_MAX_CODE;
- reg_cntl = readl_relaxed(TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
- (tmdev->tsens_addr) + (tm_sensor->sensor_hw_num *
- TSENS_SN_ADDR_OFFSET));
- switch (trip) {
- case TSENS_TRIP_WARM:
- code <<= TSENS_UPPER_THRESHOLD_SHIFT;
- reg_cntl &= ~TSENS_UPPER_THRESHOLD_MASK;
- if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
- lo_code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK);
- break;
- case TSENS_TRIP_COOL:
- reg_cntl &= ~TSENS_LOWER_THRESHOLD_MASK;
- if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
- hi_code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK)
- >> TSENS_UPPER_THRESHOLD_SHIFT;
- break;
- default:
- return -EINVAL;
- }
- if (code_err_chk < lo_code || code_err_chk > hi_code)
- return -EINVAL;
- writel_relaxed(reg_cntl | code, (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
- (tmdev->tsens_addr) +
- (tm_sensor->sensor_hw_num *
- TSENS_SN_ADDR_OFFSET)));
- mb();
- return 0;
- }
- static struct thermal_zone_device_ops tsens_thermal_zone_ops = {
- .get_temp = tsens_tz_get_temp,
- .get_mode = tsens_tz_get_mode,
- .get_trip_type = tsens_tz_get_trip_type,
- .activate_trip_type = tsens_tz_activate_trip_type,
- .get_trip_temp = tsens_tz_get_trip_temp,
- .set_trip_temp = tsens_tz_set_trip_temp,
- .notify = tsens_tz_notify,
- };
- static void notify_uspace_tsens_fn(struct work_struct *work)
- {
- struct tsens_tm_device_sensor *tm = container_of(work,
- struct tsens_tm_device_sensor, work);
- sysfs_notify(&tm->tz_dev->device.kobj,
- NULL, "type");
- }
- static void tsens_scheduler_fn(struct work_struct *work)
- {
- struct tsens_tm_device *tm = container_of(work, struct tsens_tm_device,
- tsens_work);
- unsigned int i, status, threshold;
- unsigned int sensor_status_addr, sensor_status_ctrl_addr;
- int sensor_sw_id = -EINVAL, rc = 0;
- sensor_status_addr =
- (unsigned int)TSENS_S0_STATUS_ADDR(tmdev->tsens_addr);
- sensor_status_ctrl_addr =
- (unsigned int)TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
- (tmdev->tsens_addr);
- for (i = 0; i < tm->tsens_num_sensor; i++) {
- bool upper_thr = false, lower_thr = false;
- uint32_t addr_offset;
- addr_offset = tm->sensor[i].sensor_hw_num *
- TSENS_SN_ADDR_OFFSET;
- status = readl_relaxed(sensor_status_addr + addr_offset);
- threshold = readl_relaxed(sensor_status_ctrl_addr +
- addr_offset);
- if (status & TSENS_SN_STATUS_UPPER_STATUS) {
- writel_relaxed(threshold | TSENS_UPPER_STATUS_CLR,
- TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(
- tmdev->tsens_addr + addr_offset));
- upper_thr = true;
- }
- if (status & TSENS_SN_STATUS_LOWER_STATUS) {
- writel_relaxed(threshold | TSENS_LOWER_STATUS_CLR,
- TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(
- tmdev->tsens_addr + addr_offset));
- lower_thr = true;
- }
- if (upper_thr || lower_thr) {
- unsigned long temp;
- enum thermal_trip_type trip =
- THERMAL_TRIP_CONFIGURABLE_LOW;
- if (upper_thr)
- trip = THERMAL_TRIP_CONFIGURABLE_HI;
- tsens_tz_get_temp(tm->sensor[i].tz_dev, &temp);
- thermal_sensor_trip(tm->sensor[i].tz_dev, trip, temp);
- /* Notify user space */
- queue_work(tm->tsens_wq, &tm->sensor[i].work);
- rc = tsens_get_sw_id_mapping(
- tm->sensor[i].sensor_hw_num,
- &sensor_sw_id);
- if (rc < 0)
- pr_err("tsens mapping index not found\n");
- pr_debug("sensor:%d trigger temp (%d degC)\n",
- tm->sensor[i].sensor_hw_num,
- tsens_tz_code_to_degc((status &
- TSENS_SN_STATUS_TEMP_MASK),
- sensor_sw_id));
- }
- }
- mb();
- }
- static irqreturn_t tsens_isr(int irq, void *data)
- {
- queue_work(tmdev->tsens_wq, &tmdev->tsens_work);
- return IRQ_HANDLED;
- }
- static void tsens_hw_init(void)
- {
- unsigned int reg_cntl = 0, sensor_en = 0;
- unsigned int i;
- if (tmdev->tsens_local_init) {
- writel_relaxed(reg_cntl, TSENS_CTRL_ADDR(tmdev->tsens_addr));
- writel_relaxed(reg_cntl | TSENS_SW_RST,
- TSENS_CTRL_ADDR(tmdev->tsens_addr));
- reg_cntl |= (TSENS_62_5_MS_MEAS_PERIOD <<
- TSENS_MEAS_PERIOD_SHIFT);
- for (i = 0; i < tmdev->tsens_num_sensor; i++)
- sensor_en |= (1 << tmdev->sensor[i].sensor_hw_num);
- sensor_en <<= TSENS_SENSOR0_SHIFT;
- reg_cntl |= (sensor_en | TSENS_EN);
- writel_relaxed(reg_cntl, TSENS_CTRL_ADDR(tmdev->tsens_addr));
- writel_relaxed(TSENS_GLOBAL_INIT_DATA,
- TSENS_GLOBAL_CONFIG(tmdev->tsens_addr));
- writel_relaxed(TSENS_S0_MAIN_CFG_INIT_DATA,
- TSENS_S0_MAIN_CONFIG(tmdev->tsens_addr));
- for (i = 0; i < tmdev->tsens_num_sensor; i++) {
- writel_relaxed(TSENS_SN_MIN_MAX_STATUS_CTRL_DATA,
- TSENS_SN_MIN_MAX_STATUS_CTRL(tmdev->tsens_addr)
- + (tmdev->sensor[i].sensor_hw_num *
- TSENS_SN_ADDR_OFFSET));
- writel_relaxed(TSENS_SN_REMOTE_CFG_DATA,
- TSENS_SN_REMOTE_CONFIG(tmdev->tsens_addr)
- + (tmdev->sensor[i].sensor_hw_num *
- TSENS_SN_ADDR_OFFSET));
- }
- pr_debug("Local TSENS control initialization\n");
- }
- writel_relaxed(TSENS_INTERRUPT_EN,
- TSENS_UPPER_LOWER_INTERRUPT_CTRL(tmdev->tsens_addr));
- }
- static int tsens_calib_8x10_sensors(void)
- {
- int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
- int tsens0_point2 = 0, tsens1_point2 = 0;
- int tsens_base1_data = 0, tsens_calibration_mode = 0;
- uint32_t calib_data[2], calib_redun_sel;
- uint32_t calib_tsens_point1_data[2], calib_tsens_point2_data[2];
- if (tmdev->calibration_less_mode)
- goto calibration_less_mode;
- calib_redun_sel = readl_relaxed(
- TSENS_EEPROM_8X10_2(tmdev->tsens_calib_addr));
- calib_redun_sel = calib_redun_sel & TSENS_8X10_REDUN_SEL_MASK;
- calib_redun_sel >>= TSENS_8X10_REDUN_SEL_SHIFT;
- pr_debug("calib_redun_sel:%x\n", calib_redun_sel);
- if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) {
- calib_data[0] = readl_relaxed(
- TSENS_EEPROM_8X10_SPARE_1(tmdev->tsens_calib_addr));
- calib_data[1] = readl_relaxed(
- TSENS_EEPROM_8X10_SPARE_2(tmdev->tsens_calib_addr));
- } else {
- calib_data[0] = readl_relaxed(
- TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr));
- calib_data[1] = readl_relaxed(
- (TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr) +
- TSENS_EEPROM_8X10_1_OFFSET));
- }
- tsens_calibration_mode = (calib_data[0] & TSENS_8X10_TSENS_CAL_SEL)
- >> TSENS_8X10_CAL_SEL_SHIFT;
- pr_debug("calib mode scheme:%x\n", tsens_calibration_mode);
- if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB) ||
- (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) {
- tsens_base0_data = (calib_data[0] & TSENS_8X10_BASE0_MASK);
- tsens0_point1 = (calib_data[0] & TSENS0_8X10_POINT1_MASK) >>
- TSENS0_8X10_POINT1_SHIFT;
- tsens1_point1 = calib_data[1] & TSENS1_8X10_POINT1_MASK;
- } else
- goto calibration_less_mode;
- if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- tsens_base1_data = (calib_data[0] & TSENS_8X10_BASE1_MASK) >>
- TSENS_8X10_BASE1_SHIFT;
- tsens0_point2 = (calib_data[0] & TSENS0_8X10_POINT2_MASK) >>
- TSENS0_8X10_POINT2_SHIFT;
- tsens1_point2 = (calib_data[1] & TSENS1_8X10_POINT2_MASK) >>
- TSENS1_8X10_POINT2_SHIFT;
- }
- if (tsens_calibration_mode == 0) {
- calibration_less_mode:
- pr_debug("TSENS is calibrationless mode\n");
- for (i = 0; i < tmdev->tsens_num_sensor; i++)
- calib_tsens_point2_data[i] = 780;
- calib_tsens_point1_data[0] = 595;
- calib_tsens_point1_data[1] = 629;
- goto compute_intercept_slope;
- }
- if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
- (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
- calib_tsens_point1_data[0] =
- ((((tsens_base0_data) + tsens0_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[1] =
- ((((tsens_base0_data) + tsens1_point1) << 2) |
- TSENS_BIT_APPEND);
- }
- if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- pr_debug("two point calibration calculation\n");
- calib_tsens_point2_data[0] =
- (((tsens_base1_data + tsens0_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[1] =
- (((tsens_base1_data + tsens1_point2) << 2) |
- TSENS_BIT_APPEND);
- }
- compute_intercept_slope:
- for (i = 0; i < tmdev->tsens_num_sensor; i++) {
- int32_t num = 0, den = 0;
- tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
- tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
- pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
- i, tmdev->sensor[i].calib_data_point1,
- tmdev->sensor[i].calib_data_point2);
- if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- /* slope (m) = adc_code2 - adc_code1 (y2 - y1)/
- temp_120_degc - temp_30_degc (x2 - x1) */
- num = tmdev->sensor[i].calib_data_point2 -
- tmdev->sensor[i].calib_data_point1;
- num *= tmdev->tsens_factor;
- den = TSENS_CAL_DEGC_POINT2 - TSENS_CAL_DEGC_POINT1;
- tmdev->sensor[i].slope_mul_tsens_factor = num/den;
- }
- tmdev->sensor[i].offset = (tmdev->sensor[i].calib_data_point1 *
- tmdev->tsens_factor) - (TSENS_CAL_DEGC_POINT1 *
- tmdev->sensor[i].slope_mul_tsens_factor);
- INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn);
- tmdev->prev_reading_avail = false;
- }
- return 0;
- }
- static int tsens_calib_8x26_sensors(void)
- {
- int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
- int tsens2_point1 = 0, tsens3_point1 = 0, tsens4_point1 = 0;
- int tsens5_point1 = 0, tsens6_point1 = 0, tsens6_point2 = 0;
- int tsens0_point2 = 0, tsens1_point2 = 0, tsens2_point2 = 0;
- int tsens3_point2 = 0, tsens4_point2 = 0, tsens5_point2 = 0;
- int tsens_base1_data = 0, tsens_calibration_mode = 0;
- uint32_t calib_data[6];
- uint32_t calib_tsens_point1_data[7], calib_tsens_point2_data[7];
- if (tmdev->calibration_less_mode)
- goto calibration_less_mode;
- for (i = 0; i < TSENS_8X26_MAIN_CALIB_ADDR_RANGE; i++)
- calib_data[i] = readl_relaxed(
- (TSENS_EEPROM_8X26_1(tmdev->tsens_calib_addr))
- + (i * TSENS_SN_ADDR_OFFSET));
- calib_data[4] = readl_relaxed(
- (TSENS_EEPROM_8X26_2(tmdev->tsens_calib_addr)));
- calib_data[5] = readl_relaxed(
- (TSENS_EEPROM_8X26_2(tmdev->tsens_calib_addr)) + 0x8);
- tsens_calibration_mode = (calib_data[5] & TSENS_8X26_TSENS_CAL_SEL)
- >> TSENS_8X26_CAL_SEL_SHIFT;
- pr_debug("calib mode scheme:%x\n", tsens_calibration_mode);
- if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB) ||
- (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) {
- tsens_base0_data = (calib_data[0] & TSENS_8X26_BASE0_MASK)
- >> TSENS_8X26_BASE0_SHIFT;
- tsens0_point1 = (calib_data[0] & TSENS0_8X26_POINT1_MASK) >>
- TSENS0_8X26_POINT1_SHIFT;
- tsens1_point1 = calib_data[1] & TSENS1_8X26_POINT1_MASK;
- tsens2_point1 = (calib_data[1] & TSENS2_8X26_POINT1_MASK) >>
- TSENS2_8X26_POINT1_SHIFT;
- tsens3_point1 = (calib_data[1] & TSENS3_8X26_POINT1_MASK) >>
- TSENS3_8X26_POINT1_SHIFT;
- tsens4_point1 = (calib_data[1] & TSENS4_8X26_POINT1_MASK) >>
- TSENS4_8X26_POINT1_SHIFT;
- tsens5_point1 = (calib_data[1] & TSENS5_8X26_POINT1_MASK) >>
- TSENS5_8X26_POINT1_SHIFT;
- tsens6_point1 = (calib_data[2] & TSENS6_8X26_POINT1_MASK) >>
- TSENS6_8X26_POINT1_SHIFT;
- } else
- goto calibration_less_mode;
- if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- tsens_base1_data = (calib_data[3] & TSENS_8X26_BASE1_MASK);
- tsens0_point2 = (calib_data[3] & TSENS0_8X26_POINT2_MASK) >>
- TSENS0_8X26_POINT2_SHIFT;
- tsens1_point2 = (calib_data[3] & TSENS1_8X26_POINT2_MASK) >>
- TSENS1_8X26_POINT2_SHIFT;
- tsens2_point2 = (calib_data[3] & TSENS2_8X26_POINT2_MASK) >>
- TSENS2_8X26_POINT2_SHIFT;
- tsens3_point2 = (calib_data[3] & TSENS3_8X26_POINT2_MASK) >>
- TSENS3_8X26_POINT2_SHIFT;
- tsens4_point2 = (calib_data[4] & TSENS4_8X26_POINT2_MASK) >>
- TSENS4_8X26_POINT2_SHIFT;
- tsens5_point2 = (calib_data[4] & TSENS5_8X26_POINT2_MASK) >>
- TSENS5_8X26_POINT2_SHIFT;
- tsens6_point2 = (calib_data[5] & TSENS6_8X26_POINT2_MASK) >>
- TSENS6_8X26_POINT2_SHIFT;
- }
- if (tsens_calibration_mode == 0) {
- calibration_less_mode:
- pr_debug("TSENS is calibrationless mode\n");
- for (i = 0; i < tmdev->tsens_num_sensor; i++)
- calib_tsens_point2_data[i] = 780;
- calib_tsens_point1_data[0] = 595;
- calib_tsens_point1_data[1] = 625;
- calib_tsens_point1_data[2] = 553;
- calib_tsens_point1_data[3] = 578;
- calib_tsens_point1_data[4] = 505;
- calib_tsens_point1_data[5] = 509;
- calib_tsens_point1_data[6] = 507;
- goto compute_intercept_slope;
- }
- if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
- (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
- calib_tsens_point1_data[0] =
- ((((tsens_base0_data) + tsens0_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[1] =
- ((((tsens_base0_data) + tsens1_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[2] =
- ((((tsens_base0_data) + tsens2_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[3] =
- ((((tsens_base0_data) + tsens3_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[4] =
- ((((tsens_base0_data) + tsens4_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[5] =
- ((((tsens_base0_data) + tsens5_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[6] =
- ((((tsens_base0_data) + tsens6_point1) << 2) |
- TSENS_BIT_APPEND);
- }
- if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- pr_debug("two point calibration calculation\n");
- calib_tsens_point2_data[0] =
- (((tsens_base1_data + tsens0_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[1] =
- (((tsens_base1_data + tsens1_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[2] =
- (((tsens_base1_data + tsens2_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[3] =
- (((tsens_base1_data + tsens3_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[4] =
- (((tsens_base1_data + tsens4_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[5] =
- (((tsens_base1_data + tsens5_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[6] =
- (((tsens_base1_data + tsens6_point2) << 2) |
- TSENS_BIT_APPEND);
- }
- compute_intercept_slope:
- for (i = 0; i < tmdev->tsens_num_sensor; i++) {
- int32_t num = 0, den = 0;
- tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
- tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
- pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
- i, tmdev->sensor[i].calib_data_point1,
- tmdev->sensor[i].calib_data_point2);
- if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- /* slope (m) = adc_code2 - adc_code1 (y2 - y1)/
- temp_120_degc - temp_30_degc (x2 - x1) */
- num = tmdev->sensor[i].calib_data_point2 -
- tmdev->sensor[i].calib_data_point1;
- num *= tmdev->tsens_factor;
- den = TSENS_CAL_DEGC_POINT2 - TSENS_CAL_DEGC_POINT1;
- tmdev->sensor[i].slope_mul_tsens_factor = num/den;
- }
- tmdev->sensor[i].offset = (tmdev->sensor[i].calib_data_point1 *
- tmdev->tsens_factor) - (TSENS_CAL_DEGC_POINT1 *
- tmdev->sensor[i].slope_mul_tsens_factor);
- INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn);
- tmdev->prev_reading_avail = false;
- }
- return 0;
- }
- static int tsens_calib_8974_sensors(void)
- {
- int i, tsens_base1_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
- int tsens2_point1 = 0, tsens3_point1 = 0, tsens4_point1 = 0;
- int tsens5_point1 = 0, tsens6_point1 = 0, tsens7_point1 = 0;
- int tsens8_point1 = 0, tsens9_point1 = 0, tsens10_point1 = 0;
- int tsens0_point2 = 0, tsens1_point2 = 0, tsens2_point2 = 0;
- int tsens3_point2 = 0, tsens4_point2 = 0, tsens5_point2 = 0;
- int tsens6_point2 = 0, tsens7_point2 = 0, tsens8_point2 = 0;
- int tsens9_point2 = 0, tsens10_point2 = 0;
- int tsens_base2_data = 0, tsens_calibration_mode = 0, temp = 0;
- uint32_t calib_data[6], calib_redun_sel, calib_data_backup[4];
- uint32_t calib_tsens_point1_data[11], calib_tsens_point2_data[11];
- if (tmdev->calibration_less_mode)
- goto calibration_less_mode;
- calib_redun_sel = readl_relaxed(
- TSENS_EEPROM_REDUNDANCY_SEL(tmdev->tsens_calib_addr));
- calib_redun_sel = calib_redun_sel & TSENS_QFPROM_BACKUP_REDUN_SEL;
- calib_redun_sel >>= TSENS_QFPROM_BACKUP_REDUN_SHIFT;
- pr_debug("calib_redun_sel:%x\n", calib_redun_sel);
- for (i = 0; i < TSENS_MAIN_CALIB_ADDR_RANGE; i++) {
- calib_data[i] = readl_relaxed(
- (TSENS_EEPROM(tmdev->tsens_calib_addr))
- + (i * TSENS_SN_ADDR_OFFSET));
- pr_debug("calib raw data row%d:0x%x\n", i, calib_data[i]);
- }
- if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) {
- tsens_calibration_mode = (calib_data[4] & TSENS_CAL_SEL_0_1)
- >> TSENS_CAL_SEL_SHIFT;
- temp = (calib_data[5] & TSENS_CAL_SEL_2)
- >> TSENS_CAL_SEL_SHIFT_2;
- tsens_calibration_mode |= temp;
- pr_debug("backup calib mode:%x\n", calib_redun_sel);
- for (i = 0; i < TSENS_BACKUP_CALIB_ADDR_RANGE; i++)
- calib_data_backup[i] = readl_relaxed(
- (TSENS_EEPROM_BACKUP_REGION(
- tmdev->tsens_calib_addr))
- + (i * TSENS_SN_ADDR_OFFSET));
- if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB)
- || (tsens_calibration_mode ==
- TSENS_TWO_POINT_CALIB) ||
- (tsens_calibration_mode ==
- TSENS_ONE_POINT_CALIB_OPTION_2)) {
- tsens_base1_data = (calib_data_backup[0] &
- TSENS_BASE1_MASK);
- tsens0_point1 = (calib_data_backup[0] &
- TSENS0_POINT1_MASK) >>
- TSENS0_POINT1_SHIFT;
- tsens1_point1 = (calib_data_backup[0] &
- TSENS1_POINT1_MASK) >> TSENS1_POINT1_SHIFT;
- tsens2_point1 = (calib_data_backup[0] &
- TSENS2_POINT1_MASK) >> TSENS2_POINT1_SHIFT;
- tsens3_point1 = (calib_data_backup[0] &
- TSENS3_POINT1_MASK) >> TSENS3_POINT1_SHIFT;
- tsens4_point1 = (calib_data_backup[1] &
- TSENS4_POINT1_MASK);
- tsens5_point1 = (calib_data_backup[1] &
- TSENS5_POINT1_MASK) >> TSENS5_POINT1_SHIFT;
- tsens6_point1 = (calib_data_backup[1] &
- TSENS6_POINT1_MASK) >> TSENS6_POINT1_SHIFT;
- tsens7_point1 = (calib_data_backup[1] &
- TSENS7_POINT1_MASK) >> TSENS7_POINT1_SHIFT;
- tsens8_point1 = (calib_data_backup[2] &
- TSENS8_POINT1_MASK_BACKUP) >>
- TSENS8_POINT1_SHIFT;
- tsens9_point1 = (calib_data_backup[2] &
- TSENS9_POINT1_MASK_BACKUP) >>
- TSENS9_POINT1_BACKUP_SHIFT;
- tsens10_point1 = (calib_data_backup[2] &
- TSENS10_POINT1_MASK_BACKUP) >>
- TSENS10_POINT1_BACKUP_SHIFT;
- } else
- goto calibration_less_mode;
- if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- tsens_base2_data = (calib_data_backup[2] &
- TSENS_BASE2_BACKUP_MASK) >>
- TSENS_POINT2_BASE_BACKUP_SHIFT;
- tsens0_point2 = (calib_data_backup[2] &
- TSENS0_POINT2_BACKUP_MASK) >>
- TSENS0_POINT2_BACKUP_SHIFT;
- tsens1_point2 = (calib_data_backup[3] &
- TSENS1_POINT2_BACKUP_MASK);
- tsens2_point2 = (calib_data_backup[3] &
- TSENS2_POINT2_BACKUP_MASK) >>
- TSENS2_POINT2_BACKUP_SHIFT;
- tsens3_point2 = (calib_data_backup[3] &
- TSENS3_POINT2_BACKUP_MASK) >>
- TSENS3_POINT2_BACKUP_SHIFT;
- tsens4_point2 = (calib_data_backup[3] &
- TSENS4_POINT2_BACKUP_MASK) >>
- TSENS4_POINT2_BACKUP_SHIFT;
- tsens5_point2 = (calib_data[4] &
- TSENS5_POINT2_BACKUP_MASK) >>
- TSENS5_POINT2_BACKUP_SHIFT;
- tsens6_point2 = (calib_data[5] &
- TSENS6_POINT2_BACKUP_MASK);
- tsens7_point2 = (calib_data[5] &
- TSENS7_POINT2_BACKUP_MASK) >>
- TSENS7_POINT2_BACKUP_SHIFT;
- tsens8_point2 = (calib_data[5] &
- TSENS8_POINT2_BACKUP_MASK) >>
- TSENS8_POINT2_BACKUP_SHIFT;
- tsens9_point2 = (calib_data[5] &
- TSENS9_POINT2_BACKUP_MASK) >>
- TSENS9_POINT2_BACKUP_SHIFT;
- tsens10_point2 = (calib_data[5] &
- TSENS10_POINT2_BACKUP_MASK)
- >> TSENS10_POINT2_BACKUP_SHIFT;
- }
- } else {
- tsens_calibration_mode = (calib_data[1] & TSENS_CAL_SEL_0_1)
- >> TSENS_CAL_SEL_SHIFT;
- temp = (calib_data[3] & TSENS_CAL_SEL_2)
- >> TSENS_CAL_SEL_SHIFT_2;
- tsens_calibration_mode |= temp;
- pr_debug("calib mode scheme:%x\n", tsens_calibration_mode);
- if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB) ||
- (tsens_calibration_mode ==
- TSENS_ONE_POINT_CALIB_OPTION_2) ||
- (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
- tsens_base1_data = (calib_data[0] & TSENS_BASE1_MASK);
- tsens0_point1 = (calib_data[0] & TSENS0_POINT1_MASK) >>
- TSENS0_POINT1_SHIFT;
- tsens1_point1 = (calib_data[0] & TSENS1_POINT1_MASK) >>
- TSENS1_POINT1_SHIFT;
- tsens2_point1 = (calib_data[0] & TSENS2_POINT1_MASK) >>
- TSENS2_POINT1_SHIFT;
- tsens3_point1 = (calib_data[0] & TSENS3_POINT1_MASK) >>
- TSENS3_POINT1_SHIFT;
- tsens4_point1 = (calib_data[1] & TSENS4_POINT1_MASK);
- tsens5_point1 = (calib_data[1] & TSENS5_POINT1_MASK) >>
- TSENS5_POINT1_SHIFT;
- tsens6_point1 = (calib_data[1] & TSENS6_POINT1_MASK) >>
- TSENS6_POINT1_SHIFT;
- tsens7_point1 = (calib_data[1] & TSENS7_POINT1_MASK) >>
- TSENS7_POINT1_SHIFT;
- tsens8_point1 = (calib_data[1] & TSENS8_POINT1_MASK) >>
- TSENS8_POINT1_SHIFT;
- tsens9_point1 = (calib_data[2] & TSENS9_POINT1_MASK);
- tsens10_point1 = (calib_data[2] & TSENS10_POINT1_MASK)
- >> TSENS10_POINT1_SHIFT;
- } else
- goto calibration_less_mode;
- if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- tsens_base2_data = (calib_data[2] & TSENS_BASE2_MASK) >>
- TSENS_POINT2_BASE_SHIFT;
- tsens0_point2 = (calib_data[2] & TSENS0_POINT2_MASK) >>
- TSENS0_POINT2_SHIFT;
- tsens1_point2 = (calib_data[2] & TSENS1_POINT2_MASK) >>
- TSENS1_POINT2_SHIFT;
- tsens2_point2 = (calib_data[3] & TSENS2_POINT2_MASK);
- tsens3_point2 = (calib_data[3] & TSENS3_POINT2_MASK) >>
- TSENS3_POINT2_SHIFT;
- tsens4_point2 = (calib_data[3] & TSENS4_POINT2_MASK) >>
- TSENS4_POINT2_SHIFT;
- tsens5_point2 = (calib_data[3] & TSENS5_POINT2_MASK) >>
- TSENS5_POINT2_SHIFT;
- tsens6_point2 = (calib_data[3] & TSENS6_POINT2_MASK) >>
- TSENS6_POINT2_SHIFT;
- tsens7_point2 = (calib_data[4] & TSENS7_POINT2_MASK);
- tsens8_point2 = (calib_data[4] & TSENS8_POINT2_MASK) >>
- TSENS8_POINT2_SHIFT;
- tsens9_point2 = (calib_data[4] & TSENS9_POINT2_MASK) >>
- TSENS9_POINT2_SHIFT;
- tsens10_point2 = (calib_data[4] & TSENS10_POINT2_MASK)
- >> TSENS10_POINT2_SHIFT;
- }
- if (tsens_calibration_mode == 0) {
- calibration_less_mode:
- pr_debug("TSENS is calibrationless mode\n");
- for (i = 0; i < tmdev->tsens_num_sensor; i++)
- calib_tsens_point2_data[i] = 780;
- calib_tsens_point1_data[0] = 502;
- calib_tsens_point1_data[1] = 509;
- calib_tsens_point1_data[2] = 503;
- calib_tsens_point1_data[3] = 509;
- calib_tsens_point1_data[4] = 505;
- calib_tsens_point1_data[5] = 509;
- calib_tsens_point1_data[6] = 507;
- calib_tsens_point1_data[7] = 510;
- calib_tsens_point1_data[8] = 508;
- calib_tsens_point1_data[9] = 509;
- calib_tsens_point1_data[10] = 508;
- goto compute_intercept_slope;
- }
- }
- if (tsens_calibration_mode == TSENS_ONE_POINT_CALIB) {
- calib_tsens_point1_data[0] =
- (((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
- + tsens0_point1;
- calib_tsens_point1_data[1] =
- (((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
- + tsens1_point1;
- calib_tsens_point1_data[2] =
- (((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
- + tsens2_point1;
- calib_tsens_point1_data[3] =
- (((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
- + tsens3_point1;
- calib_tsens_point1_data[4] =
- (((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
- + tsens4_point1;
- calib_tsens_point1_data[5] =
- (((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
- + tsens5_point1;
- calib_tsens_point1_data[6] =
- (((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
- + tsens6_point1;
- calib_tsens_point1_data[7] =
- (((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
- + tsens7_point1;
- calib_tsens_point1_data[8] =
- (((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
- + tsens8_point1;
- calib_tsens_point1_data[9] =
- (((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
- + tsens9_point1;
- calib_tsens_point1_data[10] =
- (((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
- + tsens10_point1;
- }
- if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
- (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
- pr_debug("one point calibration calculation\n");
- calib_tsens_point1_data[0] =
- ((((tsens_base1_data) + tsens0_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[1] =
- ((((tsens_base1_data) + tsens1_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[2] =
- ((((tsens_base1_data) + tsens2_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[3] =
- ((((tsens_base1_data) + tsens3_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[4] =
- ((((tsens_base1_data) + tsens4_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[5] =
- ((((tsens_base1_data) + tsens5_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[6] =
- ((((tsens_base1_data) + tsens6_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[7] =
- ((((tsens_base1_data) + tsens7_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[8] =
- ((((tsens_base1_data) + tsens8_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[9] =
- ((((tsens_base1_data) + tsens9_point1) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point1_data[10] =
- ((((tsens_base1_data) + tsens10_point1) << 2) |
- TSENS_BIT_APPEND);
- }
- if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- pr_debug("two point calibration calculation\n");
- calib_tsens_point2_data[0] =
- (((tsens_base2_data + tsens0_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[1] =
- (((tsens_base2_data + tsens1_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[2] =
- (((tsens_base2_data + tsens2_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[3] =
- (((tsens_base2_data + tsens3_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[4] =
- (((tsens_base2_data + tsens4_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[5] =
- (((tsens_base2_data + tsens5_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[6] =
- (((tsens_base2_data + tsens6_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[7] =
- (((tsens_base2_data + tsens7_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[8] =
- (((tsens_base2_data + tsens8_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[9] =
- (((tsens_base2_data + tsens9_point2) << 2) |
- TSENS_BIT_APPEND);
- calib_tsens_point2_data[10] =
- (((tsens_base2_data + tsens10_point2) << 2) |
- TSENS_BIT_APPEND);
- }
- compute_intercept_slope:
- for (i = 0; i < tmdev->tsens_num_sensor; i++) {
- int32_t num = 0, den = 0;
- tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
- tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
- pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
- i, tmdev->sensor[i].calib_data_point1,
- tmdev->sensor[i].calib_data_point2);
- if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- /* slope (m) = adc_code2 - adc_code1 (y2 - y1)/
- temp_120_degc - temp_30_degc (x2 - x1) */
- num = tmdev->sensor[i].calib_data_point2 -
- tmdev->sensor[i].calib_data_point1;
- num *= tmdev->tsens_factor;
- den = TSENS_CAL_DEGC_POINT2 - TSENS_CAL_DEGC_POINT1;
- tmdev->sensor[i].slope_mul_tsens_factor = num/den;
- }
- tmdev->sensor[i].offset = (tmdev->sensor[i].calib_data_point1 *
- tmdev->tsens_factor) - (TSENS_CAL_DEGC_POINT1 *
- tmdev->sensor[i].slope_mul_tsens_factor);
- pr_debug("offset:%d\n", tmdev->sensor[i].offset);
- INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn);
- tmdev->prev_reading_avail = false;
- }
- return 0;
- }
- static int tsens_calib_sensors(void)
- {
- int rc = 0;
- if (!tmdev)
- return -ENODEV;
- if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8974)
- rc = tsens_calib_8974_sensors();
- else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8X26)
- rc = tsens_calib_8x26_sensors();
- else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8X10)
- rc = tsens_calib_8x10_sensors();
- else
- rc = -ENODEV;
- return rc;
- }
- static int get_device_tree_data(struct platform_device *pdev)
- {
- struct device_node *of_node = pdev->dev.of_node;
- struct resource *res_mem = NULL;
- u32 *tsens_slope_data;
- u32 *sensor_id;
- u32 rc = 0, i, tsens_num_sensors, calib_type;
- const char *tsens_calib_mode;
- rc = of_property_read_u32(of_node,
- "qcom,sensors", &tsens_num_sensors);
- if (rc) {
- dev_err(&pdev->dev, "missing sensor number\n");
- return -ENODEV;
- }
- tsens_slope_data = devm_kzalloc(&pdev->dev,
- tsens_num_sensors * sizeof(u32), GFP_KERNEL);
- if (!tsens_slope_data) {
- dev_err(&pdev->dev, "can not allocate slope data\n");
- return -ENOMEM;
- }
- rc = of_property_read_u32_array(of_node,
- "qcom,slope", tsens_slope_data, tsens_num_sensors);
- if (rc) {
- dev_err(&pdev->dev, "invalid or missing property: tsens-slope\n");
- return rc;
- };
- rc = of_property_read_string(of_node,
- "qcom,calib-mode", &tsens_calib_mode);
- if (rc) {
- dev_err(&pdev->dev, "missing calib-mode\n");
- return -ENODEV;
- }
- if (!strncmp(tsens_calib_mode, "fuse_map1", 9))
- calib_type = TSENS_CALIB_FUSE_MAP_8974;
- else if (!strncmp(tsens_calib_mode, "fuse_map2", 9))
- calib_type = TSENS_CALIB_FUSE_MAP_8X26;
- else if (!strncmp(tsens_calib_mode, "fuse_map3", 9))
- calib_type = TSENS_CALIB_FUSE_MAP_8X10;
- else {
- pr_err("%s: Invalid calibration property\n", __func__);
- return -EINVAL;
- }
- tmdev = devm_kzalloc(&pdev->dev,
- sizeof(struct tsens_tm_device) +
- tsens_num_sensors *
- sizeof(struct tsens_tm_device_sensor),
- GFP_KERNEL);
- if (tmdev == NULL) {
- pr_err("%s: kzalloc() failed.\n", __func__);
- return -ENOMEM;
- }
- for (i = 0; i < tsens_num_sensors; i++)
- tmdev->sensor[i].slope_mul_tsens_factor = tsens_slope_data[i];
- tmdev->tsens_factor = TSENS_SLOPE_FACTOR;
- tmdev->tsens_num_sensor = tsens_num_sensors;
- tmdev->calibration_less_mode = of_property_read_bool(of_node,
- "qcom,calibration-less-mode");
- tmdev->calib_mode = calib_type;
- tmdev->tsens_local_init = of_property_read_bool(of_node,
- "qcom,tsens-local-init");
- sensor_id = devm_kzalloc(&pdev->dev,
- tsens_num_sensors * sizeof(u32), GFP_KERNEL);
- if (!sensor_id) {
- dev_err(&pdev->dev, "can not allocate sensor id\n");
- return -ENOMEM;
- }
- rc = of_property_read_u32_array(of_node,
- "qcom,sensor-id", sensor_id, tsens_num_sensors);
- if (rc) {
- pr_debug("Default sensor id mapping\n");
- for (i = 0; i < tsens_num_sensors; i++) {
- tmdev->sensor[i].sensor_hw_num = i;
- tmdev->sensor[i].sensor_sw_id = i;
- }
- } else {
- pr_debug("Use specified sensor id mapping\n");
- for (i = 0; i < tsens_num_sensors; i++) {
- tmdev->sensor[i].sensor_hw_num = sensor_id[i];
- tmdev->sensor[i].sensor_sw_id = i;
- }
- }
- tmdev->tsens_irq = platform_get_irq(pdev, 0);
- if (tmdev->tsens_irq < 0) {
- pr_err("Invalid get irq\n");
- rc = tmdev->tsens_irq;
- goto fail_tmdev;
- }
- /* TSENS register region */
- tmdev->res_tsens_mem = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, "tsens_physical");
- if (!tmdev->res_tsens_mem) {
- pr_err("Could not get tsens physical address resource\n");
- rc = -EINVAL;
- goto fail_tmdev;
- }
- tmdev->tsens_len = tmdev->res_tsens_mem->end -
- tmdev->res_tsens_mem->start + 1;
- res_mem = request_mem_region(tmdev->res_tsens_mem->start,
- tmdev->tsens_len, tmdev->res_tsens_mem->name);
- if (!res_mem) {
- pr_err("Request tsens physical memory region failed\n");
- rc = -EINVAL;
- goto fail_tmdev;
- }
- tmdev->tsens_addr = ioremap(res_mem->start, tmdev->tsens_len);
- if (!tmdev->tsens_addr) {
- pr_err("Failed to IO map TSENS registers.\n");
- rc = -EINVAL;
- goto fail_unmap_tsens_region;
- }
- /* TSENS calibration region */
- tmdev->res_calib_mem = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, "tsens_eeprom_physical");
- if (!tmdev->res_calib_mem) {
- pr_err("Could not get qfprom physical address resource\n");
- rc = -EINVAL;
- goto fail_unmap_tsens;
- }
- tmdev->calib_len = tmdev->res_calib_mem->end -
- tmdev->res_calib_mem->start + 1;
- res_mem = request_mem_region(tmdev->res_calib_mem->start,
- tmdev->calib_len, tmdev->res_calib_mem->name);
- if (!res_mem) {
- pr_err("Request calibration memory region failed\n");
- rc = -EINVAL;
- goto fail_unmap_tsens;
- }
- tmdev->tsens_calib_addr = ioremap(res_mem->start,
- tmdev->calib_len);
- if (!tmdev->tsens_calib_addr) {
- pr_err("Failed to IO map EEPROM registers.\n");
- rc = -EINVAL;
- goto fail_unmap_calib_region;
- }
- return 0;
- fail_unmap_calib_region:
- if (tmdev->res_calib_mem)
- release_mem_region(tmdev->res_calib_mem->start,
- tmdev->calib_len);
- fail_unmap_tsens:
- if (tmdev->tsens_addr)
- iounmap(tmdev->tsens_addr);
- fail_unmap_tsens_region:
- if (tmdev->res_tsens_mem)
- release_mem_region(tmdev->res_tsens_mem->start,
- tmdev->tsens_len);
- fail_tmdev:
- tmdev = NULL;
- return rc;
- }
- static int __devinit tsens_tm_probe(struct platform_device *pdev)
- {
- int rc;
- if (tmdev) {
- pr_err("TSENS device already in use\n");
- return -EBUSY;
- }
- if (pdev->dev.of_node) {
- rc = get_device_tree_data(pdev);
- if (rc) {
- pr_err("Error reading TSENS DT\n");
- return rc;
- }
- } else
- return -ENODEV;
- tmdev->pdev = pdev;
- tmdev->tsens_wq = alloc_workqueue("tsens_wq", WQ_HIGHPRI, 0);
- if (!tmdev->tsens_wq) {
- rc = -ENOMEM;
- goto fail;
- }
- rc = tsens_calib_sensors();
- if (rc < 0) {
- pr_err("Calibration failed\n");
- goto fail;
- }
- tsens_hw_init();
- tmdev->prev_reading_avail = true;
- platform_set_drvdata(pdev, tmdev);
- return 0;
- fail:
- if (tmdev->tsens_wq)
- destroy_workqueue(tmdev->tsens_wq);
- if (tmdev->tsens_calib_addr)
- iounmap(tmdev->tsens_calib_addr);
- if (tmdev->res_calib_mem)
- release_mem_region(tmdev->res_calib_mem->start,
- tmdev->calib_len);
- if (tmdev->tsens_addr)
- iounmap(tmdev->tsens_addr);
- if (tmdev->res_tsens_mem)
- release_mem_region(tmdev->res_tsens_mem->start,
- tmdev->tsens_len);
- tmdev = NULL;
- return rc;
- }
- static int __devinit _tsens_register_thermal(void)
- {
- struct platform_device *pdev;
- int rc, i;
- if (!tmdev) {
- pr_err("%s: TSENS early init not done\n", __func__);
- return -ENODEV;
- }
- pdev = tmdev->pdev;
- for (i = 0; i < tmdev->tsens_num_sensor; i++) {
- char name[18];
- snprintf(name, sizeof(name), "tsens_tz_sensor%d",
- tmdev->sensor[i].sensor_hw_num);
- tmdev->sensor[i].mode = THERMAL_DEVICE_ENABLED;
- tmdev->sensor[i].tz_dev = thermal_zone_device_register(name,
- TSENS_TRIP_NUM, &tmdev->sensor[i],
- &tsens_thermal_zone_ops, 0, 0, 0, 0);
- if (IS_ERR(tmdev->sensor[i].tz_dev)) {
- pr_err("%s: thermal_zone_device_register() failed.\n",
- __func__);
- rc = -ENODEV;
- goto fail;
- }
- }
- INIT_WORK(&tmdev->tsens_work, tsens_scheduler_fn);
- rc = request_irq(tmdev->tsens_irq, tsens_isr,
- IRQF_TRIGGER_RISING, "tsens_interrupt", tmdev);
- if (rc < 0) {
- pr_err("%s: request_irq FAIL: %d\n", __func__, rc);
- for (i = 0; i < tmdev->tsens_num_sensor; i++)
- thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
- goto fail;
- } else {
- enable_irq_wake(tmdev->tsens_irq);
- }
- platform_set_drvdata(pdev, tmdev);
- return 0;
- fail:
- if (tmdev->tsens_calib_addr)
- iounmap(tmdev->tsens_calib_addr);
- if (tmdev->res_calib_mem)
- release_mem_region(tmdev->res_calib_mem->start,
- tmdev->calib_len);
- if (tmdev->tsens_addr)
- iounmap(tmdev->tsens_addr);
- if (tmdev->res_tsens_mem)
- release_mem_region(tmdev->res_tsens_mem->start,
- tmdev->tsens_len);
- return rc;
- }
- static int __devexit tsens_tm_remove(struct platform_device *pdev)
- {
- struct tsens_tm_device *tmdev = platform_get_drvdata(pdev);
- int i;
- for (i = 0; i < tmdev->tsens_num_sensor; i++)
- thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
- if (tmdev->tsens_calib_addr)
- iounmap(tmdev->tsens_calib_addr);
- if (tmdev->res_calib_mem)
- release_mem_region(tmdev->res_calib_mem->start,
- tmdev->calib_len);
- if (tmdev->tsens_addr)
- iounmap(tmdev->tsens_addr);
- if (tmdev->res_tsens_mem)
- release_mem_region(tmdev->res_tsens_mem->start,
- tmdev->tsens_len);
- free_irq(tmdev->tsens_irq, tmdev);
- destroy_workqueue(tmdev->tsens_wq);
- platform_set_drvdata(pdev, NULL);
- return 0;
- }
- static struct of_device_id tsens_match[] = {
- { .compatible = "qcom,msm-tsens",
- },
- {}
- };
- static struct platform_driver tsens_tm_driver = {
- .probe = tsens_tm_probe,
- .remove = tsens_tm_remove,
- .driver = {
- .name = "msm-tsens",
- .owner = THIS_MODULE,
- .of_match_table = tsens_match,
- },
- };
- int __init tsens_tm_init_driver(void)
- {
- return platform_driver_register(&tsens_tm_driver);
- }
- static int __init tsens_thermal_register(void)
- {
- return _tsens_register_thermal();
- }
- module_init(tsens_thermal_register);
- static void __exit _tsens_tm_remove(void)
- {
- platform_driver_unregister(&tsens_tm_driver);
- }
- module_exit(_tsens_tm_remove);
- MODULE_ALIAS("platform:" TSENS_DRIVER_NAME);
- MODULE_LICENSE("GPL v2");
|