mvebu late fixes for v3.13
- mvebu - fix boot hang on Armada XP due to broken i2c offloading in A0 SoC revision (specifically experienced on some early OpenBlocks AX3-4 boards) -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJS1VXLAAoJEP45WPkGe8Znr94P/2Ds9luoKzglCJqcxpxFUnH+ aKR3O0Faw5WsuAW0JZAp7Qm9cWeMppVlnQIQh/FE/7Bo7ZOeasgEZinyBCcbKHEy c0kTls+m4wzvKRHDQW+U+Dhi1juXmPtlTMDvWqibYwsbP3dHMbxPRzWasaHIYesO mttWXMX1MVs65i+cC6PhqN413tiGmb3WxB05zJPvWRNXwdjc9vEd9S5LIc8XMbrW yEIDKd0D5tVL76rBpXYyMCreaIzkVvcVwuamtBHOG/kDovN8cxGu8bYT3xyyYmb1 Oshq3uhL3s3P0qDpp1MrhdlYDWduzCmY007/I9x2e4t/bT3sRHFywvJtumVsuQbZ 5Krsh27EB3dvgz7icmJBTOVWzLL0KGT2ntxlpm+KcqL1NgUJs6ejvOYreGClCkTF 6mtVa4ODSV4P1jO29dDIqOmu1t77KuETsT7ob9qR48SFwHfcMucJS9YFGoxpF6N5 v4oH/wMTtF6bLnMM/2pG69LEfC5APpvv0U6eC4IVzuddwPKraY60PyAryqCGXAsX pkXOdUcfaDN7touovm8yvAEF5+WzYU3b2a8pWclOC7n9Suu/4rhFdbtLJgorNo20 HUwnkZSuOKbaXWMpdpnQE+ANWkjKcvRW6yVpcr79ZYNDOW5HCWmOB1O9ckrgZbh8 +hoQW7Iz48jz/knQP81w =tliU -----END PGP SIGNATURE----- Merge tag 'mvebu-fixes-3.13' of git://git.infradead.org/linux-mvebu into next/fixes-non-critical From Jason Cooper: mvebu late fixes for v3.13 - mvebu - fix boot hang on Armada XP due to broken i2c offloading in A0 SoC revision (specifically experienced on some early OpenBlocks AX3-4 boards) * tag 'mvebu-fixes-3.13' of git://git.infradead.org/linux-mvebu: i2c: mv64xxx: Document the newly introduced Armada XP A0 compatible i2c: mv64xxx: Fix bus hang on A0 version of the Armada XP SoCs ARM: mvebu: Add quirk for i2c for the OpenBlocks AX3-4 board ARM: mvebu: Add support to get the ID and the revision of a SoC Signed-off-by: Kevin Hilman <khilman@linaro.org>
This commit is contained in:
commit
d267aae2f3
|
@ -5,7 +5,11 @@ Required properties :
|
|||
|
||||
- reg : Offset and length of the register set for the device
|
||||
- compatible : Should be "marvell,mv64xxx-i2c" or "allwinner,sun4i-i2c"
|
||||
or "marvell,mv78230-i2c"
|
||||
or "marvell,mv78230-i2c" or "marvell,mv78230-a0-i2c"
|
||||
Note: Only use "marvell,mv78230-a0-i2c" for a very rare,
|
||||
initial version of the SoC which had broken offload
|
||||
support. Linux auto-detects this and sets it
|
||||
appropriately.
|
||||
- interrupts : The interrupt number
|
||||
|
||||
Optional properties :
|
||||
|
|
|
@ -3,7 +3,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
|
|||
|
||||
AFLAGS_coherency_ll.o := -Wa,-march=armv7-a
|
||||
|
||||
obj-y += system-controller.o
|
||||
obj-y += system-controller.o mvebu-soc-id.o
|
||||
obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o
|
||||
obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/clocksource.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
@ -28,6 +29,7 @@
|
|||
#include "armada-370-xp.h"
|
||||
#include "common.h"
|
||||
#include "coherency.h"
|
||||
#include "mvebu-soc-id.h"
|
||||
|
||||
static void __init armada_370_xp_map_io(void)
|
||||
{
|
||||
|
@ -45,8 +47,38 @@ static void __init armada_370_xp_timer_and_clk_init(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void __init i2c_quirk(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
u32 dev, rev;
|
||||
|
||||
/*
|
||||
* Only revisons more recent than A0 support the offload
|
||||
* mechanism. We can exit only if we are sure that we can
|
||||
* get the SoC revision and it is more recent than A0.
|
||||
*/
|
||||
if (mvebu_get_soc_id(&rev, &dev) == 0 && dev > MV78XX0_A0_REV)
|
||||
return;
|
||||
|
||||
for_each_compatible_node(np, NULL, "marvell,mv78230-i2c") {
|
||||
struct property *new_compat;
|
||||
|
||||
new_compat = kzalloc(sizeof(*new_compat), GFP_KERNEL);
|
||||
|
||||
new_compat->name = kstrdup("compatible", GFP_KERNEL);
|
||||
new_compat->length = sizeof("marvell,mv78230-a0-i2c");
|
||||
new_compat->value = kstrdup("marvell,mv78230-a0-i2c",
|
||||
GFP_KERNEL);
|
||||
|
||||
of_update_property(np, new_compat);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void __init armada_370_xp_dt_init(void)
|
||||
{
|
||||
if (of_machine_is_compatible("plathome,openblocks-ax3-4"))
|
||||
i2c_quirk();
|
||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* ID and revision information for mvebu SoCs
|
||||
*
|
||||
* Copyright (C) 2014 Marvell
|
||||
*
|
||||
* Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*
|
||||
* All the mvebu SoCs have information related to their variant and
|
||||
* revision that can be read from the PCI control register. This is
|
||||
* done before the PCI initialization to avoid any conflict. Once the
|
||||
* ID and revision are retrieved, the mapping is freed.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "mvebu-soc-id: " fmt
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include "mvebu-soc-id.h"
|
||||
|
||||
#define PCIE_DEV_ID_OFF 0x0
|
||||
#define PCIE_DEV_REV_OFF 0x8
|
||||
|
||||
#define SOC_ID_MASK 0xFFFF0000
|
||||
#define SOC_REV_MASK 0xFF
|
||||
|
||||
static u32 soc_dev_id;
|
||||
static u32 soc_rev;
|
||||
static bool is_id_valid;
|
||||
|
||||
static const struct of_device_id mvebu_pcie_of_match_table[] = {
|
||||
{ .compatible = "marvell,armada-xp-pcie", },
|
||||
{ .compatible = "marvell,armada-370-pcie", },
|
||||
{},
|
||||
};
|
||||
|
||||
int mvebu_get_soc_id(u32 *dev, u32 *rev)
|
||||
{
|
||||
if (is_id_valid) {
|
||||
*dev = soc_dev_id;
|
||||
*rev = soc_rev;
|
||||
return 0;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int __init mvebu_soc_id_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
int ret = 0;
|
||||
void __iomem *pci_base;
|
||||
struct clk *clk;
|
||||
struct device_node *child;
|
||||
|
||||
np = of_find_matching_node(NULL, mvebu_pcie_of_match_table);
|
||||
if (!np)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* ID and revision are available from any port, so we
|
||||
* just pick the first one
|
||||
*/
|
||||
child = of_get_next_child(np, NULL);
|
||||
if (child == NULL) {
|
||||
pr_err("cannot get pci node\n");
|
||||
ret = -ENOMEM;
|
||||
goto clk_err;
|
||||
}
|
||||
|
||||
clk = of_clk_get_by_name(child, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("cannot get clock\n");
|
||||
ret = -ENOMEM;
|
||||
goto clk_err;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret) {
|
||||
pr_err("cannot enable clock\n");
|
||||
goto clk_err;
|
||||
}
|
||||
|
||||
pci_base = of_iomap(child, 0);
|
||||
if (IS_ERR(pci_base)) {
|
||||
pr_err("cannot map registers\n");
|
||||
ret = -ENOMEM;
|
||||
goto res_ioremap;
|
||||
}
|
||||
|
||||
/* SoC ID */
|
||||
soc_dev_id = readl(pci_base + PCIE_DEV_ID_OFF) >> 16;
|
||||
|
||||
/* SoC revision */
|
||||
soc_rev = readl(pci_base + PCIE_DEV_REV_OFF) & SOC_REV_MASK;
|
||||
|
||||
is_id_valid = true;
|
||||
|
||||
pr_info("MVEBU SoC ID=0x%X, Rev=0x%X\n", soc_dev_id, soc_rev);
|
||||
|
||||
iounmap(pci_base);
|
||||
|
||||
res_ioremap:
|
||||
clk_disable_unprepare(clk);
|
||||
|
||||
clk_err:
|
||||
of_node_put(child);
|
||||
of_node_put(np);
|
||||
|
||||
return ret;
|
||||
}
|
||||
core_initcall(mvebu_soc_id_init);
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Marvell EBU SoC ID and revision definitions.
|
||||
*
|
||||
* Copyright (C) 2014 Marvell Semiconductor
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_MVEBU_SOC_ID_H
|
||||
#define __LINUX_MVEBU_SOC_ID_H
|
||||
|
||||
/* Armada XP ID */
|
||||
#define MV78230_DEV_ID 0x7823
|
||||
#define MV78260_DEV_ID 0x7826
|
||||
#define MV78460_DEV_ID 0x7846
|
||||
|
||||
/* Armada XP Revision */
|
||||
#define MV78XX0_A0_REV 0x1
|
||||
#define MV78XX0_B0_REV 0x2
|
||||
|
||||
#ifdef CONFIG_ARCH_MVEBU
|
||||
int mvebu_get_soc_id(u32 *dev, u32 *rev);
|
||||
#else
|
||||
static inline int mvebu_get_soc_id(u32 *dev, u32 *rev)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_MVEBU_SOC_ID_H */
|
|
@ -692,6 +692,7 @@ static const struct of_device_id mv64xxx_i2c_of_match_table[] = {
|
|||
{ .compatible = "allwinner,sun4i-i2c", .data = &mv64xxx_i2c_regs_sun4i},
|
||||
{ .compatible = "marvell,mv64xxx-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
|
||||
{ .compatible = "marvell,mv78230-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
|
||||
{ .compatible = "marvell,mv78230-a0-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table);
|
||||
|
@ -783,6 +784,10 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
|
|||
drv_data->errata_delay = true;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(np, "marvell,mv78230-a0-i2c")) {
|
||||
drv_data->offload_enabled = false;
|
||||
drv_data->errata_delay = true;
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue