Message ID | e3c9b6bdfe8624d90bcc16eefe92abd66bd3da12.1713509889.git.zhoubinbin@loongson.cn (mailing list archive) |
---|---|
State | New |
Delegated to: | Daniel Lezcano |
Headers | show |
Series | thermal: loongson2: Add Loongson-2K0500 and Loongson-2K2000 thermal support | expand |
On 20/04/2024 03:46, Binbin Zhou wrote: > The Loongson-2K2000 and Loongson-2K1000 have similar thermal sensors, > except that the temperature is read differently. > > In particular, the temperature output registers of the Loongson-2K2000 > are defined in the chip configuration domain and are read in a different > way. > > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn> > Acked-by: Huacai Chen <chenhuacai@loongson.cn> > --- > drivers/thermal/loongson2_thermal.c | 50 +++++++++++++++++++++++------ > 1 file changed, 40 insertions(+), 10 deletions(-) > > diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c > index 7de01fbea801..8ecd8ed465ec 100644 > --- a/drivers/thermal/loongson2_thermal.c > +++ b/drivers/thermal/loongson2_thermal.c > @@ -30,12 +30,20 @@ > LOONGSON2_THSENS_INT_HIGH) > #define LOONGSON2_THSENS_OUT_MASK 0xFF > > +/* > + * This flag is used to indicate the temperature reading > + * method of the Loongson-2K2000 > + */ > +#define LS2K2000_THSENS_OUT_FLAG BIT(0) > + > struct loongson2_thermal_chip_data { > unsigned int thermal_sensor_sel; > + unsigned int flags; > }; > > struct loongson2_thermal_data { > - void __iomem *regs; > + void __iomem *ctrl_reg; > + void __iomem *temp_reg; > const struct loongson2_thermal_chip_data *chip_data; > }; > > @@ -48,7 +56,7 @@ static void loongson2_set_ctrl_regs(struct loongson2_thermal_data *data, > > reg_ctrl = ctrl_data + HECTO; > reg_ctrl |= enable ? 0x100 : 0; > - writew(reg_ctrl, data->regs + ctrl_reg + reg_off); > + writew(reg_ctrl, data->ctrl_reg + ctrl_reg + reg_off); > } > > static int loongson2_thermal_set(struct loongson2_thermal_data *data, > @@ -65,11 +73,16 @@ static int loongson2_thermal_set(struct loongson2_thermal_data *data, > > static int loongson2_thermal_get_temp(struct thermal_zone_device *tz, int *temp) > { > - u32 reg_val; > + int val; > struct loongson2_thermal_data *data = thermal_zone_device_priv(tz); > > - reg_val = readl(data->regs + LOONGSON2_THSENS_OUT_REG); > - *temp = ((reg_val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO; > + if (data->chip_data->flags) { > + val = readl(data->temp_reg); > + *temp = ((val & 0xffff) * 820 / 0x4000 - 311) * KILO; > + } else { > + val = readl(data->ctrl_reg + LOONGSON2_THSENS_OUT_REG); > + *temp = ((val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO; > + } Why not use a different ops. That will keep the code cleaner for the next sensor versions. For example: static int loongson2_2k2000_get_temp(...) { } static int loongson2_2k1000_get_temp(...) { } static struct thermal_zone_device_ops loongson2_of_thermal_ops = { .get_temp = loongson2_2k1000_get_temp, .set_trips = loongson2_thermal_set_trips, }; loongson2_thermal_probe { ... if (data->chip_data->flags & LS2K2000_THSENS_OUT_FLAG) loongson2_of_thermal_ops.get_temp = loongson2_2k2000_get_temp; ... } > return 0; > } > @@ -79,7 +92,7 @@ static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev) > struct thermal_zone_device *tzd = dev; > struct loongson2_thermal_data *data = thermal_zone_device_priv(tzd); > > - writeb(LOONGSON2_THSENS_INT_EN, data->regs + LOONGSON2_THSENS_STATUS_REG); > + writeb(LOONGSON2_THSENS_INT_EN, data->ctrl_reg + LOONGSON2_THSENS_STATUS_REG); > > thermal_zone_device_update(tzd, THERMAL_EVENT_UNSPECIFIED); > > @@ -111,15 +124,22 @@ static int loongson2_thermal_probe(struct platform_device *pdev) > > data->chip_data = device_get_match_data(dev); > > - data->regs = devm_platform_ioremap_resource(pdev, 0); > - if (IS_ERR(data->regs)) > - return PTR_ERR(data->regs); > + data->ctrl_reg = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(data->ctrl_reg)) > + return PTR_ERR(data->ctrl_reg); > + > + /* The temperature output register is separate for Loongson-2K2000 */ > + if (data->chip_data->flags) { > + data->temp_reg = devm_platform_ioremap_resource(pdev, 1); > + if (IS_ERR(data->temp_reg)) > + return PTR_ERR(data->temp_reg); > + } > > irq = platform_get_irq(pdev, 0); > if (irq < 0) > return irq; > > - writeb(LOONGSON2_THSENS_INT_EN, data->regs + LOONGSON2_THSENS_STATUS_REG); > + writeb(LOONGSON2_THSENS_INT_EN, data->ctrl_reg + LOONGSON2_THSENS_STATUS_REG); > > loongson2_thermal_set(data, 0, 0, false); > > @@ -146,6 +166,12 @@ static int loongson2_thermal_probe(struct platform_device *pdev) > > static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k1000_data = { > .thermal_sensor_sel = 0, > + .flags = 0, > +}; > + > +static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k2000_data = { > + .thermal_sensor_sel = 0, > + .flags = LS2K2000_THSENS_OUT_FLAG, > }; > > static const struct of_device_id of_loongson2_thermal_match[] = { > @@ -153,6 +179,10 @@ static const struct of_device_id of_loongson2_thermal_match[] = { > .compatible = "loongson,ls2k1000-thermal", > .data = &loongson2_thermal_ls2k1000_data, > }, > + { > + .compatible = "loongson,ls2k2000-thermal", > + .data = &loongson2_thermal_ls2k2000_data, > + }, > { /* end */ } > }; > MODULE_DEVICE_TABLE(of, of_loongson2_thermal_match);
On Mon, Apr 22, 2024 at 6:42 PM Daniel Lezcano <daniel.lezcano@linaro.org> wrote: > > On 20/04/2024 03:46, Binbin Zhou wrote: > > The Loongson-2K2000 and Loongson-2K1000 have similar thermal sensors, > > except that the temperature is read differently. > > > > In particular, the temperature output registers of the Loongson-2K2000 > > are defined in the chip configuration domain and are read in a different > > way. > > > > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn> > > Acked-by: Huacai Chen <chenhuacai@loongson.cn> > > --- > > drivers/thermal/loongson2_thermal.c | 50 +++++++++++++++++++++++------ > > 1 file changed, 40 insertions(+), 10 deletions(-) > > > > diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c > > index 7de01fbea801..8ecd8ed465ec 100644 > > --- a/drivers/thermal/loongson2_thermal.c > > +++ b/drivers/thermal/loongson2_thermal.c > > @@ -30,12 +30,20 @@ > > LOONGSON2_THSENS_INT_HIGH) > > #define LOONGSON2_THSENS_OUT_MASK 0xFF > > > > +/* > > + * This flag is used to indicate the temperature reading > > + * method of the Loongson-2K2000 > > + */ > > +#define LS2K2000_THSENS_OUT_FLAG BIT(0) > > + > > struct loongson2_thermal_chip_data { > > unsigned int thermal_sensor_sel; > > + unsigned int flags; > > }; > > > > struct loongson2_thermal_data { > > - void __iomem *regs; > > + void __iomem *ctrl_reg; > > + void __iomem *temp_reg; > > const struct loongson2_thermal_chip_data *chip_data; > > }; > > > > @@ -48,7 +56,7 @@ static void loongson2_set_ctrl_regs(struct loongson2_thermal_data *data, > > > > reg_ctrl = ctrl_data + HECTO; > > reg_ctrl |= enable ? 0x100 : 0; > > - writew(reg_ctrl, data->regs + ctrl_reg + reg_off); > > + writew(reg_ctrl, data->ctrl_reg + ctrl_reg + reg_off); > > } > > > > static int loongson2_thermal_set(struct loongson2_thermal_data *data, > > @@ -65,11 +73,16 @@ static int loongson2_thermal_set(struct loongson2_thermal_data *data, > > > > static int loongson2_thermal_get_temp(struct thermal_zone_device *tz, int *temp) > > { > > - u32 reg_val; > > + int val; > > struct loongson2_thermal_data *data = thermal_zone_device_priv(tz); > > > > - reg_val = readl(data->regs + LOONGSON2_THSENS_OUT_REG); > > - *temp = ((reg_val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO; > > + if (data->chip_data->flags) { > > + val = readl(data->temp_reg); > > + *temp = ((val & 0xffff) * 820 / 0x4000 - 311) * KILO; > > + } else { > > + val = readl(data->ctrl_reg + LOONGSON2_THSENS_OUT_REG); > > + *temp = ((val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO; > > + } > > Why not use a different ops. That will keep the code cleaner for the > next sensor versions. > > For example: > > static int loongson2_2k2000_get_temp(...) > { > } > > static int loongson2_2k1000_get_temp(...) > { > } > > static struct thermal_zone_device_ops loongson2_of_thermal_ops = { > .get_temp = loongson2_2k1000_get_temp, > .set_trips = loongson2_thermal_set_trips, > }; > > > loongson2_thermal_probe > { > ... > > if (data->chip_data->flags & LS2K2000_THSENS_OUT_FLAG) > loongson2_of_thermal_ops.get_temp = loongson2_2k2000_get_temp; > ... > > } Hi Daniel: Thanks for your advice. I'll use a different ops to keep the code cleaner in the next version, Thanks. Binbin > > > return 0; > > } > > @@ -79,7 +92,7 @@ static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev) > > struct thermal_zone_device *tzd = dev; > > struct loongson2_thermal_data *data = thermal_zone_device_priv(tzd); > > > > - writeb(LOONGSON2_THSENS_INT_EN, data->regs + LOONGSON2_THSENS_STATUS_REG); > > + writeb(LOONGSON2_THSENS_INT_EN, data->ctrl_reg + LOONGSON2_THSENS_STATUS_REG); > > > > thermal_zone_device_update(tzd, THERMAL_EVENT_UNSPECIFIED); > > > > @@ -111,15 +124,22 @@ static int loongson2_thermal_probe(struct platform_device *pdev) > > > > data->chip_data = device_get_match_data(dev); > > > > - data->regs = devm_platform_ioremap_resource(pdev, 0); > > - if (IS_ERR(data->regs)) > > - return PTR_ERR(data->regs); > > + data->ctrl_reg = devm_platform_ioremap_resource(pdev, 0); > > + if (IS_ERR(data->ctrl_reg)) > > + return PTR_ERR(data->ctrl_reg); > > + > > + /* The temperature output register is separate for Loongson-2K2000 */ > > + if (data->chip_data->flags) { > > + data->temp_reg = devm_platform_ioremap_resource(pdev, 1); > > + if (IS_ERR(data->temp_reg)) > > + return PTR_ERR(data->temp_reg); > > + } > > > > irq = platform_get_irq(pdev, 0); > > if (irq < 0) > > return irq; > > > > - writeb(LOONGSON2_THSENS_INT_EN, data->regs + LOONGSON2_THSENS_STATUS_REG); > > + writeb(LOONGSON2_THSENS_INT_EN, data->ctrl_reg + LOONGSON2_THSENS_STATUS_REG); > > > > loongson2_thermal_set(data, 0, 0, false); > > > > @@ -146,6 +166,12 @@ static int loongson2_thermal_probe(struct platform_device *pdev) > > > > static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k1000_data = { > > .thermal_sensor_sel = 0, > > + .flags = 0, > > +}; > > + > > +static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k2000_data = { > > + .thermal_sensor_sel = 0, > > + .flags = LS2K2000_THSENS_OUT_FLAG, > > }; > > > > static const struct of_device_id of_loongson2_thermal_match[] = { > > @@ -153,6 +179,10 @@ static const struct of_device_id of_loongson2_thermal_match[] = { > > .compatible = "loongson,ls2k1000-thermal", > > .data = &loongson2_thermal_ls2k1000_data, > > }, > > + { > > + .compatible = "loongson,ls2k2000-thermal", > > + .data = &loongson2_thermal_ls2k2000_data, > > + }, > > { /* end */ } > > }; > > MODULE_DEVICE_TABLE(of, of_loongson2_thermal_match); > > -- > <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs > > Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook | > <http://twitter.com/#!/linaroorg> Twitter | > <http://www.linaro.org/linaro-blog/> Blog >
diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c index 7de01fbea801..8ecd8ed465ec 100644 --- a/drivers/thermal/loongson2_thermal.c +++ b/drivers/thermal/loongson2_thermal.c @@ -30,12 +30,20 @@ LOONGSON2_THSENS_INT_HIGH) #define LOONGSON2_THSENS_OUT_MASK 0xFF +/* + * This flag is used to indicate the temperature reading + * method of the Loongson-2K2000 + */ +#define LS2K2000_THSENS_OUT_FLAG BIT(0) + struct loongson2_thermal_chip_data { unsigned int thermal_sensor_sel; + unsigned int flags; }; struct loongson2_thermal_data { - void __iomem *regs; + void __iomem *ctrl_reg; + void __iomem *temp_reg; const struct loongson2_thermal_chip_data *chip_data; }; @@ -48,7 +56,7 @@ static void loongson2_set_ctrl_regs(struct loongson2_thermal_data *data, reg_ctrl = ctrl_data + HECTO; reg_ctrl |= enable ? 0x100 : 0; - writew(reg_ctrl, data->regs + ctrl_reg + reg_off); + writew(reg_ctrl, data->ctrl_reg + ctrl_reg + reg_off); } static int loongson2_thermal_set(struct loongson2_thermal_data *data, @@ -65,11 +73,16 @@ static int loongson2_thermal_set(struct loongson2_thermal_data *data, static int loongson2_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - u32 reg_val; + int val; struct loongson2_thermal_data *data = thermal_zone_device_priv(tz); - reg_val = readl(data->regs + LOONGSON2_THSENS_OUT_REG); - *temp = ((reg_val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO; + if (data->chip_data->flags) { + val = readl(data->temp_reg); + *temp = ((val & 0xffff) * 820 / 0x4000 - 311) * KILO; + } else { + val = readl(data->ctrl_reg + LOONGSON2_THSENS_OUT_REG); + *temp = ((val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO; + } return 0; } @@ -79,7 +92,7 @@ static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev) struct thermal_zone_device *tzd = dev; struct loongson2_thermal_data *data = thermal_zone_device_priv(tzd); - writeb(LOONGSON2_THSENS_INT_EN, data->regs + LOONGSON2_THSENS_STATUS_REG); + writeb(LOONGSON2_THSENS_INT_EN, data->ctrl_reg + LOONGSON2_THSENS_STATUS_REG); thermal_zone_device_update(tzd, THERMAL_EVENT_UNSPECIFIED); @@ -111,15 +124,22 @@ static int loongson2_thermal_probe(struct platform_device *pdev) data->chip_data = device_get_match_data(dev); - data->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(data->regs)) - return PTR_ERR(data->regs); + data->ctrl_reg = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(data->ctrl_reg)) + return PTR_ERR(data->ctrl_reg); + + /* The temperature output register is separate for Loongson-2K2000 */ + if (data->chip_data->flags) { + data->temp_reg = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(data->temp_reg)) + return PTR_ERR(data->temp_reg); + } irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; - writeb(LOONGSON2_THSENS_INT_EN, data->regs + LOONGSON2_THSENS_STATUS_REG); + writeb(LOONGSON2_THSENS_INT_EN, data->ctrl_reg + LOONGSON2_THSENS_STATUS_REG); loongson2_thermal_set(data, 0, 0, false); @@ -146,6 +166,12 @@ static int loongson2_thermal_probe(struct platform_device *pdev) static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k1000_data = { .thermal_sensor_sel = 0, + .flags = 0, +}; + +static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k2000_data = { + .thermal_sensor_sel = 0, + .flags = LS2K2000_THSENS_OUT_FLAG, }; static const struct of_device_id of_loongson2_thermal_match[] = { @@ -153,6 +179,10 @@ static const struct of_device_id of_loongson2_thermal_match[] = { .compatible = "loongson,ls2k1000-thermal", .data = &loongson2_thermal_ls2k1000_data, }, + { + .compatible = "loongson,ls2k2000-thermal", + .data = &loongson2_thermal_ls2k2000_data, + }, { /* end */ } }; MODULE_DEVICE_TABLE(of, of_loongson2_thermal_match);