static int flounder_nct72_init(void)
{
	s32 base_cp, shft_cp;
	u32 base_ft, shft_ft;
	int nct72_port = TEGRA_GPIO_PI6;
	int ret = 0;
	int i;
	struct thermal_trip_info *trip_state;

	/* raise NCT's thresholds if soctherm CP,FT fuses are ok */
	if ((tegra_fuse_calib_base_get_cp(&base_cp, &shft_cp) >= 0) &&
	    (tegra_fuse_calib_base_get_ft(&base_ft, &shft_ft) >= 0)) {
		flounder_nct72_pdata.sensors[EXT].shutdown_limit += 20;
		for (i = 0; i < flounder_nct72_pdata.sensors[EXT].num_trips;
			 i++) {
			trip_state = &flounder_nct72_pdata.sensors[EXT].trips[i];
			if (!strncmp(trip_state->cdev_type, "cpu-balanced",
					THERMAL_NAME_LENGTH)) {
				trip_state->cdev_type = "_none_";
				break;
			}
		}
	} else {
		tegra_platform_edp_init(
			flounder_nct72_pdata.sensors[EXT].trips,
			&flounder_nct72_pdata.sensors[EXT].num_trips,
					12000); /* edp temperature margin */
		tegra_add_cpu_vmax_trips(
			flounder_nct72_pdata.sensors[EXT].trips,
			&flounder_nct72_pdata.sensors[EXT].num_trips);
		tegra_add_tgpu_trips(
			flounder_nct72_pdata.sensors[EXT].trips,
			&flounder_nct72_pdata.sensors[EXT].num_trips);
		tegra_add_vc_trips(
			flounder_nct72_pdata.sensors[EXT].trips,
			&flounder_nct72_pdata.sensors[EXT].num_trips);
		tegra_add_core_vmax_trips(
			flounder_nct72_pdata.sensors[EXT].trips,
			&flounder_nct72_pdata.sensors[EXT].num_trips);
	}

	tegra_add_all_vmin_trips(flounder_nct72_pdata.sensors[EXT].trips,
		&flounder_nct72_pdata.sensors[EXT].num_trips);

	flounder_i2c_nct72_board_info[0].irq = gpio_to_irq(nct72_port);

	ret = gpio_request(nct72_port, "temp_alert");
	if (ret < 0)
		return ret;

	ret = gpio_direction_input(nct72_port);
	if (ret < 0) {
		pr_info("%s: calling gpio_free(nct72_port)", __func__);
		gpio_free(nct72_port);
	}

	i2c_register_board_info(0, flounder_i2c_nct72_board_info,
	ARRAY_SIZE(flounder_i2c_nct72_board_info));

	return ret;
}
static int ardbeg_nct72_init(void)
{
	s32 base_cp, shft_cp;
	u32 base_ft, shft_ft;
	int nct72_port = TEGRA_GPIO_PI6;
	int ret = 0;
	int i;
	struct thermal_trip_info *trip_state;
	struct board_info board_info;

	tegra_get_board_info(&board_info);
	/* raise NCT's thresholds if soctherm CP,FT fuses are ok */
	if ((tegra_fuse_calib_base_get_cp(&base_cp, &shft_cp) >= 0) &&
	    (tegra_fuse_calib_base_get_ft(&base_ft, &shft_ft) >= 0)) {
		ardbeg_nct72_pdata.shutdown_ext_limit += 20;
		for (i = 0; i < ardbeg_nct72_pdata.num_trips; i++) {
			trip_state = &ardbeg_nct72_pdata.trips[i];
			if (!strncmp(trip_state->cdev_type, "cpu-balanced",
					THERMAL_NAME_LENGTH)) {
				trip_state->cdev_type = "_none_";
				break;
			}
		}
	} else {
		tegra_platform_edp_init(ardbeg_nct72_pdata.trips,
					&ardbeg_nct72_pdata.num_trips,
					12000); /* edp temperature margin */
		tegra_add_cpu_vmax_trips(ardbeg_nct72_pdata.trips,
				&ardbeg_nct72_pdata.num_trips);
		tegra_add_tgpu_trips(ardbeg_nct72_pdata.trips,
				     &ardbeg_nct72_pdata.num_trips);
		tegra_add_vc_trips(ardbeg_nct72_pdata.trips,
				     &ardbeg_nct72_pdata.num_trips);
		tegra_add_core_vmax_trips(ardbeg_nct72_pdata.trips,
				     &ardbeg_nct72_pdata.num_trips);
	}

	tegra_add_all_vmin_trips(ardbeg_nct72_pdata.trips,
				&ardbeg_nct72_pdata.num_trips);

	ardbeg_i2c_nct72_board_info[0].irq = gpio_to_irq(nct72_port);

	ret = gpio_request(nct72_port, "temp_alert");
	if (ret < 0)
		return ret;

	ret = gpio_direction_input(nct72_port);
	if (ret < 0) {
		pr_info("%s: calling gpio_free(nct72_port)", __func__);
		gpio_free(nct72_port);
	}

	/* ardbeg has thermal sensor on GEN2-I2C i.e. instance 1 */
	if (board_info.board_id == BOARD_PM358 ||
			board_info.board_id == BOARD_PM359 ||
			board_info.board_id == BOARD_PM370 ||
			board_info.board_id == BOARD_PM374 ||
			board_info.board_id == BOARD_PM363)
		i2c_register_board_info(1, laguna_i2c_nct72_board_info,
		ARRAY_SIZE(laguna_i2c_nct72_board_info));
	else if (board_info.board_id == BOARD_PM375 ||
			board_info.board_id == BOARD_PM377)
		i2c_register_board_info(0, laguna_i2c_nct72_board_info,
				ARRAY_SIZE(laguna_i2c_nct72_board_info));
	else
		i2c_register_board_info(1, ardbeg_i2c_nct72_board_info,
		ARRAY_SIZE(ardbeg_i2c_nct72_board_info));

	return ret;
}
static int aotag_read_fuses(struct platform_device *pdev)
{
	int ret = 0;
	struct aotag_sensor_info_t *ps_info = PDEV2SENSOR_INFO(pdev);
	struct sensor_common_params_t *pcparams =
		SENSOR_INFO2COMMON_PARAMS(ps_info);
	struct fuse_info_t *pfuse = SENSOR_INFO2FUSE_INFO(ps_info);
	u32 fuse_val = 0;
	s32 calib, delta_ts_reading, delta_temp;
	u32 reg;
	int fuse_rev = 0;
	s64 numerator, denominator;


	fuse_rev = tegra_fuse_calib_base_get_cp(NULL, NULL);
	if (0 > fuse_rev) {
		ret = fuse_rev;
		aotag_pdev_print(alert, pdev, "Invalid fuse rev\n");
		goto out;
	}

	pfuse->common_fuse_rev = fuse_rev;

	aotag_pdev_print(info, pdev, "reading fuse value for sensor %d\n",
			ps_info->id);

	/*
	 * Read average raw calibration readings and temperature shifts
	 */
	if ((0 > tegra_fuse_calib_base_get_cp(&(pfuse->avg_ts_reading_cp),
					&(pfuse->shifted_temp_cp))) ||
			(0 > tegra_fuse_calib_base_get_ft(
					&(pfuse->avg_ts_reading_ft),
					&(pfuse->shifted_temp_ft)))) {
		aotag_pdev_print(alert, pdev,
				"failed to read fuse values\n");
		ret = -EINVAL;
		goto out;
	}

	aotag_pdev_print(info, pdev, "base-cp:%x shifted-cp:%x\n",
			pfuse->avg_ts_reading_cp,
			pfuse->shifted_temp_cp);
	aotag_pdev_print(info, pdev, "base-ft:%x shifted-ft:%x\n",
			pfuse->avg_ts_reading_ft,
			pfuse->shifted_temp_ft);

	pfuse->actual_temp_cp =
		(1000*pfuse->nominal_temp_cp) + (500*pfuse->shifted_temp_cp);
	pfuse->actual_temp_ft =
		(1000*pfuse->nominal_temp_ft) + (500*pfuse->shifted_temp_ft);

	pfuse->actual_temp_cp /= 100;
	pfuse->actual_temp_ft /= 100;

	aotag_pdev_print(info, pdev, "actual_aotag_cp %d, ft %d\n",
			pfuse->actual_temp_cp, pfuse->actual_temp_ft);


	/*
	 * Now read the reading delta's per sensor that happened during
	 * calibration
	 */
	ret = tegra_fuse_get_tsensor_calib(ps_info->advertised_id,
			&fuse_val);
	if (ret) {
		aotag_pdev_print(alert, pdev,
				"unable to read fuse tsensor\n");
		goto out;
	}

	aotag_pdev_print(info, pdev,
			"- Tsens calib value - 0x%x\n", fuse_val);

	aotag_pdev_print(info, pdev, "CPmask %x FTmask %x\n",
			AOTAG_FUSE_CALIB_CP_MASK,
			AOTAG_FUSE_CALIB_FT_MASK);
	GET_REG(&calib, AOTAG_FUSE_CALIB_CP, &fuse_val);
	aotag_pdev_print(info, pdev, "Tsense calib CP - 0x%x\n", calib);

	if (calib & 0x1000) {	/* negative value */
		calib = (calib ^ 0x1FFF) + 1;
		pfuse->actual_ts_reading_cp =
			(pfuse->avg_ts_reading_cp * 64) - calib;
	} else {
		pfuse->actual_ts_reading_cp =
			((pfuse->avg_ts_reading_cp) * 64) + calib;
	}
	aotag_pdev_print(info, pdev, "Tsense Actual CP d.%d\n",
			pfuse->actual_ts_reading_cp);

	GET_REG(&calib, AOTAG_FUSE_CALIB_FT, &fuse_val);
	aotag_pdev_print(info, pdev, "Tsense calib FT - 0x%x\n", calib);
	if (calib & 0x1000) {	/* negative value */
		calib = (calib ^ 0x1FFF) + 1;
		pfuse->actual_ts_reading_ft =
			(pfuse->avg_ts_reading_ft * 32) - calib;
	} else {
		pfuse->actual_ts_reading_ft =
			((pfuse->avg_ts_reading_ft) * 32) + calib;
	}
	aotag_pdev_print(info, pdev, "Tsense Actual FT d.%d\n",
			pfuse->actual_ts_reading_ft);

	delta_ts_reading =
		pfuse->actual_ts_reading_ft - pfuse->actual_ts_reading_cp;
	delta_temp = pfuse->actual_temp_ft - pfuse->actual_temp_cp;
	aotag_pdev_print(info, pdev,
			"delta ts %d, temp %d\n", delta_ts_reading, delta_temp);

	/*
	 * THERM_A
	 */
	numerator =
		(((s64)(delta_temp))<<13) *
		pcparams->tsamp_ate * pcparams->pdiv;
	denominator =
		(s64)(delta_ts_reading) *
		pcparams->tsample * pcparams->pdiv * 10;
	do_div(numerator, denominator);
	ps_info->therm_a = numerator;
	ps_info->therm_a = (ps_info->therm_a) * (pfuse->compensation_a)/10000;

	/*
	 * THERM_B
	 */
	numerator = (
			((s64)(pfuse->actual_ts_reading_ft *
				pfuse->actual_temp_cp)) -
			((s64)(pfuse->actual_ts_reading_cp *
				pfuse->actual_temp_ft)));
	denominator = (s64)delta_ts_reading * 10;
	if (numerator > 0) {
		do_div(numerator, denominator);
		ps_info->therm_b = numerator;
	} else {
		numerator *= (-1);
		do_div(numerator, denominator);
		ps_info->therm_b = (-1) * numerator;
	}

	if (ps_info->therm_b > 0) {
		ps_info->therm_b = ((ps_info->therm_b * pfuse->compensation_a)
				+ pfuse->compensation_b)/10000;
	} else {
		ps_info->therm_b = (-1) *
			(((-1) * ((ps_info->therm_b * pfuse->compensation_a)
				  + pfuse->compensation_b))/10000);
	}
	/*
	 * Now write the thermA,B registers
	 */
	aotag_pdev_print(alert, pdev, "thermA-%d, thermB-%d\n",
			ps_info->therm_a, ps_info->therm_b);
	reg = 0;
	FILL_REG_OR(ps_info->therm_a, CONFIG2_THERM_A, &reg);
	FILL_REG_OR(ps_info->therm_b, CONFIG2_THERM_B, &reg);
	reg_write(pdev, pmc, reg, PMC_TSENSOR_CONFIG2);

out:
	return ret;
}
int __init flounder_soctherm_init(void)
{
	const int t13x_cpu_edp_temp_margin = 5000,
		t13x_gpu_edp_temp_margin = 6000;
	int cpu_edp_temp_margin, gpu_edp_temp_margin;
	int cp_rev, ft_rev;
	enum soctherm_therm_id therm_cpu = THERM_CPU;

	cp_rev = tegra_fuse_calib_base_get_cp(NULL, NULL);
	ft_rev = tegra_fuse_calib_base_get_ft(NULL, NULL);

	/* TODO: remove this part once bootloader changes merged */
	tegra_gpio_disable(TEGRA_GPIO_PJ2);
	tegra_gpio_disable(TEGRA_GPIO_PS7);

	cpu_edp_temp_margin = t13x_cpu_edp_temp_margin;
	gpu_edp_temp_margin = t13x_gpu_edp_temp_margin;

	if (!cp_rev) {
		/* ATE rev is NEW: use v2 table */
		flounder_soctherm_data.therm[THERM_CPU] =
			t132ref_v2_soctherm_data.therm[THERM_CPU];
		flounder_soctherm_data.therm[THERM_GPU] =
			t132ref_v2_soctherm_data.therm[THERM_GPU];
	} else {
		/* ATE rev is Old or Mid: use PLLx sensor only */
		flounder_soctherm_data.therm[THERM_CPU] =
			t132ref_v1_soctherm_data.therm[THERM_CPU];
		flounder_soctherm_data.therm[THERM_PLL] =
			t132ref_v1_soctherm_data.therm[THERM_PLL];
		therm_cpu = THERM_PLL; /* override CPU with PLL zone */
	}

	/* do this only for supported CP,FT fuses */
	if ((cp_rev >= 0) && (ft_rev >= 0)) {
		tegra_platform_edp_init(
			flounder_soctherm_data.therm[therm_cpu].trips,
			&flounder_soctherm_data.therm[therm_cpu].num_trips,
			t13x_cpu_edp_temp_margin);
		tegra_platform_gpu_edp_init(
			flounder_soctherm_data.therm[THERM_GPU].trips,
			&flounder_soctherm_data.therm[THERM_GPU].num_trips,
			t13x_gpu_edp_temp_margin);
		tegra_add_cpu_vmax_trips(
			flounder_soctherm_data.therm[therm_cpu].trips,
			&flounder_soctherm_data.therm[therm_cpu].num_trips);
		tegra_add_tgpu_trips(
			flounder_soctherm_data.therm[THERM_GPU].trips,
			&flounder_soctherm_data.therm[THERM_GPU].num_trips);
		tegra_add_core_vmax_trips(
			flounder_soctherm_data.therm[THERM_PLL].trips,
			&flounder_soctherm_data.therm[THERM_PLL].num_trips);
	}

	tegra_add_cpu_vmin_trips(
		flounder_soctherm_data.therm[therm_cpu].trips,
		&flounder_soctherm_data.therm[therm_cpu].num_trips);
	tegra_add_gpu_vmin_trips(
		flounder_soctherm_data.therm[THERM_GPU].trips,
		&flounder_soctherm_data.therm[THERM_GPU].num_trips);
	tegra_add_core_vmin_trips(
		flounder_soctherm_data.therm[THERM_PLL].trips,
		&flounder_soctherm_data.therm[THERM_PLL].num_trips);

	flounder_soctherm_data.tshut_pmu_trip_data = &tpdata_palmas;
	/* Enable soc_therm OC throttling on selected platforms */
	memcpy(&flounder_soctherm_data.throttle[THROTTLE_OC4],
		       &battery_oc_throttle_t13x,
		       sizeof(battery_oc_throttle_t13x));
	return tegra11_soctherm_init(&flounder_soctherm_data);
}
int __init norrin_soctherm_init(void)
{
	const int t13x_cpu_edp_temp_margin = 5000,
		t13x_gpu_edp_temp_margin = 6000;
	int cp_rev, ft_rev;
	struct board_info pmu_board_info;
	struct board_info board_info;
	enum soctherm_therm_id therm_cpu = THERM_CPU;

	tegra_get_board_info(&board_info);

	cp_rev = tegra_fuse_calib_base_get_cp(NULL, NULL);
	ft_rev = tegra_fuse_calib_base_get_ft(NULL, NULL);

	if (cp_rev) {
		/* ATE rev is Old or Mid - use PLLx sensor only */
		norrin_soctherm_data.therm[THERM_CPU] =
			norrin_v1_soctherm_data.therm[THERM_CPU];
		norrin_soctherm_data.therm[THERM_PLL] =
			norrin_v1_soctherm_data.therm[THERM_PLL];
		therm_cpu = THERM_PLL; /* override CPU with PLL zone */
	}

	/* do this only for supported CP,FT fuses */
	if ((cp_rev >= 0) && (ft_rev >= 0)) {
		tegra_platform_edp_init(
			norrin_soctherm_data.therm[therm_cpu].trips,
			&norrin_soctherm_data.therm[therm_cpu].num_trips,
			t13x_cpu_edp_temp_margin);
		tegra_platform_gpu_edp_init(
			norrin_soctherm_data.therm[THERM_GPU].trips,
			&norrin_soctherm_data.therm[THERM_GPU].num_trips,
			t13x_gpu_edp_temp_margin);
		tegra_add_cpu_vmax_trips(
			norrin_soctherm_data.therm[therm_cpu].trips,
			&norrin_soctherm_data.therm[therm_cpu].num_trips);
		tegra_add_tgpu_trips(
			norrin_soctherm_data.therm[THERM_GPU].trips,
			&norrin_soctherm_data.therm[THERM_GPU].num_trips);
		tegra_add_core_vmax_trips(
			norrin_soctherm_data.therm[THERM_PLL].trips,
			&norrin_soctherm_data.therm[THERM_PLL].num_trips);
	}

	if (board_info.board_id == BOARD_PM374 ||
		board_info.board_id == BOARD_PM375 ||
		board_info.board_id == BOARD_E1971 ||
		board_info.board_id == BOARD_E1991) {
		tegra_add_cpu_vmin_trips(
			norrin_soctherm_data.therm[therm_cpu].trips,
			&norrin_soctherm_data.therm[therm_cpu].num_trips);
		tegra_add_gpu_vmin_trips(
			norrin_soctherm_data.therm[THERM_GPU].trips,
			&norrin_soctherm_data.therm[THERM_GPU].num_trips);
		tegra_add_core_vmin_trips(
			norrin_soctherm_data.therm[THERM_PLL].trips,
			&norrin_soctherm_data.therm[THERM_PLL].num_trips);
	}

	if (board_info.board_id == BOARD_PM375)
		tegra_add_cpu_clk_switch_trips(
			norrin_soctherm_data.therm[THERM_CPU].trips,
			&norrin_soctherm_data.therm[THERM_CPU].num_trips);
	tegra_get_pmu_board_info(&pmu_board_info);

	if ((pmu_board_info.board_id == BOARD_PM374) ||
		(pmu_board_info.board_id == BOARD_PM375))
		norrin_soctherm_data.tshut_pmu_trip_data = &tpdata_as3722;
	else
		pr_warn("soctherm THERMTRIP not supported on PMU (BOARD_P%d)\n",
			pmu_board_info.board_id);

	return tegra11_soctherm_init(&norrin_soctherm_data);
}
int __init ardbeg_soctherm_init(void)
{
	s32 base_cp, shft_cp;
	u32 base_ft, shft_ft;
	struct board_info pmu_board_info;
	struct board_info board_info;

	tegra_get_board_info(&board_info);

	if (board_info.board_id == BOARD_E1923 ||
			board_info.board_id == BOARD_E1922) {
		memcpy(ardbeg_soctherm_data.therm,
				ardbeg_therm_pop, sizeof(ardbeg_therm_pop));
	}

	/* do this only for supported CP,FT fuses */
	if ((tegra_fuse_calib_base_get_cp(&base_cp, &shft_cp) >= 0) &&
	    (tegra_fuse_calib_base_get_ft(&base_ft, &shft_ft) >= 0)) {
		tegra_platform_edp_init(
			ardbeg_soctherm_data.therm[THERM_CPU].trips,
			&ardbeg_soctherm_data.therm[THERM_CPU].num_trips,
			7000); /* edp temperature margin */
		tegra_platform_gpu_edp_init(
			ardbeg_soctherm_data.therm[THERM_GPU].trips,
			&ardbeg_soctherm_data.therm[THERM_GPU].num_trips,
			7000);
		tegra_add_cpu_vmax_trips(
			ardbeg_soctherm_data.therm[THERM_CPU].trips,
			&ardbeg_soctherm_data.therm[THERM_CPU].num_trips);
		tegra_add_tgpu_trips(
			ardbeg_soctherm_data.therm[THERM_GPU].trips,
			&ardbeg_soctherm_data.therm[THERM_GPU].num_trips);
		tegra_add_vc_trips(
			ardbeg_soctherm_data.therm[THERM_CPU].trips,
			&ardbeg_soctherm_data.therm[THERM_CPU].num_trips);
		tegra_add_core_vmax_trips(
			ardbeg_soctherm_data.therm[THERM_PLL].trips,
			&ardbeg_soctherm_data.therm[THERM_PLL].num_trips);
	}

	if (board_info.board_id == BOARD_P1761 ||
		board_info.board_id == BOARD_E1784 ||
		board_info.board_id == BOARD_E1971 ||
		board_info.board_id == BOARD_E1991 ||
		board_info.board_id == BOARD_E1922) {
		tegra_add_cpu_vmin_trips(
			ardbeg_soctherm_data.therm[THERM_CPU].trips,
			&ardbeg_soctherm_data.therm[THERM_CPU].num_trips);
		tegra_add_gpu_vmin_trips(
			ardbeg_soctherm_data.therm[THERM_GPU].trips,
			&ardbeg_soctherm_data.therm[THERM_GPU].num_trips);
		tegra_add_core_vmin_trips(
			ardbeg_soctherm_data.therm[THERM_PLL].trips,
			&ardbeg_soctherm_data.therm[THERM_PLL].num_trips);
	}

	tegra_get_pmu_board_info(&pmu_board_info);

	if ((pmu_board_info.board_id == BOARD_E1733) ||
		(pmu_board_info.board_id == BOARD_E1734))
		ardbeg_soctherm_data.tshut_pmu_trip_data = &tpdata_as3722;
	else if (pmu_board_info.board_id == BOARD_E1735 ||
		 pmu_board_info.board_id == BOARD_E1736 ||
		 pmu_board_info.board_id == BOARD_E1769 ||
		 pmu_board_info.board_id == BOARD_P1761 ||
		 pmu_board_info.board_id == BOARD_E1936)
		ardbeg_soctherm_data.tshut_pmu_trip_data = &tpdata_palmas;
	else
		pr_warn("soctherm THERMTRIP not supported on PMU (BOARD_E%d)\n",
			pmu_board_info.board_id);

	/* Enable soc_therm OC throttling on selected platforms */
	switch (pmu_board_info.board_id) {
	case BOARD_P1761:
		memcpy(&ardbeg_soctherm_data.throttle[THROTTLE_OC4],
		       &battery_oc_throttle,
		       sizeof(battery_oc_throttle));
		memcpy(&ardbeg_soctherm_data.throttle[THROTTLE_OC1],
		       &voltmon_throttle,
		       sizeof(voltmon_throttle));

		break;
	default:
		break;
	}

	return tegra11_soctherm_init(&ardbeg_soctherm_data);
}