[tip:irq/core] genirq: Fix /proc/interrupts output alignment
Commit-ID: f435da416beaacc8934fc21820d9488269b39c98 Gitweb: http://git.kernel.org/tip/f435da416beaacc8934fc21820d9488269b39c98 Author: H Hartley Sweeten AuthorDate: Fri, 10 Feb 2017 09:54:16 -0700 Committer: Thomas Gleixner CommitDate: Fri, 10 Feb 2017 20:17:52 +0100 genirq: Fix /proc/interrupts output alignment If the irq_desc being output does not have a domain associated the information following the 'name' is not aligned correctly. Signed-off-by: H Hartley Sweeten Link: http://lkml.kernel.org/r/20170210165416.5629-1-hswee...@visionengravers.com Signed-off-by: Thomas Gleixner --- kernel/irq/proc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index feaa813..c53edad 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -487,6 +487,8 @@ int show_interrupts(struct seq_file *p, void *v) } if (desc->irq_data.domain) seq_printf(p, " %*d", prec, (int) desc->irq_data.hwirq); + else + seq_printf(p, " %*s", prec, ""); #ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL seq_printf(p, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge"); #endif
[PATCH] getirq: fix /proc/interrupts output alignment
If the irq_desc being output does not have a domain the information following the 'name' is not aligned correctly. Signed-off-by: H Hartley Sweeten Cc: Thomas Gleixner --- kernel/irq/proc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index feaa813..c53edad 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -487,6 +487,8 @@ int show_interrupts(struct seq_file *p, void *v) } if (desc->irq_data.domain) seq_printf(p, " %*d", prec, (int) desc->irq_data.hwirq); + else + seq_printf(p, " %*s", prec, ""); #ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL seq_printf(p, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge"); #endif -- 2.10.0
[PATCH 0/2] watchdog: cleanup ep93xx platform drivers
The ep93xx_wdt driver is used by EP93xx based platforms for the internal watchdog of the EP93xx processor. The TS-72xx platforms have an additional watchdog provided by the CPLD on those boards. Cleanup both drivers. H Hartley Sweeten (2): watchdog: ep93xx_wdt: cleanup and let the core handle the heartbeat watchdog: ts72xx_wdt: convert driver to watchdog core drivers/watchdog/ep93xx_wdt.c | 115 +-- drivers/watchdog/ts72xx_wdt.c | 447 +- 2 files changed, 139 insertions(+), 423 deletions(-) -- 2.10.0
[PATCH 1/2] watchdog: ep93xx_wdt: cleanup and let the core handle the heartbeat
Cleanup this driver and remove the 200ms heartbeat timer. The core now has the ability to handle the heartbeat. Signed-off-by: H Hartley Sweeten Cc: Wim Van Sebroeck Cc: Guenter Roeck --- drivers/watchdog/ep93xx_wdt.c | 115 +- 1 file changed, 46 insertions(+), 69 deletions(-) diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c index 0a4d7cc..756ca47 100644 --- a/drivers/watchdog/ep93xx_wdt.c +++ b/drivers/watchdog/ep93xx_wdt.c @@ -19,81 +19,55 @@ * for us to rely on the user space daemon alone. So we ping the * wdt each ~200msec and eventually stop doing it if the user space * daemon dies. - * - * TODO: - * - * - Test last reset from watchdog status - * - Add a few missing ioctls */ #include #include #include -#include #include -#define WDT_VERSION"0.4" - -/* default timeout (secs) */ -#define WDT_TIMEOUT 30 - static bool nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); -static unsigned int timeout = WDT_TIMEOUT; -module_param(timeout, uint, 0); -MODULE_PARM_DESC(timeout, - "Watchdog timeout in seconds. (1<=timeout<=3600, default=" - __MODULE_STRING(WDT_TIMEOUT) ")"); - -static void __iomem *mmio_base; -static struct timer_list timer; -static unsigned long next_heartbeat; - #define EP93XX_WATCHDOG0x00 #define EP93XX_WDSTATUS0x04 -/* reset the wdt every ~200ms - the heartbeat of the device is 0.250 seconds*/ -#define WDT_INTERVAL (HZ/5) - -static void ep93xx_wdt_timer_ping(unsigned long data) -{ - if (time_before(jiffies, next_heartbeat)) - writel(0x, mmio_base + EP93XX_WATCHDOG); - - /* Re-set the timer interval */ - mod_timer(&timer, jiffies + WDT_INTERVAL); -} +struct ep93xx_wdt_priv { + void __iomem *mmio; + struct watchdog_device wdd; +}; static int ep93xx_wdt_start(struct watchdog_device *wdd) { - next_heartbeat = jiffies + (timeout * HZ); + struct ep93xx_wdt_priv *priv = watchdog_get_drvdata(wdd); - writel(0x, mmio_base + EP93XX_WATCHDOG); - mod_timer(&timer, jiffies + WDT_INTERVAL); + writel(0x, priv->mmio + EP93XX_WATCHDOG); return 0; } static int ep93xx_wdt_stop(struct watchdog_device *wdd) { - del_timer_sync(&timer); - writel(0xaa55, mmio_base + EP93XX_WATCHDOG); + struct ep93xx_wdt_priv *priv = watchdog_get_drvdata(wdd); + + writel(0xaa55, priv->mmio + EP93XX_WATCHDOG); return 0; } -static int ep93xx_wdt_keepalive(struct watchdog_device *wdd) +static int ep93xx_wdt_ping(struct watchdog_device *wdd) { - /* user land ping */ - next_heartbeat = jiffies + (timeout * HZ); + struct ep93xx_wdt_priv *priv = watchdog_get_drvdata(wdd); + + writel(0x, priv->mmio + EP93XX_WATCHDOG); return 0; } static const struct watchdog_info ep93xx_wdt_ident = { .options= WDIOF_CARDRESET | + WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .identity = "EP93xx Watchdog", @@ -103,47 +77,48 @@ static struct watchdog_ops ep93xx_wdt_ops = { .owner = THIS_MODULE, .start = ep93xx_wdt_start, .stop = ep93xx_wdt_stop, - .ping = ep93xx_wdt_keepalive, -}; - -static struct watchdog_device ep93xx_wdt_wdd = { - .info = &ep93xx_wdt_ident, - .ops= &ep93xx_wdt_ops, + .ping = ep93xx_wdt_ping, }; static int ep93xx_wdt_probe(struct platform_device *pdev) { + struct ep93xx_wdt_priv *priv; + struct watchdog_device *wdd; struct resource *res; unsigned long val; - int err; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mmio_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(mmio_base)) - return PTR_ERR(mmio_base); + priv->mmio = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->mmio)) + return PTR_ERR(priv->mmio); + + val = readl(priv->mmio + EP93XX_WATCHDOG); - if (timeout < 1 || timeout > 3600) { - timeout = WDT_TIMEOUT; - dev_warn(&pdev->dev, - "timeout value must be 1<=x<=3600, using %d\n", - timeout); - } + wdd = &priv->wdd; + wdd->bootstatus = (val & 0x01) ? WDIOF_CARDRESET : 0; + wdd->info = &ep93xx_wdt_ident; + wdd->ops
[PATCH 2/2] watchdog: ts72xx_wdt: convert driver to watchdog core
Cleanup this driver and convert it to use the watchdog framework API. Signed-off-by: H Hartley Sweeten Cc: Mika Westerberg Cc: Wim Van Sebroeck Cc: Guenter Roeck --- drivers/watchdog/ts72xx_wdt.c | 447 +- 1 file changed, 93 insertions(+), 354 deletions(-) diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index 4b54193..857ab71 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c @@ -13,413 +13,149 @@ * warranty of any kind, whether express or implied. */ -#include -#include -#include -#include -#include -#include #include -#include +#include #include -#include - -#define TS72XX_WDT_FEED_VAL0x05 -#define TS72XX_WDT_DEFAULT_TIMEOUT 8 - -static int timeout = TS72XX_WDT_DEFAULT_TIMEOUT; -module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. " - "(1 <= timeout <= 8, default=" - __MODULE_STRING(TS72XX_WDT_DEFAULT_TIMEOUT) - ")"); +#include static bool nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); -/** - * struct ts72xx_wdt - watchdog control structure - * @lock: lock that protects this structure - * @regval: watchdog timeout value suitable for control register - * @flags: flags controlling watchdog device state - * @control_reg: watchdog control register - * @feed_reg: watchdog feed register - * @pdev: back pointer to platform dev - */ -struct ts72xx_wdt { - struct mutexlock; - int regval; - -#define TS72XX_WDT_BUSY_FLAG 1 -#define TS72XX_WDT_EXPECT_CLOSE_FLAG 2 - int flags; +/* priv->control_reg */ +#define TS72XX_WDT_CTRL_DISABLE0x00 +#define TS72XX_WDT_CTRL_250MS 0x01 +#define TS72XX_WDT_CTRL_500MS 0x02 +#define TS72XX_WDT_CTRL_1SEC 0x03 +#define TS72XX_WDT_CTRL_RESERVED 0x04 +#define TS72XX_WDT_CTRL_2SEC 0x05 +#define TS72XX_WDT_CTRL_4SEC 0x06 +#define TS72XX_WDT_CTRL_8SEC 0x07 + +/* priv->feed_reg */ +#define TS72XX_WDT_FEED_VAL0x05 +struct ts72xx_wdt_priv { void __iomem*control_reg; void __iomem*feed_reg; - - struct platform_device *pdev; + struct watchdog_device wdd; + unsigned char regval; }; -static struct platform_device *ts72xx_wdt_pdev; - -/* - * TS-72xx Watchdog supports following timeouts (value written - * to control register): - * value description - * - - * 0x00watchdog disabled - * 0x01250ms - * 0x02500ms - * 0x031s - * 0x04reserved - * 0x052s - * 0x064s - * 0x078s - * - * Timeouts below 1s are not very usable so we don't - * allow them at all. - * - * We provide two functions that convert between these: - * timeout_to_regval() and regval_to_timeout(). - */ -static const struct { - int timeout; - int regval; -} ts72xx_wdt_map[] = { - { 1, 3 }, - { 2, 5 }, - { 4, 6 }, - { 8, 7 }, -}; - -/** - * timeout_to_regval() - converts given timeout to control register value - * @new_timeout: timeout in seconds to be converted - * - * Function converts given @new_timeout into valid value that can - * be programmed into watchdog control register. When conversion is - * not possible, function returns %-EINVAL. - */ -static int timeout_to_regval(int new_timeout) +static int ts72xx_wdt_start(struct watchdog_device *wdd) { - int i; + struct ts72xx_wdt_priv *priv = watchdog_get_drvdata(wdd); - /* first limit it to 1 - 8 seconds */ - new_timeout = clamp_val(new_timeout, 1, 8); + writeb(TS72XX_WDT_FEED_VAL, priv->feed_reg); + writeb(priv->regval, priv->control_reg); - for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) { - if (ts72xx_wdt_map[i].timeout >= new_timeout) - return ts72xx_wdt_map[i].regval; - } - - return -EINVAL; -} - -/** - * regval_to_timeout() - converts control register value to timeout - * @regval: control register value to be converted - * - * Function converts given @regval to timeout in seconds (1, 2, 4 or 8). - * If @regval cannot be converted, function returns %-EINVAL. - */ -static int regval_to_timeout(int regval) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) { - if (ts72xx_wdt_map[i].regval == regval) - return ts72xx_wdt_map[i].timeout; - } - - return -EINVAL; -} - -/** - * ts72xx_wdt_kick() - kick the watchdog - * @wdt: watchdog to be kicked - * - * Called with @wdt->lock held. - */ -static inline void ts72xx_wdt_kick(struct ts72xx_wdt *wdt) -{ - __raw_writeb(TS72XX_WDT_FEED_VAL
[PATCH 2/2 v5] usb: ohci: remove ep93xx bus glue platform driver
Convert ep93xx to use the OHCI platform driver and remove the ohci-ep93xx bus glue driver. Enable CONFIG_OHCI_HCD_PLATFORM in the ep93xx_defconfig so that USB is still enabled by default on the EP93xx platform. Signed-off-by: H Hartley Sweeten Acked-by: Alan Stern Cc: Ryan Mallon Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman Cc: Olof Johansson Cc: Russell King --- v5: rebase to usb-next (patch 1/2 has already been applied) v4: propagate errno from clk_enable() in ep93xx_ohci_power_on(). v3: split patch to refresh the ep93xx_defconfig before removing ohci-ep93xx.c in favor of the Generic OHCI driver for a platform device. v2: Use the (*power_off) callback for (*power_suspend), as suggested by Alan Stern. Remove the Kconfig change to USB_OHCI_HCD_PLATFORM and refresh the ep93xx_defconfig to enable this option, as suggested by Alan Stern. arch/arm/configs/ep93xx_defconfig | 1 + arch/arm/mach-ep93xx/clock.c | 2 +- arch/arm/mach-ep93xx/core.c | 39 +++-- drivers/usb/host/Kconfig | 8 -- drivers/usb/host/Makefile | 1 - drivers/usb/host/ohci-ep93xx.c| 174 -- 6 files changed, 36 insertions(+), 189 deletions(-) delete mode 100644 drivers/usb/host/ohci-ep93xx.c diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig index 8eccbcb..6ac5ea7 100644 --- a/arch/arm/configs/ep93xx_defconfig +++ b/arch/arm/configs/ep93xx_defconfig @@ -83,6 +83,7 @@ CONFIG_USB=y CONFIG_USB_DEBUG=y CONFIG_USB_DYNAMIC_MINORS=y CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y CONFIG_USB_STORAGE=y CONFIG_USB_SERIAL=y CONFIG_USB_SERIAL_CONSOLE=y diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index c95dbce..39ef3b6 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -212,7 +212,7 @@ static struct clk_lookup clocks[] = { INIT_CK(NULL, "hclk", &clk_h), INIT_CK(NULL, "apb_pclk", &clk_p), INIT_CK(NULL, "pll2", &clk_pll2), - INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), + INIT_CK("ohci-platform",NULL, &clk_usb_host), INIT_CK("ep93xx-keypad",NULL, &clk_keypad), INIT_CK("ep93xx-fb",NULL, &clk_video), INIT_CK("ep93xx-spi.0", NULL, &clk_spi), diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 3f12b88..d95ee28a 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -297,25 +298,53 @@ static struct platform_device ep93xx_rtc_device = { .resource = ep93xx_rtc_resource, }; +/* + * EP93xx OHCI USB Host + */ + +static struct clk *ep93xx_ohci_host_clock; + +static int ep93xx_ohci_power_on(struct platform_device *pdev) +{ + if (!ep93xx_ohci_host_clock) { + ep93xx_ohci_host_clock = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(ep93xx_ohci_host_clock)) + return PTR_ERR(ep93xx_ohci_host_clock); + } + + return clk_enable(ep93xx_ohci_host_clock); +} + +static void ep93xx_ohci_power_off(struct platform_device *pdev) +{ + clk_disable(ep93xx_ohci_host_clock); +} + +static struct usb_ohci_pdata ep93xx_ohci_pdata = { + .power_on = ep93xx_ohci_power_on, + .power_off = ep93xx_ohci_power_off, + .power_suspend = ep93xx_ohci_power_off, +}; static struct resource ep93xx_ohci_resources[] = { DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000), DEFINE_RES_IRQ(IRQ_EP93XX_USB), }; +static u64 ep93xx_ohci_dma_mask = DMA_BIT_MASK(32); static struct platform_device ep93xx_ohci_device = { - .name = "ep93xx-ohci", + .name = "ohci-platform", .id = -1, + .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), + .resource = ep93xx_ohci_resources, .dev= { - .dma_mask = &ep93xx_ohci_device.dev.coherent_dma_mask, + .dma_mask = &ep93xx_ohci_dma_mask, .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &ep93xx_ohci_pdata, }, - .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), - .resource = ep93xx_ohci_resources, }; - /* * EP93xx physmap'ed flash **
[PATCH 1/2 v4] ARM: ep93xx_defconfig: cleanup ep93xx_defconfig
Generate ep93xx_defconfig by doing: make ep93xx_defconfig make savedefconfig mv defconfig arch/arm/configs/ep93xx_defconfig No function change. This just refreshes the ep93xx_defconfig to make it easier and cleaner when adding new entries. Signed-off-by: H Hartley Sweeten Acked-by: Ryan Mallon Cc: Alan Stern Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman Cc: Olof Johansson Cc: Russell King --- arch/arm/configs/ep93xx_defconfig | 16 ++-- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig index 806005a..8eccbcb 100644 --- a/arch/arm/configs/ep93xx_defconfig +++ b/arch/arm/configs/ep93xx_defconfig @@ -1,15 +1,14 @@ -CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_EXPERT=y CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y # CONFIG_IOSCHED_CFQ is not set CONFIG_ARCH_EP93XX=y CONFIG_CRUNCH=y @@ -47,11 +46,8 @@ CONFIG_IPV6=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_FW_LOADER is not set CONFIG_MTD=y -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_REDBOOT_PARTS=y CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_ADV_OPTIONS=y @@ -67,15 +63,14 @@ CONFIG_SCSI=y # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y CONFIG_EP93XX_ETH=y CONFIG_USB_RTL8150=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_AMBA_PL010=y CONFIG_SERIAL_AMBA_PL010_CONSOLE=y -# CONFIG_LEGACY_PTYS is not set # CONFIG_HW_RANDOM is not set CONFIG_I2C=y CONFIG_I2C_CHARDEV=y @@ -86,7 +81,6 @@ CONFIG_WATCHDOG=y CONFIG_EP93XX_WATCHDOG=y CONFIG_USB=y CONFIG_USB_DEBUG=y -CONFIG_USB_DEVICEFS=y CONFIG_USB_DYNAMIC_MINORS=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_STORAGE=y @@ -100,24 +94,18 @@ CONFIG_RTC_DRV_EP93XX=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -CONFIG_INOTIFY=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y -CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y -CONFIG_PARTITION_ADVANCED=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_SLAB=y CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_MUTEXES=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_DEBUG_USER=y -CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_LIBCRC32C=y -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/2 v4] usb: ohci: remove ep93xx bus glue platform driver
Convert ep93xx to use the OHCI platform driver and remove the ohci-ep93xx bus glue driver. Enable CONFIG_OHCI_HCD_PLATFORM in the ep93xx_defconfig so that USB is still enabled by default on the EP93xx platform. Signed-off-by: H Hartley Sweeten Acked-by: Alan Stern Cc: Ryan Mallon Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman Cc: Olof Johansson Cc: Russell King --- arch/arm/configs/ep93xx_defconfig | 1 + arch/arm/mach-ep93xx/clock.c | 2 +- arch/arm/mach-ep93xx/core.c | 38 +++- drivers/usb/host/ohci-ep93xx.c| 184 -- drivers/usb/host/ohci-hcd.c | 18 5 files changed, 36 insertions(+), 207 deletions(-) delete mode 100644 drivers/usb/host/ohci-ep93xx.c diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig index 8eccbcb..6ac5ea7 100644 --- a/arch/arm/configs/ep93xx_defconfig +++ b/arch/arm/configs/ep93xx_defconfig @@ -83,6 +83,7 @@ CONFIG_USB=y CONFIG_USB_DEBUG=y CONFIG_USB_DYNAMIC_MINORS=y CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y CONFIG_USB_STORAGE=y CONFIG_USB_SERIAL=y CONFIG_USB_SERIAL_CONSOLE=y diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index c95dbce..39ef3b6 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -212,7 +212,7 @@ static struct clk_lookup clocks[] = { INIT_CK(NULL, "hclk", &clk_h), INIT_CK(NULL, "apb_pclk", &clk_p), INIT_CK(NULL, "pll2", &clk_pll2), - INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), + INIT_CK("ohci-platform",NULL, &clk_usb_host), INIT_CK("ep93xx-keypad",NULL, &clk_keypad), INIT_CK("ep93xx-fb",NULL, &clk_video), INIT_CK("ep93xx-spi.0", NULL, &clk_spi), diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 3f12b88..9408fde 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -297,22 +298,51 @@ static struct platform_device ep93xx_rtc_device = { .resource = ep93xx_rtc_resource, }; +/* + * EP93xx OHCI USB Host + */ + +static struct clk *ep93xx_ohci_host_clock; + +static int ep93xx_ohci_power_on(struct platform_device *pdev) +{ + if (!ep93xx_ohci_host_clock) { + ep93xx_ohci_host_clock = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(ep93xx_ohci_host_clock)) + return PTR_ERR(ep93xx_ohci_host_clock); + } + + return clk_enable(ep93xx_ohci_host_clock); +} + +static void ep93xx_ohci_power_off(struct platform_device *pdev) +{ + clk_disable(ep93xx_ohci_host_clock); +} + +static struct usb_ohci_pdata ep93xx_ohci_pdata = { + .power_on = ep93xx_ohci_power_on, + .power_off = ep93xx_ohci_power_off, + .power_suspend = ep93xx_ohci_power_off, +}; static struct resource ep93xx_ohci_resources[] = { DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000), DEFINE_RES_IRQ(IRQ_EP93XX_USB), }; +static u64 ep93xx_ohci_dma_mask = DMA_BIT_MASK(32); static struct platform_device ep93xx_ohci_device = { - .name = "ep93xx-ohci", + .name = "ohci-platform", .id = -1, + .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), + .resource = ep93xx_ohci_resources, .dev= { - .dma_mask = &ep93xx_ohci_device.dev.coherent_dma_mask, + .dma_mask = &ep93xx_ohci_dma_mask, .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &ep93xx_ohci_pdata, }, - .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), - .resource = ep93xx_ohci_resources, }; diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c deleted file mode 100644 index 84a20d5..000 --- a/drivers/usb/host/ohci-ep93xx.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * (C) Copyright 2002 Hewlett-Packard Company - * - * Bus Glue for ep93xx. - * - * Written by Christopher Hoover - * Based on fragments of previous driver by Russell King et al. - * - * Modified for LH7A404 from ohci-sa.c - * by Durgesh Pattamatta - * - * Modified for pxa27x from ohci-lh7a404.c - * by Nick Bane 26-8-2004 - * - * Modified for ep93xx from ohci-pxa27x
[PATCH 0/2 v4] usb: ohci: remove ep93xx bus glue platform driver
Refresh the ep93xx_defconfig then remove the ep93xx OHCI bus glue driver in favor of the Generic OHCI driver for a platform device. v4: propagate errno from clk_enable() in ep93xx_ohci_power_on(). v3: split patch to refresh the ep93xx_defconfig before removing ohci-ep93xx.c in favor of the Generic OHCI driver for a platform device. v2: Use the (*power_off) callback for (*power_suspend), as suggested by Alan Stern. Remove the Kconfig change to USB_OHCI_HCD_PLATFORM and refresh the ep93xx_defconfig to enable this option, as suggested by Alan Stern. H Hartley Sweeten (2): ARM: ep93xx_defconfig: cleanup ep93xx_defconfig usb: ohci: remove ep93xx bus glue platform driver arch/arm/configs/ep93xx_defconfig | 17 +--- arch/arm/mach-ep93xx/clock.c | 2 +- arch/arm/mach-ep93xx/core.c | 38 +++- drivers/usb/host/ohci-ep93xx.c| 184 -- drivers/usb/host/ohci-hcd.c | 18 5 files changed, 38 insertions(+), 221 deletions(-) delete mode 100644 drivers/usb/host/ohci-ep93xx.c -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/2 v3] usb: ohci: remove ep93xx bus glue platform driver
Convert ep93xx to use the OHCI platform driver and remove the ohci-ep93xx bus glue driver. Enable CONFIG_OHCI_HCD_PLATFORM in the ep93xx_defconfig so that USB is still enabled by default on the EP93xx platform. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Alan Stern Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman Cc: Olof Johansson Cc: Russell King --- arch/arm/configs/ep93xx_defconfig | 1 + arch/arm/mach-ep93xx/clock.c | 2 +- arch/arm/mach-ep93xx/core.c | 40 - drivers/usb/host/ohci-ep93xx.c| 184 -- drivers/usb/host/ohci-hcd.c | 18 5 files changed, 38 insertions(+), 207 deletions(-) delete mode 100644 drivers/usb/host/ohci-ep93xx.c diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig index 8eccbcb..6ac5ea7 100644 --- a/arch/arm/configs/ep93xx_defconfig +++ b/arch/arm/configs/ep93xx_defconfig @@ -83,6 +83,7 @@ CONFIG_USB=y CONFIG_USB_DEBUG=y CONFIG_USB_DYNAMIC_MINORS=y CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y CONFIG_USB_STORAGE=y CONFIG_USB_SERIAL=y CONFIG_USB_SERIAL_CONSOLE=y diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index c95dbce..39ef3b6 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -212,7 +212,7 @@ static struct clk_lookup clocks[] = { INIT_CK(NULL, "hclk", &clk_h), INIT_CK(NULL, "apb_pclk", &clk_p), INIT_CK(NULL, "pll2", &clk_pll2), - INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), + INIT_CK("ohci-platform",NULL, &clk_usb_host), INIT_CK("ep93xx-keypad",NULL, &clk_keypad), INIT_CK("ep93xx-fb",NULL, &clk_video), INIT_CK("ep93xx-spi.0", NULL, &clk_spi), diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 3f12b88..92d59c4 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -297,22 +298,53 @@ static struct platform_device ep93xx_rtc_device = { .resource = ep93xx_rtc_resource, }; +/* + * EP93xx OHCI USB Host + */ + +static struct clk *ep93xx_ohci_host_clock; + +static int ep93xx_ohci_power_on(struct platform_device *pdev) +{ + if (!ep93xx_ohci_host_clock) { + ep93xx_ohci_host_clock = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(ep93xx_ohci_host_clock)) + return PTR_ERR(ep93xx_ohci_host_clock); + } + + clk_enable(ep93xx_ohci_host_clock); + + return 0; +} + +static void ep93xx_ohci_power_off(struct platform_device *pdev) +{ + clk_disable(ep93xx_ohci_host_clock); +} + +static struct usb_ohci_pdata ep93xx_ohci_pdata = { + .power_on = ep93xx_ohci_power_on, + .power_off = ep93xx_ohci_power_off, + .power_suspend = ep93xx_ohci_power_off, +}; static struct resource ep93xx_ohci_resources[] = { DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000), DEFINE_RES_IRQ(IRQ_EP93XX_USB), }; +static u64 ep93xx_ohci_dma_mask = DMA_BIT_MASK(32); static struct platform_device ep93xx_ohci_device = { - .name = "ep93xx-ohci", + .name = "ohci-platform", .id = -1, + .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), + .resource = ep93xx_ohci_resources, .dev= { - .dma_mask = &ep93xx_ohci_device.dev.coherent_dma_mask, + .dma_mask = &ep93xx_ohci_dma_mask, .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &ep93xx_ohci_pdata, }, - .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), - .resource = ep93xx_ohci_resources, }; diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c deleted file mode 100644 index 84a20d5..000 --- a/drivers/usb/host/ohci-ep93xx.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * (C) Copyright 2002 Hewlett-Packard Company - * - * Bus Glue for ep93xx. - * - * Written by Christopher Hoover - * Based on fragments of previous driver by Russell King et al. - * - * Modified for LH7A404 from ohci-sa.c - * by Durgesh Pattamatta - * - * Modified for pxa27x from ohci-lh7a404.c - * by Nick Bane 26-8-2004 - * - * Modified for ep93x
[PATCH 1/2 v3] ARM: ep93xx_defconfig: cleanup ep93xx_defconfig
Generate ep93xx_defconfig by doing: make ep93xx_defconfig make savedefconfig mv defconfig arch/arm/configs/ep93xx_defconfig No functional change. This just refreshes the ep93xx_defconfig to make it easier and cleaner when adding new entries. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Alan Stern Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman Cc: Olof Johansson Cc: Russell King --- arch/arm/configs/ep93xx_defconfig | 16 ++-- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig index 806005a..8eccbcb 100644 --- a/arch/arm/configs/ep93xx_defconfig +++ b/arch/arm/configs/ep93xx_defconfig @@ -1,15 +1,14 @@ -CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_EXPERT=y CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y # CONFIG_IOSCHED_CFQ is not set CONFIG_ARCH_EP93XX=y CONFIG_CRUNCH=y @@ -47,11 +46,8 @@ CONFIG_IPV6=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_FW_LOADER is not set CONFIG_MTD=y -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_REDBOOT_PARTS=y CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_ADV_OPTIONS=y @@ -67,15 +63,14 @@ CONFIG_SCSI=y # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y CONFIG_EP93XX_ETH=y CONFIG_USB_RTL8150=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_AMBA_PL010=y CONFIG_SERIAL_AMBA_PL010_CONSOLE=y -# CONFIG_LEGACY_PTYS is not set # CONFIG_HW_RANDOM is not set CONFIG_I2C=y CONFIG_I2C_CHARDEV=y @@ -86,7 +81,6 @@ CONFIG_WATCHDOG=y CONFIG_EP93XX_WATCHDOG=y CONFIG_USB=y CONFIG_USB_DEBUG=y -CONFIG_USB_DEVICEFS=y CONFIG_USB_DYNAMIC_MINORS=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_STORAGE=y @@ -100,24 +94,18 @@ CONFIG_RTC_DRV_EP93XX=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -CONFIG_INOTIFY=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y -CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y -CONFIG_PARTITION_ADVANCED=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_SLAB=y CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_MUTEXES=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_DEBUG_USER=y -CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_LIBCRC32C=y -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/2 v3] usb: ohci: remove ep93xx bus glue driver
Refresh the ep93xx_defconfig then remove the ep93xx OHCI bus glue driver in favor of the Generic OHCI driver for a platform device. v3: split patch to refresh the ep93xx_defconfig before removing ohci-ep93xx.c in favor of the Generic OHCI driver for a platform device. v2: Use the (*power_off) callback for (*power_suspend), as suggested by Alan Stern. Remove the Kconfig change to USB_OHCI_HCD_PLATFORM and refresh the ep93xx_defconfig to enable this option, as suggested by Alan Stern. H Hartley Sweeten (2): ARM: ep93xx_defconfig: cleanup ep93xx_defconfig usb: ohci: remove ep93xx bus glue platform driver arch/arm/configs/ep93xx_defconfig | 17 +--- arch/arm/mach-ep93xx/clock.c | 2 +- arch/arm/mach-ep93xx/core.c | 40 - drivers/usb/host/ohci-ep93xx.c| 184 -- drivers/usb/host/ohci-hcd.c | 18 5 files changed, 40 insertions(+), 221 deletions(-) delete mode 100644 drivers/usb/host/ohci-ep93xx.c -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] pwm: add ep93xx PWM support
Remove the non-standard EP93xx PWM driver in drivers/misc and add a new driver for the PWM controllers on the EP93xx platform based on the PWM framework. These PWM controllers each support 1 PWM channel with programmable duty cycle, frequency, and polarity inversion. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Thierry Reding Cc: Arnd Bergmann Cc: Greg Kroah-Hartman --- v2: address issues pointed out by Thierry Reding. drivers/misc/Kconfig | 13 --- drivers/misc/Makefile | 1 - drivers/misc/ep93xx_pwm.c | 286 -- drivers/pwm/Kconfig | 9 ++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-ep93xx.c | 230 + 6 files changed, 240 insertions(+), 300 deletions(-) delete mode 100644 drivers/misc/ep93xx_pwm.c create mode 100644 drivers/pwm/pwm-ep93xx.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 8dacd4c..c43c66a 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -381,19 +381,6 @@ config HMC6352 This driver provides support for the Honeywell HMC6352 compass, providing configuration and heading data via sysfs. -config EP93XX_PWM - tristate "EP93xx PWM support" - depends on ARCH_EP93XX - help - This option enables device driver support for the PWM channels - on the Cirrus EP93xx processors. The EP9307 chip only has one - PWM channel all the others have two, the second channel is an - alternate function of the EGPIO14 pin. A sysfs interface is - provided to control the PWM channels. - - To compile this driver as a module, choose M here: the module will - be called ep93xx_pwm. - config DS1682 tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" depends on I2C diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index c235d5b..ecccd00 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -33,7 +33,6 @@ obj-$(CONFIG_APDS9802ALS) += apds9802als.o obj-$(CONFIG_ISL29003) += isl29003.o obj-$(CONFIG_ISL29020) += isl29020.o obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o -obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o obj-$(CONFIG_C2PORT) += c2port/ diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c deleted file mode 100644 index cdb67a9..000 --- a/drivers/misc/ep93xx_pwm.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Simple PWM driver for EP93XX - * - * (c) Copyright 2009 Matthieu Crapet - * (c) Copyright 2009 H Hartley Sweeten - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * EP9307 has only one channel: - *- PWMOUT - * - * EP9301/02/12/15 have two channels: - *- PWMOUT - *- PWMOUT1 (alternate function for EGPIO14) - */ - -#include -#include -#include -#include -#include -#include - -#include - -#define EP93XX_PWMx_TERM_COUNT 0x00 -#define EP93XX_PWMx_DUTY_CYCLE 0x04 -#define EP93XX_PWMx_ENABLE 0x08 -#define EP93XX_PWMx_INVERT 0x0C - -#define EP93XX_PWM_MAX_COUNT 0x - -struct ep93xx_pwm { - void __iomem*mmio_base; - struct clk *clk; - u32 duty_percent; -}; - -/* - * /sys/devices/platform/ep93xx-pwm.N - * /min_freq read-only minimum pwm output frequency - * /max_req read-only maximum pwm output frequency - * /freq read-write pwm output frequency (0 = disable output) - * /duty_percent read-write pwm duty cycle percent (1..99) - * /invertread-write invert pwm output - */ - -static ssize_t ep93xx_pwm_get_min_freq(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); - unsigned long rate = clk_get_rate(pwm->clk); - - return sprintf(buf, "%ld\n", rate / (EP93XX_PWM_MAX_COUNT + 1)); -} - -static ssize_t ep93xx_pwm_get_max_freq(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); - unsigned long rate = clk_get_rate(pwm->clk); - - return sprintf(buf, "%ld\n", rate / 2); -} - -static ssize_t ep93xx_pwm_get_freq(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); - - if (readl(pwm->mmio_base + EP93XX_PWMx_EN
[PATCH] usb: ohci: remove ep93xx bus glue platform driver
Convert ep93xx to use the OHCI platform driver and remove the ohci-ep93xx bus glue driver. Signed-off-by: H Hartley Sweeten Cc: Alan Stern Cc: Greg Kroah-Hartman Cc: Ryan Mallon --- arch/arm/mach-ep93xx/clock.c | 2 +- arch/arm/mach-ep93xx/core.c| 45 +- drivers/usb/host/Kconfig | 2 +- drivers/usb/host/ohci-ep93xx.c | 184 - drivers/usb/host/ohci-hcd.c| 18 5 files changed, 43 insertions(+), 208 deletions(-) delete mode 100644 drivers/usb/host/ohci-ep93xx.c diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index c95dbce..39ef3b6 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -212,7 +212,7 @@ static struct clk_lookup clocks[] = { INIT_CK(NULL, "hclk", &clk_h), INIT_CK(NULL, "apb_pclk", &clk_p), INIT_CK(NULL, "pll2", &clk_pll2), - INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), + INIT_CK("ohci-platform",NULL, &clk_usb_host), INIT_CK("ep93xx-keypad",NULL, &clk_keypad), INIT_CK("ep93xx-fb",NULL, &clk_video), INIT_CK("ep93xx-spi.0", NULL, &clk_spi), diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 3f12b88..5489824 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -297,22 +298,58 @@ static struct platform_device ep93xx_rtc_device = { .resource = ep93xx_rtc_resource, }; +/* + * EP93xx OHCI USB Host + */ + +static struct clk *ep93xx_ohci_host_clock; + +static int ep93xx_ohci_power_on(struct platform_device *pdev) +{ + if (!ep93xx_ohci_host_clock) { + ep93xx_ohci_host_clock = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(ep93xx_ohci_host_clock)) + return PTR_ERR(ep93xx_ohci_host_clock); + } + + clk_enable(ep93xx_ohci_host_clock); + + return 0; +} + +static void ep93xx_ohci_power_off(struct platform_device *pdev) +{ + clk_disable(ep93xx_ohci_host_clock); +} + +static void ep93xx_ohci_power_suspend(struct platform_device *pdev) +{ + ep93xx_ohci_power_off(pdev); +} + +static struct usb_ohci_pdata ep93xx_ohci_pdata = { + .power_on = ep93xx_ohci_power_on, + .power_off = ep93xx_ohci_power_off, + .power_suspend = ep93xx_ohci_power_suspend, +}; static struct resource ep93xx_ohci_resources[] = { DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000), DEFINE_RES_IRQ(IRQ_EP93XX_USB), }; +static u64 ep93xx_ohci_dma_mask = DMA_BIT_MASK(32); static struct platform_device ep93xx_ohci_device = { - .name = "ep93xx-ohci", + .name = "ohci-platform", .id = -1, + .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), + .resource = ep93xx_ohci_resources, .dev= { - .dma_mask = &ep93xx_ohci_device.dev.coherent_dma_mask, + .dma_mask = &ep93xx_ohci_dma_mask, .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &ep93xx_ohci_pdata, }, - .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), - .resource = ep93xx_ohci_resources, }; diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index b3f20d7..2c8f2db 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -472,7 +472,7 @@ config USB_CNS3XXX_OHCI config USB_OHCI_HCD_PLATFORM tristate "Generic OHCI driver for a platform device" - default n + default y if ARCH_EP93XX ---help--- Adds an OHCI host driver for a generic platform device, which provides a memory space and an irq. diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c deleted file mode 100644 index 84a20d5..000 --- a/drivers/usb/host/ohci-ep93xx.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * (C) Copyright 2002 Hewlett-Packard Company - * - * Bus Glue for ep93xx. - * - * Written by Christopher Hoover - * Based on fragments of previous driver by Russell King et al. - * - * Modified for LH7A404 from ohci-sa.c - * by Durgesh Pattamatta - * - * Modified for pxa27x from ohci-lh7a404.c - * by Nick Bane 26-8-2004 - * - * Modified
[PATCH] pwm: add ep93xx PWM support
Remove the non-standard EP93xx pwm driver in drivers/misc and add a new driver for the PWM chips on the EP93xx platforms based on the PWM framework. These PWM chips each support 1 PWM channel with programmable duty cycle, frequency, and polarity inversion. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Thierry Reding Cc: Arnd Bergmann Cc: Greg Kroah-Hartman --- drivers/misc/Kconfig | 13 --- drivers/misc/Makefile | 1 - drivers/misc/ep93xx_pwm.c | 286 -- drivers/pwm/Kconfig | 9 ++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-ep93xx.c | 218 +++ 6 files changed, 228 insertions(+), 300 deletions(-) delete mode 100644 drivers/misc/ep93xx_pwm.c create mode 100644 drivers/pwm/pwm-ep93xx.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 8dacd4c..c43c66a 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -381,19 +381,6 @@ config HMC6352 This driver provides support for the Honeywell HMC6352 compass, providing configuration and heading data via sysfs. -config EP93XX_PWM - tristate "EP93xx PWM support" - depends on ARCH_EP93XX - help - This option enables device driver support for the PWM channels - on the Cirrus EP93xx processors. The EP9307 chip only has one - PWM channel all the others have two, the second channel is an - alternate function of the EGPIO14 pin. A sysfs interface is - provided to control the PWM channels. - - To compile this driver as a module, choose M here: the module will - be called ep93xx_pwm. - config DS1682 tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" depends on I2C diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index c235d5b..ecccd00 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -33,7 +33,6 @@ obj-$(CONFIG_APDS9802ALS) += apds9802als.o obj-$(CONFIG_ISL29003) += isl29003.o obj-$(CONFIG_ISL29020) += isl29020.o obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o -obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o obj-$(CONFIG_C2PORT) += c2port/ diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c deleted file mode 100644 index cdb67a9..000 --- a/drivers/misc/ep93xx_pwm.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Simple PWM driver for EP93XX - * - * (c) Copyright 2009 Matthieu Crapet - * (c) Copyright 2009 H Hartley Sweeten - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * EP9307 has only one channel: - *- PWMOUT - * - * EP9301/02/12/15 have two channels: - *- PWMOUT - *- PWMOUT1 (alternate function for EGPIO14) - */ - -#include -#include -#include -#include -#include -#include - -#include - -#define EP93XX_PWMx_TERM_COUNT 0x00 -#define EP93XX_PWMx_DUTY_CYCLE 0x04 -#define EP93XX_PWMx_ENABLE 0x08 -#define EP93XX_PWMx_INVERT 0x0C - -#define EP93XX_PWM_MAX_COUNT 0x - -struct ep93xx_pwm { - void __iomem*mmio_base; - struct clk *clk; - u32 duty_percent; -}; - -/* - * /sys/devices/platform/ep93xx-pwm.N - * /min_freq read-only minimum pwm output frequency - * /max_req read-only maximum pwm output frequency - * /freq read-write pwm output frequency (0 = disable output) - * /duty_percent read-write pwm duty cycle percent (1..99) - * /invertread-write invert pwm output - */ - -static ssize_t ep93xx_pwm_get_min_freq(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); - unsigned long rate = clk_get_rate(pwm->clk); - - return sprintf(buf, "%ld\n", rate / (EP93XX_PWM_MAX_COUNT + 1)); -} - -static ssize_t ep93xx_pwm_get_max_freq(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); - unsigned long rate = clk_get_rate(pwm->clk); - - return sprintf(buf, "%ld\n", rate / 2); -} - -static ssize_t ep93xx_pwm_get_freq(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); - - if (readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1) { - unsigned long rate = clk_get_rate(pwm-&
RE: [PATCH] gpio: (gpio-pca953x) move header to linux/platform_data/
On Friday, August 16, 2013 8:02 AM, Vivien Didelot wrote: > Hi Linus, > > You wrote: > > But: >> >>> drivers/gpio/gpio-pca953x.c | 2 +- >> (...) >>> diff --git a/drivers/gpio/gpio-pca953x.c >>> b/drivers/gpio/gpio-pca953x.c >>> index 426c51d..8804aec 100644 >>> --- a/drivers/gpio/gpio-pca953x.c >>> +++ b/drivers/gpio/gpio-pca953x.c >>> @@ -18,7 +18,7 @@ >>> #include >>> #include >>> #include >>> -#include >>> +#include >> >> Why does the GPIO driver need platform data from the >> I2C driver??? >> >> Can't this just be made to go away? > > I didn't dig that much in the driver, but I cannot imagine > another way to pass, for instance, the setup callback. > > What would be a good alternative for you? I think the confusion here is because the pca953x.h header was initially placed in linux/i2c. This device is an I2C connected GPIO expander. The pca953x.h header has the information needed for the platform to hook up to the device. It doesn't really expose the fact that it's an I2C driver. Just by 2 cents... Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH] gpio: (gpio-pca953x) move header to linux/platform_data/
On Wednesday, July 31, 2013 1:57 PM, Vivien Didelot wrote: > > This patch moves the pca953x.h header from include/linux/i2c to > include/linux/platform_data and updates existing support accordingly. > > Signed-off-by: Vivien Didelot > --- arch/arm/mach-ep93xx/vision_ep9307.c| 2 +- For the ep93xx change: Acked-by: H Hartley Sweeten Thanks -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH v2 0/4] usb: ohci-ep93xx: do a bit of housecleaning
On Monday, July 01, 2013 3:52 PM, H Hartley Sweeten wrote: > Tidy up this driver a bit. > > v2: redo patch 4 based on suggestions from Alan Stern > > H Hartley Sweeten (4): > usb: ohci-ep93xx: use devm_ioremap_resource() > usb: ohci-ep93xx: use platform_get_irq() > usb: ohci-ep93xx: use devm_clk_get() > usb: ohci-ep93xx: tidy up driver (*probe) and (*remove) > > drivers/usb/host/ohci-ep93xx.c | 137 > - > 1 file changed, 52 insertions(+), 85 deletions(-) All of these have been Acked-by: Alan Stern. Any ideas when they might be picked up and applied? Thanks, Hartley N�r��yb�X��ǧv�^�){.n�+{zX����ܨ}���Ơz�&j:+v���zZ+��+zf���h���~i���z��w���?�&�)ߢf��^jǫy�m��@A�a��� 0��h���i
RE: [PATCH 22/36] staging: comedi: convert class code to use dev_groups
On Wednesday, July 24, 2013 3:05 PM, Greg Kroah-Hartman wrote: > > The dev_attrs field of struct class is going away soon, dev_groups > should be used instead. This converts the comedi class code to use the > correct field. > > Cc: Ian Abbott > Cc: H Hartley Sweeten > Signed-off-by: Greg Kroah-Hartman > --- > drivers/staging/comedi/comedi_fops.c | 39 > ++-- > 1 file changed, 20 insertions(+), 19 deletions(-) Looks good to me. Not sure what my sign off should be so take your pick. Reviewed-by: H Hartley Sweeten Acked-by: H Hartley Sweeten -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] ASoC: ep93xx: fix build of ep93xx-ac97.c
Fix the build of this driver. It was broken by: Commit 453807f3006757a5661c4000262d7d9284b5214c ASoC: ep93xx: Use ep93xx_dma_params instead of ep93xx_pcm_dma_params The removed struct ep93xx_pcm_dma_params use the member 'dma_port' to select the dma channel. The struct ep93xx_dma_data uses the member 'port'. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Lars-Peter Clausen Cc: Mark Brown Cc: Liam Girdwood Cc: Jaroslav Kysela Cc: Takashi Iwai --- sound/soc/cirrus/ep93xx-ac97.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index ac73c60..04491f0 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c @@ -102,13 +102,13 @@ static struct ep93xx_ac97_info *ep93xx_ac97_info; static struct ep93xx_dma_data ep93xx_ac97_pcm_out = { .name = "ac97-pcm-out", - .dma_port = EP93XX_DMA_AAC1, + .port = EP93XX_DMA_AAC1, .direction = DMA_MEM_TO_DEV, }; static struct ep93xx_dma_data ep93xx_ac97_pcm_in = { .name = "ac97-pcm-in", - .dma_port = EP93XX_DMA_AAC1, + .port = EP93XX_DMA_AAC1, .direction = DMA_DEV_TO_MEM, }; -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 11/11] spi: spi-ep93xx: use master->cur_msg for in-flight message
Instead of carrying the in-flight message in the driver private data, use the cur_msg pointer that is already setup by the core. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 88 ++-- 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 4c9a50c..e85834d 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -76,7 +76,6 @@ * @min_rate: minimum clock rate (in Hz) supported by the controller * @max_rate: maximum clock rate (in Hz) supported by the controller * @wait: wait here until given transfer is completed - * @current_msg: message that is currently processed (or %NULL if none) * @tx: current byte in transfer to transmit * @rx: current byte in transfer to receive * @fifo_level: how full is FIFO (%0..%SPI_FIFO_SIZE - %1). Receiving one @@ -98,7 +97,6 @@ struct ep93xx_spi { unsigned long min_rate; unsigned long max_rate; struct completion wait; - struct spi_message *current_msg; size_t tx; size_t rx; size_t fifo_level; @@ -378,7 +376,7 @@ static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t) /** * ep93xx_spi_read_write() - perform next RX/TX transfer - * @espi: ep93xx SPI controller struct + * @master: spi_master struct * * This function transfers next bytes (or half-words) to/from RX/TX FIFOs. If * called several times, the whole transfer will be completed. Returns @@ -387,9 +385,10 @@ static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t) * When this function is finished, RX FIFO should be empty and TX FIFO should be * full. */ -static int ep93xx_spi_read_write(struct ep93xx_spi *espi) +static int ep93xx_spi_read_write(struct spi_master *master) { - struct spi_message *msg = espi->current_msg; + struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct spi_message *msg = master->cur_msg; struct spi_transfer *t = msg->state; /* read as long as RX FIFO has frames in it */ @@ -410,13 +409,15 @@ static int ep93xx_spi_read_write(struct ep93xx_spi *espi) return -EINPROGRESS; } -static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi) +static void ep93xx_spi_pio_transfer(struct spi_master *master) { + struct ep93xx_spi *espi = spi_master_get_devdata(master); + /* * Now everything is set up for the current transfer. We prime the TX * FIFO, enable interrupts, and wait for the transfer to complete. */ - if (ep93xx_spi_read_write(espi)) { + if (ep93xx_spi_read_write(master)) { ep93xx_spi_enable_interrupts(espi); wait_for_completion(&espi->wait); } @@ -424,7 +425,7 @@ static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi) /** * ep93xx_spi_dma_prepare() - prepares a DMA transfer - * @espi: ep93xx SPI controller struct + * @master: spi_master struct * @dir: DMA transfer direction * * Function configures the DMA, maps the buffer and prepares the DMA @@ -432,9 +433,11 @@ static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi) * in case of failure. */ static struct dma_async_tx_descriptor * -ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir) +ep93xx_spi_dma_prepare(struct spi_master *master, + enum dma_transfer_direction dir) { - struct spi_transfer *t = espi->current_msg->state; + struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct spi_transfer *t = master->cur_msg->state; struct dma_async_tx_descriptor *txd; enum dma_slave_buswidth buswidth; struct dma_slave_config conf; @@ -527,15 +530,16 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir) /** * ep93xx_spi_dma_finish() - finishes with a DMA transfer - * @espi: ep93xx SPI controller struct + * @master: spi_master struct * @dir: DMA transfer direction * * Function finishes with the DMA transfer. After this, the DMA buffer is * unmapped. */ -static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi, +static void ep93xx_spi_dma_finish(struct spi_master *master, enum dma_transfer_direction dir) { + struct ep93xx_spi *espi = spi_master_get_devdata(master); struct dma_chan *chan; struct sg_table *sgt; @@ -555,21 +559,22 @@ static void ep93xx_spi_dma_callback(void *callback_param) complete(callback_param); } -static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi) +static void ep93xx_spi_dma_transfer(struct spi_master *master) { - struct spi_mess
RE: [PATCH v2 09/11] spi: spi-ep93xx: move the clock divider calcs into ep93xx_spi_chip_setup()
On Monday, July 08, 2013 5:10 AM, Mark Brown wrote: > On Tue, Jul 02, 2013 at 10:10:29AM -0700, H Hartley Sweeten wrote: >> The divider values stored in the per chip data are only used to set the >> registers in the hardware to generate the desired SPI clock. Since these >> are calculated per transfer based on the t->speed_hz there is no reason >> keep them in the per chip data. > > Applied, thanks. I don't seem to have been sent patch 10? Thanks. Looks like I fat-fingered the To: address on patches 10 and 11 of the series. I'll repost them in just a sec. Regards, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 10/11] spi: spi-ep93xx: convert to the queued driver infrastructure
The SPI core provides infrastructure for standard message queueing. Use that instead of handling it in the driver. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Cc: Ryan Mallon Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 165 ++- 1 file changed, 19 insertions(+), 146 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 2e64806..4c9a50c 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -70,19 +69,13 @@ /** * struct ep93xx_spi - EP93xx SPI controller structure - * @lock: spinlock that protects concurrent accesses to fields @running, - *@current_msg and @msg_queue * @pdev: pointer to platform device * @clk: clock for the controller * @regs_base: pointer to ioremap()'d registers * @sspdr_phys: physical address of the SSPDR register * @min_rate: minimum clock rate (in Hz) supported by the controller * @max_rate: maximum clock rate (in Hz) supported by the controller - * @running: is the queue running - * @wq: workqueue used by the driver - * @msg_work: work that is queued for the driver * @wait: wait here until given transfer is completed - * @msg_queue: queue for the messages * @current_msg: message that is currently processed (or %NULL if none) * @tx: current byte in transfer to transmit * @rx: current byte in transfer to receive @@ -96,30 +89,15 @@ * @tx_sgt: sg table for TX transfers * @zeropage: dummy page used as RX buffer when only TX buffer is passed in by *the client - * - * This structure holds EP93xx SPI controller specific information. When - * @running is %true, driver accepts transfer requests from protocol drivers. - * @current_msg is used to hold pointer to the message that is currently - * processed. If @current_msg is %NULL, it means that no processing is going - * on. - * - * Most of the fields are only written once and they can be accessed without - * taking the @lock. Fields that are accessed concurrently are: @current_msg, - * @running, and @msg_queue. */ struct ep93xx_spi { - spinlock_t lock; const struct platform_device*pdev; struct clk *clk; void __iomem*regs_base; unsigned long sspdr_phys; unsigned long min_rate; unsigned long max_rate; - boolrunning; - struct workqueue_struct *wq; - struct work_struct msg_work; struct completion wait; - struct list_headmsg_queue; struct spi_message *current_msg; size_t tx; size_t rx; @@ -230,7 +208,7 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, /* * Make sure that max value is between values supported by the * controller. Note that minimum value is already checked in -* ep93xx_spi_transfer(). +* ep93xx_spi_transfer_one_message(). */ rate = clamp(rate, espi->min_rate, espi->max_rate); @@ -306,54 +284,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) } /** - * ep93xx_spi_transfer() - queue message to be transferred - * @spi: target SPI device - * @msg: message to be transferred - * - * This function is called by SPI device drivers when they are going to transfer - * a new message. It simply puts the message in the queue and schedules - * workqueue to perform the actual transfer later on. - * - * Returns %0 on success and negative error in case of failure. - */ -static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg) -{ - struct ep93xx_spi *espi = spi_master_get_devdata(spi->master); - struct spi_transfer *t; - unsigned long flags; - - if (!msg || !msg->complete) - return -EINVAL; - - /* first validate each transfer */ - list_for_each_entry(t, &msg->transfers, transfer_list) { - if (t->speed_hz && t->speed_hz < espi->min_rate) - return -EINVAL; - } - - /* -* Now that we own the message, let's initialize it so that it is -* suitable for us. We use @msg->status to signal whether there was -* error in transfer and @msg->state is used to hold pointer to the -* current transfer (or %NULL if no active current transfer). -*/ - msg->state = NULL; - msg->status = 0; - msg->actual_length = 0; - - spin_lock_irqsave(&espi->lock, flags); - if (!espi->running) { - spin_unlock_irqrestore(&espi->lock, flags); -
RE: [PATCH v2 05/11] spi: spi-ep93xx: use devm_clk_get()
On Wednesday, July 03, 2013 11:21 AM, Mark Brown wrote: > On Tue, Jul 02, 2013 at 10:08:21AM -0700, H Hartley Sweeten wrote: >> Use devm_clk_get() so that the clk_put() happens automatically when >> the last reference to this driver is dropped. > > This doesn't apply against current code - always submit against the > relevant development tree, in this case topic/ep93xx. I've applied it > with a manual fixup. Hello Mark, It appears your topic/ep93xx branch is missing this: commit 24778be20f87d5aadb19624fc768b3159fa43efc Author: Stephen Warren Date: Tue May 21 20:36:35 2013 -0600 spi: convert drivers to use bits_per_word_mask This commit is in linux-next which is what the patch series was based on. I'm not sure what branch you applied that patch to. If you need to drop my previous patches that you applied to topic/ep93xx in order to sync things up please let me know how to proceed. There are four more patches pending for spi-ep93xx to finish the cleanup and convert it to the SPI queued driver infrastructure. These are the relevant commits in topic/spi-ep93xx: kernel / pub/scm/linux/kernel/git/broonie/spi / topic/ep93xx / drivers / spi / spi-ep93xx.c 3051c43 spi: spi-ep93xx: use devm_clk_get() by H Hartley Sweeten - 28 hours ago topic/ep93xx e5ae625 spi: spi-ep93xx: remove 'dss' from per chip private data by H Hartley Sweeten - 28 hours ago 4af59ef spi: spi-ep93xx: remove dev_err() for kzalloc() failure by H Hartley Sweeten - 28 hours ago 8b9d957 spi: spi-ep93xx: get platform resources early in (*probe) by H Hartley Sweeten - 28 hours ago c6b7f14 spi: spi-ep93xx: remove bits_per_word() helper by H Hartley Sweeten - 28 hours ago 75c7444 spi: spi-ep93xx: use read,write instead of __raw_* variants by H Hartley Sweeten - 28 hours ago eb41eeb spi: spi-ep93xx: always handle transfer specific settings by H Hartley Sweeten - 5 days ago Sorry about the trouble. I don't have your tree pulled so I was starting from linux-next under the assumption that it was current to your tree. Regards, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH v2 05/11] spi: spi-ep93xx: use devm_clk_get()
On Wednesday, July 03, 2013 11:21 AM, Mark Brown wrote: > On Tue, Jul 02, 2013 at 10:08:21AM -0700, H Hartley Sweeten wrote: >> Use devm_clk_get() so that the clk_put() happens automatically when >> the last reference to this driver is dropped. > > This doesn't apply against current code - always submit against the > relevant development tree, in this case topic/ep93xx. I've applied it > with a manual fixup. Sorry about the trouble. Thanks for fixing it. Regards, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 06/11] spi: spi-ep93xx: remove dev_err() for kzalloc() failure
The kzalloc() failure will have already output a message. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index c1a610e..34aade1 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -1004,10 +1004,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev) } master = spi_alloc_master(&pdev->dev, sizeof(*espi)); - if (!master) { - dev_err(&pdev->dev, "failed to allocate spi master\n"); + if (!master) return -ENOMEM; - } master->setup = ep93xx_spi_setup; master->transfer = ep93xx_spi_transfer; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 09/11] spi: spi-ep93xx: move the clock divider calcs into ep93xx_spi_chip_setup()
The divider values stored in the per chip data are only used to set the registers in the hardware to generate the desired SPI clock. Since these are calculated per transfer based on the t->speed_hz there is no reason keep them in the per chip data. Move the ep93xx_spi_calc_divisors() call into ep93xx_spi_chip_setup() and return the dividers thru pointers. Remove the divider values from the per chip data structure. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Cc: Ryan Mallon Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 57 +--- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 6cdfc40..2e64806 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -136,18 +136,10 @@ struct ep93xx_spi { /** * struct ep93xx_spi_chip - SPI device hardware settings * @spi: back pointer to the SPI device - * @div_cpsr: cpsr (pre-scaler) divider - * @div_scr: scr divider * @ops: private chip operations - * - * This structure is used to store hardware register specific settings for each - * SPI device. Settings are written to hardware by function - * ep93xx_spi_chip_setup(). */ struct ep93xx_spi_chip { const struct spi_device *spi; - u8 div_cpsr; - u8 div_scr; struct ep93xx_spi_chip_ops *ops; }; @@ -224,17 +216,13 @@ static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi) /** * ep93xx_spi_calc_divisors() - calculates SPI clock divisors * @espi: ep93xx SPI controller struct - * @chip: divisors are calculated for this chip * @rate: desired SPI output clock rate - * - * Function calculates cpsr (clock pre-scaler) and scr divisors based on - * given @rate and places them to @chip->div_cpsr and @chip->div_scr. If, - * for some reason, divisors cannot be calculated nothing is stored and - * %-EINVAL is returned. + * @div_cpsr: pointer to return the cpsr (pre-scaler) divider + * @div_scr: pointer to return the scr divider */ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, - struct ep93xx_spi_chip *chip, - unsigned long rate) + unsigned long rate, + u8 *div_cpsr, u8 *div_scr) { unsigned long spi_clk_rate = clk_get_rate(espi->clk); int cpsr, scr; @@ -257,8 +245,8 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, for (cpsr = 2; cpsr <= 254; cpsr += 2) { for (scr = 0; scr <= 255; scr++) { if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) { - chip->div_scr = (u8)scr; - chip->div_cpsr = (u8)cpsr; + *div_scr = (u8)scr; + *div_cpsr = (u8)cpsr; return 0; } } @@ -389,29 +377,35 @@ static void ep93xx_spi_cleanup(struct spi_device *spi) * ep93xx_spi_chip_setup() - configures hardware according to given @chip * @espi: ep93xx SPI controller struct * @chip: chip specific settings + * @speed_hz: transfer speed * @bits_per_word: transfer bits_per_word - * - * This function sets up the actual hardware registers with settings given in - * @chip. Note that no validation is done so make sure that callers validate - * settings before calling this. */ -static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, - const struct ep93xx_spi_chip *chip, - u8 bits_per_word) +static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, +const struct ep93xx_spi_chip *chip, +u32 speed_hz, u8 bits_per_word) { u8 dss = bits_per_word_to_dss(bits_per_word); + u8 div_cpsr = 0; + u8 div_scr = 0; u16 cr0; + int err; + + err = ep93xx_spi_calc_divisors(espi, speed_hz, &div_cpsr, &div_scr); + if (err) + return err; - cr0 = chip->div_scr << SSPCR0_SCR_SHIFT; + cr0 = div_scr << SSPCR0_SCR_SHIFT; cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT; cr0 |= dss; dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", - chip->spi->mode, chip->div_cpsr, chip->div_scr, dss); + chip->spi->mode, div_cpsr, div_scr, dss); dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0); - ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr); + ep93xx_spi_write_u8(espi, SSPCPSR, div_cpsr); ep93xx_spi_write_u16(espi,
[PATCH v2 08/11] spi: spi-ep93xx: don't bother calculating the divisors in ep93xx_spi_setup()
The divisors needed to generate the SPI clock are calculated per transfer based on the t->speed_hz. There is no reason to calculate them in ep93xx_spi_setup(). Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Cc: Ryan Mallon Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 14 -- 1 file changed, 14 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index cc2a240..6cdfc40 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -136,7 +136,6 @@ struct ep93xx_spi { /** * struct ep93xx_spi_chip - SPI device hardware settings * @spi: back pointer to the SPI device - * @rate: max rate in hz this chip supports * @div_cpsr: cpsr (pre-scaler) divider * @div_scr: scr divider * @ops: private chip operations @@ -147,7 +146,6 @@ struct ep93xx_spi { */ struct ep93xx_spi_chip { const struct spi_device *spi; - unsigned long rate; u8 div_cpsr; u8 div_scr; struct ep93xx_spi_chip_ops *ops; @@ -315,18 +313,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) spi_set_ctldata(spi, chip); } - if (spi->max_speed_hz != chip->rate) { - int err; - - err = ep93xx_spi_calc_divisors(espi, chip, spi->max_speed_hz); - if (err != 0) { - spi_set_ctldata(spi, NULL); - kfree(chip); - return err; - } - chip->rate = spi->max_speed_hz; - } - ep93xx_spi_cs_control(spi, false); return 0; } -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 07/11] spi: spi-ep93xx: remove 'dss' from per chip private data
This value is only needed to set the bits per word for each transfer of a message. There is no reason to set the value in ep93xx_spi_enable() because ep93xx_spi_process_transfer() sets it again for each transfer. Just pass the t->bits_per_word directly to ep93xx_spi_chip_setup() in ep93xx_spi_process_transfer() and remove 'dss' from the per chip private data. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 17 +++-- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 34aade1..cc2a240 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -139,7 +139,6 @@ struct ep93xx_spi { * @rate: max rate in hz this chip supports * @div_cpsr: cpsr (pre-scaler) divider * @div_scr: scr divider - * @dss: bits per word (4 - 16 bits) * @ops: private chip operations * * This structure is used to store hardware register specific settings for each @@ -151,7 +150,6 @@ struct ep93xx_spi_chip { unsigned long rate; u8 div_cpsr; u8 div_scr; - u8 dss; struct ep93xx_spi_chip_ops *ops; }; @@ -329,8 +327,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) chip->rate = spi->max_speed_hz; } - chip->dss = bits_per_word_to_dss(spi->bits_per_word); - ep93xx_spi_cs_control(spi, false); return 0; } @@ -407,22 +403,25 @@ static void ep93xx_spi_cleanup(struct spi_device *spi) * ep93xx_spi_chip_setup() - configures hardware according to given @chip * @espi: ep93xx SPI controller struct * @chip: chip specific settings + * @bits_per_word: transfer bits_per_word * * This function sets up the actual hardware registers with settings given in * @chip. Note that no validation is done so make sure that callers validate * settings before calling this. */ static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, - const struct ep93xx_spi_chip *chip) + const struct ep93xx_spi_chip *chip, + u8 bits_per_word) { + u8 dss = bits_per_word_to_dss(bits_per_word); u16 cr0; cr0 = chip->div_scr << SSPCR0_SCR_SHIFT; cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT; - cr0 |= chip->dss; + cr0 |= dss; dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", - chip->spi->mode, chip->div_cpsr, chip->div_scr, chip->dss); + chip->spi->mode, chip->div_cpsr, chip->div_scr, dss); dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0); ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr); @@ -709,9 +708,7 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, return; } - chip->dss = bits_per_word_to_dss(t->bits_per_word); - - ep93xx_spi_chip_setup(espi, chip); + ep93xx_spi_chip_setup(espi, chip, t->bits_per_word); espi->rx = 0; espi->tx = 0; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 05/11] spi: spi-ep93xx: use devm_clk_get()
Use devm_clk_get() so that the clk_put() happens automatically when the last reference to this driver is dropped. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 9 +++-- 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index c2660c2..c1a610e 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -1021,7 +1021,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev) espi = spi_master_get_devdata(master); - espi->clk = clk_get(&pdev->dev, NULL); + espi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(espi->clk)) { dev_err(&pdev->dev, "unable to get spi clock\n"); error = PTR_ERR(espi->clk); @@ -1044,14 +1044,14 @@ static int ep93xx_spi_probe(struct platform_device *pdev) espi->regs_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(espi->regs_base)) { error = PTR_ERR(espi->regs_base); - goto fail_put_clock; + goto fail_release_master; } error = devm_request_irq(&pdev->dev, irq, ep93xx_spi_interrupt, 0, "ep93xx-spi", espi); if (error) { dev_err(&pdev->dev, "failed to request irq\n"); - goto fail_put_clock; + goto fail_release_master; } if (info->use_dma && ep93xx_spi_setup_dma(espi)) @@ -1085,8 +1085,6 @@ fail_free_queue: destroy_workqueue(espi->wq); fail_free_dma: ep93xx_spi_release_dma(espi); -fail_put_clock: - clk_put(espi->clk); fail_release_master: spi_master_put(master); @@ -1122,7 +1120,6 @@ static int ep93xx_spi_remove(struct platform_device *pdev) spin_unlock_irq(&espi->lock); ep93xx_spi_release_dma(espi); - clk_put(espi->clk); spi_unregister_master(master); return 0; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 04/11] spi: spi-ep93xx: get platform resources early in (*probe)
Get the platform resources early in the (*probe) to minimize the number of goto's in the error path. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 26 -- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d5e6420..c2660c2 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -991,6 +991,18 @@ static int ep93xx_spi_probe(struct platform_device *pdev) info = pdev->dev.platform_data; + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get irq resources\n"); + return -EBUSY; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "unable to get iomem resource\n"); + return -ENODEV; + } + master = spi_alloc_master(&pdev->dev, sizeof(*espi)); if (!master) { dev_err(&pdev->dev, "failed to allocate spi master\n"); @@ -1027,20 +1039,6 @@ static int ep93xx_spi_probe(struct platform_device *pdev) espi->min_rate = clk_get_rate(espi->clk) / (254 * 256); espi->pdev = pdev; - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - error = -EBUSY; - dev_err(&pdev->dev, "failed to get irq resources\n"); - goto fail_put_clock; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "unable to get iomem resource\n"); - error = -ENODEV; - goto fail_put_clock; - } - espi->sspdr_phys = res->start + SSPDR; espi->regs_base = devm_ioremap_resource(&pdev->dev, res); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 03/11] spi: spi-ep93xx: remove bits_per_word() helper
Check t->bits_per_word directly and remove the inline helper function. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 14 +++--- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d7eccfc..d5e6420 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -429,17 +429,9 @@ static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, ep93xx_spi_write_u16(espi, SSPCR0, cr0); } -static inline int bits_per_word(const struct ep93xx_spi *espi) -{ - struct spi_message *msg = espi->current_msg; - struct spi_transfer *t = msg->state; - - return t->bits_per_word; -} - static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) { - if (bits_per_word(espi) > 8) { + if (t->bits_per_word > 8) { u16 tx_val = 0; if (t->tx_buf) @@ -458,7 +450,7 @@ static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t) { - if (bits_per_word(espi) > 8) { + if (t->bits_per_word > 8) { u16 rx_val; rx_val = ep93xx_spi_read_u16(espi, SSPDR); @@ -544,7 +536,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir) size_t len = t->len; int i, ret, nents; - if (bits_per_word(espi) > 8) + if (t->bits_per_word > 8) buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; else buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 02/11] spi: spi-ep93xx: use read,write instead of __raw_* variants
The memory resource used by this driver is ioremap()'d and the normal read,write calls can be used instead of the __raw_* variants. Also, remove the inline tag on the helper functions and let the compiler decide if they are inlined. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 22 ++ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 11e2b99..d7eccfc 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -158,28 +158,26 @@ struct ep93xx_spi_chip { /* converts bits per word to CR0.DSS value */ #define bits_per_word_to_dss(bpw) ((bpw) - 1) -static inline void -ep93xx_spi_write_u8(const struct ep93xx_spi *espi, u16 reg, u8 value) +static void ep93xx_spi_write_u8(const struct ep93xx_spi *espi, + u16 reg, u8 value) { - __raw_writeb(value, espi->regs_base + reg); + writeb(value, espi->regs_base + reg); } -static inline u8 -ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg) +static u8 ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg) { - return __raw_readb(spi->regs_base + reg); + return readb(spi->regs_base + reg); } -static inline void -ep93xx_spi_write_u16(const struct ep93xx_spi *espi, u16 reg, u16 value) +static void ep93xx_spi_write_u16(const struct ep93xx_spi *espi, +u16 reg, u16 value) { - __raw_writew(value, espi->regs_base + reg); + writew(value, espi->regs_base + reg); } -static inline u16 -ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg) +static u16 ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg) { - return __raw_readw(spi->regs_base + reg); + return readw(spi->regs_base + reg); } static int ep93xx_spi_enable(const struct ep93xx_spi *espi) -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 01/11] spi: spi-ep93xx: always handle transfer specific settings
__spi_async(), which starts every SPI message transfer, initializes the bits_per_word and max speed for every transfer in the message. Since the conditional test in ep93xx_spi_process_transfer() will always succeed just remove it and always call ep93xx_spi_chip_setup() to configure the hardware for each transfer in the message. Remove the redundant ep93xx_spi_chp_setup() in ep93xx_spi_process_transfer() which just initializes the hardware to the "default" based on the SPI device. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 43 ++- 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index cad30b8..11e2b99 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -708,38 +708,20 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, struct spi_transfer *t) { struct ep93xx_spi_chip *chip = spi_get_ctldata(msg->spi); + int err; msg->state = t; - /* -* Handle any transfer specific settings if needed. We use -* temporary chip settings here and restore original later when -* the transfer is finished. -*/ - if (t->speed_hz || t->bits_per_word) { - struct ep93xx_spi_chip tmp_chip = *chip; - - if (t->speed_hz) { - int err; - - err = ep93xx_spi_calc_divisors(espi, &tmp_chip, - t->speed_hz); - if (err) { - dev_err(&espi->pdev->dev, - "failed to adjust speed\n"); - msg->status = err; - return; - } - } + err = ep93xx_spi_calc_divisors(espi, chip, t->speed_hz); + if (err) { + dev_err(&espi->pdev->dev, "failed to adjust speed\n"); + msg->status = err; + return; + } - if (t->bits_per_word) - tmp_chip.dss = bits_per_word_to_dss(t->bits_per_word); + chip->dss = bits_per_word_to_dss(t->bits_per_word); - /* -* Set up temporary new hw settings for this transfer. -*/ - ep93xx_spi_chip_setup(espi, &tmp_chip); - } + ep93xx_spi_chip_setup(espi, chip); espi->rx = 0; espi->tx = 0; @@ -783,9 +765,6 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, ep93xx_spi_cs_control(msg->spi, true); } } - - if (t->speed_hz || t->bits_per_word) - ep93xx_spi_chip_setup(espi, chip); } /* @@ -838,10 +817,8 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi, espi->fifo_level = 0; /* -* Update SPI controller registers according to spi device and assert -* the chipselect. +* Assert the chipselect. */ - ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi)); ep93xx_spi_cs_control(msg->spi, true); list_for_each_entry(t, &msg->transfers, transfer_list) { -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 00/11] spi: spi-ep93xx: tidy up and convert to queued driver infrastructure
Do a bit of housekeeping in this driver and convert it to use the SPI queued driver infrastructure. v2: rebased on next-20130702 address some comments from Ryan Mallon and Mika Westerberg added a couple more cleanup patches Patch 1/11 was already applied by Mark Brown. It is included here only for completeness. H Hartley Sweeten (11): spi: spi-ep93xx: always handle transfer specific settings spi: spi-ep93xx: use read,write instead of __raw_* variants spi: spi-ep93xx: remove bits_per_word() helper spi: spi-ep93xx: get platform resources early in (*probe) spi: spi-ep93xx: use devm_clk_get() spi: spi-ep93xx: remove dev_err() for kzalloc() failure spi: spi-ep93xx: remove 'dss' from per chip private data spi: spi-ep93xx: don't bother calculating the divisors in ep93xx_spi_setup() spi: spi-ep93xx: move the clock divider calcs into ep93xx_spi_chip_setup() spi: spi-ep93xx: convert to the queued driver infrastructure spi: spi-ep93xx: use master->cur_msg for in-flight message drivers/spi/spi-ep93xx.c | 437 ++- 1 file changed, 127 insertions(+), 310 deletions(-) -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 3/4] usb: ohci-ep93xx: use devm_clk_get()
Use devm_clk_get() to make the code a bit cleaner and simpler. This also fixes a bug where a clk_put() is not done if usb_add_hcd() fails. Signed-off-by: H Hartley Sweeten Acked-by: Alan Stern Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman --- drivers/usb/host/ohci-ep93xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index b4f5e64..28fa6b8 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -69,9 +69,8 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, goto err_put_hcd; } - usb_host_clock = clk_get(&pdev->dev, NULL); + usb_host_clock = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(usb_host_clock)) { - dev_dbg(&pdev->dev, "clk_get failed\n"); retval = PTR_ERR(usb_host_clock); goto err_put_hcd; } @@ -96,7 +95,6 @@ static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, { usb_remove_hcd(hcd); ep93xx_stop_hc(&pdev->dev); - clk_put(usb_host_clock); usb_put_hcd(hcd); } -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 4/4] usb: ohci-ep93xx: tidy up driver (*probe) and (*remove)
Merge the usb_hcd_ep93xx_probe() into ohci_hcd_ep93xx_drv_probe() and the usb_hcd_ep93xx_remove() into ohci_hcd_ep93xx_drv_remove(). As Alan Stern pointed out, there is no reason for them to be separate. Also, as Alan Stern suggested, eliminate the ep93xx_start_hc() and ep93xx_stop_hc() routines and simply call clk_enable() and clk_disable() directly. The extra level of redirection does not add any clarity. Signed-off-by: H Hartley Sweeten Cc: Alan Stern Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman --- drivers/usb/host/ohci-ep93xx.c | 128 + 1 file changed, 52 insertions(+), 76 deletions(-) diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 28fa6b8..84a20d5 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -30,74 +30,6 @@ static struct clk *usb_host_clock; -static void ep93xx_start_hc(struct device *dev) -{ - clk_enable(usb_host_clock); -} - -static void ep93xx_stop_hc(struct device *dev) -{ - clk_disable(usb_host_clock); -} - -static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, -struct platform_device *pdev) -{ - struct usb_hcd *hcd; - struct resource *res; - int irq; - int retval; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - - hcd = usb_create_hcd(driver, &pdev->dev, "ep93xx"); - if (hcd == NULL) - return -ENOMEM; - - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - - hcd->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(hcd->regs)) { - retval = PTR_ERR(hcd->regs); - goto err_put_hcd; - } - - usb_host_clock = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(usb_host_clock)) { - retval = PTR_ERR(usb_host_clock); - goto err_put_hcd; - } - - ep93xx_start_hc(&pdev->dev); - - ohci_hcd_init(hcd_to_ohci(hcd)); - - retval = usb_add_hcd(hcd, irq, 0); - if (retval == 0) - return retval; - - ep93xx_stop_hc(&pdev->dev); -err_put_hcd: - usb_put_hcd(hcd); - - return retval; -} - -static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, - struct platform_device *pdev) -{ - usb_remove_hcd(hcd); - ep93xx_stop_hc(&pdev->dev); - usb_put_hcd(hcd); -} - static int ohci_ep93xx_start(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); @@ -138,15 +70,57 @@ static struct hc_driver ohci_ep93xx_hc_driver = { .start_port_reset = ohci_start_port_reset, }; -extern int usb_disabled(void); - static int ohci_hcd_ep93xx_drv_probe(struct platform_device *pdev) { + struct usb_hcd *hcd; + struct resource *res; + int irq; int ret; - ret = -ENODEV; - if (!usb_disabled()) - ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, pdev); + if (usb_disabled()) + return -ENODEV; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENXIO; + + hcd = usb_create_hcd(&ohci_ep93xx_hc_driver, &pdev->dev, "ep93xx"); + if (!hcd) + return -ENOMEM; + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + + hcd->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hcd->regs)) { + ret = PTR_ERR(hcd->regs); + goto err_put_hcd; + } + + usb_host_clock = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(usb_host_clock)) { + ret = PTR_ERR(usb_host_clock); + goto err_put_hcd; + } + + clk_enable(usb_host_clock); + + ohci_hcd_init(hcd_to_ohci(hcd)); + + ret = usb_add_hcd(hcd, irq, 0); + if (ret) + goto err_clk_disable; + + return 0; + +err_clk_disable: + clk_disable(usb_host_clock); +err_put_hcd: + usb_put_hcd(hcd); return ret; } @@ -155,7 +129,9 @@ static int ohci_hcd_ep93xx_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); - usb_hcd_ep93xx_remove(hcd, pdev); + usb_remove_hcd(hcd); + clk_disable(usb_host_clock); + usb_put_hcd(hcd); return 0; } @@ -170,7 +146,7 @@ static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_ msleep(5); ohci->next_statechange = jiffies; - ep93xx_stop_hc(&pdev->dev); + clk_disable(usb_host_c
[PATCH v2 2/4] usb: ohci-ep93xx: use platform_get_irq()
Use platform_get_irq() instead of accessing the platform_device resources directly. Signed-off-by: H Hartley Sweeten Acked-by: Alan Stern Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman --- drivers/usb/host/ohci-ep93xx.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 4e12f67..b4f5e64 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -45,12 +45,12 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, { struct usb_hcd *hcd; struct resource *res; + int irq; int retval; - if (pdev->resource[1].flags != IORESOURCE_IRQ) { - dev_dbg(&pdev->dev, "resource[1] is not IORESOURCE_IRQ\n"); - return -ENOMEM; - } + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) @@ -80,7 +80,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, ohci_hcd_init(hcd_to_ohci(hcd)); - retval = usb_add_hcd(hcd, pdev->resource[1].start, 0); + retval = usb_add_hcd(hcd, irq, 0); if (retval == 0) return retval; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 0/4] usb: ohci-ep93xx: do a bit of housecleaning
Tidy up this driver a bit. v2: redo patch 4 based on suggestions from Alan Stern H Hartley Sweeten (4): usb: ohci-ep93xx: use devm_ioremap_resource() usb: ohci-ep93xx: use platform_get_irq() usb: ohci-ep93xx: use devm_clk_get() usb: ohci-ep93xx: tidy up driver (*probe) and (*remove) drivers/usb/host/ohci-ep93xx.c | 137 - 1 file changed, 52 insertions(+), 85 deletions(-) -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 1/4] usb: ohci-ep93xx: use devm_ioremap_resource()
Use devm_ioremap_resource() to make the code a bit cleaner and simpler. Signed-off-by: H Hartley Sweeten Acked-by: Alan Stern Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman --- drivers/usb/host/ohci-ep93xx.c | 35 ++- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 8704e9f..4e12f67 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -43,38 +43,37 @@ static void ep93xx_stop_hc(struct device *dev) static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, struct platform_device *pdev) { - int retval; struct usb_hcd *hcd; + struct resource *res; + int retval; if (pdev->resource[1].flags != IORESOURCE_IRQ) { dev_dbg(&pdev->dev, "resource[1] is not IORESOURCE_IRQ\n"); return -ENOMEM; } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENXIO; + hcd = usb_create_hcd(driver, &pdev->dev, "ep93xx"); if (hcd == NULL) return -ENOMEM; - hcd->rsrc_start = pdev->resource[0].start; - hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - usb_put_hcd(hcd); - retval = -EBUSY; - goto err1; - } + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (hcd->regs == NULL) { - dev_dbg(&pdev->dev, "ioremap failed\n"); - retval = -ENOMEM; - goto err2; + hcd->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hcd->regs)) { + retval = PTR_ERR(hcd->regs); + goto err_put_hcd; } usb_host_clock = clk_get(&pdev->dev, NULL); if (IS_ERR(usb_host_clock)) { dev_dbg(&pdev->dev, "clk_get failed\n"); retval = PTR_ERR(usb_host_clock); - goto err3; + goto err_put_hcd; } ep93xx_start_hc(&pdev->dev); @@ -86,11 +85,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, return retval; ep93xx_stop_hc(&pdev->dev); -err3: - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err1: +err_put_hcd: usb_put_hcd(hcd); return retval; @@ -102,8 +97,6 @@ static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, usb_remove_hcd(hcd); ep93xx_stop_hc(&pdev->dev); clk_put(usb_host_clock); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); } -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH 2/8] spi: spi-ep93xx: use bits_per_word_mask
On Monday, July 01, 2013 11:23 AM, H Hartley Sweeten wrote: > On Sunday, June 30, 2013 9:14 AM, Mika Westerberg wrote: >> Please use SPI_BPW_RANGE_MASK(4, 16) here. > > I thought there was a macro for this, just couldn't find it. I'll fix this. Doh... This patch is already in linux-next. I'll need to rebase this series. Regards, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH 2/8] spi: spi-ep93xx: use bits_per_word_mask
On Sunday, June 30, 2013 9:14 AM, Mika Westerberg wrote: > On Fri, Jun 28, 2013 at 11:43:07AM -0700, H Hartley Sweeten wrote: >> This driver supports 16 to 4 bits per work. Set the bits_per_word_mask >> to allows the spi core to handle validation. >> >> Signed-off-by: H Hartley Sweeten >> Cc: Ryan Mallon >> Cc: Mika Westerberg >> Cc: Mark Brown >> Cc: Grant Likely >> --- >> drivers/spi/spi-ep93xx.c | 11 +-- >> 1 file changed, 1 insertion(+), 10 deletions(-) >> >> diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c >> index c633cd0..93ae7b6 100644 >> --- a/drivers/spi/spi-ep93xx.c >> +++ b/drivers/spi/spi-ep93xx.c >> @@ -272,12 +272,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) >> struct ep93xx_spi *espi = spi_master_get_devdata(spi->master); >> struct ep93xx_spi_chip *chip; >> >> -if (spi->bits_per_word < 4 || spi->bits_per_word > 16) { >> -dev_err(&espi->pdev->dev, "invalid bits per word %d\n", >> -spi->bits_per_word); >> -return -EINVAL; >> -} >> - >> chip = spi_get_ctldata(spi); >> if (!chip) { >> dev_dbg(&espi->pdev->dev, "initial setup for %s\n", >> @@ -341,10 +335,6 @@ static int ep93xx_spi_transfer(struct spi_device *spi, >> struct spi_message *msg) >> >> /* first validate each transfer */ >> list_for_each_entry(t, &msg->transfers, transfer_list) { >> -if (t->bits_per_word) { >> -if (t->bits_per_word < 4 || t->bits_per_word > 16) >> -return -EINVAL; >> -} >> if (t->speed_hz && t->speed_hz < espi->min_rate) >> return -EINVAL; >> } >> @@ -1022,6 +1012,7 @@ static int ep93xx_spi_probe(struct platform_device >> *pdev) >> master->bus_num = pdev->id; >> master->num_chipselect = info->num_chipselect; >> master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; >> +master->bits_per_word_mask = 0xfff8;/* 16 to 4 bits per word */ > > Please use SPI_BPW_RANGE_MASK(4, 16) here. I thought there was a macro for this, just couldn't find it. I'll fix this. Thanks, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH 1/8] spi: spi-ep93xx: use read,write instead of __raw_* variants
On Monday, July 01, 2013 3:58 AM, Mark Brown wrote: > On Sat, Jun 29, 2013 at 09:15:09AM +1000, Ryan Mallon wrote: >> On 29/06/13 04:42, H Hartley Sweeten wrote: > >>> -static inline u8 >>> -ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg) >>> -{ >>> - return __raw_readb(spi->regs_base + reg); >>> -} > >> Is there a particular reason to drop these functions? It's basically just >> bike-shedding, but they can make the code more readable at very little >> cost. Even dropping the inline (which is preferred nowdays) the compiler >> will still inline these, and it would also make this patch much smaller >> to keep them. > > I tend to agree, it's much more normal to have the base + reg in a > function than not. OK. I will redo this one to just remove the __raw_. Regards, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH 3/8] spi: spi-ep93xx: always handle transfer specific settings
On Monday, July 01, 2013 3:28 AM, Mark Brown wrote: > On Fri, Jun 28, 2013 at 11:43:34AM -0700, H Hartley Sweeten wrote: >> __spi_async(), which starts every SPI message transfer, initializes >> the bits_per_word and max speed for every transfer in the message. >> Since the conditional test in ep93xx_spi_process_transfer() will >> always succeed just remove it and always call ep93xx_spi_chip_setup() >> to configure the hardware for each transfer in the message. > > Applied, thanks. Mark, I was going to redo this series based on the comments I have received so far. Did you already apply this one? Should I push it to the front of my patchset? Regards, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 4/4] usb: ohci-ep93xx: tidy up ohci_hcd_ep93xx_drv_probe()
Refactor the function a bit to remove the need for the local variable. The extern prototype of usb_disabled() is not needed. Signed-off-by: H Hartley Sweeten Cc: Alan Stern Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman --- drivers/usb/host/ohci-ep93xx.c | 11 +++ 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 28fa6b8..bdc2908 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -138,17 +138,12 @@ static struct hc_driver ohci_ep93xx_hc_driver = { .start_port_reset = ohci_start_port_reset, }; -extern int usb_disabled(void); - static int ohci_hcd_ep93xx_drv_probe(struct platform_device *pdev) { - int ret; - - ret = -ENODEV; - if (!usb_disabled()) - ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, pdev); + if (usb_disabled()) + return -ENODEV; - return ret; + return usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, pdev); } static int ohci_hcd_ep93xx_drv_remove(struct platform_device *pdev) -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/4] usb: ohci-ep93xx: use devm_clk_get()
Use devm_clk_get() to make the code a bit cleaner and simpler. This also fixes a bug where a clk_put() is not done if usb_add_hcd() fails. Signed-off-by: H Hartley Sweeten Cc: Alan Stern Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman --- drivers/usb/host/ohci-ep93xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index b4f5e64..28fa6b8 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -69,9 +69,8 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, goto err_put_hcd; } - usb_host_clock = clk_get(&pdev->dev, NULL); + usb_host_clock = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(usb_host_clock)) { - dev_dbg(&pdev->dev, "clk_get failed\n"); retval = PTR_ERR(usb_host_clock); goto err_put_hcd; } @@ -96,7 +95,6 @@ static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, { usb_remove_hcd(hcd); ep93xx_stop_hc(&pdev->dev); - clk_put(usb_host_clock); usb_put_hcd(hcd); } -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/4] usb: ohci-ep93xx: use platform_get_irq()
Use platform_get_irq() instead of accessing the platform_device resources directly. Signed-off-by: H Hartley Sweeten Cc: Alan Stern Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman --- drivers/usb/host/ohci-ep93xx.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 4e12f67..b4f5e64 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -45,12 +45,12 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, { struct usb_hcd *hcd; struct resource *res; + int irq; int retval; - if (pdev->resource[1].flags != IORESOURCE_IRQ) { - dev_dbg(&pdev->dev, "resource[1] is not IORESOURCE_IRQ\n"); - return -ENOMEM; - } + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) @@ -80,7 +80,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, ohci_hcd_init(hcd_to_ohci(hcd)); - retval = usb_add_hcd(hcd, pdev->resource[1].start, 0); + retval = usb_add_hcd(hcd, irq, 0); if (retval == 0) return retval; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/4] usb: ohci-ep93xx: use devm_ioremap_resource()
Use devm_ioremap_resource() to make the code a bit cleaner and simpler. Signed-off-by: H Hartley Sweeten Cc: Alan Stern Cc: Lennert Buytenhek Cc: Greg Kroah-Hartman --- drivers/usb/host/ohci-ep93xx.c | 35 ++- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 8704e9f..4e12f67 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -43,38 +43,37 @@ static void ep93xx_stop_hc(struct device *dev) static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, struct platform_device *pdev) { - int retval; struct usb_hcd *hcd; + struct resource *res; + int retval; if (pdev->resource[1].flags != IORESOURCE_IRQ) { dev_dbg(&pdev->dev, "resource[1] is not IORESOURCE_IRQ\n"); return -ENOMEM; } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENXIO; + hcd = usb_create_hcd(driver, &pdev->dev, "ep93xx"); if (hcd == NULL) return -ENOMEM; - hcd->rsrc_start = pdev->resource[0].start; - hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - usb_put_hcd(hcd); - retval = -EBUSY; - goto err1; - } + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (hcd->regs == NULL) { - dev_dbg(&pdev->dev, "ioremap failed\n"); - retval = -ENOMEM; - goto err2; + hcd->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hcd->regs)) { + retval = PTR_ERR(hcd->regs); + goto err_put_hcd; } usb_host_clock = clk_get(&pdev->dev, NULL); if (IS_ERR(usb_host_clock)) { dev_dbg(&pdev->dev, "clk_get failed\n"); retval = PTR_ERR(usb_host_clock); - goto err3; + goto err_put_hcd; } ep93xx_start_hc(&pdev->dev); @@ -86,11 +85,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, return retval; ep93xx_stop_hc(&pdev->dev); -err3: - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err1: +err_put_hcd: usb_put_hcd(hcd); return retval; @@ -102,8 +97,6 @@ static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, usb_remove_hcd(hcd); ep93xx_stop_hc(&pdev->dev); clk_put(usb_host_clock); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); } -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/4] usb: ohci-ep93xx: do a bit of house cleaning
Tidy up this driver a bit. H Hartley Sweeten (4): usb: ohci-ep93xx: use devm_ioremap_resource() usb: ohci-ep93xx: use platform_get_irq() usb: ohci-ep93xx: use devm_clk_get() usb: ohci-ep93xx: tidy up ohci_hcd_ep93xx_drv_probe() drivers/usb/host/ohci-ep93xx.c | 60 -- 1 file changed, 23 insertions(+), 37 deletions(-) -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Q: mmc au size
Hello all, I have a question concerning the "au" size of a SD Card. I have an old Kingston 64MB SD-Card and lately I have noticed this kernel message when I use the card: mmc0: SD Status: Invalid Allocation Unit size. This is due to the following commit: commit b63b5e819d5b21ae493c17c356018ffa98d3ee1c Author: Alan Cox Date: Mon Jul 2 18:55:13 2012 +0100 mmc: core: correct invalid error checking >From the "SD Specifications, Part 1, Physical Layer Specification", * AU_SIZE This 4-bit field indicates AU Size and the value can be selected from 16 KB. AU_SIZE Value Definition --- 0h Not Defined 1h 16 KB 2h 32 KB 3h 64 KB 4h 128 KB 5h 256 KB 6h 512 KB 7h 1 MB 8h 2 MB 9h 4 MB Ah 8 MB Bh 12 MB Ch 16 MB Dh 24 MB Eh 32 MB Fh 64 MB Also in the specification is this note: Sector: is the unit that is related to the erase commands. Its size is the number of blocks that will be erased in one portion. The size of a sector is fixed for each device. The information about the sector size (in blocks) is stored in the CSD. Note that if the card specifies AU size, sector size should be ignored. And this: * SECTOR_SIZE This field is fixed to 7Fh, which indicates 64 KBytes. This value does not relate to erase operations. High Capacity and Extended Capacity cards indicate memory boundary by AU size and this field should not be used. So, if an au size of 0 is reported wouldn't the erase size be the sector size? If nothing else I think the test needs to be adjusted to not report the error for an au size of 0. Regards, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH 3/8] spi: spi-ep93xx: always handle transfer specific settings
On Friday, June 28, 2013 4:18 PM, Ryan Mallon wrote: > On 29/06/13 04:43, H Hartley Sweeten wrote: >> __spi_async(), which starts every SPI message transfer, initializes >> the bits_per_word and max speed for every transfer in the message. >> Since the conditional test in ep93xx_spi_process_transfer() will >> always succeed just remove it and always call ep93xx_spi_chip_setup() >> to configure the hardware for each transfer in the message. >> >> Remove the redundant ep93xx_spi_chp_setup() in ep93xx_spi_process_transfer() >> which just initializes the hardware to the "default" based on the SPI >> device. >> >> Signed-off-by: H Hartley Sweeten >> Cc: Ryan Mallon >> Cc: Mika Westerberg >> Cc: Mark Brown >> Cc: Grant Likely >> --- > > >> +err = ep93xx_spi_calc_divisors(espi, chip, t->speed_hz); >> +if (err) { >> +dev_err(&espi->pdev->dev, "failed to adjust speed\n"); > > > Printing out the speed it was trying to set might be useful here? Technically I don't think this can ever happen. The minimum and maximum possible speeds are determined during the probe. espi->max_rate = clk_get_rate(espi->clk) / 2; espi->min_rate = clk_get_rate(espi->clk) / (254 * 256); Each transfer is validated to make sure the speed is greater than the minimum. if (t->speed_hz < espi->min_rate) return -EINVAL; Then the rate is clamped to the min/max rates. rate = clamp(rate, espi->min_rate, espi->max_rate); The calculations for the div_csr and div_cpsr values needed to produce the desired rate should always succeed. Patch 7/8 actually replaces that dev_err() message with a more generic one. In reality, even the new message, and the error checking, could probably be removed. Regards, Hartley N�r��yb�X��ǧv�^�){.n�+{zX����ܨ}���Ơz�&j:+v���zZ+��+zf���h���~i���z��w���?�&�)ߢf��^jǫy�m��@A�a��� 0��h���i
Q: mmc au size
Hello Chris, I have a question concerning the "au" size of a SD Card. I have an old Kingston 64MB SD-Card and lately I have noticed this kernel message when I use the card: mmc0: SD Status: Invalid Allocation Unit size. This is due to the following commit: commit b63b5e819d5b21ae493c17c356018ffa98d3ee1c Author: Alan Cox Date: Mon Jul 2 18:55:13 2012 +0100 mmc: core: correct invalid error checking >From the "SD Specifications, Part 1, Physical Layer Specification", * AU_SIZE This 4-bit field indicates AU Size and the value can be selected from 16 KB. AU_SIZE Value Definition --- 0h Not Defined 1h 16 KB 2h 32 KB 3h 64 KB 4h 128 KB 5h 256 KB 6h 512 KB 7h 1 MB 8h 2 MB 9h 4 MB Ah 8 MB Bh 12 MB Ch 16 MB Dh 24 MB Eh 32 MB Fh 64 MB Also in the specification is this note: Sector: is the unit that is related to the erase commands. Its size is the number of blocks that will be erased in one portion. The size of a sector is fixed for each device. The information about the sector size (in blocks) is stored in the CSD. Note that if the card specifies AU size, sector size should be ignored. And this: * SECTOR_SIZE This field is fixed to 7Fh, which indicates 64 KBytes. This value does not relate to erase operations. High Capacity and Extended Capacity cards indicate memory boundary by AU size and this field should not be used. So, if an au size of 0 is reported wouldn't the erase size be the sector size? If nothing else I think the test needs to be adjusted to not report the error for an au size of 0. Regards, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 8/8] spi: spi-ep93xx: convert to the queued driver infrastructure
The SPI core provides infrastructure for standard message queueing. Use that instead of handling it in the driver. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 164 ++- 1 file changed, 19 insertions(+), 145 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 56305d3..93dad1e 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -70,19 +69,13 @@ /** * struct ep93xx_spi - EP93xx SPI controller structure - * @lock: spinlock that protects concurrent accesses to fields @running, - *@current_msg and @msg_queue * @pdev: pointer to platform device * @clk: clock for the controller * @regs_base: pointer to ioremap()'d registers * @sspdr_phys: physical address of the SSPDR register * @min_rate: minimum clock rate (in Hz) supported by the controller * @max_rate: maximum clock rate (in Hz) supported by the controller - * @running: is the queue running - * @wq: workqueue used by the driver - * @msg_work: work that is queued for the driver * @wait: wait here until given transfer is completed - * @msg_queue: queue for the messages * @current_msg: message that is currently processed (or %NULL if none) * @tx: current byte in transfer to transmit * @rx: current byte in transfer to receive @@ -96,31 +89,16 @@ * @tx_sgt: sg table for TX transfers * @zeropage: dummy page used as RX buffer when only TX buffer is passed in by *the client - * - * This structure holds EP93xx SPI controller specific information. When - * @running is %true, driver accepts transfer requests from protocol drivers. - * @current_msg is used to hold pointer to the message that is currently - * processed. If @current_msg is %NULL, it means that no processing is going - * on. - * - * Most of the fields are only written once and they can be accessed without - * taking the @lock. Fields that are accessed concurrently are: @current_msg, - * @running, and @msg_queue. */ struct ep93xx_spi { - spinlock_t lock; const struct platform_device*pdev; struct clk *clk; void __iomem*regs_base; unsigned long sspdr_phys; unsigned long min_rate; unsigned long max_rate; - boolrunning; boolword_xfer; - struct workqueue_struct *wq; - struct work_struct msg_work; struct completion wait; - struct list_headmsg_queue; struct spi_message *current_msg; size_t tx; size_t rx; @@ -206,7 +184,7 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, /* * Make sure that max value is between values supported by the * controller. Note that minimum value is already checked in -* ep93xx_spi_transfer(). +* ep93xx_spi_transfer_one_message(). */ rate = clamp(rate, espi->min_rate, espi->max_rate); @@ -282,54 +260,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) } /** - * ep93xx_spi_transfer() - queue message to be transferred - * @spi: target SPI device - * @msg: message to be transferred - * - * This function is called by SPI device drivers when they are going to transfer - * a new message. It simply puts the message in the queue and schedules - * workqueue to perform the actual transfer later on. - * - * Returns %0 on success and negative error in case of failure. - */ -static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg) -{ - struct ep93xx_spi *espi = spi_master_get_devdata(spi->master); - struct spi_transfer *t; - unsigned long flags; - - if (!msg || !msg->complete) - return -EINVAL; - - /* first validate each transfer */ - list_for_each_entry(t, &msg->transfers, transfer_list) { - if (t->speed_hz && t->speed_hz < espi->min_rate) - return -EINVAL; - } - - /* -* Now that we own the message, let's initialize it so that it is -* suitable for us. We use @msg->status to signal whether there was -* error in transfer and @msg->state is used to hold pointer to the -* current transfer (or %NULL if no active current transfer). -*/ - msg->state = NULL; - msg->status = 0; - msg->actual_length = 0; - - spin_lock_irqsave(&espi->lock, flags); - if (!espi->running) { - spi
[PATCH 7/8] spi: spi-ep93xx: move the clock divider calcs into ep93xx_spi_chip_setup()
The divider values stored in the per chip data are only used to set the registers in the hardware to generate the desired SPI clock. Since these are calculated per transfer based on the t->speed_hz there is no reason keep them in the per chip data. Move the ep93xx_spi_calc_divisors() call into ep93xx_spi_chip_setup() and return the dividers thru pointers. Remove the divider values from the per chip data structure. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 58 +--- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 2f2d51a..56305d3 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -137,18 +137,10 @@ struct ep93xx_spi { /** * struct ep93xx_spi_chip - SPI device hardware settings * @spi: back pointer to the SPI device - * @div_cpsr: cpsr (pre-scaler) divider - * @div_scr: scr divider * @ops: private chip operations - * - * This structure is used to store hardware register specific settings for each - * SPI device. Settings are written to hardware by function - * ep93xx_spi_chip_setup(). */ struct ep93xx_spi_chip { const struct spi_device *spi; - u8 div_cpsr; - u8 div_scr; struct ep93xx_spi_chip_ops *ops; }; @@ -200,17 +192,13 @@ static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi) /** * ep93xx_spi_calc_divisors() - calculates SPI clock divisors * @espi: ep93xx SPI controller struct - * @chip: divisors are calculated for this chip * @rate: desired SPI output clock rate - * - * Function calculates cpsr (clock pre-scaler) and scr divisors based on - * given @rate and places them to @chip->div_cpsr and @chip->div_scr. If, - * for some reason, divisors cannot be calculated nothing is stored and - * %-EINVAL is returned. + * @div_cpsr: pointer to return the cpsr (pre-scaler) divider + * @div_scr: pointer to return the scr divider */ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, - struct ep93xx_spi_chip *chip, - unsigned long rate) + unsigned long rate, + u8 *div_cpsr, u8 *div_scr) { unsigned long spi_clk_rate = clk_get_rate(espi->clk); int cpsr, scr; @@ -233,8 +221,8 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, for (cpsr = 2; cpsr <= 254; cpsr += 2) { for (scr = 0; scr <= 255; scr++) { if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) { - chip->div_scr = (u8)scr; - chip->div_cpsr = (u8)cpsr; + *div_scr = (u8)scr; + *div_cpsr = (u8)cpsr; return 0; } } @@ -365,29 +353,34 @@ static void ep93xx_spi_cleanup(struct spi_device *spi) * ep93xx_spi_chip_setup() - configures hardware according to given @chip * @espi: ep93xx SPI controller struct * @chip: chip specific settings + * @speed_hz: transfer speed * @bits_per_word: transfer bits_per_word - * - * This function sets up the actual hardware registers with settings given in - * @chip. Note that no validation is done so make sure that callers validate - * settings before calling this. */ -static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, - const struct ep93xx_spi_chip *chip, - u8 bits_per_word) +static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, +struct ep93xx_spi_chip *chip, +u32 speed_hz, u8 bits_per_word) { + u8 div_cpsr = 0; + u8 div_scr = 0; u16 cr0; + int err; + + err = ep93xx_spi_calc_divisors(espi, speed_hz, &div_cpsr, &div_scr); + if (err) + return err; - cr0 = chip->div_scr << SSPCR0_SCR_SHIFT; + cr0 = div_scr << SSPCR0_SCR_SHIFT; cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT; cr0 |= (bits_per_word - 1); dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", - chip->spi->mode, chip->div_cpsr, chip->div_scr, - bits_per_word - 1); + chip->spi->mode, div_cpsr, div_scr, bits_per_word - 1); dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0); - writeb(chip->div_cpsr, espi->regs_base + SSPCPSR); + writeb(div_cpsr, espi->regs_base + SSPCPSR); writew(cr0, espi->regs_b
[PATCH 6/8] spi: spi-ep93xx: don't bother calculating the divisors in ep93xx_spi_setup()
The divisors needed to generate the SPI clock are calculated per transfer based on the t->speed_hz. There is no reason to calculate them in ep93xx_spi_setup(). Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 14 -- 1 file changed, 14 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index cb22c89..2f2d51a 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -137,7 +137,6 @@ struct ep93xx_spi { /** * struct ep93xx_spi_chip - SPI device hardware settings * @spi: back pointer to the SPI device - * @rate: max rate in hz this chip supports * @div_cpsr: cpsr (pre-scaler) divider * @div_scr: scr divider * @ops: private chip operations @@ -148,7 +147,6 @@ struct ep93xx_spi { */ struct ep93xx_spi_chip { const struct spi_device *spi; - unsigned long rate; u8 div_cpsr; u8 div_scr; struct ep93xx_spi_chip_ops *ops; @@ -291,18 +289,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) spi_set_ctldata(spi, chip); } - if (spi->max_speed_hz != chip->rate) { - int err; - - err = ep93xx_spi_calc_divisors(espi, chip, spi->max_speed_hz); - if (err != 0) { - spi_set_ctldata(spi, NULL); - kfree(chip); - return err; - } - chip->rate = spi->max_speed_hz; - } - ep93xx_spi_cs_control(spi, false); return 0; } -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 5/8] spi: spi-ep93xx: remove 'dss' from per chip private data
This value is only needed to set the bits per word for each transfer of a message. There is no reason to set the value in ep93xx_spi_enable() because ep93xx_spi_process_transfer() sets it again for each transfer. Just pass the t->bits_per_word directly to ep93xx_spi_chip_setup() in ep93xx_spi_process_transfer() and remove 'dss' from the per chip private data. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 20 +++- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 4fab3bb..cb22c89 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -140,7 +140,6 @@ struct ep93xx_spi { * @rate: max rate in hz this chip supports * @div_cpsr: cpsr (pre-scaler) divider * @div_scr: scr divider - * @dss: bits per word (4 - 16 bits) * @ops: private chip operations * * This structure is used to store hardware register specific settings for each @@ -152,13 +151,9 @@ struct ep93xx_spi_chip { unsigned long rate; u8 div_cpsr; u8 div_scr; - u8 dss; struct ep93xx_spi_chip_ops *ops; }; -/* converts bits per word to CR0.DSS value */ -#define bits_per_word_to_dss(bpw) ((bpw) - 1) - static int ep93xx_spi_enable(const struct ep93xx_spi *espi) { u8 regval; @@ -308,8 +303,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) chip->rate = spi->max_speed_hz; } - chip->dss = bits_per_word_to_dss(spi->bits_per_word); - ep93xx_spi_cs_control(spi, false); return 0; } @@ -386,22 +379,25 @@ static void ep93xx_spi_cleanup(struct spi_device *spi) * ep93xx_spi_chip_setup() - configures hardware according to given @chip * @espi: ep93xx SPI controller struct * @chip: chip specific settings + * @bits_per_word: transfer bits_per_word * * This function sets up the actual hardware registers with settings given in * @chip. Note that no validation is done so make sure that callers validate * settings before calling this. */ static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, - const struct ep93xx_spi_chip *chip) + const struct ep93xx_spi_chip *chip, + u8 bits_per_word) { u16 cr0; cr0 = chip->div_scr << SSPCR0_SCR_SHIFT; cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT; - cr0 |= chip->dss; + cr0 |= (bits_per_word - 1); dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", - chip->spi->mode, chip->div_cpsr, chip->div_scr, chip->dss); + chip->spi->mode, chip->div_cpsr, chip->div_scr, + bits_per_word - 1); dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0); writeb(chip->div_cpsr, espi->regs_base + SSPCPSR); @@ -688,9 +684,7 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, return; } - chip->dss = bits_per_word_to_dss(t->bits_per_word); - - ep93xx_spi_chip_setup(espi, chip); + ep93xx_spi_chip_setup(espi, chip, t->bits_per_word); espi->word_xfer = (t->bits_per_word > 8) ? true : false; espi->rx = 0; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 4/8] spi: spi-ep93xx: remove bits_per_word() helper
This inline helper function is only used to determine the bus width of the current transfer (8 or 16 bit). Add a bool flag to the private structure and set it appropriately for each transfer. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 16 +--- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index bcfd35a..4fab3bb 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -116,6 +116,7 @@ struct ep93xx_spi { unsigned long min_rate; unsigned long max_rate; boolrunning; + boolword_xfer; struct workqueue_struct *wq; struct work_struct msg_work; struct completion wait; @@ -407,17 +408,9 @@ static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, writew(cr0, espi->regs_base + SSPCR0); } -static inline int bits_per_word(const struct ep93xx_spi *espi) -{ - struct spi_message *msg = espi->current_msg; - struct spi_transfer *t = msg->state; - - return t->bits_per_word; -} - static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) { - if (bits_per_word(espi) > 8) { + if (espi->word_xfer) { u16 tx_val = 0; if (t->tx_buf) @@ -436,7 +429,7 @@ static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t) { - if (bits_per_word(espi) > 8) { + if (espi->word_xfer) { u16 rx_val; rx_val = readw(espi->regs_base + SSPDR); @@ -522,7 +515,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir) size_t len = t->len; int i, ret, nents; - if (bits_per_word(espi) > 8) + if (espi->word_xfer) buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; else buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; @@ -699,6 +692,7 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, ep93xx_spi_chip_setup(espi, chip); + espi->word_xfer = (t->bits_per_word > 8) ? true : false; espi->rx = 0; espi->tx = 0; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/8] spi: spi-ep93xx: always handle transfer specific settings
__spi_async(), which starts every SPI message transfer, initializes the bits_per_word and max speed for every transfer in the message. Since the conditional test in ep93xx_spi_process_transfer() will always succeed just remove it and always call ep93xx_spi_chip_setup() to configure the hardware for each transfer in the message. Remove the redundant ep93xx_spi_chp_setup() in ep93xx_spi_process_transfer() which just initializes the hardware to the "default" based on the SPI device. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 43 ++- 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 93ae7b6..bcfd35a 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -684,38 +684,20 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, struct spi_transfer *t) { struct ep93xx_spi_chip *chip = spi_get_ctldata(msg->spi); + int err; msg->state = t; - /* -* Handle any transfer specific settings if needed. We use -* temporary chip settings here and restore original later when -* the transfer is finished. -*/ - if (t->speed_hz || t->bits_per_word) { - struct ep93xx_spi_chip tmp_chip = *chip; - - if (t->speed_hz) { - int err; - - err = ep93xx_spi_calc_divisors(espi, &tmp_chip, - t->speed_hz); - if (err) { - dev_err(&espi->pdev->dev, - "failed to adjust speed\n"); - msg->status = err; - return; - } - } + err = ep93xx_spi_calc_divisors(espi, chip, t->speed_hz); + if (err) { + dev_err(&espi->pdev->dev, "failed to adjust speed\n"); + msg->status = err; + return; + } - if (t->bits_per_word) - tmp_chip.dss = bits_per_word_to_dss(t->bits_per_word); + chip->dss = bits_per_word_to_dss(t->bits_per_word); - /* -* Set up temporary new hw settings for this transfer. -*/ - ep93xx_spi_chip_setup(espi, &tmp_chip); - } + ep93xx_spi_chip_setup(espi, chip); espi->rx = 0; espi->tx = 0; @@ -759,9 +741,6 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, ep93xx_spi_cs_control(msg->spi, true); } } - - if (t->speed_hz || t->bits_per_word) - ep93xx_spi_chip_setup(espi, chip); } /* @@ -814,10 +793,8 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi, espi->fifo_level = 0; /* -* Update SPI controller registers according to spi device and assert -* the chipselect. +* Assert the chipselect. */ - ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi)); ep93xx_spi_cs_control(msg->spi, true); list_for_each_entry(t, &msg->transfers, transfer_list) { -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/8] spi: spi-ep93xx: use bits_per_word_mask
This driver supports 16 to 4 bits per work. Set the bits_per_word_mask to allows the spi core to handle validation. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 11 +-- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index c633cd0..93ae7b6 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -272,12 +272,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) struct ep93xx_spi *espi = spi_master_get_devdata(spi->master); struct ep93xx_spi_chip *chip; - if (spi->bits_per_word < 4 || spi->bits_per_word > 16) { - dev_err(&espi->pdev->dev, "invalid bits per word %d\n", - spi->bits_per_word); - return -EINVAL; - } - chip = spi_get_ctldata(spi); if (!chip) { dev_dbg(&espi->pdev->dev, "initial setup for %s\n", @@ -341,10 +335,6 @@ static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg) /* first validate each transfer */ list_for_each_entry(t, &msg->transfers, transfer_list) { - if (t->bits_per_word) { - if (t->bits_per_word < 4 || t->bits_per_word > 16) - return -EINVAL; - } if (t->speed_hz && t->speed_hz < espi->min_rate) return -EINVAL; } @@ -1022,6 +1012,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev) master->bus_num = pdev->id; master->num_chipselect = info->num_chipselect; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + master->bits_per_word_mask = 0xfff8;/* 16 to 4 bits per word */ platform_set_drvdata(pdev, master); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/8] spi: spi-ep93xx: use read,write instead of __raw_* variants
The memory resource used by this driver is ioremap()'d and the normal read,write calls can be used instead of the __raw_* variants. Remove the inline read,write helpers and just do the read,write directly in the callers. Signed-off-by: H Hartley Sweeten Cc: Ryan Mallon Cc: Mika Westerberg Cc: Mark Brown Cc: Grant Likely --- drivers/spi/spi-ep93xx.c | 64 +++- 1 file changed, 20 insertions(+), 44 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d7bac60..c633cd0 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -158,30 +158,6 @@ struct ep93xx_spi_chip { /* converts bits per word to CR0.DSS value */ #define bits_per_word_to_dss(bpw) ((bpw) - 1) -static inline void -ep93xx_spi_write_u8(const struct ep93xx_spi *espi, u16 reg, u8 value) -{ - __raw_writeb(value, espi->regs_base + reg); -} - -static inline u8 -ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg) -{ - return __raw_readb(spi->regs_base + reg); -} - -static inline void -ep93xx_spi_write_u16(const struct ep93xx_spi *espi, u16 reg, u16 value) -{ - __raw_writew(value, espi->regs_base + reg); -} - -static inline u16 -ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg) -{ - return __raw_readw(spi->regs_base + reg); -} - static int ep93xx_spi_enable(const struct ep93xx_spi *espi) { u8 regval; @@ -191,9 +167,9 @@ static int ep93xx_spi_enable(const struct ep93xx_spi *espi) if (err) return err; - regval = ep93xx_spi_read_u8(espi, SSPCR1); + regval = readb(espi->regs_base + SSPCR1); regval |= SSPCR1_SSE; - ep93xx_spi_write_u8(espi, SSPCR1, regval); + writeb(regval, espi->regs_base + SSPCR1); return 0; } @@ -202,9 +178,9 @@ static void ep93xx_spi_disable(const struct ep93xx_spi *espi) { u8 regval; - regval = ep93xx_spi_read_u8(espi, SSPCR1); + regval = readb(espi->regs_base + SSPCR1); regval &= ~SSPCR1_SSE; - ep93xx_spi_write_u8(espi, SSPCR1, regval); + writeb(regval, espi->regs_base + SSPCR1); clk_disable(espi->clk); } @@ -213,18 +189,18 @@ static void ep93xx_spi_enable_interrupts(const struct ep93xx_spi *espi) { u8 regval; - regval = ep93xx_spi_read_u8(espi, SSPCR1); + regval = readb(espi->regs_base + SSPCR1); regval |= (SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE); - ep93xx_spi_write_u8(espi, SSPCR1, regval); + writeb(regval, espi->regs_base + SSPCR1); } static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi) { u8 regval; - regval = ep93xx_spi_read_u8(espi, SSPCR1); + regval = readb(espi->regs_base + SSPCR1); regval &= ~(SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE); - ep93xx_spi_write_u8(espi, SSPCR1, regval); + writeb(regval, espi->regs_base + SSPCR1); } /** @@ -437,8 +413,8 @@ static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, chip->spi->mode, chip->div_cpsr, chip->div_scr, chip->dss); dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0); - ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr); - ep93xx_spi_write_u16(espi, SSPCR0, cr0); + writeb(chip->div_cpsr, espi->regs_base + SSPCPSR); + writew(cr0, espi->regs_base + SSPCR0); } static inline int bits_per_word(const struct ep93xx_spi *espi) @@ -456,14 +432,14 @@ static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) if (t->tx_buf) tx_val = ((u16 *)t->tx_buf)[espi->tx]; - ep93xx_spi_write_u16(espi, SSPDR, tx_val); + writew(tx_val, espi->regs_base + SSPDR); espi->tx += sizeof(tx_val); } else { u8 tx_val = 0; if (t->tx_buf) tx_val = ((u8 *)t->tx_buf)[espi->tx]; - ep93xx_spi_write_u8(espi, SSPDR, tx_val); + writeb(tx_val, espi->regs_base + SSPDR); espi->tx += sizeof(tx_val); } } @@ -473,14 +449,14 @@ static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t) if (bits_per_word(espi) > 8) { u16 rx_val; - rx_val = ep93xx_spi_read_u16(espi, SSPDR); + rx_val = readw(espi->regs_base + SSPDR); if (t->rx_buf) ((u16 *)t->rx_buf)[espi->rx] = rx_val; espi->rx += sizeof(rx_val); } else { u8 rx_val; - rx_val = ep93xx_spi_read_u8(espi, SSPDR); + rx_val = readb(espi->regs_base + SSPDR); if (t->rx_buf) ((u8 *)t->rx_buf)[espi->rx] = rx_val; espi->rx += sizeof(r
[PATCH 0/8] spi: spi-ep93xx: tidy up and convert to queued driver infrastructure
Do a bit of housecleaning in this driver and convert it to use the SPI queued driver infrastructure. H Hartley Sweeten (8): spi: spi-ep93xx: use read,write instead of __raw_* variants spi: spi-ep93xx: use bits_per_word_mask spi: spi-ep93xx: always handle transfer specific settings spi: spi-ep93xx: remove bits_per_word() helper spi: spi-ep93xx: remove 'dss' from per chip private data spi: spi-ep93xx: don't bother calculating the divisors in ep93xx_spi_setup() spi: spi-ep93xx: move the clock divider calcs into ep93xx_spi_chip_setup() spi: spi-ep93xx: convert to the queued driver infrastructure drivers/spi/spi-ep93xx.c | 366 ++- 1 file changed, 75 insertions(+), 291 deletions(-) -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH v4] pwm: add sysfs interface
On Tuesday, June 11, 2013 12:48 PM, Thierry Reding wrote: > > I'm tempted to take your v5 patch and make a note to clean that up > separately at some point (along with similar changes for the DEBUG_FS > support). Thierry, So you want a v6 of this patch or are you ok with v5? Thanks, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH v4] pwm: add sysfs interface
On Tuesday, June 11, 2013 11:35 AM, Thierry Reding wrote: > On Tue, Jun 11, 2013 at 11:47:23AM -0500, H Hartley Sweeten wrote: >> On Tuesday, June 11, 2013 9:09 AM, H Hartley Sweeten wrote: >>> On Tuesday, June 11, 2013 4:29 AM, Ryan Mallon wrote: >>>> On 11/06/13 20:14, Thierry Reding wrote: >>>>> On Mon, Jun 10, 2013 at 04:12:07PM -0700, H Hartley Sweeten wrote: >>>>>> +config PWM_SYSFS >>>>>> +bool "/sys/class/pwm/... (sysfs interface)" >>>>>> +depends on SYSFS >>>>>> +help >>>>>> + Say Y here to provide a sysfs interface to control PWMs. >>>>>> + >>>>>> + For every instance of a PWM device there is a pwmchipN >>>>>> directory >>>>>> + created in /sys/class/pwm. Use the export attribute to request >>>>>> + a PWM to be accessible from userspace and the unexport >>>>>> attribute >>>>>> + to return the PWM to the kernel. Each exported PWM will have a >>>>>> + pwmX directory in the pwmchipN it is associated with. >>>>> >>>>> I have a small quibble with this. Introducing options like this make it >>>>> increasingly difficult to compile-test all the various combinations, so >>>>> I'd like to see this converted to a form that will play well with the >>>>> IS_ENABLED() macro. We already have the same issue with DEBUG_FS, only >>>>> to a lesser degree because it doesn't have an additional PWM-specific >>>>> Kconfig option. >>> >>> How about removing the Kconfig option and just doing: >>> >>> obj-$(CONFIG_SYSFS) += sysfs.o >>> >>> This way the PWM sysfs interface is always compiled and included in the >>> build >>> as long as CONFIG_SYSFS is enabled. The check in the header would change to >> >> That didn't work. As Ryan pointed out we get undefined references due to >> sysfs.c being compiled but not core.c when CONFIG_PWM is not enabled. > > Why not add dummies for the missing functions? It was my impression that > we had dummies for all of them already, but if not they should certainly > be added to match what other subsystems do. I just looked it over and the undefined reference was for pwm_set_polarity(). The dummy for that function is missing. The other problem with this approach is the sysfs.c file gets compiled whenever CONFIG_SYSFS is enabled even if CONFIG_PWM is not enabled. Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v5] pwm: add sysfs interface
Add a simple sysfs interface to the generic PWM framework. /sys/class/pwm/ `-- pwmchipN/ for each PWM chip |-- export (w/o) ask the kernel to export a PWM channel |-- npwm(r/o) number of PWM channels in this PWM chip |-- pwmX/ for each exported PWM channel | |-- duty_cycle (r/w) duty cycle (in nanoseconds) | |-- enable (r/w) enable/disable PWM | |-- period (r/w) period (in nanoseconds) | `-- polarity(r/w) polarity of PWM (normal/inversed) `-- unexport(w/o) return a PWM channel to the kernel Signed-off-by: H Hartley Sweeten Cc: Thierry Reding Cc: Lars Poeschel Cc: Ryan Mallon Cc: Rob Landley --- v5: * rename the 'duty' attribute to 'duty_cycle' * make the Kconfig option hidden and enabled when CONFIG_SYSFS is enabled * use sysfs_streq() in pwm_polarity_store() v4: * address a number of issues pointed out by Thierry Reding - fix some typos and wording issues in the Documentation - rename the new source file to sysfs.c - rename some of the variables in sysfs.c to clarify them - fix the period store so it does not change the duty cycle - change the polarity attribute to use a string representation - add a warning message is the pwmchip_sysfs_export() fails v3: * fix an issue with the export/unexport of the PWM chip v2: * add API documentation and update Documentation/pwm.txt * fix some issues pointed out by Ryan Mallon * add the pwm attributes to dev.groups so they are created when the device is registered for the exported PWM v1: * Based on previous work by Lars Poecshel Documentation/ABI/testing/sysfs-class-pwm | 79 +++ Documentation/pwm.txt | 37 drivers/pwm/Kconfig | 4 + drivers/pwm/Makefile | 1 + drivers/pwm/core.c| 25 ++- drivers/pwm/sysfs.c | 352 ++ include/linux/pwm.h | 29 ++- 7 files changed, 524 insertions(+), 3 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-pwm create mode 100644 drivers/pwm/sysfs.c diff --git a/Documentation/ABI/testing/sysfs-class-pwm b/Documentation/ABI/testing/sysfs-class-pwm new file mode 100644 index 000..c479d77 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-pwm @@ -0,0 +1,79 @@ +What: /sys/class/pwm/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + The pwm/ class sub-directory belongs to the Generic PWM + Framework and provides a sysfs interface for using PWM + channels. + +What: /sys/class/pwm/pwmchipN/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + A /sys/class/pwm/pwmchipN directory is created for each + probed PWM controller/chip where N is the base of the + PWM chip. + +What: /sys/class/pwm/pwmchipN/npwm +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + The number of PWM channels supported by the PWM chip. + +What: /sys/class/pwm/pwmchipN/export +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Exports a PWM channel from the PWM chip for sysfs control. + Value is between 0 and /sys/class/pwm/pwmchipN/npwm - 1. + +What: /sys/class/pwm/pwmchipN/unexport +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Unexports a PWM channel. + +What: /sys/class/pwm/pwmchipN/pwmX +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + A /sys/class/pwm/pwmchipN/pwmX directory is created for + each exported PWM channel where X is the exported PWM + channel number. + +What: /sys/class/pwm/pwmchipN/pwmX/period +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the PWM signal period in nanoseconds. + +What: /sys/class/pwm/pwmchipN/pwmX/duty_cycle +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the PWM signal duty cycle in nanoseconds. + +What: /sys/class/pwm/pwmchipN/pwmX/polarity +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the output polarity of the PWM signal to "normal" or + "inversed". + +What: /sys/class/pwm/pwmchipN/pwmX/enable +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Enable/disable the PWM signal. +
RE: [PATCH v4] pwm: add sysfs interface
On Tuesday, June 11, 2013 9:09 AM, H Hartley Sweeten wrote: > On Tuesday, June 11, 2013 4:29 AM, Ryan Mallon wrote: >> On 11/06/13 20:14, Thierry Reding wrote: >>> On Mon, Jun 10, 2013 at 04:12:07PM -0700, H Hartley Sweeten wrote: >>>> +config PWM_SYSFS >>>> + bool "/sys/class/pwm/... (sysfs interface)" >>>> + depends on SYSFS >>>> + help >>>> +Say Y here to provide a sysfs interface to control PWMs. >>>> + >>>> +For every instance of a PWM device there is a pwmchipN directory >>>> +created in /sys/class/pwm. Use the export attribute to request >>>> +a PWM to be accessible from userspace and the unexport attribute >>>> +to return the PWM to the kernel. Each exported PWM will have a >>>> +pwmX directory in the pwmchipN it is associated with. >>> >>> I have a small quibble with this. Introducing options like this make it >>> increasingly difficult to compile-test all the various combinations, so >>> I'd like to see this converted to a form that will play well with the >>> IS_ENABLED() macro. We already have the same issue with DEBUG_FS, only >>> to a lesser degree because it doesn't have an additional PWM-specific >>> Kconfig option. > > How about removing the Kconfig option and just doing: > > obj-$(CONFIG_SYSFS) += sysfs.o > > This way the PWM sysfs interface is always compiled and included in the build > as long as CONFIG_SYSFS is enabled. The check in the header would change to That didn't work. As Ryan pointed out we get undefined references due to sysfs.c being compiled but not core.c when CONFIG_PWM is not enabled. I'll change the PWM_SYSFS to a hidden option and repost the patch to see if that is acceptable. Like Ryan mentioned, most test configs have CONFIG_SYSFS enabled so as long as CONFIG_PWM is enabled we also get the sysfs interface. Regards, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH v4] pwm: add sysfs interface
On Tuesday, June 11, 2013 4:29 AM, Ryan Mallon wrote: > On 11/06/13 20:14, Thierry Reding wrote: >> On Mon, Jun 10, 2013 at 04:12:07PM -0700, H Hartley Sweeten wrote: >> [...] >>> +What: /sys/class/pwm/pwmchipN/pwmX/duty >>> +Date: May 2013 >>> +KernelVersion: 3.11 >>> +Contact: H Hartley Sweeten >>> +Description: >>> + Sets the PWM duty cycle in nanoseconds. >> >> Sorry, I should've been more specific before. I'd like this to be named >> duty_cycle. We now have the pwm_{set,get}_duty_cycle() accessors and I'd >> like to eventually use the spelled-out form consistently. Ok. I'll change this. >>> +config PWM_SYSFS >>> + bool "/sys/class/pwm/... (sysfs interface)" >>> + depends on SYSFS >>> + help >>> + Say Y here to provide a sysfs interface to control PWMs. >>> + >>> + For every instance of a PWM device there is a pwmchipN directory >>> + created in /sys/class/pwm. Use the export attribute to request >>> + a PWM to be accessible from userspace and the unexport attribute >>> + to return the PWM to the kernel. Each exported PWM will have a >>> + pwmX directory in the pwmchipN it is associated with. >> >> I have a small quibble with this. Introducing options like this make it >> increasingly difficult to compile-test all the various combinations, so >> I'd like to see this converted to a form that will play well with the >> IS_ENABLED() macro. We already have the same issue with DEBUG_FS, only >> to a lesser degree because it doesn't have an additional PWM-specific >> Kconfig option. >> >> In order not to burden you with too much work, one option for now would >> be to unconditionally build the sysfs.c file and use something along >> these lines in pwmchip_sysfs_{,un}export(): >> >> if (!IS_ENABLED(CONFIG_PWM_SYSFS)) >> return; >> >> Which should allow the compiler to throw away all PWM_SYSFS-related >> code in that file, leaving an empty function. > > > Won't that also cause the compiler to spew a bunch of warnings about > unreachable code in the !CONFIG_PWM_SYSFS case? We have the > unreachable() macro, but that isn't supported nicely by all compilers. > > If CONFIG_SYSFS is not enabled and sysfs.c is using functions that now > do not exist, that will cause compile errors, since the compiler will > still attempt to compile all of the code, even though it will remove > most of it after doing so. > > Also, any functions that are extern will also end up generating empty > functions in the kernel binary (static linkage functions should > disappear completely). This is obviously very negligible in size, > but using a proper Kconfig option results in zero size if the option > is compiled out. > >> It's not the optimal >> solution, which would require the sysfs code to go into core.c and be >> conditionalized there, but it's good enough. I can always go and clean >> up that code later (maybe doing the same for DEBUG_FS while at it). >> >> The big advantage of this is that we get full compile coverage of the >> sysfs interface, whether it's enabled or not. Calling an empty function >> once when the chip is registered is an acceptable overhead. > > Why not just make CONFIG_PWM_SYSFS default y, so that if CONFIG_SYSFS is > enabled (which should be true for the vast majority of test configs) that > pwm sysfs is also enabled? > > The IS_ENABLED method just seems very messy for a very small gain. How about removing the Kconfig option and just doing: obj-$(CONFIG_SYSFS) += sysfs.o This way the PWM sysfs interface is always compiled and included in the build as long as CONFIG_SYSFS is enabled. The check in the header would change to #ifdef CONFIG_SYSFS void pwmchip_sysfs_export(struct pwm_chip *chip); void pwmchip_sysfs_unexport(struct pwm_chip *chip); #else static inline void pwmchip_sysfs_export(struct pwm_chip *chip) { } static inline void pwmchip_sysfs_unexport(struct pwm_chip *chip) { } #endif /* CONFIG_SYSFS */ So, no IS_ENABLED or #ifdef'ery in the source file. I'll make the change and post a v5 shortly. Regards, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4] pwm: add sysfs interface
Add a simple sysfs interface to the generic PWM framework. /sys/class/pwm/ `-- pwmchipN/ for each PWM chip |-- export (w/o) ask the kernel to export a PWM channel |-- npwm (r/o) number of PWM channels in this PWM chip |-- pwmX/ for each exported PWM channel | |-- duty (r/w) duty cycle (in nanoseconds) | |-- enable (r/w) enable/disable PWM | |-- period (r/w) period (in nanoseconds) | `-- polarity (r/w) polarity of PWM (normal/inversed) `-- unexport (w/o) return a PWM channel to the kernel Signed-off-by: H Hartley Sweeten Cc: Thierry Reding Cc: Lars Poeschel Cc: Ryan Mallon Cc: Rob Landley --- v4: * address a number of issues pointed out by Thierry Reding - fix some typos and wording issues in the Documentation - rename the new source file to sysfs.c - rename some of the variables in sysfs.c to clarify them - fix the period store so it does not change the duty cycle - change the polarity attribute to use a string representation - add a warning message is the pwmchip_sysfs_export() fails v3: * fix an issue with the export/unexport of the PWM chip v2: * add API documentation and update Documentation/pwm.txt * fix some issues pointed out by Ryan Mallon * add the pwm attributes to dev.groups so they are created when the device is registered for the exported PWM v1: * Based on previous work by Lars Poecshel Documentation/ABI/testing/sysfs-class-pwm | 78 +++ Documentation/pwm.txt | 36 +++ drivers/pwm/Kconfig | 12 + drivers/pwm/Makefile | 1 + drivers/pwm/core.c| 25 ++- drivers/pwm/sysfs.c | 351 ++ include/linux/pwm.h | 29 ++- 7 files changed, 529 insertions(+), 3 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-pwm create mode 100644 drivers/pwm/sysfs.c diff --git a/Documentation/ABI/testing/sysfs-class-pwm b/Documentation/ABI/testing/sysfs-class-pwm new file mode 100644 index 000..cb3d034 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-pwm @@ -0,0 +1,78 @@ +What: /sys/class/pwm/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + The pwm/ class sub-directory belongs to the Generic PWM + Framework and provides a sysfs interface for using PWM + channels. + +What: /sys/class/pwm/pwmchipN/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + A /sys/class/pwm/pwmchipN directory is created for each + probed PWM controller/chip where N is the base of the + PWM chip. + +What: /sys/class/pwm/pwmchipN/npwm +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + The number of PWM channels supported by the PWM chip. + +What: /sys/class/pwm/pwmchipN/export +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Exports a PWM channel from the PWM chip for sysfs control. + Value is between 0 and /sys/class/pwm/pwmchipN/npwm - 1. + +What: /sys/class/pwm/pwmchipN/unexport +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Unexports a PWM channel. + +What: /sys/class/pwm/pwmchipN/pwmX +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + A /sys/class/pwm/pwmchipN/pwmX directory is created for + each exported PWM channel where X is the exported PWM + channel number. + +What: /sys/class/pwm/pwmchipN/pwmX/period +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the PWM period in nanoseconds. + +What: /sys/class/pwm/pwmchipN/pwmX/duty +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the PWM duty cycle in nanoseconds. + +What: /sys/class/pwm/pwmchipN/pwmX/polarity +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the output polarity of the PWM to "normal" or "inversed". + +What: /sys/class/pwm/pwmchipN/pwmX/enable +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Enables/disables the PWM. + 0 is disabled + 1 is enabled diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt index 7d2b4c9..95589b1 100644 --- a/Documentation/pwm.txt +++ b/Documentation/pwm.txt @@ -45,6 +45,42 @@ int pwm_config(struct pwm_device *pwm, int dut
RE: [PATCH v3] pwm: add sysfs interface
On Monday, June 10, 2013 12:00 PM, Thierry Reding wrote: > On Thu, May 30, 2013 at 02:30:39PM -0700, H Hartley Sweeten wrote: >> Add a simple sysfs interface to the generic PWM framework. > > Sorry for taking so long to review this. Not a problem. Thanks for the review. >> /sys/class/pwm/ >> `-- pwmchipN/ for each PWM chip >> |-- export (w/o) ask the kernel to export a PWM channel >> |-- npwn (r/o) number of PWM channels in this PWM chip > > "npwm"? Fat-fingered that. Fixed. >> |-- pwmX/ for each exported PWM channel >> | |-- duty_ns(r/w) duty cycle (in nanoseconds) >> | |-- enable (r/w) enable/disable PWM >> | |-- period_ns (r/w) period (in nanoseconds) > > I'm not sure if we need the _ns suffix. If the documentation already > specifies that it should be in nanoseconds, shouldn't that be enough? In the earlier review of Lars Poeschel's patch I think you said you wanted the attributes to match the variable names. But, "duty' and "period" are probably close enough. Fixed. >> diff --git a/Documentation/ABI/testing/sysfs-class-pwm >> b/Documentation/ABI/testing/sysfs-class-pwm > [...] >> +What: /sys/class/pwm/pwmchipN/pwmX/polarity >> +Date: May 2013 >> +KernelVersion: 3.11 >> +Contact:H Hartley Sweeten >> +Description: >> +Sets the output polarity of the PWM. >> +0 is normal polarity >> +1 is inversed polarity > >I think this was discussed before, and I think it makes sense to use the >string representation here. polarity = 0 or polarity = 1 aren't very >intuitive notations in my opinion. You did mention that before. I overlooked it. I'll change this. >> diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt > [...] >> +The PWM channels are PWM chip specific from 0 to npwn-1. > >"npwm-1". "channels are PWM chip specific" sounds a bit confusing. Maybe >something like "The PWM channels are numbered using a per-chip index >from 0 to npwm-1." is more precise? Ok. >> +When a PWM channel is exported a pwmX directory will be created in the >> +pwmchipN directory it is associated with, where X is the channel number >> +that was exported. > >"..., where X is the number of the channel that was exported."? Ok. >> The following properties will then be available: >> + >> +period_ns - The total period of the PWM (read/write). > > "PWM signal"? OK. >> +Value is in nanoseconds and is the sum of the active and inactive >> +time of the PWM. If duty_ns is zero when this property is written >> +it will be automatically set to half the period_ns. > > I'm not sure that's the best approach. How about deferring the PWM > configuration until both values have been set? Or only configure the PWM > channel when it has been enabled, and refuse to enable unless both the > period and the duty cycle have been set? See below. >> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile >> index 94ba21e..fb92e1d 100644 >> --- a/drivers/pwm/Makefile >> +++ b/drivers/pwm/Makefile >> @@ -1,4 +1,5 @@ >> obj-$(CONFIG_PWM) += core.o >> +obj-$(CONFIG_PWM_SYSFS) += pwm-sysfs.o > > I'd prefer this to simple be named sysfs.[co] in order to differentiate > it from drivers and make it consistent with the naming of core.[co]. Ok. >> diff --git a/drivers/pwm/pwm-sysfs.c b/drivers/pwm/pwm-sysfs.c > [...] >> +static struct pwm_device *dev_to_pwm_device(struct device *dev) >> +{ >> +struct pwm_export *pwm_export = dev_to_pwm_export(dev); > > Maybe drop the pwm_ prefix on the variable name? Ok. >> +static ssize_t pwm_period_ns_store(struct device *dev, >> + struct device_attribute *attr, >> + const char *buf, size_t size) >> +{ >> +struct pwm_device *pwm = dev_to_pwm_device(dev); >> +unsigned int duty = pwm->duty; >> +unsigned int val; >> +int ret; >> + >> +ret = kstrtouint(buf, 0, &val); >> +if (ret) >> +return ret; >> + >> +/* if not set, default to 50% duty cycle */ >> +if (duty == 0) >> +duty = val / 2; > > How does this differentiate between the case where the user explicitly > sets the duty cycle to 0 to "disable" the PWM? It doesn't. Actually, looking at pwm_config() a duty_ns value of 0 is allowed so this check is not necess
RE: [PATCH v3] pwm: add sysfs interface
Ping? -Original Message- From: H Hartley Sweeten Sent: Thursday, May 30, 2013 2:31 PM To: Linux Kernel Cc: linux-...@vger.kernel.org; linux-...@vger.kernel.org; thierry.red...@gmail.com; poesc...@lemonage.de; Ryan Mallon; r...@landley.net; H Hartley Sweeten Subject: [PATCH v3] pwm: add sysfs interface Add a simple sysfs interface to the generic PWM framework. /sys/class/pwm/ `-- pwmchipN/ for each PWM chip |-- export (w/o) ask the kernel to export a PWM channel |-- npwn (r/o) number of PWM channels in this PWM chip |-- pwmX/ for each exported PWM channel | |-- duty_ns(r/w) duty cycle (in nanoseconds) | |-- enable (r/w) enable/disable PWM | |-- period_ns (r/w) period (in nanoseconds) | `-- polarity (r/w) polarity of PWM `-- unexport (w/o) return a PWM channel to the kernel Signed-off-by: H Hartley Sweeten Cc: Thierry Reding Cc: Lars Poeschel Cc: Ryan Mallon Cc: Rob Landley --- v3: * fix an issue with the export/unexport of the PWM chip v2: * add API documentation and update Documentation/pwm.txt * fix some issues pointed out by Ryan Mallon * add the pwm attributes to dev.groups so they are created when the device is registered for the exported PWM v1: * Based on previous work by Lars Poecshel Documentation/ABI/testing/sysfs-class-pwm | 80 +++ Documentation/pwm.txt | 39 drivers/pwm/Kconfig | 12 + drivers/pwm/Makefile | 1 + drivers/pwm/core.c| 25 ++- drivers/pwm/pwm-sysfs.c | 358 ++ include/linux/pwm.h | 28 +++ 7 files changed, 541 insertions(+), 2 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-pwm create mode 100644 drivers/pwm/pwm-sysfs.c diff --git a/Documentation/ABI/testing/sysfs-class-pwm b/Documentation/ABI/testing/sysfs-class-pwm new file mode 100644 index 000..eaa4e1f --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-pwm @@ -0,0 +1,80 @@ +What: /sys/class/pwm/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + The pwm/ class sub-directory belongs to the Generic PWM + Framework and provides a sysfs interface for using PWM + channels. + +What: /sys/class/pwm/pwmchipN/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + A /sys/class/pwm/pwmchipN directory is created for each + probed PWM controller/chip where N is the base of the + PWM chip. + +What: /sys/class/pwm/pwmchipN/npwm +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + The number of PWM channels supported by the PWM chip. + +What: /sys/class/pwm/pwmchipN/export +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Exports a PWM channel from the PWM chip for sysfs control. + Value is between 0 and /sys/class/pwm/pwmchipN/npwm - 1. + +What: /sys/class/pwm/pwmchipN/unexport +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Unexports a PWM channel. + +What: /sys/class/pwm/pwmchipN/pwmX +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + A /sys/class/pwm/pwmchipN/pwmX directory is created for + each exported PWM channel where X is the PWM channel number. + +What: /sys/class/pwm/pwmchipN/pwmX/period_ns +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the PWM period in nanoseconds. + +What: /sys/class/pwm/pwmchipN/pwmX/duty_ns +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the PWM duty cycle in nanoseconds, default is half the + /sys/class/pwm/pwmchipN/pwmX/period_ns. + +What: /sys/class/pwm/pwmchipN/pwmX/polarity +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the output polarity of the PWM. + 0 is normal polarity + 1 is inversed polarity + +What: /sys/class/pwm/pwmchipN/pwmX/enable +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Enables/disables the PWM. + 0 is disabled + 1 is enabled diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt index 7d2b4c9..b58526d 100644 --- a/Documentation/pwm.txt +++ b/Documentation/pwm.txt @@ -45,6 +45,45 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns); To start/stop toggling
[PATCH v3] pwm: add sysfs interface
Add a simple sysfs interface to the generic PWM framework. /sys/class/pwm/ `-- pwmchipN/ for each PWM chip |-- export (w/o) ask the kernel to export a PWM channel |-- npwn (r/o) number of PWM channels in this PWM chip |-- pwmX/ for each exported PWM channel | |-- duty_ns(r/w) duty cycle (in nanoseconds) | |-- enable (r/w) enable/disable PWM | |-- period_ns (r/w) period (in nanoseconds) | `-- polarity (r/w) polarity of PWM `-- unexport (w/o) return a PWM channel to the kernel Signed-off-by: H Hartley Sweeten Cc: Thierry Reding Cc: Lars Poeschel Cc: Ryan Mallon Cc: Rob Landley --- v3: * fix an issue with the export/unexport of the PWM chip v2: * add API documentation and update Documentation/pwm.txt * fix some issues pointed out by Ryan Mallon * add the pwm attributes to dev.groups so they are created when the device is registered for the exported PWM v1: * Based on previous work by Lars Poecshel Documentation/ABI/testing/sysfs-class-pwm | 80 +++ Documentation/pwm.txt | 39 drivers/pwm/Kconfig | 12 + drivers/pwm/Makefile | 1 + drivers/pwm/core.c| 25 ++- drivers/pwm/pwm-sysfs.c | 358 ++ include/linux/pwm.h | 28 +++ 7 files changed, 541 insertions(+), 2 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-pwm create mode 100644 drivers/pwm/pwm-sysfs.c diff --git a/Documentation/ABI/testing/sysfs-class-pwm b/Documentation/ABI/testing/sysfs-class-pwm new file mode 100644 index 000..eaa4e1f --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-pwm @@ -0,0 +1,80 @@ +What: /sys/class/pwm/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + The pwm/ class sub-directory belongs to the Generic PWM + Framework and provides a sysfs interface for using PWM + channels. + +What: /sys/class/pwm/pwmchipN/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + A /sys/class/pwm/pwmchipN directory is created for each + probed PWM controller/chip where N is the base of the + PWM chip. + +What: /sys/class/pwm/pwmchipN/npwm +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + The number of PWM channels supported by the PWM chip. + +What: /sys/class/pwm/pwmchipN/export +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Exports a PWM channel from the PWM chip for sysfs control. + Value is between 0 and /sys/class/pwm/pwmchipN/npwm - 1. + +What: /sys/class/pwm/pwmchipN/unexport +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Unexports a PWM channel. + +What: /sys/class/pwm/pwmchipN/pwmX +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + A /sys/class/pwm/pwmchipN/pwmX directory is created for + each exported PWM channel where X is the PWM channel number. + +What: /sys/class/pwm/pwmchipN/pwmX/period_ns +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the PWM period in nanoseconds. + +What: /sys/class/pwm/pwmchipN/pwmX/duty_ns +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the PWM duty cycle in nanoseconds, default is half the + /sys/class/pwm/pwmchipN/pwmX/period_ns. + +What: /sys/class/pwm/pwmchipN/pwmX/polarity +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the output polarity of the PWM. + 0 is normal polarity + 1 is inversed polarity + +What: /sys/class/pwm/pwmchipN/pwmX/enable +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Enables/disables the PWM. + 0 is disabled + 1 is enabled diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt index 7d2b4c9..b58526d 100644 --- a/Documentation/pwm.txt +++ b/Documentation/pwm.txt @@ -45,6 +45,45 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns); To start/stop toggling the PWM output use pwm_enable()/pwm_disable(). +Using PWMs with the sysfs interface +--- + +You have to enable CONFIG_PWM_SYSFS in your kernel configuration to use +the sysfs interface. It is exposed at /sys/class/pwm/. Each probed PWM +controller/chip will be exported as pwmchipN
RE: [PATCH v2] pwm: add sysfs interface
On Thursday, May 30, 2013 12:30 PM, H Hartley Sweeten wrote: > Add a simple sysfs interface to the generic PWM framework. > > /sys/class/pwm/ > `-- pwmchipN/ for each PWM chip > |-- export (w/o) ask the kernel to export a PWM channel > |-- npwn (r/o) number of PWM channels in this PWM chip > |-- pwmX/ for each exported PWM channel (per PWM chip) > | |-- duty_ns(r/w) duty cycle (in nanoseconds) > | |-- enable (r/w) enable/disable PWM > | |-- period_ns (r/w) period (in nanoseconds) > | `-- polarity (r/w) polarity of PWM > `-- unexport (w/o) return a PWM channel to the kernel > > Signed-off-by: H Hartley Sweeten > Cc: Thierry Reding > Cc: Lars Poeschel > Cc: Ryan Mallon > Cc: Rob Landley > --- > v2: * add API documentation and update Documentation/pwm.txt > * fix some issues pointed out by Ryan Mallon > * add the pwm attributes to dev.groups so they are created > when the device is registered for the exported PWM. > > Documentation/ABI/testing/sysfs-class-pwm | 80 +++ > Documentation/pwm.txt | 39 > drivers/pwm/Kconfig | 12 + > drivers/pwm/Makefile | 1 + > drivers/pwm/core.c| 25 ++- > drivers/pwm/pwm-sysfs.c | 350 > ++ > include/linux/pwm.h | 28 +++ > 7 files changed, 533 insertions(+), 2 deletions(-) > create mode 100644 Documentation/ABI/testing/sysfs-class-pwm > create mode 100644 drivers/pwm/pwm-sysfs.c > diff --git a/drivers/pwm/pwm-sysfs.c b/drivers/pwm/pwm-sysfs.c > +void pwmchip_sysfs_export(struct pwm_chip *chip) > +{ > + /* > + * If device_create() fails the pwm_chip is still usable by > + * the kernel its just not exported. > + */ > + chip->dev = device_create(&pwm_class, chip->dev, MKDEV(0, 0), chip, > + "pwmchip%d", chip->base); > +} I just realized this will not work. chip->dev is initialized by the PWM driver before calling pwmchip_add(). I'll post a v3 shortly. Regards, Hartley N�r��yb�X��ǧv�^�){.n�+{zX����ܨ}���Ơz�&j:+v���zZ+��+zf���h���~i���z��w���?�&�)ߢf��^jǫy�m��@A�a��� 0��h���i
[PATCH v2] pwm: add sysfs interface
Add a simple sysfs interface to the generic PWM framework. /sys/class/pwm/ `-- pwmchipN/ for each PWM chip |-- export (w/o) ask the kernel to export a PWM channel |-- npwn (r/o) number of PWM channels in this PWM chip |-- pwmX/ for each exported PWM channel (per PWM chip) | |-- duty_ns(r/w) duty cycle (in nanoseconds) | |-- enable (r/w) enable/disable PWM | |-- period_ns (r/w) period (in nanoseconds) | `-- polarity (r/w) polarity of PWM `-- unexport (w/o) return a PWM channel to the kernel Signed-off-by: H Hartley Sweeten Cc: Thierry Reding Cc: Lars Poeschel Cc: Ryan Mallon Cc: Rob Landley --- v2: * add API documentation and update Documentation/pwm.txt * fix some issues pointed out by Ryan Mallon * add the pwm attributes to dev.groups so they are created when the device is registered for the exported PWM. Documentation/ABI/testing/sysfs-class-pwm | 80 +++ Documentation/pwm.txt | 39 drivers/pwm/Kconfig | 12 + drivers/pwm/Makefile | 1 + drivers/pwm/core.c| 25 ++- drivers/pwm/pwm-sysfs.c | 350 ++ include/linux/pwm.h | 28 +++ 7 files changed, 533 insertions(+), 2 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-pwm create mode 100644 drivers/pwm/pwm-sysfs.c diff --git a/Documentation/ABI/testing/sysfs-class-pwm b/Documentation/ABI/testing/sysfs-class-pwm new file mode 100644 index 000..eaa4e1f --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-pwm @@ -0,0 +1,80 @@ +What: /sys/class/pwm/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + The pwm/ class sub-directory belongs to the Generic PWM + Framework and provides a sysfs interface for using PWM + channels. + +What: /sys/class/pwm/pwmchipN/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + A /sys/class/pwm/pwmchipN directory is created for each + probed PWM controller/chip where N is the base of the + PWM chip. + +What: /sys/class/pwm/pwmchipN/npwm +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + The number of PWM channels supported by the PWM chip. + +What: /sys/class/pwm/pwmchipN/export +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Exports a PWM channel from the PWM chip for sysfs control. + Value is between 0 and /sys/class/pwm/pwmchipN/npwm - 1. + +What: /sys/class/pwm/pwmchipN/unexport +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Unexports a PWM channel. + +What: /sys/class/pwm/pwmchipN/pwmX +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + A /sys/class/pwm/pwmchipN/pwmX directory is created for + each exported PWM channel where X is the PWM channel number. + +What: /sys/class/pwm/pwmchipN/pwmX/period_ns +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the PWM period in nanoseconds. + +What: /sys/class/pwm/pwmchipN/pwmX/duty_ns +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the PWM duty cycle in nanoseconds, default is half the + /sys/class/pwm/pwmchipN/pwmX/period_ns. + +What: /sys/class/pwm/pwmchipN/pwmX/polarity +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the output polarity of the PWM. + 0 is normal polarity + 1 is inversed polarity + +What: /sys/class/pwm/pwmchipN/pwmX/enable +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Enables/disables the PWM. + 0 is disabled + 1 is enabled diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt index 7d2b4c9..b58526d 100644 --- a/Documentation/pwm.txt +++ b/Documentation/pwm.txt @@ -45,6 +45,45 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns); To start/stop toggling the PWM output use pwm_enable()/pwm_disable(). +Using PWMs with the sysfs interface +--- + +You have to enable CONFIG_PWM_SYSFS in your kernel configuration to use +the sysfs interface. It is exposed at /sys/class/pwm/. Each probed PWM +controller/chip will be exported as pwmchipN, where N is the base of the +PWM chip. Inside the directory you will find: + +npwm - The
RE: [PATCH] pwm: add sysfs interface
On Wednesday, May 29, 2013 7:02 PM, Ryan Mallon wrote: > On 30/05/13 07:08, H Hartley Sweeten wrote: >> Add a simple sysfs interface to the PWM framework. >> >> /sys/class/pwm/ >> `-- pwmchipN/ for each PWM chip >> |-- export (w/o) ask the kernel to export a PWM to userspace >> |-- npwm (r/o) number of PWM in pwmchipN >> |-- pwmN/ for each exported PWM >> | |-- duty_ns(r/w) duty cycle (in nanoseconds) >> | |-- enable (r/w) enable/disable PWM >> | |-- period_ns (r/w) period (in nanoseconds) >> | `-- polarity (r/w) polarity of PWM >> `-- unexport (w/o) return a PWM to the kernel >> >> Signed-off-by: H Hartley Sweeten >> Cc: Thierry Reding >> Cc: Lars Poeschel >> --- >> This is based on previous work by Lars Poeshel. > > Some comments below. > > You will also fail to get this past Greg KH unless you add documentation > for the new sysfs interface to Documentation/ABI/stable/. I'm working on the documentation now. I wanted to get the implementation out for review. >> >> drivers/pwm/Kconfig | 6 + >> drivers/pwm/Makefile| 1 + >> drivers/pwm/core.c | 25 +++- >> drivers/pwm/pwm-sysfs.c | 357 >> >> include/linux/pwm.h | 28 >> 5 files changed, 415 insertions(+), 2 deletions(-) >> create mode 100644 drivers/pwm/pwm-sysfs.c >> >> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig >> index 115b644..61a53b5 100644 >> --- a/drivers/pwm/Kconfig >> +++ b/drivers/pwm/Kconfig >> @@ -28,6 +28,12 @@ menuconfig PWM >> >> if PWM >> >> +config PWM_SYSFS >> +bool "/sys/class/pwm/... (sysfs interface)" >> +depends on SYSFS >> +help >> + Say Y here to provide a sysfs interface to control PWMs. >> + >> config PWM_AB8500 >> tristate "AB8500 PWM support" >> depends on AB8500_CORE && ARCH_U8500 >> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile >> index 94ba21e..fb92e1d 100644 >> --- a/drivers/pwm/Makefile >> +++ b/drivers/pwm/Makefile >> @@ -1,4 +1,5 @@ >> obj-$(CONFIG_PWM) += core.o >> +obj-$(CONFIG_PWM_SYSFS) += pwm-sysfs.o >> obj-$(CONFIG_PWM_AB8500)+= pwm-ab8500.o >> obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o >> obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o >> diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c >> index 32221cb..f67465c 100644 >> --- a/drivers/pwm/core.c >> +++ b/drivers/pwm/core.c >> @@ -274,6 +274,8 @@ int pwmchip_add(struct pwm_chip *chip) >> if (IS_ENABLED(CONFIG_OF)) >> of_pwmchip_add(chip); >> >> +pwmchip_sysfs_export(chip); >> + >> out: >> mutex_unlock(&pwm_lock); >> return ret; >> @@ -310,6 +312,8 @@ int pwmchip_remove(struct pwm_chip *chip) >> >> free_pwms(chip); >> >> +pwmchip_sysfs_unexport(chip); >> + >> out: >> mutex_unlock(&pwm_lock); >> return ret; >> @@ -402,10 +406,19 @@ EXPORT_SYMBOL_GPL(pwm_free); >> */ >> int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) >> { >> +int err; >> + >> if (!pwm || duty_ns < 0 || period_ns <= 0 || duty_ns > period_ns) >> return -EINVAL; >> >> -return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns); >> +err = pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns); >> +if (err) >> +return err; >> + >> +pwm->duty = duty_ns; >> +pwm->period = period_ns; >> + >> +return 0; >> } >> EXPORT_SYMBOL_GPL(pwm_config); >> >> @@ -418,6 +431,8 @@ EXPORT_SYMBOL_GPL(pwm_config); >> */ >> int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity) >> { >> +int err; >> + >> if (!pwm || !pwm->chip->ops) >> return -EINVAL; >> >> @@ -427,7 +442,13 @@ int pwm_set_polarity(struct pwm_device *pwm, enum >> pwm_polarity polarity) >> if (test_bit(PWMF_ENABLED, &pwm->flags)) >> return -EBUSY; >> >> -return pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity); >> +err = pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity); >> +if (err) >> +return err; >> + >> +
RE: [PATCH 00/14] misc/ep93xx_pwm: cleanup driver for conversion to PWM framework
On Tuesday, May 28, 2013 4:42 AM, Lars Poeschel wrote: > On Tuesday 28 May 2013 at 13:00:12, Thierry Reding wrote: >> I've added Lars Poeschel on Cc, who's done some work on a sysfs >> interface for the PWM subsystem already. It's undergone some review >> already[0] and I think he's working on a v2 now. >> >> Thierry >> >> [0]: http://marc.info/?l=linux-kernel&m=136499756101273&w=2 > > I currently do not have the time to work on a v2 of the pwm sysfs patch but > I will do it as soon as possible - if not someone else will do. > Unfortunately my current involvements in other project will not allow me to > do so for at least next two months. > I received some off-list reactions to my patches from users asking for pwm > sysfs, so there is definitely a need for it! > If you decide to take attempt 2) (which is preferable) I recommend you to > take a look at what I have done and Thierrys review comments. I took the > gpiolib way and the result got rejected for very good reasons. I just posted a PWM sysfs interface patch based on the previous work by Lars. Hopefully I addressed all of Thierrys review comments. I still need to add the Documentation and the ABI doc for the sysfs but I want to make sure the interface looks acceptable. I also spotted a couple checkpatch.pl issues after I posted the patch. These are already fixed for v2. Thanks, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] pwm: add sysfs interface
Add a simple sysfs interface to the PWM framework. /sys/class/pwm/ `-- pwmchipN/ for each PWM chip |-- export (w/o) ask the kernel to export a PWM to userspace |-- npwm (r/o) number of PWM in pwmchipN |-- pwmN/ for each exported PWM | |-- duty_ns(r/w) duty cycle (in nanoseconds) | |-- enable (r/w) enable/disable PWM | |-- period_ns (r/w) period (in nanoseconds) | `-- polarity (r/w) polarity of PWM `-- unexport (w/o) return a PWM to the kernel Signed-off-by: H Hartley Sweeten Cc: Thierry Reding Cc: Lars Poeschel --- This is based on previous work by Lars Poeshel. drivers/pwm/Kconfig | 6 + drivers/pwm/Makefile| 1 + drivers/pwm/core.c | 25 +++- drivers/pwm/pwm-sysfs.c | 357 include/linux/pwm.h | 28 5 files changed, 415 insertions(+), 2 deletions(-) create mode 100644 drivers/pwm/pwm-sysfs.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 115b644..61a53b5 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -28,6 +28,12 @@ menuconfig PWM if PWM +config PWM_SYSFS + bool "/sys/class/pwm/... (sysfs interface)" + depends on SYSFS + help + Say Y here to provide a sysfs interface to control PWMs. + config PWM_AB8500 tristate "AB8500 PWM support" depends on AB8500_CORE && ARCH_U8500 diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 94ba21e..fb92e1d 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_PWM) += core.o +obj-$(CONFIG_PWM_SYSFS)+= pwm-sysfs.o obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o obj-$(CONFIG_PWM_ATMEL_TCB)+= pwm-atmel-tcb.o obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 32221cb..f67465c 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -274,6 +274,8 @@ int pwmchip_add(struct pwm_chip *chip) if (IS_ENABLED(CONFIG_OF)) of_pwmchip_add(chip); + pwmchip_sysfs_export(chip); + out: mutex_unlock(&pwm_lock); return ret; @@ -310,6 +312,8 @@ int pwmchip_remove(struct pwm_chip *chip) free_pwms(chip); + pwmchip_sysfs_unexport(chip); + out: mutex_unlock(&pwm_lock); return ret; @@ -402,10 +406,19 @@ EXPORT_SYMBOL_GPL(pwm_free); */ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) { + int err; + if (!pwm || duty_ns < 0 || period_ns <= 0 || duty_ns > period_ns) return -EINVAL; - return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns); + err = pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns); + if (err) + return err; + + pwm->duty = duty_ns; + pwm->period = period_ns; + + return 0; } EXPORT_SYMBOL_GPL(pwm_config); @@ -418,6 +431,8 @@ EXPORT_SYMBOL_GPL(pwm_config); */ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity) { + int err; + if (!pwm || !pwm->chip->ops) return -EINVAL; @@ -427,7 +442,13 @@ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity) if (test_bit(PWMF_ENABLED, &pwm->flags)) return -EBUSY; - return pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity); + err = pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity); + if (err) + return err; + + pwm->polarity = polarity; + + return 0; } EXPORT_SYMBOL_GPL(pwm_set_polarity); diff --git a/drivers/pwm/pwm-sysfs.c b/drivers/pwm/pwm-sysfs.c new file mode 100644 index 000..6a2bf76 --- /dev/null +++ b/drivers/pwm/pwm-sysfs.c @@ -0,0 +1,357 @@ +/* + * A simple sysfs interface for the generic PWM framework + * + * Copyright (C) 2013 H Hartley Sweeten + * + * Based on previous work by Lars Poeschel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +struct pwm_export { + struct device dev; + struct pwm_device *pwm; +}; + +static struct pwm_export *dev_to_pwm_export(struct device *dev) +{ + return container_of(dev, struct pwm_export, dev); +} + +static struct pwm_device *dev_to_pwm_device(struct device *dev) +{ + struct pwm_exp
RE: [PATCH 00/14] misc/ep93xx_pwm: cleanup driver for conversion to PWM framework
On Monday, May 27, 2013 8:20 AM, Arnd Bergmann wrote: > On Saturday 25 May 2013, H Hartley Sweeten wrote: >> This driver needs to be converted to the new PWM framework. >> >> Before converting it clean up all the cruft, >> >> H Hartley Sweeten (14): >> misc/ep93xx_pwm: use managed device resources >> misc/ep93xx_pwm: use {read,write}* instead of __raw_* versions for io >> misc/ep93xx_pwm: remove ep93xx_pwm_{write,read}l() inline functions >> misc/ep93xx_pwm: remove ep93xx_pwm_write_tc() inline function >> misc/ep93xx_pwm: remove ep93xx_pwm_write_dc() inline function >> misc/ep93xx_pwm: remove ep93xx_pwm_enable() inline function >> misc/ep93xx_pwm: remove ep93xx_pwm_disable() inline function >> misc/ep93xx_pwm: remove ep93xx_pwm_invert() inline function >> misc/ep93xx_pwm: remove ep93xx_pwm_normal() inline function >> misc/ep93xx_pwm: remove ep93xx_pwm_read_tc() inline function >> misc/ep93xx_pwm: remove ep93xx_pwm_is_enabled() inline function >> misc/ep93xx_pwm: remove ep93xx_pwm_is_inverted() inline function >> misc/ep93xx_pwm: use module_platform_driver() >> misc/ep93xx_pwm: use kstrtol instead of strict_strtol > > Whole series: > > Acked-by: Arnd Bergmann a...@arndb.de Arnd, Ryan Mallon has also provided a Reviewed-by for this series. Will you be the one that merges this? I would like it to be in linux-next before I convert it to the PWM framework. Also, I have a question about the conversion. If I strip the sysfs support out of this driver the conversion is quite simple. But, my use for this driver requires user space control of the PWM. Should I: 1) convert the driver to the PWM framework and leave the sysfs stuff in it 2) work out a generic sysfs support for the PWM framework and then convert the driver 3) other... I've been looking at 2) by doing something like how gpiolib does it. Do you think that would be acceptable? Thanks, Hartley-- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH 02/14] misc/ep93xx_pwm: use {read,write}* instead of __raw_* versions for io
On Monday, May 27, 2013 8:18 AM, Arnd Bergmann wrote: > On Saturday 25 May 2013, H Hartley Sweeten wrote: >> @@ -42,13 +42,13 @@ struct ep93xx_pwm { >> static inline void ep93xx_pwm_writel(struct ep93xx_pwm *pwm, >> unsigned int val, unsigned int off) >> { >> - __raw_writel(val, pwm->mmio_base + off); >> + writel(val, pwm->mmio_base + off); >> } > > Just an idea: since you are adding the writel in a lot of places in subsequent > patches, you could rename 'mmio_base' to the shorter 'base' first, which would > make the resulting code actually smaller. Hmm.. It would make the source file a bit smaller but the compiled size would be the same. But, I'll probably rename the variable when I convert this driver to the PWM framework. Thanks, Hartley-- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 13/14] misc/ep93xx_pwm: use module_platform_driver()
Add the (*probe) function to the platform_driver and use the module_platform_driver() macro to initialize the module. Remove the unnecessary __init and __exit tags. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index dd570d1..b5ad0c6 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -215,7 +215,7 @@ static const struct attribute_group ep93xx_pwm_sysfs_files = { .attrs = ep93xx_pwm_attrs, }; -static int __init ep93xx_pwm_probe(struct platform_device *pdev) +static int ep93xx_pwm_probe(struct platform_device *pdev) { struct ep93xx_pwm *pwm; struct resource *res; @@ -257,7 +257,7 @@ static int __init ep93xx_pwm_probe(struct platform_device *pdev) return 0; } -static int __exit ep93xx_pwm_remove(struct platform_device *pdev) +static int ep93xx_pwm_remove(struct platform_device *pdev) { struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); @@ -274,10 +274,10 @@ static struct platform_driver ep93xx_pwm_driver = { .name = "ep93xx-pwm", .owner = THIS_MODULE, }, - .remove = __exit_p(ep93xx_pwm_remove), + .probe = ep93xx_pwm_probe, + .remove = ep93xx_pwm_remove, }; - -module_platform_driver_probe(ep93xx_pwm_driver, ep93xx_pwm_probe); +module_platform_driver(ep93xx_pwm_driver); MODULE_AUTHOR("Matthieu Crapet , " "H Hartley Sweeten "); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 09/14] misc/ep93xx_pwm: remove ep93xx_pwm_normal() inline function
This is a simple wrapper around writel(), remove it. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 7 +-- 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index 5193faf..cdc2ffc 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -49,11 +49,6 @@ static inline int ep93xx_pwm_is_enabled(struct ep93xx_pwm *pwm) return readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1; } -static inline void ep93xx_pwm_normal(struct ep93xx_pwm *pwm) -{ - writel(0x0, pwm->mmio_base + EP93XX_PWMx_INVERT); -} - static inline int ep93xx_pwm_is_inverted(struct ep93xx_pwm *pwm) { return readl(pwm->mmio_base + EP93XX_PWMx_INVERT) & 0x1; @@ -203,7 +198,7 @@ static ssize_t ep93xx_pwm_set_invert(struct device *dev, return -EINVAL; if (val == 0) - ep93xx_pwm_normal(pwm); + writel(0x0, pwm->mmio_base + EP93XX_PWMx_INVERT); else if (val == 1) writel(0x1, pwm->mmio_base + EP93XX_PWMx_INVERT); else -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 14/14] misc/ep93xx_pwm: use kstrtol instead of strict_strtol
strict_strtol is deprecated in favor of kstrtol. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index b5ad0c6..cdb67a9 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -92,7 +92,7 @@ static ssize_t ep93xx_pwm_set_freq(struct device *dev, long val; int err; - err = strict_strtol(buf, 10, &val); + err = kstrtol(buf, 10, &val); if (err) return -EINVAL; @@ -145,7 +145,7 @@ static ssize_t ep93xx_pwm_set_duty_percent(struct device *dev, long val; int err; - err = strict_strtol(buf, 10, &val); + err = kstrtol(buf, 10, &val); if (err) return -EINVAL; @@ -179,7 +179,7 @@ static ssize_t ep93xx_pwm_set_invert(struct device *dev, long val; int err; - err = strict_strtol(buf, 10, &val); + err = kstrtol(buf, 10, &val); if (err) return -EINVAL; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 12/14] misc/ep93xx_pwm: remove ep93xx_pwm_is_inverted() inline function
This is a simple wrapper around readl(), remove it. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 8 ++-- 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index 3dd2006..dd570d1 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -39,11 +39,6 @@ struct ep93xx_pwm { u32 duty_percent; }; -static inline int ep93xx_pwm_is_inverted(struct ep93xx_pwm *pwm) -{ - return readl(pwm->mmio_base + EP93XX_PWMx_INVERT) & 0x1; -} - /* * /sys/devices/platform/ep93xx-pwm.N * /min_freq read-only minimum pwm output frequency @@ -171,8 +166,9 @@ static ssize_t ep93xx_pwm_get_invert(struct device *dev, { struct platform_device *pdev = to_platform_device(dev); struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); + int inverted = readl(pwm->mmio_base + EP93XX_PWMx_INVERT) & 0x1; - return sprintf(buf, "%d\n", ep93xx_pwm_is_inverted(pwm)); + return sprintf(buf, "%d\n", inverted); } static ssize_t ep93xx_pwm_set_invert(struct device *dev, -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 10/14] misc/ep93xx_pwm: remove ep93xx_pwm_read_tc() inline function
This is a simple wrapper around readl(), remove it. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 11 +++ 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index cdc2ffc..6f48375 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -39,11 +39,6 @@ struct ep93xx_pwm { u32 duty_percent; }; -static inline u16 ep93xx_pwm_read_tc(struct ep93xx_pwm *pwm) -{ - return readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); -} - static inline int ep93xx_pwm_is_enabled(struct ep93xx_pwm *pwm) { return readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1; @@ -91,7 +86,7 @@ static ssize_t ep93xx_pwm_get_freq(struct device *dev, if (ep93xx_pwm_is_enabled(pwm)) { unsigned long rate = clk_get_rate(pwm->clk); - u16 term = ep93xx_pwm_read_tc(pwm); + u16 term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); return sprintf(buf, "%ld\n", rate / (term + 1)); } else { @@ -122,7 +117,7 @@ static ssize_t ep93xx_pwm_set_freq(struct device *dev, if (val < 1) val = 1; - term = ep93xx_pwm_read_tc(pwm); + term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); duty = ((val + 1) * pwm->duty_percent / 100) - 1; /* If pwm is running, order is important */ @@ -165,7 +160,7 @@ static ssize_t ep93xx_pwm_set_duty_percent(struct device *dev, return -EINVAL; if (val > 0 && val < 100) { - u32 term = ep93xx_pwm_read_tc(pwm); + u32 term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); u32 duty = ((term + 1) * val / 100) - 1; writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 11/14] misc/ep93xx_pwm: remove ep93xx_pwm_is_enabled() inline function
This is a simple wrapper around readl(), remove it. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 9 ++--- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index 6f48375..3dd2006 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -39,11 +39,6 @@ struct ep93xx_pwm { u32 duty_percent; }; -static inline int ep93xx_pwm_is_enabled(struct ep93xx_pwm *pwm) -{ - return readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1; -} - static inline int ep93xx_pwm_is_inverted(struct ep93xx_pwm *pwm) { return readl(pwm->mmio_base + EP93XX_PWMx_INVERT) & 0x1; @@ -84,7 +79,7 @@ static ssize_t ep93xx_pwm_get_freq(struct device *dev, struct platform_device *pdev = to_platform_device(dev); struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); - if (ep93xx_pwm_is_enabled(pwm)) { + if (readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1) { unsigned long rate = clk_get_rate(pwm->clk); u16 term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); @@ -129,7 +124,7 @@ static ssize_t ep93xx_pwm_set_freq(struct device *dev, writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); } - if (!ep93xx_pwm_is_enabled(pwm)) + if (!readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1) writel(0x1, pwm->mmio_base + EP93XX_PWMx_ENABLE); } else { return -EINVAL; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 08/14] misc/ep93xx_pwm: remove ep93xx_pwm_invert() inline function
This is a simple wrapper around writel(), remove it. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 7 +-- 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index 320d911..5193faf 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -49,11 +49,6 @@ static inline int ep93xx_pwm_is_enabled(struct ep93xx_pwm *pwm) return readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1; } -static inline void ep93xx_pwm_invert(struct ep93xx_pwm *pwm) -{ - writel(0x1, pwm->mmio_base + EP93XX_PWMx_INVERT); -} - static inline void ep93xx_pwm_normal(struct ep93xx_pwm *pwm) { writel(0x0, pwm->mmio_base + EP93XX_PWMx_INVERT); @@ -210,7 +205,7 @@ static ssize_t ep93xx_pwm_set_invert(struct device *dev, if (val == 0) ep93xx_pwm_normal(pwm); else if (val == 1) - ep93xx_pwm_invert(pwm); + writel(0x1, pwm->mmio_base + EP93XX_PWMx_INVERT); else return -EINVAL; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 07/14] misc/ep93xx_pwm: remove ep93xx_pwm_disable() inline function
This is a simple wrapper around writel(), remove it. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 11 +++ 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index cf42347..320d911 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -44,11 +44,6 @@ static inline u16 ep93xx_pwm_read_tc(struct ep93xx_pwm *pwm) return readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); } -static inline void ep93xx_pwm_disable(struct ep93xx_pwm *pwm) -{ - writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE); -} - static inline int ep93xx_pwm_is_enabled(struct ep93xx_pwm *pwm) { return readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1; @@ -127,7 +122,7 @@ static ssize_t ep93xx_pwm_set_freq(struct device *dev, return -EINVAL; if (val == 0) { - ep93xx_pwm_disable(pwm); + writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE); } else if (val <= (clk_get_rate(pwm->clk) / 2)) { u32 term, duty; @@ -276,7 +271,7 @@ static int __init ep93xx_pwm_probe(struct platform_device *pdev) pwm->duty_percent = 50; /* disable pwm at startup. Avoids zero value. */ - ep93xx_pwm_disable(pwm); + writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE); writel(EP93XX_PWM_MAX_COUNT, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); writel(EP93XX_PWM_MAX_COUNT/2, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE); @@ -290,7 +285,7 @@ static int __exit ep93xx_pwm_remove(struct platform_device *pdev) { struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); - ep93xx_pwm_disable(pwm); + writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE); clk_disable(pwm->clk); sysfs_remove_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); ep93xx_pwm_release_gpio(pdev); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 06/14] misc/ep93xx_pwm: remove ep93xx_pwm_enable() inline function
This is a simple wrapper around writel(), remove it. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 7 +-- 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index 7a13304..cf42347 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -44,11 +44,6 @@ static inline u16 ep93xx_pwm_read_tc(struct ep93xx_pwm *pwm) return readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); } -static inline void ep93xx_pwm_enable(struct ep93xx_pwm *pwm) -{ - writel(0x1, pwm->mmio_base + EP93XX_PWMx_ENABLE); -} - static inline void ep93xx_pwm_disable(struct ep93xx_pwm *pwm) { writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE); @@ -155,7 +150,7 @@ static ssize_t ep93xx_pwm_set_freq(struct device *dev, } if (!ep93xx_pwm_is_enabled(pwm)) - ep93xx_pwm_enable(pwm); + writel(0x1, pwm->mmio_base + EP93XX_PWMx_ENABLE); } else { return -EINVAL; } -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 04/14] misc/ep93xx_pwm: remove ep93xx_pwm_write_tc() inline function
This is a simple wrapper around writel(), remove it. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 11 +++ 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index 06f0c63..ab5a481 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -39,11 +39,6 @@ struct ep93xx_pwm { u32 duty_percent; }; -static inline void ep93xx_pwm_write_tc(struct ep93xx_pwm *pwm, u16 value) -{ - writel(value, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); -} - static inline u16 ep93xx_pwm_read_tc(struct ep93xx_pwm *pwm) { return readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); @@ -157,11 +152,11 @@ static ssize_t ep93xx_pwm_set_freq(struct device *dev, /* If pwm is running, order is important */ if (val > term) { - ep93xx_pwm_write_tc(pwm, val); + writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); ep93xx_pwm_write_dc(pwm, duty); } else { ep93xx_pwm_write_dc(pwm, duty); - ep93xx_pwm_write_tc(pwm, val); + writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); } if (!ep93xx_pwm_is_enabled(pwm)) @@ -290,7 +285,7 @@ static int __init ep93xx_pwm_probe(struct platform_device *pdev) /* disable pwm at startup. Avoids zero value. */ ep93xx_pwm_disable(pwm); - ep93xx_pwm_write_tc(pwm, EP93XX_PWM_MAX_COUNT); + writel(EP93XX_PWM_MAX_COUNT, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); ep93xx_pwm_write_dc(pwm, EP93XX_PWM_MAX_COUNT / 2); clk_enable(pwm->clk); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 05/14] misc/ep93xx_pwm: remove ep93xx_pwm_write_dc() inline function
This is a simple wrapper around writel(), remove it. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 15 ++- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index ab5a481..7a13304 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -44,11 +44,6 @@ static inline u16 ep93xx_pwm_read_tc(struct ep93xx_pwm *pwm) return readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); } -static inline void ep93xx_pwm_write_dc(struct ep93xx_pwm *pwm, u16 value) -{ - writel(value, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE); -} - static inline void ep93xx_pwm_enable(struct ep93xx_pwm *pwm) { writel(0x1, pwm->mmio_base + EP93XX_PWMx_ENABLE); @@ -153,9 +148,9 @@ static ssize_t ep93xx_pwm_set_freq(struct device *dev, /* If pwm is running, order is important */ if (val > term) { writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); - ep93xx_pwm_write_dc(pwm, duty); + writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE); } else { - ep93xx_pwm_write_dc(pwm, duty); + writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE); writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); } @@ -191,7 +186,9 @@ static ssize_t ep93xx_pwm_set_duty_percent(struct device *dev, if (val > 0 && val < 100) { u32 term = ep93xx_pwm_read_tc(pwm); - ep93xx_pwm_write_dc(pwm, ((term + 1) * val / 100) - 1); + u32 duty = ((term + 1) * val / 100) - 1; + + writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE); pwm->duty_percent = val; return count; } @@ -286,7 +283,7 @@ static int __init ep93xx_pwm_probe(struct platform_device *pdev) /* disable pwm at startup. Avoids zero value. */ ep93xx_pwm_disable(pwm); writel(EP93XX_PWM_MAX_COUNT, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); - ep93xx_pwm_write_dc(pwm, EP93XX_PWM_MAX_COUNT / 2); + writel(EP93XX_PWM_MAX_COUNT/2, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE); clk_enable(pwm->clk); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 03/14] misc/ep93xx_pwm: remove ep93xx_pwm_{write,read}l() inline functions
These are simple wrappers around writel() and readl(). Remove them. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 30 +- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index af01fb9..06f0c63 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -39,61 +39,49 @@ struct ep93xx_pwm { u32 duty_percent; }; -static inline void ep93xx_pwm_writel(struct ep93xx_pwm *pwm, - unsigned int val, unsigned int off) -{ - writel(val, pwm->mmio_base + off); -} - -static inline unsigned int ep93xx_pwm_readl(struct ep93xx_pwm *pwm, - unsigned int off) -{ - return readl(pwm->mmio_base + off); -} - static inline void ep93xx_pwm_write_tc(struct ep93xx_pwm *pwm, u16 value) { - ep93xx_pwm_writel(pwm, value, EP93XX_PWMx_TERM_COUNT); + writel(value, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); } static inline u16 ep93xx_pwm_read_tc(struct ep93xx_pwm *pwm) { - return ep93xx_pwm_readl(pwm, EP93XX_PWMx_TERM_COUNT); + return readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); } static inline void ep93xx_pwm_write_dc(struct ep93xx_pwm *pwm, u16 value) { - ep93xx_pwm_writel(pwm, value, EP93XX_PWMx_DUTY_CYCLE); + writel(value, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE); } static inline void ep93xx_pwm_enable(struct ep93xx_pwm *pwm) { - ep93xx_pwm_writel(pwm, 0x1, EP93XX_PWMx_ENABLE); + writel(0x1, pwm->mmio_base + EP93XX_PWMx_ENABLE); } static inline void ep93xx_pwm_disable(struct ep93xx_pwm *pwm) { - ep93xx_pwm_writel(pwm, 0x0, EP93XX_PWMx_ENABLE); + writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE); } static inline int ep93xx_pwm_is_enabled(struct ep93xx_pwm *pwm) { - return ep93xx_pwm_readl(pwm, EP93XX_PWMx_ENABLE) & 0x1; + return readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1; } static inline void ep93xx_pwm_invert(struct ep93xx_pwm *pwm) { - ep93xx_pwm_writel(pwm, 0x1, EP93XX_PWMx_INVERT); + writel(0x1, pwm->mmio_base + EP93XX_PWMx_INVERT); } static inline void ep93xx_pwm_normal(struct ep93xx_pwm *pwm) { - ep93xx_pwm_writel(pwm, 0x0, EP93XX_PWMx_INVERT); + writel(0x0, pwm->mmio_base + EP93XX_PWMx_INVERT); } static inline int ep93xx_pwm_is_inverted(struct ep93xx_pwm *pwm) { - return ep93xx_pwm_readl(pwm, EP93XX_PWMx_INVERT) & 0x1; + return readl(pwm->mmio_base + EP93XX_PWMx_INVERT) & 0x1; } /* -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 02/14] misc/ep93xx_pwm: use {read,write}* instead of __raw_* versions for io
The mmio_base is an ioremap'ed memory resource. The normal memory io functions should be used not the __raw_* versions. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index 36370b4..af01fb9 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -42,13 +42,13 @@ struct ep93xx_pwm { static inline void ep93xx_pwm_writel(struct ep93xx_pwm *pwm, unsigned int val, unsigned int off) { - __raw_writel(val, pwm->mmio_base + off); + writel(val, pwm->mmio_base + off); } static inline unsigned int ep93xx_pwm_readl(struct ep93xx_pwm *pwm, unsigned int off) { - return __raw_readl(pwm->mmio_base + off); + return readl(pwm->mmio_base + off); } static inline void ep93xx_pwm_write_tc(struct ep93xx_pwm *pwm, u16 value) -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 01/14] misc/ep93xx_pwm: use managed device resources
Use managed device resources to clean up the probe/remove. Signed-off-by: H Hartley Sweeten Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Ryan Mallon Cc: Matthieu Crapet --- drivers/misc/ep93xx_pwm.c | 73 +-- 1 file changed, 20 insertions(+), 53 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index 9ba93f0..36370b4 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -273,50 +273,33 @@ static int __init ep93xx_pwm_probe(struct platform_device *pdev) { struct ep93xx_pwm *pwm; struct resource *res; - int err; + int ret; - err = ep93xx_pwm_acquire_gpio(pdev); - if (err) - return err; + pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); + if (!pwm) + return -ENOMEM; - pwm = kzalloc(sizeof(struct ep93xx_pwm), GFP_KERNEL); - if (!pwm) { - err = -ENOMEM; - goto fail_no_mem; - } + pwm->clk = devm_clk_get(&pdev->dev, "pwm_clk"); + if (IS_ERR(pwm->clk)) + return PTR_ERR(pwm->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - err = -ENXIO; - goto fail_no_mem_resource; - } - - res = request_mem_region(res->start, resource_size(res), pdev->name); - if (res == NULL) { - err = -EBUSY; - goto fail_no_mem_resource; - } - - pwm->mmio_base = ioremap(res->start, resource_size(res)); - if (pwm->mmio_base == NULL) { - err = -ENXIO; - goto fail_no_ioremap; - } - - err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); - if (err) - goto fail_no_sysfs; - - pwm->clk = clk_get(&pdev->dev, "pwm_clk"); - if (IS_ERR(pwm->clk)) { - err = PTR_ERR(pwm->clk); - goto fail_no_clk; + pwm->mmio_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pwm->mmio_base)) + return PTR_ERR(pwm->mmio_base); + + ret = ep93xx_pwm_acquire_gpio(pdev); + if (ret) + return ret; + + ret = sysfs_create_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); + if (ret) { + ep93xx_pwm_release_gpio(pdev); + return ret; } pwm->duty_percent = 50; - platform_set_drvdata(pdev, pwm); - /* disable pwm at startup. Avoids zero value. */ ep93xx_pwm_disable(pwm); ep93xx_pwm_write_tc(pwm, EP93XX_PWM_MAX_COUNT); @@ -324,33 +307,17 @@ static int __init ep93xx_pwm_probe(struct platform_device *pdev) clk_enable(pwm->clk); + platform_set_drvdata(pdev, pwm); return 0; - -fail_no_clk: - sysfs_remove_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); -fail_no_sysfs: - iounmap(pwm->mmio_base); -fail_no_ioremap: - release_mem_region(res->start, resource_size(res)); -fail_no_mem_resource: - kfree(pwm); -fail_no_mem: - ep93xx_pwm_release_gpio(pdev); - return err; } static int __exit ep93xx_pwm_remove(struct platform_device *pdev) { struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ep93xx_pwm_disable(pwm); clk_disable(pwm->clk); - clk_put(pwm->clk); sysfs_remove_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); - iounmap(pwm->mmio_base); - release_mem_region(res->start, resource_size(res)); - kfree(pwm); ep93xx_pwm_release_gpio(pdev); return 0; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 00/14] misc/ep93xx_pwm: cleanup driver for conversion to PWM framework
This driver needs to be converted to the new PWM framework. Before converting it clean up all the cruft, H Hartley Sweeten (14): misc/ep93xx_pwm: use managed device resources misc/ep93xx_pwm: use {read,write}* instead of __raw_* versions for io misc/ep93xx_pwm: remove ep93xx_pwm_{write,read}l() inline functions misc/ep93xx_pwm: remove ep93xx_pwm_write_tc() inline function misc/ep93xx_pwm: remove ep93xx_pwm_write_dc() inline function misc/ep93xx_pwm: remove ep93xx_pwm_enable() inline function misc/ep93xx_pwm: remove ep93xx_pwm_disable() inline function misc/ep93xx_pwm: remove ep93xx_pwm_invert() inline function misc/ep93xx_pwm: remove ep93xx_pwm_normal() inline function misc/ep93xx_pwm: remove ep93xx_pwm_read_tc() inline function misc/ep93xx_pwm: remove ep93xx_pwm_is_enabled() inline function misc/ep93xx_pwm: remove ep93xx_pwm_is_inverted() inline function misc/ep93xx_pwm: use module_platform_driver() misc/ep93xx_pwm: use kstrtol instead of strict_strtol drivers/misc/ep93xx_pwm.c | 187 +- 1 file changed, 50 insertions(+), 137 deletions(-) -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH 2/2] spi: convert drivers to use bits_per_word_mask
On Tuesday, May 21, 2013 7:37 PM, Stephen Warren wrote: > > Fill in the recently added spi_master.bits_per_word_mask field in as > many drivers as possible. Make related cleanups, such as removing any > redundant error-checking, or empty setup callbacks. > > Cc: device-drivers-de...@blackfin.uclinux.org > Cc: Mike Frysinger > Signed-off-by: Stephen Warren > --- > drivers/spi/spi-ep93xx.c| 11 +-- > diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c > index d7bac60..f1b1497 100644 > --- a/drivers/spi/spi-ep93xx.c > +++ b/drivers/spi/spi-ep93xx.c > @@ -296,12 +296,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) > struct ep93xx_spi *espi = spi_master_get_devdata(spi->master); > struct ep93xx_spi_chip *chip; > > - if (spi->bits_per_word < 4 || spi->bits_per_word > 16) { > - dev_err(&espi->pdev->dev, "invalid bits per word %d\n", > - spi->bits_per_word); > - return -EINVAL; > - } > - > chip = spi_get_ctldata(spi); > if (!chip) { > dev_dbg(&espi->pdev->dev, "initial setup for %s\n", > @@ -365,10 +359,6 @@ static int ep93xx_spi_transfer(struct spi_device *spi, > struct spi_message *msg) > > /* first validate each transfer */ > list_for_each_entry(t, &msg->transfers, transfer_list) { > - if (t->bits_per_word) { > - if (t->bits_per_word < 4 || t->bits_per_word > 16) > - return -EINVAL; > - } > if (t->speed_hz && t->speed_hz < espi->min_rate) > return -EINVAL; > } > @@ -1046,6 +1036,7 @@ static int ep93xx_spi_probe(struct platform_device > *pdev) > master->bus_num = pdev->id; > master->num_chipselect = info->num_chipselect; > master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; > + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); > > platform_set_drvdata(pdev, master); Seems reasonable. For the spi-ep93xx driver: Acked-by: H Hartley Sweeten -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH 1/7] input: ep93xx_keypad: Pass correct pointer to free_irq()
On Monday, May 20, 2013 7:51 AM, Lars-Peter Clausen wrote: > free_irq() expects the same pointer that was passed to request_irq(), > otherwise > the IRQ is not freed. > Cc: H Hartley Sweeten > Signed-off-by: Lars-Peter Clausen > --- > drivers/input/keyboard/ep93xx_keypad.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) Thanks, Acked-by: H Hartley Sweeten -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH 2/2] misc: ep93xx_pwm: remove unnecessary platform_set_drvdata()
On Monday, May 06, 2013 10:34 PM, Jingoo Han wrote: > The driver core clears the driver data to NULL after device_release > or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d > (device-core: Ensure drvdata = NULL when no driver is bound). > Thus, it is not needed to manually clear the device driver data to NULL. > > Signed-off-by: Jingoo Han > --- > drivers/misc/ep93xx_pwm.c |1 - > 1 files changed, 0 insertions(+), 1 deletions(-) Reviewed-by: H Hartley Sweeten -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH 12/12] staging: COMEDI should depend on HAS_DMA
On Thursday, May 09, 2013 2:05 PM, Geert Uytterhoeven wrote: > If NO_DMA=y: > > ERROR: "dma_free_coherent" [drivers/staging/comedi/comedi.ko] undefined! > ERROR: "dma_alloc_coherent" [drivers/staging/comedi/comedi.ko] undefined! > > Signed-off-by: Geert Uytterhoeven > Cc: Ian Abbott > Cc: Greg Kroah-Hartman > Cc: de...@driverdev.osuosl.org Grr.. The error appears to be caused by the dma alloc/free in comedi_buf.c. These only happen if the (s->async_dma_dir != DMA_NONE). The comedi core defaults the async_dma_dir to DMA_NONE. The only comedi drivers that set it are ni_660x, ni_mio_common, and ni_pcidio. The mite driver also has a dma_alloc/free. Ian, can you think of a better solution than just making comedi depend on HAS_DMA? Thanks, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: linux-next: build failure after merge of the final tree (staging tree related))
On Wednesday, April 24, 2013 12:56 AM, Stephen Rothwell wrote: > After merging the final tree, today's linux-next build (powerpc > allyesconfig) failed like this: > > drivers/staging/comedi/drivers/ni_labpc.c: In function 'labpc_ai_cmd': > drivers/staging/comedi/drivers/ni_labpc.c:980:9: error: implicit declaration > of function 'virt_to_bus' [-Werror=implicit-function-declaration] > Stephen, I just posted a patch that hopefully will fix this. Please let me know if it works. Regards, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: linux-next: build failure after merge of the final tree (staging tree related))
On Wednesday, April 24, 2013 12:56 AM, Stephen Rothwell wrote: > Hi all, > > After merging the final tree, today's linux-next build (powerpc > allyesconfig) failed like this: Ugh.. powerpc probably has CONFIG_ISA_DMA_API but not CONFIG_VIRT_TO_BUS. I'm looking for a fix now. Regards, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH 15/21] staging: comedi/dawboard2000: use mdelay for large delays
On Tuesday, April 23, 2013 9:31 AM, Arnd Bergmann wrote: > Subject: [PATCH 15/21] staging: comedi/dawboard2000: use mdelay for large > delays Nit.. Typo in subject. > On ARM, it is not legal to pass values larger than 2ms into udelay(), > and mdelay() must be used instead, to avoid this build error: > > ERROR: "__bad_udelay" [drivers/staging/comedi/drivers/daqboard2000.ko] > undefined! > > On a related note, any use of mdelay() or large udelay() numbers should > be carefully reviewed, and replaced with msleep() or a different > implementation that does not rely on delaying the work. > > Signed-off-by: Arnd Bergmann > Cc: H Hartley Sweeten > Cc: Ian Abbott > Cc: Greg Kroah-Hartman Reviewed-by: H Hartley Sweeten Thanks, Hartley -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] scsi: pcmcia: nsp_cs: remove module init/exit function prototypes
This driver now uses the module_pcmcia_driver() macro to supply the init/exit code. The nsp_cs_{init,exit} prototypes should be removed. Reported-by: kbuild test robot Signed-off-by: H Hartley Sweeten Cc: YOKOTA Hiroshi Cc: "James E.J. Bottomley" Cc: Greg Kroah-Hartman Cc: linux-s...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/scsi/pcmcia/nsp_cs.h | 4 1 file changed, 4 deletions(-) diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h index afd64f0..ea5122f 100644 --- a/drivers/scsi/pcmcia/nsp_cs.h +++ b/drivers/scsi/pcmcia/nsp_cs.h @@ -326,10 +326,6 @@ static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht); /* Interrupt handler */ //static irqreturn_t nspintr(int irq, void *dev_id); -/* Module entry point*/ -static int __init nsp_cs_init(void); -static void __exit nsp_cs_exit(void); - /* Debug */ #ifdef NSP_DEBUG static void show_command (struct scsi_cmnd *SCpnt); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/