From b1fa888e0124763e5bafda074874fc7ac0f2f23f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 24 May 2010 10:55:59 +0900 Subject: watchdog: shwdt: Kill off mmap stub and superfluous comments. The wdt mmaping thing was a special-cased hack that nothing in the wild depends on, so just kill it off. While at it, sanitize the superfluous comments in preparation for a driver rewrite and overhauled interface. Signed-off-by: Paul Mundt diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b87ba23..8828d8f 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -948,14 +948,6 @@ config SH_WDT To compile this driver as a module, choose M here: the module will be called shwdt. -config SH_WDT_MMAP - bool "Allow mmap of SH WDT" - default n - depends on SH_WDT - help - If you say Y here, user applications will be able to mmap the - WDT/CPG registers. - # SPARC Architecture # SPARC64 Architecture diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index a03f84e..bee1f58 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c @@ -1,9 +1,9 @@ /* - * drivers/char/watchdog/shwdt.c + * drivers/watchdog/shwdt.c * * Watchdog driver for integrated watchdog in the SuperH processors. * - * Copyright (C) 2001, 2002, 2003 Paul Mundt + * Copyright (C) 2001 - 2010 Paul Mundt * * 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 @@ -76,14 +76,8 @@ static DEFINE_SPINLOCK(shwdt_lock); #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ - static int nowayout = WATCHDOG_NOWAYOUT; -/** - * sh_wdt_start - Start the Watchdog - * - * Starts the watchdog. - */ static void sh_wdt_start(void) { __u8 csr; @@ -114,15 +108,6 @@ static void sh_wdt_start(void) sh_wdt_write_csr(csr); #ifdef CONFIG_CPU_SH2 - /* - * Whoever came up with the RSTCSR semantics must've been smoking - * some of the good stuff, since in addition to the WTCSR/WTCNT write - * brain-damage, it's managed to fuck things up one step further.. - * - * If we need to clear the WOVF bit, the upper byte has to be 0xa5.. - * but if we want to touch RSTE or RSTS, the upper byte has to be - * 0x5a.. - */ csr = sh_wdt_read_rstcsr(); csr &= ~RSTCSR_RSTS; sh_wdt_write_rstcsr(csr); @@ -130,10 +115,6 @@ static void sh_wdt_start(void) spin_unlock_irqrestore(&shwdt_lock, flags); } -/** - * sh_wdt_stop - Stop the Watchdog - * Stops the watchdog. - */ static void sh_wdt_stop(void) { __u8 csr; @@ -149,10 +130,6 @@ static void sh_wdt_stop(void) spin_unlock_irqrestore(&shwdt_lock, flags); } -/** - * sh_wdt_keepalive - Keep the Userspace Watchdog Alive - * The Userspace watchdog got a KeepAlive: schedule the next heartbeat. - */ static inline void sh_wdt_keepalive(void) { unsigned long flags; @@ -162,10 +139,6 @@ static inline void sh_wdt_keepalive(void) spin_unlock_irqrestore(&shwdt_lock, flags); } -/** - * sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat - * Set the Userspace Watchdog heartbeat - */ static int sh_wdt_set_heartbeat(int t) { unsigned long flags; @@ -179,12 +152,6 @@ static int sh_wdt_set_heartbeat(int t) return 0; } -/** - * sh_wdt_ping - Ping the Watchdog - * @data: Unused - * - * Clears overflow bit, resets timer counter. - */ static void sh_wdt_ping(unsigned long data) { unsigned long flags; @@ -206,13 +173,6 @@ static void sh_wdt_ping(unsigned long data) spin_unlock_irqrestore(&shwdt_lock, flags); } -/** - * sh_wdt_open - Open the Device - * @inode: inode of device - * @file: file handle of device - * - * Watchdog device is opened and started. - */ static int sh_wdt_open(struct inode *inode, struct file *file) { if (test_and_set_bit(0, &shwdt_is_open)) @@ -225,13 +185,6 @@ static int sh_wdt_open(struct inode *inode, struct file *file) return nonseekable_open(inode, file); } -/** - * sh_wdt_close - Close the Device - * @inode: inode of device - * @file: file handle of device - * - * Watchdog device is closed and stopped. - */ static int sh_wdt_close(struct inode *inode, struct file *file) { if (shwdt_expect_close == 42) { @@ -248,15 +201,6 @@ static int sh_wdt_close(struct inode *inode, struct file *file) return 0; } -/** - * sh_wdt_write - Write to Device - * @file: file handle of device - * @buf: buffer to write - * @count: length of buffer - * @ppos: offset - * - * Pings the watchdog on write. - */ static ssize_t sh_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { @@ -280,64 +224,6 @@ static ssize_t sh_wdt_write(struct file *file, const char *buf, return count; } -/** - * sh_wdt_mmap - map WDT/CPG registers into userspace - * @file: file structure for the device - * @vma: VMA to map the registers into - * - * A simple mmap() implementation for the corner cases where the counter - * needs to be mapped in userspace directly. Due to the relatively small - * size of the area, neighbouring registers not necessarily tied to the - * CPG will also be accessible through the register page, so this remains - * configurable for users that really know what they're doing. - * - * Additionaly, the register page maps in the CPG register base relative - * to the nearest page-aligned boundary, which requires that userspace do - * the appropriate CPU subtype math for calculating the page offset for - * the counter value. - */ -static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma) -{ - int ret = -ENOSYS; - -#ifdef CONFIG_SH_WDT_MMAP - unsigned long addr; - - /* Only support the simple cases where we map in a register page. */ - if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff) - return -EINVAL; - - /* - * Pick WTCNT as the start, it's usually the first register after the - * FRQCR, and neither one are generally page-aligned out of the box. - */ - addr = WTCNT & ~(PAGE_SIZE - 1); - - vma->vm_flags |= VM_IO; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, - PAGE_SIZE, vma->vm_page_prot)) { - printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n", - __func__); - return -EAGAIN; - } - - ret = 0; -#endif - - return ret; -} - -/** - * sh_wdt_ioctl - Query Device - * @file: file handle of device - * @cmd: watchdog command - * @arg: argument - * - * Query basic information from the device or ping it, as outlined by the - * watchdog API. - */ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -386,15 +272,6 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, return 0; } -/** - * sh_wdt_notify_sys - Notifier Handler - * @this: notifier block - * @code: notifier event - * @unused: unused - * - * Handles specific events, such as turning off the watchdog during a - * shutdown event. - */ static int sh_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { @@ -411,7 +288,6 @@ static const struct file_operations sh_wdt_fops = { .unlocked_ioctl = sh_wdt_ioctl, .open = sh_wdt_open, .release = sh_wdt_close, - .mmap = sh_wdt_mmap, }; static const struct watchdog_info sh_wdt_info = { @@ -431,11 +307,6 @@ static struct miscdevice sh_wdt_miscdev = { .fops = &sh_wdt_fops, }; -/** - * sh_wdt_init - Initialize module - * Registers the device and notifier handler. Actual device - * initialization is handled by sh_wdt_open(). - */ static int __init sh_wdt_init(void) { int rc; @@ -477,11 +348,6 @@ static int __init sh_wdt_init(void) return 0; } -/** - * sh_wdt_exit - Deinitialize module - * Unregisters the device and notifier handler. Actual device - * deinitialization is handled by sh_wdt_close(). - */ static void __exit sh_wdt_exit(void) { misc_deregister(&sh_wdt_miscdev); -- cgit v0.10.2 From 8f5585ec3d173819dd7e751f661c33af39d7ec60 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 25 May 2010 18:31:12 +0900 Subject: watchdog: shwdt: driver model conversion. This is a long overdue driver model conversion for the shwdt watchdog driver. This is the initial conversion, more incremental changes to follow. Signed-off-by: Paul Mundt diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index bee1f58..b7d2f8a 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c @@ -19,6 +19,7 @@ */ #include #include +#include #include #include #include @@ -28,11 +29,12 @@ #include #include #include +#include #include #include #include -#define PFX "shwdt: " +#define DRV_NAME "sh-wdt" /* * Default clock division ratio is 5.25 msecs. For an additional table of @@ -62,31 +64,36 @@ * misses its deadline, the kernel timer will allow the WDT to overflow. */ static int clock_division_ratio = WTCSR_CKS_4096; - #define next_ping_period(cks) msecs_to_jiffies(cks - 4) -static void sh_wdt_ping(unsigned long data); - -static unsigned long shwdt_is_open; static const struct watchdog_info sh_wdt_info; -static char shwdt_expect_close; -static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0); -static unsigned long next_heartbeat; +static struct platform_device *sh_wdt_dev; static DEFINE_SPINLOCK(shwdt_lock); #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ static int nowayout = WATCHDOG_NOWAYOUT; +static unsigned long next_heartbeat; + +struct sh_wdt { + void __iomem *base; + struct device *dev; -static void sh_wdt_start(void) + struct timer_list timer; + + unsigned long enabled; + char expect_close; +}; + +static void sh_wdt_start(struct sh_wdt *wdt) { - __u8 csr; unsigned long flags; + u8 csr; spin_lock_irqsave(&shwdt_lock, flags); next_heartbeat = jiffies + (heartbeat * HZ); - mod_timer(&timer, next_ping_period(clock_division_ratio)); + mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); csr = sh_wdt_read_csr(); csr |= WTCSR_WT | clock_division_ratio; @@ -115,22 +122,23 @@ static void sh_wdt_start(void) spin_unlock_irqrestore(&shwdt_lock, flags); } -static void sh_wdt_stop(void) +static void sh_wdt_stop(struct sh_wdt *wdt) { - __u8 csr; unsigned long flags; + u8 csr; spin_lock_irqsave(&shwdt_lock, flags); - del_timer(&timer); + del_timer(&wdt->timer); csr = sh_wdt_read_csr(); csr &= ~WTCSR_TME; sh_wdt_write_csr(csr); + spin_unlock_irqrestore(&shwdt_lock, flags); } -static inline void sh_wdt_keepalive(void) +static inline void sh_wdt_keepalive(struct sh_wdt *wdt) { unsigned long flags; @@ -154,11 +162,12 @@ static int sh_wdt_set_heartbeat(int t) static void sh_wdt_ping(unsigned long data) { + struct sh_wdt *wdt = (struct sh_wdt *)data; unsigned long flags; spin_lock_irqsave(&shwdt_lock, flags); if (time_before(jiffies, next_heartbeat)) { - __u8 csr; + u8 csr; csr = sh_wdt_read_csr(); csr &= ~WTCSR_IOVF; @@ -166,37 +175,43 @@ static void sh_wdt_ping(unsigned long data) sh_wdt_write_cnt(0); - mod_timer(&timer, next_ping_period(clock_division_ratio)); + mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); } else - printk(KERN_WARNING PFX "Heartbeat lost! Will not ping " - "the watchdog\n"); + dev_warn(wdt->dev, "Heartbeat lost! Will not ping " + "the watchdog\n"); spin_unlock_irqrestore(&shwdt_lock, flags); } static int sh_wdt_open(struct inode *inode, struct file *file) { - if (test_and_set_bit(0, &shwdt_is_open)) + struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev); + + if (test_and_set_bit(0, &wdt->enabled)) return -EBUSY; if (nowayout) __module_get(THIS_MODULE); - sh_wdt_start(); + file->private_data = wdt; + + sh_wdt_start(wdt); return nonseekable_open(inode, file); } static int sh_wdt_close(struct inode *inode, struct file *file) { - if (shwdt_expect_close == 42) { - sh_wdt_stop(); + struct sh_wdt *wdt = file->private_data; + + if (wdt->expect_close == 42) { + sh_wdt_stop(wdt); } else { - printk(KERN_CRIT PFX "Unexpected close, not " - "stopping watchdog!\n"); - sh_wdt_keepalive(); + dev_crit(wdt->dev, "Unexpected close, not " + "stopping watchdog!\n"); + sh_wdt_keepalive(wdt); } - clear_bit(0, &shwdt_is_open); - shwdt_expect_close = 0; + clear_bit(0, &wdt->enabled); + wdt->expect_close = 0; return 0; } @@ -204,21 +219,23 @@ static int sh_wdt_close(struct inode *inode, struct file *file) static ssize_t sh_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { + struct sh_wdt *wdt = file->private_data; + if (count) { if (!nowayout) { size_t i; - shwdt_expect_close = 0; + wdt->expect_close = 0; for (i = 0; i != count; i++) { char c; if (get_user(c, buf + i)) return -EFAULT; if (c == 'V') - shwdt_expect_close = 42; + wdt->expect_close = 42; } } - sh_wdt_keepalive(); + sh_wdt_keepalive(wdt); } return count; @@ -227,6 +244,7 @@ static ssize_t sh_wdt_write(struct file *file, const char *buf, static long sh_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + struct sh_wdt *wdt = file->private_data; int new_heartbeat; int options, retval = -EINVAL; @@ -242,18 +260,18 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, return -EFAULT; if (options & WDIOS_DISABLECARD) { - sh_wdt_stop(); + sh_wdt_stop(wdt); retval = 0; } if (options & WDIOS_ENABLECARD) { - sh_wdt_start(); + sh_wdt_start(wdt); retval = 0; } return retval; case WDIOC_KEEPALIVE: - sh_wdt_keepalive(); + sh_wdt_keepalive(wdt); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_heartbeat, (int *)arg)) @@ -262,7 +280,7 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, if (sh_wdt_set_heartbeat(new_heartbeat)) return -EINVAL; - sh_wdt_keepalive(); + sh_wdt_keepalive(wdt); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(heartbeat, (int *)arg); @@ -275,8 +293,10 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, static int sh_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { + struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev); + if (code == SYS_DOWN || code == SYS_HALT) - sh_wdt_stop(); + sh_wdt_stop(wdt); return NOTIFY_DONE; } @@ -307,56 +327,148 @@ static struct miscdevice sh_wdt_miscdev = { .fops = &sh_wdt_fops, }; -static int __init sh_wdt_init(void) +static int __devinit sh_wdt_probe(struct platform_device *pdev) { + struct sh_wdt *wdt; + struct resource *res; int rc; - if (clock_division_ratio < 0x5 || clock_division_ratio > 0x7) { - clock_division_ratio = WTCSR_CKS_4096; - printk(KERN_INFO PFX - "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n", - clock_division_ratio); + /* + * As this driver only covers the global watchdog case, reject + * any attempts to register per-CPU watchdogs. + */ + if (pdev->id != -1) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!res)) + return -EINVAL; + + if (!devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), DRV_NAME)) + return -EBUSY; + + wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL); + if (unlikely(!wdt)) { + rc = -ENOMEM; + goto out_release; } - rc = sh_wdt_set_heartbeat(heartbeat); - if (unlikely(rc)) { - heartbeat = WATCHDOG_HEARTBEAT; - printk(KERN_INFO PFX - "heartbeat value must be 1<=x<=3600, using %d\n", - heartbeat); + wdt->dev = &pdev->dev; + + wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (unlikely(!wdt->base)) { + rc = -ENXIO; + goto out_err; } rc = register_reboot_notifier(&sh_wdt_notifier); if (unlikely(rc)) { - printk(KERN_ERR PFX + dev_err(&pdev->dev, "Can't register reboot notifier (err=%d)\n", rc); - return rc; + goto out_unmap; } + sh_wdt_miscdev.parent = wdt->dev; + rc = misc_register(&sh_wdt_miscdev); if (unlikely(rc)) { - printk(KERN_ERR PFX + dev_err(&pdev->dev, "Can't register miscdev on minor=%d (err=%d)\n", sh_wdt_miscdev.minor, rc); - unregister_reboot_notifier(&sh_wdt_notifier); - return rc; + goto out_unreg; } - printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", - heartbeat, nowayout); + init_timer(&wdt->timer); + wdt->timer.function = sh_wdt_ping; + wdt->timer.data = (unsigned long)wdt; + wdt->timer.expires = next_ping_period(clock_division_ratio); + + platform_set_drvdata(pdev, wdt); + sh_wdt_dev = pdev; + + dev_info(&pdev->dev, "initialized.\n"); return 0; + +out_unreg: + unregister_reboot_notifier(&sh_wdt_notifier); +out_unmap: + devm_iounmap(&pdev->dev, wdt->base); +out_err: + devm_kfree(&pdev->dev, wdt); +out_release: + devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); + + return rc; } -static void __exit sh_wdt_exit(void) +static int __devexit sh_wdt_remove(struct platform_device *pdev) { + struct sh_wdt *wdt = platform_get_drvdata(pdev); + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + platform_set_drvdata(pdev, NULL); + misc_deregister(&sh_wdt_miscdev); + + sh_wdt_dev = NULL; + unregister_reboot_notifier(&sh_wdt_notifier); + devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); + devm_iounmap(&pdev->dev, wdt->base); + devm_kfree(&pdev->dev, wdt); + + return 0; +} + +static struct platform_driver sh_wdt_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + + .probe = sh_wdt_probe, + .remove = __devexit_p(sh_wdt_remove), +}; + +static int __init sh_wdt_init(void) +{ + int rc; + + if (unlikely(clock_division_ratio < 0x5 || + clock_division_ratio > 0x7)) { + clock_division_ratio = WTCSR_CKS_4096; + + pr_info("%s: divisor must be 0x5<=x<=0x7, using %d\n", + DRV_NAME, clock_division_ratio); + } + + rc = sh_wdt_set_heartbeat(heartbeat); + if (unlikely(rc)) { + heartbeat = WATCHDOG_HEARTBEAT; + + pr_info("%s: heartbeat value must be 1<=x<=3600, using %d\n", + DRV_NAME, heartbeat); + } + + pr_info("%s: configured with heartbeat=%d sec (nowayout=%d)\n", + DRV_NAME, heartbeat, nowayout); + + return platform_driver_register(&sh_wdt_driver); } +static void __exit sh_wdt_exit(void) +{ + platform_driver_unregister(&sh_wdt_driver); +} +module_init(sh_wdt_init); +module_exit(sh_wdt_exit); + MODULE_AUTHOR("Paul Mundt "); MODULE_DESCRIPTION("SuperH watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); module_param(clock_division_ratio, int, 0); @@ -373,6 +485,3 @@ module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); - -module_init(sh_wdt_init); -module_exit(sh_wdt_exit); -- cgit v0.10.2 From 1da09c43ce5f4fcd98143feb7d2513fe6fd62848 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 18 Jan 2011 19:56:04 +0900 Subject: sh: pci: Support asynchronous initialization of SH-X3 PCIe channels. SH-X3 controllers all have pretty dire delays needed for PHY wakeup, so we attempt to mitigate the damage by bringing them up asynchronously, simply using the synchronization points for persistent bridge to channel numbering. Signed-off-by: Paul Mundt diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index 96e9b05..ada2e69 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -1,16 +1,19 @@ /* * Low-Level PCI Express Support for the SH7786 * - * Copyright (C) 2009 - 2010 Paul Mundt + * Copyright (C) 2009 - 2011 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. */ +#define pr_fmt(fmt) "PCI: " fmt + #include #include #include #include +#include #include #include #include @@ -31,7 +34,7 @@ static unsigned int nr_ports; static struct sh7786_pcie_hwops { int (*core_init)(void); - int (*port_init_hw)(struct sh7786_pcie_port *port); + async_func_ptr *port_init_hw; } *sh7786_pcie_hwops; static struct resource sh7786_pci0_resources[] = { @@ -474,8 +477,9 @@ static int __init sh7786_pcie_core_init(void) return test_mode_pin(MODE_PIN12) ? 3 : 2; } -static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port) +static void __init sh7786_pcie_init_hw(void *data, async_cookie_t cookie) { + struct sh7786_pcie_port *port = data; int ret; /* @@ -488,18 +492,30 @@ static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port) * Setup clocks, needed both for PHY and PCIe registers. */ ret = pcie_clk_init(port); - if (unlikely(ret < 0)) - return ret; + if (unlikely(ret < 0)) { + pr_err("clock initialization failed for port#%d\n", + port->index); + return; + } ret = phy_init(port); - if (unlikely(ret < 0)) - return ret; + if (unlikely(ret < 0)) { + pr_err("phy initialization failed for port#%d\n", + port->index); + return; + } ret = pcie_init(port); - if (unlikely(ret < 0)) - return ret; + if (unlikely(ret < 0)) { + pr_err("core initialization failed for port#%d\n", + port->index); + return; + } - return register_pci_controller(port->hose); + /* In the interest of preserving device ordering, synchronize */ + async_synchronize_cookie(cookie); + + register_pci_controller(port->hose); } static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = { @@ -510,7 +526,7 @@ static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = { static int __init sh7786_pcie_init(void) { struct clk *platclk; - int ret = 0, i; + int i; printk(KERN_NOTICE "PCI: Starting initialization.\n"); @@ -552,13 +568,7 @@ static int __init sh7786_pcie_init(void) port->hose = sh7786_pci_channels + i; port->hose->io_map_base = port->hose->resources[0].start; - ret |= sh7786_pcie_hwops->port_init_hw(port); - } - - if (unlikely(ret)) { - clk_disable(platclk); - clk_put(platclk); - return ret; + async_schedule(sh7786_pcie_hwops->port_init_hw, port); } return 0; -- cgit v0.10.2 From 7c86ad4a50ece39305b1be900df9a58645716602 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 19 Jan 2011 14:16:42 +0900 Subject: serial: sh-sci: Kill off unused clock string. Now that the clock string isn't used by the driver anymore, kill it off from the platform structure. Signed-off-by: Paul Mundt diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 1630d9c..f538132 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -45,7 +45,6 @@ struct plat_sci_port { unsigned int irqs[SCIx_NR_IRQS]; /* ERI, RXI, TXI, BRI */ unsigned int type; /* SCI / SCIF / IRDA */ upf_t flags; /* UPF_* flags */ - char *clk; /* clock string */ unsigned int scbrr_algo_id; /* SCBRR calculation algo */ unsigned int scscr; /* SCSCR initialization */ -- cgit v0.10.2 From e735038f3848a720f84a819c8191ed2f6a1beed8 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 19 Jan 2011 14:18:06 +0900 Subject: serial: sh-sci: Kill off unused membase kludge. All users of the platform port data specify a mapbase where the driver later derives the membase from. Now that UPF flags are taken in to account for generic ioremapping we can kill off the port-specific membase clobbering and simply use the generic paths. This derives from a time when sh64 was not capable of using the generic ioremap implementation and had employed early bolted DTLB mappings for port access, which is no longer an issue. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 92c91c8..1d1e700 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -1619,9 +1619,6 @@ static void sci_config_port(struct uart_port *port, int flags) port->type = s->type; - if (port->membase) - return; - if (port->flags & UPF_IOREMAP) { port->membase = ioremap_nocache(port->mapbase, 0x40); @@ -1727,7 +1724,6 @@ static int __devinit sci_init_single(struct platform_device *dev, init_timer(&sci_port->break_timer); port->mapbase = p->mapbase; - port->membase = p->membase; port->irq = p->irqs[SCIx_TXI_IRQ]; port->flags = p->flags; diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index f538132..789acf5 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -40,7 +40,6 @@ struct device; * Platform device specific platform_data struct */ struct plat_sci_port { - void __iomem *membase; /* io cookie */ unsigned long mapbase; /* resource base */ unsigned int irqs[SCIx_NR_IRQS]; /* ERI, RXI, TXI, BRI */ unsigned int type; /* SCI / SCIF / IRDA */ -- cgit v0.10.2 From 22cc83780e214f4f009384f9c1d0658629625d49 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 19 Jan 2011 14:37:14 +0900 Subject: serial: sh-sci: Provide a helper for muxed IRQs. All of the muxed IRQs presently populate the IRQ array verbosely, this simply provides a trivial helper to do it for them. Signed-off-by: Paul Mundt diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 789acf5..01ffe7c 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -34,6 +34,14 @@ enum { SCIx_NR_IRQS, }; +#define SCIx_IRQ_MUXED(irq) \ +{ \ + [SCIx_ERI_IRQ] = (irq), \ + [SCIx_RXI_IRQ] = (irq), \ + [SCIx_TXI_IRQ] = (irq), \ + [SCIx_BRI_IRQ] = (irq), \ +} + struct device; /* -- cgit v0.10.2 From ce6738b60d94bb317bc568ef7b81a227b2928bd4 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 19 Jan 2011 15:24:40 +0900 Subject: serial: sh-sci: Consolidate port definition structures. Presently the port defs are lamely copied around between competing data structures (one platform facing, the other driver internal). As we pretty much require all of the data from the platform facing structure within the driver too, simply nest the pointer directly and kill off the duplication. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 1d1e700..dccc982 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -65,11 +65,8 @@ struct sci_port { struct uart_port port; - /* Port type */ - unsigned int type; - - /* Port IRQs: ERI, RXI, TXI, BRI (optional) */ - unsigned int irqs[SCIx_NR_IRQS]; + /* Platform configuration */ + struct plat_sci_port *cfg; /* Port enable callback */ void (*enable)(struct uart_port *port); @@ -81,12 +78,6 @@ struct sci_port { struct timer_list break_timer; int break_flag; - /* SCSCR initialization */ - unsigned int scscr; - - /* SCBRR calculation algo */ - unsigned int scbrr_algo_id; - /* Interface clock */ struct clk *iclk; /* Function clock */ @@ -98,9 +89,6 @@ struct sci_port { struct dma_chan *chan_rx; #ifdef CONFIG_SERIAL_SH_SCI_DMA - struct device *dma_dev; - unsigned int slave_tx; - unsigned int slave_rx; struct dma_async_tx_descriptor *desc_tx; struct dma_async_tx_descriptor *desc_rx[2]; dma_cookie_t cookie_tx; @@ -794,7 +782,7 @@ static inline unsigned long port_rx_irq_mask(struct uart_port *port) * it's unset, it's logically inferred that there's no point in * testing for it. */ - return SCSCR_RIE | (to_sci_port(port)->scscr & SCSCR_REIE); + return SCSCR_RIE | (to_sci_port(port)->cfg->scscr & SCSCR_REIE); } static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) @@ -882,21 +870,21 @@ static int sci_request_irq(struct sci_port *port) const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full", "SCI Transmit Data Empty", "SCI Break" }; - if (port->irqs[0] == port->irqs[1]) { - if (unlikely(!port->irqs[0])) + if (port->cfg->irqs[0] == port->cfg->irqs[1]) { + if (unlikely(!port->cfg->irqs[0])) return -ENODEV; - if (request_irq(port->irqs[0], sci_mpxed_interrupt, + if (request_irq(port->cfg->irqs[0], sci_mpxed_interrupt, IRQF_DISABLED, "sci", port)) { dev_err(port->port.dev, "Can't allocate IRQ\n"); return -ENODEV; } } else { for (i = 0; i < ARRAY_SIZE(handlers); i++) { - if (unlikely(!port->irqs[i])) + if (unlikely(!port->cfg->irqs[i])) continue; - if (request_irq(port->irqs[i], handlers[i], + if (request_irq(port->cfg->irqs[i], handlers[i], IRQF_DISABLED, desc[i], port)) { dev_err(port->port.dev, "Can't allocate IRQ\n"); return -ENODEV; @@ -911,14 +899,14 @@ static void sci_free_irq(struct sci_port *port) { int i; - if (port->irqs[0] == port->irqs[1]) - free_irq(port->irqs[0], port); + if (port->cfg->irqs[0] == port->cfg->irqs[1]) + free_irq(port->cfg->irqs[0], port); else { - for (i = 0; i < ARRAY_SIZE(port->irqs); i++) { - if (!port->irqs[i]) + for (i = 0; i < ARRAY_SIZE(port->cfg->irqs); i++) { + if (!port->cfg->irqs[i]) continue; - free_irq(port->irqs[i], port); + free_irq(port->cfg->irqs[i], port); } } } @@ -1325,7 +1313,7 @@ static void rx_timer_fn(unsigned long arg) if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { scr &= ~0x4000; - enable_irq(s->irqs[1]); + enable_irq(s->cfg->irqs[1]); } sci_out(port, SCSCR, scr | SCSCR_RIE); dev_dbg(port->dev, "DMA Rx timed out\n"); @@ -1341,9 +1329,9 @@ static void sci_request_dma(struct uart_port *port) int nent; dev_dbg(port->dev, "%s: port %d DMA %p\n", __func__, - port->line, s->dma_dev); + port->line, s->cfg->dma_dev); - if (!s->dma_dev) + if (!s->cfg->dma_dev) return; dma_cap_zero(mask); @@ -1352,8 +1340,8 @@ static void sci_request_dma(struct uart_port *port) param = &s->param_tx; /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */ - param->slave_id = s->slave_tx; - param->dma_dev = s->dma_dev; + param->slave_id = s->cfg->dma_slave_tx; + param->dma_dev = s->cfg->dma_dev; s->cookie_tx = -EINVAL; chan = dma_request_channel(mask, filter, param); @@ -1381,8 +1369,8 @@ static void sci_request_dma(struct uart_port *port) param = &s->param_rx; /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */ - param->slave_id = s->slave_rx; - param->dma_dev = s->dma_dev; + param->slave_id = s->cfg->dma_slave_rx; + param->dma_dev = s->cfg->dma_dev; chan = dma_request_channel(mask, filter, param); dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan); @@ -1427,7 +1415,7 @@ static void sci_free_dma(struct uart_port *port) { struct sci_port *s = to_sci_port(port); - if (!s->dma_dev) + if (!s->cfg->dma_dev) return; if (s->chan_tx) @@ -1514,7 +1502,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, baud = uart_get_baud_rate(port, termios, old, 0, max_baud); if (likely(baud && port->uartclk)) - t = sci_scbrr_calc(s->scbrr_algo_id, baud, port->uartclk); + t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, port->uartclk); do { status = sci_in(port, SCxSR); @@ -1540,7 +1528,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_out(port, SCSMR, smr_val); dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t, - s->scscr); + s->cfg->scscr); if (t > 0) { if (t >= 256) { @@ -1556,7 +1544,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_init_pins(port, termios->c_cflag); sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0)); - sci_out(port, SCSCR, s->scscr); + sci_out(port, SCSCR, s->cfg->scscr); #ifdef CONFIG_SERIAL_SH_SCI_DMA /* @@ -1617,7 +1605,7 @@ static void sci_config_port(struct uart_port *port, int flags) { struct sci_port *s = to_sci_port(port); - port->type = s->type; + port->type = s->cfg->type; if (port->flags & UPF_IOREMAP) { port->membase = ioremap_nocache(port->mapbase, 0x40); @@ -1638,7 +1626,7 @@ static int sci_verify_port(struct uart_port *port, struct serial_struct *ser) { struct sci_port *s = to_sci_port(port); - if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs) + if (ser->irq != s->cfg->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs) return -EINVAL; if (ser->baud_base < 2400) /* No paper tape reader for Mitch.. */ @@ -1723,24 +1711,27 @@ static int __devinit sci_init_single(struct platform_device *dev, sci_port->break_timer.function = sci_break_timer; init_timer(&sci_port->break_timer); - port->mapbase = p->mapbase; + sci_port->cfg = p; - port->irq = p->irqs[SCIx_TXI_IRQ]; + port->mapbase = p->mapbase; + port->type = p->type; port->flags = p->flags; - sci_port->type = port->type = p->type; - sci_port->scscr = p->scscr; - sci_port->scbrr_algo_id = p->scbrr_algo_id; -#ifdef CONFIG_SERIAL_SH_SCI_DMA - sci_port->dma_dev = p->dma_dev; - sci_port->slave_tx = p->dma_slave_tx; - sci_port->slave_rx = p->dma_slave_rx; + /* + * The UART port needs an IRQ value, so we peg this to the TX IRQ + * for the multi-IRQ ports, which is where we are primarily + * concerned with the shutdown path synchronization. + * + * For the muxed case there's nothing more to do. + */ + port->irq = p->irqs[SCIx_TXI_IRQ]; - dev_dbg(port->dev, "%s: DMA device %p, tx %d, rx %d\n", __func__, - p->dma_dev, p->dma_slave_tx, p->dma_slave_rx); +#ifdef CONFIG_SERIAL_SH_SCI_DMA + if (p->dma_dev) + dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n", + p->dma_dev, p->dma_slave_tx, p->dma_slave_rx); #endif - memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); return 0; } -- cgit v0.10.2 From 27bd107525607e6a64c612ca3c43ca0dac4768b1 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 19 Jan 2011 15:37:31 +0900 Subject: serial: sh-sci: Kill off some DMA ifdeffery. There's nothing worth hiding under the ifdef in the platform DMA definitions, and we certainly don't want board code adding this in to their platform data definitions, so we always expose the slave rx/tx and device pointer members instead. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index dccc982..5b3e976 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -1423,6 +1423,14 @@ static void sci_free_dma(struct uart_port *port) if (s->chan_rx) sci_rx_dma_release(s, false); } +#else +static inline void sci_request_dma(struct uart_port *port) +{ +} + +static inline void sci_free_dma(struct uart_port *port) +{ +} #endif static int sci_startup(struct uart_port *port) @@ -1435,9 +1443,7 @@ static int sci_startup(struct uart_port *port) s->enable(port); sci_request_irq(s); -#ifdef CONFIG_SERIAL_SH_SCI_DMA sci_request_dma(port); -#endif sci_start_tx(port); sci_start_rx(port); @@ -1452,9 +1458,7 @@ static void sci_shutdown(struct uart_port *port) sci_stop_rx(port); sci_stop_tx(port); -#ifdef CONFIG_SERIAL_SH_SCI_DMA sci_free_dma(port); -#endif sci_free_irq(s); if (s->disable) @@ -1726,11 +1730,9 @@ static int __devinit sci_init_single(struct platform_device *dev, */ port->irq = p->irqs[SCIx_TXI_IRQ]; -#ifdef CONFIG_SERIAL_SH_SCI_DMA if (p->dma_dev) dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n", p->dma_dev, p->dma_slave_tx, p->dma_slave_rx); -#endif return 0; } diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 01ffe7c..a2afc9f 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -58,10 +58,8 @@ struct plat_sci_port { struct device *dma_dev; -#ifdef CONFIG_SERIAL_SH_SCI_DMA - unsigned int dma_slave_tx; - unsigned int dma_slave_rx; -#endif + unsigned int dma_slave_tx; + unsigned int dma_slave_rx; }; #endif /* __LINUX_SERIAL_SCI_H */ -- cgit v0.10.2 From d535a2305facf9b49a65bd412c6deaaf4d4316f2 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 19 Jan 2011 17:19:35 +0900 Subject: serial: sh-sci: Require a device per port mapping. In the olden days it was possible to register a map of ports per device, but this has long since been abandoned due to the desire to match up with clkdev and other functionality. As a result, all of the in-tree users have for some time already been migrated off of such behaviour, while we've left support code in place to deal with either case. Dropping the code permits for quite a bit of simplification, so we do that now before any users of the old interface are able to be added back in. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 5b3e976..3fd1577 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -83,8 +82,6 @@ struct sci_port { /* Function clock */ struct clk *fclk; - struct list_head node; - struct dma_chan *chan_tx; struct dma_chan *chan_rx; @@ -105,16 +102,14 @@ struct sci_port { struct timer_list rx_timer; unsigned int rx_timeout; #endif -}; -struct sh_sci_priv { - spinlock_t lock; - struct list_head ports; - struct notifier_block clk_nb; + struct notifier_block freq_transition; }; /* Function prototypes */ +static void sci_start_tx(struct uart_port *port); static void sci_stop_tx(struct uart_port *port); +static void sci_start_rx(struct uart_port *port); #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS @@ -827,17 +822,17 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) static int sci_notifier(struct notifier_block *self, unsigned long phase, void *p) { - struct sh_sci_priv *priv = container_of(self, - struct sh_sci_priv, clk_nb); struct sci_port *sci_port; unsigned long flags; + sci_port = container_of(self, struct sci_port, freq_transition); + if ((phase == CPUFREQ_POSTCHANGE) || (phase == CPUFREQ_RESUMECHANGE)) { - spin_lock_irqsave(&priv->lock, flags); - list_for_each_entry(sci_port, &priv->ports, node) - sci_port->port.uartclk = clk_get_rate(sci_port->iclk); - spin_unlock_irqrestore(&priv->lock, flags); + struct uart_port *port = &sci_port->port; + spin_lock_irqsave(&port->lock, flags); + port->uartclk = clk_get_rate(sci_port->iclk); + spin_unlock_irqrestore(&port->lock, flags); } return NOTIFY_OK; @@ -1025,9 +1020,6 @@ static void sci_dma_rx_complete(void *arg) schedule_work(&s->work_rx); } -static void sci_start_rx(struct uart_port *port); -static void sci_start_tx(struct uart_port *port); - static void sci_rx_dma_release(struct sci_port *s, bool enable_pio) { struct dma_chan *chan = s->chan_rx; @@ -1874,24 +1866,18 @@ static struct uart_driver sci_uart_driver = { .cons = SCI_CONSOLE, }; - static int sci_remove(struct platform_device *dev) { - struct sh_sci_priv *priv = platform_get_drvdata(dev); - struct sci_port *p; - unsigned long flags; + struct sci_port *port = platform_get_drvdata(dev); - cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); + cpufreq_unregister_notifier(&port->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); - spin_lock_irqsave(&priv->lock, flags); - list_for_each_entry(p, &priv->ports, node) { - uart_remove_one_port(&sci_uart_driver, &p->port); - clk_put(p->iclk); - clk_put(p->fclk); - } - spin_unlock_irqrestore(&priv->lock, flags); + uart_remove_one_port(&sci_uart_driver, &port->port); + + clk_put(port->iclk); + clk_put(port->fclk); - kfree(priv); return 0; } @@ -1900,8 +1886,6 @@ static int __devinit sci_probe_single(struct platform_device *dev, struct plat_sci_port *p, struct sci_port *sciport) { - struct sh_sci_priv *priv = platform_get_drvdata(dev); - unsigned long flags; int ret; /* Sanity check */ @@ -1918,17 +1902,7 @@ static int __devinit sci_probe_single(struct platform_device *dev, if (ret) return ret; - ret = uart_add_one_port(&sci_uart_driver, &sciport->port); - if (ret) - return ret; - - INIT_LIST_HEAD(&sciport->node); - - spin_lock_irqsave(&priv->lock, flags); - list_add(&sciport->node, &priv->ports); - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; + return uart_add_one_port(&sci_uart_driver, &sciport->port); } /* @@ -1940,46 +1914,38 @@ static int __devinit sci_probe_single(struct platform_device *dev, static int __devinit sci_probe(struct platform_device *dev) { struct plat_sci_port *p = dev->dev.platform_data; - struct sh_sci_priv *priv; - int i, ret = -EINVAL; + struct sci_port *sp = &sci_ports[dev->id]; + int ret = -EINVAL; #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE if (is_early_platform_device(dev)) { - if (dev->id == -1) - return -ENOTSUPP; early_serial_console.index = dev->id; early_serial_console.data = &early_serial_port.port; + sci_init_single(NULL, &early_serial_port, dev->id, p); + serial_console_setup(&early_serial_console, early_serial_buf); + if (!strstr(early_serial_buf, "keep")) early_serial_console.flags |= CON_BOOT; + register_console(&early_serial_console); return 0; } #endif - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + platform_set_drvdata(dev, sp); - INIT_LIST_HEAD(&priv->ports); - spin_lock_init(&priv->lock); - platform_set_drvdata(dev, priv); + ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]); + if (ret) + goto err_unreg; - priv->clk_nb.notifier_call = sci_notifier; - cpufreq_register_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); + sp->freq_transition.notifier_call = sci_notifier; - if (dev->id != -1) { - ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]); - if (ret) - goto err_unreg; - } else { - for (i = 0; p && p->flags != 0; p++, i++) { - ret = sci_probe_single(dev, i, p, &sci_ports[i]); - if (ret) - goto err_unreg; - } - } + ret = cpufreq_register_notifier(&sp->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); + if (unlikely(ret < 0)) + goto err_unreg; #ifdef CONFIG_SH_STANDARD_BIOS sh_bios_gdb_detach(); @@ -1994,28 +1960,20 @@ err_unreg: static int sci_suspend(struct device *dev) { - struct sh_sci_priv *priv = dev_get_drvdata(dev); - struct sci_port *p; - unsigned long flags; + struct sci_port *sport = dev_get_drvdata(dev); - spin_lock_irqsave(&priv->lock, flags); - list_for_each_entry(p, &priv->ports, node) - uart_suspend_port(&sci_uart_driver, &p->port); - spin_unlock_irqrestore(&priv->lock, flags); + if (sport) + uart_suspend_port(&sci_uart_driver, &sport->port); return 0; } static int sci_resume(struct device *dev) { - struct sh_sci_priv *priv = dev_get_drvdata(dev); - struct sci_port *p; - unsigned long flags; + struct sci_port *sport = dev_get_drvdata(dev); - spin_lock_irqsave(&priv->lock, flags); - list_for_each_entry(p, &priv->ports, node) - uart_resume_port(&sci_uart_driver, &p->port); - spin_unlock_irqrestore(&priv->lock, flags); + if (sport) + uart_resume_port(&sci_uart_driver, &sport->port); return 0; } -- cgit v0.10.2 From 073e84c9320e3fbd26b6a2537c6f592466b25af3 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 19 Jan 2011 17:30:53 +0900 Subject: serial: sh-sci: Handle request_irq() failures. request_irq() can fail, so actually do something with the error path instead of blindly ignoring it. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 3fd1577..31ac092 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -830,6 +830,7 @@ static int sci_notifier(struct notifier_block *self, if ((phase == CPUFREQ_POSTCHANGE) || (phase == CPUFREQ_RESUMECHANGE)) { struct uart_port *port = &sci_port->port; + spin_lock_irqsave(&port->lock, flags); port->uartclk = clk_get_rate(sci_port->iclk); spin_unlock_irqrestore(&port->lock, flags); @@ -1428,14 +1429,19 @@ static inline void sci_free_dma(struct uart_port *port) static int sci_startup(struct uart_port *port) { struct sci_port *s = to_sci_port(port); + int ret; dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); if (s->enable) s->enable(port); - sci_request_irq(s); + ret = sci_request_irq(s); + if (unlikely(ret < 0)) + return ret; + sci_request_dma(port); + sci_start_tx(port); sci_start_rx(port); @@ -1450,6 +1456,7 @@ static void sci_shutdown(struct uart_port *port) sci_stop_rx(port); sci_stop_tx(port); + sci_free_dma(port); sci_free_irq(s); -- cgit v0.10.2 From 86b7d0e288c326d3ea7c22600cb7b6d84abb2968 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 19 Jan 2011 17:50:35 +0900 Subject: serial: sh-sci: Kill off unused SCSCR definitions. Presently there are only a few hardcoded cases using these definitions, so kill off the unused ones completely. This will make it easier to transition off of the remaining cases. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index b223d6c..5fefed5 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -54,9 +54,6 @@ # define PBCR 0xa4050102 #elif defined(CONFIG_CPU_SUBTYPE_SH7343) # define SCSPTR0 0xffe00010 /* 16 bit SCIF */ -# define SCSPTR1 0xffe10010 /* 16 bit SCIF */ -# define SCSPTR2 0xffe20010 /* 16 bit SCIF */ -# define SCSPTR3 0xffe30010 /* 16 bit SCIF */ #elif defined(CONFIG_CPU_SUBTYPE_SH7722) # define PADR 0xA4050120 # define PSDR 0xA405013e @@ -69,77 +66,42 @@ # define SCIF_ORER 0x0001 /* overrun error bit */ #elif defined(CONFIG_CPU_SUBTYPE_SH7723) # define SCSPTR0 0xa4050160 -# define SCSPTR1 0xa405013e -# define SCSPTR2 0xa4050160 -# define SCSPTR3 0xa405013e -# define SCSPTR4 0xa4050128 -# define SCSPTR5 0xa4050128 # define SCIF_ORER 0x0001 /* overrun error bit */ #elif defined(CONFIG_CPU_SUBTYPE_SH7724) # define SCIF_ORER 0x0001 /* overrun error bit */ #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ -#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) -# define SCIF_PTR2_OFFS 0x0000020 -# define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */ #elif defined(CONFIG_H83007) || defined(CONFIG_H83068) # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) #elif defined(CONFIG_H8S2678) # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) #elif defined(CONFIG_CPU_SUBTYPE_SH7757) # define SCSPTR0 0xfe4b0020 -# define SCSPTR1 0xfe4b0020 -# define SCSPTR2 0xfe4b0020 # define SCIF_ORER 0x0001 -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7763) # define SCSPTR0 0xffe00024 /* 16 bit SCIF */ -# define SCSPTR1 0xffe08024 /* 16 bit SCIF */ -# define SCSPTR2 0xffe10020 /* 16 bit SCIF/IRDA */ # define SCIF_ORER 0x0001 /* overrun error bit */ #elif defined(CONFIG_CPU_SUBTYPE_SH7770) # define SCSPTR0 0xff923020 /* 16 bit SCIF */ -# define SCSPTR1 0xff924020 /* 16 bit SCIF */ -# define SCSPTR2 0xff925020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ #elif defined(CONFIG_CPU_SUBTYPE_SH7780) # define SCSPTR0 0xffe00024 /* 16 bit SCIF */ -# define SCSPTR1 0xffe10024 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* Overrun error bit */ #elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \ defined(CONFIG_CPU_SUBTYPE_SH7786) # define SCSPTR0 0xffea0024 /* 16 bit SCIF */ -# define SCSPTR1 0xffeb0024 /* 16 bit SCIF */ -# define SCSPTR2 0xffec0024 /* 16 bit SCIF */ -# define SCSPTR3 0xffed0024 /* 16 bit SCIF */ -# define SCSPTR4 0xffee0024 /* 16 bit SCIF */ -# define SCSPTR5 0xffef0024 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* Overrun error bit */ #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \ defined(CONFIG_CPU_SUBTYPE_SH7203) || \ defined(CONFIG_CPU_SUBTYPE_SH7206) || \ defined(CONFIG_CPU_SUBTYPE_SH7263) # define SCSPTR0 0xfffe8020 /* 16 bit SCIF */ -# define SCSPTR1 0xfffe8820 /* 16 bit SCIF */ -# define SCSPTR2 0xfffe9020 /* 16 bit SCIF */ -# define SCSPTR3 0xfffe9820 /* 16 bit SCIF */ -# if defined(CONFIG_CPU_SUBTYPE_SH7201) -# define SCSPTR4 0xfffeA020 /* 16 bit SCIF */ -# define SCSPTR5 0xfffeA820 /* 16 bit SCIF */ -# define SCSPTR6 0xfffeB020 /* 16 bit SCIF */ -# define SCSPTR7 0xfffeB820 /* 16 bit SCIF */ -# endif #elif defined(CONFIG_CPU_SUBTYPE_SH7619) # define SCSPTR0 0xf8400020 /* 16 bit SCIF */ -# define SCSPTR1 0xf8410020 /* 16 bit SCIF */ -# define SCSPTR2 0xf8420020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ #elif defined(CONFIG_CPU_SUBTYPE_SHX3) # define SCSPTR0 0xffc30020 /* 16 bit SCIF */ -# define SCSPTR1 0xffc40020 /* 16 bit SCIF */ -# define SCSPTR2 0xffc50020 /* 16 bit SCIF */ -# define SCSPTR3 0xffc60020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* Overrun error bit */ #else # error CPU subtype not defined @@ -411,7 +373,6 @@ SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) SCIF_FNS(SCLSR, 0, 0, 0x28, 16) #elif defined(CONFIG_CPU_SUBTYPE_SH7763) SCIF_FNS(SCFDR, 0, 0, 0x1C, 16) -SCIF_FNS(SCSPTR2, 0, 0, 0x20, 16) SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) -- cgit v0.10.2 From e8183a6c6238a192fba32ac47d75fd076ca487a6 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 19 Jan 2011 17:51:37 +0900 Subject: serial: sh-sci: Fix up ioremap handling. We were using an IS_ERR() check for the ioremap case, presumably because this matched the old custom ioremap call that sh64 was providing. Now that all ioremap() implementations trap the IS_ERR case and hand back a NULL, check for that instead. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 31ac092..44d5bd1 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -1482,6 +1482,7 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, /* Warn, but use a safe default */ WARN_ON(1); + return ((freq + 16 * bps) / (32 * bps) - 1); } @@ -1517,6 +1518,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST); smr_val = sci_in(port, SCSMR) & 3; + if ((termios->c_cflag & CSIZE) == CS7) smr_val |= 0x40; if (termios->c_cflag & PARENB) @@ -1612,8 +1614,7 @@ static void sci_config_port(struct uart_port *port, int flags) if (port->flags & UPF_IOREMAP) { port->membase = ioremap_nocache(port->mapbase, 0x40); - - if (IS_ERR(port->membase)) + if (unlikely(!port->membase)) dev_err(port->dev, "can't remap port#%d\n", port->line); } else { /* -- cgit v0.10.2 From e2651647080930a1846196c3b79f4de662100388 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 20 Jan 2011 21:24:03 +0900 Subject: serial: sh-sci: Handle port memory region reservations. At the moment the request/release_port ops are no-ops with the port remapping case tied in to the config_port op. This moves the remap logic in to the request_port, balances it with unmapping in the port release, and finally takes care of the mem region reservations. All existing users are of the port autoconf variety, so we follow the example of other drivers that wrap in to the port request by way of the config op in the UART_CONFIG_TYPE case. This is the first step towards fixing up conflicts with multiple users of the same ports, as currently happens between sh-sci and spi_sh_sci. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 44d5bd1..cf2c780 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -1595,27 +1595,43 @@ static const char *sci_type(struct uart_port *port) return NULL; } -static void sci_release_port(struct uart_port *port) +static inline unsigned long sci_port_size(struct uart_port *port) { - /* Nothing here yet .. */ + /* + * Pick an arbitrary size that encapsulates all of the base + * registers by default. This can be optimized later, or derived + * from platform resource data at such a time that ports begin to + * behave more erratically. + */ + return 64; } -static int sci_request_port(struct uart_port *port) +static void sci_release_port(struct uart_port *port) { - /* Nothing here yet .. */ - return 0; + if (port->flags & UPF_IOREMAP) { + iounmap(port->membase); + port->membase = NULL; + } + + release_mem_region(port->mapbase, sci_port_size(port)); } -static void sci_config_port(struct uart_port *port, int flags) +static int sci_request_port(struct uart_port *port) { - struct sci_port *s = to_sci_port(port); + unsigned long size = sci_port_size(port); + struct resource *res; - port->type = s->cfg->type; + res = request_mem_region(port->mapbase, size, sci_type(port)); + if (unlikely(res == NULL)) + return -EBUSY; if (port->flags & UPF_IOREMAP) { - port->membase = ioremap_nocache(port->mapbase, 0x40); - if (unlikely(!port->membase)) + port->membase = ioremap_nocache(port->mapbase, size); + if (unlikely(!port->membase)) { dev_err(port->dev, "can't remap port#%d\n", port->line); + release_resource(res); + return -ENXIO; + } } else { /* * For the simple (and majority of) cases where we don't @@ -1624,6 +1640,18 @@ static void sci_config_port(struct uart_port *port, int flags) */ port->membase = (void __iomem *)port->mapbase; } + + return 0; +} + +static void sci_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) { + struct sci_port *sport = to_sci_port(port); + + port->type = sport->cfg->type; + sci_request_port(port); + } } static int sci_verify_port(struct uart_port *port, struct serial_struct *ser) -- cgit v0.10.2 From 94c8b6dbd64c51aa7ce7fcc466beccf942271b0e Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 20 Jan 2011 23:26:18 +0900 Subject: serial: sh-sci: Bring oversized error handlers out of line. Presently much of the error handling paths are inlined, stemming from a time when they were much smaller. This simply brings them out of line and leaves it up to the compiler. Given that some of these now contain nested loops, it's pretty hard to justify the inlining regardless of the footprint. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index cf2c780..83bf1b8 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -125,12 +125,6 @@ to_sci_port(struct uart_port *uart) #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) #ifdef CONFIG_CONSOLE_POLL -static inline void handle_error(struct uart_port *port) -{ - /* Clear error flags */ - sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); -} - static int sci_poll_get_char(struct uart_port *port) { unsigned short status; @@ -139,7 +133,7 @@ static int sci_poll_get_char(struct uart_port *port) do { status = sci_in(port, SCxSR); if (status & SCxSR_ERRORS(port)) { - handle_error(port); + sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); continue; } break; @@ -458,7 +452,7 @@ static void sci_transmit_chars(struct uart_port *port) /* On SH3, SCIF may read end-of-break as a space->mark char */ #define STEPFN(c) ({int __c = (c); (((__c-1)|(__c)) == -1); }) -static inline void sci_receive_chars(struct uart_port *port) +static void sci_receive_chars(struct uart_port *port) { struct sci_port *sci_port = to_sci_port(port); struct tty_struct *tty = port->state->port.tty; @@ -549,18 +543,21 @@ static inline void sci_receive_chars(struct uart_port *port) } #define SCI_BREAK_JIFFIES (HZ/20) -/* The sci generates interrupts during the break, + +/* + * The sci generates interrupts during the break, * 1 per millisecond or so during the break period, for 9600 baud. * So dont bother disabling interrupts. * But dont want more than 1 break event. * Use a kernel timer to periodically poll the rx line until * the break is finished. */ -static void sci_schedule_break_timer(struct sci_port *port) +static inline void sci_schedule_break_timer(struct sci_port *port) { port->break_timer.expires = jiffies + SCI_BREAK_JIFFIES; add_timer(&port->break_timer); } + /* Ensure that two consecutive samples find the break over. */ static void sci_break_timer(unsigned long data) { @@ -577,7 +574,7 @@ static void sci_break_timer(unsigned long data) port->break_flag = 0; } -static inline int sci_handle_errors(struct uart_port *port) +static int sci_handle_errors(struct uart_port *port) { int copied = 0; unsigned short status = sci_in(port, SCxSR); @@ -633,7 +630,7 @@ static inline int sci_handle_errors(struct uart_port *port) return copied; } -static inline int sci_handle_fifo_overrun(struct uart_port *port) +static int sci_handle_fifo_overrun(struct uart_port *port) { struct tty_struct *tty = port->state->port.tty; int copied = 0; @@ -654,7 +651,7 @@ static inline int sci_handle_fifo_overrun(struct uart_port *port) return copied; } -static inline int sci_handle_breaks(struct uart_port *port) +static int sci_handle_breaks(struct uart_port *port) { int copied = 0; unsigned short status = sci_in(port, SCxSR); -- cgit v0.10.2 From bc9b3f5c9f3702e71066a4de0afe509a201d98b4 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 20 Jan 2011 23:30:19 +0900 Subject: serial: sh-sci: Fix up break timer scheduling race. The break flag timer is presently added through add_timer() via the interrupt and error paths, where it is possible to send multiple breaks in rapid succession and trigger the timer pending BUG_ON(). This moves over to a mod_timer() instead. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 83bf1b8..999fe5f 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -554,8 +554,7 @@ static void sci_receive_chars(struct uart_port *port) */ static inline void sci_schedule_break_timer(struct sci_port *port) { - port->break_timer.expires = jiffies + SCI_BREAK_JIFFIES; - add_timer(&port->break_timer); + mod_timer(&port->break_timer, jiffies + SCI_BREAK_JIFFIES); } /* Ensure that two consecutive samples find the break over. */ -- cgit v0.10.2 From ecdf8a4607edfebbfd6baada8eaecf532bf38600 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 21 Jan 2011 00:05:48 +0900 Subject: serial: sh-sci: Limit early console to one device. Presently the early console setup will be invoked for every device handed off to he earlyprintk command line argument. In practice we can only handle one, so this adds a sanity check to prevent clobbering the existing active console. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 999fe5f..7b2760b 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -1870,13 +1870,40 @@ static int __init sci_console_init(void) console_initcall(sci_console_init); static struct sci_port early_serial_port; + static struct console early_serial_console = { .name = "early_ttySC", .write = serial_console_write, .flags = CON_PRINTBUFFER, }; + static char early_serial_buf[32]; +static int __devinit sci_probe_earlyprintk(struct platform_device *pdev) +{ + struct plat_sci_port *cfg = pdev->dev.platform_data; + + if (early_serial_console.data) + return -EEXIST; + + early_serial_console.index = pdev->id; + early_serial_console.data = &early_serial_port.port; + + sci_init_single(NULL, &early_serial_port, pdev->id, cfg); + + serial_console_setup(&early_serial_console, early_serial_buf); + + if (!strstr(early_serial_buf, "keep")) + early_serial_console.flags |= CON_BOOT; + + register_console(&early_serial_console); + return 0; +} +#else +static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev) +{ + return -EINVAL; +} #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ #if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) @@ -1937,34 +1964,19 @@ static int __devinit sci_probe_single(struct platform_device *dev, return uart_add_one_port(&sci_uart_driver, &sciport->port); } -/* - * Register a set of serial devices attached to a platform device. The - * list is terminated with a zero flags entry, which means we expect - * all entries to have at least UPF_BOOT_AUTOCONF set. Platforms that need - * remapping (such as sh64) should also set UPF_IOREMAP. - */ static int __devinit sci_probe(struct platform_device *dev) { struct plat_sci_port *p = dev->dev.platform_data; struct sci_port *sp = &sci_ports[dev->id]; - int ret = -EINVAL; - -#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE - if (is_early_platform_device(dev)) { - early_serial_console.index = dev->id; - early_serial_console.data = &early_serial_port.port; - - sci_init_single(NULL, &early_serial_port, dev->id, p); - - serial_console_setup(&early_serial_console, early_serial_buf); - - if (!strstr(early_serial_buf, "keep")) - early_serial_console.flags |= CON_BOOT; + int ret; - register_console(&early_serial_console); - return 0; - } -#endif + /* + * If we've come here via earlyprintk initialization, head off to + * the special early probe. We don't have sufficient device state + * to make it beyond this yet. + */ + if (is_early_platform_device(dev)) + return sci_probe_earlyprintk(dev); platform_set_drvdata(dev, sp); -- cgit v0.10.2 From f6e9495d68b91138afbf929c222a09f5d12b29fa Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 21 Jan 2011 15:25:36 +0900 Subject: serial: sh-sci: Fix up earlyprintk port mapping. The earlyprintk path needs to establish the membase cookie, but is too early for general resource management. Split out the remap logic accordingly. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 7b2760b..c55cec5 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -1602,6 +1602,34 @@ static inline unsigned long sci_port_size(struct uart_port *port) return 64; } +static int sci_remap_port(struct uart_port *port) +{ + unsigned long size = sci_port_size(port); + + /* + * Nothing to do if there's already an established membase. + */ + if (port->membase) + return 0; + + if (port->flags & UPF_IOREMAP) { + port->membase = ioremap_nocache(port->mapbase, size); + if (unlikely(!port->membase)) { + dev_err(port->dev, "can't remap port#%d\n", port->line); + return -ENXIO; + } + } else { + /* + * For the simple (and majority of) cases where we don't + * need to do any remapping, just cast the cookie + * directly. + */ + port->membase = (void __iomem *)port->mapbase; + } + + return 0; +} + static void sci_release_port(struct uart_port *port) { if (port->flags & UPF_IOREMAP) { @@ -1616,25 +1644,16 @@ static int sci_request_port(struct uart_port *port) { unsigned long size = sci_port_size(port); struct resource *res; + int ret; res = request_mem_region(port->mapbase, size, sci_type(port)); if (unlikely(res == NULL)) return -EBUSY; - if (port->flags & UPF_IOREMAP) { - port->membase = ioremap_nocache(port->mapbase, size); - if (unlikely(!port->membase)) { - dev_err(port->dev, "can't remap port#%d\n", port->line); - release_resource(res); - return -ENXIO; - } - } else { - /* - * For the simple (and majority of) cases where we don't - * need to do any remapping, just cast the cookie - * directly. - */ - port->membase = (void __iomem *)port->mapbase; + ret = sci_remap_port(port); + if (unlikely(ret != 0)) { + release_resource(res); + return ret; } return 0; @@ -1835,7 +1854,9 @@ static int __devinit serial_console_setup(struct console *co, char *options) if (!port->type) return -ENODEV; - sci_config_port(port, 0); + ret = sci_remap_port(port); + if (unlikely(ret != 0)) + return ret; if (sci_port->enable) sci_port->enable(port); -- cgit v0.10.2 From 1020520e41965eb11759a0c40e6ab66297340df6 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 21 Jan 2011 16:00:31 +0900 Subject: serial: sh-sci: Use dev_name() for region reservations. dev_name() matches what the other drivers are doing, so prefer that over the port type. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index c55cec5..abf144e 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -1646,7 +1646,7 @@ static int sci_request_port(struct uart_port *port) struct resource *res; int ret; - res = request_mem_region(port->mapbase, size, sci_type(port)); + res = request_mem_region(port->mapbase, size, dev_name(port->dev)); if (unlikely(res == NULL)) return -EBUSY; -- cgit v0.10.2 From 906b17dc089f7fa87e37a9cfe6ee185efc90e0da Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 21 Jan 2011 16:19:53 +0900 Subject: serial: sh-sci: Kill off the special earlyprintk device. This reworks some of the code a bit so that we always wrap in to the global port array instead of flipping between it and the special early device. This will make it easier to split the initialization in to early and late parts where we can simply initialize the remaining bits of the partially-initialized port coming off of the early console later in the boot process. Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index abf144e..0257fd5 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -1781,13 +1781,6 @@ static int __devinit sci_init_single(struct platform_device *dev, } #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE -static struct tty_driver *serial_console_device(struct console *co, int *index) -{ - struct uart_driver *p = &sci_uart_driver; - *index = co->index; - return p->tty_driver; -} - static void serial_console_putchar(struct uart_port *port, int ch) { sci_poll_put_char(port, ch); @@ -1800,8 +1793,8 @@ static void serial_console_putchar(struct uart_port *port, int ch) static void serial_console_write(struct console *co, const char *s, unsigned count) { - struct uart_port *port = co->data; - struct sci_port *sci_port = to_sci_port(port); + struct sci_port *sci_port = &sci_ports[co->index]; + struct uart_port *port = &sci_port->port; unsigned short bits; if (sci_port->enable) @@ -1829,31 +1822,14 @@ static int __devinit serial_console_setup(struct console *co, char *options) int ret; /* - * Check whether an invalid uart number has been specified, and - * if so, search for the first available port that does have - * console support. - */ - if (co->index >= SCI_NPORTS) - co->index = 0; - - if (co->data) { - port = co->data; - sci_port = to_sci_port(port); - } else { - sci_port = &sci_ports[co->index]; - port = &sci_port->port; - co->data = port; - } - - /* - * Also need to check port->type, we don't actually have any - * UPIO_PORT ports, but uart_report_port() handily misreports - * it anyways if we don't have a port available by the time this is - * called. + * Refuse to handle any bogus ports. */ - if (!port->type) + if (co->index < 0 || co->index >= SCI_NPORTS) return -ENODEV; + sci_port = &sci_ports[co->index]; + port = &sci_port->port; + ret = sci_remap_port(port); if (unlikely(ret != 0)) return ret; @@ -1876,11 +1852,12 @@ static int __devinit serial_console_setup(struct console *co, char *options) static struct console serial_console = { .name = "ttySC", - .device = serial_console_device, + .device = uart_console_device, .write = serial_console_write, .setup = serial_console_setup, .flags = CON_PRINTBUFFER, .index = -1, + .data = &sci_uart_driver, }; static int __init sci_console_init(void) @@ -1890,12 +1867,11 @@ static int __init sci_console_init(void) } console_initcall(sci_console_init); -static struct sci_port early_serial_port; - static struct console early_serial_console = { .name = "early_ttySC", .write = serial_console_write, .flags = CON_PRINTBUFFER, + .index = -1, }; static char early_serial_buf[32]; @@ -1908,9 +1884,8 @@ static int __devinit sci_probe_earlyprintk(struct platform_device *pdev) return -EEXIST; early_serial_console.index = pdev->id; - early_serial_console.data = &early_serial_port.port; - sci_init_single(NULL, &early_serial_port, pdev->id, cfg); + sci_init_single(NULL, &sci_ports[pdev->id], pdev->id, cfg); serial_console_setup(&early_serial_console, early_serial_buf); @@ -2001,7 +1976,7 @@ static int __devinit sci_probe(struct platform_device *dev) platform_set_drvdata(dev, sp); - ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]); + ret = sci_probe_single(dev, dev->id, p, sp); if (ret) goto err_unreg; -- cgit v0.10.2 From cd7bb53ff88a5acef942a87c1d04e6211b6470dc Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 28 Jan 2011 15:14:08 +0900 Subject: sh: Fix up async PCIe probing on SMP. For the SMP case we run in to a lockup without a full synchronization prior to continuing with the boot. Signed-off-by: Paul Mundt diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index ada2e69..4418f90 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -571,6 +571,8 @@ static int __init sh7786_pcie_init(void) async_schedule(sh7786_pcie_hwops->port_init_hw, port); } + async_synchronize_full(); + return 0; } arch_initcall(sh7786_pcie_init); -- cgit v0.10.2 From d4f7e513234019a005c4d33477189f2a4e53bb9c Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Fri, 12 Nov 2010 16:26:54 +0100 Subject: sh: Enable CONFIG_GCOV_PROFILE_ALL for sh This patch enables gcov kernel profiling over the whole kernel for sh. Profiling of specific files individually already worked. A handful of files have to be explicitly excluded from the profiling to avoid breaking things, notably pmb.c. Signed-off-by: Chris Smith Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile index e0b0293..780e083 100644 --- a/arch/sh/boot/compressed/Makefile +++ b/arch/sh/boot/compressed/Makefile @@ -11,6 +11,8 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz \ OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o +GCOV_PROFILE := n + # # IMAGE_OFFSET is the load offset of the compression loader # diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile index 150aa32..2228c8c 100644 --- a/arch/sh/mm/Makefile +++ b/arch/sh/mm/Makefile @@ -42,6 +42,8 @@ obj-$(CONFIG_IOREMAP_FIXED) += ioremap_fixed.o obj-$(CONFIG_UNCACHED_MAPPING) += uncached.o obj-$(CONFIG_HAVE_SRAM_POOL) += sram.o +GCOV_PROFILE_pmb.o := n + # Special flags for fault_64.o. This puts restrictions on the number of # caller-save registers that the compiler can target when building this file. # This is required because the code is called from a context in entry.S where diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig index 70a298d..b8cadf7 100644 --- a/kernel/gcov/Kconfig +++ b/kernel/gcov/Kconfig @@ -34,7 +34,7 @@ config GCOV_KERNEL config GCOV_PROFILE_ALL bool "Profile entire Kernel" depends on GCOV_KERNEL - depends on S390 || X86 || (PPC && EXPERIMENTAL) || MICROBLAZE + depends on SUPERH || S390 || X86 || (PPC && EXPERIMENTAL) || MICROBLAZE default n ---help--- This options activates profiling for the entire kernel. -- cgit v0.10.2 From 36003386f86c0624ae0662a229081ef2b11ac784 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Thu, 3 Mar 2011 08:04:42 +0000 Subject: serial: sh-sci: fix deadlock when resuming from S3 sleep S3 sleep invokes the shutdown callback of the sh-sci driver, which suspends the clocks until they are reactivated by a call to startup. However, before the latter is invoked, sci_set_termios may be called on the port by uart_resume_port. In such cases it will endlessly wait for the TEND bit to raise, which will never happen since the clocks are disabled. This patch ensures that clocks are enabled when ports registers are manipulated within sci_set_termios. Signed-off-by: Alexandre Courbot Signed-off-by: Paul Mundt diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 0257fd5..eb7958c 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1504,6 +1504,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, if (likely(baud && port->uartclk)) t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, port->uartclk); + if (s->enable) + s->enable(port); + do { status = sci_in(port, SCxSR); } while (!(status & SCxSR_TEND(port))); @@ -1571,6 +1574,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, if ((termios->c_cflag & CREAD) != 0) sci_start_rx(port); + + if (s->disable) + s->disable(port); } static const char *sci_type(struct uart_port *port) -- cgit v0.10.2 From c1d0df341fad34f9a763dd1382d256da352d67eb Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Sun, 27 Feb 2011 21:36:42 +0000 Subject: sh: Rename cpuidle states to fit general conventions C0 is known as "busy", "not idle" state. X86 "busy polling" state also got renamed from C0 to "POLL" recently. Let's stay consistent with naming to avoid confusions. Signed-off-by: Thomas Renninger Acked-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c index c19e2a9..e4469e72 100644 --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c @@ -75,7 +75,7 @@ void sh_mobile_setup_cpuidle(void) i = CPUIDLE_DRIVER_STATE_START; state = &dev->states[i++]; - snprintf(state->name, CPUIDLE_NAME_LEN, "C0"); + snprintf(state->name, CPUIDLE_NAME_LEN, "C1"); strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN); state->exit_latency = 1; state->target_residency = 1 * 2; @@ -88,7 +88,7 @@ void sh_mobile_setup_cpuidle(void) if (sh_mobile_sleep_supported & SUSP_SH_SF) { state = &dev->states[i++]; - snprintf(state->name, CPUIDLE_NAME_LEN, "C1"); + snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); strncpy(state->desc, "SuperH Sleep Mode [SF]", CPUIDLE_DESC_LEN); state->exit_latency = 100; @@ -101,7 +101,7 @@ void sh_mobile_setup_cpuidle(void) if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) { state = &dev->states[i++]; - snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); + snprintf(state->name, CPUIDLE_NAME_LEN, "C3"); strncpy(state->desc, "SuperH Mobile Standby Mode [SF]", CPUIDLE_DESC_LEN); state->exit_latency = 2300; -- cgit v0.10.2 From 0fe48601d819c838c04121bc8d6fffa3a7aaf8e3 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 25 Feb 2011 07:38:47 +0000 Subject: sh: add USB_ARCH_HAS_EHCI and OHCI for SH7757 Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 8a9011d..ca649d3 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -434,6 +434,8 @@ config CPU_SUBTYPE_SH7757 select CPU_SH4A select CPU_SHX2 select ARCH_WANT_OPTIONAL_GPIOLIB + select USB_ARCH_HAS_OHCI + select USB_ARCH_HAS_EHCI help Select SH7757 if you have a SH4A SH7757 CPU. -- cgit v0.10.2 From d0371667d1393ec6655fa3bdd6e6008cfdea528c Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 25 Feb 2011 07:39:10 +0000 Subject: sh: add platform_device for SPI Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index 9c1de26..480f665 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c @@ -124,12 +124,36 @@ static struct platform_device tmu1_device = { .num_resources = ARRAY_SIZE(tmu1_resources), }; +static struct resource spi0_resources[] = { + [0] = { + .start = 0xfe002000, + .end = 0xfe0020ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 86, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device spi0_device = { + .name = "sh_spi", + .id = 0, + .dev = { + .dma_mask = NULL, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(spi0_resources), + .resource = spi0_resources, +}; + static struct platform_device *sh7757_devices[] __initdata = { &scif2_device, &scif3_device, &scif4_device, &tmu0_device, &tmu1_device, + &spi0_device, }; static int __init sh7757_devices_setup(void) -- cgit v0.10.2 From ceb7afe270c9a41130ffd3560e284f1ba0b2abe0 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 25 Feb 2011 07:39:32 +0000 Subject: sh: add spi_board_info in sh7757lcr Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c index c475f10..be5f5cf 100644 --- a/arch/sh/boards/board-sh7757lcr.c +++ b/arch/sh/boards/board-sh7757lcr.c @@ -104,6 +104,21 @@ static struct platform_device *sh7757lcr_devices[] __initdata = { &sh7757_eth1_device, }; +static struct flash_platform_data spi_flash_data = { + .name = "m25p80", + .type = "m25px64", +}; + +static struct spi_board_info spi_board_info[] = { + { + .modalias = "m25p80", + .max_speed_hz = 25000000, + .bus_num = 0, + .chip_select = 1, + .platform_data = &spi_flash_data, + }, +}; + static int __init sh7757lcr_devices_setup(void) { /* RGMII (PTA) */ @@ -332,6 +347,10 @@ static int __init sh7757lcr_devices_setup(void) gpio_request(GPIO_PTT5, NULL); /* eMMC_PRST# */ gpio_direction_output(GPIO_PTT5, 1); + /* register SPI device information */ + spi_register_board_info(spi_board_info, + ARRAY_SIZE(spi_board_info)); + /* General platform */ return platform_add_devices(sh7757lcr_devices, ARRAY_SIZE(sh7757lcr_devices)); -- cgit v0.10.2 From 53bc18ef4d8cb287c0667389fa05721aedf54e15 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 25 Feb 2011 07:39:49 +0000 Subject: sh: add mmc clock in clock-sh7757 Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c index e073e3e..eedddad 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c @@ -77,9 +77,10 @@ struct clk div4_clks[DIV4_NR] = { #define MSTPCR0 0xffc80030 #define MSTPCR1 0xffc80034 +#define MSTPCR2 0xffc10028 enum { MSTP004, MSTP000, MSTP114, MSTP113, MSTP112, - MSTP111, MSTP110, MSTP103, MSTP102, + MSTP111, MSTP110, MSTP103, MSTP102, MSTP220, MSTP_NR }; static struct clk mstp_clks[MSTP_NR] = { @@ -95,6 +96,9 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP110] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 10, 0), [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 0), [MSTP102] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 2, 0), + + /* MSTPCR2 */ + [MSTP220] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 20, 0), }; #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } @@ -140,6 +144,7 @@ static struct clk_lookup lookups[] = { .clk = &mstp_clks[MSTP110], }, CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]), + CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]), }; int __init arch_clk_init(void) -- cgit v0.10.2 From 8ac53ed537a4a32d81279d37476bfaeb2aff15ab Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 25 Feb 2011 07:40:16 +0000 Subject: sh: dmaengine support for SH7757 Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt diff --git a/arch/sh/include/cpu-sh4/cpu/dma-register.h b/arch/sh/include/cpu-sh4/cpu/dma-register.h index 9a6125e..18fa80a 100644 --- a/arch/sh/include/cpu-sh4/cpu/dma-register.h +++ b/arch/sh/include/cpu-sh4/cpu/dma-register.h @@ -40,6 +40,11 @@ #define CHCR_TS_LOW_SHIFT 3 #define CHCR_TS_HIGH_MASK 0 #define CHCR_TS_HIGH_SHIFT 0 +#elif defined(CONFIG_CPU_SUBTYPE_SH7757) +#define CHCR_TS_LOW_MASK 0x00000018 +#define CHCR_TS_LOW_SHIFT 3 +#define CHCR_TS_HIGH_MASK 0x00100000 +#define CHCR_TS_HIGH_SHIFT (20 - 2) /* 2 bits for shifted low TS */ #elif defined(CONFIG_CPU_SUBTYPE_SH7780) #define CHCR_TS_LOW_MASK 0x00000018 #define CHCR_TS_LOW_SHIFT 3 diff --git a/arch/sh/include/cpu-sh4/cpu/sh7757.h b/arch/sh/include/cpu-sh4/cpu/sh7757.h index 15f3de1..05b8196 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7757.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7757.h @@ -251,4 +251,36 @@ enum { GPIO_FN_ON_DQ3, GPIO_FN_ON_DQ2, GPIO_FN_ON_DQ1, GPIO_FN_ON_DQ0, }; +enum { + SHDMA_SLAVE_SDHI_TX, + SHDMA_SLAVE_SDHI_RX, + SHDMA_SLAVE_MMCIF_TX, + SHDMA_SLAVE_MMCIF_RX, + SHDMA_SLAVE_SCIF2_TX, + SHDMA_SLAVE_SCIF2_RX, + SHDMA_SLAVE_SCIF3_TX, + SHDMA_SLAVE_SCIF3_RX, + SHDMA_SLAVE_SCIF4_TX, + SHDMA_SLAVE_SCIF4_RX, + SHDMA_SLAVE_RIIC0_TX, + SHDMA_SLAVE_RIIC0_RX, + SHDMA_SLAVE_RIIC1_TX, + SHDMA_SLAVE_RIIC1_RX, + SHDMA_SLAVE_RIIC2_TX, + SHDMA_SLAVE_RIIC2_RX, + SHDMA_SLAVE_RIIC3_TX, + SHDMA_SLAVE_RIIC3_RX, + SHDMA_SLAVE_RIIC4_TX, + SHDMA_SLAVE_RIIC4_RX, + SHDMA_SLAVE_RIIC5_TX, + SHDMA_SLAVE_RIIC5_RX, + SHDMA_SLAVE_RIIC6_TX, + SHDMA_SLAVE_RIIC6_RX, + SHDMA_SLAVE_RIIC7_TX, + SHDMA_SLAVE_RIIC7_RX, + SHDMA_SLAVE_RIIC8_TX, + SHDMA_SLAVE_RIIC8_RX, + SHDMA_SLAVE_RIIC9_TX, + SHDMA_SLAVE_RIIC9_RX, +}; #endif /* __ASM_SH7757_H__ */ diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index 480f665..423dabf 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c @@ -1,7 +1,7 @@ /* * SH7757 Setup * - * Copyright (C) 2009 Renesas Solutions Corp. + * Copyright (C) 2009, 2011 Renesas Solutions Corp. * * based on setup-sh7785.c : Copyright (C) 2007 Paul Mundt * @@ -16,6 +16,10 @@ #include #include #include +#include + +#include +#include static struct plat_sci_port scif2_platform_data = { .mapbase = 0xfe4b0000, /* SCIF2 */ @@ -136,6 +140,514 @@ static struct resource spi0_resources[] = { }, }; +/* DMA */ +static const struct sh_dmae_slave_config sh7757_dmae0_slaves[] = { + { + .slave_id = SHDMA_SLAVE_SDHI_TX, + .addr = 0x1fe50030, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_16BIT), + .mid_rid = 0xc5, + }, + { + .slave_id = SHDMA_SLAVE_SDHI_RX, + .addr = 0x1fe50030, + .chcr = DM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_16BIT), + .mid_rid = 0xc6, + }, + { + .slave_id = SHDMA_SLAVE_MMCIF_TX, + .addr = 0x1fcb0034, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0xd3, + }, + { + .slave_id = SHDMA_SLAVE_MMCIF_RX, + .addr = 0x1fcb0034, + .chcr = DM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0xd7, + }, +}; + +static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = { + { + .slave_id = SHDMA_SLAVE_SCIF2_TX, + .addr = 0x1f4b000c, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x21, + }, + { + .slave_id = SHDMA_SLAVE_SCIF2_RX, + .addr = 0x1f4b0014, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x22, + }, + { + .slave_id = SHDMA_SLAVE_SCIF3_TX, + .addr = 0x1f4c000c, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x29, + }, + { + .slave_id = SHDMA_SLAVE_SCIF3_RX, + .addr = 0x1f4c0014, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x2a, + }, + { + .slave_id = SHDMA_SLAVE_SCIF4_TX, + .addr = 0x1f4d000c, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x41, + }, + { + .slave_id = SHDMA_SLAVE_SCIF4_RX, + .addr = 0x1f4d0014, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x42, + }, +}; + +static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = { + { + .slave_id = SHDMA_SLAVE_RIIC0_TX, + .addr = 0x1e500012, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x21, + }, + { + .slave_id = SHDMA_SLAVE_RIIC0_RX, + .addr = 0x1e500013, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x22, + }, + { + .slave_id = SHDMA_SLAVE_RIIC1_TX, + .addr = 0x1e510012, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x29, + }, + { + .slave_id = SHDMA_SLAVE_RIIC1_RX, + .addr = 0x1e510013, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x2a, + }, + { + .slave_id = SHDMA_SLAVE_RIIC2_TX, + .addr = 0x1e520012, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0xa1, + }, + { + .slave_id = SHDMA_SLAVE_RIIC2_RX, + .addr = 0x1e520013, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0xa2, + }, + { + .slave_id = SHDMA_SLAVE_RIIC3_TX, + .addr = 0x1e530012, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0xab, + }, + { + .slave_id = SHDMA_SLAVE_RIIC3_RX, + .addr = 0x1e530013, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0xaf, + }, + { + .slave_id = SHDMA_SLAVE_RIIC4_TX, + .addr = 0x1e540012, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0xc1, + }, + { + .slave_id = SHDMA_SLAVE_RIIC4_RX, + .addr = 0x1e540013, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0xc2, + }, +}; + +static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = { + { + .slave_id = SHDMA_SLAVE_RIIC5_TX, + .addr = 0x1e550012, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x21, + }, + { + .slave_id = SHDMA_SLAVE_RIIC5_RX, + .addr = 0x1e550013, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x22, + }, + { + .slave_id = SHDMA_SLAVE_RIIC6_TX, + .addr = 0x1e560012, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x29, + }, + { + .slave_id = SHDMA_SLAVE_RIIC6_RX, + .addr = 0x1e560013, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x2a, + }, + { + .slave_id = SHDMA_SLAVE_RIIC7_TX, + .addr = 0x1e570012, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x41, + }, + { + .slave_id = SHDMA_SLAVE_RIIC7_RX, + .addr = 0x1e570013, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x42, + }, + { + .slave_id = SHDMA_SLAVE_RIIC8_TX, + .addr = 0x1e580012, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x45, + }, + { + .slave_id = SHDMA_SLAVE_RIIC8_RX, + .addr = 0x1e580013, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x46, + }, + { + .slave_id = SHDMA_SLAVE_RIIC9_TX, + .addr = 0x1e590012, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x51, + }, + { + .slave_id = SHDMA_SLAVE_RIIC9_RX, + .addr = 0x1e590013, + .chcr = SM_INC | 0x800 | 0x40000000 | + TS_INDEX2VAL(XMIT_SZ_8BIT), + .mid_rid = 0x52, + }, +}; + +static const struct sh_dmae_channel sh7757_dmae_channels[] = { + { + .offset = 0, + .dmars = 0, + .dmars_bit = 0, + }, { + .offset = 0x10, + .dmars = 0, + .dmars_bit = 8, + }, { + .offset = 0x20, + .dmars = 4, + .dmars_bit = 0, + }, { + .offset = 0x30, + .dmars = 4, + .dmars_bit = 8, + }, { + .offset = 0x50, + .dmars = 8, + .dmars_bit = 0, + }, { + .offset = 0x60, + .dmars = 8, + .dmars_bit = 8, + } +}; + +static const unsigned int ts_shift[] = TS_SHIFT; + +static struct sh_dmae_pdata dma0_platform_data = { + .slave = sh7757_dmae0_slaves, + .slave_num = ARRAY_SIZE(sh7757_dmae0_slaves), + .channel = sh7757_dmae_channels, + .channel_num = ARRAY_SIZE(sh7757_dmae_channels), + .ts_low_shift = CHCR_TS_LOW_SHIFT, + .ts_low_mask = CHCR_TS_LOW_MASK, + .ts_high_shift = CHCR_TS_HIGH_SHIFT, + .ts_high_mask = CHCR_TS_HIGH_MASK, + .ts_shift = ts_shift, + .ts_shift_num = ARRAY_SIZE(ts_shift), + .dmaor_init = DMAOR_INIT, +}; + +static struct sh_dmae_pdata dma1_platform_data = { + .slave = sh7757_dmae1_slaves, + .slave_num = ARRAY_SIZE(sh7757_dmae1_slaves), + .channel = sh7757_dmae_channels, + .channel_num = ARRAY_SIZE(sh7757_dmae_channels), + .ts_low_shift = CHCR_TS_LOW_SHIFT, + .ts_low_mask = CHCR_TS_LOW_MASK, + .ts_high_shift = CHCR_TS_HIGH_SHIFT, + .ts_high_mask = CHCR_TS_HIGH_MASK, + .ts_shift = ts_shift, + .ts_shift_num = ARRAY_SIZE(ts_shift), + .dmaor_init = DMAOR_INIT, +}; + +static struct sh_dmae_pdata dma2_platform_data = { + .slave = sh7757_dmae2_slaves, + .slave_num = ARRAY_SIZE(sh7757_dmae2_slaves), + .channel = sh7757_dmae_channels, + .channel_num = ARRAY_SIZE(sh7757_dmae_channels), + .ts_low_shift = CHCR_TS_LOW_SHIFT, + .ts_low_mask = CHCR_TS_LOW_MASK, + .ts_high_shift = CHCR_TS_HIGH_SHIFT, + .ts_high_mask = CHCR_TS_HIGH_MASK, + .ts_shift = ts_shift, + .ts_shift_num = ARRAY_SIZE(ts_shift), + .dmaor_init = DMAOR_INIT, +}; + +static struct sh_dmae_pdata dma3_platform_data = { + .slave = sh7757_dmae3_slaves, + .slave_num = ARRAY_SIZE(sh7757_dmae3_slaves), + .channel = sh7757_dmae_channels, + .channel_num = ARRAY_SIZE(sh7757_dmae_channels), + .ts_low_shift = CHCR_TS_LOW_SHIFT, + .ts_low_mask = CHCR_TS_LOW_MASK, + .ts_high_shift = CHCR_TS_HIGH_SHIFT, + .ts_high_mask = CHCR_TS_HIGH_MASK, + .ts_shift = ts_shift, + .ts_shift_num = ARRAY_SIZE(ts_shift), + .dmaor_init = DMAOR_INIT, +}; + +/* channel 0 to 5 */ +static struct resource sh7757_dmae0_resources[] = { + [0] = { + /* Channel registers and DMAOR */ + .start = 0xff608020, + .end = 0xff60808f, + .flags = IORESOURCE_MEM, + }, + [1] = { + /* DMARSx */ + .start = 0xff609000, + .end = 0xff60900b, + .flags = IORESOURCE_MEM, + }, + { + .start = 34, + .end = 34, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, + }, +}; + +/* channel 6 to 11 */ +static struct resource sh7757_dmae1_resources[] = { + [0] = { + /* Channel registers and DMAOR */ + .start = 0xff618020, + .end = 0xff61808f, + .flags = IORESOURCE_MEM, + }, + [1] = { + /* DMARSx */ + .start = 0xff619000, + .end = 0xff61900b, + .flags = IORESOURCE_MEM, + }, + { + /* DMA error */ + .start = 34, + .end = 34, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, + }, + { + /* IRQ for channels 4 */ + .start = 46, + .end = 46, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, + }, + { + /* IRQ for channels 5 */ + .start = 46, + .end = 46, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, + }, + { + /* IRQ for channels 6 */ + .start = 88, + .end = 88, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, + }, + { + /* IRQ for channels 7 */ + .start = 88, + .end = 88, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, + }, + { + /* IRQ for channels 8 */ + .start = 88, + .end = 88, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, + }, + { + /* IRQ for channels 9 */ + .start = 88, + .end = 88, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, + }, + { + /* IRQ for channels 10 */ + .start = 88, + .end = 88, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, + }, + { + /* IRQ for channels 11 */ + .start = 88, + .end = 88, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, + }, +}; + +/* channel 12 to 17 */ +static struct resource sh7757_dmae2_resources[] = { + [0] = { + /* Channel registers and DMAOR */ + .start = 0xff708020, + .end = 0xff70808f, + .flags = IORESOURCE_MEM, + }, + [1] = { + /* DMARSx */ + .start = 0xff709000, + .end = 0xff70900b, + .flags = IORESOURCE_MEM, + }, + { + /* DMA error */ + .start = 323, + .end = 323, + .flags = IORESOURCE_IRQ, + }, + { + /* IRQ for channels 12 to 16 */ + .start = 272, + .end = 276, + .flags = IORESOURCE_IRQ, + }, + { + /* IRQ for channel 17 */ + .start = 279, + .end = 279, + .flags = IORESOURCE_IRQ, + }, +}; + +/* channel 18 to 23 */ +static struct resource sh7757_dmae3_resources[] = { + [0] = { + /* Channel registers and DMAOR */ + .start = 0xff718020, + .end = 0xff71808f, + .flags = IORESOURCE_MEM, + }, + [1] = { + /* DMARSx */ + .start = 0xff719000, + .end = 0xff71900b, + .flags = IORESOURCE_MEM, + }, + { + /* DMA error */ + .start = 324, + .end = 324, + .flags = IORESOURCE_IRQ, + }, + { + /* IRQ for channels 18 to 22 */ + .start = 280, + .end = 284, + .flags = IORESOURCE_IRQ, + }, + { + /* IRQ for channel 23 */ + .start = 288, + .end = 288, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device dma0_device = { + .name = "sh-dma-engine", + .id = 0, + .resource = sh7757_dmae0_resources, + .num_resources = ARRAY_SIZE(sh7757_dmae0_resources), + .dev = { + .platform_data = &dma0_platform_data, + }, +}; + +static struct platform_device dma1_device = { + .name = "sh-dma-engine", + .id = 1, + .resource = sh7757_dmae1_resources, + .num_resources = ARRAY_SIZE(sh7757_dmae1_resources), + .dev = { + .platform_data = &dma1_platform_data, + }, +}; + +static struct platform_device dma2_device = { + .name = "sh-dma-engine", + .id = 2, + .resource = sh7757_dmae2_resources, + .num_resources = ARRAY_SIZE(sh7757_dmae2_resources), + .dev = { + .platform_data = &dma2_platform_data, + }, +}; + +static struct platform_device dma3_device = { + .name = "sh-dma-engine", + .id = 3, + .resource = sh7757_dmae3_resources, + .num_resources = ARRAY_SIZE(sh7757_dmae3_resources), + .dev = { + .platform_data = &dma3_platform_data, + }, +}; + static struct platform_device spi0_device = { .name = "sh_spi", .id = 0, @@ -153,6 +665,10 @@ static struct platform_device *sh7757_devices[] __initdata = { &scif4_device, &tmu0_device, &tmu1_device, + &dma0_device, + &dma1_device, + &dma2_device, + &dma3_device, &spi0_device, }; -- cgit v0.10.2 From 65f63eab38626a79f8a54d13686680a1ea898f72 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 25 Feb 2011 07:40:27 +0000 Subject: sh: add platform_device of tmio_mmc and sh_mmcif to sh7757lcr Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c index be5f5cf..80e502c 100644 --- a/arch/sh/boards/board-sh7757lcr.c +++ b/arch/sh/boards/board-sh7757lcr.c @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -98,10 +101,80 @@ static struct platform_device sh7757_eth1_device = { }, }; +/* SH_MMCIF */ +static struct resource sh_mmcif_resources[] = { + [0] = { + .start = 0xffcb0000, + .end = 0xffcb00ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 211, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = 212, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct sh_mmcif_dma sh7757lcr_mmcif_dma = { + .chan_priv_tx = SHDMA_SLAVE_MMCIF_TX, + .chan_priv_rx = SHDMA_SLAVE_MMCIF_RX, +}; + +static struct sh_mmcif_plat_data sh_mmcif_plat = { + .dma = &sh7757lcr_mmcif_dma, + .sup_pclk = 0x0f, + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, + .ocr = MMC_VDD_32_33 | MMC_VDD_33_34, +}; + +static struct platform_device sh_mmcif_device = { + .name = "sh_mmcif", + .id = 0, + .dev = { + .platform_data = &sh_mmcif_plat, + }, + .num_resources = ARRAY_SIZE(sh_mmcif_resources), + .resource = sh_mmcif_resources, +}; + +/* SDHI0 */ +static struct sh_mobile_sdhi_info sdhi_info = { + .dma_slave_tx = SHDMA_SLAVE_SDHI_TX, + .dma_slave_rx = SHDMA_SLAVE_SDHI_RX, + .tmio_caps = MMC_CAP_SD_HIGHSPEED, +}; + +static struct resource sdhi_resources[] = { + [0] = { + .start = 0xffe50000, + .end = 0xffe501ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 20, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sdhi_device = { + .name = "sh_mobile_sdhi", + .num_resources = ARRAY_SIZE(sdhi_resources), + .resource = sdhi_resources, + .id = 0, + .dev = { + .platform_data = &sdhi_info, + }, +}; + static struct platform_device *sh7757lcr_devices[] __initdata = { &heartbeat_device, &sh7757_eth0_device, &sh7757_eth1_device, + &sh_mmcif_device, + &sdhi_device, }; static struct flash_platform_data spi_flash_data = { -- cgit v0.10.2 From 5a79ce76e9bb8f4b2cd8106ee36d15ee05013bcf Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 25 Feb 2011 07:40:34 +0000 Subject: sh: update sh7757lcr_defconfig - enable SPI bus, MTD, MMCIF, SD, USB host, and USB storage. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt diff --git a/arch/sh/configs/sh7757lcr_defconfig b/arch/sh/configs/sh7757lcr_defconfig index 5f7f667..fa0ecf8 100644 --- a/arch/sh/configs/sh7757lcr_defconfig +++ b/arch/sh/configs/sh7757lcr_defconfig @@ -38,7 +38,15 @@ CONFIG_IPV6=y # CONFIG_WIRELESS is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_FW_LOADER is not set +CONFIG_MTD=y +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_M25P80=y CONFIG_BLK_DEV_RAM=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y CONFIG_NETDEVICES=y CONFIG_VITESSE_PHY=y CONFIG_NET_ETHERNET=y @@ -53,8 +61,17 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3 CONFIG_SERIAL_SH_SCI_CONSOLE=y # CONFIG_LEGACY_PTYS is not set # CONFIG_HW_RANDOM is not set +CONFIG_SPI=y +CONFIG_SPI_SH=y # CONFIG_HWMON is not set -# CONFIG_USB_SUPPORT is not set +CONFIG_MFD_SH_MOBILE_SDHI=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_MMC=y +CONFIG_MMC_TMIO=y +CONFIG_MMC_SH_MMCIF=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y CONFIG_ISO9660_FS=y -- cgit v0.10.2 From 984f6cfd21babd70302592641bd01b574e25ee83 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 8 Mar 2011 08:00:00 +0000 Subject: sh: add GETHER's platform_device in board-sh7757lcr This patch also modifies for ETHER's platform_device. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c index 80e502c..a9e3356 100644 --- a/arch/sh/boards/board-sh7757lcr.c +++ b/arch/sh/boards/board-sh7757lcr.c @@ -47,6 +47,17 @@ static struct platform_device heartbeat_device = { }; /* Fast Ethernet */ +#define GBECONT 0xffc10100 +#define GBECONT_RMII1 BIT(17) +#define GBECONT_RMII0 BIT(16) +static void sh7757_eth_set_mdio_gate(unsigned long addr) +{ + if ((addr & 0x00000fff) < 0x0800) + writel(readl(GBECONT) | GBECONT_RMII0, GBECONT); + else + writel(readl(GBECONT) | GBECONT_RMII1, GBECONT); +} + static struct resource sh_eth0_resources[] = { { .start = 0xfef00000, @@ -62,6 +73,8 @@ static struct resource sh_eth0_resources[] = { static struct sh_eth_plat_data sh7757_eth0_pdata = { .phy = 1, .edmac_endian = EDMAC_LITTLE_ENDIAN, + .register_type = SH_ETH_REG_FAST_SH4, + .set_mdio_gate = sh7757_eth_set_mdio_gate, }; static struct platform_device sh7757_eth0_device = { @@ -89,6 +102,8 @@ static struct resource sh_eth1_resources[] = { static struct sh_eth_plat_data sh7757_eth1_pdata = { .phy = 1, .edmac_endian = EDMAC_LITTLE_ENDIAN, + .register_type = SH_ETH_REG_FAST_SH4, + .set_mdio_gate = sh7757_eth_set_mdio_gate, }; static struct platform_device sh7757_eth1_device = { @@ -101,6 +116,82 @@ static struct platform_device sh7757_eth1_device = { }, }; +static void sh7757_eth_giga_set_mdio_gate(unsigned long addr) +{ + if ((addr & 0x00000fff) < 0x0800) { + gpio_set_value(GPIO_PTT4, 1); + writel(readl(GBECONT) & ~GBECONT_RMII0, GBECONT); + } else { + gpio_set_value(GPIO_PTT4, 0); + writel(readl(GBECONT) & ~GBECONT_RMII1, GBECONT); + } +} + +static struct resource sh_eth_giga0_resources[] = { + { + .start = 0xfee00000, + .end = 0xfee007ff, + .flags = IORESOURCE_MEM, + }, { + /* TSU */ + .start = 0xfee01800, + .end = 0xfee01fff, + .flags = IORESOURCE_MEM, + }, { + .start = 315, + .end = 315, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct sh_eth_plat_data sh7757_eth_giga0_pdata = { + .phy = 18, + .edmac_endian = EDMAC_LITTLE_ENDIAN, + .register_type = SH_ETH_REG_GIGABIT, + .set_mdio_gate = sh7757_eth_giga_set_mdio_gate, + .phy_interface = PHY_INTERFACE_MODE_RGMII_ID, +}; + +static struct platform_device sh7757_eth_giga0_device = { + .name = "sh-eth", + .resource = sh_eth_giga0_resources, + .id = 2, + .num_resources = ARRAY_SIZE(sh_eth_giga0_resources), + .dev = { + .platform_data = &sh7757_eth_giga0_pdata, + }, +}; + +static struct resource sh_eth_giga1_resources[] = { + { + .start = 0xfee00800, + .end = 0xfee00fff, + .flags = IORESOURCE_MEM, + }, { + .start = 316, + .end = 316, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct sh_eth_plat_data sh7757_eth_giga1_pdata = { + .phy = 19, + .edmac_endian = EDMAC_LITTLE_ENDIAN, + .register_type = SH_ETH_REG_GIGABIT, + .set_mdio_gate = sh7757_eth_giga_set_mdio_gate, + .phy_interface = PHY_INTERFACE_MODE_RGMII_ID, +}; + +static struct platform_device sh7757_eth_giga1_device = { + .name = "sh-eth", + .resource = sh_eth_giga1_resources, + .id = 3, + .num_resources = ARRAY_SIZE(sh_eth_giga1_resources), + .dev = { + .platform_data = &sh7757_eth_giga1_pdata, + }, +}; + /* SH_MMCIF */ static struct resource sh_mmcif_resources[] = { [0] = { @@ -173,6 +264,8 @@ static struct platform_device *sh7757lcr_devices[] __initdata = { &heartbeat_device, &sh7757_eth0_device, &sh7757_eth1_device, + &sh7757_eth_giga0_device, + &sh7757_eth_giga1_device, &sh_mmcif_device, &sdhi_device, }; -- cgit v0.10.2 From 9055f895f805afd57b833e51c4665aa1b2579d43 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 8 Mar 2011 08:00:04 +0000 Subject: sh: modify platform_device for sh_eth driver A new parameter is added to sh_eth_plat_data. And the sh_eth driver needs additional memory resource if a module has TSU. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt diff --git a/arch/sh/boards/board-espt.c b/arch/sh/boards/board-espt.c index d5ce5e1..9da92ac 100644 --- a/arch/sh/boards/board-espt.c +++ b/arch/sh/boards/board-espt.c @@ -66,6 +66,11 @@ static struct resource sh_eth_resources[] = { .end = 0xFEE00F7C - 1, .flags = IORESOURCE_MEM, }, { + .start = 0xFEE01800, /* TSU */ + .end = 0xFEE01FFF, + .flags = IORESOURCE_MEM, + }, { + .start = 57, /* irq number */ .flags = IORESOURCE_IRQ, }, @@ -74,6 +79,8 @@ static struct resource sh_eth_resources[] = { static struct sh_eth_plat_data sh7763_eth_pdata = { .phy = 0, .edmac_endian = EDMAC_LITTLE_ENDIAN, + .register_type = SH_ETH_REG_GIGABIT, + .phy_interface = PHY_INTERFACE_MODE_MII, }; static struct platform_device espt_eth_device = { diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 701667a..3b71d21 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -142,6 +142,8 @@ static struct resource sh_eth_resources[] = { static struct sh_eth_plat_data sh_eth_plat = { .phy = 0x1f, /* SMSC LAN8700 */ .edmac_endian = EDMAC_LITTLE_ENDIAN, + .register_type = SH_ETH_REG_FAST_SH4, + .phy_interface = PHY_INTERFACE_MODE_MII, .ether_link_active_low = 1 }; diff --git a/arch/sh/boards/mach-sh7763rdp/setup.c b/arch/sh/boards/mach-sh7763rdp/setup.c index f64a691..f3d828f 100644 --- a/arch/sh/boards/mach-sh7763rdp/setup.c +++ b/arch/sh/boards/mach-sh7763rdp/setup.c @@ -75,6 +75,10 @@ static struct resource sh_eth_resources[] = { .end = 0xFEE00F7C - 1, .flags = IORESOURCE_MEM, }, { + .start = 0xFEE01800, /* TSU */ + .end = 0xFEE01FFF, + .flags = IORESOURCE_MEM, + }, { .start = 57, /* irq number */ .flags = IORESOURCE_IRQ, }, @@ -83,6 +87,8 @@ static struct resource sh_eth_resources[] = { static struct sh_eth_plat_data sh7763_eth_pdata = { .phy = 1, .edmac_endian = EDMAC_LITTLE_ENDIAN, + .register_type = SH_ETH_REG_GIGABIT, + .phy_interface = PHY_INTERFACE_MODE_MII, }; static struct platform_device sh7763rdp_eth_device = { -- cgit v0.10.2 From a88403335a9ffc66a0a1b46b6d303512eddde846 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 17 Mar 2011 17:01:24 +0900 Subject: sh: Wire up new fhandle and clock_adjtime syscalls. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h index d6741fc..b5a74e8 100644 --- a/arch/sh/include/asm/unistd_32.h +++ b/arch/sh/include/asm/unistd_32.h @@ -369,8 +369,11 @@ #define __NR_recvmsg 356 #define __NR_recvmmsg 357 #define __NR_accept4 358 +#define __NR_name_to_handle_at 359 +#define __NR_open_by_handle_at 360 +#define __NR_clock_adjtime 361 -#define NR_syscalls 359 +#define NR_syscalls 362 #ifdef __KERNEL__ diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h index 09aa93f..953da4a 100644 --- a/arch/sh/include/asm/unistd_64.h +++ b/arch/sh/include/asm/unistd_64.h @@ -390,10 +390,13 @@ #define __NR_fanotify_init 367 #define __NR_fanotify_mark 368 #define __NR_prlimit64 369 +#define __NR_name_to_handle_at 370 +#define __NR_open_by_handle_at 371 +#define __NR_clock_adjtime 372 #ifdef __KERNEL__ -#define NR_syscalls 370 +#define NR_syscalls 373 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index 6fc347e..768fb33 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S @@ -376,3 +376,6 @@ ENTRY(sys_call_table) .long sys_recvmsg .long sys_recvmmsg .long sys_accept4 + .long sys_name_to_handle_at + .long sys_open_by_handle_at /* 360 */ + .long sys_clock_adjtime diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 6658570..44e7b00 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S @@ -396,3 +396,6 @@ sys_call_table: .long sys_fanotify_init .long sys_fanotify_mark .long sys_prlimit64 + .long sys_name_to_handle_at /* 370 */ + .long sys_open_by_handle_at + .long sys_clock_adjtime -- cgit v0.10.2 From 3d44ae402a4e35cf88784d443046c8fbe25c674b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 17 Mar 2011 17:31:51 +0900 Subject: sh: Convert to generic show_interrupts. Trivial conversion, simply encapsulate the NMI stats in the arch code. Signed-off-by: Paul Mundt diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ca649d3..2d264fa 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -25,6 +25,7 @@ config SUPERH select GENERIC_ATOMIC64 # Support the deprecated APIs until MFD and GPIOLIB catch up. select GENERIC_HARDIRQS_NO_DEPRECATED if !MFD_SUPPORT && !GPIOLIB + select GENERIC_IRQ_SHOW help The SuperH is a RISC processor targeted for use in embedded systems and consumer electronics; it was also used in the Sega Dreamcast diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 68ecbe6..64ea0b1 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -34,9 +34,9 @@ void ack_bad_irq(unsigned int irq) #if defined(CONFIG_PROC_FS) /* - * /proc/interrupts printing: + * /proc/interrupts printing for arch specific interrupts */ -static int show_other_interrupts(struct seq_file *p, int prec) +int arch_show_interrupts(struct seq_file *p, int prec) { int j; @@ -49,63 +49,6 @@ static int show_other_interrupts(struct seq_file *p, int prec) return 0; } - -int show_interrupts(struct seq_file *p, void *v) -{ - unsigned long flags, any_count = 0; - int i = *(loff_t *)v, j, prec; - struct irqaction *action; - struct irq_desc *desc; - struct irq_data *data; - struct irq_chip *chip; - - if (i > nr_irqs) - return 0; - - for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec) - j *= 10; - - if (i == nr_irqs) - return show_other_interrupts(p, prec); - - if (i == 0) { - seq_printf(p, "%*s", prec + 8, ""); - for_each_online_cpu(j) - seq_printf(p, "CPU%-8d", j); - seq_putc(p, '\n'); - } - - desc = irq_to_desc(i); - if (!desc) - return 0; - - data = irq_get_irq_data(i); - chip = irq_data_get_irq_chip(data); - - raw_spin_lock_irqsave(&desc->lock, flags); - for_each_online_cpu(j) - any_count |= kstat_irqs_cpu(i, j); - action = desc->action; - if (!action && !any_count) - goto out; - - seq_printf(p, "%*d: ", prec, i); - for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); - seq_printf(p, " %14s", chip->name); - seq_printf(p, "-%-8s", desc->name); - - if (action) { - seq_printf(p, " %s", action->name); - while ((action = action->next) != NULL) - seq_printf(p, ", %s", action->name); - } - - seq_putc(p, '\n'); -out: - raw_spin_unlock_irqrestore(&desc->lock, flags); - return 0; -} #endif #ifdef CONFIG_IRQSTACKS -- cgit v0.10.2