| .. | .. |
|---|
| 52 | 52 | unsigned int irq_per_ch : 1; |
|---|
| 53 | 53 | unsigned int needs_suspend_resume : 1; |
|---|
| 54 | 54 | unsigned int nirqs; |
|---|
| 55 | + unsigned int ctemp_bands; |
|---|
| 55 | 56 | }; |
|---|
| 56 | 57 | |
|---|
| 57 | 58 | static const struct rcar_thermal_chip rcar_thermal = { |
|---|
| .. | .. |
|---|
| 60 | 61 | .irq_per_ch = 0, |
|---|
| 61 | 62 | .needs_suspend_resume = 0, |
|---|
| 62 | 63 | .nirqs = 1, |
|---|
| 64 | + .ctemp_bands = 1, |
|---|
| 63 | 65 | }; |
|---|
| 64 | 66 | |
|---|
| 65 | 67 | static const struct rcar_thermal_chip rcar_gen2_thermal = { |
|---|
| .. | .. |
|---|
| 68 | 70 | .irq_per_ch = 0, |
|---|
| 69 | 71 | .needs_suspend_resume = 0, |
|---|
| 70 | 72 | .nirqs = 1, |
|---|
| 73 | + .ctemp_bands = 1, |
|---|
| 71 | 74 | }; |
|---|
| 72 | 75 | |
|---|
| 73 | 76 | static const struct rcar_thermal_chip rcar_gen3_thermal = { |
|---|
| .. | .. |
|---|
| 80 | 83 | * interrupts to detect a temperature change, rise or fall. |
|---|
| 81 | 84 | */ |
|---|
| 82 | 85 | .nirqs = 2, |
|---|
| 86 | + .ctemp_bands = 2, |
|---|
| 83 | 87 | }; |
|---|
| 84 | 88 | |
|---|
| 85 | 89 | struct rcar_thermal_priv { |
|---|
| .. | .. |
|---|
| 91 | 95 | struct mutex lock; |
|---|
| 92 | 96 | struct list_head list; |
|---|
| 93 | 97 | int id; |
|---|
| 94 | | - u32 ctemp; |
|---|
| 95 | 98 | }; |
|---|
| 96 | 99 | |
|---|
| 97 | 100 | #define rcar_thermal_for_each_priv(pos, common) \ |
|---|
| .. | .. |
|---|
| 111 | 114 | { |
|---|
| 112 | 115 | .compatible = "renesas,rcar-gen2-thermal", |
|---|
| 113 | 116 | .data = &rcar_gen2_thermal, |
|---|
| 117 | + }, |
|---|
| 118 | + { |
|---|
| 119 | + .compatible = "renesas,thermal-r8a774c0", |
|---|
| 120 | + .data = &rcar_gen3_thermal, |
|---|
| 121 | + }, |
|---|
| 122 | + { |
|---|
| 123 | + .compatible = "renesas,thermal-r8a77970", |
|---|
| 124 | + .data = &rcar_gen3_thermal, |
|---|
| 125 | + }, |
|---|
| 126 | + { |
|---|
| 127 | + .compatible = "renesas,thermal-r8a77990", |
|---|
| 128 | + .data = &rcar_gen3_thermal, |
|---|
| 114 | 129 | }, |
|---|
| 115 | 130 | { |
|---|
| 116 | 131 | .compatible = "renesas,thermal-r8a77995", |
|---|
| .. | .. |
|---|
| 183 | 198 | static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv) |
|---|
| 184 | 199 | { |
|---|
| 185 | 200 | struct device *dev = rcar_priv_to_dev(priv); |
|---|
| 186 | | - int i; |
|---|
| 187 | | - u32 ctemp, old, new; |
|---|
| 188 | | - int ret = -EINVAL; |
|---|
| 201 | + int old, new, ctemp = -EINVAL; |
|---|
| 202 | + unsigned int i; |
|---|
| 189 | 203 | |
|---|
| 190 | 204 | mutex_lock(&priv->lock); |
|---|
| 191 | 205 | |
|---|
| .. | .. |
|---|
| 195 | 209 | */ |
|---|
| 196 | 210 | rcar_thermal_bset(priv, THSCR, CPCTL, CPCTL); |
|---|
| 197 | 211 | |
|---|
| 198 | | - ctemp = 0; |
|---|
| 199 | 212 | old = ~0; |
|---|
| 200 | 213 | for (i = 0; i < 128; i++) { |
|---|
| 201 | 214 | /* |
|---|
| .. | .. |
|---|
| 203 | 216 | * to get stable temperature. |
|---|
| 204 | 217 | * see "Usage Notes" on datasheet |
|---|
| 205 | 218 | */ |
|---|
| 206 | | - udelay(300); |
|---|
| 219 | + usleep_range(300, 400); |
|---|
| 207 | 220 | |
|---|
| 208 | 221 | new = rcar_thermal_read(priv, THSSR) & CTEMP; |
|---|
| 209 | 222 | if (new == old) { |
|---|
| .. | .. |
|---|
| 213 | 226 | old = new; |
|---|
| 214 | 227 | } |
|---|
| 215 | 228 | |
|---|
| 216 | | - if (!ctemp) { |
|---|
| 229 | + if (ctemp < 0) { |
|---|
| 217 | 230 | dev_err(dev, "thermal sensor was broken\n"); |
|---|
| 218 | 231 | goto err_out_unlock; |
|---|
| 219 | 232 | } |
|---|
| .. | .. |
|---|
| 231 | 244 | ((ctemp - 1) << 0))); |
|---|
| 232 | 245 | } |
|---|
| 233 | 246 | |
|---|
| 234 | | - dev_dbg(dev, "thermal%d %d -> %d\n", priv->id, priv->ctemp, ctemp); |
|---|
| 235 | | - |
|---|
| 236 | | - priv->ctemp = ctemp; |
|---|
| 237 | | - ret = 0; |
|---|
| 238 | 247 | err_out_unlock: |
|---|
| 239 | 248 | mutex_unlock(&priv->lock); |
|---|
| 240 | | - return ret; |
|---|
| 249 | + |
|---|
| 250 | + return ctemp; |
|---|
| 241 | 251 | } |
|---|
| 242 | 252 | |
|---|
| 243 | 253 | static int rcar_thermal_get_current_temp(struct rcar_thermal_priv *priv, |
|---|
| 244 | 254 | int *temp) |
|---|
| 245 | 255 | { |
|---|
| 246 | | - int tmp; |
|---|
| 247 | | - int ret; |
|---|
| 256 | + int ctemp; |
|---|
| 248 | 257 | |
|---|
| 249 | | - ret = rcar_thermal_update_temp(priv); |
|---|
| 250 | | - if (ret < 0) |
|---|
| 251 | | - return ret; |
|---|
| 258 | + ctemp = rcar_thermal_update_temp(priv); |
|---|
| 259 | + if (ctemp < 0) |
|---|
| 260 | + return ctemp; |
|---|
| 252 | 261 | |
|---|
| 253 | | - mutex_lock(&priv->lock); |
|---|
| 254 | | - tmp = MCELSIUS((priv->ctemp * 5) - 65); |
|---|
| 255 | | - mutex_unlock(&priv->lock); |
|---|
| 262 | + /* Guaranteed operating range is -45C to 125C. */ |
|---|
| 256 | 263 | |
|---|
| 257 | | - if ((tmp < MCELSIUS(-45)) || (tmp > MCELSIUS(125))) { |
|---|
| 258 | | - struct device *dev = rcar_priv_to_dev(priv); |
|---|
| 259 | | - |
|---|
| 260 | | - dev_err(dev, "it couldn't measure temperature correctly\n"); |
|---|
| 261 | | - return -EIO; |
|---|
| 262 | | - } |
|---|
| 263 | | - |
|---|
| 264 | | - *temp = tmp; |
|---|
| 264 | + if (priv->chip->ctemp_bands == 1) |
|---|
| 265 | + *temp = MCELSIUS((ctemp * 5) - 65); |
|---|
| 266 | + else if (ctemp < 24) |
|---|
| 267 | + *temp = MCELSIUS(((ctemp * 55) - 720) / 10); |
|---|
| 268 | + else |
|---|
| 269 | + *temp = MCELSIUS((ctemp * 5) - 60); |
|---|
| 265 | 270 | |
|---|
| 266 | 271 | return 0; |
|---|
| 267 | 272 | } |
|---|
| .. | .. |
|---|
| 371 | 376 | static void rcar_thermal_work(struct work_struct *work) |
|---|
| 372 | 377 | { |
|---|
| 373 | 378 | struct rcar_thermal_priv *priv; |
|---|
| 374 | | - int cctemp, nctemp; |
|---|
| 375 | 379 | int ret; |
|---|
| 376 | 380 | |
|---|
| 377 | 381 | priv = container_of(work, struct rcar_thermal_priv, work.work); |
|---|
| 378 | | - |
|---|
| 379 | | - ret = rcar_thermal_get_current_temp(priv, &cctemp); |
|---|
| 380 | | - if (ret < 0) |
|---|
| 381 | | - return; |
|---|
| 382 | 382 | |
|---|
| 383 | 383 | ret = rcar_thermal_update_temp(priv); |
|---|
| 384 | 384 | if (ret < 0) |
|---|
| .. | .. |
|---|
| 386 | 386 | |
|---|
| 387 | 387 | rcar_thermal_irq_enable(priv); |
|---|
| 388 | 388 | |
|---|
| 389 | | - ret = rcar_thermal_get_current_temp(priv, &nctemp); |
|---|
| 390 | | - if (ret < 0) |
|---|
| 391 | | - return; |
|---|
| 392 | | - |
|---|
| 393 | | - if (nctemp != cctemp) |
|---|
| 394 | | - thermal_zone_device_update(priv->zone, |
|---|
| 395 | | - THERMAL_EVENT_UNSPECIFIED); |
|---|
| 389 | + thermal_zone_device_update(priv->zone, THERMAL_EVENT_UNSPECIFIED); |
|---|
| 396 | 390 | } |
|---|
| 397 | 391 | |
|---|
| 398 | 392 | static u32 rcar_thermal_had_changed(struct rcar_thermal_priv *priv, u32 status) |
|---|
| .. | .. |
|---|
| 552 | 546 | if (ret < 0) |
|---|
| 553 | 547 | goto error_unregister; |
|---|
| 554 | 548 | |
|---|
| 555 | | - if (chip->use_of_thermal) |
|---|
| 549 | + if (chip->use_of_thermal) { |
|---|
| 556 | 550 | priv->zone = devm_thermal_zone_of_sensor_register( |
|---|
| 557 | 551 | dev, i, priv, |
|---|
| 558 | 552 | &rcar_thermal_zone_of_ops); |
|---|
| 559 | | - else |
|---|
| 553 | + } else { |
|---|
| 560 | 554 | priv->zone = thermal_zone_device_register( |
|---|
| 561 | 555 | "rcar_thermal", |
|---|
| 562 | 556 | 1, 0, priv, |
|---|
| 563 | 557 | &rcar_thermal_zone_ops, NULL, 0, |
|---|
| 564 | 558 | idle); |
|---|
| 559 | + |
|---|
| 560 | + ret = thermal_zone_device_enable(priv->zone); |
|---|
| 561 | + if (ret) { |
|---|
| 562 | + thermal_zone_device_unregister(priv->zone); |
|---|
| 563 | + priv->zone = ERR_PTR(ret); |
|---|
| 564 | + } |
|---|
| 565 | + } |
|---|
| 565 | 566 | if (IS_ERR(priv->zone)) { |
|---|
| 566 | 567 | dev_err(dev, "can't register thermal zone\n"); |
|---|
| 567 | 568 | ret = PTR_ERR(priv->zone); |
|---|