aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCsaba Kertesz <csaba.kertesz@vincit.fi>2016-10-25 16:08:07 -0400
committerTejun Heo <tj@kernel.org>2017-01-06 15:35:17 -0500
commit54643a83b41a2bff90a0615799686b37a1109404 (patch)
treeb6baf81bd6d8abe9270672c90b6906da6c026382
parentde2518201e526f4491e5856b9818f5c18684a6a7 (diff)
ahci: imx: Add imx53 SATA temperature sensor support
Add a hwmon entry to get the temperature from the die of imx53 SATA. The original patch was made by Richard Zhu for kernel 2.6.x: ENGR00134041-MX53-Add-the-SATA-AHCI-temperature-monitor.patch Signed-off-by: Fabien Lahoudere <fabien.lahoudere@collabora.co.uk> Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--drivers/ata/ahci_imx.c195
1 files changed, 195 insertions, 0 deletions
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 3f3a7db208ae..420f065978dc 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -26,6 +26,9 @@
26#include <linux/mfd/syscon.h> 26#include <linux/mfd/syscon.h>
27#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> 27#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
28#include <linux/libata.h> 28#include <linux/libata.h>
29#include <linux/hwmon.h>
30#include <linux/hwmon-sysfs.h>
31#include <linux/thermal.h>
29#include "ahci.h" 32#include "ahci.h"
30 33
31#define DRV_NAME "ahci-imx" 34#define DRV_NAME "ahci-imx"
@@ -214,6 +217,180 @@ static int imx_sata_phy_reset(struct ahci_host_priv *hpriv)
214 return timeout ? 0 : -ETIMEDOUT; 217 return timeout ? 0 : -ETIMEDOUT;
215} 218}
216 219
220enum {
221 /* SATA PHY Register */
222 SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT = 0x0001,
223 SATA_PHY_CR_CLOCK_DAC_CTL = 0x0008,
224 SATA_PHY_CR_CLOCK_RTUNE_CTL = 0x0009,
225 SATA_PHY_CR_CLOCK_ADC_OUT = 0x000A,
226 SATA_PHY_CR_CLOCK_MPLL_TST = 0x0017,
227};
228
229static int read_adc_sum(void *dev, u16 rtune_ctl_reg, void __iomem * mmio)
230{
231 u16 adc_out_reg, read_sum;
232 u32 index, read_attempt;
233 const u32 attempt_limit = 100;
234
235 imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
236 imx_phy_reg_write(rtune_ctl_reg, mmio);
237
238 /* two dummy read */
239 index = 0;
240 read_attempt = 0;
241 adc_out_reg = 0;
242 imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_ADC_OUT, mmio);
243 while (index < 2) {
244 imx_phy_reg_read(&adc_out_reg, mmio);
245 /* check if valid */
246 if (adc_out_reg & 0x400)
247 index++;
248
249 read_attempt++;
250 if (read_attempt > attempt_limit) {
251 dev_err(dev, "Read REG more than %d times!\n",
252 attempt_limit);
253 break;
254 }
255 }
256
257 index = 0;
258 read_attempt = 0;
259 read_sum = 0;
260 while (index < 80) {
261 imx_phy_reg_read(&adc_out_reg, mmio);
262 if (adc_out_reg & 0x400) {
263 read_sum = read_sum + (adc_out_reg & 0x3FF);
264 index++;
265 }
266 read_attempt++;
267 if (read_attempt > attempt_limit) {
268 dev_err(dev, "Read REG more than %d times!\n",
269 attempt_limit);
270 break;
271 }
272 }
273
274 /* Use the U32 to make 1000 precision */
275 return (read_sum * 1000) / 80;
276}
277
278/* SATA AHCI temperature monitor */
279static int sata_ahci_read_temperature(void *dev, int *temp)
280{
281 u16 mpll_test_reg, rtune_ctl_reg, dac_ctl_reg, read_sum;
282 u32 str1, str2, str3, str4;
283 int m1, m2, a;
284 struct ahci_host_priv *hpriv = dev_get_drvdata(dev);
285 void __iomem *mmio = hpriv->mmio;
286
287 /* check rd-wr to reg */
288 read_sum = 0;
289 imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT, mmio);
290 imx_phy_reg_write(read_sum, mmio);
291 imx_phy_reg_read(&read_sum, mmio);
292 if ((read_sum & 0xffff) != 0)
293 dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
294
295 imx_phy_reg_write(0x5A5A, mmio);
296 imx_phy_reg_read(&read_sum, mmio);
297 if ((read_sum & 0xffff) != 0x5A5A)
298 dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
299
300 imx_phy_reg_write(0x1234, mmio);
301 imx_phy_reg_read(&read_sum, mmio);
302 if ((read_sum & 0xffff) != 0x1234)
303 dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
304
305 /* start temperature test */
306 imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
307 imx_phy_reg_read(&mpll_test_reg, mmio);
308 imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
309 imx_phy_reg_read(&rtune_ctl_reg, mmio);
310 imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
311 imx_phy_reg_read(&dac_ctl_reg, mmio);
312
313 /* mpll_tst.meas_iv ([12:2]) */
314 str1 = (mpll_test_reg >> 2) & 0x7FF;
315 /* rtune_ctl.mode ([1:0]) */
316 str2 = (rtune_ctl_reg) & 0x3;
317 /* dac_ctl.dac_mode ([14:12]) */
318 str3 = (dac_ctl_reg >> 12) & 0x7;
319 /* rtune_ctl.sel_atbp ([4]) */
320 str4 = (rtune_ctl_reg >> 4);
321
322 /* Calculate the m1 */
323 /* mpll_tst.meas_iv */
324 mpll_test_reg = (mpll_test_reg & 0xE03) | (512) << 2;
325 /* rtune_ctl.mode */
326 rtune_ctl_reg = (rtune_ctl_reg & 0xFFC) | (1);
327 /* dac_ctl.dac_mode */
328 dac_ctl_reg = (dac_ctl_reg & 0x8FF) | (4) << 12;
329 /* rtune_ctl.sel_atbp */
330 rtune_ctl_reg = (rtune_ctl_reg & 0xFEF) | (0) << 4;
331 imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
332 imx_phy_reg_write(mpll_test_reg, mmio);
333 imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
334 imx_phy_reg_write(dac_ctl_reg, mmio);
335 m1 = read_adc_sum(dev, rtune_ctl_reg, mmio);
336
337 /* Calculate the m2 */
338 /* rtune_ctl.sel_atbp */
339 rtune_ctl_reg = (rtune_ctl_reg & 0xFEF) | (1) << 4;
340 m2 = read_adc_sum(dev, rtune_ctl_reg, mmio);
341
342 /* restore the status */
343 /* mpll_tst.meas_iv */
344 mpll_test_reg = (mpll_test_reg & 0xE03) | (str1) << 2;
345 /* rtune_ctl.mode */
346 rtune_ctl_reg = (rtune_ctl_reg & 0xFFC) | (str2);
347 /* dac_ctl.dac_mode */
348 dac_ctl_reg = (dac_ctl_reg & 0x8FF) | (str3) << 12;
349 /* rtune_ctl.sel_atbp */
350 rtune_ctl_reg = (rtune_ctl_reg & 0xFEF) | (str4) << 4;
351
352 imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
353 imx_phy_reg_write(mpll_test_reg, mmio);
354 imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
355 imx_phy_reg_write(dac_ctl_reg, mmio);
356 imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
357 imx_phy_reg_write(rtune_ctl_reg, mmio);
358
359 /* Compute temperature */
360 if (!(m2 / 1000))
361 m2 = 1000;
362 a = (m2 - m1) / (m2/1000);
363 *temp = ((-559) * a * a) / 1000 + (1379) * a + (-458000);
364
365 return 0;
366}
367
368static ssize_t sata_ahci_show_temp(struct device *dev,
369 struct device_attribute *da,
370 char *buf)
371{
372 unsigned int temp = 0;
373 int err;
374
375 err = sata_ahci_read_temperature(dev, &temp);
376 if (err < 0)
377 return err;
378
379 return sprintf(buf, "%u\n", temp);
380}
381
382static const struct thermal_zone_of_device_ops fsl_sata_ahci_of_thermal_ops = {
383 .get_temp = sata_ahci_read_temperature,
384};
385
386static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sata_ahci_show_temp, NULL, 0);
387
388static struct attribute *fsl_sata_ahci_attrs[] = {
389 &sensor_dev_attr_temp1_input.dev_attr.attr,
390 NULL
391};
392ATTRIBUTE_GROUPS(fsl_sata_ahci);
393
217static int imx_sata_enable(struct ahci_host_priv *hpriv) 394static int imx_sata_enable(struct ahci_host_priv *hpriv)
218{ 395{
219 struct imx_ahci_priv *imxpriv = hpriv->plat_data; 396 struct imx_ahci_priv *imxpriv = hpriv->plat_data;
@@ -597,6 +774,24 @@ static int imx_ahci_probe(struct platform_device *pdev)
597 if (ret) 774 if (ret)
598 return ret; 775 return ret;
599 776
777 if (imxpriv->type == AHCI_IMX53) {
778 /* Add the temperature monitor */
779 struct device *hwmon_dev;
780
781 hwmon_dev =
782 devm_hwmon_device_register_with_groups(dev,
783 "sata_ahci",
784 hpriv,
785 fsl_sata_ahci_groups);
786 if (IS_ERR(hwmon_dev)) {
787 ret = PTR_ERR(hwmon_dev);
788 goto disable_clk;
789 }
790 devm_thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev,
791 &fsl_sata_ahci_of_thermal_ops);
792 dev_info(dev, "%s: sensor 'sata_ahci'\n", dev_name(hwmon_dev));
793 }
794
600 ret = imx_sata_enable(hpriv); 795 ret = imx_sata_enable(hpriv);
601 if (ret) 796 if (ret)
602 goto disable_clk; 797 goto disable_clk;