summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@ti.com>2014-11-24 12:02:12 -0500
committerTom Rini <trini@ti.com>2014-11-24 12:02:12 -0500
commitdee332ffb735f65ab922118791a583c17bb0b795 (patch)
treed07bc0821792831aa4baeb27868252c2d32c7738 /drivers
parent1739564e753bc3a8097f8937a3cbe738bdaaed5d (diff)
parente7eb277dced570f177d75d56f40219d9dc599ed1 (diff)
downloadblackbird-obmc-uboot-dee332ffb735f65ab922118791a583c17bb0b795.tar.gz
blackbird-obmc-uboot-dee332ffb735f65ab922118791a583c17bb0b795.zip
Merge branch 'master' of git://www.denx.de/git/u-boot-imx
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/block/ata_piix.c5
-rw-r--r--drivers/block/dwc_ahsata.c21
-rw-r--r--drivers/block/fsl_sata.c5
-rw-r--r--drivers/block/pata_bfin.c5
-rw-r--r--drivers/block/sata_dwc.c5
-rw-r--r--drivers/block/sata_sil.c5
-rw-r--r--drivers/block/sata_sil3114.c5
-rw-r--r--drivers/mmc/fsl_esdhc.c8
-rw-r--r--drivers/thermal/Makefile9
-rw-r--r--drivers/thermal/imx_thermal.c177
-rw-r--r--drivers/thermal/thermal-uclass.c30
12 files changed, 276 insertions, 0 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 33227c8bd6..7683c6139f 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -21,3 +21,4 @@ obj-y += pwm/
obj-y += input/
# SOC specific infrastructure drivers.
obj-y += soc/
+obj-y += thermal/
diff --git a/drivers/block/ata_piix.c b/drivers/block/ata_piix.c
index 5cf91ade8d..30426842cc 100644
--- a/drivers/block/ata_piix.c
+++ b/drivers/block/ata_piix.c
@@ -192,6 +192,11 @@ int init_sata(int dev)
return 0;
}
+int reset_sata(int dev)
+{
+ return 0;
+}
+
static inline u8 sata_inb(unsigned long ioaddr)
{
return inb(ioaddr);
diff --git a/drivers/block/dwc_ahsata.c b/drivers/block/dwc_ahsata.c
index c68fd2f256..9a2b547af2 100644
--- a/drivers/block/dwc_ahsata.c
+++ b/drivers/block/dwc_ahsata.c
@@ -592,6 +592,27 @@ int init_sata(int dev)
return 0;
}
+int reset_sata(int dev)
+{
+ struct ahci_probe_ent *probe_ent =
+ (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+ struct sata_host_regs *host_mmio =
+ (struct sata_host_regs *)probe_ent->mmio_base;
+
+ if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) {
+ printf("The sata index %d is out of ranges\n\r", dev);
+ return -1;
+ }
+
+ setbits_le32(&host_mmio->ghc, SATA_HOST_GHC_HR);
+ while (readl(&host_mmio->ghc) & SATA_HOST_GHC_HR)
+ udelay(100);
+
+ disable_sata_clock();
+
+ return 0;
+}
+
static void dwc_ahsata_print_info(int dev)
{
block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
diff --git a/drivers/block/fsl_sata.c b/drivers/block/fsl_sata.c
index ebd626178d..71d7cec7bd 100644
--- a/drivers/block/fsl_sata.c
+++ b/drivers/block/fsl_sata.c
@@ -255,6 +255,11 @@ int init_sata(int dev)
return 0;
}
+int reset_sata(int dev)
+{
+ return 0;
+}
+
static void fsl_sata_dump_regs(fsl_sata_reg_t __iomem *reg)
{
printf("\n\rSATA: %08x\n\r", (u32)reg);
diff --git a/drivers/block/pata_bfin.c b/drivers/block/pata_bfin.c
index b7fd1cd634..c2673bd05d 100644
--- a/drivers/block/pata_bfin.c
+++ b/drivers/block/pata_bfin.c
@@ -1009,6 +1009,11 @@ int init_sata(int dev)
return res;
}
+int reset_sata(int dev)
+{
+ return 0;
+}
+
/* Read up to 255 sectors
*
* Returns sectors read
diff --git a/drivers/block/sata_dwc.c b/drivers/block/sata_dwc.c
index efca5eaba4..9e8b067cdc 100644
--- a/drivers/block/sata_dwc.c
+++ b/drivers/block/sata_dwc.c
@@ -423,6 +423,11 @@ int init_sata(int dev)
return rc;
}
+int reset_sata(int dev)
+{
+ return 0;
+}
+
static u8 ata_check_altstatus(struct ata_port *ap)
{
u8 val = 0;
diff --git a/drivers/block/sata_sil.c b/drivers/block/sata_sil.c
index b483dbb5d1..daff7d4ab5 100644
--- a/drivers/block/sata_sil.c
+++ b/drivers/block/sata_sil.c
@@ -571,6 +571,11 @@ int init_sata(int dev)
return 0;
}
+int reset_sata(int dev)
+{
+ return 0;
+}
+
/*
* SATA interface between low level driver and command layer
*/
diff --git a/drivers/block/sata_sil3114.c b/drivers/block/sata_sil3114.c
index 3aa6fc9839..61ffb66a77 100644
--- a/drivers/block/sata_sil3114.c
+++ b/drivers/block/sata_sil3114.c
@@ -702,6 +702,11 @@ int init_sata (int dev)
return res;
}
+int reset_sata(int dev)
+{
+ return 0;
+}
+
/* Check if device is connected to port */
int sata_bus_probe (int portno)
{
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 90b8ed01cc..cb46b13cbd 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -23,6 +23,13 @@
DECLARE_GLOBAL_DATA_PTR;
+#define SDHCI_IRQ_EN_BITS (IRQSTATEN_CC | IRQSTATEN_TC | \
+ IRQSTATEN_CINT | \
+ IRQSTATEN_CTOE | IRQSTATEN_CCE | IRQSTATEN_CEBE | \
+ IRQSTATEN_CIE | IRQSTATEN_DTOE | IRQSTATEN_DCE | \
+ IRQSTATEN_DEBE | IRQSTATEN_BRR | IRQSTATEN_BWR | \
+ IRQSTATEN_DINT)
+
struct fsl_esdhc {
uint dsaddr; /* SDMA system address register */
uint blkattr; /* Block attributes register */
@@ -558,6 +565,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
| SYSCTL_IPGEN | SYSCTL_CKEN);
+ writel(SDHCI_IRQ_EN_BITS, &regs->irqstaten);
memset(&cfg->cfg, 0, sizeof(cfg->cfg));
voltage_caps = 0;
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
new file mode 100644
index 0000000000..6d4cacdcf7
--- /dev/null
+++ b/drivers/thermal/Makefile
@@ -0,0 +1,9 @@
+#
+# (C) Copyright 2014 Freescale Semiconductor, Inc.
+# Author: Nitin Garg <nitin.garg@freescale.com>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-$(CONFIG_DM_THERMAL) += thermal-uclass.o
+obj-$(CONFIG_IMX6_THERMAL) += imx_thermal.o
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
new file mode 100644
index 0000000000..116158511d
--- /dev/null
+++ b/drivers/thermal/imx_thermal.c
@@ -0,0 +1,177 @@
+/*
+ * (C) Copyright 2014 Freescale Semiconductor, Inc.
+ * Author: Nitin Garg <nitin.garg@freescale.com>
+ * Ye Li <Ye.Li@freescale.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <div64.h>
+#include <fuse.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
+#include <thermal.h>
+#include <imx_thermal.h>
+
+#define TEMPERATURE_MIN -40
+#define TEMPERATURE_HOT 80
+#define TEMPERATURE_MAX 125
+#define FACTOR0 10000000
+#define FACTOR1 15976
+#define FACTOR2 4297157
+#define MEASURE_FREQ 327
+
+#define TEMPSENSE0_TEMP_CNT_SHIFT 8
+#define TEMPSENSE0_TEMP_CNT_MASK (0xfff << TEMPSENSE0_TEMP_CNT_SHIFT)
+#define TEMPSENSE0_FINISHED (1 << 2)
+#define TEMPSENSE0_MEASURE_TEMP (1 << 1)
+#define TEMPSENSE0_POWER_DOWN (1 << 0)
+#define MISC0_REFTOP_SELBIASOFF (1 << 3)
+#define TEMPSENSE1_MEASURE_FREQ 0xffff
+
+static int read_cpu_temperature(struct udevice *dev)
+{
+ int temperature;
+ unsigned int reg, n_meas;
+ const struct imx_thermal_plat *pdata = dev_get_platdata(dev);
+ struct anatop_regs *anatop = (struct anatop_regs *)pdata->regs;
+ unsigned int *priv = dev_get_priv(dev);
+ u32 fuse = *priv;
+ int t1, n1;
+ u32 c1, c2;
+ u64 temp64;
+
+ /*
+ * Sensor data layout:
+ * [31:20] - sensor value @ 25C
+ * We use universal formula now and only need sensor value @ 25C
+ * slope = 0.4297157 - (0.0015976 * 25C fuse)
+ */
+ n1 = fuse >> 20;
+ t1 = 25; /* t1 always 25C */
+
+ /*
+ * Derived from linear interpolation:
+ * slope = 0.4297157 - (0.0015976 * 25C fuse)
+ * slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0
+ * (Nmeas - n1) / (Tmeas - t1) = slope
+ * We want to reduce this down to the minimum computation necessary
+ * for each temperature read. Also, we want Tmeas in millicelsius
+ * and we don't want to lose precision from integer division. So...
+ * Tmeas = (Nmeas - n1) / slope + t1
+ * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1
+ * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1
+ * Let constant c1 = (-1000 / slope)
+ * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1
+ * Let constant c2 = n1 *c1 + 1000 * t1
+ * milli_Tmeas = c2 - Nmeas * c1
+ */
+ temp64 = FACTOR0;
+ temp64 *= 1000;
+ do_div(temp64, FACTOR1 * n1 - FACTOR2);
+ c1 = temp64;
+ c2 = n1 * c1 + 1000 * t1;
+
+ /*
+ * now we only use single measure, every time we read
+ * the temperature, we will power on/down anadig thermal
+ * module
+ */
+ writel(TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_clr);
+ writel(MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set);
+
+ /* setup measure freq */
+ reg = readl(&anatop->tempsense1);
+ reg &= ~TEMPSENSE1_MEASURE_FREQ;
+ reg |= MEASURE_FREQ;
+ writel(reg, &anatop->tempsense1);
+
+ /* start the measurement process */
+ writel(TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_clr);
+ writel(TEMPSENSE0_FINISHED, &anatop->tempsense0_clr);
+ writel(TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_set);
+
+ /* make sure that the latest temp is valid */
+ while ((readl(&anatop->tempsense0) &
+ TEMPSENSE0_FINISHED) == 0)
+ udelay(10000);
+
+ /* read temperature count */
+ reg = readl(&anatop->tempsense0);
+ n_meas = (reg & TEMPSENSE0_TEMP_CNT_MASK)
+ >> TEMPSENSE0_TEMP_CNT_SHIFT;
+ writel(TEMPSENSE0_FINISHED, &anatop->tempsense0_clr);
+
+ /* milli_Tmeas = c2 - Nmeas * c1 */
+ temperature = (c2 - n_meas * c1)/1000;
+
+ /* power down anatop thermal sensor */
+ writel(TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_set);
+ writel(MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_clr);
+
+ return temperature;
+}
+
+int imx_thermal_get_temp(struct udevice *dev, int *temp)
+{
+ int cpu_tmp = 0;
+
+ cpu_tmp = read_cpu_temperature(dev);
+ while (cpu_tmp > TEMPERATURE_MIN && cpu_tmp < TEMPERATURE_MAX) {
+ if (cpu_tmp >= TEMPERATURE_HOT) {
+ printf("CPU Temperature is %d C, too hot to boot, waiting...\n",
+ cpu_tmp);
+ udelay(5000000);
+ cpu_tmp = read_cpu_temperature(dev);
+ } else {
+ break;
+ }
+ }
+
+ *temp = cpu_tmp;
+
+ return 0;
+}
+
+static const struct dm_thermal_ops imx_thermal_ops = {
+ .get_temp = imx_thermal_get_temp,
+};
+
+static int imx_thermal_probe(struct udevice *dev)
+{
+ unsigned int fuse = ~0;
+
+ const struct imx_thermal_plat *pdata = dev_get_platdata(dev);
+ unsigned int *priv = dev_get_priv(dev);
+
+ /* Read Temperature calibration data fuse */
+ fuse_read(pdata->fuse_bank, pdata->fuse_word, &fuse);
+
+ /* Check for valid fuse */
+ if (fuse == 0 || fuse == ~0) {
+ printf("CPU: Thermal invalid data, fuse: 0x%x\n", fuse);
+ return -EPERM;
+ } else {
+ printf("CPU: Thermal calibration data: 0x%x\n", fuse);
+ }
+
+ *priv = fuse;
+
+ enable_thermal_clk();
+
+ return 0;
+}
+
+U_BOOT_DRIVER(imx_thermal) = {
+ .name = "imx_thermal",
+ .id = UCLASS_THERMAL,
+ .ops = &imx_thermal_ops,
+ .probe = imx_thermal_probe,
+ .priv_auto_alloc_size = sizeof(unsigned int),
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/thermal/thermal-uclass.c b/drivers/thermal/thermal-uclass.c
new file mode 100644
index 0000000000..3bee1a7dc7
--- /dev/null
+++ b/drivers/thermal/thermal-uclass.c
@@ -0,0 +1,30 @@
+/*
+ * (C) Copyright 2014 Freescale Semiconductor, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <thermal.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <linux/list.h>
+
+
+int thermal_get_temp(struct udevice *dev, int *temp)
+{
+ const struct dm_thermal_ops *ops = device_get_ops(dev);
+
+ if (!ops->get_temp)
+ return -ENOSYS;
+
+ return ops->get_temp(dev, temp);
+}
+
+UCLASS_DRIVER(thermal) = {
+ .id = UCLASS_THERMAL,
+ .name = "thermal",
+};
OpenPOWER on IntegriCloud