[PATCH 5/6] ARCv2: IRQ: Use build registers for getting numbers of interrupts

2017-01-27 Thread Yuriy Kolerov
This enhancement allows to mask all available common interrupts
in IDU interrupt controller in boot time since the kernel can
discover a number of them from the build register. Also now there
is no need to specify in device tree a list of used core interrupts
by IDU. E.g. before:

idu_intc: idu-interrupt-controller {
compatible = "snps,archs-idu-intc";
interrupt-controller;
interrupt-parent = <_intc>;
#interrupt-cells = <2>;
interrupts = <24 25 26 27 28 29 30 31>;
};

and after:

idu_intc: idu-interrupt-controller {
compatible = "snps,archs-idu-intc";
interrupt-controller;
interrupt-parent = <_intc>;
#interrupt-cells = <2>;
};

Signed-off-by: Yuriy Kolerov 
---
 arch/arc/include/asm/irq.h   |  3 +++
 arch/arc/kernel/intc-arcv2.c |  7 ++-
 arch/arc/kernel/mcip.c   | 31 +++
 3 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index dfa09e3..1970d78c 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -18,6 +18,9 @@
  */
 #define NR_CPU_IRQS240
 
+/* A fixed number of exceptions which occupy first interrupt lines */
+#define NR_EXCEPTIONS  16
+
 /*
  * ARCv2 can support 240 interrupts in the core interrupts controllers and
  * 128 interrupts in IDU. Thus 512 virtual IRQs must be enough for most
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index a9a7497..b2a6de4 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -123,11 +123,16 @@ static int __init
 init_onchip_IRQ(struct device_node *intc, struct device_node *parent)
 {
struct irq_domain *root_domain;
+   struct bcr_irq_arcv2 irq_bcr;
+   unsigned int nr_cpu_irqs;
+
+   READ_BCR(ARC_REG_IRQ_BCR, irq_bcr);
+   nr_cpu_irqs = irq_bcr.irqs + NR_EXCEPTIONS;
 
if (parent)
panic("DeviceTree incore intc not a root irq controller\n");
 
-   root_domain = irq_domain_add_linear(intc, NR_CPU_IRQS, _irq_ops, 
NULL);
+   root_domain = irq_domain_add_linear(intc, nr_cpu_irqs, _irq_ops, 
NULL);
if (!root_domain)
panic("root irq domain not avail\n");
 
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 9988b42..45d45fc 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -157,15 +157,20 @@ static void idu_set_mode(unsigned int cmn_irq, unsigned 
int lvl,
__mcip_cmd_data(CMD_IDU_SET_MODE, cmn_irq, data.word);
 }
 
-static void idu_irq_mask(struct irq_data *data)
+static void idu_irq_mask_raw(irq_hw_number_t hwirq)
 {
unsigned long flags;
 
raw_spin_lock_irqsave(_lock, flags);
-   __mcip_cmd_data(CMD_IDU_SET_MASK, data->hwirq, 1);
+   __mcip_cmd_data(CMD_IDU_SET_MASK, hwirq, 1);
raw_spin_unlock_irqrestore(_lock, flags);
 }
 
+static void idu_irq_mask(struct irq_data *data)
+{
+   idu_irq_mask_raw(data->hwirq);
+}
+
 static void idu_irq_unmask(struct irq_data *data)
 {
unsigned long flags;
@@ -231,14 +236,12 @@ static struct irq_chip idu_irq_chip = {
 
 };
 
-static irq_hw_number_t idu_first_hwirq;
-
 static void idu_cascade_isr(struct irq_desc *desc)
 {
struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
struct irq_chip *core_chip = irq_desc_get_chip(desc);
irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
-   irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
+   irq_hw_number_t idu_hwirq = core_hwirq - FIRST_EXT_IRQ;
 
chained_irq_enter(core_chip, desc);
generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
@@ -284,33 +287,37 @@ static int __init
 idu_of_init(struct device_node *intc, struct device_node *parent)
 {
struct irq_domain *domain;
-   /* Read IDU BCR to confirm nr_irqs */
-   int nr_irqs = of_irq_count(intc);
+   int nr_irqs;
int i, virq;
struct mcip_bcr mp;
+   struct mcip_idu_bcr idu_bcr;
 
