* [PATCH v2 0/2] arm: omap3: am35x: Convert emac to hwmod & disable hlt when open
@ 2012-05-15 18:14 Mark A. Greer
2012-05-15 18:14 ` [PATCH v2 1/2] arm: omap3: am35x: Add Davinci EMAC/MDIO hwmod support Mark A. Greer
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Mark A. Greer @ 2012-05-15 18:14 UTC (permalink / raw)
To: paul, khilman; +Cc: linux-arm-kernel, linux-omap, Mark A. Greer
From: "Mark A. Greer" <mgreer@animalcreek.com>
These patches convert the davinci emac support for the am35x SoC
to use hwmod and add enable_hlt()/disable_hlt() calls to the
pm_runtime hooks for that driver.
I have converted the davinci_emac driver to use pm_runtime but I
can't formally submit it yet since it requires some changes on the
mach-davinci side that haven't happened yet. I will send it as an
RFC in a reply to this thread.
The patches are based on:
git://git.pwsan.com/linux-2.6 am35xx_hwmod_data_fixes_a_3.5
Changes from v1:
- patch 1/2, "arm: omap3: am35x: Add Davinci EMAC/MDIO hwmod support"
is unchanged
- patch 2/2, "arm: "omap3: am35x: Disable hlt when using Davinci EMAC"
has been reworked to keep the code as simple as possible per
http://www.spinics.net/lists/linux-omap/msg70354.html
Mark
--
Mark A. Greer (2):
arm: omap3: am35x: Add Davinci EMAC/MDIO hwmod support
arm: omap3: am35x: Disable hlt when using Davinci EMAC
arch/arm/mach-omap2/am35xx-emac.c | 116 ++++++++++++++++++----------
arch/arm/mach-omap2/clock3xxx_data.c | 2 +-
arch/arm/mach-omap2/include/mach/am35xx.h | 2 +
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 85 ++++++++++++++++++++
4 files changed, 163 insertions(+), 42 deletions(-)
--
1.7.9.4
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v2 1/2] arm: omap3: am35x: Add Davinci EMAC/MDIO hwmod support 2012-05-15 18:14 [PATCH v2 0/2] arm: omap3: am35x: Convert emac to hwmod & disable hlt when open Mark A. Greer @ 2012-05-15 18:14 ` Mark A. Greer 2012-06-27 21:19 ` Paul Walmsley 2012-06-27 21:24 ` Paul Walmsley 2012-05-15 18:14 ` [PATCH v2 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC Mark A. Greer ` (2 subsequent siblings) 3 siblings, 2 replies; 9+ messages in thread From: Mark A. Greer @ 2012-05-15 18:14 UTC (permalink / raw) To: paul, khilman; +Cc: linux-arm-kernel, linux-omap, Mark A. Greer From: "Mark A. Greer" <mgreer@animalcreek.com> Add hwmod support for the EMAC (and MDIO) ethernet controller that's on the am35x family of SoC's. Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> --- arch/arm/mach-omap2/am35xx-emac.c | 92 ++++++++++++++-------------- arch/arm/mach-omap2/clock3xxx_data.c | 2 +- arch/arm/mach-omap2/include/mach/am35xx.h | 2 + arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 85 +++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 46 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 1f97e74..3bb5cb3 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -15,27 +15,13 @@ * General Public License for more details. */ -#include <linux/clk.h> +#include <linux/err.h> #include <linux/davinci_emac.h> -#include <linux/platform_device.h> -#include <plat/irqs.h> +#include <asm/system.h> +#include <plat/omap_device.h> #include <mach/am35xx.h> - #include "control.h" - -static struct mdio_platform_data am35xx_emac_mdio_pdata; - -static struct resource am35xx_emac_mdio_resources[] = { - DEFINE_RES_MEM(AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET, SZ_4K), -}; - -static struct platform_device am35xx_emac_mdio_device = { - .name = "davinci_mdio", - .id = 0, - .num_resources = ARRAY_SIZE(am35xx_emac_mdio_resources), - .resource = am35xx_emac_mdio_resources, - .dev.platform_data = &am35xx_emac_mdio_pdata, -}; +#include "am35xx-emac.h" static void am35xx_enable_emac_int(void) { @@ -72,41 +58,57 @@ static struct emac_platform_data am35xx_emac_pdata = { .interrupt_disable = am35xx_disable_emac_int, }; -static struct resource am35xx_emac_resources[] = { - DEFINE_RES_MEM(AM35XX_IPSS_EMAC_BASE, 0x30000), - DEFINE_RES_IRQ(INT_35XX_EMAC_C0_RXTHRESH_IRQ), - DEFINE_RES_IRQ(INT_35XX_EMAC_C0_RX_PULSE_IRQ), - DEFINE_RES_IRQ(INT_35XX_EMAC_C0_TX_PULSE_IRQ), - DEFINE_RES_IRQ(INT_35XX_EMAC_C0_MISC_PULSE_IRQ), -}; +static struct mdio_platform_data am35xx_mdio_pdata; -static struct platform_device am35xx_emac_device = { - .name = "davinci_emac", - .id = -1, - .num_resources = ARRAY_SIZE(am35xx_emac_resources), - .resource = am35xx_emac_resources, - .dev = { - .platform_data = &am35xx_emac_pdata, - }, -}; +static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, + void *pdata, int pdata_len) +{ + struct platform_device *pdev; + + pdev = omap_device_build(oh->class->name, 0, oh, pdata, pdata_len, + NULL, 0, false); + if (IS_ERR(pdev)) { + WARN(1, "Can't build omap_device for %s:%s.\n", + oh->class->name, oh->name); + return PTR_ERR(pdev); + } + + return 0; +} void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) { - unsigned int regval; - int err; + struct omap_hwmod *oh; + u32 regval; + int ret; - am35xx_emac_pdata.rmii_en = rmii_en; - am35xx_emac_mdio_pdata.bus_freq = mdio_bus_freq; - err = platform_device_register(&am35xx_emac_device); - if (err) { - pr_err("AM35x: failed registering EMAC device: %d\n", err); + oh = omap_hwmod_lookup("davinci_mdio"); + if (!oh) { + pr_err("Could not find davinci_mdio hwmod\n"); + return; + } + + am35xx_mdio_pdata.bus_freq = mdio_bus_freq; + + ret = omap_davinci_emac_dev_init(oh, &am35xx_mdio_pdata, + sizeof(am35xx_mdio_pdata)); + if (ret) { + pr_err("Could not build davinci_mdio hwmod device\n"); return; } - err = platform_device_register(&am35xx_emac_mdio_device); - if (err) { - pr_err("AM35x: failed registering EMAC MDIO device: %d\n", err); - platform_device_unregister(&am35xx_emac_device); + oh = omap_hwmod_lookup("davinci_emac"); + if (!oh) { + pr_err("Could not find davinci_emac hwmod\n"); + return; + } + + am35xx_emac_pdata.rmii_en = rmii_en; + + ret = omap_davinci_emac_dev_init(oh, &am35xx_emac_pdata, + sizeof(am35xx_emac_pdata)); + if (ret) { + pr_err("Could not build davinci_emac hwmod device\n"); return; } diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 12c64db..f2f422e 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3478,7 +3478,7 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "ipss_ick", &ipss_ick, CK_AM35XX), CLK(NULL, "rmii_ck", &rmii_ck, CK_AM35XX), CLK(NULL, "pclk_ck", &pclk_ck, CK_AM35XX), - CLK("davinci_emac", NULL, &emac_ick, CK_AM35XX), + CLK("davinci_emac.0", NULL, &emac_ick, CK_AM35XX), CLK("davinci_mdio.0", NULL, &emac_fck, CK_AM35XX), CLK("vpfe-capture", "master", &vpfe_ick, CK_AM35XX), CLK("vpfe-capture", "slave", &vpfe_fck, CK_AM35XX), diff --git a/arch/arm/mach-omap2/include/mach/am35xx.h b/arch/arm/mach-omap2/include/mach/am35xx.h index f1e13d1..9559449 100644 --- a/arch/arm/mach-omap2/include/mach/am35xx.h +++ b/arch/arm/mach-omap2/include/mach/am35xx.h @@ -36,6 +36,8 @@ #define AM35XX_EMAC_CNTRL_MOD_OFFSET (0x0) #define AM35XX_EMAC_CNTRL_RAM_OFFSET (0x20000) #define AM35XX_EMAC_MDIO_OFFSET (0x30000) +#define AM35XX_IPSS_MDIO_BASE (AM35XX_IPSS_EMAC_BASE + \ + AM35XX_EMAC_MDIO_OFFSET) #define AM35XX_EMAC_CNTRL_RAM_SIZE (0x2000) #define AM35XX_EMAC_RAM_ADDR (AM3517_EMAC_BASE + \ AM3517_EMAC_CNTRL_RAM_OFFSET) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index c6653a80..87d817d 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -3075,6 +3075,87 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_tll_hs = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* am35xx has Davinci MDIO & EMAC */ +static struct omap_hwmod_class am35xx_mdio_class = { + .name = "davinci_mdio", +}; + +static struct omap_hwmod am35xx_mdio_hwmod = { + .name = "davinci_mdio", + .class = &am35xx_mdio_class, + .flags = HWMOD_NO_IDLEST, +}; + +static struct omap_hwmod_ocp_if am35xx_mdio__l3 = { + .master = &am35xx_mdio_hwmod, + .slave = &omap3xxx_l3_main_hwmod, + .clk = "emac_fck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space am35xx_mdio_addrs[] = { + { + .pa_start = AM35XX_IPSS_MDIO_BASE, + .pa_end = AM35XX_IPSS_MDIO_BASE + SZ_4K - 1, + .flags = ADDR_TYPE_RT, + }, + { } +}; + +/* l4_core -> davinci mdio */ +static struct omap_hwmod_ocp_if am35xx_l4_core__mdio = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &am35xx_mdio_hwmod, + .clk = "emac_fck", + .addr = am35xx_mdio_addrs, + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_irq_info am35xx_emac_mpu_irqs[] = { + { .name = "rxthresh", .irq = INT_35XX_EMAC_C0_RXTHRESH_IRQ }, + { .name = "rx_pulse", .irq = INT_35XX_EMAC_C0_RX_PULSE_IRQ }, + { .name = "tx_pulse", .irq = INT_35XX_EMAC_C0_TX_PULSE_IRQ }, + { .name = "misc_pulse", .irq = INT_35XX_EMAC_C0_MISC_PULSE_IRQ }, + { .irq = -1 } +}; + +static struct omap_hwmod_class am35xx_emac_class = { + .name = "davinci_emac", +}; + +static struct omap_hwmod am35xx_emac_hwmod = { + .name = "davinci_emac", + .mpu_irqs = am35xx_emac_mpu_irqs, + .class = &am35xx_emac_class, + .flags = HWMOD_NO_IDLEST, +}; + +/* l3_core -> davinci emac interface */ +static struct omap_hwmod_ocp_if am35xx_emac__l3 = { + .master = &am35xx_emac_hwmod, + .slave = &omap3xxx_l3_main_hwmod, + .clk = "emac_ick", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space am35xx_emac_addrs[] = { + { + .pa_start = AM35XX_IPSS_EMAC_BASE, + .pa_end = AM35XX_IPSS_EMAC_BASE + 0x30000 - 1, + .flags = ADDR_TYPE_RT, + }, + { } +}; + +/* l4_core -> davinci emac */ +static struct omap_hwmod_ocp_if am35xx_l4_core__emac = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &am35xx_emac_hwmod, + .clk = "emac_ick", + .addr = am35xx_emac_addrs, + .user = OCP_USER_MPU, +}; + static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = { &omap3xxx_l3_main__l4_core, &omap3xxx_l3_main__l4_per, @@ -3200,6 +3281,10 @@ static struct omap_hwmod_ocp_if *am35xx_hwmod_ocp_ifs[] __initdata = { &omap3xxx_l4_core__usb_tll_hs, &omap3xxx_l4_core__es3plus_mmc1, &omap3xxx_l4_core__es3plus_mmc2, + &am35xx_mdio__l3, + &am35xx_l4_core__mdio, + &am35xx_emac__l3, + &am35xx_l4_core__emac, NULL }; -- 1.7.9.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] arm: omap3: am35x: Add Davinci EMAC/MDIO hwmod support 2012-05-15 18:14 ` [PATCH v2 1/2] arm: omap3: am35x: Add Davinci EMAC/MDIO hwmod support Mark A. Greer @ 2012-06-27 21:19 ` Paul Walmsley 2012-06-27 21:24 ` Paul Walmsley 1 sibling, 0 replies; 9+ messages in thread From: Paul Walmsley @ 2012-06-27 21:19 UTC (permalink / raw) To: Mark A. Greer; +Cc: khilman, linux-arm-kernel, linux-omap Hi On Tue, 15 May 2012, Mark A. Greer wrote: > From: "Mark A. Greer" <mgreer@animalcreek.com> > > Add hwmod support for the EMAC (and MDIO) > ethernet controller that's on the am35x > family of SoC's. > > Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> I had to update this patch to apply on v3.5-rc4; updated patch below. - Paul From: "Mark A. Greer" <mgreer@animalcreek.com> Date: Wed, 27 Jun 2012 14:59:57 -0600 Subject: [PATCH 1/2] ARM: OMAP AM35x: EMAC/MDIO integration: Add Davinci EMAC/MDIO hwmod support Add hwmod support for the EMAC (and MDIO) ethernet controller that's on the am35x family of SoC's. Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> [paul@pwsan.com: updated subject line; updated to apply on v3.5-rc4] Signed-off-by: Paul Walmsley <paul@pwsan.com> --- arch/arm/mach-omap2/am35xx-emac.c | 90 ++++++++++++++-------------- arch/arm/mach-omap2/clock3xxx_data.c | 2 +- arch/arm/mach-omap2/include/mach/am35xx.h | 2 + arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 85 ++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 45 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 447682c..2c90ac6 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -15,27 +15,13 @@ * General Public License for more details. */ -#include <linux/clk.h> +#include <linux/err.h> #include <linux/davinci_emac.h> -#include <linux/platform_device.h> -#include <plat/irqs.h> +#include <asm/system.h> +#include <plat/omap_device.h> #include <mach/am35xx.h> - #include "control.h" - -static struct mdio_platform_data am35xx_emac_mdio_pdata; - -static struct resource am35xx_emac_mdio_resources[] = { - DEFINE_RES_MEM(AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET, SZ_4K), -}; - -static struct platform_device am35xx_emac_mdio_device = { - .name = "davinci_mdio", - .id = 0, - .num_resources = ARRAY_SIZE(am35xx_emac_mdio_resources), - .resource = am35xx_emac_mdio_resources, - .dev.platform_data = &am35xx_emac_mdio_pdata, -}; +#include "am35xx-emac.h" static void am35xx_enable_emac_int(void) { @@ -69,41 +55,57 @@ static struct emac_platform_data am35xx_emac_pdata = { .interrupt_disable = am35xx_disable_emac_int, }; -static struct resource am35xx_emac_resources[] = { - DEFINE_RES_MEM(AM35XX_IPSS_EMAC_BASE, 0x30000), - DEFINE_RES_IRQ(INT_35XX_EMAC_C0_RXTHRESH_IRQ), - DEFINE_RES_IRQ(INT_35XX_EMAC_C0_RX_PULSE_IRQ), - DEFINE_RES_IRQ(INT_35XX_EMAC_C0_TX_PULSE_IRQ), - DEFINE_RES_IRQ(INT_35XX_EMAC_C0_MISC_PULSE_IRQ), -}; +static struct mdio_platform_data am35xx_mdio_pdata; -static struct platform_device am35xx_emac_device = { - .name = "davinci_emac", - .id = -1, - .num_resources = ARRAY_SIZE(am35xx_emac_resources), - .resource = am35xx_emac_resources, - .dev = { - .platform_data = &am35xx_emac_pdata, - }, -}; +static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, + void *pdata, int pdata_len) +{ + struct platform_device *pdev; + + pdev = omap_device_build(oh->class->name, 0, oh, pdata, pdata_len, + NULL, 0, false); + if (IS_ERR(pdev)) { + WARN(1, "Can't build omap_device for %s:%s.\n", + oh->class->name, oh->name); + return PTR_ERR(pdev); + } + + return 0; +} void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) { + struct omap_hwmod *oh; u32 v; - int err; + int ret; - am35xx_emac_pdata.rmii_en = rmii_en; - am35xx_emac_mdio_pdata.bus_freq = mdio_bus_freq; - err = platform_device_register(&am35xx_emac_device); - if (err) { - pr_err("AM35x: failed registering EMAC device: %d\n", err); + oh = omap_hwmod_lookup("davinci_mdio"); + if (!oh) { + pr_err("Could not find davinci_mdio hwmod\n"); + return; + } + + am35xx_mdio_pdata.bus_freq = mdio_bus_freq; + + ret = omap_davinci_emac_dev_init(oh, &am35xx_mdio_pdata, + sizeof(am35xx_mdio_pdata)); + if (ret) { + pr_err("Could not build davinci_mdio hwmod device\n"); return; } - err = platform_device_register(&am35xx_emac_mdio_device); - if (err) { - pr_err("AM35x: failed registering EMAC MDIO device: %d\n", err); - platform_device_unregister(&am35xx_emac_device); + oh = omap_hwmod_lookup("davinci_emac"); + if (!oh) { + pr_err("Could not find davinci_emac hwmod\n"); + return; + } + + am35xx_emac_pdata.rmii_en = rmii_en; + + ret = omap_davinci_emac_dev_init(oh, &am35xx_emac_pdata, + sizeof(am35xx_emac_pdata)); + if (ret) { + pr_err("Could not build davinci_emac hwmod device\n"); return; } diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 1efdec2..10c1395 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3474,7 +3474,7 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "ipss_ick", &ipss_ick, CK_AM35XX), CLK(NULL, "rmii_ck", &rmii_ck, CK_AM35XX), CLK(NULL, "pclk_ck", &pclk_ck, CK_AM35XX), - CLK("davinci_emac", NULL, &emac_ick, CK_AM35XX), + CLK("davinci_emac.0", NULL, &emac_ick, CK_AM35XX), CLK("davinci_mdio.0", NULL, &emac_fck, CK_AM35XX), CLK("vpfe-capture", "master", &vpfe_ick, CK_AM35XX), CLK("vpfe-capture", "slave", &vpfe_fck, CK_AM35XX), diff --git a/arch/arm/mach-omap2/include/mach/am35xx.h b/arch/arm/mach-omap2/include/mach/am35xx.h index f1e13d1..9559449 100644 --- a/arch/arm/mach-omap2/include/mach/am35xx.h +++ b/arch/arm/mach-omap2/include/mach/am35xx.h @@ -36,6 +36,8 @@ #define AM35XX_EMAC_CNTRL_MOD_OFFSET (0x0) #define AM35XX_EMAC_CNTRL_RAM_OFFSET (0x20000) #define AM35XX_EMAC_MDIO_OFFSET (0x30000) +#define AM35XX_IPSS_MDIO_BASE (AM35XX_IPSS_EMAC_BASE + \ + AM35XX_EMAC_MDIO_OFFSET) #define AM35XX_EMAC_CNTRL_RAM_SIZE (0x2000) #define AM35XX_EMAC_RAM_ADDR (AM3517_EMAC_BASE + \ AM3517_EMAC_CNTRL_RAM_OFFSET) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index b26d3c9..f33e8d5 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -3138,6 +3138,87 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__counter_32k = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* am35xx has Davinci MDIO & EMAC */ +static struct omap_hwmod_class am35xx_mdio_class = { + .name = "davinci_mdio", +}; + +static struct omap_hwmod am35xx_mdio_hwmod = { + .name = "davinci_mdio", + .class = &am35xx_mdio_class, + .flags = HWMOD_NO_IDLEST, +}; + +static struct omap_hwmod_ocp_if am35xx_mdio__l3 = { + .master = &am35xx_mdio_hwmod, + .slave = &omap3xxx_l3_main_hwmod, + .clk = "emac_fck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space am35xx_mdio_addrs[] = { + { + .pa_start = AM35XX_IPSS_MDIO_BASE, + .pa_end = AM35XX_IPSS_MDIO_BASE + SZ_4K - 1, + .flags = ADDR_TYPE_RT, + }, + { } +}; + +/* l4_core -> davinci mdio */ +static struct omap_hwmod_ocp_if am35xx_l4_core__mdio = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &am35xx_mdio_hwmod, + .clk = "emac_fck", + .addr = am35xx_mdio_addrs, + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_irq_info am35xx_emac_mpu_irqs[] = { + { .name = "rxthresh", .irq = INT_35XX_EMAC_C0_RXTHRESH_IRQ }, + { .name = "rx_pulse", .irq = INT_35XX_EMAC_C0_RX_PULSE_IRQ }, + { .name = "tx_pulse", .irq = INT_35XX_EMAC_C0_TX_PULSE_IRQ }, + { .name = "misc_pulse", .irq = INT_35XX_EMAC_C0_MISC_PULSE_IRQ }, + { .irq = -1 } +}; + +static struct omap_hwmod_class am35xx_emac_class = { + .name = "davinci_emac", +}; + +static struct omap_hwmod am35xx_emac_hwmod = { + .name = "davinci_emac", + .mpu_irqs = am35xx_emac_mpu_irqs, + .class = &am35xx_emac_class, + .flags = HWMOD_NO_IDLEST, +}; + +/* l3_core -> davinci emac interface */ +static struct omap_hwmod_ocp_if am35xx_emac__l3 = { + .master = &am35xx_emac_hwmod, + .slave = &omap3xxx_l3_main_hwmod, + .clk = "emac_ick", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space am35xx_emac_addrs[] = { + { + .pa_start = AM35XX_IPSS_EMAC_BASE, + .pa_end = AM35XX_IPSS_EMAC_BASE + 0x30000 - 1, + .flags = ADDR_TYPE_RT, + }, + { } +}; + +/* l4_core -> davinci emac */ +static struct omap_hwmod_ocp_if am35xx_l4_core__emac = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &am35xx_emac_hwmod, + .clk = "emac_ick", + .addr = am35xx_emac_addrs, + .user = OCP_USER_MPU, +}; + static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = { &omap3xxx_l3_main__l4_core, &omap3xxx_l3_main__l4_per, @@ -3266,6 +3347,10 @@ static struct omap_hwmod_ocp_if *am35xx_hwmod_ocp_ifs[] __initdata = { &omap3xxx_l4_core__usb_tll_hs, &omap3xxx_l4_core__es3plus_mmc1, &omap3xxx_l4_core__es3plus_mmc2, + &am35xx_mdio__l3, + &am35xx_l4_core__mdio, + &am35xx_emac__l3, + &am35xx_l4_core__emac, NULL }; -- 1.7.10 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] arm: omap3: am35x: Add Davinci EMAC/MDIO hwmod support 2012-05-15 18:14 ` [PATCH v2 1/2] arm: omap3: am35x: Add Davinci EMAC/MDIO hwmod support Mark A. Greer 2012-06-27 21:19 ` Paul Walmsley @ 2012-06-27 21:24 ` Paul Walmsley 1 sibling, 0 replies; 9+ messages in thread From: Paul Walmsley @ 2012-06-27 21:24 UTC (permalink / raw) To: Mark A. Greer; +Cc: khilman, linux-arm-kernel, linux-omap Hi one comment on this one On Tue, 15 May 2012, Mark A. Greer wrote: > From: "Mark A. Greer" <mgreer@animalcreek.com> > > Add hwmod support for the EMAC (and MDIO) > ethernet controller that's on the am35x > family of SoC's. > > Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> > +static struct omap_hwmod_ocp_if am35xx_mdio__l3 = { > + .master = &am35xx_mdio_hwmod, > + .slave = &omap3xxx_l3_main_hwmod, > + .clk = "emac_fck", > + .user = OCP_USER_MPU, > +}; ... > +/* l4_core -> davinci mdio */ > +static struct omap_hwmod_ocp_if am35xx_l4_core__mdio = { > + .master = &omap3xxx_l4_core_hwmod, > + .slave = &am35xx_mdio_hwmod, > + .clk = "emac_fck", > + .addr = am35xx_mdio_addrs, > + .user = OCP_USER_MPU, > +}; ... > +/* l4_core -> davinci emac */ > +static struct omap_hwmod_ocp_if am35xx_l4_core__emac = { > + .master = &omap3xxx_l4_core_hwmod, > + .slave = &am35xx_emac_hwmod, > + .clk = "emac_ick", > + .addr = am35xx_emac_addrs, > + .user = OCP_USER_MPU, > +}; As I understand it, these devices are actually directly connected to the IPSS. However, for such a topology to work correctly, we'll probably need some changes in the hwmod core. I had hoped to have this done for 3.6, but that's looking pretty unlikely. So instead, will drop some comments in the data to note that this will need to be fixed. - Paul ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC 2012-05-15 18:14 [PATCH v2 0/2] arm: omap3: am35x: Convert emac to hwmod & disable hlt when open Mark A. Greer 2012-05-15 18:14 ` [PATCH v2 1/2] arm: omap3: am35x: Add Davinci EMAC/MDIO hwmod support Mark A. Greer @ 2012-05-15 18:14 ` Mark A. Greer 2012-05-31 18:58 ` Kevin Hilman 2012-06-27 21:20 ` Paul Walmsley 2012-05-31 18:57 ` [PATCH v2 0/2] arm: omap3: am35x: Convert emac to hwmod & disable hlt when open Kevin Hilman 2012-06-27 21:58 ` Paul Walmsley 3 siblings, 2 replies; 9+ messages in thread From: Mark A. Greer @ 2012-05-15 18:14 UTC (permalink / raw) To: paul, khilman; +Cc: linux-arm-kernel, linux-omap, Mark A. Greer From: "Mark A. Greer" <mgreer@animalcreek.com> The am35x family of SoCs has a Davinci EMAC ethernet controller on-chip. Unfortunately, the EMAC is unable to wake the PRCM when there is network activity which leads to a hung or extremely slow system when the MPU has executed a 'wfi' instruction (because of pm_idle or CPUidle). To prevent this, add hooks to the EMAC pm_runtime suspend/resume calls so that hlt is disabled whenever the EMAC is in use. Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> --- arch/arm/mach-omap2/am35xx-emac.c | 40 +++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 3bb5cb3..887a057 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -23,6 +23,35 @@ #include "control.h" #include "am35xx-emac.h" +/* + * Default pm_lats for the am35x. + * The net effect of using am35xx_emac_pm_lats[] is that + * pm_idle or CPUidle won't be called while the emac + * interface is open. This is required because the + * EMAC can't wake up PRCM so if the MPU is executing + * a 'wfi' instruction (e.g., from pm_idle or CPUidle), + * it won't break out of it due to emac activity. + */ +static int am35xx_emac_deactivate_func(struct omap_device *od) +{ + enable_hlt(); + return omap_device_idle_hwmods(od); +} + +static int am35xx_emac_activate_func(struct omap_device *od) +{ + disable_hlt(); + return omap_device_enable_hwmods(od); +} + +static struct omap_device_pm_latency am35xx_emac_pm_lats[] = { + { + .deactivate_func = am35xx_emac_deactivate_func, + .activate_func = am35xx_emac_activate_func, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + static void am35xx_enable_emac_int(void) { u32 regval; @@ -61,12 +90,13 @@ static struct emac_platform_data am35xx_emac_pdata = { static struct mdio_platform_data am35xx_mdio_pdata; static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, - void *pdata, int pdata_len) + void *pdata, int pdata_len, + struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct platform_device *pdev; pdev = omap_device_build(oh->class->name, 0, oh, pdata, pdata_len, - NULL, 0, false); + pm_lats, pm_lats_size, false); if (IS_ERR(pdev)) { WARN(1, "Can't build omap_device for %s:%s.\n", oh->class->name, oh->name); @@ -91,7 +121,7 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_mdio_pdata.bus_freq = mdio_bus_freq; ret = omap_davinci_emac_dev_init(oh, &am35xx_mdio_pdata, - sizeof(am35xx_mdio_pdata)); + sizeof(am35xx_mdio_pdata), NULL, 0); if (ret) { pr_err("Could not build davinci_mdio hwmod device\n"); return; @@ -106,7 +136,9 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_emac_pdata.rmii_en = rmii_en; ret = omap_davinci_emac_dev_init(oh, &am35xx_emac_pdata, - sizeof(am35xx_emac_pdata)); + sizeof(am35xx_emac_pdata), + am35xx_emac_pm_lats, + ARRAY_SIZE(am35xx_emac_pm_lats)); if (ret) { pr_err("Could not build davinci_emac hwmod device\n"); return; -- 1.7.9.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC 2012-05-15 18:14 ` [PATCH v2 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC Mark A. Greer @ 2012-05-31 18:58 ` Kevin Hilman 2012-06-27 21:20 ` Paul Walmsley 1 sibling, 0 replies; 9+ messages in thread From: Kevin Hilman @ 2012-05-31 18:58 UTC (permalink / raw) To: Mark A. Greer; +Cc: paul, linux-arm-kernel, linux-omap "Mark A. Greer" <mgreer@animalcreek.com> writes: > From: "Mark A. Greer" <mgreer@animalcreek.com> > > The am35x family of SoCs has a Davinci EMAC ethernet > controller on-chip. Unfortunately, the EMAC is unable > to wake the PRCM when there is network activity which > leads to a hung or extremely slow system when the MPU > has executed a 'wfi' instruction (because of pm_idle > or CPUidle). To prevent this, add hooks to the EMAC > pm_runtime suspend/resume calls so that hlt is disabled > whenever the EMAC is in use. > > Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> Looks good, Acked-by: Kevin Hilman <khilman@ti.com> ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC 2012-05-15 18:14 ` [PATCH v2 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC Mark A. Greer 2012-05-31 18:58 ` Kevin Hilman @ 2012-06-27 21:20 ` Paul Walmsley 1 sibling, 0 replies; 9+ messages in thread From: Paul Walmsley @ 2012-06-27 21:20 UTC (permalink / raw) To: Mark A. Greer; +Cc: khilman, linux-arm-kernel, linux-omap Hi On Tue, 15 May 2012, Mark A. Greer wrote: > From: "Mark A. Greer" <mgreer@animalcreek.com> > > The am35x family of SoCs has a Davinci EMAC ethernet > controller on-chip. Unfortunately, the EMAC is unable > to wake the PRCM when there is network activity which > leads to a hung or extremely slow system when the MPU > has executed a 'wfi' instruction (because of pm_idle > or CPUidle). To prevent this, add hooks to the EMAC > pm_runtime suspend/resume calls so that hlt is disabled > whenever the EMAC is in use. > > Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> This patch has been updated to apply on v3.5-rc4; updated patch below. - Paul From: "Mark A. Greer" <mgreer@animalcreek.com> Date: Wed, 27 Jun 2012 15:03:20 -0600 Subject: [PATCH 2/2] ARM: OMAP AM35x: EMAC integration: Disable hlt when using Davinci EMAC The am35x family of SoCs has a Davinci EMAC ethernet controller on-chip. Unfortunately, the EMAC is unable to wake the PRCM when there is network activity which leads to a hung or extremely slow system when the MPU has executed a 'wfi' instruction (because of pm_idle or CPUidle). To prevent this, add hooks to the EMAC pm_runtime suspend/resume calls so that hlt is disabled whenever the EMAC is in use. Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> [paul@pwsan.com: updated subject line; updated to apply on v3.5-rc4] Signed-off-by: Paul Walmsley <paul@pwsan.com> --- arch/arm/mach-omap2/am35xx-emac.c | 41 +++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 2c90ac6..37639ee 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -23,6 +23,35 @@ #include "control.h" #include "am35xx-emac.h" +/* + * Default pm_lats for the am35x. + * The net effect of using am35xx_emac_pm_lats[] is that + * pm_idle or CPUidle won't be called while the emac + * interface is open. This is required because the + * EMAC can't wake up PRCM so if the MPU is executing + * a 'wfi' instruction (e.g., from pm_idle or CPUidle), + * it won't break out of it due to emac activity. + */ +static int am35xx_emac_deactivate_func(struct omap_device *od) +{ + enable_hlt(); + return omap_device_idle_hwmods(od); +} + +static int am35xx_emac_activate_func(struct omap_device *od) +{ + disable_hlt(); + return omap_device_enable_hwmods(od); +} + +static struct omap_device_pm_latency am35xx_emac_pm_lats[] = { + { + .deactivate_func = am35xx_emac_deactivate_func, + .activate_func = am35xx_emac_activate_func, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + static void am35xx_enable_emac_int(void) { u32 v; @@ -58,12 +87,14 @@ static struct emac_platform_data am35xx_emac_pdata = { static struct mdio_platform_data am35xx_mdio_pdata; static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, - void *pdata, int pdata_len) + void *pdata, int pdata_len, + struct omap_device_pm_latency *pm_lats, + int pm_lats_size) { struct platform_device *pdev; pdev = omap_device_build(oh->class->name, 0, oh, pdata, pdata_len, - NULL, 0, false); + pm_lats, pm_lats_size, false); if (IS_ERR(pdev)) { WARN(1, "Can't build omap_device for %s:%s.\n", oh->class->name, oh->name); @@ -88,7 +119,7 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_mdio_pdata.bus_freq = mdio_bus_freq; ret = omap_davinci_emac_dev_init(oh, &am35xx_mdio_pdata, - sizeof(am35xx_mdio_pdata)); + sizeof(am35xx_mdio_pdata), NULL, 0); if (ret) { pr_err("Could not build davinci_mdio hwmod device\n"); return; @@ -103,7 +134,9 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_emac_pdata.rmii_en = rmii_en; ret = omap_davinci_emac_dev_init(oh, &am35xx_emac_pdata, - sizeof(am35xx_emac_pdata)); + sizeof(am35xx_emac_pdata), + am35xx_emac_pm_lats, + ARRAY_SIZE(am35xx_emac_pm_lats)); if (ret) { pr_err("Could not build davinci_emac hwmod device\n"); return; -- 1.7.10 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 0/2] arm: omap3: am35x: Convert emac to hwmod & disable hlt when open 2012-05-15 18:14 [PATCH v2 0/2] arm: omap3: am35x: Convert emac to hwmod & disable hlt when open Mark A. Greer 2012-05-15 18:14 ` [PATCH v2 1/2] arm: omap3: am35x: Add Davinci EMAC/MDIO hwmod support Mark A. Greer 2012-05-15 18:14 ` [PATCH v2 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC Mark A. Greer @ 2012-05-31 18:57 ` Kevin Hilman 2012-06-27 21:58 ` Paul Walmsley 3 siblings, 0 replies; 9+ messages in thread From: Kevin Hilman @ 2012-05-31 18:57 UTC (permalink / raw) To: Mark A. Greer, hvaibhav, vaibhav.bedia; +Cc: paul, linux-arm-kernel, linux-omap "Mark A. Greer" <mgreer@animalcreek.com> writes: > From: "Mark A. Greer" <mgreer@animalcreek.com> > > These patches convert the davinci emac support for the am35x SoC > to use hwmod and add enable_hlt()/disable_hlt() calls to the > pm_runtime hooks for that driver. > > I have converted the davinci_emac driver to use pm_runtime but I > can't formally submit it yet since it requires some changes on the > mach-davinci side that haven't happened yet. I will send it as an > RFC in a reply to this thread. I haven't seen any patches for the davinci runtime PM support, so I thought I would do a quick patch to show how easy it is to use some generic PM core code to manage clocks in runtime PM. The patch below implments this on davinci but has only been boot tested on my ancient dm6446 EVM. Combined with Mark's RFC patch to convert davinci_emac to runtime PM, it was working fine on dm6446 to enable the emac clocks. Kevin >From 7a90e650ad8542b7f85076b58703e94bdc058562 Mon Sep 17 00:00:00 2001 From: Kevin Hilman <khilman@ti.com> Date: Thu, 31 May 2012 09:59:53 -0700 Subject: [PATCH] ARM: davinci: add runtime PM support for clock management Add runtime PM core support to davinci by using the pm_clk infrastructure of the PM core. When runtime PM is enabled, the davinci runtime PM implementation will use the pm_clk layer to enable/disable clocks on demand. When runtime PM is disabled, the pm_clk core will automatically enable clocks when the driver is bound and disable clocks when the driver is unbound. Cc: Mark A. Greer <mgreer@animalcreek.com> Cc: Sekhar Nori <nsekhar@ti.com Signed-off-by: Kevin Hilman <khilman@ti.com> --- Applies on v3.4 arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/pm_domain.c | 70 +++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 arch/arm/mach-davinci/pm_domain.c diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 2db78bd..2227eff 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -39,3 +39,4 @@ obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_SUSPEND) += pm.o sleep.o +obj-$(CONFIG_HAVE_CLK) += pm_domain.o diff --git a/arch/arm/mach-davinci/pm_domain.c b/arch/arm/mach-davinci/pm_domain.c new file mode 100644 index 0000000..f34258f --- /dev/null +++ b/arch/arm/mach-davinci/pm_domain.c @@ -0,0 +1,70 @@ +/* + * Runtime PM support code for DaVinci + * + * Author: Kevin Hilman + * + * Copyright (C) 2010 Texas Instruments, Inc. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/pm_runtime.h> +#include <linux/pm_clock.h> +#include <linux/platform_device.h> +#include <linux/mutex.h> +#include <linux/clk.h> +#include <linux/err.h> + +#ifdef CONFIG_PM_RUNTIME +static int davinci_pm_runtime_suspend(struct device *dev) +{ + int ret; + + dev_dbg(dev, "%s\n", __func__); + + ret = pm_generic_runtime_suspend(dev); + if (ret) + return ret; + + ret = pm_clk_suspend(dev); + if (ret) { + pm_generic_runtime_resume(dev); + return ret; + } + + return 0; +} + +static int davinci_pm_runtime_resume(struct device *dev) +{ + dev_dbg(dev, "%s\n", __func__); + dump_stack(); + + pm_clk_resume(dev); + return pm_generic_runtime_resume(dev); +} +#endif + +static struct dev_pm_domain davinci_pm_domain = { + .ops = { + SET_RUNTIME_PM_OPS(davinci_pm_runtime_suspend, + davinci_pm_runtime_resume, NULL) + USE_PLATFORM_PM_SLEEP_OPS + }, +}; + +static struct pm_clk_notifier_block platform_bus_notifier = { + .pm_domain = &davinci_pm_domain, +}; + +static int __init davinci_pm_runtime_init(void) +{ + pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier); + + return 0; +} +core_initcall(davinci_pm_runtime_init); -- 1.7.9.2 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 0/2] arm: omap3: am35x: Convert emac to hwmod & disable hlt when open 2012-05-15 18:14 [PATCH v2 0/2] arm: omap3: am35x: Convert emac to hwmod & disable hlt when open Mark A. Greer ` (2 preceding siblings ...) 2012-05-31 18:57 ` [PATCH v2 0/2] arm: omap3: am35x: Convert emac to hwmod & disable hlt when open Kevin Hilman @ 2012-06-27 21:58 ` Paul Walmsley 3 siblings, 0 replies; 9+ messages in thread From: Paul Walmsley @ 2012-06-27 21:58 UTC (permalink / raw) To: Mark A. Greer; +Cc: khilman, linux-arm-kernel, linux-omap Hi On Tue, 15 May 2012, Mark A. Greer wrote: > From: "Mark A. Greer" <mgreer@animalcreek.com> > > These patches convert the davinci emac support for the am35x SoC > to use hwmod and add enable_hlt()/disable_hlt() calls to the > pm_runtime hooks for that driver. > > I have converted the davinci_emac driver to use pm_runtime but I > can't formally submit it yet since it requires some changes on the > mach-davinci side that haven't happened yet. I will send it as an > RFC in a reply to this thread. > > The patches are based on: > git://git.pwsan.com/linux-2.6 am35xx_hwmod_data_fixes_a_3.5 > > Changes from v1: > - patch 1/2, "arm: omap3: am35x: Add Davinci EMAC/MDIO hwmod support" > is unchanged > - patch 2/2, "arm: "omap3: am35x: Disable hlt when using Davinci EMAC" > has been reworked to keep the code as simple as possible per > http://www.spinics.net/lists/linux-omap/msg70354.html The updated patches that were just reposted today have been queued for 3.6, along with a few comments about the IPSS issue, mentioned earlier. They can be found in the branch am35xx_emac_mdio_devel_3.6 in git://git.pwsan.com/linux-2.6. Please let me know if you have any comments. - Paul ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-06-27 21:58 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-05-15 18:14 [PATCH v2 0/2] arm: omap3: am35x: Convert emac to hwmod & disable hlt when open Mark A. Greer 2012-05-15 18:14 ` [PATCH v2 1/2] arm: omap3: am35x: Add Davinci EMAC/MDIO hwmod support Mark A. Greer 2012-06-27 21:19 ` Paul Walmsley 2012-06-27 21:24 ` Paul Walmsley 2012-05-15 18:14 ` [PATCH v2 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC Mark A. Greer 2012-05-31 18:58 ` Kevin Hilman 2012-06-27 21:20 ` Paul Walmsley 2012-05-31 18:57 ` [PATCH v2 0/2] arm: omap3: am35x: Convert emac to hwmod & disable hlt when open Kevin Hilman 2012-06-27 21:58 ` Paul Walmsley
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox