forked from Minki/linux
ARC updates for 5.3-rc7
- Support for Edge Triggered IRQs in ARC IDU intc - other fixes here and there -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJdZWFxAAoJEGnX8d3iisJe1/QP/1QlB6bDp36ONuc0wgtvyZhS /KDfgwyLK89WiH/lc2AgPL6BkFaOBSqpNe9PS8IdjRscGMJFaXnfifKBl2eX/sM3 4nkiIjAb9Fl4dLdaPs/51p+wvHlkdD9pzI5SYJl2IeNCZRNjjixBlaF8fezONtlu 2yuzmikeggcT7NZGnZ5IQGj6CWRm7Drb5J4mfmZu3HJ+BJOnXZpdza3q3WduT3DC 6tUA/xtUXq8sGpylXL2MgA34SbgjBDmxW8Kv32sQp6mipGJwq4jF4+n8rxF/znCe 6ILiqOwp7CjEHmpYTn2cxMC5FTP0BuvnLh/ECEFKUWgIH4/A3zy/RJOKhbZ0P0rV +vraRvdjOA2/0P6Y1A+cGGYP2c3HwmSgHmtXwd/QRfesX2/Y7jhMlEOXZ9H2K6CC zTqobUWQ4tFprz1P0H6p1h7Z/tJv/q4TNMZR5tcQyjwT6i7Sw+ReffTnwpPMr92V GAZu6sahsJCOqRqk0MfaZVa54r+UlE8bbapGZo+7fZ9+UVrxLKgWwfnYbe/6eSHX osddo3zoLuBrgq2gt/ZMseeQRdRYeH8p/3jgnEws2G/uen7GjAw9m0c3Yrs+ibVS oNp3DNk8wkzgrLgC7xXhBkwyok85SEoCfZoQg96DXo365G0YyHZyHCI2HzIAP4oy wtRcqnsQgEtvV1s7RiTU =CJKr -----END PGP SIGNATURE----- Merge tag 'arc-5.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc Pull ARC updates from Vineet Gupta: - support for Edge Triggered IRQs in ARC IDU intc - other fixes here and there * tag 'arc-5.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc: arc: prefer __section from compiler_attributes.h dt-bindings: IDU-intc: Add support for edge-triggered interrupts dt-bindings: IDU-intc: Clean up documentation ARCv2: IDU-intc: Add support for edge-triggered interrupts ARC: unwind: Mark expected switch fall-throughs ARC: [plat-hsdk]: allow to switch between AXI DMAC port configurations ARC: fix typo in setup_dma_ops log message ARCv2: entry: early return from exception need not clear U & DE bits
This commit is contained in:
commit
6525771f58
@ -1,20 +1,30 @@
|
||||
* ARC-HS Interrupt Distribution Unit
|
||||
|
||||
This optional 2nd level interrupt controller can be used in SMP configurations for
|
||||
dynamic IRQ routing, load balancing of common/external IRQs towards core intc.
|
||||
This optional 2nd level interrupt controller can be used in SMP configurations
|
||||
for dynamic IRQ routing, load balancing of common/external IRQs towards core
|
||||
intc.
|
||||
|
||||
Properties:
|
||||
|
||||
- compatible: "snps,archs-idu-intc"
|
||||
- interrupt-controller: This is an interrupt controller.
|
||||
- #interrupt-cells: Must be <1>.
|
||||
- #interrupt-cells: Must be <1> or <2>.
|
||||
|
||||
Value of the cell specifies the "common" IRQ from peripheral to IDU. Number N
|
||||
of the particular interrupt line of IDU corresponds to the line N+24 of the
|
||||
core interrupt controller.
|
||||
Value of the first cell specifies the "common" IRQ from peripheral to IDU.
|
||||
Number N of the particular interrupt line of IDU corresponds to the line N+24
|
||||
of the core interrupt controller.
|
||||
|
||||
intc accessed via the special ARC AUX register interface, hence "reg" property
|
||||
is not specified.
|
||||
The (optional) second cell specifies any of the following flags:
|
||||
- bits[3:0] trigger type and level flags
|
||||
1 = low-to-high edge triggered
|
||||
2 = NOT SUPPORTED (high-to-low edge triggered)
|
||||
4 = active high level-sensitive <<< DEFAULT
|
||||
8 = NOT SUPPORTED (active low level-sensitive)
|
||||
When no second cell is specified, the interrupt is assumed to be level
|
||||
sensitive.
|
||||
|
||||
The interrupt controller is accessed via the special ARC AUX register
|
||||
interface, hence "reg" property is not specified.
|
||||
|
||||
Example:
|
||||
core_intc: core-interrupt-controller {
|
||||
|
@ -12,3 +12,6 @@ dtb-y := $(builtindtb-y).dtb
|
||||
# for CONFIG_OF_ALL_DTBS test
|
||||
dtstree := $(srctree)/$(src)
|
||||
dtb- := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
|
||||
|
||||
# board-specific dtc flags
|
||||
DTC_FLAGS_hsdk += --pad 20
|
||||
|
@ -256,7 +256,7 @@
|
||||
|
||||
.macro FAKE_RET_FROM_EXCPN
|
||||
lr r9, [status32]
|
||||
bic r9, r9, (STATUS_U_MASK|STATUS_DE_MASK|STATUS_AE_MASK)
|
||||
bic r9, r9, STATUS_AE_MASK
|
||||
or r9, r9, STATUS_IE_MASK
|
||||
kflag r9
|
||||
.endm
|
||||
|
@ -62,15 +62,15 @@
|
||||
#else /* !__ASSEMBLY__ */
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_ICCM
|
||||
#define __arcfp_code __attribute__((__section__(".text.arcfp")))
|
||||
#define __arcfp_code __section(.text.arcfp)
|
||||
#else
|
||||
#define __arcfp_code __attribute__((__section__(".text")))
|
||||
#define __arcfp_code __section(.text)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_DCCM
|
||||
#define __arcfp_data __attribute__((__section__(".data.arcfp")))
|
||||
#define __arcfp_data __section(.data.arcfp)
|
||||
#else
|
||||
#define __arcfp_data __attribute__((__section__(".data")))
|
||||
#define __arcfp_data __section(.data)
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
@ -53,8 +53,7 @@ extern const struct machine_desc __arch_info_begin[], __arch_info_end[];
|
||||
*/
|
||||
#define MACHINE_START(_type, _name) \
|
||||
static const struct machine_desc __mach_desc_##_type \
|
||||
__used \
|
||||
__attribute__((__section__(".arch.info.init"))) = { \
|
||||
__used __section(.arch.info.init) = { \
|
||||
.name = _name,
|
||||
|
||||
#define MACHINE_END \
|
||||
|
@ -202,8 +202,8 @@ static void idu_set_dest(unsigned int cmn_irq, unsigned int cpu_mask)
|
||||
__mcip_cmd_data(CMD_IDU_SET_DEST, cmn_irq, cpu_mask);
|
||||
}
|
||||
|
||||
static void idu_set_mode(unsigned int cmn_irq, unsigned int lvl,
|
||||
unsigned int distr)
|
||||
static void idu_set_mode(unsigned int cmn_irq, bool set_lvl, unsigned int lvl,
|
||||
bool set_distr, unsigned int distr)
|
||||
{
|
||||
union {
|
||||
unsigned int word;
|
||||
@ -212,8 +212,11 @@ static void idu_set_mode(unsigned int cmn_irq, unsigned int lvl,
|
||||
};
|
||||
} data;
|
||||
|
||||
data.distr = distr;
|
||||
data.lvl = lvl;
|
||||
data.word = __mcip_cmd_read(CMD_IDU_READ_MODE, cmn_irq);
|
||||
if (set_distr)
|
||||
data.distr = distr;
|
||||
if (set_lvl)
|
||||
data.lvl = lvl;
|
||||
__mcip_cmd_data(CMD_IDU_SET_MODE, cmn_irq, data.word);
|
||||
}
|
||||
|
||||
@ -240,6 +243,25 @@ static void idu_irq_unmask(struct irq_data *data)
|
||||
raw_spin_unlock_irqrestore(&mcip_lock, flags);
|
||||
}
|
||||
|
||||
static void idu_irq_ack(struct irq_data *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&mcip_lock, flags);
|
||||
__mcip_cmd(CMD_IDU_ACK_CIRQ, data->hwirq);
|
||||
raw_spin_unlock_irqrestore(&mcip_lock, flags);
|
||||
}
|
||||
|
||||
static void idu_irq_mask_ack(struct irq_data *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&mcip_lock, flags);
|
||||
__mcip_cmd_data(CMD_IDU_SET_MASK, data->hwirq, 1);
|
||||
__mcip_cmd(CMD_IDU_ACK_CIRQ, data->hwirq);
|
||||
raw_spin_unlock_irqrestore(&mcip_lock, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
|
||||
bool force)
|
||||
@ -263,13 +285,36 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
|
||||
else
|
||||
distribution_mode = IDU_M_DISTRI_RR;
|
||||
|
||||
idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, distribution_mode);
|
||||
idu_set_mode(data->hwirq, false, 0, true, distribution_mode);
|
||||
|
||||
raw_spin_unlock_irqrestore(&mcip_lock, flags);
|
||||
|
||||
return IRQ_SET_MASK_OK;
|
||||
}
|
||||
|
||||
static int idu_irq_set_type(struct irq_data *data, u32 type)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* ARCv2 IDU HW does not support inverse polarity, so these are the
|
||||
* only interrupt types supported.
|
||||
*/
|
||||
if (type & ~(IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock_irqsave(&mcip_lock, flags);
|
||||
|
||||
idu_set_mode(data->hwirq, true,
|
||||
type & IRQ_TYPE_EDGE_RISING ? IDU_M_TRIG_EDGE :
|
||||
IDU_M_TRIG_LEVEL,
|
||||
false, 0);
|
||||
|
||||
raw_spin_unlock_irqrestore(&mcip_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void idu_irq_enable(struct irq_data *data)
|
||||
{
|
||||
/*
|
||||
@ -289,7 +334,10 @@ static struct irq_chip idu_irq_chip = {
|
||||
.name = "MCIP IDU Intc",
|
||||
.irq_mask = idu_irq_mask,
|
||||
.irq_unmask = idu_irq_unmask,
|
||||
.irq_ack = idu_irq_ack,
|
||||
.irq_mask_ack = idu_irq_mask_ack,
|
||||
.irq_enable = idu_irq_enable,
|
||||
.irq_set_type = idu_irq_set_type,
|
||||
#ifdef CONFIG_SMP
|
||||
.irq_set_affinity = idu_irq_set_affinity,
|
||||
#endif
|
||||
@ -317,7 +365,7 @@ static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops idu_irq_ops = {
|
||||
.xlate = irq_domain_xlate_onecell,
|
||||
.xlate = irq_domain_xlate_onetwocell,
|
||||
.map = idu_irq_map,
|
||||
};
|
||||
|
||||
|
@ -826,7 +826,7 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
|
||||
case DW_CFA_def_cfa:
|
||||
state->cfa.reg = get_uleb128(&ptr.p8, end);
|
||||
unw_debug("cfa_def_cfa: r%lu ", state->cfa.reg);
|
||||
/*nobreak*/
|
||||
/* fall through */
|
||||
case DW_CFA_def_cfa_offset:
|
||||
state->cfa.offs = get_uleb128(&ptr.p8, end);
|
||||
unw_debug("cfa_def_cfa_offset: 0x%lx ",
|
||||
@ -834,7 +834,7 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
|
||||
break;
|
||||
case DW_CFA_def_cfa_sf:
|
||||
state->cfa.reg = get_uleb128(&ptr.p8, end);
|
||||
/*nobreak */
|
||||
/* fall through */
|
||||
case DW_CFA_def_cfa_offset_sf:
|
||||
state->cfa.offs = get_sleb128(&ptr.p8, end)
|
||||
* state->dataAlign;
|
||||
|
@ -101,7 +101,7 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
|
||||
if (is_isa_arcv2() && ioc_enable && coherent)
|
||||
dev->dma_coherent = true;
|
||||
|
||||
dev_info(dev, "use %sncoherent DMA ops\n",
|
||||
dev_info(dev, "use %scoherent DMA ops\n",
|
||||
dev->dma_coherent ? "" : "non");
|
||||
}
|
||||
|
||||
|
@ -6,11 +6,15 @@
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/smp.h>
|
||||
#include <asm/arcregs.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mach_desc.h>
|
||||
|
||||
int arc_hsdk_axi_dmac_coherent __section(.data) = 0;
|
||||
|
||||
#define ARC_CCM_UNUSED_ADDR 0x60000000
|
||||
|
||||
static void __init hsdk_init_per_cpu(unsigned int cpu)
|
||||
@ -97,6 +101,42 @@ static void __init hsdk_enable_gpio_intc_wire(void)
|
||||
iowrite32(GPIO_INT_CONNECTED_MASK, (void __iomem *) GPIO_INTEN);
|
||||
}
|
||||
|
||||
static int __init hsdk_tweak_node_coherency(const char *path, bool coherent)
|
||||
{
|
||||
void *fdt = initial_boot_params;
|
||||
const void *prop;
|
||||
int node, ret;
|
||||
bool dt_coh_set;
|
||||
|
||||
node = fdt_path_offset(fdt, path);
|
||||
if (node < 0)
|
||||
goto tweak_fail;
|
||||
|
||||
prop = fdt_getprop(fdt, node, "dma-coherent", &ret);
|
||||
if (!prop && ret != -FDT_ERR_NOTFOUND)
|
||||
goto tweak_fail;
|
||||
|
||||
dt_coh_set = ret != -FDT_ERR_NOTFOUND;
|
||||
ret = 0;
|
||||
|
||||
/* need to remove "dma-coherent" property */
|
||||
if (dt_coh_set && !coherent)
|
||||
ret = fdt_delprop(fdt, node, "dma-coherent");
|
||||
|
||||
/* need to set "dma-coherent" property */
|
||||
if (!dt_coh_set && coherent)
|
||||
ret = fdt_setprop(fdt, node, "dma-coherent", NULL, 0);
|
||||
|
||||
if (ret < 0)
|
||||
goto tweak_fail;
|
||||
|
||||
return 0;
|
||||
|
||||
tweak_fail:
|
||||
pr_err("failed to tweak %s to %scoherent\n", path, coherent ? "" : "non");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
enum hsdk_axi_masters {
|
||||
M_HS_CORE = 0,
|
||||
M_HS_RTT,
|
||||
@ -162,6 +202,39 @@ enum hsdk_axi_masters {
|
||||
#define CREG_PAE ((void __iomem *)(CREG_BASE + 0x180))
|
||||
#define CREG_PAE_UPDT ((void __iomem *)(CREG_BASE + 0x194))
|
||||
|
||||
static void __init hsdk_init_memory_bridge_axi_dmac(void)
|
||||
{
|
||||
bool coherent = !!arc_hsdk_axi_dmac_coherent;
|
||||
u32 axi_m_slv1, axi_m_oft1;
|
||||
|
||||
/*
|
||||
* Don't tweak memory bridge configuration if we failed to tweak DTB
|
||||
* as we will end up in a inconsistent state.
|
||||
*/
|
||||
if (hsdk_tweak_node_coherency("/soc/dmac@80000", coherent))
|
||||
return;
|
||||
|
||||
if (coherent) {
|
||||
axi_m_slv1 = 0x77999999;
|
||||
axi_m_oft1 = 0x76DCBA98;
|
||||
} else {
|
||||
axi_m_slv1 = 0x77777777;
|
||||
axi_m_oft1 = 0x76543210;
|
||||
}
|
||||
|
||||
writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0));
|
||||
writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0));
|
||||
writel(axi_m_slv1, CREG_AXI_M_SLV1(M_DMAC_0));
|
||||
writel(axi_m_oft1, CREG_AXI_M_OFT1(M_DMAC_0));
|
||||
writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0));
|
||||
|
||||
writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1));
|
||||
writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1));
|
||||
writel(axi_m_slv1, CREG_AXI_M_SLV1(M_DMAC_1));
|
||||
writel(axi_m_oft1, CREG_AXI_M_OFT1(M_DMAC_1));
|
||||
writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1));
|
||||
}
|
||||
|
||||
static void __init hsdk_init_memory_bridge(void)
|
||||
{
|
||||
u32 reg;
|
||||
@ -227,24 +300,14 @@ static void __init hsdk_init_memory_bridge(void)
|
||||
writel(0x76543210, CREG_AXI_M_OFT1(M_GPU));
|
||||
writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_GPU));
|
||||
|
||||
writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0));
|
||||
writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_0));
|
||||
writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0));
|
||||
writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_0));
|
||||
writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0));
|
||||
|
||||
writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1));
|
||||
writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_1));
|
||||
writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1));
|
||||
writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_1));
|
||||
writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1));
|
||||
|
||||
writel(0x00000000, CREG_AXI_M_SLV0(M_DVFS));
|
||||
writel(0x60000000, CREG_AXI_M_SLV1(M_DVFS));
|
||||
writel(0x00000000, CREG_AXI_M_OFT0(M_DVFS));
|
||||
writel(0x00000000, CREG_AXI_M_OFT1(M_DVFS));
|
||||
writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DVFS));
|
||||
|
||||
hsdk_init_memory_bridge_axi_dmac();
|
||||
|
||||
/*
|
||||
* PAE remapping for DMA clients does not work due to an RTL bug, so
|
||||
* CREG_PAE register must be programmed to all zeroes, otherwise it
|
||||
|
@ -46,7 +46,9 @@ struct mcip_cmd {
|
||||
#define CMD_IDU_ENABLE 0x71
|
||||
#define CMD_IDU_DISABLE 0x72
|
||||
#define CMD_IDU_SET_MODE 0x74
|
||||
#define CMD_IDU_READ_MODE 0x75
|
||||
#define CMD_IDU_SET_DEST 0x76
|
||||
#define CMD_IDU_ACK_CIRQ 0x79
|
||||
#define CMD_IDU_SET_MASK 0x7C
|
||||
|
||||
#define IDU_M_TRIG_LEVEL 0x0
|
||||
@ -119,4 +121,13 @@ static inline void __mcip_cmd_data(unsigned int cmd, unsigned int param,
|
||||
__mcip_cmd(cmd, param);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read MCIP register
|
||||
*/
|
||||
static inline unsigned int __mcip_cmd_read(unsigned int cmd, unsigned int param)
|
||||
{
|
||||
__mcip_cmd(cmd, param);
|
||||
return read_aux_reg(ARC_REG_MCIP_READBACK);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user