From 7bfa5ab6fa1b18f53fb94f922e107e6fbdc5e485 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 13 Oct 2014 15:51:07 -0700 Subject: drivers: dma-coherent: add initialization from device tree Initialization procedure of dma coherent pool has been split into two parts, so memory pool can now be initialized without assigning to particular struct device. Then initialized region can be assigned to more than one struct device. To protect from concurent allocations from structure. The last part of this patch adds support for handling 'shared-dma-pool' reserved-memory device tree nodes. [akpm@linux-foundation.org: use more appropriate printk facility levels] [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Marek Szyprowski Cc: Arnd Bergmann Cc: Michal Nazarewicz Cc: Grant Likely Cc: Laura Abbott Cc: Josh Cartwright Cc: Joonsoo Kim Cc: Kyungmin Park Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/dma-coherent.c | 151 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 129 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 7d6e84a51424..55b83983a9c0 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -14,11 +14,14 @@ struct dma_coherent_mem { int size; int flags; unsigned long *bitmap; + spinlock_t spinlock; }; -int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, - dma_addr_t device_addr, size_t size, int flags) +static int dma_init_coherent_memory(phys_addr_t phys_addr, dma_addr_t device_addr, + size_t size, int flags, + struct dma_coherent_mem **mem) { + struct dma_coherent_mem *dma_mem = NULL; void __iomem *mem_base = NULL; int pages = size >> PAGE_SHIFT; int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long); @@ -27,40 +30,77 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, goto out; if (!size) goto out; - if (dev->dma_mem) - goto out; - - /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ mem_base = ioremap(phys_addr, size); if (!mem_base) goto out; - dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); - if (!dev->dma_mem) + dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); + if (!dma_mem) goto out; - dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!dev->dma_mem->bitmap) - goto free1_out; + dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!dma_mem->bitmap) + goto out; + + dma_mem->virt_base = mem_base; + dma_mem->device_base = device_addr; + dma_mem->pfn_base = PFN_DOWN(phys_addr); + dma_mem->size = pages; + dma_mem->flags = flags; + spin_lock_init(&dma_mem->spinlock); - dev->dma_mem->virt_base = mem_base; - dev->dma_mem->device_base = device_addr; - dev->dma_mem->pfn_base = PFN_DOWN(phys_addr); - dev->dma_mem->size = pages; - dev->dma_mem->flags = flags; + *mem = dma_mem; if (flags & DMA_MEMORY_MAP) return DMA_MEMORY_MAP; return DMA_MEMORY_IO; - free1_out: - kfree(dev->dma_mem); - out: +out: + kfree(dma_mem); if (mem_base) iounmap(mem_base); return 0; } + +static void dma_release_coherent_memory(struct dma_coherent_mem *mem) +{ + if (!mem) + return; + iounmap(mem->virt_base); + kfree(mem->bitmap); + kfree(mem); +} + +static int dma_assign_coherent_memory(struct device *dev, + struct dma_coherent_mem *mem) +{ + if (dev->dma_mem) + return -EBUSY; + + dev->dma_mem = mem; + /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ + + return 0; +} + +int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, + dma_addr_t device_addr, size_t size, int flags) +{ + struct dma_coherent_mem *mem; + int ret; + + ret = dma_init_coherent_memory(phys_addr, device_addr, size, flags, + &mem); + if (ret == 0) + return 0; + + if (dma_assign_coherent_memory(dev, mem) == 0) + return ret; + + dma_release_coherent_memory(mem); + return 0; +} EXPORT_SYMBOL(dma_declare_coherent_memory); void dma_release_declared_memory(struct device *dev) @@ -69,10 +109,8 @@ void dma_release_declared_memory(struct device *dev) if (!mem) return; + dma_release_coherent_memory(mem); dev->dma_mem = NULL; - iounmap(mem->virt_base); - kfree(mem->bitmap); - kfree(mem); } EXPORT_SYMBOL(dma_release_declared_memory); @@ -80,6 +118,7 @@ void *dma_mark_declared_memory_occupied(struct device *dev, dma_addr_t device_addr, size_t size) { struct dma_coherent_mem *mem = dev->dma_mem; + unsigned long flags; int pos, err; size += device_addr & ~PAGE_MASK; @@ -87,8 +126,11 @@ void *dma_mark_declared_memory_occupied(struct device *dev, if (!mem) return ERR_PTR(-EINVAL); + spin_lock_irqsave(&mem->spinlock, flags); pos = (device_addr - mem->device_base) >> PAGE_SHIFT; err = bitmap_allocate_region(mem->bitmap, pos, get_order(size)); + spin_unlock_irqrestore(&mem->spinlock, flags); + if (err != 0) return ERR_PTR(err); return mem->virt_base + (pos << PAGE_SHIFT); @@ -115,6 +157,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, { struct dma_coherent_mem *mem; int order = get_order(size); + unsigned long flags; int pageno; if (!dev) @@ -124,6 +167,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, return 0; *ret = NULL; + spin_lock_irqsave(&mem->spinlock, flags); if (unlikely(size > (mem->size << PAGE_SHIFT))) goto err; @@ -138,10 +182,12 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, *dma_handle = mem->device_base + (pageno << PAGE_SHIFT); *ret = mem->virt_base + (pageno << PAGE_SHIFT); memset(*ret, 0, size); + spin_unlock_irqrestore(&mem->spinlock, flags); return 1; err: + spin_unlock_irqrestore(&mem->spinlock, flags); /* * In the case where the allocation can not be satisfied from the * per-device area, try to fall back to generic memory if the @@ -171,8 +217,11 @@ int dma_release_from_coherent(struct device *dev, int order, void *vaddr) if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; + unsigned long flags; + spin_lock_irqsave(&mem->spinlock, flags); bitmap_release_region(mem->bitmap, page, order); + spin_unlock_irqrestore(&mem->spinlock, flags); return 1; } return 0; @@ -218,3 +267,61 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, return 0; } EXPORT_SYMBOL(dma_mmap_from_coherent); + +/* + * Support for reserved memory regions defined in device tree + */ +#ifdef CONFIG_OF_RESERVED_MEM +#include +#include +#include + +static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev) +{ + struct dma_coherent_mem *mem = rmem->priv; + + if (!mem && + dma_init_coherent_memory(rmem->base, rmem->base, rmem->size, + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE, + &mem) != DMA_MEMORY_MAP) { + pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n", + &rmem->base, (unsigned long)rmem->size / SZ_1M); + return -ENODEV; + } + rmem->priv = mem; + dma_assign_coherent_memory(dev, mem); + return 0; +} + +static void rmem_dma_device_release(struct reserved_mem *rmem, + struct device *dev) +{ + dev->dma_mem = NULL; +} + +static const struct reserved_mem_ops rmem_dma_ops = { + .device_init = rmem_dma_device_init, + .device_release = rmem_dma_device_release, +}; + +static int __init rmem_dma_setup(struct reserved_mem *rmem) +{ + unsigned long node = rmem->fdt_node; + + if (of_get_flat_dt_prop(node, "reusable", NULL)) + return -EINVAL; + +#ifdef CONFIG_ARM + if (!of_get_flat_dt_prop(node, "no-map", NULL)) { + pr_err("Reserved memory: regions without no-map are not yet supported\n"); + return -EINVAL; + } +#endif + + rmem->ops = &rmem_dma_ops; + pr_info("Reserved memory: created DMA memory pool at %pa, size %ld MiB\n", + &rmem->base, (unsigned long)rmem->size / SZ_1M); + return 0; +} +RESERVEDMEM_OF_DECLARE(dma, "shared-dma-pool", rmem_dma_setup); +#endif -- cgit v1.2.3 From de9e14eebf33a60712a52a0bc6e08c043c0aba53 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 13 Oct 2014 15:51:09 -0700 Subject: drivers: dma-contiguous: add initialization from device tree Add a function to create CMA region from previously reserved memory and add support for handling 'shared-dma-pool' reserved-memory device tree nodes. Based on previous code provided by Josh Cartwright Signed-off-by: Marek Szyprowski Cc: Arnd Bergmann Cc: Michal Nazarewicz Cc: Grant Likely Cc: Laura Abbott Cc: Josh Cartwright Cc: Joonsoo Kim Cc: Kyungmin Park Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/dma-contiguous.c | 66 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'drivers') diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 6606abdf880c..473ff4892401 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -211,3 +211,69 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages, { return cma_release(dev_get_cma_area(dev), pages, count); } + +/* + * Support for reserved memory regions defined in device tree + */ +#ifdef CONFIG_OF_RESERVED_MEM +#include +#include +#include + +#undef pr_fmt +#define pr_fmt(fmt) fmt + +static void rmem_cma_device_init(struct reserved_mem *rmem, struct device *dev) +{ + dev_set_cma_area(dev, rmem->priv); +} + +static void rmem_cma_device_release(struct reserved_mem *rmem, + struct device *dev) +{ + dev_set_cma_area(dev, NULL); +} + +static const struct reserved_mem_ops rmem_cma_ops = { + .device_init = rmem_cma_device_init, + .device_release = rmem_cma_device_release, +}; + +static int __init rmem_cma_setup(struct reserved_mem *rmem) +{ + phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order); + phys_addr_t mask = align - 1; + unsigned long node = rmem->fdt_node; + struct cma *cma; + int err; + + if (!of_get_flat_dt_prop(node, "reusable", NULL) || + of_get_flat_dt_prop(node, "no-map", NULL)) + return -EINVAL; + + if ((rmem->base & mask) || (rmem->size & mask)) { + pr_err("Reserved memory: incorrect alignment of CMA region\n"); + return -EINVAL; + } + + err = cma_init_reserved_mem(rmem->base, rmem->size, 0, &cma); + if (err) { + pr_err("Reserved memory: unable to setup CMA region\n"); + return err; + } + /* Architecture specific contiguous memory fixup. */ + dma_contiguous_early_fixup(rmem->base, rmem->size); + + if (of_get_flat_dt_prop(node, "linux,cma-default", NULL)) + dma_contiguous_set_default(cma); + + rmem->ops = &rmem_cma_ops; + rmem->priv = cma; + + pr_info("Reserved memory: created CMA memory pool at %pa, size %ld MiB\n", + &rmem->base, (unsigned long)rmem->size / SZ_1M); + + return 0; +} +RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup); +#endif -- cgit v1.2.3 From 473b86451276d6d342ecd26d5e503163c30ea974 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 13 Oct 2014 15:52:26 -0700 Subject: rtc: use c99 initializers in structures Use c99 initializers for structures. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @decl@ identifier i1,fld; type T; field list[n] fs; @@ struct i1 { fs T fld; ...}; @bad@ identifier decl.i1,i2; expression e; initializer list[decl.n] is; @@ struct i1 i2 = { is, + .fld = e - e ,...}; // Signed-off-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pcf8583.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index c2639845186b..5911a6dca291 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c @@ -176,7 +176,11 @@ static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct i2c_client *client = to_i2c_client(dev); unsigned char ctrl, year[2]; - struct rtc_mem mem = { CMOS_YEAR, sizeof(year), year }; + struct rtc_mem mem = { + .loc = CMOS_YEAR, + .nr = sizeof(year), + .data = year + }; int real_year, year_offset, err; /* @@ -222,8 +226,16 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct i2c_client *client = to_i2c_client(dev); unsigned char year[2], chk; - struct rtc_mem cmos_year = { CMOS_YEAR, sizeof(year), year }; - struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk }; + struct rtc_mem cmos_year = { + .loc = CMOS_YEAR, + .nr = sizeof(year), + .data = year + }; + struct rtc_mem cmos_check = { + .loc = CMOS_CHECKSUM, + .nr = 1, + .data = &chk + }; unsigned int proper_year = tm->tm_year + 1900; int ret; -- cgit v1.2.3 From 19be09f51d36101e4dc1577eb73ff8397bedd0a3 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 13 Oct 2014 15:52:28 -0700 Subject: rtc: s3c: define s3c_rtc structure to remove global variables. Define s3c_rtc structure including necessary variables for S3C RTC device instead of global variables. This patch improves the readability by removing global variables. Signed-off-by: Chanwoo Choi Acked-by: Kyungmin Park Cc: Alessandro Zummo Cc: Kukjin Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s3c.c | 431 +++++++++++++++++++++++++------------------------- 1 file changed, 216 insertions(+), 215 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 4958a363b2c7..2f71b13c00d6 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -43,125 +43,132 @@ struct s3c_rtc_drv_data { int cpu_type; }; -/* I have yet to find an S3C implementation with more than one - * of these rtc blocks in */ +struct s3c_rtc { + struct device *dev; + struct rtc_device *rtc; + + void __iomem *base; + struct clk *rtc_clk; + bool enabled; + + enum s3c_cpu_type cpu_type; -static struct clk *rtc_clk; -static void __iomem *s3c_rtc_base; -static int s3c_rtc_alarmno; -static int s3c_rtc_tickno; -static enum s3c_cpu_type s3c_rtc_cpu_type; + int irq_alarm; + int irq_tick; -static DEFINE_SPINLOCK(s3c_rtc_pie_lock); + spinlock_t pie_lock; + spinlock_t alarm_clk_lock; -static void s3c_rtc_alarm_clk_enable(bool enable) + int ticnt_save, ticnt_en_save; + bool wake_en; +}; + +static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable) { - static DEFINE_SPINLOCK(s3c_rtc_alarm_clk_lock); - static bool alarm_clk_enabled; unsigned long irq_flags; - spin_lock_irqsave(&s3c_rtc_alarm_clk_lock, irq_flags); + spin_lock_irqsave(&info->alarm_clk_lock, irq_flags); if (enable) { - if (!alarm_clk_enabled) { - clk_enable(rtc_clk); - alarm_clk_enabled = true; + if (!info->enabled) { + clk_enable(info->rtc_clk); + info->enabled = true; } } else { - if (alarm_clk_enabled) { - clk_disable(rtc_clk); - alarm_clk_enabled = false; + if (info->enabled) { + clk_disable(info->rtc_clk); + info->enabled = false; } } - spin_unlock_irqrestore(&s3c_rtc_alarm_clk_lock, irq_flags); + spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags); } /* IRQ Handlers */ - static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) { - struct rtc_device *rdev = id; + struct s3c_rtc *info = (struct s3c_rtc *)id; - clk_enable(rtc_clk); - rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); + clk_enable(info->rtc_clk); + rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); - if (s3c_rtc_cpu_type == TYPE_S3C64XX) - writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); + if (info->cpu_type == TYPE_S3C64XX) + writeb(S3C2410_INTP_ALM, info->base + S3C2410_INTP); - clk_disable(rtc_clk); + clk_disable(info->rtc_clk); - s3c_rtc_alarm_clk_enable(false); + s3c_rtc_alarm_clk_enable(info, false); return IRQ_HANDLED; } static irqreturn_t s3c_rtc_tickirq(int irq, void *id) { - struct rtc_device *rdev = id; + struct s3c_rtc *info = (struct s3c_rtc *)id; - clk_enable(rtc_clk); - rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); + clk_enable(info->rtc_clk); + rtc_update_irq(info->rtc, 1, RTC_PF | RTC_IRQF); - if (s3c_rtc_cpu_type == TYPE_S3C64XX) - writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); + if (info->cpu_type == TYPE_S3C64XX) + writeb(S3C2410_INTP_TIC, info->base + S3C2410_INTP); + + clk_disable(info->rtc_clk); - clk_disable(rtc_clk); return IRQ_HANDLED; } /* Update control registers */ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled) { + struct s3c_rtc *info = dev_get_drvdata(dev); unsigned int tmp; - dev_dbg(dev, "%s: aie=%d\n", __func__, enabled); + dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled); - clk_enable(rtc_clk); - tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; + clk_enable(info->rtc_clk); + tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; if (enabled) tmp |= S3C2410_RTCALM_ALMEN; - writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); - clk_disable(rtc_clk); + writeb(tmp, info->base + S3C2410_RTCALM); + clk_disable(info->rtc_clk); - s3c_rtc_alarm_clk_enable(enabled); + s3c_rtc_alarm_clk_enable(info, enabled); return 0; } -static int s3c_rtc_setfreq(struct device *dev, int freq) +static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_device *rtc_dev = platform_get_drvdata(pdev); unsigned int tmp = 0; int val; if (!is_power_of_2(freq)) return -EINVAL; - clk_enable(rtc_clk); - spin_lock_irq(&s3c_rtc_pie_lock); + clk_enable(info->rtc_clk); + spin_lock_irq(&info->pie_lock); - if (s3c_rtc_cpu_type != TYPE_S3C64XX) { - tmp = readb(s3c_rtc_base + S3C2410_TICNT); + if (info->cpu_type != TYPE_S3C64XX) { + tmp = readb(info->base + S3C2410_TICNT); tmp &= S3C2410_TICNT_ENABLE; } - val = (rtc_dev->max_user_freq / freq) - 1; + val = (info->rtc->max_user_freq / freq) - 1; - if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) { + if (info->cpu_type == TYPE_S3C2416 || info->cpu_type == TYPE_S3C2443) { tmp |= S3C2443_TICNT_PART(val); - writel(S3C2443_TICNT1_PART(val), s3c_rtc_base + S3C2443_TICNT1); + writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1); - if (s3c_rtc_cpu_type == TYPE_S3C2416) - writel(S3C2416_TICNT2_PART(val), s3c_rtc_base + S3C2416_TICNT2); + if (info->cpu_type == TYPE_S3C2416) + writel(S3C2416_TICNT2_PART(val), + info->base + S3C2416_TICNT2); } else { tmp |= val; } - writel(tmp, s3c_rtc_base + S3C2410_TICNT); - spin_unlock_irq(&s3c_rtc_pie_lock); - clk_disable(rtc_clk); + writel(tmp, info->base + S3C2410_TICNT); + spin_unlock_irq(&info->pie_lock); + clk_disable(info->rtc_clk); return 0; } @@ -170,17 +177,17 @@ static int s3c_rtc_setfreq(struct device *dev, int freq) static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) { + struct s3c_rtc *info = dev_get_drvdata(dev); unsigned int have_retried = 0; - void __iomem *base = s3c_rtc_base; - clk_enable(rtc_clk); + clk_enable(info->rtc_clk); retry_get_time: - rtc_tm->tm_min = readb(base + S3C2410_RTCMIN); - rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR); - rtc_tm->tm_mday = readb(base + S3C2410_RTCDATE); - rtc_tm->tm_mon = readb(base + S3C2410_RTCMON); - rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR); - rtc_tm->tm_sec = readb(base + S3C2410_RTCSEC); + rtc_tm->tm_min = readb(info->base + S3C2410_RTCMIN); + rtc_tm->tm_hour = readb(info->base + S3C2410_RTCHOUR); + rtc_tm->tm_mday = readb(info->base + S3C2410_RTCDATE); + rtc_tm->tm_mon = readb(info->base + S3C2410_RTCMON); + rtc_tm->tm_year = readb(info->base + S3C2410_RTCYEAR); + rtc_tm->tm_sec = readb(info->base + S3C2410_RTCSEC); /* the only way to work out whether the system was mid-update * when we read it is to check the second counter, and if it @@ -207,13 +214,14 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_mon -= 1; - clk_disable(rtc_clk); + clk_disable(info->rtc_clk); + return rtc_valid_tm(rtc_tm); } static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) { - void __iomem *base = s3c_rtc_base; + struct s3c_rtc *info = dev_get_drvdata(dev); int year = tm->tm_year - 100; dev_dbg(dev, "set time %04d.%02d.%02d %02d:%02d:%02d\n", @@ -227,33 +235,35 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) return -EINVAL; } - clk_enable(rtc_clk); - writeb(bin2bcd(tm->tm_sec), base + S3C2410_RTCSEC); - writeb(bin2bcd(tm->tm_min), base + S3C2410_RTCMIN); - writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR); - writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE); - writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON); - writeb(bin2bcd(year), base + S3C2410_RTCYEAR); - clk_disable(rtc_clk); + clk_enable(info->rtc_clk); + + writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_RTCSEC); + writeb(bin2bcd(tm->tm_min), info->base + S3C2410_RTCMIN); + writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_RTCHOUR); + writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_RTCDATE); + writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON); + writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR); + + clk_disable(info->rtc_clk); return 0; } static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) { + struct s3c_rtc *info = dev_get_drvdata(dev); struct rtc_time *alm_tm = &alrm->time; - void __iomem *base = s3c_rtc_base; unsigned int alm_en; - clk_enable(rtc_clk); - alm_tm->tm_sec = readb(base + S3C2410_ALMSEC); - alm_tm->tm_min = readb(base + S3C2410_ALMMIN); - alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); - alm_tm->tm_mon = readb(base + S3C2410_ALMMON); - alm_tm->tm_mday = readb(base + S3C2410_ALMDATE); - alm_tm->tm_year = readb(base + S3C2410_ALMYEAR); + clk_enable(info->rtc_clk); + alm_tm->tm_sec = readb(info->base + S3C2410_ALMSEC); + alm_tm->tm_min = readb(info->base + S3C2410_ALMMIN); + alm_tm->tm_hour = readb(info->base + S3C2410_ALMHOUR); + alm_tm->tm_mon = readb(info->base + S3C2410_ALMMON); + alm_tm->tm_mday = readb(info->base + S3C2410_ALMDATE); + alm_tm->tm_year = readb(info->base + S3C2410_ALMYEAR); - alm_en = readb(base + S3C2410_RTCALM); + alm_en = readb(info->base + S3C2410_RTCALM); alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; @@ -297,65 +307,67 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) else alm_tm->tm_year = -1; - clk_disable(rtc_clk); + clk_disable(info->rtc_clk); return 0; } static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) { + struct s3c_rtc *info = dev_get_drvdata(dev); struct rtc_time *tm = &alrm->time; - void __iomem *base = s3c_rtc_base; unsigned int alrm_en; - clk_enable(rtc_clk); + clk_enable(info->rtc_clk); dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", alrm->enabled, 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; - writeb(0x00, base + S3C2410_RTCALM); + alrm_en = readb(info->base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; + writeb(0x00, info->base + S3C2410_RTCALM); if (tm->tm_sec < 60 && tm->tm_sec >= 0) { alrm_en |= S3C2410_RTCALM_SECEN; - writeb(bin2bcd(tm->tm_sec), base + S3C2410_ALMSEC); + writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_ALMSEC); } if (tm->tm_min < 60 && tm->tm_min >= 0) { alrm_en |= S3C2410_RTCALM_MINEN; - writeb(bin2bcd(tm->tm_min), base + S3C2410_ALMMIN); + writeb(bin2bcd(tm->tm_min), info->base + S3C2410_ALMMIN); } if (tm->tm_hour < 24 && tm->tm_hour >= 0) { alrm_en |= S3C2410_RTCALM_HOUREN; - writeb(bin2bcd(tm->tm_hour), base + S3C2410_ALMHOUR); + writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR); } dev_dbg(dev, "setting S3C2410_RTCALM to %08x\n", alrm_en); - writeb(alrm_en, base + S3C2410_RTCALM); + writeb(alrm_en, info->base + S3C2410_RTCALM); s3c_rtc_setaie(dev, alrm->enabled); - clk_disable(rtc_clk); + clk_disable(info->rtc_clk); + return 0; } static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) { + struct s3c_rtc *info = dev_get_drvdata(dev); unsigned int ticnt; - clk_enable(rtc_clk); - if (s3c_rtc_cpu_type == TYPE_S3C64XX) { - ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); + clk_enable(info->rtc_clk); + if (info->cpu_type == TYPE_S3C64XX) { + ticnt = readw(info->base + S3C2410_RTCCON); ticnt &= S3C64XX_RTCCON_TICEN; } else { - ticnt = readb(s3c_rtc_base + S3C2410_TICNT); + ticnt = readb(info->base + S3C2410_TICNT); ticnt &= S3C2410_TICNT_ENABLE; } seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); - clk_disable(rtc_clk); + clk_disable(info->rtc_clk); return 0; } @@ -368,63 +380,61 @@ static const struct rtc_class_ops s3c_rtcops = { .alarm_irq_enable = s3c_rtc_setaie, }; -static void s3c_rtc_enable(struct platform_device *pdev, int en) +static void s3c_rtc_enable(struct s3c_rtc *info, int en) { - void __iomem *base = s3c_rtc_base; unsigned int tmp; - if (s3c_rtc_base == NULL) - return; - - clk_enable(rtc_clk); + clk_enable(info->rtc_clk); if (!en) { - tmp = readw(base + S3C2410_RTCCON); - if (s3c_rtc_cpu_type == TYPE_S3C64XX) + tmp = readw(info->base + S3C2410_RTCCON); + if (info->cpu_type == TYPE_S3C64XX) tmp &= ~S3C64XX_RTCCON_TICEN; tmp &= ~S3C2410_RTCCON_RTCEN; - writew(tmp, base + S3C2410_RTCCON); + writew(tmp, info->base + S3C2410_RTCCON); - if (s3c_rtc_cpu_type != TYPE_S3C64XX) { - tmp = readb(base + S3C2410_TICNT); + if (info->cpu_type != TYPE_S3C64XX) { + tmp = readb(info->base + S3C2410_TICNT); tmp &= ~S3C2410_TICNT_ENABLE; - writeb(tmp, base + S3C2410_TICNT); + writeb(tmp, info->base + S3C2410_TICNT); } } else { /* re-enable the device, and check it is ok */ - if ((readw(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) { - dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); + if ((readw(info->base + S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) { + dev_info(info->dev, "rtc disabled, re-enabling\n"); - tmp = readw(base + S3C2410_RTCCON); + tmp = readw(info->base + S3C2410_RTCCON); writew(tmp | S3C2410_RTCCON_RTCEN, - base + S3C2410_RTCCON); + info->base + S3C2410_RTCCON); } - if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) { - dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); + if ((readw(info->base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) { + dev_info(info->dev, "removing RTCCON_CNTSEL\n"); - tmp = readw(base + S3C2410_RTCCON); + tmp = readw(info->base + S3C2410_RTCCON); writew(tmp & ~S3C2410_RTCCON_CNTSEL, - base + S3C2410_RTCCON); + info->base + S3C2410_RTCCON); } - if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) { - dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); + if ((readw(info->base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) { + dev_info(info->dev, "removing RTCCON_CLKRST\n"); - tmp = readw(base + S3C2410_RTCCON); + tmp = readw(info->base + S3C2410_RTCCON); writew(tmp & ~S3C2410_RTCCON_CLKRST, - base + S3C2410_RTCCON); + info->base + S3C2410_RTCCON); } } - clk_disable(rtc_clk); + clk_disable(info->rtc_clk); } -static int s3c_rtc_remove(struct platform_device *dev) +static int s3c_rtc_remove(struct platform_device *pdev) { - s3c_rtc_setaie(&dev->dev, 0); + struct s3c_rtc *info = platform_get_drvdata(pdev); + + s3c_rtc_setaie(info->dev, 0); - clk_unprepare(rtc_clk); - rtc_clk = NULL; + clk_unprepare(info->rtc_clk); + info->rtc_clk = NULL; return 0; } @@ -447,73 +457,85 @@ static inline int s3c_rtc_get_driver_data(struct platform_device *pdev) static int s3c_rtc_probe(struct platform_device *pdev) { - struct rtc_device *rtc; + struct s3c_rtc *info = NULL; struct rtc_time rtc_tm; struct resource *res; int ret; int tmp; - dev_dbg(&pdev->dev, "%s: probe=%p\n", __func__, pdev); + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; /* find the IRQs */ - - s3c_rtc_tickno = platform_get_irq(pdev, 1); - if (s3c_rtc_tickno < 0) { + info->irq_tick = platform_get_irq(pdev, 1); + if (info->irq_tick < 0) { dev_err(&pdev->dev, "no irq for rtc tick\n"); - return s3c_rtc_tickno; + return info->irq_tick; } - s3c_rtc_alarmno = platform_get_irq(pdev, 0); - if (s3c_rtc_alarmno < 0) { + info->dev = &pdev->dev; + info->cpu_type = s3c_rtc_get_driver_data(pdev); + spin_lock_init(&info->pie_lock); + spin_lock_init(&info->alarm_clk_lock); + + platform_set_drvdata(pdev, info); + + info->irq_alarm = platform_get_irq(pdev, 0); + if (info->irq_alarm < 0) { dev_err(&pdev->dev, "no irq for alarm\n"); - return s3c_rtc_alarmno; + return info->irq_alarm; } dev_dbg(&pdev->dev, "s3c2410_rtc: tick irq %d, alarm irq %d\n", - s3c_rtc_tickno, s3c_rtc_alarmno); + info->irq_tick, info->irq_alarm); /* get the memory region */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - s3c_rtc_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(s3c_rtc_base)) - return PTR_ERR(s3c_rtc_base); + info->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(info->base)) + return PTR_ERR(info->base); - rtc_clk = devm_clk_get(&pdev->dev, "rtc"); - if (IS_ERR(rtc_clk)) { + info->rtc_clk = devm_clk_get(&pdev->dev, "rtc"); + if (IS_ERR(info->rtc_clk)) { dev_err(&pdev->dev, "failed to find rtc clock source\n"); - ret = PTR_ERR(rtc_clk); - rtc_clk = NULL; - return ret; + return PTR_ERR(info->rtc_clk); } - - clk_prepare_enable(rtc_clk); + clk_prepare_enable(info->rtc_clk); /* check to see if everything is setup correctly */ - - s3c_rtc_enable(pdev, 1); + s3c_rtc_enable(info, 1); dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n", - readw(s3c_rtc_base + S3C2410_RTCCON)); + readw(info->base + S3C2410_RTCCON)); device_init_wakeup(&pdev->dev, 1); /* register RTC and exit */ - - rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops, + info->rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops, THIS_MODULE); - - if (IS_ERR(rtc)) { + if (IS_ERR(info->rtc)) { dev_err(&pdev->dev, "cannot attach rtc\n"); - ret = PTR_ERR(rtc); + ret = PTR_ERR(info->rtc); goto err_nortc; } - s3c_rtc_cpu_type = s3c_rtc_get_driver_data(pdev); + ret = devm_request_irq(&pdev->dev, info->irq_alarm, s3c_rtc_alarmirq, + 0, "s3c2410-rtc alarm", info); + if (ret) { + dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_alarm, ret); + goto err_nortc; + } - /* Check RTC Time */ + ret = devm_request_irq(&pdev->dev, info->irq_tick, s3c_rtc_tickirq, + 0, "s3c2410-rtc tick", info); + if (ret) { + dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_tick, ret); + goto err_nortc; + } - s3c_rtc_gettime(NULL, &rtc_tm); + /* Check RTC Time */ + s3c_rtc_gettime(&pdev->dev, &rtc_tm); if (rtc_valid_tm(&rtc_tm)) { rtc_tm.tm_year = 100; @@ -523,111 +545,90 @@ static int s3c_rtc_probe(struct platform_device *pdev) rtc_tm.tm_min = 0; rtc_tm.tm_sec = 0; - s3c_rtc_settime(NULL, &rtc_tm); + s3c_rtc_settime(&pdev->dev, &rtc_tm); dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); } - if (s3c_rtc_cpu_type != TYPE_S3C2410) - rtc->max_user_freq = 32768; + if (info->cpu_type != TYPE_S3C2410) + info->rtc->max_user_freq = 32768; else - rtc->max_user_freq = 128; + info->rtc->max_user_freq = 128; - if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) { - tmp = readw(s3c_rtc_base + S3C2410_RTCCON); + if (info->cpu_type == TYPE_S3C2416 || info->cpu_type == TYPE_S3C2443) { + tmp = readw(info->base + S3C2410_RTCCON); tmp |= S3C2443_RTCCON_TICSEL; - writew(tmp, s3c_rtc_base + S3C2410_RTCCON); - } - - platform_set_drvdata(pdev, rtc); - - s3c_rtc_setfreq(&pdev->dev, 1); - - ret = devm_request_irq(&pdev->dev, s3c_rtc_alarmno, s3c_rtc_alarmirq, - 0, "s3c2410-rtc alarm", rtc); - if (ret) { - dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); - goto err_nortc; + writew(tmp, info->base + S3C2410_RTCCON); } - ret = devm_request_irq(&pdev->dev, s3c_rtc_tickno, s3c_rtc_tickirq, - 0, "s3c2410-rtc tick", rtc); - if (ret) { - dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); - goto err_nortc; - } + s3c_rtc_setfreq(info, 1); - clk_disable(rtc_clk); + clk_disable(info->rtc_clk); return 0; err_nortc: - s3c_rtc_enable(pdev, 0); - clk_disable_unprepare(rtc_clk); + s3c_rtc_enable(info, 0); + clk_disable_unprepare(info->rtc_clk); return ret; } #ifdef CONFIG_PM_SLEEP -/* RTC Power management control */ - -static int ticnt_save, ticnt_en_save; -static bool wake_en; static int s3c_rtc_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); + struct s3c_rtc *info = dev_get_drvdata(dev); - clk_enable(rtc_clk); + clk_enable(info->rtc_clk); /* save TICNT for anyone using periodic interrupts */ - if (s3c_rtc_cpu_type == TYPE_S3C64XX) { - ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON); - ticnt_en_save &= S3C64XX_RTCCON_TICEN; - ticnt_save = readl(s3c_rtc_base + S3C2410_TICNT); + if (info->cpu_type == TYPE_S3C64XX) { + info->ticnt_en_save = readw(info->base + S3C2410_RTCCON); + info->ticnt_en_save &= S3C64XX_RTCCON_TICEN; + info->ticnt_save = readl(info->base + S3C2410_TICNT); } else { - ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); + info->ticnt_save = readb(info->base + S3C2410_TICNT); } - s3c_rtc_enable(pdev, 0); + s3c_rtc_enable(info, 0); - if (device_may_wakeup(dev) && !wake_en) { - if (enable_irq_wake(s3c_rtc_alarmno) == 0) - wake_en = true; + if (device_may_wakeup(dev) && !info->wake_en) { + if (enable_irq_wake(info->irq_alarm) == 0) + info->wake_en = true; else dev_err(dev, "enable_irq_wake failed\n"); } - clk_disable(rtc_clk); + clk_disable(info->rtc_clk); return 0; } static int s3c_rtc_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); + struct s3c_rtc *info = dev_get_drvdata(dev); unsigned int tmp; - clk_enable(rtc_clk); - s3c_rtc_enable(pdev, 1); - if (s3c_rtc_cpu_type == TYPE_S3C64XX) { - writel(ticnt_save, s3c_rtc_base + S3C2410_TICNT); - if (ticnt_en_save) { - tmp = readw(s3c_rtc_base + S3C2410_RTCCON); - writew(tmp | ticnt_en_save, - s3c_rtc_base + S3C2410_RTCCON); + clk_enable(info->rtc_clk); + s3c_rtc_enable(info, 1); + if (info->cpu_type == TYPE_S3C64XX) { + writel(info->ticnt_save, info->base + S3C2410_TICNT); + if (info->ticnt_en_save) { + tmp = readw(info->base + S3C2410_RTCCON); + writew(tmp | info->ticnt_en_save, + info->base + S3C2410_RTCCON); } } else { - writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); + writeb(info->ticnt_save, info->base + S3C2410_TICNT); } - if (device_may_wakeup(dev) && wake_en) { - disable_irq_wake(s3c_rtc_alarmno); - wake_en = false; + if (device_may_wakeup(dev) && info->wake_en) { + disable_irq_wake(info->irq_alarm); + info->wake_en = false; } - clk_disable(rtc_clk); + clk_disable(info->rtc_clk); return 0; } #endif - static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume); #ifdef CONFIG_OF -- cgit v1.2.3 From d67288da51b782f54dd3ae1455b997131160fd41 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 13 Oct 2014 15:52:31 -0700 Subject: rtc: s3c: remove warning message when checking coding style with checkpatch script Remove warning message when checking codeing style with checkpatch script and reduce un-necessary i2c read operation on s3c_rtc_enable. WARNING: line over 80 characters #406: FILE: drivers/rtc/rtc-s3c.c:406: + if ((readw(info->base + S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) { WARNING: line over 80 characters #414: FILE: drivers/rtc/rtc-s3c.c:414: + if ((readw(info->base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) { WARNING: line over 80 characters #422: FILE: drivers/rtc/rtc-s3c.c:422: + if ((readw(info->base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) { WARNING: Missing a blank line after declarations #451: FILE: drivers/rtc/rtc-s3c.c:451: + struct s3c_rtc_drv_data *data; + if (pdev->dev.of_node) { WARNING: Missing a blank line after declarations #453: FILE: drivers/rtc/rtc-s3c.c:453: + const struct of_device_id *match; + match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node); WARNING: DT compatible string "samsung,s3c2416-rtc" appears un-documented -- check ./Documentation/devicetree/bindings/ #650: FILE: drivers/rtc/rtc-s3c.c:650: + .compatible = "samsung,s3c2416-rtc", WARNING: DT compatible string "samsung,s3c2443-rtc" appears un-documented -- check ./Documentation/devicetree/bindings/ #653: FILE: drivers/rtc/rtc-s3c.c:653: + .compatible = "samsung,s3c2443-rtc", Signed-off-by: Chanwoo Choi Acked-by: Kyungmin Park Cc: Alessandro Zummo Cc: Kukjin Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s3c.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 2f71b13c00d6..4e95cca7615c 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -382,25 +382,25 @@ static const struct rtc_class_ops s3c_rtcops = { static void s3c_rtc_enable(struct s3c_rtc *info, int en) { - unsigned int tmp; + unsigned int con, tmp; clk_enable(info->rtc_clk); + + con = readw(info->base + S3C2410_RTCCON); if (!en) { - tmp = readw(info->base + S3C2410_RTCCON); if (info->cpu_type == TYPE_S3C64XX) - tmp &= ~S3C64XX_RTCCON_TICEN; - tmp &= ~S3C2410_RTCCON_RTCEN; - writew(tmp, info->base + S3C2410_RTCCON); + con &= ~S3C64XX_RTCCON_TICEN; + con &= ~S3C2410_RTCCON_RTCEN; + writew(con, info->base + S3C2410_RTCCON); if (info->cpu_type != TYPE_S3C64XX) { - tmp = readb(info->base + S3C2410_TICNT); - tmp &= ~S3C2410_TICNT_ENABLE; - writeb(tmp, info->base + S3C2410_TICNT); + con = readb(info->base + S3C2410_TICNT); + con &= ~S3C2410_TICNT_ENABLE; + writeb(con, info->base + S3C2410_TICNT); } } else { /* re-enable the device, and check it is ok */ - - if ((readw(info->base + S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) { + if ((con & S3C2410_RTCCON_RTCEN) == 0) { dev_info(info->dev, "rtc disabled, re-enabling\n"); tmp = readw(info->base + S3C2410_RTCCON); @@ -408,7 +408,7 @@ static void s3c_rtc_enable(struct s3c_rtc *info, int en) info->base + S3C2410_RTCCON); } - if ((readw(info->base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) { + if (con & S3C2410_RTCCON_CNTSEL) { dev_info(info->dev, "removing RTCCON_CNTSEL\n"); tmp = readw(info->base + S3C2410_RTCCON); @@ -416,7 +416,7 @@ static void s3c_rtc_enable(struct s3c_rtc *info, int en) info->base + S3C2410_RTCCON); } - if ((readw(info->base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) { + if (con & S3C2410_RTCCON_CLKRST) { dev_info(info->dev, "removing RTCCON_CLKRST\n"); tmp = readw(info->base + S3C2410_RTCCON); @@ -445,8 +445,10 @@ static inline int s3c_rtc_get_driver_data(struct platform_device *pdev) { #ifdef CONFIG_OF struct s3c_rtc_drv_data *data; + if (pdev->dev.of_node) { const struct of_device_id *match; + match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node); data = (struct s3c_rtc_drv_data *) match->data; return data->cpu_type; -- cgit v1.2.3 From ae05c95074e0ead8a8fda4aca066e10270086e3f Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 13 Oct 2014 15:52:33 -0700 Subject: rtc: s3c: add s3c_rtc_data structure to use variant data instead of s3c_cpu_type Add s3c_rtc_data structure to variant data according to SoC type. The s3c_rtc_data structure includes some functions to control RTC operation and specific data dependent on SoC type. Signed-off-by: Chanwoo Choi Acked-by: Kyungmin Park Cc: Alessandro Zummo Cc: Kukjin Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s3c.c | 461 +++++++++++++++++++++++++++++++------------------- 1 file changed, 289 insertions(+), 172 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 4e95cca7615c..0d9089228bb0 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -32,17 +32,6 @@ #include #include "rtc-s3c.h" -enum s3c_cpu_type { - TYPE_S3C2410, - TYPE_S3C2416, - TYPE_S3C2443, - TYPE_S3C64XX, -}; - -struct s3c_rtc_drv_data { - int cpu_type; -}; - struct s3c_rtc { struct device *dev; struct rtc_device *rtc; @@ -51,7 +40,7 @@ struct s3c_rtc { struct clk *rtc_clk; bool enabled; - enum s3c_cpu_type cpu_type; + struct s3c_rtc_data *data; int irq_alarm; int irq_tick; @@ -63,6 +52,19 @@ struct s3c_rtc { bool wake_en; }; +struct s3c_rtc_data { + int max_user_freq; + + void (*irq_handler) (struct s3c_rtc *info, int mask); + void (*set_freq) (struct s3c_rtc *info, int freq); + void (*enable_tick) (struct s3c_rtc *info, struct seq_file *seq); + void (*select_tick_clk) (struct s3c_rtc *info); + void (*save_tick_cnt) (struct s3c_rtc *info); + void (*restore_tick_cnt) (struct s3c_rtc *info); + void (*enable) (struct s3c_rtc *info); + void (*disable) (struct s3c_rtc *info); +}; + static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable) { unsigned long irq_flags; @@ -83,34 +85,22 @@ static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable) } /* IRQ Handlers */ -static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) +static irqreturn_t s3c_rtc_tickirq(int irq, void *id) { struct s3c_rtc *info = (struct s3c_rtc *)id; - clk_enable(info->rtc_clk); - rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); - - if (info->cpu_type == TYPE_S3C64XX) - writeb(S3C2410_INTP_ALM, info->base + S3C2410_INTP); - - clk_disable(info->rtc_clk); - - s3c_rtc_alarm_clk_enable(info, false); + if (info->data->irq_handler) + info->data->irq_handler(info, S3C2410_INTP_TIC); return IRQ_HANDLED; } -static irqreturn_t s3c_rtc_tickirq(int irq, void *id) +static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) { struct s3c_rtc *info = (struct s3c_rtc *)id; - clk_enable(info->rtc_clk); - rtc_update_irq(info->rtc, 1, RTC_PF | RTC_IRQF); - - if (info->cpu_type == TYPE_S3C64XX) - writeb(S3C2410_INTP_TIC, info->base + S3C2410_INTP); - - clk_disable(info->rtc_clk); + if (info->data->irq_handler) + info->data->irq_handler(info, S3C2410_INTP_ALM); return IRQ_HANDLED; } @@ -137,36 +127,18 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled) return 0; } +/* Set RTC frequency */ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) { - unsigned int tmp = 0; - int val; - if (!is_power_of_2(freq)) return -EINVAL; clk_enable(info->rtc_clk); spin_lock_irq(&info->pie_lock); - if (info->cpu_type != TYPE_S3C64XX) { - tmp = readb(info->base + S3C2410_TICNT); - tmp &= S3C2410_TICNT_ENABLE; - } - - val = (info->rtc->max_user_freq / freq) - 1; - - if (info->cpu_type == TYPE_S3C2416 || info->cpu_type == TYPE_S3C2443) { - tmp |= S3C2443_TICNT_PART(val); - writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1); + if (info->data->set_freq) + info->data->set_freq(info, freq); - if (info->cpu_type == TYPE_S3C2416) - writel(S3C2416_TICNT2_PART(val), - info->base + S3C2416_TICNT2); - } else { - tmp |= val; - } - - writel(tmp, info->base + S3C2410_TICNT); spin_unlock_irq(&info->pie_lock); clk_disable(info->rtc_clk); @@ -174,7 +146,6 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) } /* Time read/write */ - static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) { struct s3c_rtc *info = dev_get_drvdata(dev); @@ -355,19 +326,14 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) { struct s3c_rtc *info = dev_get_drvdata(dev); - unsigned int ticnt; clk_enable(info->rtc_clk); - if (info->cpu_type == TYPE_S3C64XX) { - ticnt = readw(info->base + S3C2410_RTCCON); - ticnt &= S3C64XX_RTCCON_TICEN; - } else { - ticnt = readb(info->base + S3C2410_TICNT); - ticnt &= S3C2410_TICNT_ENABLE; - } - seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); + if (info->data->enable_tick) + info->data->enable_tick(info, seq); + clk_disable(info->rtc_clk); + return 0; } @@ -380,50 +346,69 @@ static const struct rtc_class_ops s3c_rtcops = { .alarm_irq_enable = s3c_rtc_setaie, }; -static void s3c_rtc_enable(struct s3c_rtc *info, int en) +static void s3c24xx_rtc_enable(struct s3c_rtc *info) { unsigned int con, tmp; clk_enable(info->rtc_clk); con = readw(info->base + S3C2410_RTCCON); - if (!en) { - if (info->cpu_type == TYPE_S3C64XX) - con &= ~S3C64XX_RTCCON_TICEN; - con &= ~S3C2410_RTCCON_RTCEN; - writew(con, info->base + S3C2410_RTCCON); - - if (info->cpu_type != TYPE_S3C64XX) { - con = readb(info->base + S3C2410_TICNT); - con &= ~S3C2410_TICNT_ENABLE; - writeb(con, info->base + S3C2410_TICNT); - } - } else { - /* re-enable the device, and check it is ok */ - if ((con & S3C2410_RTCCON_RTCEN) == 0) { - dev_info(info->dev, "rtc disabled, re-enabling\n"); + /* re-enable the device, and check it is ok */ + if ((con & S3C2410_RTCCON_RTCEN) == 0) { + dev_info(info->dev, "rtc disabled, re-enabling\n"); - tmp = readw(info->base + S3C2410_RTCCON); - writew(tmp | S3C2410_RTCCON_RTCEN, - info->base + S3C2410_RTCCON); - } + tmp = readw(info->base + S3C2410_RTCCON); + writew(tmp | S3C2410_RTCCON_RTCEN, + info->base + S3C2410_RTCCON); + } - if (con & S3C2410_RTCCON_CNTSEL) { - dev_info(info->dev, "removing RTCCON_CNTSEL\n"); + if (con & S3C2410_RTCCON_CNTSEL) { + dev_info(info->dev, "removing RTCCON_CNTSEL\n"); - tmp = readw(info->base + S3C2410_RTCCON); - writew(tmp & ~S3C2410_RTCCON_CNTSEL, - info->base + S3C2410_RTCCON); - } + tmp = readw(info->base + S3C2410_RTCCON); + writew(tmp & ~S3C2410_RTCCON_CNTSEL, + info->base + S3C2410_RTCCON); + } - if (con & S3C2410_RTCCON_CLKRST) { - dev_info(info->dev, "removing RTCCON_CLKRST\n"); + if (con & S3C2410_RTCCON_CLKRST) { + dev_info(info->dev, "removing RTCCON_CLKRST\n"); - tmp = readw(info->base + S3C2410_RTCCON); - writew(tmp & ~S3C2410_RTCCON_CLKRST, - info->base + S3C2410_RTCCON); - } + tmp = readw(info->base + S3C2410_RTCCON); + writew(tmp & ~S3C2410_RTCCON_CLKRST, + info->base + S3C2410_RTCCON); } + + clk_disable(info->rtc_clk); +} + +static void s3c24xx_rtc_disable(struct s3c_rtc *info) +{ + unsigned int con; + + clk_enable(info->rtc_clk); + + con = readw(info->base + S3C2410_RTCCON); + con &= ~S3C2410_RTCCON_RTCEN; + writew(con, info->base + S3C2410_RTCCON); + + con = readb(info->base + S3C2410_TICNT); + con &= ~S3C2410_TICNT_ENABLE; + writeb(con, info->base + S3C2410_TICNT); + + clk_disable(info->rtc_clk); +} + +static void s3c6410_rtc_disable(struct s3c_rtc *info) +{ + unsigned int con; + + clk_enable(info->rtc_clk); + + con = readw(info->base + S3C2410_RTCCON); + con &= ~S3C64XX_RTCCON_TICEN; + con &= ~S3C2410_RTCCON_RTCEN; + writew(con, info->base + S3C2410_RTCCON); + clk_disable(info->rtc_clk); } @@ -441,20 +426,12 @@ static int s3c_rtc_remove(struct platform_device *pdev) static const struct of_device_id s3c_rtc_dt_match[]; -static inline int s3c_rtc_get_driver_data(struct platform_device *pdev) +static struct s3c_rtc_data *s3c_rtc_get_data(struct platform_device *pdev) { -#ifdef CONFIG_OF - struct s3c_rtc_drv_data *data; + const struct of_device_id *match; - if (pdev->dev.of_node) { - const struct of_device_id *match; - - match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node); - data = (struct s3c_rtc_drv_data *) match->data; - return data->cpu_type; - } -#endif - return platform_get_device_id(pdev)->driver_data; + match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node); + return (struct s3c_rtc_data *)match->data; } static int s3c_rtc_probe(struct platform_device *pdev) @@ -463,7 +440,6 @@ static int s3c_rtc_probe(struct platform_device *pdev) struct rtc_time rtc_tm; struct resource *res; int ret; - int tmp; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) @@ -477,7 +453,11 @@ static int s3c_rtc_probe(struct platform_device *pdev) } info->dev = &pdev->dev; - info->cpu_type = s3c_rtc_get_driver_data(pdev); + info->data = s3c_rtc_get_data(pdev); + if (!info->data) { + dev_err(&pdev->dev, "failed getting s3c_rtc_data\n"); + return -EINVAL; + } spin_lock_init(&info->pie_lock); spin_lock_init(&info->alarm_clk_lock); @@ -506,7 +486,8 @@ static int s3c_rtc_probe(struct platform_device *pdev) clk_prepare_enable(info->rtc_clk); /* check to see if everything is setup correctly */ - s3c_rtc_enable(info, 1); + if (info->data->enable) + info->data->enable(info); dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n", readw(info->base + S3C2410_RTCCON)); @@ -552,16 +533,8 @@ static int s3c_rtc_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); } - if (info->cpu_type != TYPE_S3C2410) - info->rtc->max_user_freq = 32768; - else - info->rtc->max_user_freq = 128; - - if (info->cpu_type == TYPE_S3C2416 || info->cpu_type == TYPE_S3C2443) { - tmp = readw(info->base + S3C2410_RTCCON); - tmp |= S3C2443_RTCCON_TICSEL; - writew(tmp, info->base + S3C2410_RTCCON); - } + if (info->data->select_tick_clk) + info->data->select_tick_clk(info); s3c_rtc_setfreq(info, 1); @@ -570,7 +543,8 @@ static int s3c_rtc_probe(struct platform_device *pdev) return 0; err_nortc: - s3c_rtc_enable(info, 0); + if (info->data->disable) + info->data->disable(info); clk_disable_unprepare(info->rtc_clk); return ret; @@ -583,15 +557,13 @@ static int s3c_rtc_suspend(struct device *dev) struct s3c_rtc *info = dev_get_drvdata(dev); clk_enable(info->rtc_clk); + /* save TICNT for anyone using periodic interrupts */ - if (info->cpu_type == TYPE_S3C64XX) { - info->ticnt_en_save = readw(info->base + S3C2410_RTCCON); - info->ticnt_en_save &= S3C64XX_RTCCON_TICEN; - info->ticnt_save = readl(info->base + S3C2410_TICNT); - } else { - info->ticnt_save = readb(info->base + S3C2410_TICNT); - } - s3c_rtc_enable(info, 0); + if (info->data->save_tick_cnt) + info->data->save_tick_cnt(info); + + if (info->data->disable) + info->data->disable(info); if (device_may_wakeup(dev) && !info->wake_en) { if (enable_irq_wake(info->irq_alarm) == 0) @@ -599,6 +571,7 @@ static int s3c_rtc_suspend(struct device *dev) else dev_err(dev, "enable_irq_wake failed\n"); } + clk_disable(info->rtc_clk); return 0; @@ -607,25 +580,20 @@ static int s3c_rtc_suspend(struct device *dev) static int s3c_rtc_resume(struct device *dev) { struct s3c_rtc *info = dev_get_drvdata(dev); - unsigned int tmp; clk_enable(info->rtc_clk); - s3c_rtc_enable(info, 1); - if (info->cpu_type == TYPE_S3C64XX) { - writel(info->ticnt_save, info->base + S3C2410_TICNT); - if (info->ticnt_en_save) { - tmp = readw(info->base + S3C2410_RTCCON); - writew(tmp | info->ticnt_en_save, - info->base + S3C2410_RTCCON); - } - } else { - writeb(info->ticnt_save, info->base + S3C2410_TICNT); - } + + if (info->data->enable) + info->data->enable(info); + + if (info->data->restore_tick_cnt) + info->data->restore_tick_cnt(info); if (device_may_wakeup(dev) && info->wake_en) { disable_irq_wake(info->irq_alarm); info->wake_en = false; } + clk_disable(info->rtc_clk); return 0; @@ -633,56 +601,206 @@ static int s3c_rtc_resume(struct device *dev) #endif static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume); -#ifdef CONFIG_OF -static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = { - [TYPE_S3C2410] = { TYPE_S3C2410 }, - [TYPE_S3C2416] = { TYPE_S3C2416 }, - [TYPE_S3C2443] = { TYPE_S3C2443 }, - [TYPE_S3C64XX] = { TYPE_S3C64XX }, +static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask) +{ + clk_enable(info->rtc_clk); + rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); + clk_disable(info->rtc_clk); + + s3c_rtc_alarm_clk_enable(info, false); +} + +static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask) +{ + clk_enable(info->rtc_clk); + rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); + writeb(mask, info->base + S3C2410_INTP); + clk_disable(info->rtc_clk); + + s3c_rtc_alarm_clk_enable(info, false); +} + +static void s3c2410_rtc_setfreq(struct s3c_rtc *info, int freq) +{ + unsigned int tmp = 0; + int val; + + tmp = readb(info->base + S3C2410_TICNT); + tmp &= S3C2410_TICNT_ENABLE; + + val = (info->rtc->max_user_freq / freq) - 1; + tmp |= val; + + writel(tmp, info->base + S3C2410_TICNT); +} + +static void s3c2416_rtc_setfreq(struct s3c_rtc *info, int freq) +{ + unsigned int tmp = 0; + int val; + + tmp = readb(info->base + S3C2410_TICNT); + tmp &= S3C2410_TICNT_ENABLE; + + val = (info->rtc->max_user_freq / freq) - 1; + + tmp |= S3C2443_TICNT_PART(val); + writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1); + + writel(S3C2416_TICNT2_PART(val), info->base + S3C2416_TICNT2); + + writel(tmp, info->base + S3C2410_TICNT); +} + +static void s3c2443_rtc_setfreq(struct s3c_rtc *info, int freq) +{ + unsigned int tmp = 0; + int val; + + tmp = readb(info->base + S3C2410_TICNT); + tmp &= S3C2410_TICNT_ENABLE; + + val = (info->rtc->max_user_freq / freq) - 1; + + tmp |= S3C2443_TICNT_PART(val); + writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1); + + writel(tmp, info->base + S3C2410_TICNT); +} + +static void s3c6410_rtc_setfreq(struct s3c_rtc *info, int freq) +{ + int val; + + val = (info->rtc->max_user_freq / freq) - 1; + writel(val, info->base + S3C2410_TICNT); +} + +static void s3c24xx_rtc_enable_tick(struct s3c_rtc *info, struct seq_file *seq) +{ + unsigned int ticnt; + + ticnt = readb(info->base + S3C2410_TICNT); + ticnt &= S3C2410_TICNT_ENABLE; + + seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); +} + +static void s3c2416_rtc_select_tick_clk(struct s3c_rtc *info) +{ + unsigned int con; + + con = readw(info->base + S3C2410_RTCCON); + con |= S3C2443_RTCCON_TICSEL; + writew(con, info->base + S3C2410_RTCCON); +} + +static void s3c6410_rtc_enable_tick(struct s3c_rtc *info, struct seq_file *seq) +{ + unsigned int ticnt; + + ticnt = readw(info->base + S3C2410_RTCCON); + ticnt &= S3C64XX_RTCCON_TICEN; + + seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); +} + +static void s3c24xx_rtc_save_tick_cnt(struct s3c_rtc *info) +{ + info->ticnt_save = readb(info->base + S3C2410_TICNT); +} + +static void s3c24xx_rtc_restore_tick_cnt(struct s3c_rtc *info) +{ + writeb(info->ticnt_save, info->base + S3C2410_TICNT); +} + +static void s3c6410_rtc_save_tick_cnt(struct s3c_rtc *info) +{ + info->ticnt_en_save = readw(info->base + S3C2410_RTCCON); + info->ticnt_en_save &= S3C64XX_RTCCON_TICEN; + info->ticnt_save = readl(info->base + S3C2410_TICNT); +} + +static void s3c6410_rtc_restore_tick_cnt(struct s3c_rtc *info) +{ + unsigned int con; + + writel(info->ticnt_save, info->base + S3C2410_TICNT); + if (info->ticnt_en_save) { + con = readw(info->base + S3C2410_RTCCON); + writew(con | info->ticnt_en_save, + info->base + S3C2410_RTCCON); + } +} + +static struct s3c_rtc_data const s3c2410_rtc_data = { + .max_user_freq = 128, + .irq_handler = s3c24xx_rtc_irq, + .set_freq = s3c2410_rtc_setfreq, + .enable_tick = s3c24xx_rtc_enable_tick, + .save_tick_cnt = s3c24xx_rtc_save_tick_cnt, + .restore_tick_cnt = s3c24xx_rtc_restore_tick_cnt, + .enable = s3c24xx_rtc_enable, + .disable = s3c24xx_rtc_disable, +}; + +static struct s3c_rtc_data const s3c2416_rtc_data = { + .max_user_freq = 32768, + .irq_handler = s3c24xx_rtc_irq, + .set_freq = s3c2416_rtc_setfreq, + .enable_tick = s3c24xx_rtc_enable_tick, + .select_tick_clk = s3c2416_rtc_select_tick_clk, + .save_tick_cnt = s3c24xx_rtc_save_tick_cnt, + .restore_tick_cnt = s3c24xx_rtc_restore_tick_cnt, + .enable = s3c24xx_rtc_enable, + .disable = s3c24xx_rtc_disable, +}; + +static struct s3c_rtc_data const s3c2443_rtc_data = { + .max_user_freq = 32768, + .irq_handler = s3c24xx_rtc_irq, + .set_freq = s3c2443_rtc_setfreq, + .enable_tick = s3c24xx_rtc_enable_tick, + .select_tick_clk = s3c2416_rtc_select_tick_clk, + .save_tick_cnt = s3c24xx_rtc_save_tick_cnt, + .restore_tick_cnt = s3c24xx_rtc_restore_tick_cnt, + .enable = s3c24xx_rtc_enable, + .disable = s3c24xx_rtc_disable, +}; + +static struct s3c_rtc_data const s3c6410_rtc_data = { + .max_user_freq = 32768, + .irq_handler = s3c6410_rtc_irq, + .set_freq = s3c6410_rtc_setfreq, + .enable_tick = s3c6410_rtc_enable_tick, + .save_tick_cnt = s3c6410_rtc_save_tick_cnt, + .restore_tick_cnt = s3c6410_rtc_restore_tick_cnt, + .enable = s3c24xx_rtc_enable, + .disable = s3c6410_rtc_disable, }; static const struct of_device_id s3c_rtc_dt_match[] = { { .compatible = "samsung,s3c2410-rtc", - .data = &s3c_rtc_drv_data_array[TYPE_S3C2410], + .data = (void *)&s3c2410_rtc_data, }, { .compatible = "samsung,s3c2416-rtc", - .data = &s3c_rtc_drv_data_array[TYPE_S3C2416], + .data = (void *)&s3c2416_rtc_data, }, { .compatible = "samsung,s3c2443-rtc", - .data = &s3c_rtc_drv_data_array[TYPE_S3C2443], + .data = (void *)&s3c2443_rtc_data, }, { .compatible = "samsung,s3c6410-rtc", - .data = &s3c_rtc_drv_data_array[TYPE_S3C64XX], + .data = (void *)&s3c6410_rtc_data, }, - {}, + { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match); -#endif - -static struct platform_device_id s3c_rtc_driver_ids[] = { - { - .name = "s3c2410-rtc", - .driver_data = TYPE_S3C2410, - }, { - .name = "s3c2416-rtc", - .driver_data = TYPE_S3C2416, - }, { - .name = "s3c2443-rtc", - .driver_data = TYPE_S3C2443, - }, { - .name = "s3c64xx-rtc", - .driver_data = TYPE_S3C64XX, - }, - { } -}; - -MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids); static struct platform_driver s3c_rtc_driver = { .probe = s3c_rtc_probe, .remove = s3c_rtc_remove, - .id_table = s3c_rtc_driver_ids, .driver = { .name = "s3c-rtc", .owner = THIS_MODULE, @@ -690,7 +808,6 @@ static struct platform_driver s3c_rtc_driver = { .of_match_table = of_match_ptr(s3c_rtc_dt_match), }, }; - module_platform_driver(s3c_rtc_driver); MODULE_DESCRIPTION("Samsung S3C RTC Driver"); -- cgit v1.2.3 From df9e26d093d33a097c5558aab017dd2f540ccfe5 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 13 Oct 2014 15:52:35 -0700 Subject: rtc: s3c: add support for RTC of Exynos3250 SoC Add support for RTC of Exynos3250 SoC. The Exynos3250 needs source clock(32.768KHz) for RTC block. If source clock of RTC is registerd on clock list of common clk framework, Exynos RTC drvier have to control this clock. Clock list for s3c-rtc device: - rtc : CLK_RTC of CLK_GATE_IP_PERIR is gate clock for RTC. - rtc_src : XrtcXTI is 32.768.kHz source clock for RTC. (XRTCXTI: Specifies a clock from 32.768 kHz crystal pad with XRTCXTI and XRTCXTO pins. RTC uses this clock as the source of a real-time clock.) Signed-off-by: Chanwoo Choi Acked-by: Kyungmin Park Cc: Alessandro Zummo Cc: Kukjin Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s3c.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 0d9089228bb0..a6b1252c9941 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -38,6 +38,7 @@ struct s3c_rtc { void __iomem *base; struct clk *rtc_clk; + struct clk *rtc_src_clk; bool enabled; struct s3c_rtc_data *data; @@ -54,6 +55,7 @@ struct s3c_rtc { struct s3c_rtc_data { int max_user_freq; + bool needs_src_clk; void (*irq_handler) (struct s3c_rtc *info, int mask); void (*set_freq) (struct s3c_rtc *info, int freq); @@ -73,10 +75,14 @@ static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable) if (enable) { if (!info->enabled) { clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); info->enabled = true; } } else { if (info->enabled) { + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); info->enabled = false; } @@ -114,12 +120,16 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled) dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled); clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; if (enabled) tmp |= S3C2410_RTCALM_ALMEN; writeb(tmp, info->base + S3C2410_RTCALM); + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); s3c_rtc_alarm_clk_enable(info, enabled); @@ -134,12 +144,16 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) return -EINVAL; clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); spin_lock_irq(&info->pie_lock); if (info->data->set_freq) info->data->set_freq(info, freq); spin_unlock_irq(&info->pie_lock); + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); return 0; @@ -152,6 +166,9 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) unsigned int have_retried = 0; clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); + retry_get_time: rtc_tm->tm_min = readb(info->base + S3C2410_RTCMIN); rtc_tm->tm_hour = readb(info->base + S3C2410_RTCHOUR); @@ -185,6 +202,8 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_mon -= 1; + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); return rtc_valid_tm(rtc_tm); @@ -207,6 +226,8 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) } clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_RTCSEC); writeb(bin2bcd(tm->tm_min), info->base + S3C2410_RTCMIN); @@ -215,6 +236,8 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON); writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR); + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); return 0; @@ -227,6 +250,9 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) unsigned int alm_en; clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); + alm_tm->tm_sec = readb(info->base + S3C2410_ALMSEC); alm_tm->tm_min = readb(info->base + S3C2410_ALMMIN); alm_tm->tm_hour = readb(info->base + S3C2410_ALMHOUR); @@ -278,7 +304,10 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) else alm_tm->tm_year = -1; + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); + return 0; } @@ -289,6 +318,9 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) unsigned int alrm_en; clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); + dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", alrm->enabled, 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, @@ -318,6 +350,8 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) s3c_rtc_setaie(dev, alrm->enabled); + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); return 0; @@ -328,10 +362,14 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) struct s3c_rtc *info = dev_get_drvdata(dev); clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); if (info->data->enable_tick) info->data->enable_tick(info, seq); + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); return 0; @@ -351,6 +389,8 @@ static void s3c24xx_rtc_enable(struct s3c_rtc *info) unsigned int con, tmp; clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); con = readw(info->base + S3C2410_RTCCON); /* re-enable the device, and check it is ok */ @@ -378,6 +418,8 @@ static void s3c24xx_rtc_enable(struct s3c_rtc *info) info->base + S3C2410_RTCCON); } + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); } @@ -386,6 +428,8 @@ static void s3c24xx_rtc_disable(struct s3c_rtc *info) unsigned int con; clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); con = readw(info->base + S3C2410_RTCCON); con &= ~S3C2410_RTCCON_RTCEN; @@ -395,6 +439,8 @@ static void s3c24xx_rtc_disable(struct s3c_rtc *info) con &= ~S3C2410_TICNT_ENABLE; writeb(con, info->base + S3C2410_TICNT); + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); } @@ -403,12 +449,16 @@ static void s3c6410_rtc_disable(struct s3c_rtc *info) unsigned int con; clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); con = readw(info->base + S3C2410_RTCCON); con &= ~S3C64XX_RTCCON_TICEN; con &= ~S3C2410_RTCCON_RTCEN; writew(con, info->base + S3C2410_RTCCON); + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); } @@ -480,11 +530,19 @@ static int s3c_rtc_probe(struct platform_device *pdev) info->rtc_clk = devm_clk_get(&pdev->dev, "rtc"); if (IS_ERR(info->rtc_clk)) { - dev_err(&pdev->dev, "failed to find rtc clock source\n"); + dev_err(&pdev->dev, "failed to find rtc clock\n"); return PTR_ERR(info->rtc_clk); } clk_prepare_enable(info->rtc_clk); + info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src"); + if (IS_ERR(info->rtc_src_clk)) { + dev_err(&pdev->dev, "failed to find rtc source clock\n"); + return PTR_ERR(info->rtc_src_clk); + } + clk_prepare_enable(info->rtc_src_clk); + + /* check to see if everything is setup correctly */ if (info->data->enable) info->data->enable(info); @@ -538,6 +596,8 @@ static int s3c_rtc_probe(struct platform_device *pdev) s3c_rtc_setfreq(info, 1); + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); return 0; @@ -557,6 +617,8 @@ static int s3c_rtc_suspend(struct device *dev) struct s3c_rtc *info = dev_get_drvdata(dev); clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); /* save TICNT for anyone using periodic interrupts */ if (info->data->save_tick_cnt) @@ -572,6 +634,8 @@ static int s3c_rtc_suspend(struct device *dev) dev_err(dev, "enable_irq_wake failed\n"); } + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); return 0; @@ -582,6 +646,8 @@ static int s3c_rtc_resume(struct device *dev) struct s3c_rtc *info = dev_get_drvdata(dev); clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); if (info->data->enable) info->data->enable(info); @@ -594,6 +660,8 @@ static int s3c_rtc_resume(struct device *dev) info->wake_en = false; } + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); return 0; @@ -604,7 +672,11 @@ static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume); static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask) { clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); s3c_rtc_alarm_clk_enable(info, false); @@ -613,8 +685,12 @@ static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask) static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask) { clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); writeb(mask, info->base + S3C2410_INTP); + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); clk_disable(info->rtc_clk); s3c_rtc_alarm_clk_enable(info, false); @@ -780,6 +856,18 @@ static struct s3c_rtc_data const s3c6410_rtc_data = { .disable = s3c6410_rtc_disable, }; +static struct s3c_rtc_data const exynos3250_rtc_data = { + .max_user_freq = 32768, + .needs_src_clk = true, + .irq_handler = s3c6410_rtc_irq, + .set_freq = s3c6410_rtc_setfreq, + .enable_tick = s3c6410_rtc_enable_tick, + .save_tick_cnt = s3c6410_rtc_save_tick_cnt, + .restore_tick_cnt = s3c6410_rtc_restore_tick_cnt, + .enable = s3c24xx_rtc_enable, + .disable = s3c6410_rtc_disable, +}; + static const struct of_device_id s3c_rtc_dt_match[] = { { .compatible = "samsung,s3c2410-rtc", @@ -793,6 +881,9 @@ static const struct of_device_id s3c_rtc_dt_match[] = { }, { .compatible = "samsung,s3c6410-rtc", .data = (void *)&s3c6410_rtc_data, + }, { + .compatible = "samsung,exynos3250-rtc", + .data = (void *)&exynos3250_rtc_data, }, { /* sentinel */ }, }; -- cgit v1.2.3 From a28885bc75da0aac61b975eb9c103407dbdf5cb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 13 Oct 2014 15:52:39 -0700 Subject: rtc: make of_device_ids const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit of_device_ids (i.e. compatible strings and the respective data) are not supposed to change at runtime. All functions working with of_device_ids provided by work with const of_device_ids. This allows to mark all struct of_device_id below drivers/rtc const, too. Signed-off-by: Uwe Kleine-König Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-isl12022.c | 2 +- drivers/rtc/rtc-mpc5121.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index aa55f081c505..ee3ba7e6b45e 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -274,7 +274,7 @@ static int isl12022_probe(struct i2c_client *client, } #ifdef CONFIG_OF -static struct of_device_id isl12022_dt_match[] = { +static const struct of_device_id isl12022_dt_match[] = { { .compatible = "isl,isl12022" }, { }, }; diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index dc4f14255cc3..3b965ad6f4d5 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -401,7 +401,7 @@ static int mpc5121_rtc_remove(struct platform_device *op) } #ifdef CONFIG_OF -static struct of_device_id mpc5121_rtc_match[] = { +static const struct of_device_id mpc5121_rtc_match[] = { { .compatible = "fsl,mpc5121-rtc", }, { .compatible = "fsl,mpc5200-rtc", }, {}, -- cgit v1.2.3 From 3ca1e326f5952f3acca320b8a91d92393a188c15 Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Mon, 13 Oct 2014 15:52:42 -0700 Subject: RTC: RK808: add RTC driver for RK808 This is the initial version of the RK808 PMIC. This is a power management IC for multimedia products. It provides regulators that are able to supply power to processor cores and other components. The chip provides other modules including RTC, Clockout. Add RTC driver for supporting RTC device present inside RK808 PMIC. [akpm@linux-foundation.org: make tm_def static] Signed-off-by: Chris Zhong Signed-off-by: Zhang Qing Tested-by: Heiko Stuebner Reviewed-by: Doug Anderson Tested-by: Doug Anderson Cc: Pawel Moll Cc: Mark Rutland Cc: Ian Campbell Cc: Samuel Ortiz says: Cc: Alessandro Zummo Cc: Olof Johansson Cc: Dmitry Torokhov Cc: Javier Martinez Canillas Cc: Kever Yang Cc: Li Zhong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 10 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-rk808.c | 414 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 425 insertions(+) create mode 100644 drivers/rtc/rtc-rk808.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 1bea0fc43464..943afaf8f448 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -288,6 +288,16 @@ config RTC_DRV_MAX77686 This driver can also be built as a module. If so, the module will be called rtc-max77686. +config RTC_DRV_RK808 + tristate "Rockchip RK808 RTC" + depends on MFD_RK808 + help + If you say yes here you will get support for the + RTC of RK808 PMIC. + + This driver can also be built as a module. If so, the module + will be called rk808-rtc. + config RTC_DRV_RS5C372 tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 9055b7dd3dc5..7dec7fd90f90 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -109,6 +109,7 @@ obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o obj-$(CONFIG_RTC_DRV_RC5T583) += rtc-rc5t583.o +obj-$(CONFIG_RTC_DRV_RK808) += rtc-rk808.o obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c new file mode 100644 index 000000000000..df42257668ac --- /dev/null +++ b/drivers/rtc/rtc-rk808.c @@ -0,0 +1,414 @@ +/* + * RTC driver for Rockchip RK808 + * + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * + * Author: Chris Zhong + * Author: Zhang Qing + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* RTC_CTRL_REG bitfields */ +#define BIT_RTC_CTRL_REG_STOP_RTC_M BIT(0) + +/* RK808 has a shadowed register for saving a "frozen" RTC time. + * When user setting "GET_TIME" to 1, the time will save in this shadowed + * register. If set "READSEL" to 1, user read rtc time register, actually + * get the time of that moment. If we need the real time, clr this bit. + */ +#define BIT_RTC_CTRL_REG_RTC_GET_TIME BIT(6) +#define BIT_RTC_CTRL_REG_RTC_READSEL_M BIT(7) +#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M BIT(3) +#define RTC_STATUS_MASK 0xFE + +#define SECONDS_REG_MSK 0x7F +#define MINUTES_REG_MAK 0x7F +#define HOURS_REG_MSK 0x3F +#define DAYS_REG_MSK 0x3F +#define MONTHS_REG_MSK 0x1F +#define YEARS_REG_MSK 0xFF +#define WEEKS_REG_MSK 0x7 + +/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */ + +#define NUM_TIME_REGS (RK808_WEEKS_REG - RK808_SECONDS_REG + 1) +#define NUM_ALARM_REGS (RK808_ALARM_YEARS_REG - RK808_ALARM_SECONDS_REG + 1) + +struct rk808_rtc { + struct rk808 *rk808; + struct rtc_device *rtc; + int irq; +}; + +/* Read current time and date in RTC */ +static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) +{ + struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); + struct rk808 *rk808 = rk808_rtc->rk808; + u8 rtc_data[NUM_TIME_REGS]; + int ret; + + /* Force an update of the shadowed registers right now */ + ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + BIT_RTC_CTRL_REG_RTC_GET_TIME, + 0); + if (ret) { + dev_err(dev, "Failed to update bits rtc_ctrl: %d\n", ret); + return ret; + } + + ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + BIT_RTC_CTRL_REG_RTC_GET_TIME, + BIT_RTC_CTRL_REG_RTC_GET_TIME); + if (ret) { + dev_err(dev, "Failed to update bits rtc_ctrl: %d\n", ret); + return ret; + } + + ret = regmap_bulk_read(rk808->regmap, RK808_SECONDS_REG, + rtc_data, NUM_TIME_REGS); + if (ret) { + dev_err(dev, "Failed to bulk read rtc_data: %d\n", ret); + return ret; + } + + tm->tm_sec = bcd2bin(rtc_data[0] & SECONDS_REG_MSK); + tm->tm_min = bcd2bin(rtc_data[1] & MINUTES_REG_MAK); + tm->tm_hour = bcd2bin(rtc_data[2] & HOURS_REG_MSK); + tm->tm_mday = bcd2bin(rtc_data[3] & DAYS_REG_MSK); + tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) - 1; + tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100; + tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK); + dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, + tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec); + + return ret; +} + +/* Set current time and date in RTC */ +static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); + struct rk808 *rk808 = rk808_rtc->rk808; + u8 rtc_data[NUM_TIME_REGS]; + int ret; + + rtc_data[0] = bin2bcd(tm->tm_sec); + rtc_data[1] = bin2bcd(tm->tm_min); + rtc_data[2] = bin2bcd(tm->tm_hour); + rtc_data[3] = bin2bcd(tm->tm_mday); + rtc_data[4] = bin2bcd(tm->tm_mon + 1); + rtc_data[5] = bin2bcd(tm->tm_year - 100); + rtc_data[6] = bin2bcd(tm->tm_wday); + dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, + tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec); + + /* Stop RTC while updating the RTC registers */ + ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + BIT_RTC_CTRL_REG_STOP_RTC_M, + BIT_RTC_CTRL_REG_STOP_RTC_M); + if (ret) { + dev_err(dev, "Failed to update RTC control: %d\n", ret); + return ret; + } + + ret = regmap_bulk_write(rk808->regmap, RK808_SECONDS_REG, + rtc_data, NUM_TIME_REGS); + if (ret) { + dev_err(dev, "Failed to bull write rtc_data: %d\n", ret); + return ret; + } + /* Start RTC again */ + ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + BIT_RTC_CTRL_REG_STOP_RTC_M, 0); + if (ret) { + dev_err(dev, "Failed to update RTC control: %d\n", ret); + return ret; + } + return 0; +} + +/* Read alarm time and date in RTC */ +static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); + struct rk808 *rk808 = rk808_rtc->rk808; + u8 alrm_data[NUM_ALARM_REGS]; + uint32_t int_reg; + int ret; + + ret = regmap_bulk_read(rk808->regmap, RK808_ALARM_SECONDS_REG, + alrm_data, NUM_ALARM_REGS); + + alrm->time.tm_sec = bcd2bin(alrm_data[0] & SECONDS_REG_MSK); + alrm->time.tm_min = bcd2bin(alrm_data[1] & MINUTES_REG_MAK); + alrm->time.tm_hour = bcd2bin(alrm_data[2] & HOURS_REG_MSK); + alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK); + alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) - 1; + alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100; + + ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg); + if (ret) { + dev_err(dev, "Failed to read RTC INT REG: %d\n", ret); + return ret; + } + + dev_dbg(dev, "alrm read RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + 1900 + alrm->time.tm_year, alrm->time.tm_mon + 1, + alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour, + alrm->time.tm_min, alrm->time.tm_sec); + + alrm->enabled = (int_reg & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) ? 1 : 0; + + return 0; +} + +static int rk808_rtc_stop_alarm(struct rk808_rtc *rk808_rtc) +{ + struct rk808 *rk808 = rk808_rtc->rk808; + int ret; + + ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG, + BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, 0); + + return ret; +} + +static int rk808_rtc_start_alarm(struct rk808_rtc *rk808_rtc) +{ + struct rk808 *rk808 = rk808_rtc->rk808; + int ret; + + ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG, + BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, + BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); + + return ret; +} + +static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); + struct rk808 *rk808 = rk808_rtc->rk808; + u8 alrm_data[NUM_ALARM_REGS]; + int ret; + + ret = rk808_rtc_stop_alarm(rk808_rtc); + if (ret) { + dev_err(dev, "Failed to stop alarm: %d\n", ret); + return ret; + } + dev_dbg(dev, "alrm set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + 1900 + alrm->time.tm_year, alrm->time.tm_mon + 1, + alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour, + alrm->time.tm_min, alrm->time.tm_sec); + + alrm_data[0] = bin2bcd(alrm->time.tm_sec); + alrm_data[1] = bin2bcd(alrm->time.tm_min); + alrm_data[2] = bin2bcd(alrm->time.tm_hour); + alrm_data[3] = bin2bcd(alrm->time.tm_mday); + alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1); + alrm_data[5] = bin2bcd(alrm->time.tm_year - 100); + + ret = regmap_bulk_write(rk808->regmap, RK808_ALARM_SECONDS_REG, + alrm_data, NUM_ALARM_REGS); + if (ret) { + dev_err(dev, "Failed to bulk write: %d\n", ret); + return ret; + } + if (alrm->enabled) { + ret = rk808_rtc_start_alarm(rk808_rtc); + if (ret) { + dev_err(dev, "Failed to start alarm: %d\n", ret); + return ret; + } + } + return 0; +} + +static int rk808_rtc_alarm_irq_enable(struct device *dev, + unsigned int enabled) +{ + struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); + + if (enabled) + return rk808_rtc_start_alarm(rk808_rtc); + + return rk808_rtc_stop_alarm(rk808_rtc); +} + +/* + * We will just handle setting the frequency and make use the framework for + * reading the periodic interupts. + * + * @freq: Current periodic IRQ freq: + * bit 0: every second + * bit 1: every minute + * bit 2: every hour + * bit 3: every day + */ +static irqreturn_t rk808_alarm_irq(int irq, void *data) +{ + struct rk808_rtc *rk808_rtc = data; + struct rk808 *rk808 = rk808_rtc->rk808; + struct i2c_client *client = rk808->i2c; + int ret; + + ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG, + RTC_STATUS_MASK); + if (ret) { + dev_err(&client->dev, + "%s:Failed to update RTC status: %d\n", __func__, ret); + return ret; + } + + rtc_update_irq(rk808_rtc->rtc, 1, RTC_IRQF | RTC_AF); + dev_dbg(&client->dev, + "%s:irq=%d\n", __func__, irq); + return IRQ_HANDLED; +} + +static const struct rtc_class_ops rk808_rtc_ops = { + .read_time = rk808_rtc_readtime, + .set_time = rk808_rtc_set_time, + .read_alarm = rk808_rtc_readalarm, + .set_alarm = rk808_rtc_setalarm, + .alarm_irq_enable = rk808_rtc_alarm_irq_enable, +}; + +#ifdef CONFIG_PM_SLEEP +/* Turn off the alarm if it should not be a wake source. */ +static int rk808_rtc_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev); + + if (device_may_wakeup(dev)) + enable_irq_wake(rk808_rtc->irq); + + return 0; +} + +/* Enable the alarm if it should be enabled (in case it was disabled to + * prevent use as a wake source). + */ +static int rk808_rtc_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev); + + if (device_may_wakeup(dev)) + disable_irq_wake(rk808_rtc->irq); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(rk808_rtc_pm_ops, + rk808_rtc_suspend, rk808_rtc_resume); + +static int rk808_rtc_probe(struct platform_device *pdev) +{ + struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); + struct rk808_rtc *rk808_rtc; + struct rtc_time tm; + int ret; + + rk808_rtc = devm_kzalloc(&pdev->dev, sizeof(*rk808_rtc), GFP_KERNEL); + if (rk808_rtc == NULL) + return -ENOMEM; + + platform_set_drvdata(pdev, rk808_rtc); + rk808_rtc->rk808 = rk808; + + /* start rtc running by default, and use shadowed timer. */ + ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + BIT_RTC_CTRL_REG_STOP_RTC_M | + BIT_RTC_CTRL_REG_RTC_READSEL_M, + BIT_RTC_CTRL_REG_RTC_READSEL_M); + if (ret) { + dev_err(&pdev->dev, + "Failed to update RTC control: %d\n", ret); + return ret; + } + + ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG, + RTC_STATUS_MASK); + if (ret) { + dev_err(&pdev->dev, + "Failed to write RTC status: %d\n", ret); + return ret; + } + + /* set init time */ + ret = rk808_rtc_readtime(&pdev->dev, &tm); + if (ret) { + dev_err(&pdev->dev, "Failed to read RTC time\n"); + return ret; + } + ret = rtc_valid_tm(&tm); + if (ret) + dev_warn(&pdev->dev, "invalid date/time\n"); + + device_init_wakeup(&pdev->dev, 1); + + rk808_rtc->rtc = devm_rtc_device_register(&pdev->dev, "rk808-rtc", + &rk808_rtc_ops, THIS_MODULE); + if (IS_ERR(rk808_rtc->rtc)) { + ret = PTR_ERR(rk808_rtc->rtc); + return ret; + } + + rk808_rtc->irq = platform_get_irq(pdev, 0); + if (rk808_rtc->irq < 0) { + if (rk808_rtc->irq != -EPROBE_DEFER) + dev_err(&pdev->dev, "Wake up is not possible as irq = %d\n", + rk808_rtc->irq); + return rk808_rtc->irq; + } + + /* request alarm irq of rk808 */ + ret = devm_request_threaded_irq(&pdev->dev, rk808_rtc->irq, NULL, + rk808_alarm_irq, 0, + "RTC alarm", rk808_rtc); + if (ret) { + dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", + rk808_rtc->irq, ret); + } + + return ret; +} + +static struct platform_driver rk808_rtc_driver = { + .probe = rk808_rtc_probe, + .driver = { + .name = "rk808-rtc", + .pm = &rk808_rtc_pm_ops, + }, +}; + +module_platform_driver(rk808_rtc_driver); + +MODULE_DESCRIPTION("RTC driver for the rk808 series PMICs"); +MODULE_AUTHOR("Chris Zhong "); +MODULE_AUTHOR("Zhang Qing "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rk808-rtc"); -- cgit v1.2.3 From 038b892aa925cd0530472284c7b4b3f32e2b1f56 Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Mon, 13 Oct 2014 15:52:44 -0700 Subject: clk: RK808: add clkout driver for RK808 This is the initial version of the RK808 PMIC. This is a power management IC for multimedia products. It provides regulators that are able to supply power to processor cores and other components. The chip provides other modules including RTC, Clockout. Signed-off-by: Chris Zhong Reviewed-by: Doug Anderson Tested-by: Doug Anderson Tested-by: Heiko Stuebner Cc: Pawel Moll Cc: Mark Rutland Cc: Ian Campbell Cc: Samuel Ortiz says: Cc: Alessandro Zummo Cc: Olof Johansson Cc: Dmitry Torokhov Cc: Javier Martinez Canillas Cc: Kever Yang Cc: Li Zhong Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/clk/Kconfig | 9 +++ drivers/clk/Makefile | 1 + drivers/clk/clk-rk808.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 drivers/clk/clk-rk808.c (limited to 'drivers') diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index cfd3af7b2cbd..84e0590e31dc 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -38,6 +38,15 @@ config COMMON_CLK_MAX77686 ---help--- This driver supports Maxim 77686 crystal oscillator clock. +config COMMON_CLK_RK808 + tristate "Clock driver for RK808" + depends on MFD_RK808 + ---help--- + This driver supports RK808 crystal oscillator clock. These + multi-function devices have two fixed-rate oscillators, + clocked at 32KHz each. Clkout1 is always on, Clkout2 can off + by control register. + config COMMON_CLK_SI5351 tristate "Clock driver for SiLabs 5351A/B/C" depends on I2C diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index f537a0b1f798..99f53d5f8766 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o +obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o diff --git a/drivers/clk/clk-rk808.c b/drivers/clk/clk-rk808.c new file mode 100644 index 000000000000..83902b9cd49e --- /dev/null +++ b/drivers/clk/clk-rk808.c @@ -0,0 +1,170 @@ +/* + * Clkout driver for Rockchip RK808 + * + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * + * Author:Chris Zhong + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define RK808_NR_OUTPUT 2 + +struct rk808_clkout { + struct rk808 *rk808; + struct clk_onecell_data clk_data; + struct clk_hw clkout1_hw; + struct clk_hw clkout2_hw; +}; + +static unsigned long rk808_clkout_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return 32768; +} + +static int rk808_clkout2_enable(struct clk_hw *hw, bool enable) +{ + struct rk808_clkout *rk808_clkout = container_of(hw, + struct rk808_clkout, + clkout2_hw); + struct rk808 *rk808 = rk808_clkout->rk808; + + return regmap_update_bits(rk808->regmap, RK808_CLK32OUT_REG, + CLK32KOUT2_EN, enable ? CLK32KOUT2_EN : 0); +} + +static int rk808_clkout2_prepare(struct clk_hw *hw) +{ + return rk808_clkout2_enable(hw, true); +} + +static void rk808_clkout2_unprepare(struct clk_hw *hw) +{ + rk808_clkout2_enable(hw, false); +} + +static int rk808_clkout2_is_prepared(struct clk_hw *hw) +{ + struct rk808_clkout *rk808_clkout = container_of(hw, + struct rk808_clkout, + clkout2_hw); + struct rk808 *rk808 = rk808_clkout->rk808; + uint32_t val; + + int ret = regmap_read(rk808->regmap, RK808_CLK32OUT_REG, &val); + + if (ret < 0) + return ret; + + return (val & CLK32KOUT2_EN) ? 1 : 0; +} + +static const struct clk_ops rk808_clkout1_ops = { + .recalc_rate = rk808_clkout_recalc_rate, +}; + +static const struct clk_ops rk808_clkout2_ops = { + .prepare = rk808_clkout2_prepare, + .unprepare = rk808_clkout2_unprepare, + .is_prepared = rk808_clkout2_is_prepared, + .recalc_rate = rk808_clkout_recalc_rate, +}; + +static int rk808_clkout_probe(struct platform_device *pdev) +{ + struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); + struct i2c_client *client = rk808->i2c; + struct device_node *node = client->dev.of_node; + struct clk_init_data init = {}; + struct clk **clk_table; + struct rk808_clkout *rk808_clkout; + + rk808_clkout = devm_kzalloc(&client->dev, + sizeof(*rk808_clkout), GFP_KERNEL); + if (!rk808_clkout) + return -ENOMEM; + + rk808_clkout->rk808 = rk808; + + clk_table = devm_kcalloc(&client->dev, RK808_NR_OUTPUT, + sizeof(struct clk *), GFP_KERNEL); + if (!clk_table) + return -ENOMEM; + + init.flags = CLK_IS_ROOT; + init.parent_names = NULL; + init.num_parents = 0; + init.name = "rk808-clkout1"; + init.ops = &rk808_clkout1_ops; + rk808_clkout->clkout1_hw.init = &init; + + /* optional override of the clockname */ + of_property_read_string_index(node, "clock-output-names", + 0, &init.name); + + clk_table[0] = devm_clk_register(&client->dev, + &rk808_clkout->clkout1_hw); + if (IS_ERR(clk_table[0])) + return PTR_ERR(clk_table[0]); + + init.name = "rk808-clkout2"; + init.ops = &rk808_clkout2_ops; + rk808_clkout->clkout2_hw.init = &init; + + /* optional override of the clockname */ + of_property_read_string_index(node, "clock-output-names", + 1, &init.name); + + clk_table[1] = devm_clk_register(&client->dev, + &rk808_clkout->clkout2_hw); + if (IS_ERR(clk_table[1])) + return PTR_ERR(clk_table[1]); + + rk808_clkout->clk_data.clks = clk_table; + rk808_clkout->clk_data.clk_num = RK808_NR_OUTPUT; + + return of_clk_add_provider(node, of_clk_src_onecell_get, + &rk808_clkout->clk_data); +} + +static int rk808_clkout_remove(struct platform_device *pdev) +{ + struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); + struct i2c_client *client = rk808->i2c; + struct device_node *node = client->dev.of_node; + + of_clk_del_provider(node); + + return 0; +} + +static struct platform_driver rk808_clkout_driver = { + .probe = rk808_clkout_probe, + .remove = rk808_clkout_remove, + .driver = { + .name = "rk808-clkout", + }, +}; + +module_platform_driver(rk808_clkout_driver); + +MODULE_DESCRIPTION("Clkout driver for the rk808 series PMICs"); +MODULE_AUTHOR("Chris Zhong "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rk808-clkout"); -- cgit v1.2.3 From 33b04b7b7c03d04584be3f91ebc1eb40eb1ed33c Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 13 Oct 2014 15:52:48 -0700 Subject: rtc: ds1307: add trickle charger device tree binding Some DS13XX devices have "trickle chargers". Introduce a device tree binding for specifying the trickle charger configuration for ds1339. Only ds1339 dt binding is supported because this is the only chip I have. I _assume_ the code would have worked on other allready supported chips. However I cannot check the resistor values for the other chips or test them. For other chips the driver code works as earlier Eg. it does not check the dt bindings at all Signed-off-by: Matti Vaittinen Cc: Rob Herring Cc: Pawel Moll Cc: Jason Cooper Cc: Guenter Roeck Cc: Alessandro Zummo Cc: Mark Rutland Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-ds1307.c | 67 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index f03d5ba96db1..bb43cf703efc 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -126,9 +126,14 @@ struct chip_desc { u16 nvram_offset; u16 nvram_size; u16 trickle_charger_reg; + u8 trickle_charger_setup; + u8 (*do_trickle_setup)(struct i2c_client *, uint32_t, bool); }; -static const struct chip_desc chips[last_ds_type] = { +static u8 do_trickle_setup_ds1339(struct i2c_client *, + uint32_t ohms, bool diode); + +static struct chip_desc chips[last_ds_type] = { [ds_1307] = { .nvram_offset = 8, .nvram_size = 56, @@ -143,6 +148,7 @@ static const struct chip_desc chips[last_ds_type] = { [ds_1339] = { .alarm = 1, .trickle_charger_reg = 0x10, + .do_trickle_setup = &do_trickle_setup_ds1339, }, [ds_1340] = { .trickle_charger_reg = 0x08, @@ -833,15 +839,58 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj, return count; } + /*----------------------------------------------------------------------*/ +static u8 do_trickle_setup_ds1339(struct i2c_client *client, + uint32_t ohms, bool diode) +{ + u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE : + DS1307_TRICKLE_CHARGER_NO_DIODE; + + switch (ohms) { + case 250: + setup |= DS1307_TRICKLE_CHARGER_250_OHM; + break; + case 2000: + setup |= DS1307_TRICKLE_CHARGER_2K_OHM; + break; + case 4000: + setup |= DS1307_TRICKLE_CHARGER_4K_OHM; + break; + default: + dev_warn(&client->dev, + "Unsupported ohm value %u in dt\n", ohms); + return 0; + } + return setup; +} + +static void ds1307_trickle_of_init(struct i2c_client *client, + struct chip_desc *chip) +{ + uint32_t ohms = 0; + bool diode = true; + + if (!chip->do_trickle_setup) + goto out; + if (of_property_read_u32(client->dev.of_node, "trickle-resistor-ohms" , &ohms)) + goto out; + if (of_property_read_bool(client->dev.of_node, "trickle-diode-disable")) + diode = false; + chip->trickle_charger_setup = chip->do_trickle_setup(client, + ohms, diode); +out: + return; +} + static int ds1307_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ds1307 *ds1307; int err = -ENODEV; int tmp; - const struct chip_desc *chip = &chips[id->driver_data]; + struct chip_desc *chip = &chips[id->driver_data]; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); bool want_irq = false; unsigned char *buf; @@ -866,9 +915,19 @@ static int ds1307_probe(struct i2c_client *client, ds1307->client = client; ds1307->type = id->driver_data; - if (pdata && pdata->trickle_charger_setup && chip->trickle_charger_reg) + if (!pdata && client->dev.of_node) + ds1307_trickle_of_init(client, chip); + else if (pdata && pdata->trickle_charger_setup) + chip->trickle_charger_setup = pdata->trickle_charger_setup; + + if (chip->trickle_charger_setup && chip->trickle_charger_reg) { + dev_dbg(&client->dev, "writing trickle charger info 0x%x to 0x%x\n", + DS13XX_TRICKLE_CHARGER_MAGIC | chip->trickle_charger_setup, + chip->trickle_charger_reg); i2c_smbus_write_byte_data(client, chip->trickle_charger_reg, - DS13XX_TRICKLE_CHARGER_MAGIC | pdata->trickle_charger_setup); + DS13XX_TRICKLE_CHARGER_MAGIC | + chip->trickle_charger_setup); + } buf = ds1307->regs; if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { -- cgit v1.2.3 From 765a98a6b9e71702fd8e3822b654f9041a206b47 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 13 Oct 2014 15:52:50 -0700 Subject: rtc: bq32000: add trickle charger option, with device tree binding BQ32000 devices have "trickle chargers". Introduce a code to enable the charger, based on device tree. Without charger, RTC does not keep time after power off. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Pavel Machek Cc: Jason Cooper Cc: Matti Vaittinen Cc: Rob Herring Cc: Ian Campbell Cc: Alessandro Zummo Cc: Guenter Roeck Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-bq32k.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index c74bf0dc52cc..314129e66d6e 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -2,10 +2,14 @@ * Driver for TI BQ32000 RTC. * * Copyright (C) 2009 Semihalf. + * Copyright (C) 2014 Pavel Machek * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * You can get hardware description at + * http://www.ti.com/lit/ds/symlink/bq32000.pdf */ #include @@ -27,6 +31,10 @@ #define BQ32K_CENT 0x40 /* Century flag */ #define BQ32K_CENT_EN 0x80 /* Century flag enable bit */ +#define BQ32K_CALIBRATION 0x07 /* CAL_CFG1, calibration and control */ +#define BQ32K_TCH2 0x08 /* Trickle charge enable */ +#define BQ32K_CFG2 0x09 /* Trickle charger control */ + struct bq32k_regs { uint8_t seconds; uint8_t minutes; @@ -122,6 +130,57 @@ static const struct rtc_class_ops bq32k_rtc_ops = { .set_time = bq32k_rtc_set_time, }; +static int trickle_charger_of_init(struct device *dev, struct device_node *node) +{ + unsigned char reg; + int error; + u32 ohms = 0; + + if (of_property_read_u32(node, "trickle-resistor-ohms" , &ohms)) + return 0; + + switch (ohms) { + case 180+940: + /* + * TCHE[3:0] == 0x05, TCH2 == 1, TCFE == 0 (charging + * over diode and 940ohm resistor) + */ + + if (of_property_read_bool(node, "trickle-diode-disable")) { + dev_err(dev, "diode and resistor mismatch\n"); + return -EINVAL; + } + reg = 0x05; + break; + + case 180+20000: + /* diode disabled */ + + if (!of_property_read_bool(node, "trickle-diode-disable")) { + dev_err(dev, "bq32k: diode and resistor mismatch\n"); + return -EINVAL; + } + reg = 0x25; + break; + + default: + dev_err(dev, "invalid resistor value (%d)\n", ohms); + return -EINVAL; + } + + error = bq32k_write(dev, ®, BQ32K_CFG2, 1); + if (error) + return error; + + reg = 0x20; + error = bq32k_write(dev, ®, BQ32K_TCH2, 1); + if (error) + return error; + + dev_info(dev, "Enabled trickle RTC battery charge.\n"); + return 0; +} + static int bq32k_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -153,6 +212,9 @@ static int bq32k_probe(struct i2c_client *client, if (error) return error; + if (client && client->dev.of_node) + trickle_charger_of_init(dev, client->dev.of_node); + rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name, &bq32k_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) -- cgit v1.2.3 From e7f7fc73693e0a9de693f261d63aa681f7979c33 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Mon, 13 Oct 2014 15:52:55 -0700 Subject: rtc: max77686: Allow the max77686 rtc to wakeup the system This series add support for the Real Time clock present in the Maxim 77802 Power Managment IC. The version number is quite high because it previously was part of a bigger series [0] that aimed to add support for all the devices in the max77802 PMIC. But now that the max77802 dependencies were already merged for 3.17, the series were split but I kept the version numbering. While working on the max77802 rtc support a lot of feedback was given and the issues pointed out also apply to a driver for a similar PMIC RTC (max77686). So patches 01/06 to 05/06 in the series are cleanups for the max77686 driver and patch 06/06 adds the support for the max77802 RTC. The series were tested on an Exynos5250 Snow (max77686) and Exynos5420 Peach Pit (max77802) machines. This patch (of 6): The max77686 includes an RTC that keeps power during suspend. It's convenient to be able to use it as a wakeup source. Signed-off-by: Doug Anderson Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Cc: Alessandro Zummo Cc: Olof Johansson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-max77686.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index d20a7f0786eb..c1c6055ccb71 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -583,6 +583,33 @@ static void max77686_rtc_shutdown(struct platform_device *pdev) #endif /* MAX77686_RTC_WTSR_SMPL */ } +#ifdef CONFIG_PM_SLEEP +static int max77686_rtc_suspend(struct device *dev) +{ + if (device_may_wakeup(dev)) { + struct max77686_rtc_info *info = dev_get_drvdata(dev); + + return enable_irq_wake(info->virq); + } + + return 0; +} + +static int max77686_rtc_resume(struct device *dev) +{ + if (device_may_wakeup(dev)) { + struct max77686_rtc_info *info = dev_get_drvdata(dev); + + return disable_irq_wake(info->virq); + } + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops, + max77686_rtc_suspend, max77686_rtc_resume); + static const struct platform_device_id rtc_id[] = { { "max77686-rtc", 0 }, {}, @@ -592,6 +619,7 @@ static struct platform_driver max77686_rtc_driver = { .driver = { .name = "max77686-rtc", .owner = THIS_MODULE, + .pm = &max77686_rtc_pm_ops, }, .probe = max77686_rtc_probe, .shutdown = max77686_rtc_shutdown, -- cgit v1.2.3 From 6b50fac5ddb9748487aab3c5f8d323da01a6648f Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 13 Oct 2014 15:52:57 -0700 Subject: rtc: max77686: remove dead code for SMPL and WTSR The MAX77686 RTC chip has two features called SMPL (Sudden Momentary Power Loss) and WTSR (Watchdog Timeout and Software Resets). Support for these features seems to be implemented in the driver but compilation is disabled using a C pre-processor conditional. This code has been disabled since the driver was original merged in commit fca1dd031a28 ("rtc: max77686: add Maxim 77686 driver"). So, since this code has never been built, let's just remove it. Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Cc: Doug Anderson Cc: Alessandro Zummo Cc: Olof Johansson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-max77686.c | 101 --------------------------------------------- 1 file changed, 101 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index c1c6055ccb71..7bb543344369 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -32,15 +32,6 @@ #define RTC_UDR_MASK (1 << RTC_UDR_SHIFT) #define RTC_RBUDR_SHIFT 4 #define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT) -/* WTSR and SMPL Register */ -#define WTSRT_SHIFT 0 -#define SMPLT_SHIFT 2 -#define WTSR_EN_SHIFT 6 -#define SMPL_EN_SHIFT 7 -#define WTSRT_MASK (3 << WTSRT_SHIFT) -#define SMPLT_MASK (3 << SMPLT_SHIFT) -#define WTSR_EN_MASK (1 << WTSR_EN_SHIFT) -#define SMPL_EN_MASK (1 << SMPL_EN_SHIFT) /* RTC Hour register */ #define HOUR_PM_SHIFT 6 #define HOUR_PM_MASK (1 << HOUR_PM_SHIFT) @@ -49,7 +40,6 @@ #define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) #define MAX77686_RTC_UPDATE_DELAY 16 -#undef MAX77686_RTC_WTSR_SMPL enum { RTC_SEC = 0, @@ -412,64 +402,6 @@ static const struct rtc_class_ops max77686_rtc_ops = { .alarm_irq_enable = max77686_rtc_alarm_irq_enable, }; -#ifdef MAX77686_RTC_WTSR_SMPL -static void max77686_rtc_enable_wtsr(struct max77686_rtc_info *info, bool enable) -{ - int ret; - unsigned int val, mask; - - if (enable) - val = (1 << WTSR_EN_SHIFT) | (3 << WTSRT_SHIFT); - else - val = 0; - - mask = WTSR_EN_MASK | WTSRT_MASK; - - dev_info(info->dev, "%s: %s WTSR\n", __func__, - enable ? "enable" : "disable"); - - ret = regmap_update_bits(info->max77686->rtc_regmap, - MAX77686_WTSR_SMPL_CNTL, mask, val); - if (ret < 0) { - dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n", - __func__, ret); - return; - } - - max77686_rtc_update(info, MAX77686_RTC_WRITE); -} - -static void max77686_rtc_enable_smpl(struct max77686_rtc_info *info, bool enable) -{ - int ret; - unsigned int val, mask; - - if (enable) - val = (1 << SMPL_EN_SHIFT) | (0 << SMPLT_SHIFT); - else - val = 0; - - mask = SMPL_EN_MASK | SMPLT_MASK; - - dev_info(info->dev, "%s: %s SMPL\n", __func__, - enable ? "enable" : "disable"); - - ret = regmap_update_bits(info->max77686->rtc_regmap, - MAX77686_WTSR_SMPL_CNTL, mask, val); - if (ret < 0) { - dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n", - __func__, ret); - return; - } - - max77686_rtc_update(info, MAX77686_RTC_WRITE); - - val = 0; - regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val); - dev_info(info->dev, "%s: WTSR_SMPL(0x%02x)\n", __func__, val); -} -#endif /* MAX77686_RTC_WTSR_SMPL */ - static int max77686_rtc_init_reg(struct max77686_rtc_info *info) { u8 data[2]; @@ -519,11 +451,6 @@ static int max77686_rtc_probe(struct platform_device *pdev) goto err_rtc; } -#ifdef MAX77686_RTC_WTSR_SMPL - max77686_rtc_enable_wtsr(info, true); - max77686_rtc_enable_smpl(info, true); -#endif - device_init_wakeup(&pdev->dev, 1); info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc", @@ -556,33 +483,6 @@ err_rtc: return ret; } -static void max77686_rtc_shutdown(struct platform_device *pdev) -{ -#ifdef MAX77686_RTC_WTSR_SMPL - struct max77686_rtc_info *info = platform_get_drvdata(pdev); - int i; - u8 val = 0; - - for (i = 0; i < 3; i++) { - max77686_rtc_enable_wtsr(info, false); - regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val); - dev_info(info->dev, "%s: WTSR_SMPL reg(0x%02x)\n", __func__, - val); - if (val & WTSR_EN_MASK) { - dev_emerg(info->dev, "%s: fail to disable WTSR\n", - __func__); - } else { - dev_info(info->dev, "%s: success to disable WTSR\n", - __func__); - break; - } - } - - /* Disable SMPL when power off */ - max77686_rtc_enable_smpl(info, false); -#endif /* MAX77686_RTC_WTSR_SMPL */ -} - #ifdef CONFIG_PM_SLEEP static int max77686_rtc_suspend(struct device *dev) { @@ -622,7 +522,6 @@ static struct platform_driver max77686_rtc_driver = { .pm = &max77686_rtc_pm_ops, }, .probe = max77686_rtc_probe, - .shutdown = max77686_rtc_shutdown, .id_table = rtc_id, }; -- cgit v1.2.3 From 1745d6d3bc181800ba2e0930ab15432b3e2755ff Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 13 Oct 2014 15:52:59 -0700 Subject: rtc: max77686: fail to probe if no RTC regmap irqchip is set The max77686 mfd driver adds a regmap IRQ chip which creates an IRQ domain that is used to map the virtual RTC alarm1 interrupt. The RTC driver assumes that this will always be true since the PMIC IRQ is a required property according to the max77686 DT binding doc. If an "interrupts" property is not defined for a max77686 PMIC, then the mfd probe function will fail and the RTC platform driver will never be probed. But even when it is not possible to probe the rtc-max77686 driver without a regmap IRQ chip, it's better to explicitly check if the IRQ chip data is not NULL and gracefully fail instead of getting an OOPS. Signed-off-by: Javier Martinez Canillas Reported-by: Krzysztof Kozlowski Cc: Doug Anderson Cc: Alessandro Zummo Cc: Olof Johansson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-max77686.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 7bb543344369..55396bb3de21 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -466,6 +466,12 @@ static int max77686_rtc_probe(struct platform_device *pdev) goto err_rtc; } + if (!max77686->rtc_irq_data) { + ret = -EINVAL; + dev_err(&pdev->dev, "%s: no RTC regmap IRQ chip\n", __func__); + goto err_rtc; + } + info->virq = regmap_irq_get_virq(max77686->rtc_irq_data, MAX77686_RTCIRQ_RTCA1); if (!info->virq) { -- cgit v1.2.3 From ea33c31b621e296356ab74ea0237ba7761f2287e Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 13 Oct 2014 15:53:01 -0700 Subject: rtc: max77686: remove unneeded info log If devm_rtc_device_register() fails a dev_err() is already reported so there is no need to do an additional dev_info(). Signed-off-by: Javier Martinez Canillas Cc: Doug Anderson Cc: Krzysztof Kozlowski Cc: Alessandro Zummo Cc: Olof Johansson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-max77686.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 55396bb3de21..b177ba199a3d 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -457,8 +457,6 @@ static int max77686_rtc_probe(struct platform_device *pdev) &max77686_rtc_ops, THIS_MODULE); if (IS_ERR(info->rtc_dev)) { - dev_info(&pdev->dev, "%s: fail\n", __func__); - ret = PTR_ERR(info->rtc_dev); dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); if (ret == 0) -- cgit v1.2.3 From a20cd88e20e59ce11ebca84fac769654193c51e0 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 13 Oct 2014 15:53:03 -0700 Subject: rtc: max77686: Use ffs() to calculate tm_wday max77686_rtc_calculate_wday() is used to calculate the day of the week to be filled in struct rtc_time but that function only calculates the number of bits shifted. So the ffs() function can be used to find the first bit set instead of a special function. [akpm@linux-foundation.org: add comment clarifying ffs() use] Signed-off-by: Javier Martinez Canillas Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-max77686.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index b177ba199a3d..cf73e969c8cc 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -70,16 +70,6 @@ enum MAX77686_RTC_OP { MAX77686_RTC_READ, }; -static inline int max77686_rtc_calculate_wday(u8 shifted) -{ - int counter = -1; - while (shifted) { - shifted >>= 1; - counter++; - } - return counter; -} - static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, int rtc_24hr_mode) { @@ -93,7 +83,8 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, tm->tm_hour += 12; } - tm->tm_wday = max77686_rtc_calculate_wday(data[RTC_WEEKDAY] & 0x7f); + /* Only a single bit is set in data[], so fls() would be equivalent */ + tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f) - 1; tm->tm_mday = data[RTC_DATE] & 0x1f; tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100; -- cgit v1.2.3 From a4d4121ba753737c89e42a8df22e4859069fcf25 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 13 Oct 2014 15:53:05 -0700 Subject: rtc: add driver for Maxim 77802 PMIC Real-Time-Clock The MAX7802 PMIC has a Real-Time-Clock (RTC) with two alarms. This patch adds support for the RTC and is based on a driver added by Simon Glass to the Chrome OS kernel 3.8 tree. [akpm@linux-foundation.org: add comment clarifying ffs() use] Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Cc: Doug Anderson Cc: Alessandro Zummo Cc: Olof Johansson Cc: Simon Glass Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 10 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-max77802.c | 502 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 513 insertions(+) create mode 100644 drivers/rtc/rtc-max77802.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 943afaf8f448..d59c365788a1 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -298,6 +298,16 @@ config RTC_DRV_RK808 This driver can also be built as a module. If so, the module will be called rk808-rtc. +config RTC_DRV_MAX77802 + tristate "Maxim 77802 RTC" + depends on MFD_MAX77686 + help + If you say yes here you will get support for the + RTC of Maxim MAX77802 PMIC. + + This driver can also be built as a module. If so, the module + will be called rtc-max77802. + config RTC_DRV_RS5C372 tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 7dec7fd90f90..b188323c096a 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -85,6 +85,7 @@ obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o +obj-$(CONFIG_RTC_DRV_MAX77802) += rtc-max77802.o obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o obj-$(CONFIG_RTC_DRV_MCP795) += rtc-mcp795.o obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o diff --git a/drivers/rtc/rtc-max77802.c b/drivers/rtc/rtc-max77802.c new file mode 100644 index 000000000000..566471335b33 --- /dev/null +++ b/drivers/rtc/rtc-max77802.c @@ -0,0 +1,502 @@ +/* + * RTC driver for Maxim MAX77802 + * + * Copyright (C) 2013 Google, Inc + * + * Copyright (C) 2012 Samsung Electronics Co.Ltd + * + * based on rtc-max8997.c + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* RTC Control Register */ +#define BCD_EN_SHIFT 0 +#define BCD_EN_MASK (1 << BCD_EN_SHIFT) +#define MODEL24_SHIFT 1 +#define MODEL24_MASK (1 << MODEL24_SHIFT) +/* RTC Update Register1 */ +#define RTC_UDR_SHIFT 0 +#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT) +#define RTC_RBUDR_SHIFT 4 +#define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT) +/* RTC Hour register */ +#define HOUR_PM_SHIFT 6 +#define HOUR_PM_MASK (1 << HOUR_PM_SHIFT) +/* RTC Alarm Enable */ +#define ALARM_ENABLE_SHIFT 7 +#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) + +/* For the RTCAE1 register, we write this value to enable the alarm */ +#define ALARM_ENABLE_VALUE 0x77 + +#define MAX77802_RTC_UPDATE_DELAY_US 200 + +enum { + RTC_SEC = 0, + RTC_MIN, + RTC_HOUR, + RTC_WEEKDAY, + RTC_MONTH, + RTC_YEAR, + RTC_DATE, + RTC_NR_TIME +}; + +struct max77802_rtc_info { + struct device *dev; + struct max77686_dev *max77802; + struct i2c_client *rtc; + struct rtc_device *rtc_dev; + struct mutex lock; + + struct regmap *regmap; + + int virq; + int rtc_24hr_mode; +}; + +enum MAX77802_RTC_OP { + MAX77802_RTC_WRITE, + MAX77802_RTC_READ, +}; + +static void max77802_rtc_data_to_tm(u8 *data, struct rtc_time *tm, + int rtc_24hr_mode) +{ + tm->tm_sec = data[RTC_SEC] & 0xff; + tm->tm_min = data[RTC_MIN] & 0xff; + if (rtc_24hr_mode) + tm->tm_hour = data[RTC_HOUR] & 0x1f; + else { + tm->tm_hour = data[RTC_HOUR] & 0x0f; + if (data[RTC_HOUR] & HOUR_PM_MASK) + tm->tm_hour += 12; + } + + /* Only a single bit is set in data[], so fls() would be equivalent */ + tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0xff) - 1; + tm->tm_mday = data[RTC_DATE] & 0x1f; + tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; + + tm->tm_year = data[RTC_YEAR] & 0xff; + tm->tm_yday = 0; + tm->tm_isdst = 0; +} + +static int max77802_rtc_tm_to_data(struct rtc_time *tm, u8 *data) +{ + data[RTC_SEC] = tm->tm_sec; + data[RTC_MIN] = tm->tm_min; + data[RTC_HOUR] = tm->tm_hour; + data[RTC_WEEKDAY] = 1 << tm->tm_wday; + data[RTC_DATE] = tm->tm_mday; + data[RTC_MONTH] = tm->tm_mon + 1; + data[RTC_YEAR] = tm->tm_year; + + return 0; +} + +static int max77802_rtc_update(struct max77802_rtc_info *info, + enum MAX77802_RTC_OP op) +{ + int ret; + unsigned int data; + + if (op == MAX77802_RTC_WRITE) + data = 1 << RTC_UDR_SHIFT; + else + data = 1 << RTC_RBUDR_SHIFT; + + ret = regmap_update_bits(info->max77802->regmap, + MAX77802_RTC_UPDATE0, data, data); + if (ret < 0) + dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n", + __func__, ret, data); + else { + /* Minimum delay required before RTC update. */ + usleep_range(MAX77802_RTC_UPDATE_DELAY_US, + MAX77802_RTC_UPDATE_DELAY_US * 2); + } + + return ret; +} + +static int max77802_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct max77802_rtc_info *info = dev_get_drvdata(dev); + u8 data[RTC_NR_TIME]; + int ret; + + mutex_lock(&info->lock); + + ret = max77802_rtc_update(info, MAX77802_RTC_READ); + if (ret < 0) + goto out; + + ret = regmap_bulk_read(info->max77802->regmap, + MAX77802_RTC_SEC, data, RTC_NR_TIME); + if (ret < 0) { + dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, + ret); + goto out; + } + + max77802_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); + + ret = rtc_valid_tm(tm); + +out: + mutex_unlock(&info->lock); + return ret; +} + +static int max77802_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct max77802_rtc_info *info = dev_get_drvdata(dev); + u8 data[RTC_NR_TIME]; + int ret; + + ret = max77802_rtc_tm_to_data(tm, data); + if (ret < 0) + return ret; + + mutex_lock(&info->lock); + + ret = regmap_bulk_write(info->max77802->regmap, + MAX77802_RTC_SEC, data, RTC_NR_TIME); + if (ret < 0) { + dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, + ret); + goto out; + } + + ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); + +out: + mutex_unlock(&info->lock); + return ret; +} + +static int max77802_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct max77802_rtc_info *info = dev_get_drvdata(dev); + u8 data[RTC_NR_TIME]; + unsigned int val; + int ret; + + mutex_lock(&info->lock); + + ret = max77802_rtc_update(info, MAX77802_RTC_READ); + if (ret < 0) + goto out; + + ret = regmap_bulk_read(info->max77802->regmap, + MAX77802_ALARM1_SEC, data, RTC_NR_TIME); + if (ret < 0) { + dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", + __func__, __LINE__, ret); + goto out; + } + + max77802_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); + + alrm->enabled = 0; + ret = regmap_read(info->max77802->regmap, + MAX77802_RTC_AE1, &val); + if (ret < 0) { + dev_err(info->dev, "%s:%d fail to read alarm enable(%d)\n", + __func__, __LINE__, ret); + goto out; + } + if (val) + alrm->enabled = 1; + + alrm->pending = 0; + ret = regmap_read(info->max77802->regmap, MAX77802_REG_STATUS2, &val); + if (ret < 0) { + dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n", + __func__, __LINE__, ret); + goto out; + } + + if (val & (1 << 2)) /* RTCA1 */ + alrm->pending = 1; + +out: + mutex_unlock(&info->lock); + return 0; +} + +static int max77802_rtc_stop_alarm(struct max77802_rtc_info *info) +{ + int ret; + + if (!mutex_is_locked(&info->lock)) + dev_warn(info->dev, "%s: should have mutex locked\n", __func__); + + ret = max77802_rtc_update(info, MAX77802_RTC_READ); + if (ret < 0) + goto out; + + ret = regmap_write(info->max77802->regmap, + MAX77802_RTC_AE1, 0); + if (ret < 0) { + dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", + __func__, ret); + goto out; + } + + ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); +out: + return ret; +} + +static int max77802_rtc_start_alarm(struct max77802_rtc_info *info) +{ + int ret; + + if (!mutex_is_locked(&info->lock)) + dev_warn(info->dev, "%s: should have mutex locked\n", + __func__); + + ret = max77802_rtc_update(info, MAX77802_RTC_READ); + if (ret < 0) + goto out; + + ret = regmap_write(info->max77802->regmap, + MAX77802_RTC_AE1, + ALARM_ENABLE_VALUE); + + if (ret < 0) { + dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", + __func__, ret); + goto out; + } + + ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); +out: + return ret; +} + +static int max77802_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct max77802_rtc_info *info = dev_get_drvdata(dev); + u8 data[RTC_NR_TIME]; + int ret; + + ret = max77802_rtc_tm_to_data(&alrm->time, data); + if (ret < 0) + return ret; + + mutex_lock(&info->lock); + + ret = max77802_rtc_stop_alarm(info); + if (ret < 0) + goto out; + + ret = regmap_bulk_write(info->max77802->regmap, + MAX77802_ALARM1_SEC, data, RTC_NR_TIME); + + if (ret < 0) { + dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", + __func__, ret); + goto out; + } + + ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); + if (ret < 0) + goto out; + + if (alrm->enabled) + ret = max77802_rtc_start_alarm(info); +out: + mutex_unlock(&info->lock); + return ret; +} + +static int max77802_rtc_alarm_irq_enable(struct device *dev, + unsigned int enabled) +{ + struct max77802_rtc_info *info = dev_get_drvdata(dev); + int ret; + + mutex_lock(&info->lock); + if (enabled) + ret = max77802_rtc_start_alarm(info); + else + ret = max77802_rtc_stop_alarm(info); + mutex_unlock(&info->lock); + + return ret; +} + +static irqreturn_t max77802_rtc_alarm_irq(int irq, void *data) +{ + struct max77802_rtc_info *info = data; + + dev_dbg(info->dev, "%s:irq(%d)\n", __func__, irq); + + rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); + + return IRQ_HANDLED; +} + +static const struct rtc_class_ops max77802_rtc_ops = { + .read_time = max77802_rtc_read_time, + .set_time = max77802_rtc_set_time, + .read_alarm = max77802_rtc_read_alarm, + .set_alarm = max77802_rtc_set_alarm, + .alarm_irq_enable = max77802_rtc_alarm_irq_enable, +}; + +static int max77802_rtc_init_reg(struct max77802_rtc_info *info) +{ + u8 data[2]; + int ret; + + max77802_rtc_update(info, MAX77802_RTC_READ); + + /* Set RTC control register : Binary mode, 24hour mdoe */ + data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); + data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); + + info->rtc_24hr_mode = 1; + + ret = regmap_bulk_write(info->max77802->regmap, + MAX77802_RTC_CONTROLM, data, ARRAY_SIZE(data)); + if (ret < 0) { + dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", + __func__, ret); + return ret; + } + + ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); + return ret; +} + +static int max77802_rtc_probe(struct platform_device *pdev) +{ + struct max77686_dev *max77802 = dev_get_drvdata(pdev->dev.parent); + struct max77802_rtc_info *info; + int ret; + + dev_dbg(&pdev->dev, "%s\n", __func__); + + info = devm_kzalloc(&pdev->dev, sizeof(struct max77802_rtc_info), + GFP_KERNEL); + if (!info) + return -ENOMEM; + + mutex_init(&info->lock); + info->dev = &pdev->dev; + info->max77802 = max77802; + info->rtc = max77802->i2c; + + platform_set_drvdata(pdev, info); + + ret = max77802_rtc_init_reg(info); + + if (ret < 0) { + dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret); + return ret; + } + + device_init_wakeup(&pdev->dev, 1); + + info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77802-rtc", + &max77802_rtc_ops, THIS_MODULE); + + if (IS_ERR(info->rtc_dev)) { + ret = PTR_ERR(info->rtc_dev); + dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); + if (ret == 0) + ret = -EINVAL; + return ret; + } + + if (!max77802->rtc_irq_data) { + dev_err(&pdev->dev, "No RTC regmap IRQ chip\n"); + return -EINVAL; + } + + info->virq = regmap_irq_get_virq(max77802->rtc_irq_data, + MAX77686_RTCIRQ_RTCA1); + + if (info->virq <= 0) { + dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n", + MAX77686_RTCIRQ_RTCA1); + return -EINVAL; + } + + ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL, + max77802_rtc_alarm_irq, 0, "rtc-alarm1", + info); + if (ret < 0) + dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", + info->virq, ret); + + return ret; +} + +#ifdef CONFIG_PM_SLEEP +static int max77802_rtc_suspend(struct device *dev) +{ + if (device_may_wakeup(dev)) { + struct max77802_rtc_info *info = dev_get_drvdata(dev); + + return enable_irq_wake(info->virq); + } + + return 0; +} + +static int max77802_rtc_resume(struct device *dev) +{ + if (device_may_wakeup(dev)) { + struct max77802_rtc_info *info = dev_get_drvdata(dev); + + return disable_irq_wake(info->virq); + } + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(max77802_rtc_pm_ops, + max77802_rtc_suspend, max77802_rtc_resume); + +static const struct platform_device_id rtc_id[] = { + { "max77802-rtc", 0 }, + {}, +}; + +static struct platform_driver max77802_rtc_driver = { + .driver = { + .name = "max77802-rtc", + .owner = THIS_MODULE, + .pm = &max77802_rtc_pm_ops, + }, + .probe = max77802_rtc_probe, + .id_table = rtc_id, +}; + +module_platform_driver(max77802_rtc_driver); + +MODULE_DESCRIPTION("Maxim MAX77802 RTC driver"); +MODULE_AUTHOR("Simon Glass "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From e698a51239f26c370247d759da9ea016f5841fc3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 13 Oct 2014 15:53:07 -0700 Subject: drivers/rtc/rtc-pcf8563.c: fix uninitialized use warning gcc-4.9 found a potential condition under which the 'pending' variable may be used uninitialized: drivers/rtc/rtc-pcf8563.c: In function 'pcf8563_irq': drivers/rtc/rtc-pcf8563.c:173:5: warning: 'pending' may be used uninitialized in this function [-Wmaybe-uninitialized] This is because in the pcf8563_get_alarm_mode() function, we check any nonzero return of pcf8563_read_block_data, but in the irq function we only check for negative values, so a possible positive value does not get detected if the compiler chooses not to inline the entire call chain. Checking for any non-zero value in the interrupt handler as well is just as correct and lets the compiler know what we are doing, without needing a bogus initialization. Signed-off-by: Arnd Bergmann Cc: Sergei Shtylyov Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pcf8563.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 5a197d9dc7e7..3a6f994c4da8 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -167,7 +167,7 @@ static irqreturn_t pcf8563_irq(int irq, void *dev_id) char pending; err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending); - if (err < 0) + if (err) return err; if (pending) { -- cgit v1.2.3 From 3ff38237f183ecd8a190318e0046138b92ee5e35 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 13 Oct 2014 15:53:10 -0700 Subject: drivers/rtc/rtc-pcf8563.c: fix pcf8563_irq() error return value As pointed out by Sergei Shtylyov, the pcf8563_irq function contains a bug in the error handling: an interrupt handler is not supposed to return an errno value but an 'enum irqreturn'. Let's fix this by returning IRQ_NONE in case of a communication error. Signed-off-by: Arnd Bergmann Cc: Sergei Shtylyov Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pcf8563.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 3a6f994c4da8..c2ef0a22ee94 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -168,7 +168,7 @@ static irqreturn_t pcf8563_irq(int irq, void *dev_id) err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending); if (err) - return err; + return IRQ_NONE; if (pending) { rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF); -- cgit v1.2.3 From b513e522cb8bda32560fb6b7f0475aa56e486ab9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 13 Oct 2014 15:53:12 -0700 Subject: drivers/rtc/rtc-rs5c372.c: use %*ph to dump small buffers Instead of pushing each byte let's reduce stack usage by using %*ph specifier. Signed-off-by: Andy Shevchenko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-rs5c372.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index ccf54f06396b..28871cd7e3b5 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -142,12 +142,11 @@ static int rs5c_get_regs(struct rs5c372 *rs5c) } dev_dbg(&client->dev, - "%02x %02x %02x (%02x) %02x %02x %02x (%02x), " - "%02x %02x %02x, %02x %02x %02x; %02x %02x\n", - rs5c->regs[0], rs5c->regs[1], rs5c->regs[2], rs5c->regs[3], - rs5c->regs[4], rs5c->regs[5], rs5c->regs[6], rs5c->regs[7], - rs5c->regs[8], rs5c->regs[9], rs5c->regs[10], rs5c->regs[11], - rs5c->regs[12], rs5c->regs[13], rs5c->regs[14], rs5c->regs[15]); + "%3ph (%02x) %3ph (%02x), %3ph, %3ph; %02x %02x\n", + rs5c->regs + 0, rs5c->regs[3], + rs5c->regs + 4, rs5c->regs[7], + rs5c->regs + 8, rs5c->regs + 11, + rs5c->regs[14], rs5c->regs[15]); return 0; } -- cgit v1.2.3 From 706b632d042c87a288f8b9adc8b6c83207e6d452 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Mon, 13 Oct 2014 15:53:14 -0700 Subject: drivers/rtc/Kconfig: Let several drivers depend on HAS_IOMEM to avoid compiling issue Some drivers need 'devm_ioremap_resource' or 'devm_ioremap' which need HAS_IOMEM, so let them depend on it. The related error (with allmodconfig under score): MODPOST 1365 modules ERROR: "devm_ioremap_resource" [drivers/rtc/rtc-xgene.ko] undefined! ERROR: "devm_ioremap_resource" [drivers/rtc/rtc-stk17ta8.ko] undefined! ERROR: "devm_ioremap_resource" [drivers/rtc/rtc-ds1742.ko] undefined! ERROR: "devm_ioremap_resource" [drivers/rtc/rtc-ds1553.ko] undefined! ERROR: "devm_ioremap_resource" [drivers/rtc/rtc-ds1511.ko] undefined! ERROR: "devm_ioremap_resource" [drivers/rtc/rtc-ds1286.ko] undefined! ERROR: "devm_ioremap" [drivers/rtc/rtc-rp5c01.ko] undefined! ERROR: "devm_ioremap" [drivers/rtc/rtc-msm6242.ko] undefined! ERROR: "devm_ioremap" [drivers/rtc/rtc-m48t59.ko] undefined! ERROR: "devm_ioremap" [drivers/rtc/rtc-m48t35.ko] undefined! ERROR: "devm_ioremap" [drivers/rtc/rtc-bq4802.ko] undefined! Signed-off-by: Chen Gang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index d59c365788a1..8cd0beebdc3f 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -752,6 +752,7 @@ config RTC_DRV_DS1216 config RTC_DRV_DS1286 tristate "Dallas DS1286" + depends on HAS_IOMEM help If you say yes here you get support for the Dallas DS1286 RTC chips. @@ -763,6 +764,7 @@ config RTC_DRV_DS1302 config RTC_DRV_DS1511 tristate "Dallas DS1511" + depends on HAS_IOMEM help If you say yes here you get support for the Dallas DS1511 timekeeping/watchdog chip. @@ -772,6 +774,7 @@ config RTC_DRV_DS1511 config RTC_DRV_DS1553 tristate "Maxim/Dallas DS1553" + depends on HAS_IOMEM help If you say yes here you get support for the Maxim/Dallas DS1553 timekeeping chip. @@ -781,6 +784,7 @@ config RTC_DRV_DS1553 config RTC_DRV_DS1742 tristate "Maxim/Dallas DS1742/1743" + depends on HAS_IOMEM help If you say yes here you get support for the Maxim/Dallas DS1742/1743 timekeeping chip. @@ -836,6 +840,7 @@ config RTC_DRV_EFI config RTC_DRV_STK17TA8 tristate "Simtek STK17TA8" + depends on HAS_IOMEM help If you say yes here you get support for the Simtek STK17TA8 timekeeping chip. @@ -854,6 +859,7 @@ config RTC_DRV_M48T86 config RTC_DRV_M48T35 tristate "ST M48T35" + depends on HAS_IOMEM help If you say Y here you will get support for the ST M48T35 RTC chip. @@ -863,6 +869,7 @@ config RTC_DRV_M48T35 config RTC_DRV_M48T59 tristate "ST M48T59/M48T08/M48T02" + depends on HAS_IOMEM help If you say Y here you will get support for the ST M48T59 RTC chip and compatible ST M48T08 and M48T02. @@ -875,6 +882,7 @@ config RTC_DRV_M48T59 config RTC_DRV_MSM6242 tristate "Oki MSM6242" + depends on HAS_IOMEM help If you say yes here you get support for the Oki MSM6242 timekeeping chip. It is used in some Amiga models (e.g. A2000). @@ -884,6 +892,7 @@ config RTC_DRV_MSM6242 config RTC_DRV_BQ4802 tristate "TI BQ4802" + depends on HAS_IOMEM help If you say Y here you will get support for the TI BQ4802 RTC chip. @@ -893,6 +902,7 @@ config RTC_DRV_BQ4802 config RTC_DRV_RP5C01 tristate "Ricoh RP5C01" + depends on HAS_IOMEM help If you say yes here you get support for the Ricoh RP5C01 timekeeping chip. It is used in some Amiga models (e.g. A3000 @@ -1394,6 +1404,7 @@ config RTC_DRV_MOXART config RTC_DRV_XGENE tristate "APM X-Gene RTC" + depends on HAS_IOMEM help If you say yes here you get support for the APM X-Gene SoC real time clock. -- cgit v1.2.3 From a882b14fe84951e236cd074e93575adc8a4be32e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Date: Mon, 13 Oct 2014 15:53:16 -0700 Subject: rtc-cmos: fix wakeup from S5 without CONFIG_PM_SLEEP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b5ada4600dfd ("drivers/rtc/rtc-cmos.c: fix compilation warning when !CONFIG_PM_SLEEP") broke wakeup from S5 by making cmos_poweroff a nop unless CONFIG_PM_SLEEP was defined. Fix this by restricting the #ifdef to cmos_resume and restoring the old dependency on CONFIG_PM for cmos_suspend and cmos_poweroff. Signed-off-by: Daniel Glöckner Cc: Mika Westerberg Cc: Alessandro Zummo Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-cmos.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index b0e4a3eb33c7..5b2e76159b41 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -856,7 +856,7 @@ static void __exit cmos_do_remove(struct device *dev) cmos->dev = NULL; } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int cmos_suspend(struct device *dev) { @@ -907,6 +907,8 @@ static inline int cmos_poweroff(struct device *dev) return cmos_suspend(dev); } +#ifdef CONFIG_PM_SLEEP + static int cmos_resume(struct device *dev) { struct cmos_rtc *cmos = dev_get_drvdata(dev); @@ -954,6 +956,7 @@ static int cmos_resume(struct device *dev) return 0; } +#endif #else static inline int cmos_poweroff(struct device *dev) -- cgit v1.2.3 From 5ef9819234e285abe6b616864e7b1b4607d39b58 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 13 Oct 2014 15:53:59 -0700 Subject: memstick: r592: fix build warnings for !PM_SLEEP When PM_SLEEP is not enabled, the r592_clear_interrupts() function is never used. If so, don't build it to prevent a compiler warning. Signed-off-by: Thierry Reding Cc: Maxim Levitsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/memstick/host/r592.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c index 31727bf285d0..e2a4f5f415b2 100644 --- a/drivers/memstick/host/r592.c +++ b/drivers/memstick/host/r592.c @@ -188,6 +188,7 @@ static void r592_host_reset(struct r592_device *dev) r592_set_mode(dev, dev->parallel_mode); } +#ifdef CONFIG_PM_SLEEP /* Disable all hardware interrupts */ static void r592_clear_interrupts(struct r592_device *dev) { @@ -195,6 +196,7 @@ static void r592_clear_interrupts(struct r592_device *dev) r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_ACK_MASK); r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_EN_MASK); } +#endif /* Tests if there is an CRC error */ static int r592_test_io_error(struct r592_device *dev) -- cgit v1.2.3 From c4dd08694b8f078900c8e0c86e369b667a5101c5 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 Oct 2014 15:54:33 -0700 Subject: video: fbdev: replace strnicmp with strncasecmp The kernel used to contain two functions for length-delimited, case-insensitive string comparison, strnicmp with correct semantics and a slightly buggy strncasecmp. The latter is the POSIX name, so strnicmp was renamed to strncasecmp, and strnicmp made into a wrapper for the new strncasecmp to avoid breaking existing users. To allow the compat wrapper strnicmp to be removed at some point in the future, and to avoid the extra indirection cost, do s/strnicmp/strncasecmp/g. Signed-off-by: Rasmus Villemoes Cc: Jean-Christophe Plagniol-Villard Cc: Tomi Valkeinen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/fbdev/pvr2fb.c | 2 +- drivers/video/fbdev/s3c2410fb.c | 8 ++--- drivers/video/fbdev/sis/sis_main.c | 66 +++++++++++++++++++------------------- drivers/video/fbdev/sm501fb.c | 4 +-- 4 files changed, 40 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c index 167cffff3d4e..7c74f58fc101 100644 --- a/drivers/video/fbdev/pvr2fb.c +++ b/drivers/video/fbdev/pvr2fb.c @@ -1001,7 +1001,7 @@ static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val, for (i = 0 ; i < size ; i++ ) { if (s != NULL) { - if (!strnicmp(p[i].name, s, strlen(s))) + if (!strncasecmp(p[i].name, s, strlen(s))) return p[i].val; } else { if (p[i].val == val) diff --git a/drivers/video/fbdev/s3c2410fb.c b/drivers/video/fbdev/s3c2410fb.c index 43c63a4f3178..e350eb57f11d 100644 --- a/drivers/video/fbdev/s3c2410fb.c +++ b/drivers/video/fbdev/s3c2410fb.c @@ -601,12 +601,12 @@ static int s3c2410fb_debug_store(struct device *dev, if (len < 1) return -EINVAL; - if (strnicmp(buf, "on", 2) == 0 || - strnicmp(buf, "1", 1) == 0) { + if (strncasecmp(buf, "on", 2) == 0 || + strncasecmp(buf, "1", 1) == 0) { debug = 1; dev_dbg(dev, "s3c2410fb: Debug On"); - } else if (strnicmp(buf, "off", 3) == 0 || - strnicmp(buf, "0", 1) == 0) { + } else if (strncasecmp(buf, "off", 3) == 0 || + strncasecmp(buf, "0", 1) == 0) { debug = 0; dev_dbg(dev, "s3c2410fb: Debug Off"); } else { diff --git a/drivers/video/fbdev/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c index 3f12a2dd959a..4f5cf035ac3c 100644 --- a/drivers/video/fbdev/sis/sis_main.c +++ b/drivers/video/fbdev/sis/sis_main.c @@ -162,7 +162,7 @@ static void sisfb_search_mode(char *name, bool quiet) return; } - if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) { + if(!strncasecmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) { if(!quiet) printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n"); @@ -201,7 +201,7 @@ static void sisfb_search_mode(char *name, bool quiet) i = 0; j = 0; while(sisbios_mode[i].mode_no[0] != 0) { - if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) { + if(!strncasecmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) { if(sisfb_fstn) { if(sisbios_mode[i-1].mode_no[1] == 0x50 || sisbios_mode[i-1].mode_no[1] == 0x56 || @@ -262,7 +262,7 @@ sisfb_search_crt2type(const char *name) if(name == NULL) return; while(sis_crt2type[i].type_no != -1) { - if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) { + if(!strncasecmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) { sisfb_crt2type = sis_crt2type[i].type_no; sisfb_tvplug = sis_crt2type[i].tvplug_no; sisfb_crt2flags = sis_crt2type[i].flags; @@ -289,7 +289,7 @@ sisfb_search_tvstd(const char *name) return; while(sis_tvtype[i].type_no != -1) { - if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) { + if(!strncasecmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) { sisfb_tvstd = sis_tvtype[i].type_no; break; } @@ -308,12 +308,12 @@ sisfb_search_specialtiming(const char *name) if(name == NULL) return; - if(!strnicmp(name, "none", 4)) { + if(!strncasecmp(name, "none", 4)) { sisfb_specialtiming = CUT_FORCENONE; printk(KERN_DEBUG "sisfb: Special timing disabled\n"); } else { while(mycustomttable[i].chipID != 0) { - if(!strnicmp(name,mycustomttable[i].optionName, + if(!strncasecmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) { sisfb_specialtiming = mycustomttable[i].SpecialID; found = true; @@ -3952,68 +3952,68 @@ static int __init sisfb_setup(char *options) if(!(*this_opt)) continue; - if(!strnicmp(this_opt, "off", 3)) { + if(!strncasecmp(this_opt, "off", 3)) { sisfb_off = 1; - } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) { + } else if(!strncasecmp(this_opt, "forcecrt2type:", 14)) { /* Need to check crt2 type first for fstn/dstn */ sisfb_search_crt2type(this_opt + 14); - } else if(!strnicmp(this_opt, "tvmode:",7)) { + } else if(!strncasecmp(this_opt, "tvmode:",7)) { sisfb_search_tvstd(this_opt + 7); - } else if(!strnicmp(this_opt, "tvstandard:",11)) { + } else if(!strncasecmp(this_opt, "tvstandard:",11)) { sisfb_search_tvstd(this_opt + 11); - } else if(!strnicmp(this_opt, "mode:", 5)) { + } else if(!strncasecmp(this_opt, "mode:", 5)) { sisfb_search_mode(this_opt + 5, false); - } else if(!strnicmp(this_opt, "vesa:", 5)) { + } else if(!strncasecmp(this_opt, "vesa:", 5)) { sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false); - } else if(!strnicmp(this_opt, "rate:", 5)) { + } else if(!strncasecmp(this_opt, "rate:", 5)) { sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0); - } else if(!strnicmp(this_opt, "forcecrt1:", 10)) { + } else if(!strncasecmp(this_opt, "forcecrt1:", 10)) { sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0); - } else if(!strnicmp(this_opt, "mem:",4)) { + } else if(!strncasecmp(this_opt, "mem:",4)) { sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0); - } else if(!strnicmp(this_opt, "pdc:", 4)) { + } else if(!strncasecmp(this_opt, "pdc:", 4)) { sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0); - } else if(!strnicmp(this_opt, "pdc1:", 5)) { + } else if(!strncasecmp(this_opt, "pdc1:", 5)) { sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0); - } else if(!strnicmp(this_opt, "noaccel", 7)) { + } else if(!strncasecmp(this_opt, "noaccel", 7)) { sisfb_accel = 0; - } else if(!strnicmp(this_opt, "accel", 5)) { + } else if(!strncasecmp(this_opt, "accel", 5)) { sisfb_accel = -1; - } else if(!strnicmp(this_opt, "noypan", 6)) { + } else if(!strncasecmp(this_opt, "noypan", 6)) { sisfb_ypan = 0; - } else if(!strnicmp(this_opt, "ypan", 4)) { + } else if(!strncasecmp(this_opt, "ypan", 4)) { sisfb_ypan = -1; - } else if(!strnicmp(this_opt, "nomax", 5)) { + } else if(!strncasecmp(this_opt, "nomax", 5)) { sisfb_max = 0; - } else if(!strnicmp(this_opt, "max", 3)) { + } else if(!strncasecmp(this_opt, "max", 3)) { sisfb_max = -1; - } else if(!strnicmp(this_opt, "userom:", 7)) { + } else if(!strncasecmp(this_opt, "userom:", 7)) { sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0); - } else if(!strnicmp(this_opt, "useoem:", 7)) { + } else if(!strncasecmp(this_opt, "useoem:", 7)) { sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); - } else if(!strnicmp(this_opt, "nocrt2rate", 10)) { + } else if(!strncasecmp(this_opt, "nocrt2rate", 10)) { sisfb_nocrt2rate = 1; - } else if(!strnicmp(this_opt, "scalelcd:", 9)) { + } else if(!strncasecmp(this_opt, "scalelcd:", 9)) { unsigned long temp = 2; temp = simple_strtoul(this_opt + 9, NULL, 0); if((temp == 0) || (temp == 1)) { sisfb_scalelcd = temp ^ 1; } - } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) { + } else if(!strncasecmp(this_opt, "tvxposoffset:", 13)) { int temp = 0; temp = (int)simple_strtol(this_opt + 13, NULL, 0); if((temp >= -32) && (temp <= 32)) { sisfb_tvxposoffset = temp; } - } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) { + } else if(!strncasecmp(this_opt, "tvyposoffset:", 13)) { int temp = 0; temp = (int)simple_strtol(this_opt + 13, NULL, 0); if((temp >= -32) && (temp <= 32)) { sisfb_tvyposoffset = temp; } - } else if(!strnicmp(this_opt, "specialtiming:", 14)) { + } else if(!strncasecmp(this_opt, "specialtiming:", 14)) { sisfb_search_specialtiming(this_opt + 14); - } else if(!strnicmp(this_opt, "lvdshl:", 7)) { + } else if(!strncasecmp(this_opt, "lvdshl:", 7)) { int temp = 4; temp = simple_strtoul(this_opt + 7, NULL, 0); if((temp >= 0) && (temp <= 3)) { @@ -4022,9 +4022,9 @@ static int __init sisfb_setup(char *options) } else if(this_opt[0] >= '0' && this_opt[0] <= '9') { sisfb_search_mode(this_opt, true); #if !defined(__i386__) && !defined(__x86_64__) - } else if(!strnicmp(this_opt, "resetcard", 9)) { + } else if(!strncasecmp(this_opt, "resetcard", 9)) { sisfb_resetcard = 1; - } else if(!strnicmp(this_opt, "videoram:", 9)) { + } else if(!strncasecmp(this_opt, "videoram:", 9)) { sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0); #endif } else { diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c index c2c8eb668784..9e74e8fbe074 100644 --- a/drivers/video/fbdev/sm501fb.c +++ b/drivers/video/fbdev/sm501fb.c @@ -1187,9 +1187,9 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev, if (len < 1) return -EINVAL; - if (strnicmp(buf, "crt", 3) == 0) + if (strncasecmp(buf, "crt", 3) == 0) head = HEAD_CRT; - else if (strnicmp(buf, "panel", 5) == 0) + else if (strncasecmp(buf, "panel", 5) == 0) head = HEAD_PANEL; else return -EINVAL; -- cgit v1.2.3 From 48a968763dba039972623caea2355fc573b559ba Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 Oct 2014 15:54:44 -0700 Subject: scsi: replace strnicmp with strncasecmp The kernel used to contain two functions for length-delimited, case-insensitive string comparison, strnicmp with correct semantics and a slightly buggy strncasecmp. The latter is the POSIX name, so strnicmp was renamed to strncasecmp, and strnicmp made into a wrapper for the new strncasecmp to avoid breaking existing users. To allow the compat wrapper strnicmp to be removed at some point in the future, and to avoid the extra indirection cost, do s/strnicmp/strncasecmp/g. Signed-off-by: Rasmus Villemoes Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/ips.c | 2 +- drivers/scsi/scsi_debug.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 52a216f21ae5..e5afc3884d74 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -528,7 +528,7 @@ ips_setup(char *ips_str) * Update the variables */ for (i = 0; i < ARRAY_SIZE(options); i++) { - if (strnicmp + if (strncasecmp (key, options[i].option_name, strlen(options[i].option_name)) == 0) { if (value) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 2b6d447ad6d6..238e06f13b8a 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -3371,7 +3371,7 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf, char work[20]; if (1 == sscanf(buf, "%10s", work)) { - if (0 == strnicmp(work,"0x", 2)) { + if (0 == strncasecmp(work,"0x", 2)) { if (1 == sscanf(&work[2], "%x", &opts)) goto opts_done; } else { -- cgit v1.2.3 From b60459f080bf3a1fcc6f55cfb628d1d79423b6ff Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 Oct 2014 15:54:46 -0700 Subject: ib_srpt: replace strnicmp with strncasecmp The kernel used to contain two functions for length-delimited, case-insensitive string comparison, strnicmp with correct semantics and a slightly buggy strncasecmp. The latter is the POSIX name, so strnicmp was renamed to strncasecmp, and strnicmp made into a wrapper for the new strncasecmp to avoid breaking existing users. To allow the compat wrapper strnicmp to be removed at some point in the future, and to avoid the extra indirection cost, do s/strnicmp/strncasecmp/g. Signed-off-by: Rasmus Villemoes Cc: Roland Dreier Cc: Nicholas Bellinger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/infiniband/ulp/srpt/ib_srpt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index d28a8c284da9..7206547c13ce 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -3574,7 +3574,7 @@ static int srpt_parse_i_port_id(u8 i_port_id[16], const char *name) int ret, rc; p = name; - if (strnicmp(p, "0x", 2) == 0) + if (strncasecmp(p, "0x", 2) == 0) p += 2; ret = -EINVAL; len = strlen(p); -- cgit v1.2.3 From 0f3ae5baafba9e48e2d3b173b982a46ad90149b4 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 Oct 2014 15:54:48 -0700 Subject: input: edt-ft5x06: replace strnicmp with strncasecmp The kernel used to contain two functions for length-delimited, case-insensitive string comparison, strnicmp with correct semantics and a slightly buggy strncasecmp. The latter is the POSIX name, so strnicmp was renamed to strncasecmp, and strnicmp made into a wrapper for the new strncasecmp to avoid breaking existing users. To allow the compat wrapper strnicmp to be removed at some point in the future, and to avoid the extra indirection cost, do s/strnicmp/strncasecmp/g. Signed-off-by: Rasmus Villemoes Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/input/touchscreen/edt-ft5x06.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 8857d5b9be71..ee3434f1e949 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -812,7 +812,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, /* if we find something consistent, stay with that assumption * at least M09 won't send 3 bytes here */ - if (!(strnicmp(rdbuf + 1, "EP0", 3))) { + if (!(strncasecmp(rdbuf + 1, "EP0", 3))) { tsdata->version = M06; /* remove last '$' end marker */ -- cgit v1.2.3 From 30614cf34105c5b5b9a39c65a2ea32c58b03aa8e Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 Oct 2014 15:54:50 -0700 Subject: altera-stapl: replace strnicmp with strncasecmp The kernel used to contain two functions for length-delimited, case-insensitive string comparison, strnicmp with correct semantics and a slightly buggy strncasecmp. The latter is the POSIX name, so strnicmp was renamed to strncasecmp, and strnicmp made into a wrapper for the new strncasecmp to avoid breaking existing users. To allow the compat wrapper strnicmp to be removed at some point in the future, and to avoid the extra indirection cost, do s/strnicmp/strncasecmp/g. Signed-off-by: Rasmus Villemoes Cc: "Igor M. Liplianin" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/altera-stapl/altera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/altera-stapl/altera.c b/drivers/misc/altera-stapl/altera.c index 24272e022bec..bca2630d006f 100644 --- a/drivers/misc/altera-stapl/altera.c +++ b/drivers/misc/altera-stapl/altera.c @@ -454,7 +454,7 @@ exit_done: name = &p[str_table + name_id]; - if (strnicmp(aconf->action, name, strlen(name)) == 0) { + if (strncasecmp(aconf->action, name, strlen(name)) == 0) { action_found = 1; current_proc = get_unaligned_be32(&p[action_table + @@ -2176,7 +2176,7 @@ static int altera_get_note(u8 *p, s32 program_size, key_ptr = &p[note_strings + get_unaligned_be32( &p[note_table + (8 * i)])]; - if ((strnicmp(key, key_ptr, strlen(key_ptr)) == 0) && + if ((strncasecmp(key, key_ptr, strlen(key_ptr)) == 0) && (key != NULL)) { status = 0; -- cgit v1.2.3 From 40f5c777ec61d908ffc7f2a6ccbed60d9930a1f8 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 Oct 2014 15:54:52 -0700 Subject: thinkpad_acpi: replace strnicmp with strncasecmp The kernel used to contain two functions for length-delimited, case-insensitive string comparison, strnicmp with correct semantics and a slightly buggy strncasecmp. The latter is the POSIX name, so strnicmp was renamed to strncasecmp, and strnicmp made into a wrapper for the new strncasecmp to avoid breaking existing users. To allow the compat wrapper strnicmp to be removed at some point in the future, and to avoid the extra indirection cost, do s/strnicmp/strncasecmp/g. Signed-off-by: Rasmus Villemoes Cc: Henrique de Moraes Holschuh Cc: Darren Hart Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/platform/x86/thinkpad_acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index f959978c7aac..cf0f89364d44 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -8878,13 +8878,13 @@ static int __must_check __init get_thinkpad_model_data( } s = dmi_get_system_info(DMI_PRODUCT_VERSION); - if (s && !(strnicmp(s, "ThinkPad", 8) && strnicmp(s, "Lenovo", 6))) { + if (s && !(strncasecmp(s, "ThinkPad", 8) && strncasecmp(s, "Lenovo", 6))) { tp->model_str = kstrdup(s, GFP_KERNEL); if (!tp->model_str) return -ENOMEM; } else { s = dmi_get_system_info(DMI_BIOS_VENDOR); - if (s && !(strnicmp(s, "Lenovo", 6))) { + if (s && !(strncasecmp(s, "Lenovo", 6))) { tp->model_str = kstrdup(s, GFP_KERNEL); if (!tp->model_str) return -ENOMEM; -- cgit v1.2.3 From 7fb1cab4ac8ef7a1fed5c19593cd5b4be1b1a9b3 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 Oct 2014 15:54:54 -0700 Subject: PNP: replace strnicmp with strncasecmp The kernel used to contain two functions for length-delimited, case-insensitive string comparison, strnicmp with correct semantics and a slightly buggy strncasecmp. The latter is the POSIX name, so strnicmp was renamed to strncasecmp, and strnicmp made into a wrapper for the new strncasecmp to avoid breaking existing users. To allow the compat wrapper strnicmp to be removed at some point in the future, and to avoid the extra indirection cost, do s/strnicmp/strncasecmp/g. Signed-off-by: Rasmus Villemoes Cc: "Rafael J. Wysocki" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pnp/interface.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index e6c403be09a9..4b6808ff0e5d 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -346,41 +346,41 @@ static ssize_t resources_store(struct device *dmdev, } buf = skip_spaces(buf); - if (!strnicmp(buf, "disable", 7)) { + if (!strncasecmp(buf, "disable", 7)) { retval = pnp_disable_dev(dev); goto done; } - if (!strnicmp(buf, "activate", 8)) { + if (!strncasecmp(buf, "activate", 8)) { retval = pnp_activate_dev(dev); goto done; } - if (!strnicmp(buf, "fill", 4)) { + if (!strncasecmp(buf, "fill", 4)) { if (dev->active) goto done; retval = pnp_auto_config_dev(dev); goto done; } - if (!strnicmp(buf, "auto", 4)) { + if (!strncasecmp(buf, "auto", 4)) { if (dev->active) goto done; pnp_init_resources(dev); retval = pnp_auto_config_dev(dev); goto done; } - if (!strnicmp(buf, "clear", 5)) { + if (!strncasecmp(buf, "clear", 5)) { if (dev->active) goto done; pnp_init_resources(dev); goto done; } - if (!strnicmp(buf, "get", 3)) { + if (!strncasecmp(buf, "get", 3)) { mutex_lock(&pnp_res_mutex); if (pnp_can_read(dev)) dev->protocol->get(dev); mutex_unlock(&pnp_res_mutex); goto done; } - if (!strnicmp(buf, "set", 3)) { + if (!strncasecmp(buf, "set", 3)) { resource_size_t start; resource_size_t end; unsigned long flags; @@ -392,31 +392,31 @@ static ssize_t resources_store(struct device *dmdev, mutex_lock(&pnp_res_mutex); while (1) { buf = skip_spaces(buf); - if (!strnicmp(buf, "io", 2)) { + if (!strncasecmp(buf, "io", 2)) { buf = pnp_get_resource_value(buf + 2, IORESOURCE_IO, &start, &end, &flags); pnp_add_io_resource(dev, start, end, flags); - } else if (!strnicmp(buf, "mem", 3)) { + } else if (!strncasecmp(buf, "mem", 3)) { buf = pnp_get_resource_value(buf + 3, IORESOURCE_MEM, &start, &end, &flags); pnp_add_mem_resource(dev, start, end, flags); - } else if (!strnicmp(buf, "irq", 3)) { + } else if (!strncasecmp(buf, "irq", 3)) { buf = pnp_get_resource_value(buf + 3, IORESOURCE_IRQ, &start, NULL, &flags); pnp_add_irq_resource(dev, start, flags); - } else if (!strnicmp(buf, "dma", 3)) { + } else if (!strncasecmp(buf, "dma", 3)) { buf = pnp_get_resource_value(buf + 3, IORESOURCE_DMA, &start, NULL, &flags); pnp_add_dma_resource(dev, start, flags); - } else if (!strnicmp(buf, "bus", 3)) { + } else if (!strncasecmp(buf, "bus", 3)) { buf = pnp_get_resource_value(buf + 3, IORESOURCE_BUS, &start, &end, -- cgit v1.2.3 From 3f8bfd9a7504bff350acd50c6eee23ca5c9913b2 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 Oct 2014 15:54:57 -0700 Subject: s390/cio: replace strnicmp with strncasecmp The kernel used to contain two functions for length-delimited, case-insensitive string comparison, strnicmp with correct semantics and a slightly buggy strncasecmp. The latter is the POSIX name, so strnicmp was renamed to strncasecmp, and strnicmp made into a wrapper for the new strncasecmp to avoid breaking existing users. To allow the compat wrapper strnicmp to be removed at some point in the future, and to avoid the extra indirection cost, do s/strnicmp/strncasecmp/g. Signed-off-by: Rasmus Villemoes Cc: Sebastian Ott Cc: Peter Oberparleiter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/chp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index d497aa05a72f..c692dfebd0ba 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -257,11 +257,11 @@ static ssize_t chp_status_write(struct device *dev, if (!num_args) return count; - if (!strnicmp(cmd, "on", 2) || !strcmp(cmd, "1")) { + if (!strncasecmp(cmd, "on", 2) || !strcmp(cmd, "1")) { mutex_lock(&cp->lock); error = s390_vary_chpid(cp->chpid, 1); mutex_unlock(&cp->lock); - } else if (!strnicmp(cmd, "off", 3) || !strcmp(cmd, "0")) { + } else if (!strncasecmp(cmd, "off", 3) || !strcmp(cmd, "0")) { mutex_lock(&cp->lock); error = s390_vary_chpid(cp->chpid, 0); mutex_unlock(&cp->lock); -- cgit v1.2.3 From 7569055b81fc9e75b96d1a259163fc5325aac799 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 Oct 2014 15:54:59 -0700 Subject: staging: r8188eu: replace strnicmp with strncasecmp The kernel used to contain two functions for length-delimited, case-insensitive string comparison, strnicmp with correct semantics and a slightly buggy strncasecmp. The latter is the POSIX name, so strnicmp was renamed to strncasecmp, and strnicmp made into a wrapper for the new strncasecmp to avoid breaking existing users. To allow the compat wrapper strnicmp to be removed at some point in the future, and to avoid the extra indirection cost, do s/strnicmp/strncasecmp/g. Signed-off-by: Rasmus Villemoes Cc: Greg Kroah-Hartman Cc: Larry Finger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/staging/rtl8188eu/os_dep/rtw_android.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_android.c b/drivers/staging/rtl8188eu/os_dep/rtw_android.c index 1718229f6278..d9d55d12fd5f 100644 --- a/drivers/staging/rtl8188eu/os_dep/rtw_android.c +++ b/drivers/staging/rtl8188eu/os_dep/rtw_android.c @@ -79,7 +79,7 @@ int rtw_android_cmdstr_to_num(char *cmdstr) { int cmd_num; for (cmd_num = 0; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++) - if (0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], + if (0 == strncasecmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num]))) break; return cmd_num; -- cgit v1.2.3 From 484ac2f32d3a282bd583f7195b0b2970ef8d0c04 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 Oct 2014 15:55:01 -0700 Subject: thermal: replace strnicmp with strncasecmp The kernel used to contain two functions for length-delimited, case-insensitive string comparison, strnicmp with correct semantics and a slightly buggy strncasecmp. The latter is the POSIX name, so strnicmp was renamed to strncasecmp, and strnicmp made into a wrapper for the new strncasecmp to avoid breaking existing users. To allow the compat wrapper strnicmp to be removed at some point in the future, and to avoid the extra indirection cost, do s/strnicmp/strncasecmp/g. Signed-off-by: Rasmus Villemoes Acked-by: Zhang Rui Cc: Eduardo Valentin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/thermal/thermal_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 71b0ec0c370d..1e23f4f8d2c2 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -66,7 +66,7 @@ static struct thermal_governor *__find_governor(const char *name) return def_governor; list_for_each_entry(pos, &thermal_governor_list, governor_list) - if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH)) + if (!strncasecmp(name, pos->name, THERMAL_NAME_LENGTH)) return pos; return NULL; @@ -104,7 +104,7 @@ int thermal_register_governor(struct thermal_governor *governor) name = pos->tzp->governor_name; - if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH)) + if (!strncasecmp(name, governor->name, THERMAL_NAME_LENGTH)) pos->governor = governor; } @@ -129,7 +129,7 @@ void thermal_unregister_governor(struct thermal_governor *governor) mutex_lock(&thermal_list_lock); list_for_each_entry(pos, &thermal_tz_list, node) { - if (!strnicmp(pos->governor->name, governor->name, + if (!strncasecmp(pos->governor->name, governor->name, THERMAL_NAME_LENGTH)) pos->governor = NULL; } @@ -1665,7 +1665,7 @@ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name) mutex_lock(&thermal_list_lock); list_for_each_entry(pos, &thermal_tz_list, node) - if (!strnicmp(name, pos->type, THERMAL_NAME_LENGTH)) { + if (!strncasecmp(name, pos->type, THERMAL_NAME_LENGTH)) { found++; ref = pos; } -- cgit v1.2.3 From da169607ae17c4340fe2ab286130741266709b07 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 13 Oct 2014 15:55:20 -0700 Subject: wireless: libertas: print esaped string via %*pE Instead of custom approach this allows to print escaped strings via recently added kernel extension: %*pE. Signed-off-by: Andy Shevchenko Cc: "John W . Linville" Cc: Johannes Berg Cc: Greg Kroah-Hartman Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/wireless/libertas/cfg.c | 8 ++------ drivers/net/wireless/libertas/mesh.c | 7 +++---- 2 files changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 818b1edaaa9a..34f09ef90bb3 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -590,7 +590,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, int chan_no = -1; const u8 *ssid = NULL; u8 ssid_len = 0; - DECLARE_SSID_BUF(ssid_buf); int len = get_unaligned_le16(pos); pos += 2; @@ -644,10 +643,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq); - lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %s, " - "%d dBm\n", - bssid, capa, chan_no, - print_ssid(ssid_buf, ssid, ssid_len), + lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %*pE, %d dBm\n", + bssid, capa, chan_no, ssid_len, ssid, LBS_SCAN_RSSI_TO_MBM(rssi)/100); if (channel && @@ -1984,7 +1981,6 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct lbs_private *priv = wiphy_priv(wiphy); int ret = 0; struct cfg80211_bss *bss; - DECLARE_SSID_BUF(ssid_buf); if (dev == priv->mesh_dev) return -EOPNOTSUPP; diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 01a67f62696f..d0c881dd5846 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c @@ -93,7 +93,6 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action, { struct cmd_ds_mesh_config cmd; struct mrvl_meshie *ie; - DECLARE_SSID_BUF(ssid); memset(&cmd, 0, sizeof(cmd)); cmd.channel = cpu_to_le16(chan); @@ -122,9 +121,9 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action, default: return -1; } - lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n", - action, priv->mesh_tlv, chan, - print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len)); + lbs_deb_cmd("mesh config action %d type %x channel %d SSID %*pE\n", + action, priv->mesh_tlv, chan, priv->mesh_ssid_len, + priv->mesh_ssid); return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); } -- cgit v1.2.3 From 4b4890cb6aebb1669879a02c51a3c3eff629dff0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 13 Oct 2014 15:55:22 -0700 Subject: wireless: ipw2x00: print SSID via %*pE Instead of custom approach this allows to print escaped strings via recently added kernel extension: %*pE. Signed-off-by: Andy Shevchenko Cc: "John W . Linville" Cc: Johannes Berg Cc: Greg Kroah-Hartman Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/wireless/ipw2x00/ipw2100.c | 22 +-- drivers/net/wireless/ipw2x00/ipw2200.c | 270 ++++++++++--------------------- drivers/net/wireless/ipw2x00/libipw_rx.c | 65 +++----- drivers/net/wireless/ipw2x00/libipw_wx.c | 16 +- 4 files changed, 126 insertions(+), 247 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index c3d726f334e3..6fabea0309dd 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -2005,7 +2005,6 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) u32 chan; char *txratename; u8 bssid[ETH_ALEN]; - DECLARE_SSID_BUF(ssid); /* * TBD: BSSID is usually 00:00:00:00:00:00 here and not @@ -2067,8 +2066,8 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) break; } - IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID=%pM)\n", - priv->net_dev->name, print_ssid(ssid, essid, essid_len), + IPW_DEBUG_INFO("%s: Associated with '%*pE' at %s, channel %d (BSSID=%pM)\n", + priv->net_dev->name, essid_len, essid, txratename, chan, bssid); /* now we copy read ssid into dev */ @@ -2095,9 +2094,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, .host_command_length = ssid_len }; int err; - DECLARE_SSID_BUF(ssid); - IPW_DEBUG_HC("SSID: '%s'\n", print_ssid(ssid, essid, ssid_len)); + IPW_DEBUG_HC("SSID: '%*pE'\n", ssid_len, essid); if (ssid_len) memcpy(cmd.host_command_parameters, essid, ssid_len); @@ -2138,11 +2136,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) { - DECLARE_SSID_BUF(ssid); - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, - "disassociated: '%s' %pM\n", - print_ssid(ssid, priv->essid, priv->essid_len), + "disassociated: '%*pE' %pM\n", priv->essid_len, priv->essid, priv->bssid); priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); @@ -6975,7 +6970,6 @@ static int ipw2100_wx_set_essid(struct net_device *dev, char *essid = ""; /* ANY */ int length = 0; int err = 0; - DECLARE_SSID_BUF(ssid); mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { @@ -7005,8 +6999,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev, goto done; } - IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", - print_ssid(ssid, essid, length), length); + IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, essid, length); priv->essid_len = length; memcpy(priv->essid, essid, priv->essid_len); @@ -7027,13 +7020,12 @@ static int ipw2100_wx_get_essid(struct net_device *dev, */ struct ipw2100_priv *priv = libipw_priv(dev); - DECLARE_SSID_BUF(ssid); /* If we are associated, trying to associate, or have a statically * configured ESSID then return that; otherwise return ANY */ if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) { - IPW_DEBUG_WX("Getting essid: '%s'\n", - print_ssid(ssid, priv->essid, priv->essid_len)); + IPW_DEBUG_WX("Getting essid: '%*pE'\n", + priv->essid_len, priv->essid); memcpy(extra, priv->essid, priv->essid_len); wrqu->essid.length = priv->essid_len; wrqu->essid.flags = 1; /* active */ diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index f0c3c77a48d3..edc344334a75 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -4496,7 +4496,6 @@ static void handle_scan_event(struct ipw_priv *priv) static void ipw_rx_notification(struct ipw_priv *priv, struct ipw_rx_notification *notif) { - DECLARE_SSID_BUF(ssid); u16 size = le16_to_cpu(notif->size); IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size); @@ -4509,9 +4508,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, case CMAS_ASSOCIATED:{ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, - "associated: '%s' %pM\n", - print_ssid(ssid, priv->essid, - priv->essid_len), + "associated: '%*pE' %pM\n", + priv->essid_len, priv->essid, priv->bssid); switch (priv->ieee->iw_mode) { @@ -4585,14 +4583,9 @@ static void ipw_rx_notification(struct ipw_priv *priv, IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, - "deauthenticated: '%s' " - "%pM" - ": (0x%04X) - %s\n", - print_ssid(ssid, - priv-> - essid, - priv-> - essid_len), + "deauthenticated: '%*pE' %pM: (0x%04X) - %s\n", + priv->essid_len, + priv->essid, priv->bssid, le16_to_cpu(auth->status), ipw_get_status_code @@ -4610,9 +4603,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, - "authenticated: '%s' %pM\n", - print_ssid(ssid, priv->essid, - priv->essid_len), + "authenticated: '%*pE' %pM\n", + priv->essid_len, priv->essid, priv->bssid); break; } @@ -4638,9 +4630,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, - "disassociated: '%s' %pM\n", - print_ssid(ssid, priv->essid, - priv->essid_len), + "disassociated: '%*pE' %pM\n", + priv->essid_len, priv->essid, priv->bssid); priv->status &= @@ -4676,9 +4667,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, switch (auth->state) { case CMAS_AUTHENTICATED: IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, - "authenticated: '%s' %pM\n", - print_ssid(ssid, priv->essid, - priv->essid_len), + "authenticated: '%*pE' %pM\n", + priv->essid_len, priv->essid, priv->bssid); priv->status |= STATUS_AUTH; break; @@ -4695,9 +4685,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, } IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, - "deauthenticated: '%s' %pM\n", - print_ssid(ssid, priv->essid, - priv->essid_len), + "deauthenticated: '%*pE' %pM\n", + priv->essid_len, priv->essid, priv->bssid); priv->status &= ~(STATUS_ASSOCIATING | @@ -5516,16 +5505,13 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, int roaming) { struct ipw_supported_rates rates; - DECLARE_SSID_BUF(ssid); /* Verify that this network's capability is compatible with the * current mode (AdHoc or Infrastructure) */ if ((priv->ieee->iw_mode == IW_MODE_ADHOC && !(network->capability & WLAN_CAPABILITY_IBSS))) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded due to " - "capability mismatch.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded due to capability mismatch.\n", + network->ssid_len, network->ssid, network->bssid); return 0; } @@ -5536,10 +5522,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, if ((network->ssid_len != match->network->ssid_len) || memcmp(network->ssid, match->network->ssid, network->ssid_len)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of non-network ESSID.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of non-network ESSID.\n", + network->ssid_len, network->ssid, network->bssid); return 0; } @@ -5550,17 +5534,10 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, ((network->ssid_len != priv->essid_len) || memcmp(network->ssid, priv->essid, min(network->ssid_len, priv->essid_len)))) { - char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - - strlcpy(escaped, - print_ssid(ssid, network->ssid, - network->ssid_len), - sizeof(escaped)); - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of ESSID mismatch: '%s'.\n", - escaped, network->bssid, - print_ssid(ssid, priv->essid, - priv->essid_len)); + IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of ESSID mismatch: '%*pE'.\n", + network->ssid_len, network->ssid, + network->bssid, priv->essid_len, + priv->essid); return 0; } } @@ -5569,26 +5546,20 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, * testing everything else. */ if (network->time_stamp[0] < match->network->time_stamp[0]) { - IPW_DEBUG_MERGE("Network '%s excluded because newer than " - "current network.\n", - print_ssid(ssid, match->network->ssid, - match->network->ssid_len)); + IPW_DEBUG_MERGE("Network '%*pE excluded because newer than current network.\n", + match->network->ssid_len, match->network->ssid); return 0; } else if (network->time_stamp[1] < match->network->time_stamp[1]) { - IPW_DEBUG_MERGE("Network '%s excluded because newer than " - "current network.\n", - print_ssid(ssid, match->network->ssid, - match->network->ssid_len)); + IPW_DEBUG_MERGE("Network '%*pE excluded because newer than current network.\n", + match->network->ssid_len, match->network->ssid); return 0; } /* Now go through and see if the requested network is valid... */ if (priv->ieee->scan_age != 0 && time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of age: %ums.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of age: %ums.\n", + network->ssid_len, network->ssid, network->bssid, jiffies_to_msecs(jiffies - network->last_scanned)); @@ -5597,10 +5568,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, if ((priv->config & CFG_STATIC_CHANNEL) && (network->channel != priv->channel)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of channel mismatch: %d != %d.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of channel mismatch: %d != %d.\n", + network->ssid_len, network->ssid, network->bssid, network->channel, priv->channel); return 0; @@ -5609,10 +5578,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, /* Verify privacy compatibility */ if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) != ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of privacy mismatch: %s != %s.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of privacy mismatch: %s != %s.\n", + network->ssid_len, network->ssid, network->bssid, priv-> capability & CAP_PRIVACY_ON ? "on" : "off", @@ -5623,22 +5590,16 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, } if (ether_addr_equal(network->bssid, priv->bssid)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of the same BSSID match: %pM" - ".\n", print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid, - priv->bssid); + IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of the same BSSID match: %pM.\n", + network->ssid_len, network->ssid, + network->bssid, priv->bssid); return 0; } /* Filter out any incompatible freq / mode combinations */ if (!libipw_is_valid_mode(priv->ieee, network->mode)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of invalid frequency/mode " - "combination.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of invalid frequency/mode combination.\n", + network->ssid_len, network->ssid, network->bssid); return 0; } @@ -5646,20 +5607,15 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, /* Ensure that the rates supported by the driver are compatible with * this AP, including verification of basic rates (mandatory) */ if (!ipw_compatible_rates(priv, network, &rates)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because configured rate mask excludes " - "AP mandatory rate.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because configured rate mask excludes AP mandatory rate.\n", + network->ssid_len, network->ssid, network->bssid); return 0; } if (rates.num_rates == 0) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of no compatible rates.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of no compatible rates.\n", + network->ssid_len, network->ssid, network->bssid); return 0; } @@ -5671,16 +5627,14 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, /* Set up 'new' AP to this network */ ipw_copy_rates(&match->rates, &rates); match->network = network; - IPW_DEBUG_MERGE("Network '%s (%pM)' is a viable match.\n", - print_ssid(ssid, network->ssid, network->ssid_len), - network->bssid); + IPW_DEBUG_MERGE("Network '%*pE (%pM)' is a viable match.\n", + network->ssid_len, network->ssid, network->bssid); return 1; } static void ipw_merge_adhoc_network(struct work_struct *work) { - DECLARE_SSID_BUF(ssid); struct ipw_priv *priv = container_of(work, struct ipw_priv, merge_networks); struct libipw_network *network = NULL; @@ -5710,9 +5664,8 @@ static void ipw_merge_adhoc_network(struct work_struct *work) mutex_lock(&priv->mutex); if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) { - IPW_DEBUG_MERGE("remove network %s\n", - print_ssid(ssid, priv->essid, - priv->essid_len)); + IPW_DEBUG_MERGE("remove network %*pE\n", + priv->essid_len, priv->essid); ipw_remove_current_network(priv); } @@ -5728,7 +5681,6 @@ static int ipw_best_network(struct ipw_priv *priv, struct libipw_network *network, int roaming) { struct ipw_supported_rates rates; - DECLARE_SSID_BUF(ssid); /* Verify that this network's capability is compatible with the * current mode (AdHoc or Infrastructure) */ @@ -5736,10 +5688,8 @@ static int ipw_best_network(struct ipw_priv *priv, !(network->capability & WLAN_CAPABILITY_ESS)) || (priv->ieee->iw_mode == IW_MODE_ADHOC && !(network->capability & WLAN_CAPABILITY_IBSS))) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded due to " - "capability mismatch.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded due to capability mismatch.\n", + network->ssid_len, network->ssid, network->bssid); return 0; } @@ -5750,10 +5700,8 @@ static int ipw_best_network(struct ipw_priv *priv, if ((network->ssid_len != match->network->ssid_len) || memcmp(network->ssid, match->network->ssid, network->ssid_len)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of non-network ESSID.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of non-network ESSID.\n", + network->ssid_len, network->ssid, network->bssid); return 0; } @@ -5764,16 +5712,10 @@ static int ipw_best_network(struct ipw_priv *priv, ((network->ssid_len != priv->essid_len) || memcmp(network->ssid, priv->essid, min(network->ssid_len, priv->essid_len)))) { - char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - strlcpy(escaped, - print_ssid(ssid, network->ssid, - network->ssid_len), - sizeof(escaped)); - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of ESSID mismatch: '%s'.\n", - escaped, network->bssid, - print_ssid(ssid, priv->essid, - priv->essid_len)); + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of ESSID mismatch: '%*pE'.\n", + network->ssid_len, network->ssid, + network->bssid, priv->essid_len, + priv->essid); return 0; } } @@ -5781,16 +5723,10 @@ static int ipw_best_network(struct ipw_priv *priv, /* If the old network rate is better than this one, don't bother * testing everything else. */ if (match->network && match->network->stats.rssi > network->stats.rssi) { - char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - strlcpy(escaped, - print_ssid(ssid, network->ssid, network->ssid_len), - sizeof(escaped)); - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded because " - "'%s (%pM)' has a stronger signal.\n", - escaped, network->bssid, - print_ssid(ssid, match->network->ssid, - match->network->ssid_len), - match->network->bssid); + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because '%*pE (%pM)' has a stronger signal.\n", + network->ssid_len, network->ssid, + network->bssid, match->network->ssid_len, + match->network->ssid, match->network->bssid); return 0; } @@ -5798,11 +5734,8 @@ static int ipw_best_network(struct ipw_priv *priv, * last 3 seconds, do not try and associate again... */ if (network->last_associate && time_after(network->last_associate + (HZ * 3UL), jiffies)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of storming (%ums since last " - "assoc attempt).\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of storming (%ums since last assoc attempt).\n", + network->ssid_len, network->ssid, network->bssid, jiffies_to_msecs(jiffies - network->last_associate)); @@ -5812,10 +5745,8 @@ static int ipw_best_network(struct ipw_priv *priv, /* Now go through and see if the requested network is valid... */ if (priv->ieee->scan_age != 0 && time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of age: %ums.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of age: %ums.\n", + network->ssid_len, network->ssid, network->bssid, jiffies_to_msecs(jiffies - network->last_scanned)); @@ -5824,10 +5755,8 @@ static int ipw_best_network(struct ipw_priv *priv, if ((priv->config & CFG_STATIC_CHANNEL) && (network->channel != priv->channel)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of channel mismatch: %d != %d.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of channel mismatch: %d != %d.\n", + network->ssid_len, network->ssid, network->bssid, network->channel, priv->channel); return 0; @@ -5836,10 +5765,8 @@ static int ipw_best_network(struct ipw_priv *priv, /* Verify privacy compatibility */ if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) != ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of privacy mismatch: %s != %s.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of privacy mismatch: %s != %s.\n", + network->ssid_len, network->ssid, network->bssid, priv->capability & CAP_PRIVACY_ON ? "on" : "off", @@ -5850,31 +5777,24 @@ static int ipw_best_network(struct ipw_priv *priv, if ((priv->config & CFG_STATIC_BSSID) && !ether_addr_equal(network->bssid, priv->bssid)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of BSSID mismatch: %pM.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of BSSID mismatch: %pM.\n", + network->ssid_len, network->ssid, network->bssid, priv->bssid); return 0; } /* Filter out any incompatible freq / mode combinations */ if (!libipw_is_valid_mode(priv->ieee, network->mode)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of invalid frequency/mode " - "combination.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of invalid frequency/mode combination.\n", + network->ssid_len, network->ssid, network->bssid); return 0; } /* Filter out invalid channel in current GEO */ if (!libipw_is_valid_channel(priv->ieee, network->channel)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of invalid channel in current GEO\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of invalid channel in current GEO\n", + network->ssid_len, network->ssid, network->bssid); return 0; } @@ -5882,20 +5802,15 @@ static int ipw_best_network(struct ipw_priv *priv, /* Ensure that the rates supported by the driver are compatible with * this AP, including verification of basic rates (mandatory) */ if (!ipw_compatible_rates(priv, network, &rates)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because configured rate mask excludes " - "AP mandatory rate.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because configured rate mask excludes AP mandatory rate.\n", + network->ssid_len, network->ssid, network->bssid); return 0; } if (rates.num_rates == 0) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of no compatible rates.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of no compatible rates.\n", + network->ssid_len, network->ssid, network->bssid); return 0; } @@ -5908,9 +5823,8 @@ static int ipw_best_network(struct ipw_priv *priv, ipw_copy_rates(&match->rates, &rates); match->network = network; - IPW_DEBUG_ASSOC("Network '%s (%pM)' is a viable match.\n", - print_ssid(ssid, network->ssid, network->ssid_len), - network->bssid); + IPW_DEBUG_ASSOC("Network '%*pE (%pM)' is a viable match.\n", + network->ssid_len, network->ssid, network->bssid); return 1; } @@ -6152,7 +6066,6 @@ static void ipw_bg_adhoc_check(struct work_struct *work) static void ipw_debug_config(struct ipw_priv *priv) { - DECLARE_SSID_BUF(ssid); IPW_DEBUG_INFO("Scan completed, no valid APs matched " "[CFG 0x%08X]\n", priv->config); if (priv->config & CFG_STATIC_CHANNEL) @@ -6160,8 +6073,8 @@ static void ipw_debug_config(struct ipw_priv *priv) else IPW_DEBUG_INFO("Channel unlocked.\n"); if (priv->config & CFG_STATIC_ESSID) - IPW_DEBUG_INFO("ESSID locked to '%s'\n", - print_ssid(ssid, priv->essid, priv->essid_len)); + IPW_DEBUG_INFO("ESSID locked to '%*pE'\n", + priv->essid_len, priv->essid); else IPW_DEBUG_INFO("ESSID unlocked.\n"); if (priv->config & CFG_STATIC_BSSID) @@ -7385,7 +7298,6 @@ static int ipw_associate_network(struct ipw_priv *priv, struct ipw_supported_rates *rates, int roaming) { int err; - DECLARE_SSID_BUF(ssid); if (priv->config & CFG_FIXED_RATE) ipw_set_fixed_rate(priv, network->mode); @@ -7451,10 +7363,9 @@ static int ipw_associate_network(struct ipw_priv *priv, priv->assoc_request.capability &= ~cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME); - IPW_DEBUG_ASSOC("%ssociation attempt: '%s', channel %d, " - "802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n", + IPW_DEBUG_ASSOC("%ssociation attempt: '%*pE', channel %d, 802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n", roaming ? "Rea" : "A", - print_ssid(ssid, priv->essid, priv->essid_len), + priv->essid_len, priv->essid, network->channel, ipw_modes[priv->assoc_request.ieee_mode], rates->num_rates, @@ -7553,9 +7464,8 @@ static int ipw_associate_network(struct ipw_priv *priv, return err; } - IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM\n", - print_ssid(ssid, priv->essid, priv->essid_len), - priv->bssid); + IPW_DEBUG(IPW_DL_STATE, "associating: '%*pE' %pM\n", + priv->essid_len, priv->essid, priv->bssid); return 0; } @@ -7645,7 +7555,6 @@ static int ipw_associate(void *data) struct ipw_supported_rates *rates; struct list_head *element; unsigned long flags; - DECLARE_SSID_BUF(ssid); if (priv->ieee->iw_mode == IW_MODE_MONITOR) { IPW_DEBUG_ASSOC("Not attempting association (monitor mode)\n"); @@ -7704,10 +7613,8 @@ static int ipw_associate(void *data) /* If there are no more slots, expire the oldest */ list_del(&oldest->list); target = oldest; - IPW_DEBUG_ASSOC("Expired '%s' (%pM) from " - "network list.\n", - print_ssid(ssid, target->ssid, - target->ssid_len), + IPW_DEBUG_ASSOC("Expired '%*pE' (%pM) from network list.\n", + target->ssid_len, target->ssid, target->bssid); list_add_tail(&target->list, &priv->ieee->network_free_list); @@ -9093,7 +9000,6 @@ static int ipw_wx_set_essid(struct net_device *dev, { struct ipw_priv *priv = libipw_priv(dev); int length; - DECLARE_SSID_BUF(ssid); mutex_lock(&priv->mutex); @@ -9118,8 +9024,7 @@ static int ipw_wx_set_essid(struct net_device *dev, return 0; } - IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", - print_ssid(ssid, extra, length), length); + IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, extra, length); priv->essid_len = length; memcpy(priv->essid, extra, priv->essid_len); @@ -9138,15 +9043,14 @@ static int ipw_wx_get_essid(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = libipw_priv(dev); - DECLARE_SSID_BUF(ssid); /* If we are associated, trying to associate, or have a statically * configured ESSID then return that; otherwise return ANY */ mutex_lock(&priv->mutex); if (priv->config & CFG_STATIC_ESSID || priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { - IPW_DEBUG_WX("Getting essid: '%s'\n", - print_ssid(ssid, priv->essid, priv->essid_len)); + IPW_DEBUG_WX("Getting essid: '%*pE'\n", + priv->essid_len, priv->essid); memcpy(extra, priv->essid, priv->essid_len); wrqu->essid.length = priv->essid_len; wrqu->essid.flags = 1; /* active */ diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index a586a85bfcfe..2d66984079bb 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -1120,7 +1120,6 @@ static int libipw_parse_info_param(struct libipw_info_element *info_element, u16 length, struct libipw_network *network) { - DECLARE_SSID_BUF(ssid); u8 i; #ifdef CONFIG_LIBIPW_DEBUG char rates_str[64]; @@ -1151,10 +1150,9 @@ static int libipw_parse_info_param(struct libipw_info_element memset(network->ssid + network->ssid_len, 0, IW_ESSID_MAX_SIZE - network->ssid_len); - LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%s' len=%d.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->ssid_len); + LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%*pE' len=%d.\n", + network->ssid_len, network->ssid, + network->ssid_len); break; case WLAN_EID_SUPP_RATES: @@ -1399,8 +1397,6 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r struct libipw_network *network, struct libipw_rx_stats *stats) { - DECLARE_SSID_BUF(ssid); - network->qos_data.active = 0; network->qos_data.supported = 0; network->qos_data.param_count = 0; @@ -1447,11 +1443,9 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r } if (network->mode == 0) { - LIBIPW_DEBUG_SCAN("Filtered out '%s (%pM)' " - "network.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); + LIBIPW_DEBUG_SCAN("Filtered out '%*pE (%pM)' network.\n", + network->ssid_len, network->ssid, + network->bssid); return 1; } @@ -1563,11 +1557,9 @@ static void libipw_process_probe_response(struct libipw_device struct libipw_info_element *info_element = beacon->info_element; #endif unsigned long flags; - DECLARE_SSID_BUF(ssid); - LIBIPW_DEBUG_SCAN("'%s' (%pM" - "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", - print_ssid(ssid, info_element->data, info_element->len), + LIBIPW_DEBUG_SCAN("'%*pE' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", + info_element->len, info_element->data, beacon->header.addr3, (beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0', (beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0', @@ -1587,12 +1579,11 @@ static void libipw_process_probe_response(struct libipw_device (beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0'); if (libipw_network_init(ieee, beacon, &network, stats)) { - LIBIPW_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n", - print_ssid(ssid, info_element->data, - info_element->len), - beacon->header.addr3, - is_beacon(beacon->header.frame_ctl) ? - "BEACON" : "PROBE RESPONSE"); + LIBIPW_DEBUG_SCAN("Dropped '%*pE' (%pM) via %s.\n", + info_element->len, info_element->data, + beacon->header.addr3, + is_beacon(beacon->header.frame_ctl) ? + "BEACON" : "PROBE RESPONSE"); return; } @@ -1624,11 +1615,9 @@ static void libipw_process_probe_response(struct libipw_device /* If there are no more slots, expire the oldest */ list_del(&oldest->list); target = oldest; - LIBIPW_DEBUG_SCAN("Expired '%s' (%pM) from " - "network list.\n", - print_ssid(ssid, target->ssid, - target->ssid_len), - target->bssid); + LIBIPW_DEBUG_SCAN("Expired '%*pE' (%pM) from network list.\n", + target->ssid_len, target->ssid, + target->bssid); libipw_network_reset(target); } else { /* Otherwise just pull from the free list */ @@ -1638,23 +1627,21 @@ static void libipw_process_probe_response(struct libipw_device } #ifdef CONFIG_LIBIPW_DEBUG - LIBIPW_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n", - print_ssid(ssid, network.ssid, - network.ssid_len), - network.bssid, - is_beacon(beacon->header.frame_ctl) ? - "BEACON" : "PROBE RESPONSE"); + LIBIPW_DEBUG_SCAN("Adding '%*pE' (%pM) via %s.\n", + network.ssid_len, network.ssid, + network.bssid, + is_beacon(beacon->header.frame_ctl) ? + "BEACON" : "PROBE RESPONSE"); #endif memcpy(target, &network, sizeof(*target)); network.ibss_dfs = NULL; list_add_tail(&target->list, &ieee->network_list); } else { - LIBIPW_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n", - print_ssid(ssid, target->ssid, - target->ssid_len), - target->bssid, - is_beacon(beacon->header.frame_ctl) ? - "BEACON" : "PROBE RESPONSE"); + LIBIPW_DEBUG_SCAN("Updating '%*pE' (%pM) via %s.\n", + target->ssid_len, target->ssid, + target->bssid, + is_beacon(beacon->header.frame_ctl) ? + "BEACON" : "PROBE RESPONSE"); update_network(target, &network); network.ibss_dfs = NULL; } diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c index 54aba4744438..dd29f46d086b 100644 --- a/drivers/net/wireless/ipw2x00/libipw_wx.c +++ b/drivers/net/wireless/ipw2x00/libipw_wx.c @@ -272,7 +272,6 @@ int libipw_wx_get_scan(struct libipw_device *ieee, char *ev = extra; char *stop = ev + wrqu->data.length; int i = 0; - DECLARE_SSID_BUF(ssid); LIBIPW_DEBUG_WX("Getting scan\n"); @@ -290,12 +289,10 @@ int libipw_wx_get_scan(struct libipw_device *ieee, ev = libipw_translate_scan(ieee, ev, stop, network, info); else { - LIBIPW_DEBUG_SCAN("Not showing network '%s (" - "%pM)' due to age (%ums).\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid, - elapsed_jiffies_msecs( + LIBIPW_DEBUG_SCAN("Not showing network '%*pE (%pM)' due to age (%ums).\n", + network->ssid_len, network->ssid, + network->bssid, + elapsed_jiffies_msecs( network->last_scanned)); } } @@ -322,7 +319,6 @@ int libipw_wx_set_encode(struct libipw_device *ieee, int i, key, key_provided, len; struct lib80211_crypt_data **crypt; int host_crypto = ieee->host_encrypt || ieee->host_decrypt; - DECLARE_SSID_BUF(ssid); LIBIPW_DEBUG_WX("SET_ENCODE\n"); @@ -417,8 +413,8 @@ int libipw_wx_set_encode(struct libipw_device *ieee, if (len > erq->length) memset(sec.keys[key] + erq->length, 0, len - erq->length); - LIBIPW_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n", - key, print_ssid(ssid, sec.keys[key], len), + LIBIPW_DEBUG_WX("Setting key %d to '%*pE' (%d:%d bytes)\n", + key, len, sec.keys[key], erq->length, len); sec.key_sizes[key] = len; if (*crypt) -- cgit v1.2.3 From e5ead669a3de3cc822f19b7289932ffbf9664328 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 13 Oct 2014 15:55:24 -0700 Subject: wireless: hostap: proc: print properly escaped SSID Instead of substituting non-printable characters by '_' let's print SSID properly escaped by using recently added %*pE specifier. [akpm@linux-foundation.org: fix printk type warning] [akpm@linux-foundation.org: remove now-unused local `i'] Signed-off-by: Andy Shevchenko Cc: "John W . Linville" Cc: Johannes Berg Cc: Greg Kroah-Hartman Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/wireless/hostap/hostap_proc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c index 8efd17c52f65..dd84557cf957 100644 --- a/drivers/net/wireless/hostap/hostap_proc.c +++ b/drivers/net/wireless/hostap/hostap_proc.c @@ -168,7 +168,6 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v) local_info_t *local = m->private; struct list_head *ptr = v; struct hostap_bss_info *bss; - int i; if (ptr == &local->bss_list) { seq_printf(m, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t" @@ -181,9 +180,7 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v) bss->bssid, bss->last_update, bss->count, bss->capab_info); - for (i = 0; i < bss->ssid_len; i++) - seq_putc(m,bss->ssid[i] >= 32 && bss->ssid[i] < 127 ? - bss->ssid[i] : '_'); + seq_printf(m, "%*pE", (int)bss->ssid_len, bss->ssid); seq_putc(m, '\t'); seq_printf(m, "%*phN", (int)bss->ssid_len, bss->ssid); -- cgit v1.2.3 From 068c11dac2a5df02c650b8511e10055c95073d5a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 13 Oct 2014 15:55:29 -0700 Subject: staging: wlan-ng: use %*pEhp to print SN This is a generic specifier to print an escaped buffer by given criteria. Let's use it instead of custom approach. Signed-off-by: Andy Shevchenko Cc: "John W . Linville" Cc: Johannes Berg Cc: Greg Kroah-Hartman Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/staging/wlan-ng/prism2sta.c | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 799ce8aa70ef..df577dfe7ffb 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -60,7 +60,6 @@ #include #include #include -#include #include #include @@ -81,27 +80,6 @@ #include "hfa384x.h" #include "prism2mgmt.h" -/* Create a string of printable chars from something that might not be */ -/* It's recommended that the str be 4*len + 1 bytes long */ -#define wlan_mkprintstr(buf, buflen, str, strlen) \ -{ \ - int i = 0; \ - int j = 0; \ - memset(str, 0, (strlen)); \ - for (i = 0; i < (buflen); i++) { \ - if (isprint((buf)[i])) { \ - (str)[j] = (buf)[i]; \ - j++; \ - } else { \ - (str)[j] = '\\'; \ - (str)[j+1] = 'x'; \ - (str)[j+2] = hex_asc_hi((buf)[i]); \ - (str)[j+3] = hex_asc_lo((buf)[i]); \ - j += 4; \ - } \ - } \ -} - static char *dev_info = "prism2_usb"; static wlandevice_t *create_wlan(void); @@ -607,7 +585,6 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) hfa384x_t *hw = (hfa384x_t *) wlandev->priv; u16 temp; u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN]; - char pstr[(HFA384x_RID_NICSERIALNUMBER_LEN * 4) + 1]; /* Collect version and compatibility info */ /* Some are critical, some are not */ @@ -862,9 +839,8 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER, snum, HFA384x_RID_NICSERIALNUMBER_LEN); if (!result) { - wlan_mkprintstr(snum, HFA384x_RID_NICSERIALNUMBER_LEN, - pstr, sizeof(pstr)); - netdev_info(wlandev->netdev, "Prism2 card SN: %s\n", pstr); + netdev_info(wlandev->netdev, "Prism2 card SN: %*pEhp\n", + HFA384x_RID_NICSERIALNUMBER_LEN, snum); } else { netdev_err(wlandev->netdev, "Failed to retrieve Prism2 Card SN\n"); goto failed; -- cgit v1.2.3 From 50d5e53ddfc0d9cf4707d7d8e22624b26ab9114e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 13 Oct 2014 15:55:31 -0700 Subject: staging: rtl8192e: use %*pEn to escape buffer Let's use kernel's native specifier to escape a buffer. Signed-off-by: Andy Shevchenko Cc: "John W . Linville" Cc: Johannes Berg Cc: Greg Kroah-Hartman Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/staging/rtl8192e/rtllib.h | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 91d35df286c3..2d82f8993ea1 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -2957,25 +2957,13 @@ extern inline int rtllib_get_scans(struct rtllib_device *ieee) static inline const char *escape_essid(const char *essid, u8 essid_len) { static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - const char *s = essid; - char *d = escaped; if (rtllib_is_empty_essid(essid, essid_len)) { memcpy(escaped, "", sizeof("")); return escaped; } - essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE); - while (essid_len--) { - if (*s == '\0') { - *d++ = '\\'; - *d++ = '0'; - s++; - } else { - *d++ = *s++; - } - } - *d = '\0'; + snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid); return escaped; } -- cgit v1.2.3 From 8a1db92830d0a71e1429725992eb91470214c820 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 13 Oct 2014 15:55:33 -0700 Subject: staging: rtl8192u: use %*pEn to escape buffer Let's use kernel's native specifier to escape a buffer. Signed-off-by: Andy Shevchenko Cc: "John W . Linville" Cc: Johannes Berg Cc: Greg Kroah-Hartman Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/staging/rtl8192u/ieee80211/ieee80211.h | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 9ecfa4a2421d..b44aa17d30a7 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -2593,25 +2593,13 @@ static inline int ieee80211_get_scans(struct ieee80211_device *ieee) static inline const char *escape_essid(const char *essid, u8 essid_len) { static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - const char *s = essid; - char *d = escaped; if (ieee80211_is_empty_essid(essid, essid_len)) { memcpy(escaped, "", sizeof("")); return escaped; } - essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE); - while (essid_len--) { - if (*s == '\0') { - *d++ = '\\'; - *d++ = '0'; - s++; - } else { - *d++ = *s++; - } - } - *d = '\0'; + snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid); return escaped; } -- cgit v1.2.3