From 1758ef68a07f42983371dc1d2bf0ae80b4d8ea16 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 29 Oct 2008 15:33:28 -0700 Subject: sparc64: remove byteshifting from out* helpers __raw_write avoids the need to byteswap, as we are reading from a host-endian area, just deref the pointers directly, taking care of alignment. As before, outsw must be called with a 2-byte aligned pointer. Signed-off-by: Harvey Harrison Signed-off-by: David S. Miller --- arch/sparc64/lib/PeeCeeI.c | 139 +++++++++++++++------------------------------ 1 file changed, 47 insertions(+), 92 deletions(-) (limited to 'arch/sparc64') diff --git a/arch/sparc64/lib/PeeCeeI.c b/arch/sparc64/lib/PeeCeeI.c index 8b313f11bc8d..46053e6ddd7b 100644 --- a/arch/sparc64/lib/PeeCeeI.c +++ b/arch/sparc64/lib/PeeCeeI.c @@ -20,107 +20,62 @@ void outsw(unsigned long __addr, const void *src, unsigned long count) { void __iomem *addr = (void __iomem *) __addr; - if (count) { - u16 *ps = (u16 *)src; - u32 *pi; - - if (((u64)src) & 0x2) { - u16 val = le16_to_cpup(ps); - outw(val, addr); - ps++; - count--; - } - pi = (u32 *)ps; - while (count >= 2) { - u32 w = le32_to_cpup(pi); - - pi++; - outw(w >> 0, addr); - outw(w >> 16, addr); - count -= 2; - } - ps = (u16 *)pi; - if (count) { - u16 val = le16_to_cpup(ps); - outw(val, addr); - } + while (count--) { + __raw_writew(*(u16 *)src, addr); + src += sizeof(u16); } } void outsl(unsigned long __addr, const void *src, unsigned long count) { void __iomem *addr = (void __iomem *) __addr; + u32 l, l2; - if (count) { - if ((((u64)src) & 0x3) == 0) { - u32 *p = (u32 *)src; - while (count--) { - u32 val = cpu_to_le32p(p); - outl(val, addr); - p++; - } - } else { - u8 *pb; - u16 *ps = (u16 *)src; - u32 l = 0, l2; - u32 *pi; - - switch (((u64)src) & 0x3) { - case 0x2: - count -= 1; - l = cpu_to_le16p(ps) << 16; - ps++; - pi = (u32 *)ps; - while (count--) { - l2 = cpu_to_le32p(pi); - pi++; - outl(((l >> 16) | (l2 << 16)), addr); - l = l2; - } - ps = (u16 *)pi; - l2 = cpu_to_le16p(ps); - outl(((l >> 16) | (l2 << 16)), addr); - break; - - case 0x1: - count -= 1; - pb = (u8 *)src; - l = (*pb++ << 8); - ps = (u16 *)pb; - l2 = cpu_to_le16p(ps); - ps++; - l |= (l2 << 16); - pi = (u32 *)ps; - while (count--) { - l2 = cpu_to_le32p(pi); - pi++; - outl(((l >> 8) | (l2 << 24)), addr); - l = l2; - } - pb = (u8 *)pi; - outl(((l >> 8) | (*pb << 24)), addr); - break; + if (!count) + return; - case 0x3: - count -= 1; - pb = (u8 *)src; - l = (*pb++ << 24); - pi = (u32 *)pb; - while (count--) { - l2 = cpu_to_le32p(pi); - pi++; - outl(((l >> 24) | (l2 << 8)), addr); - l = l2; - } - ps = (u16 *)pi; - l2 = cpu_to_le16p(ps); - ps++; - pb = (u8 *)ps; - l2 |= (*pb << 16); - outl(((l >> 24) | (l2 << 8)), addr); - break; - } + switch (((unsigned long)src) & 0x3) { + case 0x0: + /* src is naturally aligned */ + while (count--) { + __raw_writel(*(u32 *)src, addr); + src += sizeof(u32); + } + break; + case 0x2: + /* 2-byte alignment */ + while (count--) { + l = (*(u16 *)src) << 16; + l |= *(u16 *)(src + sizeof(u16)); + __raw_writel(l, addr); + src += sizeof(u32); + } + break; + case 0x1: + /* Hold three bytes in l each time, grab a byte from l2 */ + l = (*(u8 *)src) << 24; + l |= (*(u16 *)(src + sizeof(u8))) << 8; + src += sizeof(u8) + sizeof(u16); + while (count--) { + l2 = *(u32 *)src; + l |= (l2 >> 24); + __raw_writel(l, addr); + l = l2 << 8; + src += sizeof(u32); + } + break; + case 0x3: + /* Hold a byte in l each time, grab 3 bytes from l2 */ + l = (*(u8 *)src) << 24; + src += sizeof(u8); + while (count--) { + l2 = *(u32 *)src; + l |= (l2 >> 8); + __raw_writel(l, addr); + l = l2 << 24; + src += sizeof(u32); } + break; } } -- cgit v1.2.3-59-g8ed1b From 12a9ee3cce256ae0f178d604f2c8764fb2942cfe Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Wed, 29 Oct 2008 15:35:24 -0700 Subject: rtc-m48t59: shift zero year to 1968 on sparc (rev 2) Shift the first year to 1968 for Sun SPARC machines. Move this logic from platform specific files to rtc driver as this fixes problems with calculating a century bit. Signed-off-by: Krzysztof Helt Tested-by: Alexander Beregalov Signed-off-by: David S. Miller --- arch/sparc/kernel/time.c | 27 ++++----------------------- arch/sparc64/kernel/time.c | 33 +++++---------------------------- drivers/rtc/rtc-m48t59.c | 34 ++++++++++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 55 deletions(-) (limited to 'arch/sparc64') diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 62c1d94cb434..00f7383c7657 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -119,35 +119,16 @@ static unsigned char mostek_read_byte(struct device *dev, u32 ofs) { struct platform_device *pdev = to_platform_device(dev); struct m48t59_plat_data *pdata = pdev->dev.platform_data; - void __iomem *regs = pdata->ioaddr; - unsigned char val = readb(regs + ofs); - - /* the year 0 is 1968 */ - if (ofs == pdata->offset + M48T59_YEAR) { - val += 0x68; - if ((val & 0xf) > 9) - val += 6; - } - return val; + + return readb(pdata->ioaddr + ofs); } static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) { struct platform_device *pdev = to_platform_device(dev); struct m48t59_plat_data *pdata = pdev->dev.platform_data; - void __iomem *regs = pdata->ioaddr; - - if (ofs == pdata->offset + M48T59_YEAR) { - if (val < 0x68) - val += 0x32; - else - val -= 0x68; - if ((val & 0xf) > 9) - val += 6; - if ((val & 0xf0) > 0x9A) - val += 0x60; - } - writeb(val, regs + ofs); + + writeb(val, pdata->ioaddr + ofs); } static struct m48t59_plat_data m48t59_data = { diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 80d71a5ce1e3..dfd1b33e770a 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -503,39 +503,16 @@ static struct of_platform_driver bq4802_driver = { static unsigned char mostek_read_byte(struct device *dev, u32 ofs) { struct platform_device *pdev = to_platform_device(dev); - struct m48t59_plat_data *pdata = pdev->dev.platform_data; - void __iomem *regs; - unsigned char val; - - regs = (void __iomem *) pdev->resource[0].start; - val = readb(regs + ofs); - - /* the year 0 is 1968 */ - if (ofs == pdata->offset + M48T59_YEAR) { - val += 0x68; - if ((val & 0xf) > 9) - val += 6; - } - return val; + void __iomem *regs = (void __iomem *) pdev->resource[0].start; + + return readb(regs + ofs); } static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) { struct platform_device *pdev = to_platform_device(dev); - struct m48t59_plat_data *pdata = pdev->dev.platform_data; - void __iomem *regs; - - regs = (void __iomem *) pdev->resource[0].start; - if (ofs == pdata->offset + M48T59_YEAR) { - if (val < 0x68) - val += 0x32; - else - val -= 0x68; - if ((val & 0xf) > 9) - val += 6; - if ((val & 0xf0) > 0x9A) - val += 0x60; - } + void __iomem *regs = (void __iomem *) pdev->resource[0].start; + writeb(val, regs + ofs); } diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 04b63dab6932..43afb7ab5289 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -87,6 +87,10 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) dev_dbg(dev, "Century bit is enabled\n"); tm->tm_year += 100; /* one century */ } +#ifdef CONFIG_SPARC + /* Sun SPARC machines count years since 1968 */ + tm->tm_year += 68; +#endif tm->tm_wday = bcd2bin(val & 0x07); tm->tm_hour = bcd2bin(M48T59_READ(M48T59_HOUR) & 0x3F); @@ -110,11 +114,20 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) struct m48t59_private *m48t59 = platform_get_drvdata(pdev); unsigned long flags; u8 val = 0; + int year = tm->tm_year; + +#ifdef CONFIG_SPARC + /* Sun SPARC machines count years since 1968 */ + year -= 68; +#endif dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n", - tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, + year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + if (year < 0) + return -EINVAL; + spin_lock_irqsave(&m48t59->lock, flags); /* Issue the WRITE command */ M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); @@ -125,9 +138,9 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) M48T59_WRITE((bin2bcd(tm->tm_mday) & 0x3F), M48T59_MDAY); /* tm_mon is 0-11 */ M48T59_WRITE((bin2bcd(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); - M48T59_WRITE(bin2bcd(tm->tm_year % 100), M48T59_YEAR); + M48T59_WRITE(bin2bcd(year % 100), M48T59_YEAR); - if (pdata->type == M48T59RTC_TYPE_M48T59 && (tm->tm_year / 100)) + if (pdata->type == M48T59RTC_TYPE_M48T59 && (year / 100)) val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); val |= (bin2bcd(tm->tm_wday) & 0x07); M48T59_WRITE(val, M48T59_WDAY); @@ -159,6 +172,10 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)); +#ifdef CONFIG_SPARC + /* Sun SPARC machines count years since 1968 */ + tm->tm_year += 68; +#endif /* tm_mon is 0-11 */ tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1; @@ -192,11 +209,20 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) struct rtc_time *tm = &alrm->time; u8 mday, hour, min, sec; unsigned long flags; + int year = tm->tm_year; + +#ifdef CONFIG_SPARC + /* Sun SPARC machines count years since 1968 */ + year -= 68; +#endif /* If no irq, we don't support ALARM */ if (m48t59->irq == NO_IRQ) return -EIO; + if (year < 0) + return -EINVAL; + /* * 0xff means "always match" */ @@ -228,7 +254,7 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) spin_unlock_irqrestore(&m48t59->lock, flags); dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d/%02d/%02d\n", - tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, + year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return 0; } -- cgit v1.2.3-59-g8ed1b From 770a424112cb2c3a3e39221299eaf5244b76479a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 30 Oct 2008 22:58:06 -0700 Subject: sparc64: Add missing null terminating entry to bq4802_match[]. Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/sparc64') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index dfd1b33e770a..141da3759091 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -490,6 +490,7 @@ static struct of_device_id __initdata bq4802_match[] = { .name = "rtc", .compatible = "bq4802", }, + {}, }; static struct of_platform_driver bq4802_driver = { -- cgit v1.2.3-59-g8ed1b From 5769907ade8dda7002b304c03ef9e4ee5c1e0821 Mon Sep 17 00:00:00 2001 From: Max Dmitrichenko Date: Sun, 2 Nov 2008 00:34:10 -0700 Subject: sparc64: Fix PCI resource mapping on sparc64 There is a problem discovered in recent versions of ATI Mach64 driver in X.org on sparc64 architecture. In short, the driver fails to mmap MMIO aperture (PCI resource #2). I've found that kernel's __pci_mmap_make_offset() returns EINVAL. It checks whether user attempts to mmap more than the resource length, which is 0x1000 bytes in our case. But PAGE_SIZE on SPARC64 is 0x2000 and this is what actually is being mmaped. So __pci_mmap_make_offset() failed for this PCI resource. Signed-off-by: Max Dmitrichenko Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'arch/sparc64') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 242ac1ccae7d..bdb7c0a6d83d 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -889,6 +889,7 @@ static int __pci_mmap_make_offset(struct pci_dev *pdev, for (i = 0; i <= PCI_ROM_RESOURCE; i++) { struct resource *rp = &pdev->resource[i]; + resource_size_t aligned_end; /* Active? */ if (!rp->flags) @@ -906,8 +907,15 @@ static int __pci_mmap_make_offset(struct pci_dev *pdev, continue; } + /* Align the resource end to the next page address. + * PAGE_SIZE intentionally added instead of (PAGE_SIZE - 1), + * because actually we need the address of the next byte + * after rp->end. + */ + aligned_end = (rp->end + PAGE_SIZE) & PAGE_MASK; + if ((rp->start <= user_paddr) && - (user_paddr + user_size) <= (rp->end + 1UL)) + (user_paddr + user_size) <= aligned_end) break; } -- cgit v1.2.3-59-g8ed1b