* [PATCH] drivers: bus: omap_interconnect: Fix rand-config build warning
From: Lokesh Vutla @ 2012-10-29 7:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <508A2F28.3020204@ti.com>
Hi Tony,
On Friday 26 October 2012 12:05 PM, Santosh Shilimkar wrote:
> On Friday 26 October 2012 12:45 AM, Tony Lindgren wrote:
>> * Santosh Shilimkar <santosh.shilimkar@ti.com> [121024 23:34]:
>>> On Thursday 25 October 2012 06:12 AM, Tony Lindgren wrote:
>>>> * Tony Lindgren <tony@atomide.com> [121024 17:36]:
>>>>> * Santosh Shilimkar <santosh.shilimkar@ti.com> [121017 06:35]:
>>>>>> (Looping Arnd and Olof)
>>>>>>
>>>>>> On Wednesday 17 October 2012 06:58 PM, Lokesh Vutla wrote:
>>>>>>> When building omap_l3_noc/smx drivers as modules, the following
>>>>>>> warning appears:
>>>>>>>
>>>>>>> CC [M] drivers/bus/omap_l3_smx.o
>>>>>>> drivers/bus/omap_l3_smx.c:291: warning: data definition has no
>>>>>>> type or storage class
>>>>>>> drivers/bus/omap_l3_smx.c:291: warning: type defaults to 'int' in
>>>>>>> declaration of 'postcore_initcall_sync'
>>>>>>> drivers/bus/omap_l3_smx.c:291: warning: parameter names (without
>>>>>>> types) in function declaration
>>>>>>> drivers/bus/omap_l3_smx.c:287: warning: 'omap3_l3_init' defined
>>>>>>> but not used
>>>>>>> CC [M] drivers/bus/omap_l3_noc.o
>>>>>>> drivers/bus/omap_l3_noc.c:260: warning: data definition has no
>>>>>>> type or storage class
>>>>>>> drivers/bus/omap_l3_noc.c:260: warning: type defaults to 'int' in
>>>>>>> declaration of 'arch_initcall_sync'
>>>>>>> drivers/bus/omap_l3_noc.c:260: warning: parameter names (without
>>>>>>> types) in function declaration
>>>>>>> drivers/bus/omap_l3_noc.c:256: warning: 'omap4_l3_init' defined
>>>>>>> but not used
>>>>>>>
>>>>>>> Adding module_init() and macros in omap_l3_noc/smx drivers when
>>>>>>> building
>>>>>>> as modules to remove the above warning.
>>>>>>>
>>>>>>> Reported-by: Tony Lindgren <tony@atomide.com>
>>>>>>> Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
>>>>>>> ---
>>>>>> Thanks for the fix Lokesh. Looks fine to me.
>>>>>>
>>>>>> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>>
>>>>> Looks like nobody else has picked this up so I'll queue this along
>>>>> with few other omap warnings and regressions.
>>>>
>>>> Hmm actually this might require some more discussion. If we make
>>>> it use regular initcalls, then the ugly ifdefs can be left
>>>> out. Is there a reason to init this early, can't we just use regular
>>>> initcalls?
>>>>
>>> I thought about it. The whole reason we want interconnect errors
>>> enabled early in the boot to avoid bad accesses issued on
>>> interconnect
>>> in early boot by various init codes. We managed to discovered many
>>> init sequence issues where the a driver is trying to access registers
>>> when clocks are not active, or drivers are using bad mapping. At times
>>> these errors gets un-noticed because of the behavior of interconnect
>>> and later causes serious issues. Leaving the driver init late in the
>>> boot means we can't catch any of the issues happen till the L3 driver
>>> init happens.
>>
>> OK yeah that makes sense. How about let's just make it
>> just postcore_initcall instead of postcore_initcall_sync?
>>
> _sync was added by purpose since the driver has depedency on
> the hwmod initialisation which is postcore_initcall. Without
> the sync, we open the race condition and the l3 driver
> registration will fail.
>
>> In include/linux/module.h we have:
>>
>> ...
>> #else /* MODULE */
>>
>> /* Don't use these in loadable modules, but some people do... */
>> #define early_initcall(fn) module_init(fn)
>> #define core_initcall(fn) module_init(fn)
>> #define postcore_initcall(fn) module_init(fn)
>> ...
>>
>> While the postcore_initcall_sync does not have those.
>>
>> No idea what the current plan is, but I sort of remember reading
>> that the _sync versions are going away at some point anyways?
>>
> I have no idea either. As mentioned sync was added to avoid the
> race. If and when _sync is removed, something should come as an
> alternative to avoid initcall completion dependencies for the one
> which falls in same group.
Is the above discussion fine for you ?
Will you pick this patch or
you want any more modifications ?
Thanks
Lokesh
>
> Regards,
> Santosh
>
>
^ permalink raw reply
* [PATCH 0/2] ARM: tegra: add speedo identification for T20/T30
From: Danny Huang @ 2012-10-29 7:21 UTC (permalink / raw)
To: linux-arm-kernel
This patch series adds speedo identification functionality for tegra
T20 and T30. It reads speedo value from fuse and chooses CPU and core
process ID by checking speedo corner tables.
Danny Huang (2):
ARM: tegra: Add speedo-based process identification
ARM: tegra: T30 speedo-based identification
arch/arm/mach-tegra/Makefile | 2 +
arch/arm/mach-tegra/fuse.c | 35 +++--
arch/arm/mach-tegra/fuse.h | 16 ++
arch/arm/mach-tegra/tegra20_speedo.c | 102 ++++++++++++
arch/arm/mach-tegra/tegra30_speedo.c | 290 +++++++++++++++++++++++++++++++++++
5 files changed, 433 insertions(+), 12 deletions(-)
create mode 100644 arch/arm/mach-tegra/tegra20_speedo.c
create mode 100644 arch/arm/mach-tegra/tegra30_speedo.c
--
1.8.0
^ permalink raw reply
* [PATCH 1/2] ARM: tegra: Add speedo-based process identification
From: Danny Huang @ 2012-10-29 7:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351495315-3282-1-git-send-email-dahuang@nvidia.com>
Detect CPU and core process ID by checking speedo corner tables.
This can provide a more accurate process ID.
Signed-off-by: Danny Huang <dahuang@nvidia.com>
---
arch/arm/mach-tegra/Makefile | 1 +
arch/arm/mach-tegra/fuse.c | 13 ++---
arch/arm/mach-tegra/fuse.h | 8 +++
arch/arm/mach-tegra/tegra20_speedo.c | 102 +++++++++++++++++++++++++++++++++++
4 files changed, 116 insertions(+), 8 deletions(-)
create mode 100644 arch/arm/mach-tegra/tegra20_speedo.c
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 9aa653b..7ab6092 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_CPU_IDLE) += sleep.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks_data.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += sleep-t20.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks_data.o
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index 0b7db17..b28e6d2 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -35,6 +35,7 @@ int tegra_sku_id;
int tegra_cpu_process_id;
int tegra_core_process_id;
int tegra_chip_id;
+int tegra_soc_speedo_id;
enum tegra_revision tegra_revision;
/* The BCT to use at boot is specified by board straps that can be read
@@ -62,7 +63,7 @@ static inline u32 tegra_fuse_readl(unsigned long offset)
return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
}
-static inline bool get_spare_fuse(int bit)
+unsigned int tegra_spare_fuse(int bit)
{
return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
}
@@ -78,7 +79,7 @@ static enum tegra_revision tegra_get_revision(u32 id)
return TEGRA_REVISION_A02;
case 3:
if (tegra_chip_id == TEGRA20 &&
- (get_spare_fuse(18) || get_spare_fuse(19)))
+ (tegra_spare_fuse(18) || tegra_spare_fuse(19)))
return TEGRA_REVISION_A03p;
else
return TEGRA_REVISION_A03;
@@ -100,12 +101,6 @@ void tegra_init_fuse(void)
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;
@@ -114,6 +109,8 @@ void tegra_init_fuse(void)
tegra_revision = tegra_get_revision(id);
+ tegra20_init_speedo_data();
+
pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
tegra_revision_name[tegra_revision],
tegra_sku_id, tegra_cpu_process_id,
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
index d2107b2..f1cafb9 100644
--- a/arch/arm/mach-tegra/fuse.h
+++ b/arch/arm/mach-tegra/fuse.h
@@ -42,11 +42,19 @@ extern int tegra_sku_id;
extern int tegra_cpu_process_id;
extern int tegra_core_process_id;
extern int tegra_chip_id;
+extern int tegra_soc_speedo_id;
extern enum tegra_revision tegra_revision;
extern int tegra_bct_strapping;
unsigned long long tegra_chip_uid(void);
void tegra_init_fuse(void);
+unsigned int tegra_spare_fuse(int bit);
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+void tegra20_init_speedo_data(void);
+#else
+static inline void tegra20_init_speedo_data(void) {}
+#endif
#endif
diff --git a/arch/arm/mach-tegra/tegra20_speedo.c b/arch/arm/mach-tegra/tegra20_speedo.c
new file mode 100644
index 0000000..b9202ea
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra20_speedo.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+
+#include "fuse.h"
+
+#define CPU_SPEEDO_LSBIT 20
+#define CPU_SPEEDO_MSBIT 29
+#define CPU_SPEEDO_REDUND_LSBIT 30
+#define CPU_SPEEDO_REDUND_MSBIT 39
+#define CPU_SPEEDO_REDUND_OFFS (CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT)
+
+#define CORE_SPEEDO_LSBIT 40
+#define CORE_SPEEDO_MSBIT 47
+#define CORE_SPEEDO_REDUND_LSBIT 48
+#define CORE_SPEEDO_REDUND_MSBIT 55
+#define CORE_SPEEDO_REDUND_OFFS (CORE_SPEEDO_REDUND_MSBIT - CORE_SPEEDO_MSBIT)
+
+#define SPEEDO_MULT 4
+
+#define PROCESS_CORNERS_NUM 4
+
+#define SPEEDO_ID_SELECT_0(rev) ((rev) <= 2)
+#define SPEEDO_ID_SELECT_1(sku) \
+ (((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \
+ ((sku) != 27) && ((sku) != 28))
+
+static const u32 cpu_process_speedos[][PROCESS_CORNERS_NUM] = {
+ {315, 366, 420, UINT_MAX},
+ {303, 368, 419, UINT_MAX},
+ {316, 331, 383, UINT_MAX},
+};
+
+static const u32 core_process_speedos[][PROCESS_CORNERS_NUM] = {
+ {165, 195, 224, UINT_MAX},
+ {165, 195, 224, UINT_MAX},
+ {165, 195, 224, UINT_MAX},
+};
+
+void tegra20_init_speedo_data(void)
+{
+ u32 reg;
+ u32 val;
+ int i;
+
+ if (SPEEDO_ID_SELECT_0(tegra_revision))
+ tegra_soc_speedo_id = 0;
+ else if (SPEEDO_ID_SELECT_1(tegra_sku_id))
+ tegra_soc_speedo_id = 1;
+ else
+ tegra_soc_speedo_id = 2;
+
+ WARN_ON(tegra_soc_speedo_id >= ARRAY_SIZE(cpu_process_speedos));
+ WARN_ON(tegra_soc_speedo_id >= ARRAY_SIZE(core_process_speedos));
+
+ val = 0;
+ for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) {
+ reg = tegra_spare_fuse(i) |
+ tegra_spare_fuse(i + CPU_SPEEDO_REDUND_OFFS);
+ val = (val << 1) | (reg & 0x1);
+ }
+ val = val * SPEEDO_MULT;
+ pr_debug("%s CPU speedo value %u\n", __func__, val);
+
+ for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
+ if (val <= cpu_process_speedos[tegra_soc_speedo_id][i])
+ break;
+ }
+ tegra_cpu_process_id = i;
+
+ val = 0;
+ for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) {
+ reg = tegra_spare_fuse(i) |
+ tegra_spare_fuse(i + CORE_SPEEDO_REDUND_OFFS);
+ val = (val << 1) | (reg & 0x1);
+ }
+ val = val * SPEEDO_MULT;
+ pr_debug("%s Core speedo value %u\n", __func__, val);
+
+ for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
+ if (val <= core_process_speedos[tegra_soc_speedo_id][i])
+ break;
+ }
+ tegra_core_process_id = i;
+
+ pr_info("Tegra2 Soc Speedo ID %d", tegra_soc_speedo_id);
+}
--
1.8.0
^ permalink raw reply related
* [PATCH 2/2] ARM: tegra: T30 speedo-based identification
From: Danny Huang @ 2012-10-29 7:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351495315-3282-1-git-send-email-dahuang@nvidia.com>
This patch adds speedo-based identification support for T30.
Signed-off-by: Danny Huang <dahuang@nvidia.com>
---
arch/arm/mach-tegra/Makefile | 1 +
arch/arm/mach-tegra/fuse.c | 26 +++-
arch/arm/mach-tegra/fuse.h | 8 +
arch/arm/mach-tegra/tegra30_speedo.c | 290 +++++++++++++++++++++++++++++++++++
4 files changed, 319 insertions(+), 6 deletions(-)
create mode 100644 arch/arm/mach-tegra/tegra30_speedo.c
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 7ab6092..fae982a 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += sleep-t20.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks_data.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_speedo.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += sleep-t30.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_SMP) += reset.o
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index b28e6d2..03e697a 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -29,12 +29,17 @@
#define FUSE_UID_LOW 0x108
#define FUSE_UID_HIGH 0x10c
#define FUSE_SKU_INFO 0x110
-#define FUSE_SPARE_BIT 0x200
+
+#define TEGRA20_FUSE_SPARE_BIT 0x200
+#define TEGRA30_FUSE_SPARE_BIT 0x244
+
+static int tegra_fuse_spare_bit;
int tegra_sku_id;
int tegra_cpu_process_id;
int tegra_core_process_id;
int tegra_chip_id;
+int tegra_cpu_speedo_id;
int tegra_soc_speedo_id;
enum tegra_revision tegra_revision;
@@ -58,14 +63,14 @@ static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
[TEGRA_REVISION_A04] = "A04",
};
-static inline u32 tegra_fuse_readl(unsigned long offset)
+u32 tegra_fuse_readl(unsigned long offset)
{
return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
}
unsigned int tegra_spare_fuse(int bit)
{
- return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
+ return tegra_fuse_readl(tegra_fuse_spare_bit + bit * 4);
}
static enum tegra_revision tegra_get_revision(u32 id)
@@ -107,9 +112,18 @@ void tegra_init_fuse(void)
id = readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804);
tegra_chip_id = (id >> 8) & 0xff;
- tegra_revision = tegra_get_revision(id);
-
- tegra20_init_speedo_data();
+ switch (tegra_chip_id) {
+ case TEGRA20:
+ tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
+ tegra_revision = tegra_get_revision(id);
+ tegra20_init_speedo_data();
+ break;
+ case TEGRA30:
+ tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT;
+ tegra_revision = tegra_get_revision(id);
+ tegra30_init_speedo_data();
+ break;
+ }
pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
tegra_revision_name[tegra_revision],
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
index f1cafb9..544769c 100644
--- a/arch/arm/mach-tegra/fuse.h
+++ b/arch/arm/mach-tegra/fuse.h
@@ -42,6 +42,7 @@ extern int tegra_sku_id;
extern int tegra_cpu_process_id;
extern int tegra_core_process_id;
extern int tegra_chip_id;
+extern int tegra_cpu_speedo_id;
extern int tegra_soc_speedo_id;
extern enum tegra_revision tegra_revision;
@@ -50,6 +51,7 @@ extern int tegra_bct_strapping;
unsigned long long tegra_chip_uid(void);
void tegra_init_fuse(void);
unsigned int tegra_spare_fuse(int bit);
+u32 tegra_fuse_readl(unsigned long offset);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
void tegra20_init_speedo_data(void);
@@ -57,4 +59,10 @@ void tegra20_init_speedo_data(void);
static inline void tegra20_init_speedo_data(void) {}
#endif
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+void tegra30_init_speedo_data(void);
+#else
+static inline void tegra30_init_speedo_data(void) {}
+#endif
+
#endif
diff --git a/arch/arm/mach-tegra/tegra30_speedo.c b/arch/arm/mach-tegra/tegra30_speedo.c
new file mode 100644
index 0000000..d3f4885
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra30_speedo.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+
+#include "fuse.h"
+
+#define CORE_PROCESS_CORNERS_NUM 1
+#define CPU_PROCESS_CORNERS_NUM 6
+
+#define FUSE_SPEEDO_CALIB_0 0x114
+#define FUSE_PACKAGE_INFO 0X1FC
+#define FUSE_TEST_PROG_VER 0X128
+
+#define G_SPEEDO_BIT_MINUS1 58
+#define G_SPEEDO_BIT_MINUS1_R 59
+#define G_SPEEDO_BIT_MINUS2 60
+#define G_SPEEDO_BIT_MINUS2_R 61
+#define LP_SPEEDO_BIT_MINUS1 62
+#define LP_SPEEDO_BIT_MINUS1_R 63
+#define LP_SPEEDO_BIT_MINUS2 64
+#define LP_SPEEDO_BIT_MINUS2_R 65
+
+static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
+ {180},
+ {170},
+ {195},
+ {180},
+ {168},
+ {192},
+ {180},
+ {170},
+ {195},
+ {180},
+ {180},
+ {180},
+};
+
+static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
+ {306, 338, 360, 376, UINT_MAX},
+ {295, 336, 358, 375, UINT_MAX},
+ {325, 325, 358, 375, UINT_MAX},
+ {325, 325, 358, 375, UINT_MAX},
+ {292, 324, 348, 364, UINT_MAX},
+ {324, 324, 348, 364, UINT_MAX},
+ {324, 324, 348, 364, UINT_MAX},
+ {295, 336, 358, 375, UINT_MAX},
+ {358, 358, 358, 358, 397, UINT_MAX},
+ {364, 364, 364, 364, 397, UINT_MAX},
+ {295, 336, 358, 375, 391, UINT_MAX},
+ {295, 336, 358, 375, 391, UINT_MAX},
+};
+
+static int threshold_index;
+static int package_id;
+
+static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
+{
+ u32 reg;
+ int ate_ver;
+ int bit_minus1;
+ int bit_minus2;
+
+ WARN_ON(!speedo_g || !speedo_lp);
+ reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
+
+ *speedo_lp = (reg & 0xFFFF) * 4;
+ *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
+
+ ate_ver = tegra_fuse_readl(FUSE_TEST_PROG_VER);
+ pr_info("%s: ATE prog ver %d.%d\n", __func__, ate_ver/10, ate_ver%10);
+
+ if (ate_ver >= 26) {
+ bit_minus1 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1) & 0x1;
+ bit_minus1 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1_R) & 0x1;
+ bit_minus2 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2) & 0x1;
+ bit_minus2 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2_R) & 0x1;
+ *speedo_lp |= (bit_minus1 << 1) | bit_minus2;
+
+ bit_minus1 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS1) & 0x1;
+ bit_minus1 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS1_R) & 0x1;
+ bit_minus2 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS2) & 0x1;
+ bit_minus2 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS2_R) & 0x1;
+ *speedo_g |= (bit_minus1 << 1) | bit_minus2;
+ } else {
+ *speedo_lp |= 0x3;
+ *speedo_g |= 0x3;
+ }
+}
+
+static void rev_sku_to_speedo_ids(int rev, int sku)
+{
+ switch (rev) {
+ case TEGRA_REVISION_A01:
+ tegra_cpu_speedo_id = 0;
+ tegra_soc_speedo_id = 0;
+ threshold_index = 0;
+ break;
+ case TEGRA_REVISION_A02:
+ case TEGRA_REVISION_A03:
+ switch (sku) {
+ case 0x87:
+ case 0x82:
+ tegra_cpu_speedo_id = 1;
+ tegra_soc_speedo_id = 1;
+ threshold_index = 1;
+ break;
+ case 0x81:
+ switch (package_id) {
+ case 1:
+ tegra_cpu_speedo_id = 2;
+ tegra_soc_speedo_id = 2;
+ threshold_index = 2;
+ break;
+ case 2:
+ tegra_cpu_speedo_id = 4;
+ tegra_soc_speedo_id = 1;
+ threshold_index = 7;
+ break;
+ default:
+ pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
+ package_id);
+ BUG();
+ break;
+ }
+ break;
+ case 0x80:
+ switch (package_id) {
+ case 1:
+ tegra_cpu_speedo_id = 5;
+ tegra_soc_speedo_id = 2;
+ threshold_index = 8;
+ break;
+ case 2:
+ tegra_cpu_speedo_id = 6;
+ tegra_soc_speedo_id = 2;
+ threshold_index = 9;
+ break;
+ default:
+ pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
+ package_id);
+ BUG();
+ break;
+ }
+ break;
+ case 0x83:
+ switch (package_id) {
+ case 1:
+ tegra_cpu_speedo_id = 7;
+ tegra_soc_speedo_id = 1;
+ threshold_index = 10;
+ break;
+ case 2:
+ tegra_cpu_speedo_id = 3;
+ tegra_soc_speedo_id = 2;
+ threshold_index = 3;
+ break;
+ default:
+ pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
+ package_id);
+ BUG();
+ break;
+ }
+ break;
+ case 0x8F:
+ tegra_cpu_speedo_id = 8;
+ tegra_soc_speedo_id = 1;
+ threshold_index = 11;
+ break;
+ case 0x08:
+ tegra_cpu_speedo_id = 1;
+ tegra_soc_speedo_id = 1;
+ threshold_index = 4;
+ break;
+ case 0x02:
+ tegra_cpu_speedo_id = 2;
+ tegra_soc_speedo_id = 2;
+ threshold_index = 5;
+ break;
+ case 0x04:
+ tegra_cpu_speedo_id = 3;
+ tegra_soc_speedo_id = 2;
+ threshold_index = 6;
+ break;
+ case 0:
+ pr_info("Tegra3 ENG SKU: Checking package_id\n");
+ switch (package_id) {
+ case 1:
+ tegra_cpu_speedo_id = 2;
+ tegra_soc_speedo_id = 2;
+ threshold_index = 2;
+ break;
+ case 2:
+ tegra_cpu_speedo_id = 3;
+ tegra_soc_speedo_id = 2;
+ threshold_index = 3;
+ break;
+ default:
+ pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
+ package_id);
+ BUG();
+ break;
+ }
+ break;
+ default:
+ pr_err("Tegra3: Unknown SKU %d\n", sku);
+ tegra_cpu_speedo_id = 0;
+ tegra_soc_speedo_id = 0;
+ threshold_index = 0;
+ break;
+ }
+ break;
+ default:
+ BUG();
+ break;
+ }
+}
+
+void tegra30_init_speedo_data(void)
+{
+ u32 cpu_speedo_val;
+ u32 core_speedo_val;
+ int i;
+
+ package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
+
+ WARN_ON(ARRAY_SIZE(cpu_process_speedos) !=
+ ARRAY_SIZE(core_process_speedos));
+
+ rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id);
+ WARN_ON(threshold_index >= ARRAY_SIZE(cpu_process_speedos));
+
+ fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
+ pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val);
+ pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val);
+
+ for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) {
+ if (cpu_speedo_val <
+ cpu_process_speedos[threshold_index][i]) {
+ break;
+ }
+ }
+ tegra_cpu_process_id = i - 1;
+
+ if (tegra_cpu_process_id == -1) {
+ pr_err("****************************************************");
+ pr_err("****************************************************");
+ pr_err("* tegra3_speedo: CPU speedo value %3d out of range *",
+ cpu_speedo_val);
+ pr_err("****************************************************");
+ pr_err("****************************************************");
+
+ tegra_cpu_speedo_id = 1;
+ }
+
+ for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) {
+ if (core_speedo_val <
+ core_process_speedos[threshold_index][i]) {
+ break;
+ }
+ }
+ tegra_core_process_id = i - 1;
+
+ if (tegra_core_process_id == -1) {
+ pr_err("****************************************************");
+ pr_err("****************************************************");
+ pr_err("* tegra3_speedo: CORE speedo value %3d out of range *",
+ core_speedo_val);
+ pr_err("****************************************************");
+ pr_err("****************************************************");
+
+ tegra_soc_speedo_id = 1;
+ }
+ pr_info("Tegra3: CPU Speedo ID %d, Soc Speedo ID %d",
+ tegra_cpu_speedo_id, tegra_soc_speedo_id);
+}
--
1.8.0
^ permalink raw reply related
* [PATCH v4 0/5] zynq subarch cleanups
From: Michal Simek @ 2012-10-29 7:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1351466765.git.josh.cartwright@ni.com>
Hi Josh,
Michal-
>
> Here is a v5 of the zynq cleanup patchset that addresses your feedback. I've
> intentionally left patches 4 and 5 in the set until we figure out the appropriate
> way to get them in tree (feel free to just apply 1-3)
I am ok to pick just several patches from your patchset. But this is no definitely
good working style. Not expert for submission process but I think that
if there is one broken patch maintainer shouldn't apply it.
Can someone else check this?
> I've also moved the uart mapping in patch 5 to a known working address, until
> we can work out what is happening there. This should allow this patchset to be
> applied and have the zc702 boot.
Will look at it and apply if works.
> You had suggested removing/renaming the zynq-ep107.dts; it wasn't clear
> whether you had wanted that in this patchset or not. I'm going to assume not.
> I'll follow up with this, after this patchset is applied, if that works for you.
Not in this patchset. Sure feel free to send it.
Thanks,
Michal
^ permalink raw reply
* Fwd: [PATCH 2/5] ARM: OMAP3+: hwmod: Add AM33XX HWMOD data for davinci_mdio
From: Richard Cochran @ 2012-10-29 7:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <79CD15C6BA57404B839C016229A409A83EB500C9@DBDE01.ent.ti.com>
On Mon, Oct 29, 2012 at 04:58:23AM +0000, Hiremath, Vaibhav wrote:
>
> Now the expectation has grown to the level where people expect everything in
> the Mainline kernel and not in some custom kernel release.
You are right, except for the "has grown" part. I have always expected
the official kernel releases to be working and complete, without the
kind of half baked stumps that the embedded vendors are pushing.
In my experience with Freescale (and now TI also), the vendor supports
Linux on their platform by providing a heavily patched, quick and
dirty, customized kernel that is kinda, sorta working, somehow. This
provides a way for their customers to get started with the development
kits right away, and as such I have no problem with it.
What I do have a problem with is the fact the vendors then drop the
ball and don't follow through by getting their changes into
mainline. This makes a huge problem for the vendor's customers later
on, when the choice becomes either stay with the dead end vendor
kernel, or try to get mainline working all by themselves.
And so I am pleased to hear that the Ethernet ports on the am335x will
be working in v3.8. Better late than never.
Thanks,
Richard
^ permalink raw reply
* [PATCH v4 1/5] zynq: use GIC device tree bindings
From: Michal Simek @ 2012-10-29 7:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <94010fc0a0094ef29dc87fbdb77507e379c5fe76.1351466765.git.josh.cartwright@ni.com>
> -----Original Message-----
> From: Josh Cartwright [mailto:josh.cartwright at ni.com]
> Sent: Thursday, October 18, 2012 2:47 AM
> To: arm at kernel.org; Arnd Bergmann
> Cc: linux-kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org; John
> Linn; Nick Bowler; Michal Simek
> Subject: [PATCH v4 1/5] zynq: use GIC device tree bindings
>
> The Zynq uses the cortex-a9-gic. This eliminates the need to hardcode register
> addresses.
>
> Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
> Cc: John Linn <john.linn@xilinx.com>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> ---
> arch/arm/boot/dts/zynq-ep107.dts | 10 ++++++----
> arch/arm/mach-zynq/common.c | 7 ++++++-
> arch/arm/mach-zynq/include/mach/zynq_soc.h | 2 --
> 3 files changed, 12 insertions(+), 7 deletions(-)
>
Applied to http://git.xilinx.com/?p=linux-xlnx.git;a=shortlog;h=refs/heads/arm-next
Thanks,
Michal
^ permalink raw reply
* [PATCH v4 2/5] zynq: use pl310 device tree bindings
From: Michal Simek @ 2012-10-29 8:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a60818e7f2bf13cbc06b21bb3e3b0071539379ea.1351466765.git.josh.cartwright@ni.com>
> -----Original Message-----
> From: Josh Cartwright [mailto:josh.cartwright at ni.com]
> Sent: Wednesday, October 24, 2012 12:34 AM
> To: arm at kernel.org; Arnd Bergmann
> Cc: linux-kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org; John
> Linn; Nick Bowler; Michal Simek
> Subject: [PATCH v4 2/5] zynq: use pl310 device tree bindings
>
> The Zynq has a PL310 L2 cache controller. Convert in-tree uses to using the
> device tree.
>
> Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
> Cc: John Linn <john.linn@xilinx.com>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Acked-by: Michal Simek <michal.simek@xilinx.com>
> ---
> arch/arm/boot/dts/zynq-ep107.dts | 9 +++++++++
> arch/arm/mach-zynq/common.c | 9 +--------
> arch/arm/mach-zynq/include/mach/zynq_soc.h | 4 ----
> 3 files changed, 10 insertions(+), 12 deletions(-)
Applied to http://git.xilinx.com/?p=linux-xlnx.git;a=shortlog;h=refs/heads/arm-next
Thanks,
Michal
^ permalink raw reply
* [PATCH v4 3/5] zynq: remove use of CLKDEV_LOOKUP
From: Michal Simek @ 2012-10-29 8:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <079dc4cc1d0abd19cef111045ba305c474eb0e4c.1351466765.git.josh.cartwright@ni.com>
> -----Original Message-----
> From: Josh Cartwright [mailto:josh.cartwright at ni.com]
> Sent: Sunday, October 21, 2012 6:17 PM
> To: arm at kernel.org; Arnd Bergmann
> Cc: linux-kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org; John
> Linn; Nick Bowler; Michal Simek
> Subject: [PATCH v4 3/5] zynq: remove use of CLKDEV_LOOKUP
>
> The Zynq support in mainline does not (yet) make use of any of the generic clk
> or clk lookup functionality. Remove what is upstream for now, until the out-of-
> tree implementation is in suitable form for merging.
>
> An important side effect of this patch is that it allows the building of a Zynq
> kernel without running into unresolved symbol problems:
>
> drivers/built-in.o: In function `amba_get_enable_pclk':
> clkdev.c:(.text+0x444): undefined reference to `clk_enable'
> drivers/built-in.o: In function `amba_remove':
> clkdev.c:(.text+0x488): undefined reference to `clk_disable'
> drivers/built-in.o: In function `amba_probe':
> clkdev.c:(.text+0x540): undefined reference to `clk_disable'
> drivers/built-in.o: In function `amba_device_add':
> clkdev.c:(.text+0x77c): undefined reference to `clk_disable'
> drivers/built-in.o: In function `enable_clock':
> clkdev.c:(.text+0x29738): undefined reference to `clk_enable'
> drivers/built-in.o: In function `disable_clock':
> clkdev.c:(.text+0x29778): undefined reference to `clk_disable'
> drivers/built-in.o: In function `__pm_clk_remove':
> clkdev.c:(.text+0x297f8): undefined reference to `clk_disable'
> drivers/built-in.o: In function `pm_clk_suspend':
> clkdev.c:(.text+0x29bc8): undefined reference to `clk_disable'
> drivers/built-in.o: In function `pm_clk_resume':
> clkdev.c:(.text+0x29c28): undefined reference to `clk_enable'
> make[2]: *** [vmlinux] Error 1
> make[1]: *** [sub-make] Error 2
> make: *** [all] Error 2
>
> In addition, eliminate Zynq's "use" of the versatile platform, as it is no longer
> needed. As Nick Bowler points out:
>
> For the record, I think this was introduced by commit 56a34b03ff427
> ("ARM: versatile: Make plat-versatile clock optional") which forgot to
> select PLAT_VERSATILE_CLOCK on Zynq. This is not all that surprising,
> because the fact that Zynq "uses" PLAT_VERSATILE is secretly hidden in
> the Makefile.
>
> Nevertheless, the only feature from versatile that Zynq needed was the
> clock support, so this patch should *also* delete the secret use of
> plat-versatile by removing this line from arch/arm/Makefile:
>
> plat-$(CONFIG_ARCH_ZYNQ) += versatile
>
> Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
> Cc: John Linn <john.linn@xilinx.com>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Tested-by: Michal Simek <michal.simek@xilinx.com>
> ---
> arch/arm/Kconfig | 1 -
> arch/arm/Makefile | 1 -
> arch/arm/mach-zynq/common.c | 1 -
> arch/arm/mach-zynq/include/mach/clkdev.h | 32 --------------------------------
> 4 files changed, 35 deletions(-)
> delete mode 100644 arch/arm/mach-zynq/include/mach/clkdev.h
>
Applied to http://git.xilinx.com/?p=linux-xlnx.git;a=shortlog;h=refs/heads/arm-next
Thanks,
Michal
^ permalink raw reply
* [PATCH v4 5/5] zynq: move static peripheral mappings
From: Michal Simek @ 2012-10-29 8:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <7a663040dc05b79262d7bd8bf8224ca49eb00162.1351466765.git.josh.cartwright@ni.com>
> -----Original Message-----
> From: Josh Cartwright [mailto:josh.cartwright at ni.com]
> Sent: Monday, October 22, 2012 4:16 AM
> To: arm at kernel.org; Arnd Bergmann
> Cc: linux-kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org; John
> Linn; Nick Bowler; Michal Simek
> Subject: [PATCH v4 5/5] zynq: move static peripheral mappings
>
> Shifting them up into the vmalloc region prevents the following warning, when
> booting a zynq qemu target with more than 512mb of RAM:
>
> BUG: mapping for 0xe0000000 at 0xe0000000 out of vmalloc space
>
> In addition, it allows for reuse of these mappings when the proper drivers issue
> requests via ioremap().
>
> There are currently unknown issues with the early uart mapping. For now, the
> uart will be mapped to a known working address.
>
> Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
> Cc: John Linn <john.linn@xilinx.com>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> ---
> arch/arm/mach-zynq/common.c | 6 +++---
> arch/arm/mach-zynq/include/mach/zynq_soc.h | 25 +++++++++++++++----------
> 2 files changed, 18 insertions(+), 13 deletions(-)
>
Tested and applied to http://git.xilinx.com/?p=linux-xlnx.git;a=shortlog;h=refs/heads/arm-next
Thanks,
Michal
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
^ permalink raw reply
* [PATCH v4 3/5] rtc: omap: dt support
From: Afzal Mohammed @ 2012-10-29 8:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5084523F.2070800@gmail.com>
Hi Daniel,
On Monday 22 October 2012 01:21 AM, Daniel Mack wrote:
> On 19.10.2012 11:59, Afzal Mohammed wrote:
>> +static const struct of_device_id omap_rtc_of_match[] = {
>> + { .compatible = "ti,da830-rtc",
>> + .data =&omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX],
> Wouldn't it make sense to list all the compatible models here? The
> advantage of a compatible list is that we can name the models
> explicitly, or maybe at least "davinci-rtc". Is there any reason for
> this particular name?
Exact name followed by compatible models needs to be
specified in DT node only, right ? (when driver for the
first variant can handle it)
And when additional features of newer IP's has to be
leveraged, new entries can be added in the driver
match table.
First known variant of SoC for DT is da830 (exact name),
hence it was used.
Regards
Afzal
^ permalink raw reply
* [PATCH v2 06/14] mtd: onenand: omap: use pdata info instead of cpu_is
From: Afzal Mohammed @ 2012-10-29 8:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121026164115.GE11908@atomide.com>
On Friday 26 October 2012 10:11 PM, Tony Lindgren wrote:
> * Paul Walmsley<paul@pwsan.com> [121025 22:05]:
>> It also breaks an OMAP3+4 config:
>> Fix below.
> Thanks, I'd like to pull this fix in too along with the
> others.
Thanks Paul and Tony for taking care of this issue.
I am sorry about the issue and had been on vacation
last week.
Regards
Afzal
^ permalink raw reply
* [PATCH] ARM: AM33xx: add support for reboot
From: Afzal Mohammed @ 2012-10-29 8:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <508D8537.9010107@gmail.com>
Hi Daniel,
On Monday 29 October 2012 12:49 AM, Daniel Mack wrote:
> Afzal, are you planning to resubmit this for mainline? My version can of
> course be disposed then.
I am not planning to submit it as of now, and Vaibhav H has
a better suggestion on this, you may co-ordinate with him.
Regards
Afzal
^ permalink raw reply
* [PATCH 4/4] OMAP: mtd: gpmc: add DT bindings for GPMC timings and NAND
From: Afzal Mohammed @ 2012-10-29 8:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5088F19B.7050606@gmail.com>
Hi Daniel,
On Thursday 25 October 2012 01:30 PM, Daniel Mack wrote:
> Hmm, that number is currently hard-coded in GPMC_CS_NUM. It would take
> some effort to make that dynamic but I agree that this would be a good
> thing to have. Afzal?
It would be good to have (to the best of my knowledge
am335x has only 7 pinned out, even though IP has 8)
Regards
Afzal
^ permalink raw reply
* [PATCH 4/4] OMAP: mtd: gpmc: add DT bindings for GPMC timings and NAND
From: Afzal Mohammed @ 2012-10-29 8:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50887A6B.3050108@gmail.com>
Hi Daniel,
On Thursday 25 October 2012 05:01 AM, Daniel Mack wrote:
> Thanks for the review. I'll wait for feedback from Afzal next week and
> then repost. Wanted to see first if that goes in the right direction at
> all before bordering the DT people with binding details :)
I was thinking of a generic approach, where there won't be
any check for peripheral device type.
But going that path would delay achieving DT, may be let's
proceed with your approach to start with so that we can
have a minimal level of DT support for GPMC and probably
we can make it generic later. While adding new properties,
it would be better to keep in mind that we need not change
these later once gpmc DT is made generic.
Regarding the bindings, there are some generic nand
properties like ecc already available, may be that be made
use here. Also perhaps memory size (and offset if
needed) to be mapped for peripherals can go with reg
property of child.
Regards
Afzal
^ permalink raw reply
* [RFC PATCH v3 11/16] mmc: omap_hsmmc: limit max_segs with the EDMA DMAC
From: Sekhar Nori @ 2012-10-29 8:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350566815-409-12-git-send-email-mporter@ti.com>
On 10/18/2012 6:56 PM, Matt Porter wrote:
> The EDMA DMAC has a hardware limitation that prevents supporting
> scatter gather lists with any number of segments. Since the EDMA
> DMA Engine driver sets the maximum segments to 16, we do the
> same.
>
> TODO: this will be replaced once the DMA Engine API supports an
> API to query the DMAC's segment size limit.
>
> Signed-off-by: Matt Porter <mporter@ti.com>
> ---
> drivers/mmc/host/omap_hsmmc.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> index b327cd0..52bab01 100644
> --- a/drivers/mmc/host/omap_hsmmc.c
> +++ b/drivers/mmc/host/omap_hsmmc.c
> @@ -1828,6 +1828,16 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
> * as we want. */
> mmc->max_segs = 1024;
>
> + /* Eventually we should get our max_segs limitation for EDMA by
> + * querying the dmaengine API */
Nit picking: This is not as per multi-line comment style in
Documentation/CodingStyle.
Thanks,
Sekhar
^ permalink raw reply
* # (c) 2007, Joe Perches <joe@perches.com>
From: Vaibhav Hiremath @ 2012-10-29 8:21 UTC (permalink / raw)
To: linux-arm-kernel
use strict;
my $P = $0;
my $V = '0.26';
use Getopt::Long qw(:config no_auto_abbrev);
my $lk_path = "./";
my $email = 1;
my $email_usename = 1;
my $email_maintainer = 1;
my $email_list = 1;
my $email_subscriber_list = 0;
my $email_git_penguin_chiefs = 0;
my $email_git = 0;
my $email_git_all_signature_types = 0;
my $email_git_blame = 0;
my $email_git_blame_signatures = 1;
my $email_git_fallback = 1;
my $email_git_min_signatures = 1;
my $email_git_max_maintainers = 5;
my $email_git_min_percent = 5;
my $email_git_since = "1-year-ago";
my $email_hg_since = "-365";
my $interactive = 0;
my $email_remove_duplicates = 1;
my $email_use_mailmap = 1;
my $output_multiline = 1;
my $output_separator = ", ";
my $output_roles = 0;
my $output_rolestats = 1;
my $scm = 0;
my $web = 0;
my $subsystem = 0;
my $status = 0;
my $keywords = 1;
my $sections = 0;
my $file_emails = 0;
my $from_filename = 0;
my $pattern_depth = 0;
my $version = 0;
my $help = 0;
my $vcs_used = 0;
my $exit = 0;
my %commit_author_hash;
my %commit_signer_hash;
my @penguin_chief = ();
push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org");
#Andrew wants in on most everything - 2009/01/14
#push(@penguin_chief, "Andrew Morton:akpm\@linux-foundation.org");
my @penguin_chief_names = ();
foreach my $chief (@penguin_chief) {
if ($chief =~ m/^(.*):(.*)/) {
my $chief_name = $1;
my $chief_addr = $2;
push(@penguin_chief_names, $chief_name);
}
}
my $penguin_chiefs = "\(" . join("|", @penguin_chief_names) . "\)";
# Signature types of people who are either
# a) responsible for the code in question, or
# b) familiar enough with it to give relevant feedback
my @signature_tags = ();
push(@signature_tags, "Signed-off-by:");
push(@signature_tags, "Reviewed-by:");
push(@signature_tags, "Acked-by:");
my $signature_pattern = "\(" . join("|", @signature_tags) . "\)";
# rfc822 email address - preloaded methods go here.
my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])";
my $rfc822_char = '[\\000-\\377]';
# VCS command support: class-like functions and strings
my %VCS_cmds;
my %VCS_cmds_git = (
"execute_cmd" => \&git_execute_cmd,
"available" => '(which("git") ne "") && (-d ".git")',
"find_signers_cmd" =>
"git log --no-color --follow --since=\$email_git_since " .
'--format="GitCommit: %H%n' .
'GitAuthor: %an <%ae>%n' .
'GitDate: %aD%n' .
'GitSubject: %s%n' .
'%b%n"' .
" -- \$file",
"find_commit_signers_cmd" =>
"git log --no-color " .
'--format="GitCommit: %H%n' .
'GitAuthor: %an <%ae>%n' .
'GitDate: %aD%n' .
'GitSubject: %s%n' .
'%b%n"' .
" -1 \$commit",
"find_commit_author_cmd" =>
"git log --no-color " .
'--format="GitCommit: %H%n' .
'GitAuthor: %an <%ae>%n' .
'GitDate: %aD%n' .
'GitSubject: %s%n"' .
" -1 \$commit",
"blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file",
"blame_file_cmd" => "git blame -l \$file",
"commit_pattern" => "^GitCommit: ([0-9a-f]{40,40})",
"blame_commit_pattern" => "^([0-9a-f]+) ",
"author_pattern" => "^GitAuthor: (.*)",
"subject_pattern" => "^GitSubject: (.*)",
);
my %VCS_cmds_hg = (
"execute_cmd" => \&hg_execute_cmd,
"available" => '(which("hg") ne "") && (-d ".hg")',
"find_signers_cmd" =>
"hg log --date=\$email_hg_since " .
"--template='HgCommit: {node}\\n" .
"HgAuthor: {author}\\n" .
"HgSubject: {desc}\\n'" .
" -- \$file",
"find_commit_signers_cmd" =>
"hg log " .
"--template='HgSubject: {desc}\\n'" .
" -r \$commit",
"find_commit_author_cmd" =>
"hg log " .
"--template='HgCommit: {node}\\n" .
"HgAuthor: {author}\\n" .
"HgSubject: {desc|firstline}\\n'" .
" -r \$commit",
"blame_range_cmd" => "", # not supported
"blame_file_cmd" => "hg blame -n \$file",
"commit_pattern" => "^HgCommit: ([0-9a-f]{40,40})",
"blame_commit_pattern" => "^([ 0-9a-f]+):",
"author_pattern" => "^HgAuthor: (.*)",
"subject_pattern" => "^HgSubject: (.*)",
);
my $conf = which_conf(".get_maintainer.conf");
if (-f $conf) {
my @conf_args;
open(my $conffile, '<', "$conf")
or warn "$P: Can't find a readable .get_maintainer.conf file $!\n";
while (<$conffile>) {
my $line = $_;
$line =~ s/\s*\n?$//g;
$line =~ s/^\s*//g;
$line =~ s/\s+/ /g;
next if ($line =~ m/^\s*#/);
next if ($line =~ m/^\s*$/);
my @words = split(" ", $line);
foreach my $word (@words) {
last if ($word =~ m/^#/);
push (@conf_args, $word);
}
}
close($conffile);
unshift(@ARGV, @conf_args) if @conf_args;
}
if (!GetOptions(
'email!' => \$email,
'git!' => \$email_git,
'git-all-signature-types!' => \$email_git_all_signature_types,
'git-blame!' => \$email_git_blame,
'git-blame-signatures!' => \$email_git_blame_signatures,
'git-fallback!' => \$email_git_fallback,
'git-chief-penguins!' => \$email_git_penguin_chiefs,
'git-min-signatures=i' => \$email_git_min_signatures,
'git-max-maintainers=i' => \$email_git_max_maintainers,
'git-min-percent=i' => \$email_git_min_percent,
'git-since=s' => \$email_git_since,
'hg-since=s' => \$email_hg_since,
'i|interactive!' => \$interactive,
'remove-duplicates!' => \$email_remove_duplicates,
'mailmap!' => \$email_use_mailmap,
'm!' => \$email_maintainer,
'n!' => \$email_usename,
'l!' => \$email_list,
's!' => \$email_subscriber_list,
'multiline!' => \$output_multiline,
'roles!' => \$output_roles,
'rolestats!' => \$output_rolestats,
'separator=s' => \$output_separator,
'subsystem!' => \$subsystem,
'status!' => \$status,
'scm!' => \$scm,
'web!' => \$web,
'pattern-depth=i' => \$pattern_depth,
'k|keywords!' => \$keywords,
'sections!' => \$sections,
'fe|file-emails!' => \$file_emails,
'f|file' => \$from_filename,
'v|version' => \$version,
'h|help|usage' => \$help,
)) {
die "$P: invalid argument - use --help if necessary\n";
}
if ($help != 0) {
usage();
exit 0;
}
if ($version != 0) {
print("${P} ${V}\n");
exit 0;
}
if (-t STDIN && !@ARGV) {
# We're talking to a terminal, but have no command line arguments.
die "$P: missing patchfile or -f file - use --help if necessary\n";
}
$output_multiline = 0 if ($output_separator ne ", ");
$output_rolestats = 1 if ($interactive);
$output_roles = 1 if ($output_rolestats);
if ($sections) {
$email = 0;
$email_list = 0;
$scm = 0;
$status = 0;
$subsystem = 0;
$web = 0;
$keywords = 0;
$interactive = 0;
} else {
my $selections = $email + $scm + $status + $subsystem + $web;
if ($selections == 0) {
die "$P: Missing required option: email, scm, status, subsystem or web\n";
}
}
if ($email &&
($email_maintainer + $email_list + $email_subscriber_list +
$email_git + $email_git_penguin_chiefs + $email_git_blame) == 0) {
die "$P: Please select at least 1 email option\n";
}
if (!top_of_kernel_tree($lk_path)) {
die "$P: The current directory does not appear to be "
. "a linux kernel source tree.\n";
}
## Read MAINTAINERS for type/value pairs
my @typevalue = ();
my %keyword_hash;
open (my $maint, '<', "${lk_path}MAINTAINERS")
or die "$P: Can't open MAINTAINERS: $!\n";
while (<$maint>) {
my $line = $_;
if ($line =~ m/^(\C):\s*(.*)/) {
my $type = $1;
my $value = $2;
##Filename pattern matching
if ($type eq "F" || $type eq "X") {
$value =~ s@\.@\\\. at g; ##Convert . to \.
$value =~ s/\*/\.\*/g; ##Convert * to .*
$value =~ s/\?/\./g; ##Convert ? to .
##if pattern is a directory and it lacks a trailing slash, add one
if ((-d $value)) {
$value =~ s@([^/])$@$1/@;
}
} elsif ($type eq "K") {
$keyword_hash{@typevalue} = $value;
}
push(@typevalue, "$type:$value");
} elsif (!/^(\s)*$/) {
$line =~ s/\n$//g;
push(@typevalue, $line);
}
}
close($maint);
#
# Read mail address map
#
my $mailmap;
read_mailmap();
sub read_mailmap {
$mailmap = {
names => {},
addresses => {}
};
return if (!$email_use_mailmap || !(-f "${lk_path}.mailmap"));
open(my $mailmap_file, '<', "${lk_path}.mailmap")
or warn "$P: Can't open .mailmap: $!\n";
while (<$mailmap_file>) {
s/#.*$//; #strip comments
s/^\s+|\s+$//g; #trim
next if (/^\s*$/); #skip empty lines
#entries have one of the following formats:
# name1 <mail1>
# <mail1> <mail2>
# name1 <mail1> <mail2>
# name1 <mail1> name2 <mail2>
# (see man git-shortlog)
if (/^([^<]+)<([^>]+)>$/) {
my $real_name = $1;
my $address = $2;
$real_name =~ s/\s+$//;
($real_name, $address) = parse_email("$real_name <$address>");
$mailmap->{names}->{$address} = $real_name;
} elsif (/^<([^>]+)>\s*<([^>]+)>$/) {
my $real_address = $1;
my $wrong_address = $2;
$mailmap->{addresses}->{$wrong_address} = $real_address;
} elsif (/^(.+)<([^>]+)>\s*<([^>]+)>$/) {
my $real_name = $1;
my $real_address = $2;
my $wrong_address = $3;
$real_name =~ s/\s+$//;
($real_name, $real_address) =
parse_email("$real_name <$real_address>");
$mailmap->{names}->{$wrong_address} = $real_name;
$mailmap->{addresses}->{$wrong_address} = $real_address;
} elsif (/^(.+)<([^>]+)>\s*(.+)\s*<([^>]+)>$/) {
my $real_name = $1;
my $real_address = $2;
my $wrong_name = $3;
my $wrong_address = $4;
$real_name =~ s/\s+$//;
($real_name, $real_address) =
parse_email("$real_name <$real_address>");
$wrong_name =~ s/\s+$//;
($wrong_name, $wrong_address) =
parse_email("$wrong_name <$wrong_address>");
my $wrong_email = format_email($wrong_name, $wrong_address, 1);
$mailmap->{names}->{$wrong_email} = $real_name;
$mailmap->{addresses}->{$wrong_email} = $real_address;
}
}
close($mailmap_file);
}
## use the filenames on the command line or find the filenames in the patchfiles
my @files = ();
my @range = ();
my @keyword_tvi = ();
my @file_emails = ();
if (!@ARGV) {
push(@ARGV, "&STDIN");
}
foreach my $file (@ARGV) {
if ($file ne "&STDIN") {
##if $file is a directory and it lacks a trailing slash, add one
if ((-d $file)) {
$file =~ s@([^/])$@$1/@;
} elsif (!(-f $file)) {
die "$P: file '${file}' not found\n";
}
}
if ($from_filename) {
push(@files, $file);
if ($file ne "MAINTAINERS" && -f $file && ($keywords || $file_emails)) {
open(my $f, '<', $file)
or die "$P: Can't open $file: $!\n";
my $text = do { local($/) ; <$f> };
close($f);
if ($keywords) {
foreach my $line (keys %keyword_hash) {
if ($text =~ m/$keyword_hash{$line}/x) {
push(@keyword_tvi, $line);
}
}
}
if ($file_emails) {
my @poss_addr = $text =~ m$[A-Za-z??-??\"\' \,\.\+-]*\s*[\,]*\s*[\(\<\{]{0,1}[A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+\.[A-Za-z0-9]+[\)\>\}]{0,1}$g;
push(@file_emails, clean_file_emails(@poss_addr));
}
}
} else {
my $file_cnt = @files;
my $lastfile;
open(my $patch, "< $file")
or die "$P: Can't open $file: $!\n";
# We can check arbitrary information before the patch
# like the commit message, mail headers, etc...
# This allows us to match arbitrary keywords against any part
# of a git format-patch generated file (subject tags, etc...)
my $patch_prefix = ""; #Parsing the intro
while (<$patch>) {
my $patch_line = $_;
if (m/^\+\+\+\s+(\S+)/) {
my $filename = $1;
$filename =~ s@^[^/]*/@@;
$filename =~ s@\n@@;
$lastfile = $filename;
push(@files, $filename);
$patch_prefix = "^[+-].*"; #Now parsing the actual patch
} elsif (m/^\@\@ -(\d+),(\d+)/) {
if ($email_git_blame) {
push(@range, "$lastfile:$1:$2");
}
} elsif ($keywords) {
foreach my $line (keys %keyword_hash) {
if ($patch_line =~ m/${patch_prefix}$keyword_hash{$line}/x) {
push(@keyword_tvi, $line);
}
}
}
}
close($patch);
if ($file_cnt == @files) {
warn "$P: file '${file}' doesn't appear to be a patch. "
. "Add -f to options?\n";
}
@files = sort_and_uniq(@files);
}
}
@file_emails = uniq(@file_emails);
my %email_hash_name;
my %email_hash_address;
my @email_to = ();
my %hash_list_to;
my @list_to = ();
my @scm = ();
my @web = ();
my @subsystem = ();
my @status = ();
my %deduplicate_name_hash = ();
my %deduplicate_address_hash = ();
my @maintainers = get_maintainers();
if (@maintainers) {
@maintainers = merge_email(@maintainers);
output(@maintainers);
}
if ($scm) {
@scm = uniq(@scm);
output(@scm);
}
if ($status) {
@status = uniq(@status);
output(@status);
}
if ($subsystem) {
@subsystem = uniq(@subsystem);
output(@subsystem);
}
if ($web) {
@web = uniq(@web);
output(@web);
}
exit($exit);
sub range_is_maintained {
my ($start, $end) = @_;
for (my $i = $start; $i < $end; $i++) {
my $line = $typevalue[$i];
if ($line =~ m/^(\C):\s*(.*)/) {
my $type = $1;
my $value = $2;
if ($type eq 'S') {
if ($value =~ /(maintain|support)/i) {
return 1;
}
}
}
}
return 0;
}
sub range_has_maintainer {
my ($start, $end) = @_;
for (my $i = $start; $i < $end; $i++) {
my $line = $typevalue[$i];
if ($line =~ m/^(\C):\s*(.*)/) {
my $type = $1;
my $value = $2;
if ($type eq 'M') {
return 1;
}
}
}
return 0;
}
sub get_maintainers {
%email_hash_name = ();
%email_hash_address = ();
%commit_author_hash = ();
%commit_signer_hash = ();
@email_to = ();
%hash_list_to = ();
@list_to = ();
@scm = ();
@web = ();
@subsystem = ();
@status = ();
%deduplicate_name_hash = ();
%deduplicate_address_hash = ();
if ($email_git_all_signature_types) {
$signature_pattern = "(.+?)[Bb][Yy]:";
} else {
$signature_pattern = "\(" . join("|", @signature_tags) . "\)";
}
# Find responsible parties
my %exact_pattern_match_hash = ();
foreach my $file (@files) {
my %hash;
my $tvi = find_first_section();
while ($tvi < @typevalue) {
my $start = find_starting_index($tvi);
my $end = find_ending_index($tvi);
my $exclude = 0;
my $i;
#Do not match excluded file patterns
for ($i = $start; $i < $end; $i++) {
my $line = $typevalue[$i];
if ($line =~ m/^(\C):\s*(.*)/) {
my $type = $1;
my $value = $2;
if ($type eq 'X') {
if (file_match_pattern($file, $value)) {
$exclude = 1;
last;
}
}
}
}
if (!$exclude) {
for ($i = $start; $i < $end; $i++) {
my $line = $typevalue[$i];
if ($line =~ m/^(\C):\s*(.*)/) {
my $type = $1;
my $value = $2;
if ($type eq 'F') {
if (file_match_pattern($file, $value)) {
my $value_pd = ($value =~ tr@/@@);
my $file_pd = ($file =~ tr@/@@);
$value_pd++ if (substr($value,-1,1) ne "/");
$value_pd = -1 if ($value =~ /^\.\*/);
if ($value_pd >= $file_pd &&
range_is_maintained($start, $end) &&
range_has_maintainer($start, $end)) {
$exact_pattern_match_hash{$file} = 1;
}
if ($pattern_depth == 0 ||
(($file_pd - $value_pd) < $pattern_depth)) {
$hash{$tvi} = $value_pd;
}
}
}
}
}
}
$tvi = $end + 1;
}
foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
add_categories($line);
if ($sections) {
my $i;
my $start = find_starting_index($line);
my $end = find_ending_index($line);
for ($i = $start; $i < $end; $i++) {
my $line = $typevalue[$i];
if ($line =~ /^[FX]:/) { ##Restore file patterns
$line =~ s/([^\\])\.([^\*])/$1\?$2/g;
$line =~ s/([^\\])\.$/$1\?/g; ##Convert . back to ?
$line =~ s/\\\./\./g; ##Convert \. to .
$line =~ s/\.\*/\*/g; ##Convert .* to *
}
$line =~ s/^([A-Z]):/$1:\t/g;
print("$line\n");
}
print("\n");
}
}
}
if ($keywords) {
@keyword_tvi = sort_and_uniq(@keyword_tvi);
foreach my $line (@keyword_tvi) {
add_categories($line);
}
}
foreach my $email (@email_to, @list_to) {
$email->[0] = deduplicate_email($email->[0]);
}
foreach my $file (@files) {
if ($email &&
($email_git || ($email_git_fallback &&
!$exact_pattern_match_hash{$file}))) {
vcs_file_signoffs($file);
}
if ($email && $email_git_blame) {
vcs_file_blame($file);
}
}
if ($email) {
foreach my $chief (@penguin_chief) {
if ($chief =~ m/^(.*):(.*)/) {
my $email_address;
$email_address = format_email($1, $2, $email_usename);
if ($email_git_penguin_chiefs) {
push(@email_to, [$email_address, 'chief penguin']);
} else {
@email_to = grep($_->[0] !~ /${email_address}/, @email_to);
}
}
}
foreach my $email (@file_emails) {
my ($name, $address) = parse_email($email);
my $tmp_email = format_email($name, $address, $email_usename);
push_email_address($tmp_email, '');
add_role($tmp_email, 'in file');
}
}
my @to = ();
if ($email || $email_list) {
if ($email) {
@to = (@to, @email_to);
}
if ($email_list) {
@to = (@to, @list_to);
}
}
if ($interactive) {
@to = interactive_get_maintainers(\@to);
}
return @to;
}
sub file_match_pattern {
my ($file, $pattern) = @_;
if (substr($pattern, -1) eq "/") {
if ($file =~ m@^$pattern@) {
return 1;
}
} else {
if ($file =~ m@^$pattern@) {
my $s1 = ($file =~ tr@/@@);
my $s2 = ($pattern =~ tr@/@@);
if ($s1 == $s2) {
return 1;
}
}
}
return 0;
}
sub usage {
print <<EOT;
usage: $P [options] patchfile
$P [options] -f file|directory
version: $V
MAINTAINER field selection options:
--email => print email address(es) if any
--git => include recent git \*-by: signers
--git-all-signature-types => include signers regardless of signature type
or use only ${signature_pattern} signers (default: $email_git_all_signature_types)
--git-fallback => use git when no exact MAINTAINERS pattern (default: $email_git_fallback)
--git-chief-penguins => include ${penguin_chiefs}
--git-min-signatures => number of signatures required (default: $email_git_min_signatures)
--git-max-maintainers => maximum maintainers to add (default: $email_git_max_maintainers)
--git-min-percent => minimum percentage of commits required (default: $email_git_min_percent)
--git-blame => use git blame to find modified commits for patch or file
--git-since => git history to use (default: $email_git_since)
--hg-since => hg history to use (default: $email_hg_since)
--interactive => display a menu (mostly useful if used with the --git option)
--m => include maintainer(s) if any
--n => include name 'Full Name <addr\@domain.tld>'
--l => include list(s) if any
--s => include subscriber only list(s) if any
--remove-duplicates => minimize duplicate email names/addresses
--roles => show roles (status:subsystem, git-signer, list, etc...)
--rolestats => show roles and statistics (commits/total_commits, %)
--file-emails => add email addresses found in -f file (default: 0 (off))
--scm => print SCM tree(s) if any
--status => print status if any
--subsystem => print subsystem name if any
--web => print website(s) if any
Output type options:
--separator [, ] => separator for multiple entries on 1 line
using --separator also sets --nomultiline if --separator is not [, ]
--multiline => print 1 entry per line
Other options:
--pattern-depth => Number of pattern directory traversals (default: 0 (all))
--keywords => scan patch for keywords (default: $keywords)
--sections => print all of the subsystem sections with pattern matches
--mailmap => use .mailmap file (default: $email_use_mailmap)
--version => show version
--help => show this help information
Default options:
[--email --nogit --git-fallback --m --n --l --multiline -pattern-depth=0
--remove-duplicates --rolestats]
Notes:
Using "-f directory" may give unexpected results:
Used with "--git", git signators for _all_ files in and below
directory are examined as git recurses directories.
Any specified X: (exclude) pattern matches are _not_ ignored.
Used with "--nogit", directory is used as a pattern match,
no individual file within the directory or subdirectory
is matched.
Used with "--git-blame", does not iterate all files in directory
Using "--git-blame" is slow and may add old committers and authors
that are no longer active maintainers to the output.
Using "--roles" or "--rolestats" with git send-email --cc-cmd or any
other automated tools that expect only ["name"] <email address>
may not work because of additional output after <email address>.
Using "--rolestats" and "--git-blame" shows the #/total=% commits,
not the percentage of the entire file authored. # of commits is
not a good measure of amount of code authored. 1 major commit may
contain a thousand lines, 5 trivial commits may modify a single line.
If git is not installed, but mercurial (hg) is installed and an .hg
repository exists, the following options apply to mercurial:
--git,
--git-min-signatures, --git-max-maintainers, --git-min-percent, and
--git-blame
Use --hg-since not --git-since to control date selection
File ".get_maintainer.conf", if it exists in the linux kernel source root
directory, can change whatever get_maintainer defaults are desired.
Entries in this file can be any command line argument.
This file is prepended to any additional command line arguments.
Multiple lines and # comments are allowed.
EOT
}
sub top_of_kernel_tree {
my ($lk_path) = @_;
if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") {
$lk_path .= "/";
}
if ( (-f "${lk_path}COPYING")
&& (-f "${lk_path}CREDITS")
&& (-f "${lk_path}Kbuild")
&& (-f "${lk_path}MAINTAINERS")
&& (-f "${lk_path}Makefile")
&& (-f "${lk_path}README")
&& (-d "${lk_path}Documentation")
&& (-d "${lk_path}arch")
&& (-d "${lk_path}include")
&& (-d "${lk_path}drivers")
&& (-d "${lk_path}fs")
&& (-d "${lk_path}init")
&& (-d "${lk_path}ipc")
&& (-d "${lk_path}kernel")
&& (-d "${lk_path}lib")
&& (-d "${lk_path}scripts")) {
return 1;
}
return 0;
}
sub parse_email {
my ($formatted_email) = @_;
my $name = "";
my $address = "";
if ($formatted_email =~ /^([^<]+)<(.+\@.*)>.*$/) {
$name = $1;
$address = $2;
} elsif ($formatted_email =~ /^\s*<(.+\@\S*)>.*$/) {
$address = $1;
} elsif ($formatted_email =~ /^(.+\@\S*).*$/) {
$address = $1;
}
$name =~ s/^\s+|\s+$//g;
$name =~ s/^\"|\"$//g;
$address =~ s/^\s+|\s+$//g;
if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
$name = "\"$name\"";
}
return ($name, $address);
}
sub format_email {
my ($name, $address, $usename) = @_;
my $formatted_email;
$name =~ s/^\s+|\s+$//g;
$name =~ s/^\"|\"$//g;
$address =~ s/^\s+|\s+$//g;
if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
$name = "\"$name\"";
}
if ($usename) {
if ("$name" eq "") {
$formatted_email = "$address";
} else {
$formatted_email = "$name <$address>";
}
} else {
$formatted_email = $address;
}
return $formatted_email;
}
sub find_first_section {
my $index = 0;
while ($index < @typevalue) {
my $tv = $typevalue[$index];
if (($tv =~ m/^(\C):\s*(.*)/)) {
last;
}
$index++;
}
return $index;
}
sub find_starting_index {
my ($index) = @_;
while ($index > 0) {
my $tv = $typevalue[$index];
if (!($tv =~ m/^(\C):\s*(.*)/)) {
last;
}
$index--;
}
return $index;
}
sub find_ending_index {
my ($index) = @_;
while ($index < @typevalue) {
my $tv = $typevalue[$index];
if (!($tv =~ m/^(\C):\s*(.*)/)) {
last;
}
$index++;
}
return $index;
}
sub get_maintainer_role {
my ($index) = @_;
my $i;
my $start = find_starting_index($index);
my $end = find_ending_index($index);
my $role = "unknown";
my $subsystem = $typevalue[$start];
if (length($subsystem) > 20) {
$subsystem = substr($subsystem, 0, 17);
$subsystem =~ s/\s*$//;
$subsystem = $subsystem . "...";
}
for ($i = $start + 1; $i < $end; $i++) {
my $tv = $typevalue[$i];
if ($tv =~ m/^(\C):\s*(.*)/) {
my $ptype = $1;
my $pvalue = $2;
if ($ptype eq "S") {
$role = $pvalue;
}
}
}
$role = lc($role);
if ($role eq "supported") {
$role = "supporter";
} elsif ($role eq "maintained") {
$role = "maintainer";
} elsif ($role eq "odd fixes") {
$role = "odd fixer";
} elsif ($role eq "orphan") {
$role = "orphan minder";
} elsif ($role eq "obsolete") {
$role = "obsolete minder";
} elsif ($role eq "buried alive in reporters") {
$role = "chief penguin";
}
return $role . ":" . $subsystem;
}
sub get_list_role {
my ($index) = @_;
my $i;
my $start = find_starting_index($index);
my $end = find_ending_index($index);
my $subsystem = $typevalue[$start];
if (length($subsystem) > 20) {
$subsystem = substr($subsystem, 0, 17);
$subsystem =~ s/\s*$//;
$subsystem = $subsystem . "...";
}
if ($subsystem eq "THE REST") {
$subsystem = "";
}
return $subsystem;
}
sub add_categories {
my ($index) = @_;
my $i;
my $start = find_starting_index($index);
my $end = find_ending_index($index);
push(@subsystem, $typevalue[$start]);
for ($i = $start + 1; $i < $end; $i++) {
my $tv = $typevalue[$i];
if ($tv =~ m/^(\C):\s*(.*)/) {
my $ptype = $1;
my $pvalue = $2;
if ($ptype eq "L") {
my $list_address = $pvalue;
my $list_additional = "";
my $list_role = get_list_role($i);
if ($list_role ne "") {
$list_role = ":" . $list_role;
}
if ($list_address =~ m/([^\s]+)\s+(.*)$/) {
$list_address = $1;
$list_additional = $2;
}
if ($list_additional =~ m/subscribers-only/) {
if ($email_subscriber_list) {
if (!$hash_list_to{lc($list_address)}) {
$hash_list_to{lc($list_address)} = 1;
push(@list_to, [$list_address,
"subscriber list${list_role}"]);
}
}
} else {
if ($email_list) {
if (!$hash_list_to{lc($list_address)}) {
$hash_list_to{lc($list_address)} = 1;
if ($list_additional =~ m/moderated/) {
push(@list_to, [$list_address,
"moderated list${list_role}"]);
} else {
push(@list_to, [$list_address,
"open list${list_role}"]);
}
}
}
}
} elsif ($ptype eq "M") {
my ($name, $address) = parse_email($pvalue);
if ($name eq "") {
if ($i > 0) {
my $tv = $typevalue[$i - 1];
if ($tv =~ m/^(\C):\s*(.*)/) {
if ($1 eq "P") {
$name = $2;
$pvalue = format_email($name, $address, $email_usename);
}
}
}
}
if ($email_maintainer) {
my $role = get_maintainer_role($i);
push_email_addresses($pvalue, $role);
}
} elsif ($ptype eq "T") {
push(@scm, $pvalue);
} elsif ($ptype eq "W") {
push(@web, $pvalue);
} elsif ($ptype eq "S") {
push(@status, $pvalue);
}
}
}
}
sub email_inuse {
my ($name, $address) = @_;
return 1 if (($name eq "") && ($address eq ""));
return 1 if (($name ne "") && exists($email_hash_name{lc($name)}));
return 1 if (($address ne "") && exists($email_hash_address{lc($address)}));
return 0;
}
sub push_email_address {
my ($line, $role) = @_;
my ($name, $address) = parse_email($line);
if ($address eq "") {
return 0;
}
if (!$email_remove_duplicates) {
push(@email_to, [format_email($name, $address, $email_usename), $role]);
} elsif (!email_inuse($name, $address)) {
push(@email_to, [format_email($name, $address, $email_usename), $role]);
$email_hash_name{lc($name)}++ if ($name ne "");
$email_hash_address{lc($address)}++;
}
return 1;
}
sub push_email_addresses {
my ($address, $role) = @_;
my @address_list = ();
if (rfc822_valid($address)) {
push_email_address($address, $role);
} elsif (@address_list = rfc822_validlist($address)) {
my $array_count = shift(@address_list);
while (my $entry = shift(@address_list)) {
push_email_address($entry, $role);
}
} else {
if (!push_email_address($address, $role)) {
warn("Invalid MAINTAINERS address: '" . $address . "'\n");
}
}
}
sub add_role {
my ($line, $role) = @_;
my ($name, $address) = parse_email($line);
my $email = format_email($name, $address, $email_usename);
foreach my $entry (@email_to) {
if ($email_remove_duplicates) {
my ($entry_name, $entry_address) = parse_email($entry->[0]);
if (($name eq $entry_name || $address eq $entry_address)
&& ($role eq "" || !($entry->[1] =~ m/$role/))
) {
if ($entry->[1] eq "") {
$entry->[1] = "$role";
} else {
$entry->[1] = "$entry->[1],$role";
}
}
} else {
if ($email eq $entry->[0]
&& ($role eq "" || !($entry->[1] =~ m/$role/))
) {
if ($entry->[1] eq "") {
$entry->[1] = "$role";
} else {
$entry->[1] = "$entry->[1],$role";
}
}
}
}
}
sub which {
my ($bin) = @_;
foreach my $path (split(/:/, $ENV{PATH})) {
if (-e "$path/$bin") {
return "$path/$bin";
}
}
return "";
}
sub which_conf {
my ($conf) = @_;
foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
if (-e "$path/$conf") {
return "$path/$conf";
}
}
return "";
}
sub mailmap_email {
my ($line) = @_;
my ($name, $address) = parse_email($line);
my $email = format_email($name, $address, 1);
my $real_name = $name;
my $real_address = $address;
if (exists $mailmap->{names}->{$email} ||
exists $mailmap->{addresses}->{$email}) {
if (exists $mailmap->{names}->{$email}) {
$real_name = $mailmap->{names}->{$email};
}
if (exists $mailmap->{addresses}->{$email}) {
$real_address = $mailmap->{addresses}->{$email};
}
} else {
if (exists $mailmap->{names}->{$address}) {
$real_name = $mailmap->{names}->{$address};
}
if (exists $mailmap->{addresses}->{$address}) {
$real_address = $mailmap->{addresses}->{$address};
}
}
return format_email($real_name, $real_address, 1);
}
sub mailmap {
my (@addresses) = @_;
my @mapped_emails = ();
foreach my $line (@addresses) {
push(@mapped_emails, mailmap_email($line));
}
merge_by_realname(@mapped_emails) if ($email_use_mailmap);
return @mapped_emails;
}
sub merge_by_realname {
my %address_map;
my (@emails) = @_;
foreach my $email (@emails) {
my ($name, $address) = parse_email($email);
if (exists $address_map{$name}) {
$address = $address_map{$name};
$email = format_email($name, $address, 1);
} else {
$address_map{$name} = $address;
}
}
}
sub git_execute_cmd {
my ($cmd) = @_;
my @lines = ();
my $output = `$cmd`;
$output =~ s/^\s*//gm;
@lines = split("\n", $output);
return @lines;
}
sub hg_execute_cmd {
my ($cmd) = @_;
my @lines = ();
my $output = `$cmd`;
@lines = split("\n", $output);
return @lines;
}
sub extract_formatted_signatures {
my (@signature_lines) = @_;
my @type = @signature_lines;
s/\s*(.*):.*/$1/ for (@type);
# cut -f2- -d":"
s/\s*.*:\s*(.+)\s*/$1/ for (@signature_lines);
## Reformat email addresses (with names) to avoid badly written signatures
foreach my $signer (@signature_lines) {
$signer = deduplicate_email($signer);
}
return (\@type, \@signature_lines);
}
sub vcs_find_signers {
my ($cmd) = @_;
my $commits;
my @lines = ();
my @signatures = ();
@lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
my $pattern = $VCS_cmds{"commit_pattern"};
$commits = grep(/$pattern/, @lines); # of commits
@signatures = grep(/^[ \t]*${signature_pattern}.*\@.*$/, @lines);
return (0, @signatures) if !@signatures;
save_commits_by_author(@lines) if ($interactive);
save_commits_by_signer(@lines) if ($interactive);
if (!$email_git_penguin_chiefs) {
@signatures = grep(!/${penguin_chiefs}/i, @signatures);
}
my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
return ($commits, @$signers_ref);
}
sub vcs_find_author {
my ($cmd) = @_;
my @lines = ();
@lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
if (!$email_git_penguin_chiefs) {
@lines = grep(!/${penguin_chiefs}/i, @lines);
}
return @lines if !@lines;
my @authors = ();
foreach my $line (@lines) {
if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
my $author = $1;
my ($name, $address) = parse_email($author);
$author = format_email($name, $address, 1);
push(@authors, $author);
}
}
save_commits_by_author(@lines) if ($interactive);
save_commits_by_signer(@lines) if ($interactive);
return @authors;
}
sub vcs_save_commits {
my ($cmd) = @_;
my @lines = ();
my @commits = ();
@lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
foreach my $line (@lines) {
if ($line =~ m/$VCS_cmds{"blame_commit_pattern"}/) {
push(@commits, $1);
}
}
return @commits;
}
sub vcs_blame {
my ($file) = @_;
my $cmd;
my @commits = ();
return @commits if (!(-f $file));
if (@range && $VCS_cmds{"blame_range_cmd"} eq "") {
my @all_commits = ();
$cmd = $VCS_cmds{"blame_file_cmd"};
$cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
@all_commits = vcs_save_commits($cmd);
foreach my $file_range_diff (@range) {
next if (!($file_range_diff =~ m/(.+):(.+):(.+)/));
my $diff_file = $1;
my $diff_start = $2;
my $diff_length = $3;
next if ("$file" ne "$diff_file");
for (my $i = $diff_start; $i < $diff_start + $diff_length; $i++) {
push(@commits, $all_commits[$i]);
}
}
} elsif (@range) {
foreach my $file_range_diff (@range) {
next if (!($file_range_diff =~ m/(.+):(.+):(.+)/));
my $diff_file = $1;
my $diff_start = $2;
my $diff_length = $3;
next if ("$file" ne "$diff_file");
$cmd = $VCS_cmds{"blame_range_cmd"};
$cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
push(@commits, vcs_save_commits($cmd));
}
} else {
$cmd = $VCS_cmds{"blame_file_cmd"};
$cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
@commits = vcs_save_commits($cmd);
}
foreach my $commit (@commits) {
$commit =~ s/^\^//g;
}
return @commits;
}
my $printed_novcs = 0;
sub vcs_exists {
%VCS_cmds = %VCS_cmds_git;
return 1 if eval $VCS_cmds{"available"};
%VCS_cmds = %VCS_cmds_hg;
return 2 if eval $VCS_cmds{"available"};
%VCS_cmds = ();
if (!$printed_novcs) {
warn("$P: No supported VCS found. Add --nogit to options?\n");
warn("Using a git repository produces better results.\n");
warn("Try Linus Torvalds' latest git repository using:\n");
warn("git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git\n");
$printed_novcs = 1;
}
return 0;
}
sub vcs_is_git {
vcs_exists();
return $vcs_used == 1;
}
sub vcs_is_hg {
return $vcs_used == 2;
}
sub interactive_get_maintainers {
my ($list_ref) = @_;
my @list = @$list_ref;
vcs_exists();
my %selected;
my %authored;
my %signed;
my $count = 0;
my $maintained = 0;
foreach my $entry (@list) {
$maintained = 1 if ($entry->[1] =~ /^(maintainer|supporter)/i);
$selected{$count} = 1;
$authored{$count} = 0;
$signed{$count} = 0;
$count++;
}
#menu loop
my $done = 0;
my $print_options = 0;
my $redraw = 1;
while (!$done) {
$count = 0;
if ($redraw) {
printf STDERR "\n%1s %2s %-65s",
"*", "#", "email/list and role:stats";
if ($email_git ||
($email_git_fallback && !$maintained) ||
$email_git_blame) {
print STDERR "auth sign";
}
print STDERR "\n";
foreach my $entry (@list) {
my $email = $entry->[0];
my $role = $entry->[1];
my $sel = "";
$sel = "*" if ($selected{$count});
my $commit_author = $commit_author_hash{$email};
my $commit_signer = $commit_signer_hash{$email};
my $authored = 0;
my $signed = 0;
$authored++ for (@{$commit_author});
$signed++ for (@{$commit_signer});
printf STDERR "%1s %2d %-65s", $sel, $count + 1, $email;
printf STDERR "%4d %4d", $authored, $signed
if ($authored > 0 || $signed > 0);
printf STDERR "\n %s\n", $role;
if ($authored{$count}) {
my $commit_author = $commit_author_hash{$email};
foreach my $ref (@{$commit_author}) {
print STDERR " Author: @{$ref}[1]\n";
}
}
if ($signed{$count}) {
my $commit_signer = $commit_signer_hash{$email};
foreach my $ref (@{$commit_signer}) {
print STDERR " @{$ref}[2]: @{$ref}[1]\n";
}
}
$count++;
}
}
my $date_ref = \$email_git_since;
$date_ref = \$email_hg_since if (vcs_is_hg());
if ($print_options) {
$print_options = 0;
if (vcs_exists()) {
print STDERR <<EOT
Version Control options:
g use git history [$email_git]
gf use git-fallback [$email_git_fallback]
b use git blame [$email_git_blame]
bs use blame signatures [$email_git_blame_signatures]
c# minimum commits [$email_git_min_signatures]
%# min percent [$email_git_min_percent]
d# history to use [$$date_ref]
x# max maintainers [$email_git_max_maintainers]
t all signature types [$email_git_all_signature_types]
m use .mailmap [$email_use_mailmap]
EOT
}
print STDERR <<EOT
Additional options:
0 toggle all
tm toggle maintainers
tg toggle git entries
tl toggle open list entries
ts toggle subscriber list entries
f emails in file [$file_emails]
k keywords in file [$keywords]
r remove duplicates [$email_remove_duplicates]
p# pattern match depth [$pattern_depth]
EOT
}
print STDERR
"\n#(toggle), A#(author), S#(signed) *(all), ^(none), O(options), Y(approve): ";
my $input = <STDIN>;
chomp($input);
$redraw = 1;
my $rerun = 0;
my @wish = split(/[, ]+/, $input);
foreach my $nr (@wish) {
$nr = lc($nr);
my $sel = substr($nr, 0, 1);
my $str = substr($nr, 1);
my $val = 0;
$val = $1 if $str =~ /^(\d+)$/;
if ($sel eq "y") {
$interactive = 0;
$done = 1;
$output_rolestats = 0;
$output_roles = 0;
last;
} elsif ($nr =~ /^\d+$/ && $nr > 0 && $nr <= $count) {
$selected{$nr - 1} = !$selected{$nr - 1};
} elsif ($sel eq "*" || $sel eq '^') {
my $toggle = 0;
$toggle = 1 if ($sel eq '*');
for (my $i = 0; $i < $count; $i++) {
$selected{$i} = $toggle;
}
} elsif ($sel eq "0") {
for (my $i = 0; $i < $count; $i++) {
$selected{$i} = !$selected{$i};
}
} elsif ($sel eq "t") {
if (lc($str) eq "m") {
for (my $i = 0; $i < $count; $i++) {
$selected{$i} = !$selected{$i}
if ($list[$i]->[1] =~ /^(maintainer|supporter)/i);
}
} elsif (lc($str) eq "g") {
for (my $i = 0; $i < $count; $i++) {
$selected{$i} = !$selected{$i}
if ($list[$i]->[1] =~ /^(author|commit|signer)/i);
}
} elsif (lc($str) eq "l") {
for (my $i = 0; $i < $count; $i++) {
$selected{$i} = !$selected{$i}
if ($list[$i]->[1] =~ /^(open list)/i);
}
} elsif (lc($str) eq "s") {
for (my $i = 0; $i < $count; $i++) {
$selected{$i} = !$selected{$i}
if ($list[$i]->[1] =~ /^(subscriber list)/i);
}
}
} elsif ($sel eq "a") {
if ($val > 0 && $val <= $count) {
$authored{$val - 1} = !$authored{$val - 1};
} elsif ($str eq '*' || $str eq '^') {
my $toggle = 0;
$toggle = 1 if ($str eq '*');
for (my $i = 0; $i < $count; $i++) {
$authored{$i} = $toggle;
}
}
} elsif ($sel eq "s") {
if ($val > 0 && $val <= $count) {
$signed{$val - 1} = !$signed{$val - 1};
} elsif ($str eq '*' || $str eq '^') {
my $toggle = 0;
$toggle = 1 if ($str eq '*');
for (my $i = 0; $i < $count; $i++) {
$signed{$i} = $toggle;
}
}
} elsif ($sel eq "o") {
$print_options = 1;
$redraw = 1;
} elsif ($sel eq "g") {
if ($str eq "f") {
bool_invert(\$email_git_fallback);
} else {
bool_invert(\$email_git);
}
$rerun = 1;
} elsif ($sel eq "b") {
if ($str eq "s") {
bool_invert(\$email_git_blame_signatures);
} else {
bool_invert(\$email_git_blame);
}
$rerun = 1;
} elsif ($sel eq "c") {
if ($val > 0) {
$email_git_min_signatures = $val;
$rerun = 1;
}
} elsif ($sel eq "x") {
if ($val > 0) {
$email_git_max_maintainers = $val;
$rerun = 1;
}
} elsif ($sel eq "%") {
if ($str ne "" && $val >= 0) {
$email_git_min_percent = $val;
$rerun = 1;
}
} elsif ($sel eq "d") {
if (vcs_is_git()) {
$email_git_since = $str;
} elsif (vcs_is_hg()) {
$email_hg_since = $str;
}
$rerun = 1;
} elsif ($sel eq "t") {
bool_invert(\$email_git_all_signature_types);
$rerun = 1;
} elsif ($sel eq "f") {
bool_invert(\$file_emails);
$rerun = 1;
} elsif ($sel eq "r") {
bool_invert(\$email_remove_duplicates);
$rerun = 1;
} elsif ($sel eq "m") {
bool_invert(\$email_use_mailmap);
read_mailmap();
$rerun = 1;
} elsif ($sel eq "k") {
bool_invert(\$keywords);
$rerun = 1;
} elsif ($sel eq "p") {
if ($str ne "" && $val >= 0) {
$pattern_depth = $val;
$rerun = 1;
}
} elsif ($sel eq "h" || $sel eq "?") {
print STDERR <<EOT
Interactive mode allows you to select the various maintainers, submitters,
commit signers and mailing lists that could be CC'd on a patch.
Any *'d entry is selected.
If you have git or hg installed, you can choose to summarize the commit
history of files in the patch. Also, each line of the current file can
be matched to its commit author and that commits signers with blame.
Various knobs exist to control the length of time for active commit
tracking, the maximum number of commit authors and signers to add,
and such.
Enter selections@the prompt until you are satisfied that the selected
maintainers are appropriate. You may enter multiple selections separated
by either commas or spaces.
EOT
} else {
print STDERR "invalid option: '$nr'\n";
$redraw = 0;
}
}
if ($rerun) {
print STDERR "git-blame can be very slow, please have patience..."
if ($email_git_blame);
goto &get_maintainers;
}
}
#drop not selected entries
$count = 0;
my @new_emailto = ();
foreach my $entry (@list) {
if ($selected{$count}) {
push(@new_emailto, $list[$count]);
}
$count++;
}
return @new_emailto;
}
sub bool_invert {
my ($bool_ref) = @_;
if ($$bool_ref) {
$$bool_ref = 0;
} else {
$$bool_ref = 1;
}
}
sub deduplicate_email {
my ($email) = @_;
my $matched = 0;
my ($name, $address) = parse_email($email);
$email = format_email($name, $address, 1);
$email = mailmap_email($email);
return $email if (!$email_remove_duplicates);
($name, $address) = parse_email($email);
if ($name ne "" && $deduplicate_name_hash{lc($name)}) {
$name = $deduplicate_name_hash{lc($name)}->[0];
$address = $deduplicate_name_hash{lc($name)}->[1];
$matched = 1;
} elsif ($deduplicate_address_hash{lc($address)}) {
$name = $deduplicate_address_hash{lc($address)}->[0];
$address = $deduplicate_address_hash{lc($address)}->[1];
$matched = 1;
}
if (!$matched) {
$deduplicate_name_hash{lc($name)} = [ $name, $address ];
$deduplicate_address_hash{lc($address)} = [ $name, $address ];
}
$email = format_email($name, $address, 1);
$email = mailmap_email($email);
return $email;
}
sub save_commits_by_author {
my (@lines) = @_;
my @authors = ();
my @commits = ();
my @subjects = ();
foreach my $line (@lines) {
if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
my $author = $1;
$author = deduplicate_email($author);
push(@authors, $author);
}
push(@commits, $1) if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
push(@subjects, $1) if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
}
for (my $i = 0; $i < @authors; $i++) {
my $exists = 0;
foreach my $ref(@{$commit_author_hash{$authors[$i]}}) {
if (@{$ref}[0] eq $commits[$i] &&
@{$ref}[1] eq $subjects[$i]) {
$exists = 1;
last;
}
}
if (!$exists) {
push(@{$commit_author_hash{$authors[$i]}},
[ ($commits[$i], $subjects[$i]) ]);
}
}
}
sub save_commits_by_signer {
my (@lines) = @_;
my $commit = "";
my $subject = "";
foreach my $line (@lines) {
$commit = $1 if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
$subject = $1 if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
if ($line =~ /^[ \t]*${signature_pattern}.*\@.*$/) {
my @signatures = ($line);
my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
my @types = @$types_ref;
my @signers = @$signers_ref;
my $type = $types[0];
my $signer = $signers[0];
$signer = deduplicate_email($signer);
my $exists = 0;
foreach my $ref(@{$commit_signer_hash{$signer}}) {
if (@{$ref}[0] eq $commit &&
@{$ref}[1] eq $subject &&
@{$ref}[2] eq $type) {
$exists = 1;
last;
}
}
if (!$exists) {
push(@{$commit_signer_hash{$signer}},
[ ($commit, $subject, $type) ]);
}
}
}
}
sub vcs_assign {
my ($role, $divisor, @lines) = @_;
my %hash;
my $count = 0;
return if (@lines <= 0);
if ($divisor <= 0) {
warn("Bad divisor in " . (caller(0))[3] . ": $divisor\n");
$divisor = 1;
}
@lines = mailmap(@lines);
return if (@lines <= 0);
@lines = sort(@lines);
# uniq -c
$hash{$_}++ for @lines;
# sort -rn
foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
my $sign_offs = $hash{$line};
my $percent = $sign_offs * 100 / $divisor;
$percent = 100 if ($percent > 100);
$count++;
last if ($sign_offs < $email_git_min_signatures ||
$count > $email_git_max_maintainers ||
$percent < $email_git_min_percent);
push_email_address($line, '');
if ($output_rolestats) {
my $fmt_percent = sprintf("%.0f", $percent);
add_role($line, "$role:$sign_offs/$divisor=$fmt_percent%");
} else {
add_role($line, $role);
}
}
}
sub vcs_file_signoffs {
my ($file) = @_;
my @signers = ();
my $commits;
$vcs_used = vcs_exists();
return if (!$vcs_used);
my $cmd = $VCS_cmds{"find_signers_cmd"};
$cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd
($commits, @signers) = vcs_find_signers($cmd);
foreach my $signer (@signers) {
$signer = deduplicate_email($signer);
}
vcs_assign("commit_signer", $commits, @signers);
}
sub vcs_file_blame {
my ($file) = @_;
my @signers = ();
my @all_commits = ();
my @commits = ();
my $total_commits;
my $total_lines;
$vcs_used = vcs_exists();
return if (!$vcs_used);
@all_commits = vcs_blame($file);
@commits = uniq(@all_commits);
$total_commits = @commits;
$total_lines = @all_commits;
if ($email_git_blame_signatures) {
if (vcs_is_hg()) {
my $commit_count;
my @commit_signers = ();
my $commit = join(" -r ", @commits);
my $cmd;
$cmd = $VCS_cmds{"find_commit_signers_cmd"};
$cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
($commit_count, @commit_signers) = vcs_find_signers($cmd);
push(@signers, @commit_signers);
} else {
foreach my $commit (@commits) {
my $commit_count;
my @commit_signers = ();
my $cmd;
$cmd = $VCS_cmds{"find_commit_signers_cmd"};
$cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
($commit_count, @commit_signers) = vcs_find_signers($cmd);
push(@signers, @commit_signers);
}
}
}
if ($from_filename) {
if ($output_rolestats) {
my @blame_signers;
if (vcs_is_hg()) {{ # Double brace for last exit
my $commit_count;
my @commit_signers = ();
@commits = uniq(@commits);
@commits = sort(@commits);
my $commit = join(" -r ", @commits);
my $cmd;
$cmd = $VCS_cmds{"find_commit_author_cmd"};
$cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
my @lines = ();
@lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
if (!$email_git_penguin_chiefs) {
@lines = grep(!/${penguin_chiefs}/i, @lines);
}
last if !@lines;
my @authors = ();
foreach my $line (@lines) {
if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
my $author = $1;
$author = deduplicate_email($author);
push(@authors, $author);
}
}
save_commits_by_author(@lines) if ($interactive);
save_commits_by_signer(@lines) if ($interactive);
push(@signers, @authors);
}}
else {
foreach my $commit (@commits) {
my $i;
my $cmd = $VCS_cmds{"find_commit_author_cmd"};
$cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
my @author = vcs_find_author($cmd);
next if !@author;
my $formatted_author = deduplicate_email($author[0]);
my $count = grep(/$commit/, @all_commits);
for ($i = 0; $i < $count ; $i++) {
push(@blame_signers, $formatted_author);
}
}
}
if (@blame_signers) {
vcs_assign("authored lines", $total_lines, @blame_signers);
}
}
foreach my $signer (@signers) {
$signer = deduplicate_email($signer);
}
vcs_assign("commits", $total_commits, @signers);
} else {
foreach my $signer (@signers) {
$signer = deduplicate_email($signer);
}
vcs_assign("modified commits", $total_commits, @signers);
}
}
sub uniq {
my (@parms) = @_;
my %saw;
@parms = grep(!$saw{$_}++, @parms);
return @parms;
}
sub sort_and_uniq {
my (@parms) = @_;
my %saw;
@parms = sort @parms;
@parms = grep(!$saw{$_}++, @parms);
return @parms;
}
sub clean_file_emails {
my (@file_emails) = @_;
my @fmt_emails = ();
foreach my $email (@file_emails) {
$email =~ s/[\(\<\{]{0,1}([A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+)[\)\>\}]{0,1}/\<$1\>/g;
my ($name, $address) = parse_email($email);
if ($name eq '"[,\.]"') {
$name = "";
}
my @nw = split(/[^A-Za-z??-??\'\,\.\+-]/, $name);
if (@nw > 2) {
my $first = $nw[@nw - 3];
my $middle = $nw[@nw - 2];
my $last = $nw[@nw - 1];
if (((length($first) == 1 && $first =~ m/[A-Za-z]/) ||
(length($first) == 2 && substr($first, -1) eq ".")) ||
(length($middle) == 1 ||
(length($middle) == 2 && substr($middle, -1) eq "."))) {
$name = "$first $middle $last";
} else {
$name = "$middle $last";
}
}
if (substr($name, -1) =~ /[,\.]/) {
$name = substr($name, 0, length($name) - 1);
} elsif (substr($name, -2) =~ /[,\.]"/) {
$name = substr($name, 0, length($name) - 2) . '"';
}
if (substr($name, 0, 1) =~ /[,\.]/) {
$name = substr($name, 1, length($name) - 1);
} elsif (substr($name, 0, 2) =~ /"[,\.]/) {
$name = '"' . substr($name, 2, length($name) - 2);
}
my $fmt_email = format_email($name, $address, $email_usename);
push(@fmt_emails, $fmt_email);
}
return @fmt_emails;
}
sub merge_email {
my @lines;
my %saw;
for (@_) {
my ($address, $role) = @$_;
if (!$saw{$address}) {
if ($output_roles) {
push(@lines, "$address ($role)");
} else {
push(@lines, $address);
}
$saw{$address} = 1;
}
}
return @lines;
}
sub output {
my (@parms) = @_;
if ($output_multiline) {
foreach my $line (@parms) {
print("${line}\n");
}
} else {
print(join($output_separator, @parms));
print("\n");
}
}
my $rfc822re;
sub make_rfc822re {
# Basic lexical tokens are specials, domain_literal, quoted_string, atom, and
# comment. We must allow for rfc822_lwsp (or comments) after each of these.
# This regexp will only work on addresses which have had comments stripped
# and replaced with rfc822_lwsp.
my $specials = '()<>@,;:\\\\".\\[\\]';
my $controls = '\\000-\\037\\177';
my $dtext = "[^\\[\\]\\r\\\\]";
my $domain_literal = "\\[(?:$dtext|\\\\.)*\\]$rfc822_lwsp*";
my $quoted_string = "\"(?:[^\\\"\\r\\\\]|\\\\.|$rfc822_lwsp)*\"$rfc822_lwsp*";
# Use zero-width assertion to spot the limit of an atom. A simple
# $rfc822_lwsp* causes the regexp engine to hang occasionally.
my $atom = "[^$specials $controls]+(?:$rfc822_lwsp+|\\Z|(?=[\\[\"$specials]))";
my $word = "(?:$atom|$quoted_string)";
my $localpart = "$word(?:\\.$rfc822_lwsp*$word)*";
my $sub_domain = "(?:$atom|$domain_literal)";
my $domain = "$sub_domain(?:\\.$rfc822_lwsp*$sub_domain)*";
my $addr_spec = "$localpart\@$rfc822_lwsp*$domain";
my $phrase = "$word*";
my $route = "(?:\@$domain(?:,\@$rfc822_lwsp*$domain)*:$rfc822_lwsp*)";
my $route_addr = "\\<$rfc822_lwsp*$route?$addr_spec\\>$rfc822_lwsp*";
my $mailbox = "(?:$addr_spec|$phrase$route_addr)";
my $group = "$phrase:$rfc822_lwsp*(?:$mailbox(?:,\\s*$mailbox)*)?;\\s*";
my $address = "(?:$mailbox|$group)";
return "$rfc822_lwsp*$address";
}
sub rfc822_strip_comments {
my $s = shift;
# Recursively remove comments, and replace with a single space. The simpler
# regexps in the Email Addressing FAQ are imperfect - they will miss escaped
# chars in atoms, for example.
while ($s =~ s/^((?:[^"\\]|\\.)*
(?:"(?:[^"\\]|\\.)*"(?:[^"\\]|\\.)*)*)
\((?:[^()\\]|\\.)*\)/$1 /osx) {}
return $s;
}
# valid: returns true if the parameter is an RFC822 valid address
#
sub rfc822_valid {
my $s = rfc822_strip_comments(shift);
if (!$rfc822re) {
$rfc822re = make_rfc822re();
}
return $s =~ m/^$rfc822re$/so && $s =~ m/^$rfc822_char*$/;
}
# validlist: In scalar context, returns true if the parameter is an RFC822
# valid list of addresses.
#
# In list context, returns an empty list on failure (an invalid
# address was found); otherwise a list whose first element is the
# number of addresses found and whose remaining elements are the
# addresses. This is needed to disambiguate failure (invalid)
# from success with no addresses found, because an empty string is
# a valid list.
sub rfc822_validlist {
my $s = rfc822_strip_comments(shift);
if (!$rfc822re) {
$rfc822re = make_rfc822re();
}
# * null list items are valid according to the RFC
# * the '1' business is to aid in distinguishing failure from no results
my @r;
if ($s =~ m/^(?:$rfc822re)?(?:,(?:$rfc822re)?)*$/so &&
$s =~ m/^$rfc822_char*$/) {
while ($s =~ m/(?:^|,$rfc822_lwsp*)($rfc822re)/gos) {
push(@r, $1);
}
return wantarray ? (scalar(@r), @r) : 1;
}
return wantarray ? () : 0;
}
^ permalink raw reply
* [PATCH-V2 0/4] ARM: AM33XX: net: Add DT support to CPGMAC and MDIO driver
From: Vaibhav Hiremath @ 2012-10-29 8:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351498881-32482-1-git-send-email-hvaibhav@ti.com>
This patch-series adds support for,
[1/4]: Typo mistake in CPSW driver while invoking runtime_pm api's
[2/4]: Adds parent<->child relation between CPSW & MDIO module inside cpsw
driver, as in case of AM33XX, the resources are shared and common
register bit-field is provided to control module/clock enable/disable,
makes it difficult to handle common resource.
So the solution here is, to create parent<->child relation between them.
[3/4]: Add hwmod entry for MDIO module, required for MDIO driver.
[4/4]: Add DT device nodes for both CPSW and MDIO modules in am33xx.dtsi,
am335x-evm.dts and am335x-bone.dts file
This patch series has been created on top of linux-omap/master and tested
on both AM335x-EVM and BeagleBone platforms for NFS boot and basic ping
test cases.
All the patches are also available at,
git at github.com:hvaibhav/am335x-linux.git am335x-upstream-staging-cpsw
Mugunthan V N (2):
ARM: OMAP3+: hwmod: Add AM33XX HWMOD data for davinci_mdio module
arm/dts: am33xx: Add CPSW and MDIO module nodes for AM33XX
Vaibhav Hiremath (2):
net: davinci_mdio: Fix typo mistake in calling runtime-pm api
net: cpsw: Add parent<->child relation support between cpsw and mdio
arch/arm/boot/dts/am335x-bone.dts | 8 ++++
arch/arm/boot/dts/am335x-evm.dts | 8 ++++
arch/arm/boot/dts/am33xx.dtsi | 50 ++++++++++++++++++++++++++++
arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 32 ++++++++++++++++++
drivers/net/ethernet/ti/cpsw.c | 16 ++++++++-
drivers/net/ethernet/ti/davinci_mdio.c | 2 +-
6 files changed, 113 insertions(+), 3 deletions(-)
^ permalink raw reply
* [PATCH 1/4] net: davinci_mdio: Fix typo mistake in calling runtime-pm api
From: Vaibhav Hiremath @ 2012-10-29 8:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351498881-32482-1-git-send-email-hvaibhav@ti.com>
By mistake (most likely a copy-paste), instead of pm_runtime_get_sync()
api, driver is calling pm_runtime_put_sync() api in resume callback
function. The bug was introduced by commit id (ae2c07aaf74:
davinci_mdio: runtime PM support).
Now, the reason why it didn't impact functionality is, the patch has
been tested on AM335x-EVM and BeagleBone platform while submitting;
and in case of AM335x the MDIO driver doesn't control the module
enable/disable part, which is handled by CPSW driver.
Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
Cc: Mugunthan V N <mugunthanvnm@ti.com>
Cc: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/ethernet/ti/davinci_mdio.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index 51a96db..ae74280 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -465,7 +465,7 @@ static int davinci_mdio_resume(struct device *dev)
u32 ctrl;
spin_lock(&data->lock);
- pm_runtime_put_sync(data->dev);
+ pm_runtime_get_sync(data->dev);
/* restart the scan state machine */
ctrl = __raw_readl(&data->regs->control);
--
1.7.0.4
^ permalink raw reply related
* [PATCH 2/4] net: cpsw: Add parent<->child relation support between cpsw and mdio
From: Vaibhav Hiremath @ 2012-10-29 8:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351498881-32482-1-git-send-email-hvaibhav@ti.com>
CPGMAC SubSystem consist of various sub-modules, like, mdio, cpdma,
cpsw, etc... These sub-modules are also used in some of Davinci family
of devices. Now based on requirement, use-case and available technology
nodes the integration of these sub-modules varies across devices.
So coming back to Linux net driver, currently separate and independent
platform devices & drivers for CPSW and MDIO is implemented. In case of
Davinci they both has separate control, from resources perspective,
like clock.
In case of AM33XX, the resources are shared and only one register
bit-field is provided to control module/clock enable/disable, makes it
difficult to handle common resource.
So the solution here implemented in this patch is,
Create parent<->child relationship between both the drivers, making
CPSW as a parent and MDIO as its child and enumerate all the child nodes
under CPSW module.
Both the drivers will function exactly the way it was operating before,
including runtime-pm functionality. No change is required in MDIO driver
(for that matter to any child driver).
As this is only supported during DT boot, the parent<->child relationship
is created and populated in DT execution flow. The only required change
is inside DTS file, making MDIO as a child to CPSW node.
Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
Cc: Mugunthan V N <mugunthanvnm@ti.com>
Cc: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/ethernet/ti/cpsw.c | 16 ++++++++++++++--
1 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index df55e24..fb1a692 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -827,7 +827,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->mac_control = prop;
- for_each_child_of_node(node, slave_node) {
+ for_each_node_by_name(slave_node, "slave") {
struct cpsw_slave_data *slave_data = data->slave_data + i;
const char *phy_id = NULL;
const void *mac_addr = NULL;
@@ -862,6 +862,14 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
i++;
}
+ /*
+ * Populate all the child nodes here...
+ */
+ ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
+ /* We do not want to force this, as in some cases may not have child */
+ if (ret)
+ pr_warn("Doesn't have any child node\n");
+
return 0;
error_ret:
@@ -895,6 +903,11 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
priv->rx_packet_max = max(rx_packet_max, 128);
+ /*
+ * This may be required here for child devices.
+ */
+ pm_runtime_enable(&pdev->dev);
+
if (cpsw_probe_dt(&priv->data, pdev)) {
pr_err("cpsw: platform data missing\n");
ret = -ENODEV;
@@ -921,7 +934,6 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
for (i = 0; i < data->slaves; i++)
priv->slaves[i].slave_num = i;
- pm_runtime_enable(&pdev->dev);
priv->clk = clk_get(&pdev->dev, "fck");
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "fck is not found\n");
--
1.7.0.4
^ permalink raw reply related
* [PATCH 3/4] ARM: OMAP3+: hwmod: Add AM33XX HWMOD data for davinci_mdio module
From: Vaibhav Hiremath @ 2012-10-29 8:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351498881-32482-1-git-send-email-hvaibhav@ti.com>
From: Mugunthan V N <mugunthanvnm@ti.com>
This patch adds hwmod entry for davinci MDIO module,
creating parent<->child relationship between CPSW and MDIO module.
This Parent-child relation is required in order to use common resources
like, clock, but still maintaining the logical separation between them.
CPGMAC SubSystem consist of various sub-modules, like, mdio, cpdma,
cpsw, etc... These sub-modules are also used in some of Davinci
family of devices, so separate and independent platform devices &
drivers for CPSW and MDIO is implemented.
In case of AM33XX, the resources are shared and common register
bit-field is provided to control module/clock enable/disable,
makes it difficult to handle common resources from both drivers.
So the solution is, create parent<->child relationship between
CPGMAC & MDIO modules.
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Paul Walmsley <paul@pwsan.com>
---
arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 32 ++++++++++++++++++++++++++++
1 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
index ad8d43b..3c235d8 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
@@ -674,6 +674,7 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = {
.name = "cpgmac0",
.class = &am33xx_cpgmac0_hwmod_class,
.clkdm_name = "cpsw_125mhz_clkdm",
+ .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
.mpu_irqs = am33xx_cpgmac0_irqs,
.main_clk = "cpsw_125mhz_gclk",
.prcm = {
@@ -685,6 +686,20 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = {
};
/*
+ * mdio class
+ */
+static struct omap_hwmod_class am33xx_mdio_hwmod_class = {
+ .name = "davinci_mdio",
+};
+
+static struct omap_hwmod am33xx_mdio_hwmod = {
+ .name = "davinci_mdio",
+ .class = &am33xx_mdio_hwmod_class,
+ .clkdm_name = "cpsw_125mhz_clkdm",
+ .main_clk = "cpsw_125mhz_gclk",
+};
+
+/*
* dcan class
*/
static struct omap_hwmod_class am33xx_dcan_hwmod_class = {
@@ -2501,6 +2516,22 @@ static struct omap_hwmod_ocp_if am33xx_l4_hs__cpgmac0 = {
.user = OCP_USER_MPU,
};
+struct omap_hwmod_addr_space am33xx_mdio_addr_space[] = {
+ {
+ .pa_start = 0x4A101000,
+ .pa_end = 0x4A101000 + SZ_256 - 1,
+ .flags = ADDR_MAP_ON_INIT,
+ },
+ { }
+};
+
+struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio = {
+ .master = &am33xx_cpgmac0_hwmod,
+ .slave = &am33xx_mdio_hwmod,
+ .addr = am33xx_mdio_addr_space,
+ .user = OCP_USER_MPU,
+};
+
static struct omap_hwmod_addr_space am33xx_elm_addr_space[] = {
{
.pa_start = 0x48080000,
@@ -3371,6 +3402,7 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
&am33xx_l3_main__tptc2,
&am33xx_l3_s__usbss,
&am33xx_l4_hs__cpgmac0,
+ &am33xx_cpgmac0__mdio,
NULL,
};
--
1.7.0.4
^ permalink raw reply related
* [PATCH 4/4] arm/dts: am33xx: Add CPSW and MDIO module nodes for AM33XX
From: Vaibhav Hiremath @ 2012-10-29 8:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351498881-32482-1-git-send-email-hvaibhav@ti.com>
From: Mugunthan V N <mugunthanvnm@ti.com>
Add CPSW and MDIO related device tree data for AM33XX.
Also enable them into board/evm dts files by providing
respective phy-id.
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
arch/arm/boot/dts/am335x-bone.dts | 8 ++++++
arch/arm/boot/dts/am335x-evm.dts | 8 ++++++
arch/arm/boot/dts/am33xx.dtsi | 50 +++++++++++++++++++++++++++++++++++++
3 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
index c634f87..e233cfa 100644
--- a/arch/arm/boot/dts/am335x-bone.dts
+++ b/arch/arm/boot/dts/am335x-bone.dts
@@ -78,3 +78,11 @@
};
};
};
+
+&cpsw_emac0 {
+ phy_id = "4a101000.mdio:00";
+};
+
+&cpsw_emac1 {
+ phy_id = "4a101000.mdio:01";
+};
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index 185d632..415c3b3 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -118,3 +118,11 @@
};
};
};
+
+&cpsw_emac0 {
+ phy_id = "4a101000.mdio:00";
+};
+
+&cpsw_emac1 {
+ phy_id = "4a101000.mdio:01";
+};
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index bb31bff..f6bea04 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -210,5 +210,55 @@
interrupt-parent = <&intc>;
interrupts = <91>;
};
+
+ mac: ethernet at 4A100000 {
+ compatible = "ti,cpsw";
+ ti,hwmods = "cpgmac0";
+ cpdma_channels = <8>;
+ host_port_no = <0>;
+ cpdma_reg_ofs = <0x800>;
+ cpdma_sram_ofs = <0xa00>;
+ ale_reg_ofs = <0xd00>;
+ ale_entries = <1024>;
+ host_port_reg_ofs = <0x108>;
+ hw_stats_reg_ofs = <0x900>;
+ bd_ram_ofs = <0x2000>;
+ bd_ram_size = <0x2000>;
+ no_bd_ram = <0>;
+ rx_descs = <64>;
+ mac_control = <0x20>;
+ slaves = <2>;
+ reg = <0x4a100000 0x800
+ 0x4a101200 0x100
+ 0x4a101000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+ /* c0_rx_thresh_pend c0_rx_pend c0_tx_pend c0_misc_pend*/
+ interrupts = <40 41 42 43>;
+ ranges;
+ cpsw_emac0: slave at 0 {
+ slave_reg_ofs = <0x208>;
+ sliver_reg_ofs = <0xd80>;
+ /* Filled in by U-Boot */
+ mac-address = [ 00 00 00 00 00 00 ];
+ };
+ cpsw_emac1: slave at 1 {
+ slave_reg_ofs = <0x308>;
+ sliver_reg_ofs = <0xdc0>;
+ /* Filled in by U-Boot */
+ mac-address = [ 00 00 00 00 00 00 ];
+ };
+
+ davinci_mdio: mdio at 4a101000 {
+ compatible = "ti,davinci_mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ti,hwmods = "davinci_mdio";
+ bus_freq = <1000000>;
+ reg = <0x4a101000 0x100>;
+ };
+
+ };
};
};
--
1.7.0.4
^ permalink raw reply related
* Fwd: [PATCH 2/5] ARM: OMAP3+: hwmod: Add AM33XX HWMOD data for davinci_mdio
From: Hiremath, Vaibhav @ 2012-10-29 8:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121029075003.GA2527@netboy.at.omicron.at>
On Mon, Oct 29, 2012 at 13:20:03, Richard Cochran wrote:
> On Mon, Oct 29, 2012 at 04:58:23AM +0000, Hiremath, Vaibhav wrote:
> >
> > Now the expectation has grown to the level where people expect everything in
> > the Mainline kernel and not in some custom kernel release.
>
> You are right, except for the "has grown" part. I have always expected
> the official kernel releases to be working and complete, without the
> kind of half baked stumps that the embedded vendors are pushing.
>
> In my experience with Freescale (and now TI also), the vendor supports
> Linux on their platform by providing a heavily patched, quick and
> dirty, customized kernel that is kinda, sorta working, somehow. This
> provides a way for their customers to get started with the development
> kits right away, and as such I have no problem with it.
>
> What I do have a problem with is the fact the vendors then drop the
> ball and don't follow through by getting their changes into
> mainline. This makes a huge problem for the vendor's customers later
> on, when the choice becomes either stay with the dead end vendor
> kernel, or try to get mainline working all by themselves.
>
I completely understand and I can only say that, we have learned our lessons
long time back on this and we now try to push all our code to Mainline.
Even with TI release kernel we try to stay closer to mainline, so that later
it would be easier to submit the patches to mainline.
For example, in some cases we have back-ported some of the framework changes
to v3.2 kernel to stay closer to mainline.
> And so I am pleased to hear that the Ethernet ports on the am335x will
> be working in v3.8. Better late than never.
>
Just submitted patches to the list, care to ack them.
Thanks,
Vaibhav
^ permalink raw reply
* [PULL REQ] IXP4xx changes for Linux 3.7
From: Richard Cochran @ 2012-10-29 8:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <m3a9vkahci.fsf@intrepid.localdomain>
On Thu, Oct 18, 2012 at 12:01:17AM +0200, Krzysztof Halasa wrote:
>
> Don't get me wrong. If I had time for this it could be different.
> Unfortunately IXP4xx is a legacy arch, and for me it's simply a hobby at
> this point. Given the raised barriers to participate, probably aimed at
> paid maintainers, I have to quit doing this.
>
> BTW since Imre has probably even much less time, it would be a good time
> to find someone to maintain IXP4xx code. I will be publishing (from time
> to time) my tree (I'm using the hw myself), so even simple
> cherry-picking would probably make some sense.
So if no one else wants to do this, then I am willing to look after
the IXP code. I think that I do have the time for it.
Thanks,
Richard
^ permalink raw reply
* [PATCH-V2 0/4] ARM: AM33XX: net: Add DT support to CPGMAC and MDIO driver
From: Richard Cochran @ 2012-10-29 8:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351498881-32482-2-git-send-email-hvaibhav@ti.com>
On Mon, Oct 29, 2012 at 01:51:17PM +0530, Vaibhav Hiremath wrote:
> This patch-series adds support for,
>
> [1/4]: Typo mistake in CPSW driver while invoking runtime_pm api's
>
> [2/4]: Adds parent<->child relation between CPSW & MDIO module inside cpsw
> driver, as in case of AM33XX, the resources are shared and common
> register bit-field is provided to control module/clock enable/disable,
> makes it difficult to handle common resource.
>
> So the solution here is, to create parent<->child relation between them.
>
> [3/4]: Add hwmod entry for MDIO module, required for MDIO driver.
>
> [4/4]: Add DT device nodes for both CPSW and MDIO modules in am33xx.dtsi,
> am335x-evm.dts and am335x-bone.dts file
Many Thanks!
Acked-by: Richard Cochran <richardcochran@gmail.com>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox