Skip to content

Commit

Permalink
thermal/drivers/hisi: Add support for hi3660 SoC
Browse files Browse the repository at this point in the history
This patch adds the support for thermal sensor on the Hi3660 SoC.
Hi3660 tsensor support alarm in alarm threshold, it also has a configurable
hysteresis interval, interrupt will be triggered when temperature rise above
the alarm threshold or fall below the hysteresis threshold.

Signed-off-by: Kevin Wangtao <kevin.wangtao@linaro.org>
Tested-by: Daniel Lezcano <daniel.lezcano@linaro.org> # hikey6220
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
  • Loading branch information
Kevin Wangtao authored and Eduardo Valentin committed Nov 1, 2017
1 parent a160a46 commit 2bb60a8
Showing 1 changed file with 144 additions and 1 deletion.
145 changes: 144 additions & 1 deletion drivers/thermal/hisi_thermal.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,24 @@
#define HI6220_TEMP0_RST_MSK (0x1C)
#define HI6220_TEMP0_VALUE (0x28)

#define HI3660_OFFSET(chan) ((chan) * 0x40)
#define HI3660_TEMP(chan) (HI3660_OFFSET(chan) + 0x1C)
#define HI3660_TH(chan) (HI3660_OFFSET(chan) + 0x20)
#define HI3660_LAG(chan) (HI3660_OFFSET(chan) + 0x28)
#define HI3660_INT_EN(chan) (HI3660_OFFSET(chan) + 0x2C)
#define HI3660_INT_CLR(chan) (HI3660_OFFSET(chan) + 0x30)

#define HI6220_TEMP_BASE (-60000)
#define HI6220_TEMP_RESET (100000)
#define HI6220_TEMP_STEP (785)
#define HI6220_TEMP_LAG (3500)

#define HI3660_TEMP_BASE (-63780)
#define HI3660_TEMP_STEP (205)
#define HI3660_TEMP_LAG (4000)

#define HI6220_DEFAULT_SENSOR 2
#define HI3660_DEFAULT_SENSOR 1

struct hisi_thermal_sensor {
struct thermal_zone_device *tzd;
Expand Down Expand Up @@ -92,6 +104,24 @@ static inline int hi6220_thermal_temp_to_step(int temp)
return DIV_ROUND_UP(temp - HI6220_TEMP_BASE, HI6220_TEMP_STEP);
}

/*
* for Hi3660,
* Step: 189/922 (0.205)
* Temperature base: -63.780°C
*
* The register is programmed in temperature steps, every step is 205
* millidegree and begins at -63 780 m°C
*/
static inline int hi3660_thermal_step_to_temp(int step)
{
return HI3660_TEMP_BASE + step * HI3660_TEMP_STEP;
}

static inline int hi3660_thermal_temp_to_step(int temp)
{
return DIV_ROUND_UP(temp - HI3660_TEMP_BASE, HI3660_TEMP_STEP);
}

/*
* The lag register contains 5 bits encoding the temperature in steps.
*
Expand Down Expand Up @@ -165,6 +195,45 @@ static inline int hi6220_thermal_get_temperature(void __iomem *addr)
return hi6220_thermal_step_to_temp(readl(addr + HI6220_TEMP0_VALUE));
}

/*
* [0:6] lag register
*
* The temperature is coded in steps, cf. HI3660_TEMP_STEP.
*
* Min : 0x00 : 0.0 °C
* Max : 0x7F : 26.0 °C
*
*/
static inline void hi3660_thermal_set_lag(void __iomem *addr,
int id, int value)
{
writel(DIV_ROUND_UP(value, HI3660_TEMP_STEP) & 0x7F,
addr + HI3660_LAG(id));
}

static inline void hi3660_thermal_alarm_clear(void __iomem *addr,
int id, int value)
{
writel(value, addr + HI3660_INT_CLR(id));
}

static inline void hi3660_thermal_alarm_enable(void __iomem *addr,
int id, int value)
{
writel(value, addr + HI3660_INT_EN(id));
}

