* [PATCH v6 03/10] ARM: edma: add AM33XX support to the private EDMA API
From: Matt Porter @ 2013-01-31 18:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201301300932.58732.arnd@arndb.de>
On Wed, Jan 30, 2013 at 09:32:58AM +0000, Arnd Bergmann wrote:
> On Wednesday 30 January 2013, Matt Porter wrote:
> > + dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap);
> > + of_dma_controller_register(dev->of_node,
> > + of_dma_simple_xlate,
> > + &edma_filter_info);
> > + }
>
> How do you actually deal with the problem mentioned by Padma, that
> the filter function does not know which edma instance it is looking
> at? If you assume that there can only be a single edma instance in
> the system, that is probably a limitation that should be documented
> somewhere, and ideally the probe() function should check for that.
I make an assumption of one edma instance in the system in the case of
DT being populated. This is always true right now as the only SoC with
two EDMA controllers in existence is Davinci DA850. Until recently,
Davinci had no DT support. Given the steady work being done today on DT
support for DA850, it'll probably be something needed in 3.10.
I will add a comment and check in probe() to capture this assumption
and then plan to update separately to support DA850 booting from DT.
-Matt
^ permalink raw reply
* [PATCH, RFC] default machine descriptor for multiplatform
From: Stephen Warren @ 2013-01-31 18:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1638002.UJ7zfj1Wn5@wuerfel>
On 01/31/2013 10:51 AM, Arnd Bergmann wrote:
> This is what I think it would look like to do a default platform
> with an empty machine descriptor on ARM. It makes the few required
> entries in the descriptor optional by using the new irqchip_init()
> and clocksource_of_init() functions as defaults, and adds
> a fallback for the DT case to customize_machine to probe all
> the default devices.
>
> For the case that CONFIG_MULTIPLATFORM is enabled, it then
> adds a machine descriptor that never matches any machine but
> is used as a fallback if nothing else matches.
> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
> static int __init customize_machine(void)
> {
> - /* customizes platform devices, or adds new ones */
> + /*
> + * customizes platform devices, or adds new ones
> + * On DT based machines, we fall back to populating the
> + * machine from the device tree, if no callback is provided,
> + * otherwise we would always need an init_machine callback.
> + */
> if (machine_desc->init_machine)
> machine_desc->init_machine();
> + else
> + of_platform_populate(NULL, of_default_bus_match_table,
> + NULL, NULL);
With that change, we can remove the custom .init_machine() functions for
all of Tegra, since they just do that:-)
> diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c
> +#ifdef CONFIG_IRQCHIP
> void __init irqchip_init(void)
> {
> of_irq_init(__irqchip_begin);
> }
> +#else
> +static inline void irqchip_init(void)
> +{
> +}
> +#endif
That'd need to go in a header file.
^ permalink raw reply
* [PATCH] power/reset: restart: remove __dev{init,exit}
From: Jason Cooper @ 2013-01-31 18:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130106220426.GE26928@lizard.sbx05280.losalca.wayport.net>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
---
drivers/power/reset/restart-poweroff.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/power/reset/restart-poweroff.c b/drivers/power/reset/restart-poweroff.c
index b11b9e8..059cd15 100644
--- a/drivers/power/reset/restart-poweroff.c
+++ b/drivers/power/reset/restart-poweroff.c
@@ -22,7 +22,7 @@ static void restart_poweroff_do_poweroff(void)
arm_pm_restart('h', NULL);
}
-static int __devinit restart_poweroff_probe(struct platform_device *pdev)
+static int restart_poweroff_probe(struct platform_device *pdev)
{
/* If a pm_power_off function has already been added, leave it alone */
if (pm_power_off != NULL) {
@@ -35,7 +35,7 @@ static int __devinit restart_poweroff_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit restart_poweroff_remove(struct platform_device *pdev)
+static int restart_poweroff_remove(struct platform_device *pdev)
{
if (pm_power_off == &restart_poweroff_do_poweroff)
pm_power_off = NULL;
@@ -50,7 +50,7 @@ static const struct of_device_id of_restart_poweroff_match[] = {
static struct platform_driver restart_poweroff_driver = {
.probe = restart_poweroff_probe,
- .remove = __devexit_p(restart_poweroff_remove),
+ .remove = restart_poweroff_remove,
.driver = {
.name = "poweroff-restart",
.owner = THIS_MODULE,
--
1.8.1.1
^ permalink raw reply related
* [PATCH] power/reset: restart: remove __dev{init,exit}
From: Jason Cooper @ 2013-01-31 18:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359658469-14856-1-git-send-email-jason@lakedaemon.net>
Anton,
I forgot to mention, this fixes a build breakage on battery/master.
thx,
Jason.
On Thu, Jan 31, 2013 at 06:54:29PM +0000, Jason Cooper wrote:
> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
> ---
> drivers/power/reset/restart-poweroff.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/power/reset/restart-poweroff.c b/drivers/power/reset/restart-poweroff.c
> index b11b9e8..059cd15 100644
> --- a/drivers/power/reset/restart-poweroff.c
> +++ b/drivers/power/reset/restart-poweroff.c
> @@ -22,7 +22,7 @@ static void restart_poweroff_do_poweroff(void)
> arm_pm_restart('h', NULL);
> }
>
> -static int __devinit restart_poweroff_probe(struct platform_device *pdev)
> +static int restart_poweroff_probe(struct platform_device *pdev)
> {
> /* If a pm_power_off function has already been added, leave it alone */
> if (pm_power_off != NULL) {
> @@ -35,7 +35,7 @@ static int __devinit restart_poweroff_probe(struct platform_device *pdev)
> return 0;
> }
>
> -static int __devexit restart_poweroff_remove(struct platform_device *pdev)
> +static int restart_poweroff_remove(struct platform_device *pdev)
> {
> if (pm_power_off == &restart_poweroff_do_poweroff)
> pm_power_off = NULL;
> @@ -50,7 +50,7 @@ static const struct of_device_id of_restart_poweroff_match[] = {
>
> static struct platform_driver restart_poweroff_driver = {
> .probe = restart_poweroff_probe,
> - .remove = __devexit_p(restart_poweroff_remove),
> + .remove = restart_poweroff_remove,
> .driver = {
> .name = "poweroff-restart",
> .owner = THIS_MODULE,
> --
> 1.8.1.1
>
^ permalink raw reply
* [PATCH v3 0/2] Add CPSW VLAN Support
From: Mugunthan V N @ 2013-01-31 19:03 UTC (permalink / raw)
To: linux-arm-kernel
CPSW is capable of filtering VLAN packets in hardware. This patch series
implements VLAN support to CPSW driver.
This patch series is tested on net-next with AM335x EVM with ping test.
Changes from initial version
* added vlan support to existing add/delete unicast/multicast apis
* Made driver as default VLAN enabled so that drivers need to be recompiled
when stack is compiled with VLAN
Changes from V2
* Moved repeated code to static inline function
* Made vlan add/delete function return type to void as it is not used in
the current driver implementation
* Modified cpsw_add_default_vlan for better readability
* changed BIT(1) port representation to defines
Mugunthan V N (2):
drivers: net: cpsw: Add helper functions for VLAN ALE implementation
drivers: net:ethernet: cpsw: add support for VLAN
Documentation/devicetree/bindings/net/cpsw.txt | 2 +
drivers/net/ethernet/ti/cpsw.c | 93 +++++++++++++++++++--
drivers/net/ethernet/ti/cpsw_ale.c | 105 +++++++++++++++++++++---
drivers/net/ethernet/ti/cpsw_ale.h | 24 ++++--
include/linux/platform_data/cpsw.h | 1 +
5 files changed, 201 insertions(+), 24 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCH v3 1/2] drivers: net: cpsw: Add helper functions for VLAN ALE implementation
From: Mugunthan V N @ 2013-01-31 19:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359659000-25995-1-git-send-email-mugunthanvnm@ti.com>
Add helper functions for VLAN ALE implementations for Add, Delete
Dump VLAN related ALE entries
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/net/ethernet/ti/cpsw.c | 8 +--
drivers/net/ethernet/ti/cpsw_ale.c | 105 +++++++++++++++++++++++++++++++-----
drivers/net/ethernet/ti/cpsw_ale.h | 20 ++++---
3 files changed, 111 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index b35e6a7..a40750e 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -345,7 +345,7 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
/* program multicast address list into ALE register */
netdev_for_each_mc_addr(ha, ndev) {
cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr,
- ALE_ALL_PORTS << priv->host_port, 0, 0);
+ ALE_ALL_PORTS << priv->host_port, 0, 0, 0);
}
}
}
@@ -592,7 +592,7 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
slave_port = cpsw_get_slave_port(priv, slave->slave_num);
cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
- 1 << slave_port, 0, ALE_MCAST_FWD_2);
+ 1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
&cpsw_adjust_link, slave->data->phy_if);
@@ -624,9 +624,9 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
cpsw_ale_control_set(priv->ale, priv->host_port,
ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
- cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, 0);
+ cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, 0, 0);
cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
- 1 << priv->host_port, 0, ALE_MCAST_FWD_2);
+ 1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
}
static int cpsw_ndo_open(struct net_device *ndev)
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 0e9ccc2..0354875 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -148,7 +148,7 @@ static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
return idx;
}
-static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
+int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS];
int type, idx;
@@ -160,6 +160,8 @@ static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
type = cpsw_ale_get_entry_type(ale_entry);
if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
continue;
+ if (cpsw_ale_get_vlan_id(ale_entry) != vid)
+ continue;
cpsw_ale_get_addr(ale_entry, entry_addr);
if (memcmp(entry_addr, addr, 6) == 0)
return idx;
@@ -167,6 +169,22 @@ static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
return -ENOENT;
}
+int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS];
+ int type, idx;
+
+ for (idx = 0; idx < ale->params.ale_entries; idx++) {
+ cpsw_ale_read(ale, idx, ale_entry);
+ type = cpsw_ale_get_entry_type(ale_entry);
+ if (type != ALE_TYPE_VLAN)
+ continue;
+ if (cpsw_ale_get_vlan_id(ale_entry) == vid)
+ return idx;
+ }
+ return -ENOENT;
+}
+
static int cpsw_ale_match_free(struct cpsw_ale *ale)
{
u32 ale_entry[ALE_ENTRY_WORDS];
@@ -274,19 +292,32 @@ int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
return 0;
}
-int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
+static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
+ int flags, u16 vid)
+{
+ if (flags & ALE_VLAN) {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
+ cpsw_ale_set_vlan_id(ale_entry, vid);
+ } else {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ }
+}
+
+int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
- cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
+
cpsw_ale_set_addr(ale_entry, addr);
cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
cpsw_ale_set_port_num(ale_entry, port);
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx < 0)
idx = cpsw_ale_match_free(ale);
if (idx < 0)
@@ -298,12 +329,13 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
return 0;
}
-int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port)
+int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx < 0)
return -ENOENT;
@@ -313,18 +345,19 @@ int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port)
}
int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
- int super, int mcast_state)
+ int flags, u16 vid, int mcast_state)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx, mask;
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx >= 0)
cpsw_ale_read(ale, idx, ale_entry);
- cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
+
cpsw_ale_set_addr(ale_entry, addr);
- cpsw_ale_set_super(ale_entry, super);
+ cpsw_ale_set_super(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
cpsw_ale_set_mcast_state(ale_entry, mcast_state);
mask = cpsw_ale_get_port_mask(ale_entry);
@@ -342,12 +375,13 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
return 0;
}
-int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
+int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
+ int flags, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx < 0)
return -EINVAL;
@@ -362,6 +396,53 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
return 0;
}
+void cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
+ int reg_mcast, int unreg_mcast)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+
+ idx = cpsw_ale_match_vlan(ale, vid);
+ if (idx >= 0)
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
+ cpsw_ale_set_vlan_id(ale_entry, vid);
+
+ cpsw_ale_set_vlan_untag_force(ale_entry, untag);
+ cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast);
+ cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
+ cpsw_ale_set_vlan_member_list(ale_entry, port);
+
+ if (idx < 0)
+ idx = cpsw_ale_match_free(ale);
+ if (idx < 0)
+ idx = cpsw_ale_find_ageable(ale);
+ if (idx < 0)
+ return;
+
+ cpsw_ale_write(ale, idx, ale_entry);
+}
+
+void cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+
+ idx = cpsw_ale_match_vlan(ale, vid);
+ if (idx < 0)
+ return;
+
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ if (port_mask)
+ cpsw_ale_set_vlan_member_list(ale_entry, port_mask);
+ else
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
+
+ cpsw_ale_write(ale, idx, ale_entry);
+}
+
struct ale_control_info {
const char *name;
int offset, port_offset;
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index 2bd09cb..74f6fe2 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -64,8 +64,10 @@ enum cpsw_ale_port_state {
};
/* ALE unicast entry flags - passed into cpsw_ale_add_ucast() */
-#define ALE_SECURE 1
-#define ALE_BLOCKED 2
+#define ALE_SECURE BIT(0)
+#define ALE_BLOCKED BIT(1)
+#define ALE_SUPER BIT(2)
+#define ALE_VLAN BIT(3)
#define ALE_MCAST_FWD 0
#define ALE_MCAST_BLOCK_LEARN_FWD 1
@@ -81,11 +83,17 @@ void cpsw_ale_stop(struct cpsw_ale *ale);
int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout);
int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask);
int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask);
-int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags);
-int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port);
+int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid);
+int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid);
int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
- int super, int mcast_state);
-int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask);
+ int flags, u16 vid, int mcast_state);
+int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
+ int flags, u16 vid);
+void cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
+ int reg_mcast, int unreg_mcast);
+void cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port);
int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control);
int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 2/2] drivers: net:ethernet: cpsw: add support for VLAN
From: Mugunthan V N @ 2013-01-31 19:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359659000-25995-1-git-send-email-mugunthanvnm@ti.com>
adding support for VLAN interface for cpsw.
CPSW VLAN Capability
* Can filter VLAN packets in Hardware
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 2 +
drivers/net/ethernet/ti/cpsw.c | 85 +++++++++++++++++++++++-
drivers/net/ethernet/ti/cpsw_ale.h | 4 ++
include/linux/platform_data/cpsw.h | 1 +
4 files changed, 90 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 6ddd028..99696bf 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -24,6 +24,8 @@ Required properties:
Optional properties:
- ti,hwmods : Must be "cpgmac0"
- no_bd_ram : Must be 0 or 1
+- default_vlan : Specifies Default VLAN for non tagged packets
+ ALE processing
Note: "ti,hwmods" field is used to fetch the base address and irq
resources from TI, omap hwmod data base during device registration.
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index a40750e..63b1563 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -32,6 +32,7 @@
#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/of_device.h>
+#include <linux/if_vlan.h>
#include <linux/platform_data/cpsw.h>
@@ -118,6 +119,9 @@ do { \
#define TX_PRIORITY_MAPPING 0x33221100
#define CPDMA_TX_PRIORITY_MAP 0x76543210
+#define CPSW_VLAN_AWARE BIT(1)
+#define CPSW_ALE_VLAN_AWARE 1
+
#define cpsw_enable_irq(priv) \
do { \
u32 i; \
@@ -607,14 +611,40 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
}
}
+static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
+{
+ const int vlan = priv->data.default_vlan;
+ const int port = priv->host_port;
+ u32 reg;
+ int i;
+
+ reg = (priv->version == CPSW_VERSION_1) ? CPSW1_PORT_VLAN :
+ CPSW2_PORT_VLAN;
+
+ writel(vlan, &priv->host_port_regs->port_vlan);
+
+ for (i = 0; i < 2; i++)
+ slave_write(priv->slaves + i, vlan, reg);
+
+ cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port,
+ ALE_ALL_PORTS << port, ALE_ALL_PORTS << port,
+ (ALE_PORT_1 | ALE_PORT_2) << port);
+}
+
static void cpsw_init_host_port(struct cpsw_priv *priv)
{
+ u32 control_reg;
+
/* soft reset the controller and initialize ale */
soft_reset("cpsw", &priv->regs->soft_reset);
cpsw_ale_start(priv->ale);
/* switch to vlan unaware mode */
- cpsw_ale_control_set(priv->ale, 0, ALE_VLAN_AWARE, 0);
+ cpsw_ale_control_set(priv->ale, priv->host_port, ALE_VLAN_AWARE,
+ CPSW_ALE_VLAN_AWARE);
+ control_reg = readl(&priv->regs->control);
+ control_reg |= CPSW_VLAN_AWARE;
+ writel(control_reg, &priv->regs->control);
/* setup host port priority mapping */
__raw_writel(CPDMA_TX_PRIORITY_MAP,
@@ -650,6 +680,9 @@ static int cpsw_ndo_open(struct net_device *ndev)
cpsw_init_host_port(priv);
for_each_slave(priv, cpsw_slave_open, priv);
+ /* Add default VLAN */
+ cpsw_add_default_vlan(priv);
+
/* setup tx dma to fixed prio and zero offset */
cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
@@ -933,6 +966,49 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
}
#endif
+static inline void cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
+ unsigned short vid)
+{
+ cpsw_ale_add_vlan(priv->ale, vid, ALE_ALL_PORTS << priv->host_port,
+ 0, ALE_ALL_PORTS << priv->host_port,
+ (ALE_PORT_1 | ALE_PORT_2) << priv->host_port);
+ cpsw_ale_add_ucast(priv->ale, priv->mac_addr,
+ priv->host_port, ALE_VLAN, vid);
+ cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+ ALE_ALL_PORTS << priv->host_port, ALE_VLAN, vid, 0);
+}
+
+static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev,
+ unsigned short vid)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ if (vid == priv->data.default_vlan)
+ return 0;
+
+ dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid);
+ cpsw_add_vlan_ale_entry(priv, vid);
+
+ return 0;
+}
+
+static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
+ unsigned short vid)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ if (vid == priv->data.default_vlan)
+ return 0;
+
+ dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid);
+ cpsw_ale_del_vlan(priv->ale, vid, 0);
+ cpsw_ale_del_ucast(priv->ale, priv->mac_addr,
+ priv->host_port, ALE_VLAN, vid);
+ cpsw_ale_del_mcast(priv->ale, priv->ndev->broadcast, 0, ALE_VLAN, vid);
+
+ return 0;
+}
+
static const struct net_device_ops cpsw_netdev_ops = {
.ndo_open = cpsw_ndo_open,
.ndo_stop = cpsw_ndo_stop,
@@ -947,6 +1023,8 @@ static const struct net_device_ops cpsw_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cpsw_ndo_poll_controller,
#endif
+ .ndo_vlan_rx_add_vid = cpsw_ndo_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = cpsw_ndo_vlan_rx_kill_vid,
};
static void cpsw_get_drvinfo(struct net_device *ndev,
@@ -1103,6 +1181,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->mac_control = prop;
+ if (!of_property_read_u32(node, "default_vlan", &prop))
+ data->default_vlan = prop;
+
/*
* Populate all the child nodes here...
*/
@@ -1356,7 +1437,7 @@ static int cpsw_probe(struct platform_device *pdev)
k++;
}
- ndev->flags |= IFF_ALLMULTI; /* see cpsw_ndo_change_rx_flags() */
+ ndev->features |= NETIF_F_HW_VLAN_FILTER;
ndev->netdev_ops = &cpsw_netdev_ops;
SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index 74f6fe2..f554c05 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -69,6 +69,10 @@ enum cpsw_ale_port_state {
#define ALE_SUPER BIT(2)
#define ALE_VLAN BIT(3)
+#define ALE_PORT_HOST BUT(0)
+#define ALE_PORT_1 BIT(1)
+#define ALE_PORT_2 BIT(2)
+
#define ALE_MCAST_FWD 0
#define ALE_MCAST_BLOCK_LEARN_FWD 1
#define ALE_MCAST_FWD_LEARN 2
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index 24368a2..e962cfd 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -35,6 +35,7 @@ struct cpsw_platform_data {
u32 bd_ram_size; /*buffer descriptor ram size */
u32 rx_descs; /* Number of Rx Descriptios */
u32 mac_control; /* Mac control register */
+ u16 default_vlan; /* Def VLAN for ALE lookup in VLAN aware mode*/
};
#endif /* __CPSW_H__ */
--
1.7.9.5
^ permalink raw reply related
* [PATCH 0/2] ARM: OMAP2+: Export SoC information to userspace using SoC infrastructure
From: Ruslan Bilovol @ 2013-01-31 19:24 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This patch series is an attempt to export some OMAP SoC
information (like name, revision etc.) to userspace.
The first patch does some unification of OMAP SoC
information representation in current sources.
Second patch adds exactly needed changes using
exists in Linux kernel SoC infrastructure.
Ruslan Bilovol (2):
ARM: OMAP2+: SoC name and revision unification
ARM: OMAP2+: Export SoC information to userspace
arch/arm/mach-omap2/Kconfig | 1 +
arch/arm/mach-omap2/common.h | 8 +++
arch/arm/mach-omap2/id.c | 152 ++++++++++++++++++++++++++++++++----------
arch/arm/mach-omap2/io.c | 1 +
4 files changed, 125 insertions(+), 37 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCH 1/2] ARM: OMAP2+: SoC name and revision unification
From: Ruslan Bilovol @ 2013-01-31 19:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359660284-5225-1-git-send-email-ruslan.bilovol@ti.com>
This is a long story where for each new generation of
OMAP we used different approaches for creating
strings for SoCs names and revisions that this patch
fixes. It makes future exporting of this information
to SoC infrastructure easier.
Signed-off-by: Ruslan Bilovol <ruslan.bilovol@ti.com>
---
arch/arm/mach-omap2/id.c | 87 ++++++++++++++++++++++++++--------------------
1 file changed, 50 insertions(+), 37 deletions(-)
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 45cc7ed4..436fcf9 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -31,8 +31,11 @@
#define OMAP4_SILICON_TYPE_STANDARD 0x01
#define OMAP4_SILICON_TYPE_PERFORMANCE 0x02
+#define OMAP_SOC_MAX_NAME_LENGTH 16
+
static unsigned int omap_revision;
-static const char *cpu_rev;
+static char cpu_name[OMAP_SOC_MAX_NAME_LENGTH];
+static char cpu_rev[OMAP_SOC_MAX_NAME_LENGTH];
u32 omap_features;
unsigned int omap_rev(void)
@@ -169,9 +172,12 @@ void __init omap2xxx_check_revision(void)
j = i;
}
- pr_info("OMAP%04x", omap_rev() >> 16);
+ sprintf(cpu_name, "OMAP%04x", omap_rev() >> 16);
+ sprintf(cpu_rev, "ES%x", (omap_rev() >> 12) & 0xf);
+
+ pr_info("%s", cpu_name);
if ((omap_rev() >> 8) & 0x0f)
- pr_info("ES%x", (omap_rev() >> 12) & 0xf);
+ pr_info("%s", cpu_rev);
pr_info("\n");
}
@@ -181,8 +187,7 @@ void __init omap2xxx_check_revision(void)
static void __init omap3_cpuinfo(void)
{
- const char *cpu_name;
-
+ const char *omap3_cpu_name;
/*
* OMAP3430 and OMAP3530 are assumed to be same.
*
@@ -191,28 +196,30 @@ static void __init omap3_cpuinfo(void)
* and CPU class bits.
*/
if (cpu_is_omap3630()) {
- cpu_name = "OMAP3630";
+ omap3_cpu_name = "OMAP3630";
} else if (soc_is_am35xx()) {
- cpu_name = (omap3_has_sgx()) ? "AM3517" : "AM3505";
+ omap3_cpu_name = (omap3_has_sgx()) ? "AM3517" : "AM3505";
} else if (cpu_is_ti816x()) {
- cpu_name = "TI816X";
+ omap3_cpu_name = "TI816X";
} else if (soc_is_am335x()) {
- cpu_name = "AM335X";
+ omap3_cpu_name = "AM335X";
} else if (cpu_is_ti814x()) {
- cpu_name = "TI814X";
+ omap3_cpu_name = "TI814X";
} else if (omap3_has_iva() && omap3_has_sgx()) {
/* OMAP3430, OMAP3525, OMAP3515, OMAP3503 devices */
- cpu_name = "OMAP3430/3530";
+ omap3_cpu_name = "OMAP3430/3530";
} else if (omap3_has_iva()) {
- cpu_name = "OMAP3525";
+ omap3_cpu_name = "OMAP3525";
} else if (omap3_has_sgx()) {
- cpu_name = "OMAP3515";
+ omap3_cpu_name = "OMAP3515";
} else {
- cpu_name = "OMAP3503";
+ omap3_cpu_name = "OMAP3503";
}
+ sprintf(cpu_name, "%s", omap3_cpu_name);
+
/* Print verbose information */
- pr_info("%s ES%s (", cpu_name, cpu_rev);
+ pr_info("%s %s (", cpu_name, cpu_rev);
OMAP3_SHOW_FEATURE(l2cache);
OMAP3_SHOW_FEATURE(iva);
@@ -291,6 +298,7 @@ void __init ti81xx_check_features(void)
void __init omap3xxx_check_revision(void)
{
+ const char *omap3_cpu_rev;
u32 cpuid, idcode;
u16 hawkeye;
u8 rev;
@@ -303,7 +311,7 @@ void __init omap3xxx_check_revision(void)
cpuid = read_cpuid(CPUID_ID);
if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) {
omap_revision = OMAP3430_REV_ES1_0;
- cpu_rev = "1.0";
+ omap3_cpu_rev = "ES1.0";
return;
}
@@ -324,26 +332,26 @@ void __init omap3xxx_check_revision(void)
case 0: /* Take care of early samples */
case 1:
omap_revision = OMAP3430_REV_ES2_0;
- cpu_rev = "2.0";
+ omap3_cpu_rev = "ES2.0";
break;
case 2:
omap_revision = OMAP3430_REV_ES2_1;
- cpu_rev = "2.1";
+ omap3_cpu_rev = "ES2.1";
break;
case 3:
omap_revision = OMAP3430_REV_ES3_0;
- cpu_rev = "3.0";
+ omap3_cpu_rev = "ES3.0";
break;
case 4:
omap_revision = OMAP3430_REV_ES3_1;
- cpu_rev = "3.1";
+ omap3_cpu_rev = "ES3.1";
break;
case 7:
/* FALLTHROUGH */
default:
/* Use the latest known revision as default */
omap_revision = OMAP3430_REV_ES3_1_2;
- cpu_rev = "3.1.2";
+ omap3_cpu_rev = "ES3.1.2";
}
break;
case 0xb868:
@@ -356,13 +364,13 @@ void __init omap3xxx_check_revision(void)
switch (rev) {
case 0:
omap_revision = AM35XX_REV_ES1_0;
- cpu_rev = "1.0";
+ omap3_cpu_rev = "ES1.0";
break;
case 1:
/* FALLTHROUGH */
default:
omap_revision = AM35XX_REV_ES1_1;
- cpu_rev = "1.1";
+ omap3_cpu_rev = "ES1.1";
}
break;
case 0xb891:
@@ -371,36 +379,36 @@ void __init omap3xxx_check_revision(void)
switch(rev) {
case 0: /* Take care of early samples */
omap_revision = OMAP3630_REV_ES1_0;
- cpu_rev = "1.0";
+ omap3_cpu_rev = "1.0";
break;
case 1:
omap_revision = OMAP3630_REV_ES1_1;
- cpu_rev = "1.1";
+ omap3_cpu_rev = "ES1.1";
break;
case 2:
/* FALLTHROUGH */
default:
omap_revision = OMAP3630_REV_ES1_2;
- cpu_rev = "1.2";
+ omap3_cpu_rev = "ES1.2";
}
break;
case 0xb81e:
switch (rev) {
case 0:
omap_revision = TI8168_REV_ES1_0;
- cpu_rev = "1.0";
+ omap3_cpu_rev = "ES1.0";
break;
case 1:
/* FALLTHROUGH */
default:
omap_revision = TI8168_REV_ES1_1;
- cpu_rev = "1.1";
+ omap3_cpu_rev = "ES1.1";
break;
}
break;
case 0xb944:
omap_revision = AM335X_REV_ES1_0;
- cpu_rev = "1.0";
+ omap3_cpu_rev = "ES1.0";
break;
case 0xb8f2:
switch (rev) {
@@ -408,26 +416,27 @@ void __init omap3xxx_check_revision(void)
/* FALLTHROUGH */
case 1:
omap_revision = TI8148_REV_ES1_0;
- cpu_rev = "1.0";
+ omap3_cpu_rev = "ES1.0";
break;
case 2:
omap_revision = TI8148_REV_ES2_0;
- cpu_rev = "2.0";
+ omap3_cpu_rev = "ES2.0";
break;
case 3:
/* FALLTHROUGH */
default:
omap_revision = TI8148_REV_ES2_1;
- cpu_rev = "2.1";
+ omap3_cpu_rev = "ES2.1";
break;
}
break;
default:
/* Unknown default to latest silicon rev as default */
omap_revision = OMAP3630_REV_ES1_2;
- cpu_rev = "1.2";
+ omap3_cpu_rev = "ES1.2";
pr_warn("Warning: unknown chip type; assuming OMAP3630ES1.2\n");
}
+ sprintf(cpu_rev, "%s", omap3_cpu_rev);
}
void __init omap4xxx_check_revision(void)
@@ -502,8 +511,10 @@ void __init omap4xxx_check_revision(void)
omap_revision = OMAP4430_REV_ES2_3;
}
- pr_info("OMAP%04x ES%d.%d\n", omap_rev() >> 16,
- ((omap_rev() >> 12) & 0xf), ((omap_rev() >> 8) & 0xf));
+ sprintf(cpu_name, "OMAP%04x", omap_rev() >> 16);
+ sprintf(cpu_rev, "ES%d.%d", (omap_rev() >> 12) & 0xf,
+ (omap_rev() >> 8) & 0xf);
+ pr_info("%s %s\n", cpu_name, cpu_rev);
}
void __init omap5xxx_check_revision(void)
@@ -537,8 +548,10 @@ void __init omap5xxx_check_revision(void)
omap_revision = OMAP5430_REV_ES1_0;
}
- pr_info("OMAP%04x ES%d.0\n",
- omap_rev() >> 16, ((omap_rev() >> 12) & 0xf));
+ sprintf(cpu_name, "OMAP%04x", omap_rev() >> 16);
+ sprintf(cpu_rev, "ES%d.0", (omap_rev() >> 12) & 0xf);
+
+ pr_info("%s %s\n", cpu_name, cpu_rev);
}
/*
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/2] ARM: OMAP2+: Export SoC information to userspace
From: Ruslan Bilovol @ 2013-01-31 19:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359660284-5225-1-git-send-email-ruslan.bilovol@ti.com>
In some situations it is useful for userspace to
know some SoC-specific information. For example,
this may be used for deciding what kernel module to
use or how to better configure some settings etc.
This patch exports OMAP SoC information to userspace
using existing in Linux kernel SoC infrastructure.
This information can be read under
/sys/devices/socX directory
Signed-off-by: Ruslan Bilovol <ruslan.bilovol@ti.com>
---
arch/arm/mach-omap2/Kconfig | 1 +
arch/arm/mach-omap2/common.h | 8 ++++++
arch/arm/mach-omap2/id.c | 65 ++++++++++++++++++++++++++++++++++++++++++
arch/arm/mach-omap2/io.c | 1 +
4 files changed, 75 insertions(+)
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index fe926e0..47da0bd 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -17,6 +17,7 @@ config ARCH_OMAP2PLUS
select PROC_DEVICETREE if PROC_FS
select SPARSE_IRQ
select USE_OF
+ select SOC_BUS
help
Systems based on OMAP2, OMAP3, OMAP4 or OMAP5
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 948bcaa..2a6f866 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -111,6 +111,14 @@ void ti81xx_init_late(void);
void omap4430_init_late(void);
int omap2_common_pm_late_init(void);
+#ifdef CONFIG_SOC_BUS
+void omap_soc_device_init(void);
+#else
+static inline void omap_soc_device_init(void)
+{
+}
+#endif
+
#if defined(CONFIG_SOC_OMAP2420) || defined(CONFIG_SOC_OMAP2430)
void omap2xxx_restart(char mode, const char *cmd);
#else
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 436fcf9..5724ee8 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -18,6 +18,11 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_SOC_BUS
+#include <linux/sys_soc.h>
+#endif
#include <asm/cputype.h>
@@ -572,3 +577,63 @@ void __init omap2_set_globals_tap(u32 class, void __iomem *tap)
else
tap_prod_id = 0x0208;
}
+
+#ifdef CONFIG_SOC_BUS
+
+static const char const *omap_types[] = {
+ [OMAP2_DEVICE_TYPE_TEST] = "TST",
+ [OMAP2_DEVICE_TYPE_EMU] = "EMU",
+ [OMAP2_DEVICE_TYPE_SEC] = "HS",
+ [OMAP2_DEVICE_TYPE_GP] = "GP",
+ [OMAP2_DEVICE_TYPE_BAD] = "BAD",
+};
+
+static const char * __init omap_get_family(void)
+{
+ if (cpu_is_omap24xx())
+ return kasprintf(GFP_KERNEL, "OMAP2");
+ else if (cpu_is_omap34xx())
+ return kasprintf(GFP_KERNEL, "OMAP3");
+ else if (cpu_is_omap44xx())
+ return kasprintf(GFP_KERNEL, "OMAP4");
+ else if (soc_is_omap54xx())
+ return kasprintf(GFP_KERNEL, "OMAP5");
+ else
+ return kasprintf(GFP_KERNEL, "Unknown");
+}
+
+static ssize_t omap_get_type(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", omap_types[omap_type()]);
+}
+
+static struct device_attribute omap_soc_attr =
+ __ATTR(type, S_IRUGO, omap_get_type, NULL);
+
+void __init omap_soc_device_init(void)
+{
+ struct device *parent;
+ struct soc_device *soc_dev;
+ struct soc_device_attribute *soc_dev_attr;
+
+ soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ if (!soc_dev_attr)
+ return;
+
+ soc_dev_attr->machine = cpu_name;
+ soc_dev_attr->family = omap_get_family();
+ soc_dev_attr->revision = cpu_rev;
+
+ soc_dev = soc_device_register(soc_dev_attr);
+ if (IS_ERR_OR_NULL(soc_dev)) {
+ kfree(soc_dev_attr);
+ return;
+ }
+
+ parent = soc_device_to_device(soc_dev);
+ if (!IS_ERR_OR_NULL(parent))
+ device_create_file(parent, &omap_soc_attr);
+}
+#endif /* CONFIG_SOC_BUS */
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 2c3fdd6..08003c1 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -602,6 +602,7 @@ void __init omap4430_init_late(void)
omap2_common_pm_late_init();
omap4_pm_init();
omap2_clk_enable_autoidle_all();
+ omap_soc_device_init();
}
#endif
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3] arm: mvebu: add DTS file for Marvell RD-A370-A1 board
From: Florian Fainelli @ 2013-01-31 19:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130131175743.GF7717@titan.lakedaemon.net>
Le 31/01/2013 18:57, Jason Cooper a ?crit :
> Florian,
>
> On Mon, Jan 14, 2013 at 03:47:32PM +0100, Florian Fainelli wrote:
>> This patch adds the DTS file to support the Marvell RD-A370-A1
>> (Reference Design board) also known as RD-88F6710 board. It is almost
>> entirely similar to the DB-A370 except on the following points:
>>
>> - second Ethernet MAC is connected to a switch using RGMII
>> - it only has 512MB of physical RAM
>> - SDIO interface is enabled and working by default (no need for jumpers)
>>
>> Signed-off-by: Florian Fainelli <florian@openwrt.org>
>> ---
>> Jason,
>>
>> This is rebased against your mvebu/for-next branch, can you please drop v2 of
>> the previous patch and take this one instead? Thanks!
>>
>> Changes since v2:
>> - rebased against Jason's mvebu/for-next
>> - added SDIO bindings
>> - changed commit message a bit
>
> This breaks badly as sdio bindings aren't added until mvebu/dt. Since
> this is a new board, it goes in *before* mvebu/dt (mvebu/boards). I'm
> going to go ahead and pull v2 instead as there seems to be no
> significant difference other than mvsdio being added.
Whoops, sounds like the right thing to do, thanks!
>
> If you want to get sdio support in for v3.9, please submit a separate
> patch on top of your v2.
Will do.
--
Florian
^ permalink raw reply
* [PATCH 0/3] More highbank fixes for 3.8
From: Rob Herring @ 2013-01-31 20:01 UTC (permalink / raw)
To: linux-arm-kernel
From: Rob Herring <rob.herring@calxeda.com>
A couple more fixes for highbank related to fallout from using MPIDR
value for the physical cpu id and an scu build error introduced by
suspend fixes.
Rob
Rob Herring (3):
ARM: scu: add empty scu_enable for !CONFIG_SMP
ARM: scu: mask cluster id from cpu_logical_map
ARM: highbank: mask cluster id from cpu_logical_map
arch/arm/include/asm/smp_scu.h | 8 +++++++-
arch/arm/kernel/smp_scu.c | 2 +-
arch/arm/mach-highbank/highbank.c | 3 ++-
arch/arm/mach-highbank/sysregs.h | 4 ++--
4 files changed, 12 insertions(+), 5 deletions(-)
--
1.7.10.4
^ permalink raw reply
* [PATCH 1/3] ARM: scu: add empty scu_enable for !CONFIG_SMP
From: Rob Herring @ 2013-01-31 20:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359662474-1883-1-git-send-email-robherring2@gmail.com>
From: Rob Herring <rob.herring@calxeda.com>
Add an empty version of scu_enable for !SMP builds. This fixes
compile error for highbank suspend code on !SMP builds.
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
arch/arm/include/asm/smp_scu.h | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/smp_scu.h b/arch/arm/include/asm/smp_scu.h
index 4eb6d00..86dff32 100644
--- a/arch/arm/include/asm/smp_scu.h
+++ b/arch/arm/include/asm/smp_scu.h
@@ -7,8 +7,14 @@
#ifndef __ASSEMBLER__
unsigned int scu_get_core_count(void __iomem *);
-void scu_enable(void __iomem *);
int scu_power_mode(void __iomem *, unsigned int);
+
+#ifdef CONFIG_SMP
+void scu_enable(void __iomem *scu_base);
+#else
+static inline void scu_enable(void __iomem *scu_base) {}
+#endif
+
#endif
#endif
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/3] ARM: scu: mask cluster id from cpu_logical_map
From: Rob Herring @ 2013-01-31 20:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359662474-1883-1-git-send-email-robherring2@gmail.com>
From: Rob Herring <rob.herring@calxeda.com>
With commit a0ae0240 (ARM: kernel: add device tree init map function),
the cpu id value may include the cluster id and is no longer 0-3, so we
need to mask it in scu_power_mode to get the local cpu number. Since we
are only dealing with the cpu we are running on, the cluster id should
not ever be needed.
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
arch/arm/kernel/smp_scu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c
index b9f015e..45eac87 100644
--- a/arch/arm/kernel/smp_scu.c
+++ b/arch/arm/kernel/smp_scu.c
@@ -75,7 +75,7 @@ void scu_enable(void __iomem *scu_base)
int scu_power_mode(void __iomem *scu_base, unsigned int mode)
{
unsigned int val;
- int cpu = cpu_logical_map(smp_processor_id());
+ int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(smp_processor_id()), 0);
if (mode > 3 || mode == 1 || cpu > 3)
return -EINVAL;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 3/3] ARM: highbank: mask cluster id from cpu_logical_map
From: Rob Herring @ 2013-01-31 20:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359662474-1883-1-git-send-email-robherring2@gmail.com>
From: Rob Herring <rob.herring@calxeda.com>
With commit a0ae0240 (ARM: kernel: add device tree init map function),
the cpu id value may include the cluster id and is no longer 0-3, so we
need to mask it now to get the right hard cpu index.
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
arch/arm/mach-highbank/highbank.c | 3 ++-
arch/arm/mach-highbank/sysregs.h | 4 ++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index 981dc1e..e6c0612 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -28,6 +28,7 @@
#include <asm/arch_timer.h>
#include <asm/cacheflush.h>
+#include <asm/cputype.h>
#include <asm/smp_plat.h>
#include <asm/smp_twd.h>
#include <asm/hardware/arm_timer.h>
@@ -59,7 +60,7 @@ static void __init highbank_scu_map_io(void)
void highbank_set_cpu_jump(int cpu, void *jump_addr)
{
- cpu = cpu_logical_map(cpu);
+ cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0);
writel(virt_to_phys(jump_addr), HB_JUMP_TABLE_VIRT(cpu));
__cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
diff --git a/arch/arm/mach-highbank/sysregs.h b/arch/arm/mach-highbank/sysregs.h
index 70af9d1..5995df7 100644
--- a/arch/arm/mach-highbank/sysregs.h
+++ b/arch/arm/mach-highbank/sysregs.h
@@ -37,7 +37,7 @@ extern void __iomem *sregs_base;
static inline void highbank_set_core_pwr(void)
{
- int cpu = cpu_logical_map(smp_processor_id());
+ int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(smp_processor_id()), 0);
if (scu_base_addr)
scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
else
@@ -46,7 +46,7 @@ static inline void highbank_set_core_pwr(void)
static inline void highbank_clear_core_pwr(void)
{
- int cpu = cpu_logical_map(smp_processor_id());
+ int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(smp_processor_id()), 0);
if (scu_base_addr)
scu_power_mode(scu_base_addr, SCU_PM_NORMAL);
else
--
1.7.10.4
^ permalink raw reply related
* [PATCH] power/reset: restart: remove __dev{init,exit}
From: Andrew Lunn @ 2013-01-31 20:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359658469-14856-1-git-send-email-jason@lakedaemon.net>
On Thu, Jan 31, 2013 at 06:54:29PM +0000, Jason Cooper wrote:
> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Hi Jason
I Acked-by: a very similar patch to this yesterday....
https://lkml.org/lkml/2013/1/30/233
Andrew
> ---
> drivers/power/reset/restart-poweroff.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/power/reset/restart-poweroff.c b/drivers/power/reset/restart-poweroff.c
> index b11b9e8..059cd15 100644
> --- a/drivers/power/reset/restart-poweroff.c
> +++ b/drivers/power/reset/restart-poweroff.c
> @@ -22,7 +22,7 @@ static void restart_poweroff_do_poweroff(void)
> arm_pm_restart('h', NULL);
> }
>
> -static int __devinit restart_poweroff_probe(struct platform_device *pdev)
> +static int restart_poweroff_probe(struct platform_device *pdev)
> {
> /* If a pm_power_off function has already been added, leave it alone */
> if (pm_power_off != NULL) {
> @@ -35,7 +35,7 @@ static int __devinit restart_poweroff_probe(struct platform_device *pdev)
> return 0;
> }
>
> -static int __devexit restart_poweroff_remove(struct platform_device *pdev)
> +static int restart_poweroff_remove(struct platform_device *pdev)
> {
> if (pm_power_off == &restart_poweroff_do_poweroff)
> pm_power_off = NULL;
> @@ -50,7 +50,7 @@ static const struct of_device_id of_restart_poweroff_match[] = {
>
> static struct platform_driver restart_poweroff_driver = {
> .probe = restart_poweroff_probe,
> - .remove = __devexit_p(restart_poweroff_remove),
> + .remove = restart_poweroff_remove,
> .driver = {
> .name = "poweroff-restart",
> .owner = THIS_MODULE,
> --
> 1.8.1.1
>
^ permalink raw reply
* [PATCH 2/4] drm/i2c: nxp-tda998x (v3)
From: Sebastian Hesselbarth @ 2013-01-31 20:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAF6AEGsYzyefOpeHnsRh-YczVfaTh2d5AtoTFfT7AEWuukJZUA@mail.gmail.com>
On 01/31/2013 03:23 PM, Rob Clark wrote:
> On Wed, Jan 30, 2013 at 8:23 PM, Sebastian Hesselbarth
> <sebastian.hesselbarth@gmail.com> wrote:
>> On 01/29/2013 06:23 PM, Rob Clark wrote:
[...]
>>> +
>>> +/* The TDA9988 series of devices use a paged register scheme.. to
>>> simplify
>>> + * things we encode the page # in upper bits of the register #. To read/
>>> + * write a given register, we need to make sure CURPAGE register is set
>>> + * appropriately. Which implies reads/writes are not atomic. Fun!
>>> + */
>>
>> Please have a look at regmap-i2c, it also supports paged i2c registers
>> and will save you _a lot_ of the i2c handling.
>
> Yeah, I have looked at it, and will eventually convert over to using
> it. The problems at the moment are that I don't really have enough
> documentation about the chip at the register level to properly use the
> caching modes, and from my digging through the regmap code it looked
> like paged regmap + non-caching will result in writes to the page
> register for every transaction. That, and a bit of docs or few more
> examples of using the paging support in regmap would be nice. For
> now, I am punting on regmap conversion.
Hmm, flipping through the public tda998x sources *sigh* I found a
quite complete register list that also states if registers are RO or RW.
Even if you are not using all registers you can still prevent regmap from
reading/writing to them. But yes, documentation lacks some examples ;)
>>> [...]
>>> +
>>> +/* Device versions: */
>>> +#define TDA9989N2 0x0101
>>> +#define TDA19989 0x0201
>>> +#define TDA19989N2 0x0202
>>> +#define TDA19988 0x0301
>>
>>
>> Maybe split this into device_version/revision? What does N2 stand for
>> or is this the name NXP uses for that device?
>
> The register names are based on the names used in the NXP out-of-tree
> driver (the 50kloc monstrosity, if you've seen it).. that was pretty
> much all the register level documentation I had.
Yeah, but there is a comment about N2, that says the last bit is "not a
register bit, but is derived by the driver from the new N5 registers..".
I guess you will not see that many i2c devices returning you "N2" version
registers..
>>> [...]
>>
>>> +static void
>>> +cec_write(struct drm_encoder *encoder, uint16_t addr, uint8_t val)
>>> +{
>>> + struct i2c_client *client = to_tda998x_priv(encoder)->cec;
>>> + uint8_t buf[] = {addr, val};
>>> + int ret;
>>> +
>>> + ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
>>> + if (ret< 0)
>>> + dev_err(&client->dev, "Error %d writing to cec:0x%x\n",
>>> ret, addr);
>>> +}
>>
>>
>> Has there been any decision on how to split/integrate cec from drm?
>> Or is there display stuff located in cec i2c slave (I see HPD in
>> ..._detect below)?
>
> not sure, but at least in this case it can't really be decoupled. I
> need to use the CEC interface for HPD (as you noticed) and also to
> power up the HDMI bits..
Just to make things clearer here, TDA998x ususally has two i2c slaves
at power-up, 0x70 (hdmi slave) and 0x34 (cec slave). Are you actually
accessing the cec slave?
[...]
>>> +static bool
>>> +tda998x_encoder_mode_fixup(struct drm_encoder *encoder,
>>> + const struct drm_display_mode *mode,
>>> + struct drm_display_mode *adjusted_mode)
>>> +{
>>> + return true;
>>> +}
>>> +
>>> +static int
>>> +tda998x_encoder_mode_valid(struct drm_encoder *encoder,
>>> + struct drm_display_mode *mode)
>>> +{
>>> + return MODE_OK;
>>> +}
>>
>>
>> At least a note would be helpful to see what callbacks are
>> not yet done. I guess there will be some kind of mode check
>> someday?
>
> Well, some of these drm will assume the fxn ptrs are not null, so we
> need something even if it is empty.
>
> I suppose there are must be some upper bounds on pixel clock
> supported, which could perhaps be added some day in _mode_valid(). On
Depends what drm expects on mode_valid or mode_fixup, I haven't dug into
drm encoders, yet. But usually for HDMI/DVI you will only choose between
modes supplied by monitor EDID and not choose something "close". Anyway,
I just think a note about stuff that is not yet working is helpful.
> the device I am working on, the limiting factor is the crtc (upstream
> of the encoder), so I haven't really needed this yet. I expect that
> as people start using this on some other devices, we'll come across
> some enhancements needed, some places where we need to add some
> configuration, etc. I cannot really predict exactly what is needed,
> so I prefer just to put the driver out there in some form, and then
> add it it as needed. So, I wouldn't really say that these functions
> are "TODO", but I also wouldn't say that we won't find some reason to
> add some code there at some point.
Or put it in staging?
>>> [...]
>>>
>>> +static enum drm_connector_status
>>> +tda998x_encoder_detect(struct drm_encoder *encoder,
>>> + struct drm_connector *connector)
>>> +{
>>> + uint8_t val = cec_read(encoder, REG_CEC_RXSHPDLEV);
>>> + return (val& CEC_RXSHPDLEV_HPD) ? connector_status_connected :
>>> + connector_status_disconnected;
>>> +}
>>
>>
>> This is where cec slave gets called from hdmi i2c driver. Any chance
>> there is HPD status in hdmi registers, too?
>
> Not that I know of. But like I mentioned, we also need to use the CEC
> interface just to talk to the HDMI interface. Before setting ENAMODS
> reg via cec address, the hdmi address won't even show up (for ex, on
> i2cdetect).
Again, I quickly checked the public sources. The cec slave looks like is
only for cec communication, i.e. actually sending/receiving messages.
But from your patch it isn't even clear to me, when you access hdmi or
cec slave as you are bypassing i2c client subsystem somehow.
> Maybe there is some way that this code should register some interface
> with CEC driver/subsystem? (Is there such a thing? I am not really
> CEC expert.) But I don't think there is any way to completely split
> it out.
When speaking about CEC subsystem you mean sending/receiving cec messages
and the corresponding kernel API? That can come later, for now everything
this driver needs can IMHO depend on EDID, i.e. DVI-style, only.
CEC communication can come later.
>>> +/* I2C driver functions */
>>> +
>>> +static int
>>> +tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
>>> +{
>>> + return 0;
>>> +}
>>> +
>>> +static int
>>> +tda998x_remove(struct i2c_client *client)
>>> +{
>>> + return 0;
>>> +}
>>
>>
>> Hmm, empty _probe and _remove? Maybe these should get some code
>> from _init below?
>
> naw, they aren't really used for drm i2c encoder slaves.
Well, if you use a i2c_client_addr != 0 below, the i2c subsystem will only
bother you if it finds e.g. device 0x70 on an i2c bus. So they should be
used. The drm API must be clear about what should happen in encoder_init
and encoder_probe.
>>> +static int
>>> +tda998x_encoder_init(struct i2c_client *client,
>>> + struct drm_device *dev,
>>> + struct drm_encoder_slave *encoder_slave)
>>> +{
>>> + struct drm_encoder *encoder =&encoder_slave->base;
>>>
>>> + struct tda998x_priv *priv;
>>> +
>>> + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
>>> + if (!priv)
>>> + return -ENOMEM;
>>> +
>>> + priv->current_page = 0;
>>> + priv->cec = i2c_new_dummy(client->adapter, 0x34);
>>> + priv->dpms = DRM_MODE_DPMS_OFF;
>>> +
>>> + encoder_slave->slave_priv = priv;
>>> + encoder_slave->slave_funcs =&tda998x_encoder_funcs;
>>> +
>>> + /* wake up the device: */
>>> + cec_write(encoder, REG_CEC_ENAMODS,
>>> + CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI);
>>> +
>>> + tda998x_reset(encoder);
>>> +
>>> + /* read version: */
>>> + priv->rev = reg_read(encoder, REG_VERSION_LSB) |
>>> + reg_read(encoder, REG_VERSION_MSB)<< 8;
>>> +
>>> + /* mask off feature bits: */
>>> + priv->rev&= ~0x30; /* not-hdcp and not-scalar bit */
>>
>>
>> If revision register contains features, why not save them for later
>> driver improvements?
>>
>
> can be added later if the need arises. I prefer to leave out code
> that only might be used later.. otherwise it is a good way to
> accumulate cruft.
True, but magic masking (~0x30) and some comments don't help either.
>>
>>> + switch (priv->rev) {
>>> + case TDA9989N2: dev_info(dev->dev, "found TDA9989 n2"); break;
>>> + case TDA19989: dev_info(dev->dev, "found TDA19989"); break;
>>> + case TDA19989N2: dev_info(dev->dev, "found TDA19989 n2"); break;
>>> + case TDA19988: dev_info(dev->dev, "found TDA19988"); break;
>>> + default:
>>> + DBG("found unsupported device: %04x", priv->rev);
>>> + goto fail;
>>> + }
>>
>>
>> I think printing revision is sufficient, no user will care about the
>> actual device or revision.
>>
>>
>>> + /* after reset, enable DDC: */
>>> + reg_write(encoder, REG_DDC_DISABLE, 0x00);
>>> +
>>> + /* set clock on DDC channel: */
>>> + reg_write(encoder, REG_TX3, 39);
>>
>>
>> This should be kept disabled as long as there is no monitor attached
>> (HPD!)
>>
>
> The sequence is based on NXP's driver.. I'll have to go back and
> check, but IIRC there were a few things I had to turn on just to make
> HPD work in the first place.
Hmm, I have seen a note about issues with some monitors that expect
ddc clock to be stable very early. And this looks like the NXP proposed
workaround to always clock ddc - but it tells nothing about the reason
and more important the note from NXP clearly puts some restrictions on
how hdmi tx needs to be clocked by pixclk. Can you ensure a stable pixclk
at this point at all?
> Ofc, if there were actually some decent docs about the part, it would
> be a bit easier to know what is actually required and what is not. So
> I don't claim everything in it's current form is optimal.
I know, everybody knows I guess. But that is what this list is for,
discussing when a driver is ready to be mainlined. And without regmap
and proper i2c client handling, I have a feeling that it is not close.
>>> + /* if necessary, disable multi-master: */
>>> + if (priv->rev == TDA19989)
>>> + reg_set(encoder, REG_I2C_MASTER, I2C_MASTER_DIS_MM);
>>> +
>>> + cec_write(encoder, REG_CEC_FRO_IM_CLK_CTRL,
>>> + CEC_FRO_IM_CLK_CTRL_GHOST_DIS |
>>> CEC_FRO_IM_CLK_CTRL_IMCLK_SEL);
>>> +
>>> + return 0;
>>> +
>>> +fail:
>>> + /* if encoder_init fails, the encoder slave is never registered,
>>> + * so cleanup here:
>>> + */
>>> + if (priv->cec)
>>> + i2c_unregister_device(priv->cec);
>>> + kfree(priv);
>>> + encoder_slave->slave_priv = NULL;
>>> + encoder_slave->slave_funcs = NULL;
>>> + return -ENXIO;
>>> +}
>>> +
>>> +static struct i2c_device_id tda998x_ids[] = {
>>> + { "tda998x", 0 },
>>> + { }
>>> +};
>>> +MODULE_DEVICE_TABLE(i2c, tda998x_ids);
>>
>>
>> Shouldn't the above carry the hdmi core i2c address at least?
>>
>
> no, it should come from the user of the encoder slave. Actually the
> CEC address should too, but current drm i2c encoder slave code sort of
> assumes the device just has a single address
Hmm, that is a limitation for sure. Well I checked drm_encoder_slave and
it is calling i2c_register_driver directly. Passing a valid i2c slave address
will work here.
For the cec i2c slave, we at least know that it is on the same i2c bus
and can probe it during _init or _probe ourselves.
Sebastian
^ permalink raw reply
* [PATCH] power/reset: restart: remove __dev{init,exit}
From: Jason Cooper @ 2013-01-31 20:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130131200250.GR29973@lunn.ch>
On Thu, Jan 31, 2013 at 09:02:50PM +0100, Andrew Lunn wrote:
> On Thu, Jan 31, 2013 at 06:54:29PM +0000, Jason Cooper wrote:
> > Signed-off-by: Jason Cooper <jason@lakedaemon.net>
>
> Hi Jason
>
> I Acked-by: a very similar patch to this yesterday....
>
> https://lkml.org/lkml/2013/1/30/233
Hmm, I need to read more carefully. My auto-flagging script didn't
catch it because it didn't have any of the mvebu/kirkwood/dove/orion
keywords in it :-(
Sorry for the noise.
thx,
Jason.
^ permalink raw reply
* [PATCH 6/6] ARM: integrator: ensure ap_syscon_base is initialised when !CONFIG_MMU
From: Linus Walleij @ 2013-01-31 20:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359556069-28289-7-git-send-email-will.deacon@arm.com>
On Wed, Jan 30, 2013 at 3:27 PM, Will Deacon <will.deacon@arm.com> wrote:
> When running on Integrator/AP using atags, ap_syscon_base is initialised
> in ->map_io, which isn't called for !MMU platforms.
Oh hm. Haha apparently there is one guy with more bizarre hobbies
than myself, you're making me feel un-geeky... ;-)
> Instead, initialise the pointer in ->machine_init, as we do when booting
> with device-tree.
I was trying to figure out if there is some case where we need it earlier
but apparently not so.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Maybe you should send this oneliner directly to the ARM SoC
people?
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH v2 4/4] irqchip: gic: Perform the gic_secondary_init() call via CPU notifier
From: Nicolas Pitre @ 2013-01-31 20:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130131175526.GE23505@n2100.arm.linux.org.uk>
On Thu, 31 Jan 2013, Russell King - ARM Linux wrote:
> On Thu, Jan 31, 2013 at 12:32:11PM -0500, Nicolas Pitre wrote:
> > On Thu, 31 Jan 2013, Russell King - ARM Linux wrote:
> >
> > > I haven't tried Versatile Express yet as it has the TC2 tile on, and I
> > > don't yet a boot loader on it which is capable of TFTP (which makes it
> > > rather useless to me - I've been saying this for a time now but this is
> > > probably the first time publically.) I'm thinking about putting the
> > > CA9x4 tile back on because that's a lot more functionally useful to me
> > > than TC2.
> >
> > You might be interested by this then:
> >
> > http://lists.linaro.org/pipermail/linaro-dev/2012-October/014136.html
>
> Great news. Everyone has been telling me that there's no uboot for TC2,
> or "we think Linaro might have something but we don't really know".
Note that I cobbled those instructions on my own and the result is not
officially supported by Linaro. This is obviously not suitable for
setting up products or demo systems, but for a kernel developer I think
such a setup is invaluable.
Nicolas
^ permalink raw reply
* [PATCH, RFC] default machine descriptor for multiplatform
From: Nicolas Pitre @ 2013-01-31 20:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1638002.UJ7zfj1Wn5@wuerfel>
On Thu, 31 Jan 2013, Arnd Bergmann wrote:
> This is what I think it would look like to do a default platform
> with an empty machine descriptor on ARM. It makes the few required
> entries in the descriptor optional by using the new irqchip_init()
> and clocksource_of_init() functions as defaults, and adds
> a fallback for the DT case to customize_machine to probe all
> the default devices.
>
> For the case that CONFIG_MULTIPLATFORM is enabled, it then
> adds a machine descriptor that never matches any machine but
> is used as a fallback if nothing else matches.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Looks sensible.
Acked-by: Nicolas Pitre <nico@linaro.org>
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 3e3444e..8ff1d38 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -979,7 +979,6 @@ config ARCH_MULTI_V7
> bool "ARMv7 based platforms (Cortex-A, PJ4, Krait)"
> default y
> select ARCH_MULTI_V6_V7
> - select ARCH_VEXPRESS
> select CPU_V7
>
> config ARCH_MULTI_V6_V7
> diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
> index 70f1bde..e6e34ba 100644
> --- a/arch/arm/kernel/devtree.c
> +++ b/arch/arm/kernel/devtree.c
> @@ -180,6 +180,13 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
> unsigned long dt_root;
> const char *model;
>
> + if (IS_ENABLED(CONFIG_ARCH_MULTIPLATFORM)) {
> + DT_MACHINE_START(GENERIC_DT, "Generic DT based system")
> + MACHINE_END
> +
> + mdesc_best = (struct machine_desc *)&__mach_desc_GENERIC_DT;
> + }
> +
> if (!dt_phys)
> return NULL;
>
> @@ -199,7 +206,7 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
> mdesc_score = score;
> }
> }
> - if (!mdesc_best) {
> + if (!mdesc_best && !IS_ENABLED(CONFIG_ARCH_MULTIPLATFORM)) {
> const char *prop;
> long size;
>
> diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
> index 8e4ef4c..df6f9a1 100644
> --- a/arch/arm/kernel/irq.c
> +++ b/arch/arm/kernel/irq.c
> @@ -26,6 +26,7 @@
> #include <linux/ioport.h>
> #include <linux/interrupt.h>
> #include <linux/irq.h>
> +#include <linux/irqchip.h>
> #include <linux/random.h>
> #include <linux/smp.h>
> #include <linux/init.h>
> @@ -114,7 +115,10 @@ EXPORT_SYMBOL_GPL(set_irq_flags);
>
> void __init init_IRQ(void)
> {
> - machine_desc->init_irq();
> + if (machine_desc->init_irq)
> + machine_desc->init_irq();
> + else
> + irqchip_init();
> }
>
> #ifdef CONFIG_MULTI_IRQ_HANDLER
> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
> index 3f6cbb2..1d40c9d 100644
> --- a/arch/arm/kernel/setup.c
> +++ b/arch/arm/kernel/setup.c
> @@ -18,6 +18,7 @@
> #include <linux/bootmem.h>
> #include <linux/seq_file.h>
> #include <linux/screen_info.h>
> +#include <linux/of_platform.h>
> #include <linux/init.h>
> #include <linux/kexec.h>
> #include <linux/of_fdt.h>
> @@ -640,9 +641,17 @@ struct screen_info screen_info = {
>
> static int __init customize_machine(void)
> {
> - /* customizes platform devices, or adds new ones */
> + /*
> + * customizes platform devices, or adds new ones
> + * On DT based machines, we fall back to populating the
> + * machine from the device tree, if no callback is provided,
> + * otherwise we would always need an init_machine callback.
> + */
> if (machine_desc->init_machine)
> machine_desc->init_machine();
> + else
> + of_platform_populate(NULL, of_default_bus_match_table,
> + NULL, NULL);
> return 0;
> }
> arch_initcall(customize_machine);
> @@ -732,7 +741,7 @@ void __init setup_arch(char **cmdline_p)
>
> setup_processor();
> mdesc = setup_machine_fdt(__atags_pointer);
> - if (!mdesc)
> + if (!mdesc && __machine_arch_type != ~0)
> mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);
> machine_desc = mdesc;
> machine_name = mdesc->name;
> diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
> index 955d92d..abff4e9 100644
> --- a/arch/arm/kernel/time.c
> +++ b/arch/arm/kernel/time.c
> @@ -22,6 +22,7 @@
> #include <linux/errno.h>
> #include <linux/profile.h>
> #include <linux/timer.h>
> +#include <linux/clocksource.h>
> #include <linux/irq.h>
>
> #include <asm/thread_info.h>
> @@ -115,6 +116,10 @@ int __init register_persistent_clock(clock_access_fn read_boot,
>
> void __init time_init(void)
> {
> - machine_desc->init_time();
> + if (machine_desc->init_time)
> + machine_desc->init_time();
> + else
> + clocksource_of_init();
> +
> sched_clock_postinit();
> }
> diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c
> index f496afc..c5e7a45 100644
> --- a/drivers/irqchip/irqchip.c
> +++ b/drivers/irqchip/irqchip.c
> @@ -24,7 +24,13 @@ irqchip_of_match_end __used __section(__irqchip_of_end);
>
> extern struct of_device_id __irqchip_begin[];
>
> +#ifdef CONFIG_IRQCHIP
> void __init irqchip_init(void)
> {
> of_irq_init(__irqchip_begin);
> }
> +#else
> +static inline void irqchip_init(void)
> +{
> +}
> +#endif
> diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
> index 7944f14..b14d224 100644
> --- a/include/linux/clocksource.h
> +++ b/include/linux/clocksource.h
> @@ -339,6 +339,10 @@ extern void clocksource_of_init(void);
> static const struct of_device_id __clksrc_of_table_##name \
> __used __section(__clksrc_of_table) \
> = { .compatible = compat, .data = fn };
> +#else
> +static inline void clocksource_of_init(void)
> +{
> +}
> #endif
>
> #endif /* _LINUX_CLOCKSOURCE_H */
>
^ permalink raw reply
* [PATCH v2 19/27] pci: PCIe driver for Marvell Armada 370/XP systems
From: Arnd Bergmann @ 2013-01-31 20:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130131180249.GA30869@obsidianresearch.com>
On Thursday 31 January 2013, Jason Gunthorpe wrote:
> Thinking about this some more, which of these methods to choose is
> going to be dictated by what the Marvell HW does.
>
> Since the IO space in the TLP is a full 32 bits, it matters what 32
> bit value the HW PCI core places in the IO Rd/Wr transaction. This
> value must match the value given to the Linux PCI core for resource
> allocation, because it must be correctly programmed by Linux into the
> downstream BARs/bridge windows.
>
> So there are probably two choices for what the HW does, given a MBUS
> window of 0xDEAD0000 -> 0xDEADFFFF set for IO, a read from physical
> address 0xDEAD0000 produces a IO Rd TLP with either '0x00000000' or
> '0xDEAD0000' in the address field.
>
> If it is 0xDEAD0000, then Thomas has to keep what he has now, you
> can't mess with this address. Verify that the full 32 bit address
> exactly matching the MBUS window address is written to the PCI-PCI
> bridge IO base/limit registers.
If you do this, you break all sorts of expectations in the kernel and
I guess you'd have to set the io_offset value of that bus to 0x21530000
in order to make Linux I/O port 0 go to the first byte of the window
and come out as 0xDEAD0000 on the bus, but you still won't be able to
use legacy devices with hardcoded I/O port numbers.
> If it is 0x00000000 then the mmap scheme I outlined before must be
> used, and verify that only 0->0xFFFF is written to the PCI-PCI bridge
> IO base/limit registers..
For the primary bus, yes, but there are still two options for the
second one: you can either start at 0 again or you can continue
at 0x10000 as we do for mv78xx0 and kirkwood for instance. Both
approaches probably have their merit.
Arnd
^ permalink raw reply
* [PATCH 05/10] gpio: pxa: remove gpio_type
From: Linus Walleij @ 2013-01-31 20:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <51066118.1000200@compulab.co.il>
On Mon, Jan 28, 2013 at 12:29 PM, Igor Grinberg <grinberg@compulab.co.il> wrote:
> On 01/25/13 12:01, Linus Walleij wrote:
>> On Wed, Jan 23, 2013 at 9:25 AM, Haojian Zhuang
>> <haojian.zhuang@linaro.org> wrote:
>>
>>> Since gpio_type is used to check whether gafr register is valid. So
>>> move it into platform data.
>>>
>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>
>> (...)
>>
>>> +++ b/drivers/gpio/gpio-pxa.c
>>> @@ -72,6 +72,7 @@ struct pxa_gpio_chip {
>>> void __iomem *regbase;
>>> unsigned int irq_base;
>>> unsigned int inverted;
>>> + unsigned int gafr;
>>> char label[10];
>>
>> Also looks like some kind of a bool.
>
> Actually, no... GAFR is the PXA Alternate Function register name,
> so unsigned int (or u32) is good.
Alternate funtion register?
Thanks for telling!
So this is about muxing and should thus be in the pinctrl
framework?
Or is there some criss-cross with pinctrl already that I'm
not aware of?
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 1/6 v14] gpio: Add a block GPIO API to gpiolib
From: Linus Walleij @ 2013-01-31 20:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOY=C6GReEpO7ukOS8WiQgdFFAreaYK1YrZ8HQrQ9dGMFObAdQ@mail.gmail.com>
On Mon, Jan 28, 2013 at 12:30 PM, Stijn Devriendt <highguy@gmail.com> wrote:
> This is one of the warts of the GPIO API, if you ask me (and probably
> others too).
> Using a resource without allocating it first is just asking for
> trouble. It's one of those
> things pinctl was designed to solve... I've been thinking about
> spending spare time
> sending out patches converting all implicit requests and then removing
> the implicit
> request, but spare time is limited...
It would be much appreciated. We can make good use of all
help we can get in this area...
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH, RFC] default machine descriptor for multiplatform
From: Arnd Bergmann @ 2013-01-31 20:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <510ABD70.1020408@wwwdotorg.org>
On Thursday 31 January 2013, Stephen Warren wrote:
> With that change, we can remove the custom .init_machine() functions for
> all of Tegra, since they just do that:-)
Yes, actually quite a lot of them have the same code, and we also have
an increasing number of users of the irqchip_init and clocksource_of_init,
so those can also be cleaned up as a follow-on to this patch.
The main thing that has to remain for a lot of the platforms is SMP
support, and I don't see a good way around that yet.
> > diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c
>
> > +#ifdef CONFIG_IRQCHIP
> > void __init irqchip_init(void)
> > {
> > of_irq_init(__irqchip_begin);
> > }
> > +#else
> > +static inline void irqchip_init(void)
> > +{
> > +}
> > +#endif
>
> That'd need to go in a header file.
Yep, you're right, my mistake.
Arnd
^ 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