READ_BCR(ARC_REG_MCIP_BCR, mp);
 
if (!mp.idu)
panic("IDU not detected, but DeviceTree using it");
 
-   pr_info("MCIP: IDU referenced from Devicetree %d irqs\n", nr_irqs);
+   READ_BCR(ARC_REG_MCIP_IDU_BCR, idu_bcr);
+   nr_irqs = mcip_idu_bcr_to_nr_irqs(idu_bcr);
+
+   pr_info("MCIP: IDU supports %u common irqs\n", nr_irqs);
 
domain = irq_domain_add_linear(intc, nr_irqs, _irq_ops, NULL);
 
/* Parent interrupts (core-intc) are already mapped */
 
for (i = 0; i < nr_irqs; i++) {
+   /* Mask all common interrupts by default */
+   idu_irq_mask_raw(i);
+
/*
 * Return parent uplink IRQs (towards core intc) 24,25,.
 * this step has been done before already
 * however we need it to get the parent virq and set IDU handler
   

[PATCH 6/6] ARCv2: IRQ: Set a default priority for all core interrupts

2017-01-27 Thread Yuriy Kolerov
After reset all interrupts in the core interrupt controller has
the highest priority P0. If the platform supports Fast IRQs and
has more than 1 banks of registers then CPU automatically switch
banks of registers when P0 interrupt comes.

The problem is that the kernel expects that by default switching
of banks is not used by all interrupts. It is necessary to set a
default nonzero priority for all available interrupts to avoid
undefined behaviour.

Signed-off-by: Yuriy Kolerov 
---
 arch/arc/kernel/intc-arcv2.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index b2a6de4..b9d9ce6 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -22,7 +22,7 @@
  */
 void arc_init_IRQ(void)
 {
-   unsigned int tmp, irq_prio;
+   unsigned int tmp, irq_prio, i;
 
struct bcr_irq_arcv2 irq_bcr;
struct aux_irq_ctrl_arcv2 ictrl;
@@ -51,6 +51,16 @@ void arc_init_IRQ(void)
irq_prio + 1, ARCV2_IRQ_DEF_PRIO,
irq_bcr.firq ? " FIRQ (not used)":"");
 
+   /*
+* Set a default priority for all available interrupts to prevent
+* switching of register banks if Fast IRQ and multiple register banks
+* are supported by CPU.
+*/
+   for (i = NR_EXCEPTIONS; i < irq_bcr.irqs + NR_EXCEPTIONS; i++) {
+   write_aux_reg(AUX_IRQ_SELECT, i);
+   write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO);
+   }
+
/* setup status32, don't enable intr yet as kernel doesn't want */
tmp = read_aux_reg(ARC_REG_STATUS32);
tmp |= STATUS_AD_MASK | (ARCV2_IRQ_DEF_PRIO << 1);
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 3/6] ARCv2: IRQ: Add macro for the first external interrupt number

2017-01-27 Thread Yuriy Kolerov
Signed-off-by: Yuriy Kolerov 
---
 arch/arc/include/asm/irq.h   | 1 +
 arch/arc/kernel/intc-arcv2.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index c0fa0d2..e61ad30 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -16,6 +16,7 @@
 #ifdef CONFIG_ISA_ARCV2
 #define IPI_IRQ19
 #define SOFTIRQ_IRQ21