static inline void hi3660_thermal_alarm_set(void __iomem *addr,
int id, int value)
{
writel(value, addr + HI3660_TH(id));
}

static inline int hi3660_thermal_get_temperature(void __iomem *addr, int id)
{
return hi3660_thermal_step_to_temp(readl(addr + HI3660_TEMP(id)));
}

/*
* Temperature configuration register - Sensor selection
*
Expand Down Expand Up @@ -203,11 +272,22 @@ static int hi6220_thermal_irq_handler(struct hisi_thermal_data *data)
return 0;
}

static int hi3660_thermal_irq_handler(struct hisi_thermal_data *data)
{
hi3660_thermal_alarm_clear(data->regs, data->sensor.id, 1);
return 0;
}

static int hi6220_thermal_get_temp(struct hisi_thermal_data *data)
{
return hi6220_thermal_get_temperature(data->regs);
}

static int hi3660_thermal_get_temp(struct hisi_thermal_data *data)
{
return hi3660_thermal_get_temperature(data->regs, data->sensor.id);
}

static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data)
{
/* disable sensor module */
Expand All @@ -220,6 +300,13 @@ static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data)
return 0;
}

static int hi3660_thermal_disable_sensor(struct hisi_thermal_data *data)
{
/* disable sensor module */
hi3660_thermal_alarm_enable(data->regs, data->sensor.id, 0);
return 0;
}

static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data)
{
struct hisi_thermal_sensor *sensor = &data->sensor;
Expand Down Expand Up @@ -258,6 +345,28 @@ static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data)
return 0;
}

static int hi3660_thermal_enable_sensor(struct hisi_thermal_data *data)
{
unsigned int value;
struct hisi_thermal_sensor *sensor = &data->sensor;

/* disable interrupt */
hi3660_thermal_alarm_enable(data->regs, sensor->id, 0);

/* setting lag value between current temp and the threshold */
hi3660_thermal_set_lag(data->regs, sensor->id, HI3660_TEMP_LAG);

/* set interrupt threshold */
value = hi3660_thermal_temp_to_step(sensor->thres_temp);
hi3660_thermal_alarm_set(data->regs, sensor->id, value);

/* enable interrupt */
hi3660_thermal_alarm_clear(data->regs, sensor->id, 1);
hi3660_thermal_alarm_enable(data->regs, sensor->id, 1);

return 0;
}

static int hi6220_thermal_probe(struct hisi_thermal_data *data)
{
struct platform_device *pdev = data->pdev;
Expand Down Expand Up @@ -294,6 +403,33 @@ static int hi6220_thermal_probe(struct hisi_thermal_data *data)
return 0;
}

static int hi3660_thermal_probe(struct hisi_thermal_data *data)
{
struct platform_device *pdev = data->pdev;
struct device *dev = &pdev->dev;
struct resource *res;

data->get_temp = hi3660_thermal_get_temp;
data->enable_sensor = hi3660_thermal_enable_sensor;
data->disable_sensor = hi3660_thermal_disable_sensor;
data->irq_handler = hi3660_thermal_irq_handler;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(data->regs)) {
dev_err(dev, "failed to get io address\n");
return PTR_ERR(data->regs);
}

data->irq = platform_get_irq(pdev, 0);
if (data->irq < 0)
return data->irq;

data->sensor.id = HI3660_DEFAULT_SENSOR;

return 0;
}

static int hisi_thermal_get_temp(void *__data, int *temp)
{
struct hisi_thermal_data *data = __data;
Expand Down Expand Up @@ -367,7 +503,14 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev,
}

static const struct of_device_id of_hisi_thermal_match[] = {
{ .compatible = "hisilicon,tsensor", .data = hi6220_thermal_probe },
{
.compatible = "hisilicon,tsensor",
.data = hi6220_thermal_probe
},
{
.compatible = "hisilicon,hi3660-tsensor",
.data = hi3660_thermal_probe
},
{ /* end */ }
};
MODULE_DEVICE_TABLE(of, of_hisi_thermal_match);
Expand Down

0 comments on commit 2bb60a8

Please sign in to comment.