Merge tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull "ARM: driver specific updates" from Arnd Bergmann:
"These are all specific to some driver. They are typically the
platform side of a change in the drivers directory, such as adding a
new driver or extending the interface to the platform. In cases where
there is no maintainer for the driver, or the maintainer prefers to
have the platform changes in the same branch as the driver changes,
the patches to the drivers are included as well.
A much smaller set of driver updates that depend on other branches
getting merged first will be sent later.
The new export of tegra_chip_uid conflicts with other changes in
fuse.c. In rtc-sa1100.c, the global removal of IRQF_DISABLED
conflicts with the cleanup of the interrupt handling of that driver.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>"
Fixed up aforementioned trivial conflicts.
* tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (94 commits)
ARM: SAMSUNG: change the name from s3c-sdhci to exynos4-sdhci
mmc: sdhci-s3c: add platform data for the second capability
ARM: SAMSUNG: support the second capability for samsung-soc
ARM: EXYNOS: add support DMA for EXYNOS4X12 SoC
ARM: EXYNOS: Add apb_pclk clkdev entry for mdma1
ARM: EXYNOS: Enable MDMA driver
regulator: Remove bq24022 regulator driver
rtc: sa1100: add OF support
pxa: magician/hx4700: Convert to gpio-regulator from bq24022
ARM: OMAP3+: SmartReflex: fix error handling
ARM: OMAP3+: SmartReflex: fix the use of debugfs_create_* API
ARM: OMAP3+: SmartReflex: micro-optimization for sanity check
ARM: OMAP3+: SmartReflex: misc cleanups
ARM: OMAP3+: SmartReflex: move late_initcall() closer to its argument
ARM: OMAP3+: SmartReflex: add missing platform_set_drvdata()
ARM: OMAP3+: hwmod: add SmartReflex IRQs
ARM: OMAP3+: SmartReflex: clear ERRCONFIG_VPBOUNDINTST only on a need
ARM: OMAP3+: SmartReflex: Fix status masking in ERRCONFIG register
ARM: OMAP3+: SmartReflex: Add a shutdown hook
ARM: OMAP3+: SmartReflex Class3: disable errorgen before disable VP
...
Conflicts:
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/fuse.c
drivers/rtc/rtc-sa1100.c
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index ea49bd9..c1afb27 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -19,25 +19,75 @@
#include <linux/kernel.h>
#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
#include <mach/iomap.h>
#include "fuse.h"
+#include "apbio.h"
#define FUSE_UID_LOW 0x108
#define FUSE_UID_HIGH 0x10c
#define FUSE_SKU_INFO 0x110
#define FUSE_SPARE_BIT 0x200
-static inline u32 fuse_readl(unsigned long offset)
+int tegra_sku_id;
+int tegra_cpu_process_id;
+int tegra_core_process_id;
+enum tegra_revision tegra_revision;
+
+/* The BCT to use at boot is specified by board straps that can be read
+ * through a APB misc register and decoded. 2 bits, i.e. 4 possible BCTs.
+ */
+int tegra_bct_strapping;
+
+#define STRAP_OPT 0x008
+#define GMI_AD0 (1 << 4)
+#define GMI_AD1 (1 << 5)
+#define RAM_ID_MASK (GMI_AD0 | GMI_AD1)
+#define RAM_CODE_SHIFT 4
+
+static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
+ [TEGRA_REVISION_UNKNOWN] = "unknown",
+ [TEGRA_REVISION_A01] = "A01",
+ [TEGRA_REVISION_A02] = "A02",
+ [TEGRA_REVISION_A03] = "A03",
+ [TEGRA_REVISION_A03p] = "A03 prime",
+ [TEGRA_REVISION_A04] = "A04",
+};
+
+static inline u32 tegra_fuse_readl(unsigned long offset)
{
- return readl(IO_TO_VIRT(TEGRA_FUSE_BASE + offset));
+ return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
}
-static inline void fuse_writel(u32 value, unsigned long offset)
+static inline bool get_spare_fuse(int bit)
{
- writel(value, IO_TO_VIRT(TEGRA_FUSE_BASE + offset));
+ return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
+}
+
+static enum tegra_revision tegra_get_revision(void)
+{
+ void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804;
+ u32 id = readl(chip_id);
+ u32 minor_rev = (id >> 16) & 0xf;
+ u32 chipid = (id >> 8) & 0xff;
+
+ switch (minor_rev) {
+ case 1:
+ return TEGRA_REVISION_A01;
+ case 2:
+ return TEGRA_REVISION_A02;
+ case 3:
+ if (chipid == 0x20 && (get_spare_fuse(18) || get_spare_fuse(19)))
+ return TEGRA_REVISION_A03p;
+ else
+ return TEGRA_REVISION_A03;
+ case 4:
+ return TEGRA_REVISION_A04;
+ default:
+ return TEGRA_REVISION_UNKNOWN;
+ }
}
void tegra_init_fuse(void)
@@ -46,41 +96,32 @@
reg |= 1 << 28;
writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
- pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n",
- tegra_sku_id(), tegra_cpu_process_id(),
- tegra_core_process_id());
+ reg = tegra_fuse_readl(FUSE_SKU_INFO);
+ tegra_sku_id = reg & 0xFF;
+
+ reg = tegra_fuse_readl(FUSE_SPARE_BIT);
+ tegra_cpu_process_id = (reg >> 6) & 3;
+
+ reg = tegra_fuse_readl(FUSE_SPARE_BIT);
+ tegra_core_process_id = (reg >> 12) & 3;
+
+ reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
+ tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
+
+ tegra_revision = tegra_get_revision();
+
+ pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
+ tegra_revision_name[tegra_get_revision()],
+ tegra_sku_id, tegra_cpu_process_id,
+ tegra_core_process_id);
}
unsigned long long tegra_chip_uid(void)
{
unsigned long long lo, hi;
- lo = fuse_readl(FUSE_UID_LOW);
- hi = fuse_readl(FUSE_UID_HIGH);
+ lo = tegra_fuse_readl(FUSE_UID_LOW);
+ hi = tegra_fuse_readl(FUSE_UID_HIGH);
return (hi << 32ull) | lo;
}
EXPORT_SYMBOL(tegra_chip_uid);
-
-int tegra_sku_id(void)
-{
- int sku_id;
- u32 reg = fuse_readl(FUSE_SKU_INFO);
- sku_id = reg & 0xFF;
- return sku_id;
-}
-
-int tegra_cpu_process_id(void)
-{
- int cpu_process_id;
- u32 reg = fuse_readl(FUSE_SPARE_BIT);
- cpu_process_id = (reg >> 6) & 3;
- return cpu_process_id;
-}
-
-int tegra_core_process_id(void)
-{
- int core_process_id;
- u32 reg = fuse_readl(FUSE_SPARE_BIT);
- core_process_id = (reg >> 12) & 3;
- return core_process_id;
-}