+#define FIRST_EXT_IRQ  24
 #endif
 
 #include 
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index 2f31bb1..a9a7497 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -98,7 +98,7 @@ static int arcv2_irq_map(struct irq_domain *d, unsigned int 
irq,
 * core intc IRQs [16, 23]:
 * Statically assigned always private-per-core (Timers, WDT, IPI, PCT)
 */
-   if (hw < 24) {
+   if (hw < FIRST_EXT_IRQ) {
/*
 * A subsequent request_percpu_irq() fails if percpu_devid is
 * not set. That in turns sets NOAUTOEN, meaning each core needs
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 2/6] ARCv2: MCIP: Add structure for build register of IDU

2017-01-27 Thread Yuriy Kolerov
This structure is necessary for retrieving of supported
number of common interrupts in IDU interrupt controller.

Signed-off-by: Yuriy Kolerov 
---
 include/soc/arc/mcip.h | 17 +
 1 file changed, 17 insertions(+)

diff --git a/include/soc/arc/mcip.h b/include/soc/arc/mcip.h
index 6902c2a..798c01b 100644
--- a/include/soc/arc/mcip.h
+++ b/include/soc/arc/mcip.h
@@ -14,6 +14,7 @@
 #include 
 
 #define ARC_REG_MCIP_BCR   0x0d0
+#define ARC_REG_MCIP_IDU_BCR   0x0D5
 #define ARC_REG_MCIP_CMD   0x600
 #define ARC_REG_MCIP_WDATA 0x601
 #define ARC_REG_MCIP_READBACK  0x602
@@ -69,6 +70,22 @@ struct mcip_bcr {
 #endif
 };
 
+struct mcip_idu_bcr {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+   unsigned int pad:21, cirqnum:3, ver:8;
+#else
+   unsigned int ver:8, cirqnum:3, pad:21;
+#endif
+};
+
+
+/*
+ * Build register for IDU contains not an actual number of supported common
+ * interrupts but an exponent of 2 which must be multiplied by 4 to
+ * get a number of supported common interrupts.
+ */
+#define mcip_idu_bcr_to_nr_irqs(bcr) (4 * (1 << (bcr).cirqnum))
+
 /*
  * MCIP programming model
  *
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 4/6] ARCv2: IRQ: Remove option for setting number of interrupts

2017-01-27 Thread Yuriy Kolerov
When you set a value of ARC_NUMBER_OF_INTERRUPTS option
it affects only a size of the interrupts table but macros
for number of virtual interrupts (NR_IRQS) and for number
of hardware interrupts (NR_CPU_IRQS) remain unchanged.
Moreover usage of ARC_NUMBER_OF_INTERRUPTS is bad for
portability since it is not possible to change size
of the interrupts table after linkage.

This patch makes these changes in IRQ subsystem:

  * NR_CPU_IRQS defines a maximum number of hardware interrupts.
  * Remove ARC_NUMBER_OF_INTERRUPTS option and create interrupts
table for all possible hardware interrupts.
  * Increase a maximum number of virtual IRQs to 512. ARCv2 can
support 240 interrupts in the core interrupts controllers
and 128 interrupts in IDU. Thus 512 virtual IRQs must be
enough for most configurations of boards.

Signed-off-by: Yuriy Kolerov 
---
 arch/arc/Kconfig  | 11 ---
 arch/arc/include/asm/irq.h| 28 +---
 arch/arc/kernel/entry-arcv2.S |  3 ++-
 3 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 283099c..ba15cb8 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -412,17 +412,6 @@ config ARC_HAS_DIV_REM
bool "Insn: div, divu, rem, remu"
default y
 
-config ARC_NUMBER_OF_INTERRUPTS
-   int "Number of interrupts"
-   range 8 240
-   default 32
-   help
- This defines the number of interrupts on the ARCv2HS core.
- It affects the size of vector table.
- The initial 8 IRQs are fixed (Timer, ICI etc) and although 
configurable
- in hardware, it keep things simple for Linux to assume they are always
- present.
-
 endif  # ISA_ARCV2
 
 endmenu   # "ARC CPU Configuration"
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index e61ad30..dfa09e3 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -9,19 +9,41 @@
 #ifndef __ASM_ARC_IRQ_H
 #define __ASM_ARC_IRQ_H
 
-#define NR_CPU_IRQS32  /* number of interrupt lines of ARC770 CPU */
-#define NR_IRQS128 /* allow some CPU external IRQ handling */
+#ifdef CONFIG_ISA_ARCV2
+
+/*
+ * A maximum number of supported interrupts in the core interrupt controller.
+ * This number is not equal to the maximum interrupt number (256) because
+ * first 16 lines are reserved for exceptions and are not configurable.
+ */
+#define NR_CPU_IRQS240
+
+/*
+ * ARCv2 can support 240 interrupts in the core interrupts controllers and
+ * 128 interrupts in IDU. Thus 512 virtual IRQs must be enough for most
+ * configurations of boards.
+ */
+#define NR_IRQS512
 
 /* Platform Independent IRQs */
-#ifdef CONFIG_ISA_ARCV2
 #define IPI_IRQ19
 #define SOFTIRQ_IRQ21
 #define FIRST_EXT_IRQ  24
+
+#else
+
+#define NR_CPU_IRQS32  /* number of interrupt lines of ARC770 CPU */
+#define NR_IRQS128 /* allow some CPU external IRQ handling */
+
 #endif
 
+#ifndef __ASSEMBLY__
+
 #include 
 #include 
 
 extern void arc_init_IRQ(void);
 
 #endif
+
+#endif
diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S
index 0b6388a..f22101e 100644
--- a/arch/arc/kernel/entry-arcv2.S
+++ b/arch/arc/kernel/entry-arcv2.S
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
.cpu HS
 
@@ -52,7 +53,7 @@ VECTORhandle_interrupt; unused
 VECTOR handle_interrupt; (23) unused
 # End of fixed IRQs
 
-.rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8
+.rept NR_CPU_IRQS - 8
VECTOR  handle_interrupt
 .endr
 
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


Re: stmmac: GMAC_RGSMIIIS reports bogus values

2017-01-27 Thread Alexey Brodkin
Hi Giuseppe,

On Wed, 2017-01-25 at 21:39 +0300, Alexey Brodkin wrote:
> Hi Giuseppe,
> 
> On Mon, 2016-11-14 at 09:14 +0100, Giuseppe CAVALLARO wrote:
> > 
> > Hello Alexey
> > 
> > Sorry for my late reply. In that case, I think that the stmmac
> > is using own RGMII/SGMII support (PCS) to dialog with the
> > transceiver. I think, from the HW capability register
> > this feature is present and the driver is using it as default.
> 
> Yep looks like that.

Hm, so I took a look at what am I reading from
"Register 22 (HW Feature Register)" in dwmac1000_get_hw_feature()
and was really surprised to see the register value = 0x100509bf.

See bit 6 "PCSSEL" is zeroed which stands for
"PCS registers (TBI, SGMII, or RTBI PHY interface)".

I.e. PCS doesn't exist in our GMAC so most of the previous comments
below should be discarded.

> > I kindly ask you to verify if this is your setup or if you
> > do not want to use it. In that case, it is likely we need to
> > add some code in the driver.
> 
> Well GMAC's databook says:
> --->8--
> The DWC_gmac provides an IEEE 802.3z compliant 10-bit
> Physical Coding Sublayer (PCS) interface that you can use
> when the MAC is configured for the TBI, RTBI, or SGMII PHY
> interface.
> 
> ...
> 
> You can include the optional PCS module in the DWC_gmac by
> selecting the TBI, RTBI, or SGMII interface in coreConsultant
> during configuration.
> --->8--
> 
> But we use RGMII for communication with the PHY.
> And from the quote above I would conclude that for RGMII we should
> have PCS excluded from GMAC.
> 
> I just sent email to GMAC developers here in Synopsys and
> hopefully will get some clarifications from them soon.
> 
> Probably correct solution is as simple as:
> --->8--
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index a276a32d57f2..f4b67dc7d530 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -803,13 +803,7 @@ static void stmmac_check_pcs_mode(struct stmmac_priv 
> *priv)
> int interface = priv->plat->interface;
>  
> if (priv->dma_cap.pcs) {
> -   if ((interface == PHY_INTERFACE_MODE_RGMII) ||
> -   (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
> -   (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
> -   (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
> -   netdev_dbg(priv->dev, "PCS RGMII support enabled\n");
> -   priv->hw->pcs = STMMAC_PCS_RGMII;
> -   } else if (interface == PHY_INTERFACE_MODE_SGMII) {
> +   if (interface == PHY_INTERFACE_MODE_SGMII) {
> netdev_dbg(priv->dev, "PCS SGMII support enabled\n");
> priv->hw->pcs = STMMAC_PCS_SGMII;
> }
> --->8--
> 
> > 
> > Also I wonder if, other version of the stmmac worked on this platform
> > before.
> 
> It did work and still works. The only problem is we're getting
> a lot of noise now about bogus link status change. That's because
> this info is now in pr_info() compared to being previously in pr_debug().

So it all really boils down to the following problem:
Link state reported via "Register 54 (SGMII/RGMII/SMII Control and Status 
Register)"
doesn't match status read via MDIO from the PHY.

That's why my initial proposal was to ignore whatever we read from this register
if we have MDIO bus instantiated already.

-Alexey

___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc