Merge branches 'sh/smp' and 'sh/stable-updates'
authorPaul Mundt <lethal@linux-sh.org>
Tue, 8 Sep 2009 07:27:31 +0000 (16:27 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Tue, 8 Sep 2009 07:27:31 +0000 (16:27 +0900)
247 files changed:
Documentation/kernel-parameters.txt
Documentation/power/runtime_pm.txt [new file with mode: 0644]
arch/arm/include/asm/device.h
arch/arm/plat-omap/debug-leds.c
arch/arm/plat-omap/gpio.c
arch/ia64/include/asm/device.h
arch/microblaze/include/asm/device.h
arch/powerpc/include/asm/device.h
arch/sh/Kconfig
arch/sh/Kconfig.debug
arch/sh/Makefile
arch/sh/boards/Kconfig
arch/sh/boards/board-ap325rxa.c
arch/sh/boards/board-sh7785lcr.c
arch/sh/boards/mach-ecovec24/Makefile [new file with mode: 0644]
arch/sh/boards/mach-ecovec24/setup.c [new file with mode: 0644]
arch/sh/boards/mach-highlander/setup.c
arch/sh/boards/mach-kfr2r09/Makefile [new file with mode: 0644]
arch/sh/boards/mach-kfr2r09/lcd_wqvga.c [new file with mode: 0644]
arch/sh/boards/mach-kfr2r09/setup.c [new file with mode: 0644]
arch/sh/boards/mach-migor/setup.c
arch/sh/boards/mach-se/7722/setup.c
arch/sh/boards/mach-se/7724/setup.c
arch/sh/boards/mach-x3proto/setup.c
arch/sh/boot/.gitignore
arch/sh/boot/Makefile
arch/sh/boot/compressed/.gitignore [new file with mode: 0644]
arch/sh/boot/compressed/Makefile
arch/sh/boot/compressed/head_32.S
arch/sh/boot/compressed/misc.c [new file with mode: 0644]
arch/sh/boot/compressed/misc_32.c [deleted file]
arch/sh/boot/compressed/misc_64.c [deleted file]
arch/sh/boot/compressed/piggy.S [deleted file]
arch/sh/boot/compressed/vmlinux.scr [new file with mode: 0644]
arch/sh/boot/romimage/Makefile [new file with mode: 0644]
arch/sh/boot/romimage/head.S [new file with mode: 0644]
arch/sh/boot/romimage/vmlinux.scr [new file with mode: 0644]
arch/sh/configs/ecovec24_defconfig [new file with mode: 0644]
arch/sh/configs/kfr2r09-romimage_defconfig [new file with mode: 0644]
arch/sh/configs/kfr2r09_defconfig [new file with mode: 0644]
arch/sh/configs/snapgear_defconfig
arch/sh/drivers/dma/Kconfig
arch/sh/drivers/heartbeat.c
arch/sh/drivers/pci/pci.c
arch/sh/include/asm/Kbuild
arch/sh/include/asm/bug.h
arch/sh/include/asm/bugs.h
arch/sh/include/asm/cachectl.h [new file with mode: 0644]
arch/sh/include/asm/cacheflush.h
arch/sh/include/asm/device.h
arch/sh/include/asm/dma-sh.h
arch/sh/include/asm/dwarf.h [new file with mode: 0644]
arch/sh/include/asm/entry-macros.S
arch/sh/include/asm/ftrace.h
arch/sh/include/asm/hardirq.h
arch/sh/include/asm/heartbeat.h
arch/sh/include/asm/hwblk.h [new file with mode: 0644]
arch/sh/include/asm/io.h
arch/sh/include/asm/kdebug.h
arch/sh/include/asm/kgdb.h
arch/sh/include/asm/lmb.h [new file with mode: 0644]
arch/sh/include/asm/mmu_context.h
arch/sh/include/asm/page.h
arch/sh/include/asm/pgtable.h
arch/sh/include/asm/pgtable_32.h
arch/sh/include/asm/pgtable_64.h
arch/sh/include/asm/processor.h
arch/sh/include/asm/sections.h
arch/sh/include/asm/stacktrace.h [new file with mode: 0644]
arch/sh/include/asm/suspend.h
arch/sh/include/asm/syscall_32.h
arch/sh/include/asm/system.h
arch/sh/include/asm/system_32.h
arch/sh/include/asm/system_64.h
arch/sh/include/asm/thread_info.h
arch/sh/include/asm/types.h
arch/sh/include/asm/unistd_32.h
arch/sh/include/asm/unistd_64.h
arch/sh/include/asm/unwinder.h [new file with mode: 0644]
arch/sh/include/asm/vmlinux.lds.h [new file with mode: 0644]
arch/sh/include/asm/watchdog.h
arch/sh/include/cpu-common/cpu/cacheflush.h [deleted file]
arch/sh/include/cpu-sh2a/cpu/cacheflush.h [deleted file]
arch/sh/include/cpu-sh3/cpu/cacheflush.h [deleted file]
arch/sh/include/cpu-sh4/cpu/cacheflush.h [deleted file]
arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
arch/sh/include/cpu-sh4/cpu/freq.h
arch/sh/include/cpu-sh4/cpu/sh7722.h
arch/sh/include/cpu-sh4/cpu/sh7723.h
arch/sh/include/cpu-sh4/cpu/sh7724.h
arch/sh/include/cpu-sh4/cpu/sh7757.h [new file with mode: 0644]
arch/sh/include/cpu-sh5/cpu/cacheflush.h [deleted file]
arch/sh/include/mach-common/mach/migor.h [deleted file]
arch/sh/include/mach-common/mach/romimage.h [new file with mode: 0644]
arch/sh/include/mach-common/mach/sh7785lcr.h
arch/sh/include/mach-kfr2r09/mach/kfr2r09.h [new file with mode: 0644]
arch/sh/include/mach-kfr2r09/mach/partner-jet-setup.txt [new file with mode: 0644]
arch/sh/include/mach-kfr2r09/mach/romimage.h [new file with mode: 0644]
arch/sh/include/mach-migor/mach/migor.h [new file with mode: 0644]
arch/sh/kernel/Makefile
arch/sh/kernel/Makefile_32 [deleted file]
arch/sh/kernel/Makefile_64 [deleted file]
arch/sh/kernel/asm-offsets.c
arch/sh/kernel/cpu/Makefile
arch/sh/kernel/cpu/hwblk.c [new file with mode: 0644]
arch/sh/kernel/cpu/init.c
arch/sh/kernel/cpu/irq/ipr.c
arch/sh/kernel/cpu/sh2/entry.S
arch/sh/kernel/cpu/sh2/probe.c
arch/sh/kernel/cpu/sh2a/entry.S
arch/sh/kernel/cpu/sh2a/probe.c
arch/sh/kernel/cpu/sh3/entry.S
arch/sh/kernel/cpu/sh3/ex.S
arch/sh/kernel/cpu/sh3/probe.c
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/cpu/sh4a/Makefile
arch/sh/kernel/cpu/sh4a/clock-sh7722.c
arch/sh/kernel/cpu/sh4a/clock-sh7723.c
arch/sh/kernel/cpu/sh4a/clock-sh7724.c
arch/sh/kernel/cpu/sh4a/clock-sh7757.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/setup-sh7366.c
arch/sh/kernel/cpu/sh4a/setup-sh7722.c
arch/sh/kernel/cpu/sh4a/setup-sh7723.c
arch/sh/kernel/cpu/sh4a/setup-sh7724.c
arch/sh/kernel/cpu/sh4a/setup-sh7757.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/smp-shx3.c
arch/sh/kernel/cpu/sh5/probe.c
arch/sh/kernel/cpu/shmobile/Makefile
arch/sh/kernel/cpu/shmobile/cpuidle.c [new file with mode: 0644]
arch/sh/kernel/cpu/shmobile/pm.c
arch/sh/kernel/cpu/shmobile/pm_runtime.c [new file with mode: 0644]
arch/sh/kernel/cpu/shmobile/sleep.S
arch/sh/kernel/dumpstack.c [new file with mode: 0644]
arch/sh/kernel/dwarf.c [new file with mode: 0644]
arch/sh/kernel/early_printk.c
arch/sh/kernel/entry-common.S
arch/sh/kernel/ftrace.c
arch/sh/kernel/io.c
arch/sh/kernel/io_generic.c
arch/sh/kernel/io_trapped.c
arch/sh/kernel/irq.c
arch/sh/kernel/kgdb.c
arch/sh/kernel/localtimer.c
arch/sh/kernel/nmi_debug.c [new file with mode: 0644]
arch/sh/kernel/process_32.c
arch/sh/kernel/process_64.c
arch/sh/kernel/ptrace_32.c
arch/sh/kernel/setup.c
arch/sh/kernel/sh_ksyms_32.c
arch/sh/kernel/sh_ksyms_64.c
arch/sh/kernel/signal_32.c
arch/sh/kernel/signal_64.c
arch/sh/kernel/stacktrace.c
arch/sh/kernel/sys_sh.c
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/syscalls_64.S
arch/sh/kernel/time.c
arch/sh/kernel/traps.c
arch/sh/kernel/traps_32.c
arch/sh/kernel/unwinder.c [new file with mode: 0644]
arch/sh/kernel/vmlinux.lds.S
arch/sh/lib/Makefile
arch/sh/lib/__clear_user.S [moved from arch/sh/lib/clear_page.S with 75% similarity]
arch/sh/lib/copy_page.S
arch/sh/lib/delay.c
arch/sh/lib/mcount.S
arch/sh/lib64/Makefile
arch/sh/lib64/clear_page.S [deleted file]
arch/sh/mm/Kconfig
arch/sh/mm/Makefile
arch/sh/mm/Makefile_32 [deleted file]
arch/sh/mm/Makefile_64 [deleted file]
arch/sh/mm/cache-sh2.c
arch/sh/mm/cache-sh2a.c
arch/sh/mm/cache-sh3.c
arch/sh/mm/cache-sh4.c
arch/sh/mm/cache-sh5.c
arch/sh/mm/cache-sh7705.c
arch/sh/mm/cache.c [new file with mode: 0644]
arch/sh/mm/fault_32.c
arch/sh/mm/fault_64.c
arch/sh/mm/flush-sh4.c [new file with mode: 0644]
arch/sh/mm/init.c
arch/sh/mm/ioremap_32.c
arch/sh/mm/ioremap_64.c
arch/sh/mm/kmap.c [new file with mode: 0644]
arch/sh/mm/mmap.c
arch/sh/mm/nommu.c [moved from arch/sh/mm/tlb-nommu.c with 54% similarity]
arch/sh/mm/numa.c
arch/sh/mm/pg-nommu.c [deleted file]
arch/sh/mm/pg-sh4.c [deleted file]
arch/sh/mm/pg-sh7705.c [deleted file]
arch/sh/mm/tlb-pteaex.c
arch/sh/mm/tlb-sh3.c
arch/sh/mm/tlb-sh4.c
arch/sh/mm/tlb-sh5.c
arch/sh/mm/tlbflush_64.c
arch/sh/oprofile/backtrace.c
arch/sh/tools/mach-types
arch/sparc/include/asm/device.h
arch/x86/include/asm/device.h
drivers/base/dd.c
drivers/base/platform.c
drivers/base/power/Makefile
drivers/base/power/main.c
drivers/base/power/power.h
drivers/base/power/runtime.c [new file with mode: 0644]
drivers/dma/dw_dmac.c
drivers/dma/txx9dmac.c
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/media/video/sh_mobile_ceu_camera.c
drivers/pci/pci-driver.c
drivers/rtc/rtc-ds1302.c
drivers/rtc/rtc-sh.c
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h
drivers/sh/intc.c
drivers/uio/uio_pdrv_genirq.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/Makefile
drivers/usb/gadget/gadget_chips.h
drivers/usb/gadget/m66592-udc.c
drivers/usb/gadget/m66592-udc.h
drivers/usb/gadget/r8a66597-udc.c [new file with mode: 0644]
drivers/usb/gadget/r8a66597-udc.h [new file with mode: 0644]
drivers/usb/host/Kconfig
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/r8a66597.h
drivers/usb/musb/musb_core.c
drivers/video/Kconfig
drivers/video/sh_mobile_lcdcfb.c
include/asm-generic/device.h
include/linux/device.h
include/linux/platform_device.h
include/linux/pm.h
include/linux/pm_runtime.h [new file with mode: 0644]
include/linux/sh_intc.h
include/linux/usb/m66592.h [new file with mode: 0644]
include/linux/usb/r8a66597.h
kernel/power/Kconfig
kernel/power/main.c

index 7936b80..76c3552 100644 (file)
@@ -1514,7 +1514,7 @@ and is between 256 and 4096 characters. It is defined in the file
                        of returning the full 64-bit number.
                        The default is to return 64-bit inode numbers.
 
-       nmi_debug=      [KNL,AVR32] Specify one or more actions to take
+       nmi_debug=      [KNL,AVR32,SH] Specify one or more actions to take
                        when a NMI is triggered.
                        Format: [state][,regs][,debounce][,die]
 
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
new file mode 100644 (file)
index 0000000..f49a33b
--- /dev/null
@@ -0,0 +1,378 @@
+Run-time Power Management Framework for I/O Devices
+
+(C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+
+1. Introduction
+
+Support for run-time power management (run-time PM) of I/O devices is provided
+at the power management core (PM core) level by means of:
+
+* The power management workqueue pm_wq in which bus types and device drivers can
+  put their PM-related work items.  It is strongly recommended that pm_wq be
+  used for queuing all work items related to run-time PM, because this allows
+  them to be synchronized with system-wide power transitions (suspend to RAM,
+  hibernation and resume from system sleep states).  pm_wq is declared in
+  include/linux/pm_runtime.h and defined in kernel/power/main.c.
+
+* A number of run-time PM fields in the 'power' member of 'struct device' (which
+  is of the type 'struct dev_pm_info', defined in include/linux/pm.h) that can
+  be used for synchronizing run-time PM operations with one another.
+
+* Three device run-time PM callbacks in 'struct dev_pm_ops' (defined in
+  include/linux/pm.h).
+
+* A set of helper functions defined in drivers/base/power/runtime.c that can be
+  used for carrying out run-time PM operations in such a way that the
+  synchronization between them is taken care of by the PM core.  Bus types and
+  device drivers are encouraged to use these functions.
+
+The run-time PM callbacks present in 'struct dev_pm_ops', the device run-time PM
+fields of 'struct dev_pm_info' and the core helper functions provided for
+run-time PM are described below.
+
+2. Device Run-time PM Callbacks
+
+There are three device run-time PM callbacks defined in 'struct dev_pm_ops':
+
+struct dev_pm_ops {
+       ...
+       int (*runtime_suspend)(struct device *dev);
+       int (*runtime_resume)(struct device *dev);
+       void (*runtime_idle)(struct device *dev);
+       ...
+};
+
+The ->runtime_suspend() callback is executed by the PM core for the bus type of
+the device being suspended.  The bus type's callback is then _entirely_
+_responsible_ for handling the device as appropriate, which may, but need not
+include executing the device driver's own ->runtime_suspend() callback (from the
+PM core's point of view it is not necessary to implement a ->runtime_suspend()
+callback in a device driver as long as the bus type's ->runtime_suspend() knows
+what to do to handle the device).
+
+  * Once the bus type's ->runtime_suspend() callback has completed successfully
+    for given device, the PM core regards the device as suspended, which need
+    not mean that the device has been put into a low power state.  It is
+    supposed to mean, however, that the device will not process data and will
+    not communicate with the CPU(s) and RAM until its bus type's
+    ->runtime_resume() callback is executed for it.  The run-time PM status of
+    a device after successful execution of its bus type's ->runtime_suspend()
+    callback is 'suspended'.
+
+  * If the bus type's ->runtime_suspend() callback returns -EBUSY or -EAGAIN,
+    the device's run-time PM status is supposed to be 'active', which means that
+    the device _must_ be fully operational afterwards.
+
+  * If the bus type's ->runtime_suspend() callback returns an error code
+    different from -EBUSY or -EAGAIN, the PM core regards this as a fatal
+    error and will refuse to run the helper functions described in Section 4
+    for the device, until the status of it is directly set either to 'active'
+    or to 'suspended' (the PM core provides special helper functions for this
+    purpose).
+
+In particular, if the driver requires remote wakeup capability for proper
+functioning and device_may_wakeup() returns 'false' for the device, then
+->runtime_suspend() should return -EBUSY.  On the other hand, if
+device_may_wakeup() returns 'true' for the device and the device is put
+into a low power state during the execution of its bus type's
+->runtime_suspend(), it is expected that remote wake-up (i.e. hardware mechanism
+allowing the device to request a change of its power state, such as PCI PME)
+will be enabled for the device.  Generally, remote wake-up should be enabled
+for all input devices put into a low power state at run time.
+
+The ->runtime_resume() callback is executed by the PM core for the bus type of
+the device being woken up.  The bus type's callback is then _entirely_
+_responsible_ for handling the device as appropriate, which may, but need not
+include executing the device driver's own ->runtime_resume() callback (from the
+PM core's point of view it is not necessary to implement a ->runtime_resume()
+callback in a device driver as long as the bus type's ->runtime_resume() knows
+what to do to handle the device).
+
+  * Once the bus type's ->runtime_resume() callback has completed successfully,
+    the PM core regards the device as fully operational, which means that the
+    device _must_ be able to complete I/O operations as needed.  The run-time
+    PM status of the device is then 'active'.
+
+  * If the bus type's ->runtime_resume() callback returns an error code, the PM
+    core regards this as a fatal error and will refuse to run the helper
+    functions described in Section 4 for the device, until its status is
+    directly set either to 'active' or to 'suspended' (the PM core provides
+    special helper functions for this purpose).
+
+The ->runtime_idle() callback is executed by the PM core for the bus type of
+given device whenever the device appears to be idle, which is indicated to the
+PM core by two counters, the device's usage counter and the counter of 'active'
+children of the device.
+
+  * If any of these counters is decreased using a helper function provided by
+    the PM core and it turns out to be equal to zero, the other counter is
+    checked.  If that counter also is equal to zero, the PM core executes the
+    device bus type's ->runtime_idle() callback (with the device as an
+    argument).
+
+The action performed by a bus type's ->runtime_idle() callback is totally
+dependent on the bus type in question, but the expected and recommended action
+is to check if the device can be suspended (i.e. if all of the conditions
+necessary for suspending the device are satisfied) and to queue up a suspend
+request for the device in that case.
+
+The helper functions provided by the PM core, described in Section 4, guarantee
+that the following constraints are met with respect to the bus type's run-time
+PM callbacks:
+
+(1) The callbacks are mutually exclusive (e.g. it is forbidden to execute
+    ->runtime_suspend() in parallel with ->runtime_resume() or with another
+    instance of ->runtime_suspend() for the same device) with the exception that
+    ->runtime_suspend() or ->runtime_resume() can be executed in parallel with
+    ->runtime_idle() (although ->runtime_idle() will not be started while any
+    of the other callbacks is being executed for the same device).
+
+(2) ->runtime_idle() and ->runtime_suspend() can only be executed for 'active'
+    devices (i.e. the PM core will only execute ->runtime_idle() or
+    ->runtime_suspend() for the devices the run-time PM status of which is
+    'active').
+
+(3) ->runtime_idle() and ->runtime_suspend() can only be executed for a device
+    the usage counter of which is equal to zero _and_ either the counter of
+    'active' children of which is equal to zero, or the 'power.ignore_children'
+    flag of which is set.
+
+(4) ->runtime_resume() can only be executed for 'suspended' devices  (i.e. the
+    PM core will only execute ->runtime_resume() for the devices the run-time
+    PM status of which is 'suspended').
+
+Additionally, the helper functions provided by the PM core obey the following
+rules:
+
+  * If ->runtime_suspend() is about to be executed or there's a pending request
+    to execute it, ->runtime_idle() will not be executed for the same device.
+
+  * A request to execute or to schedule the execution of ->runtime_suspend()
+    will cancel any pending requests to execute ->runtime_idle() for the same
+    device.
+
+  * If ->runtime_resume() is about to be executed or there's a pending request
+    to execute it, the other callbacks will not be executed for the same device.
+
+  * A request to execute ->runtime_resume() will cancel any pending or
+    scheduled requests to execute the other callbacks for the same device.
+
+3. Run-time PM Device Fields
+
+The following device run-time PM fields are present in 'struct dev_pm_info', as
+defined in include/linux/pm.h:
+
+  struct timer_list suspend_timer;
+    - timer used for scheduling (delayed) suspend request
+
+  unsigned long timer_expires;
+    - timer expiration time, in jiffies (if this is different from zero, the
+      timer is running and will expire at that time, otherwise the timer is not
+      running)
+
+  struct work_struct work;
+    - work structure used for queuing up requests (i.e. work items in pm_wq)
+
+  wait_queue_head_t wait_queue;
+    - wait queue used if any of the helper functions needs to wait for another
+      one to complete
+
+  spinlock_t lock;
+    - lock used for synchronisation
+
+  atomic_t usage_count;
+    - the usage counter of the device
+
+  atomic_t child_count;
+    - the count of 'active' children of the device
+
+  unsigned int ignore_children;
+    - if set, the value of child_count is ignored (but still updated)
+
+  unsigned int disable_depth;
+    - used for disabling the helper funcions (they work normally if this is
+      equal to zero); the initial value of it is 1 (i.e. run-time PM is
+      initially disabled for all devices)
+
+  unsigned int runtime_error;
+    - if set, there was a fatal error (one of the callbacks returned error code
+      as described in Section 2), so the helper funtions will not work until
+      this flag is cleared; this is the error code returned by the failing
+      callback
+
+  unsigned int idle_notification;
+    - if set, ->runtime_idle() is being executed
+
+  unsigned int request_pending;
+    - if set, there's a pending request (i.e. a work item queued up into pm_wq)
+
+  enum rpm_request request;
+    - type of request that's pending (valid if request_pending is set)
+
+  unsigned int deferred_resume;
+    - set if ->runtime_resume() is about to be run while ->runtime_suspend() is
+      being executed for that device and it is not practical to wait for the
+      suspend to complete; means "start a resume as soon as you've suspended"
+
+  enum rpm_status runtime_status;
+    - the run-time PM status of the device; this field's initial value is
+      RPM_SUSPENDED, which means that each device is initially regarded by the
+      PM core as 'suspended', regardless of its real hardware status
+
+All of the above fields are members of the 'power' member of 'struct device'.
+
+4. Run-time PM Device Helper Functions
+
+The following run-time PM helper functions are defined in
+drivers/base/power/runtime.c and include/linux/pm_runtime.h:
+
+  void pm_runtime_init(struct device *dev);
+    - initialize the device run-time PM fields in 'struct dev_pm_info'
+
+  void pm_runtime_remove(struct device *dev);
+    - make sure that the run-time PM of the device will be disabled after
+      removing the device from device hierarchy
+
+  int pm_runtime_idle(struct device *dev);
+    - execute ->runtime_idle() for the device's bus type; returns 0 on success
+      or error code on failure, where -EINPROGRESS means that ->runtime_idle()
+      is already being executed
+
+  int pm_runtime_suspend(struct device *dev);
+    - execute ->runtime_suspend() for the device's bus type; returns 0 on
+      success, 1 if the device's run-time PM status was already 'suspended', or
+      error code on failure, where -EAGAIN or -EBUSY means it is safe to attempt
+      to suspend the device again in future
+
+  int pm_runtime_resume(struct device *dev);
+    - execute ->runtime_resume() for the device's bus type; returns 0 on
+      success, 1 if the device's run-time PM status was already 'active' or
+      error code on failure, where -EAGAIN means it may be safe to attempt to
+      resume the device again in future, but 'power.runtime_error' should be
+      checked additionally
+
+  int pm_request_idle(struct device *dev);
+    - submit a request to execute ->runtime_idle() for the device's bus type
+      (the request is represented by a work item in pm_wq); returns 0 on success
+      or error code if the request has not been queued up
+
+  int pm_schedule_suspend(struct device *dev, unsigned int delay);
+    - schedule the execution of ->runtime_suspend() for the device's bus type
+      in future, where 'delay' is the time to wait before queuing up a suspend
+      work item in pm_wq, in milliseconds (if 'delay' is zero, the work item is
+      queued up immediately); returns 0 on success, 1 if the device's PM
+      run-time status was already 'suspended', or error code if the request
+      hasn't been scheduled (or queued up if 'delay' is 0); if the execution of
+      ->runtime_suspend() is already scheduled and not yet expired, the new
+      value of 'delay' will be used as the time to wait
+
+  int pm_request_resume(struct device *dev);
+    - submit a request to execute ->runtime_resume() for the device's bus type
+      (the request is represented by a work item in pm_wq); returns 0 on
+      success, 1 if the device's run-time PM status was already 'active', or
+      error code if the request hasn't been queued up
+
+  void pm_runtime_get_noresume(struct device *dev);
+    - increment the device's usage counter
+
+  int pm_runtime_get(struct device *dev);
+    - increment the device's usage counter, run pm_request_resume(dev) and
+      return its result
+
+  int pm_runtime_get_sync(struct device *dev);
+    - increment the device's usage counter, run pm_runtime_resume(dev) and
+      return its result
+
+  void pm_runtime_put_noidle(struct device *dev);
+    - decrement the device's usage counter
+
+  int pm_runtime_put(struct device *dev);
+    - decrement the device's usage counter, run pm_request_idle(dev) and return
+      its result
+
+  int pm_runtime_put_sync(struct device *dev);
+    - decrement the device's usage counter, run pm_runtime_idle(dev) and return
+      its result
+
+  void pm_runtime_enable(struct device *dev);
+    - enable the run-time PM helper functions to run the device bus type's
+      run-time PM callbacks described in Section 2
+
+  int pm_runtime_disable(struct device *dev);
+    - prevent the run-time PM helper functions from running the device bus
+      type's run-time PM callbacks, make sure that all of the pending run-time
+      PM operations on the device are either completed or canceled; returns
+      1 if there was a resume request pending and it was necessary to execute
+      ->runtime_resume() for the device's bus type to satisfy that request,
+      otherwise 0 is returned
+
+  void pm_suspend_ignore_children(struct device *dev, bool enable);
+    - set/unset the power.ignore_children flag of the device
+
+  int pm_runtime_set_active(struct device *dev);
+    - clear the device's 'power.runtime_error' flag, set the device's run-time
+      PM status to 'active' and update its parent's counter of 'active'
+      children as appropriate (it is only valid to use this function if
+      'power.runtime_error' is set or 'power.disable_depth' is greater than
+      zero); it will fail and return error code if the device has a parent
+      which is not active and the 'power.ignore_children' flag of which is unset
+
+  void pm_runtime_set_suspended(struct device *dev);
+    - clear the device's 'power.runtime_error' flag, set the device's run-time
+      PM status to 'suspended' and update its parent's counter of 'active'
+      children as appropriate (it is only valid to use this function if
+      'power.runtime_error' is set or 'power.disable_depth' is greater than
+      zero)
+
+It is safe to execute the following helper functions from interrupt context:
+
+pm_request_idle()
+pm_schedule_suspend()
+pm_request_resume()
+pm_runtime_get_noresume()
+pm_runtime_get()
+pm_runtime_put_noidle()
+pm_runtime_put()
+pm_suspend_ignore_children()
+pm_runtime_set_active()
+pm_runtime_set_suspended()
+pm_runtime_enable()
+
+5. Run-time PM Initialization, Device Probing and Removal
+
+Initially, the run-time PM is disabled for all devices, which means that the
+majority of the run-time PM helper funtions described in Section 4 will return
+-EAGAIN until pm_runtime_enable() is called for the device.
+
+In addition to that, the initial run-time PM status of all devices is
+'suspended', but it need not reflect the actual physical state of the device.
+Thus, if the device is initially active (i.e. it is able to process I/O), its
+run-time PM status must be changed to 'active', with the help of
+pm_runtime_set_active(), before pm_runtime_enable() is called for the device.
+
+However, if the device has a parent and the parent's run-time PM is enabled,
+calling pm_runtime_set_active() for the device will affect the parent, unless
+the parent's 'power.ignore_children' flag is set.  Namely, in that case the
+parent won't be able to suspend at run time, using the PM core's helper
+functions, as long as the child's status is 'active', even if the child's
+run-time PM is still disabled (i.e. pm_runtime_enable() hasn't been called for
+the child yet or pm_runtime_disable() has been called for it).  For this reason,
+once pm_runtime_set_active() has been called for the device, pm_runtime_enable()
+should be called for it too as soon as reasonably possible or its run-time PM
+status should be changed back to 'suspended' with the help of
+pm_runtime_set_suspended().
+
+If the default initial run-time PM status of the device (i.e. 'suspended')
+reflects the actual state of the device, its bus type's or its driver's
+->probe() callback will likely need to wake it up using one of the PM core's
+helper functions described in Section 4.  In that case, pm_runtime_resume()
+should be used.  Of course, for this purpose the device's run-time PM has to be
+enabled earlier by calling pm_runtime_enable().
+
+If the device bus type's or driver's ->probe() or ->remove() callback runs
+pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
+they will fail returning -EAGAIN, because the device's usage counter is
+incremented by the core before executing ->probe() and ->remove().  Still, it
+may be desirable to suspend the device as soon as ->probe() or ->remove() has
+finished, so the PM core uses pm_runtime_idle_sync() to invoke the device bus
+type's ->runtime_idle() callback at that time.
index c61642b..9f390ce 100644 (file)
@@ -12,4 +12,7 @@ struct dev_archdata {
 #endif
 };
 
+struct pdev_archdata {
+};
+
 #endif
index be4eefd..9395898 100644 (file)
@@ -281,24 +281,27 @@ static int /* __init */ fpga_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int fpga_suspend_late(struct platform_device *pdev, pm_message_t mesg)
+static int fpga_suspend_noirq(struct device *dev)
 {
        __raw_writew(~0, &fpga->leds);
        return 0;
 }
 
-static int fpga_resume_early(struct platform_device *pdev)
+static int fpga_resume_noirq(struct device *dev)
 {
        __raw_writew(~hw_led_state, &fpga->leds);
        return 0;
 }
 
+static struct dev_pm_ops fpga_dev_pm_ops = {
+       .suspend_noirq = fpga_suspend_noirq,
+       .resume_noirq = fpga_resume_noirq,
+};
 
 static struct platform_driver led_driver = {
        .driver.name    = "omap_dbg_led",
+       .driver.pm      = &fpga_dev_pm_ops,
        .probe          = fpga_probe,
-       .suspend_late   = fpga_suspend_late,
-       .resume_early   = fpga_resume_early,
 };
 
 static int __init fpga_init(void)
index 9298bc0..50b19a3 100644 (file)
@@ -1315,8 +1315,9 @@ static struct irq_chip mpuio_irq_chip = {
 
 #include <linux/platform_device.h>
 
-static int omap_mpuio_suspend_late(struct platform_device *pdev, pm_message_t mesg)
+static int omap_mpuio_suspend_noirq(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct gpio_bank        *bank = platform_get_drvdata(pdev);
        void __iomem            *mask_reg = bank->base + OMAP_MPUIO_GPIO_MASKIT;
        unsigned long           flags;
@@ -1329,8 +1330,9 @@ static int omap_mpuio_suspend_late(struct platform_device *pdev, pm_message_t me
        return 0;
 }
 
-static int omap_mpuio_resume_early(struct platform_device *pdev)
+static int omap_mpuio_resume_noirq(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct gpio_bank        *bank = platform_get_drvdata(pdev);
        void __iomem            *mask_reg = bank->base + OMAP_MPUIO_GPIO_MASKIT;
        unsigned long           flags;
@@ -1342,14 +1344,18 @@ static int omap_mpuio_resume_early(struct platform_device *pdev)
        return 0;
 }
 
+static struct dev_pm_ops omap_mpuio_dev_pm_ops = {
+       .suspend_noirq = omap_mpuio_suspend_noirq,
+       .resume_noirq = omap_mpuio_resume_noirq,
+};
+
 /* use platform_driver for this, now that there's no longer any
  * point to sys_device (other than not disturbing old code).
  */
 static struct platform_driver omap_mpuio_driver = {
-       .suspend_late   = omap_mpuio_suspend_late,
-       .resume_early   = omap_mpuio_resume_early,
        .driver         = {
                .name   = "mpuio",
+               .pm     = &omap_mpuio_dev_pm_ops,
        },
 };
 
index 41ab85d..d66d446 100644 (file)
@@ -15,4 +15,7 @@ struct dev_archdata {
 #endif
 };
 
+struct pdev_archdata {
+};
+
 #endif /* _ASM_IA64_DEVICE_H */
index c042830..30286db 100644 (file)
@@ -16,6 +16,9 @@ struct dev_archdata {
        struct device_node      *of_node;
 };
 
+struct pdev_archdata {
+};
+
 #endif /* _ASM_MICROBLAZE_DEVICE_H */
 
 
index 7d2277c..e3e06e0 100644 (file)
@@ -30,4 +30,7 @@ dev_archdata_get_node(const struct dev_archdata *ad)
        return ad->of_node;
 }
 
+struct pdev_archdata {
+};
+
 #endif /* _ASM_POWERPC_DEVICE_H */
index e2bdd7b..2f5352c 100644 (file)
@@ -10,12 +10,16 @@ config SUPERH
        select EMBEDDED
        select HAVE_CLK
        select HAVE_IDE
+       select HAVE_LMB
        select HAVE_OPROFILE
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_IOREMAP_PROT if MMU
        select HAVE_ARCH_TRACEHOOK
        select HAVE_DMA_API_DEBUG
        select HAVE_PERF_COUNTERS
+       select HAVE_KERNEL_GZIP
+       select HAVE_KERNEL_BZIP2
+       select HAVE_KERNEL_LZMA
        select RTC_LIB
        select GENERIC_ATOMIC64
        help
@@ -31,6 +35,9 @@ config SUPERH32
        select HAVE_FUNCTION_TRACER
        select HAVE_FTRACE_MCOUNT_RECORD
        select HAVE_DYNAMIC_FTRACE
+       select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+       select HAVE_FTRACE_SYSCALLS
+       select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_ARCH_KGDB
        select ARCH_HIBERNATION_POSSIBLE if MMU
 
@@ -212,6 +219,8 @@ config CPU_SHX3
 config ARCH_SHMOBILE
        bool
        select ARCH_SUSPEND_POSSIBLE
+       select PM
+       select PM_RUNTIME
 
 if SUPERH32
 
@@ -389,6 +398,13 @@ config CPU_SUBTYPE_SH7724
        help
          Select SH7724 if you have an SH-MobileR2R CPU.
 
+config CPU_SUBTYPE_SH7757
+       bool "Support SH7757 processor"
+       select CPU_SH4A
+       select CPU_SHX2
+       help
+         Select SH7757 if you have a SH4A SH7757 CPU.
+
 config CPU_SUBTYPE_SH7763
        bool "Support SH7763 processor"
        select CPU_SH4A
@@ -751,12 +767,31 @@ config UBC_WAKEUP
 
          If unsure, say N.
 
-config CMDLINE_BOOL
-       bool "Default bootloader kernel arguments"
+choice
+       prompt "Kernel command line"
+       optional
+       default CMDLINE_OVERWRITE
+       help
+         Setting this option allows the kernel command line arguments
+         to be set.
+
+config CMDLINE_OVERWRITE
+       bool "Overwrite bootloader kernel arguments"
+       help
+         Given string will overwrite any arguments passed in by
+         a bootloader.
+
+config CMDLINE_EXTEND
+       bool "Extend bootloader kernel arguments"
+       help
+         Given string will be concatenated with arguments passed in
+         by a bootloader.
+
+endchoice
 
 config CMDLINE
-       string "Initial kernel command string"
-       depends on CMDLINE_BOOL
+       string "Kernel command line arguments string"
+       depends on CMDLINE_OVERWRITE || CMDLINE_EXTEND
        default "console=ttySC1,115200"
 
 endmenu
index 39224b5..55907af 100644 (file)
@@ -38,11 +38,13 @@ config EARLY_SCIF_CONSOLE_PORT
        default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \
                                CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 || \
                                CPU_SUBTYPE_SH7343
-       default "0xffea0000" if CPU_SUBTYPE_SH7785
+       default "0xfe4c0000" if CPU_SUBTYPE_SH7757
+       default "0xffeb0000" if CPU_SUBTYPE_SH7785
        default "0xffeb0000" if CPU_SUBTYPE_SH7786
        default "0xfffe8000" if CPU_SUBTYPE_SH7203
        default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263
        default "0xffe80000" if CPU_SH4
+       default "0xa4000150" if CPU_SH3
        default "0x00000000"
 
 config EARLY_PRINTK
@@ -61,12 +63,14 @@ config EARLY_PRINTK
          select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
          the kernel command line option to toggle back and forth.
 
-config DEBUG_STACKOVERFLOW
+config STACK_DEBUG
        bool "Check for stack overflows"
        depends on DEBUG_KERNEL && SUPERH32
        help
          This option will cause messages to be printed if free stack space
-         drops below a certain limit.
+         drops below a certain limit. Saying Y here will add overhead to
+         every function call and will therefore incur a major
+         performance hit. Most users should say N.
 
 config DEBUG_STACK_USAGE
        bool "Stack utilization instrumentation"
@@ -107,6 +111,14 @@ config DUMP_CODE
 
          Those looking for more verbose debugging output should say Y.
 
+config DWARF_UNWINDER
+       bool "Enable the DWARF unwinder for stacktraces"
+       select FRAME_POINTER
+       default n
+       help
+         Enabling this option will make stacktraces more accurate, at
+         the cost of an increase in overall kernel size.
+
 config SH_NO_BSS_INIT
        bool "Avoid zeroing BSS (to speed-up startup on suitable platforms)"
        depends on DEBUG_KERNEL
@@ -123,4 +135,9 @@ config SH64_SR_WATCH
        bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
        depends on SUPERH64
 
+config MCOUNT
+       def_bool y
+       depends on SUPERH32
+       depends on STACK_DEBUG || FUNCTION_TRACER
+
 endmenu
index 75d049b..fc51a91 100644 (file)
@@ -136,6 +136,8 @@ machdir-$(CONFIG_SH_7751_SYSTEMH)           += mach-systemh
 machdir-$(CONFIG_SH_EDOSK7705)                 += mach-edosk7705
 machdir-$(CONFIG_SH_HIGHLANDER)                        += mach-highlander
 machdir-$(CONFIG_SH_MIGOR)                     += mach-migor
+machdir-$(CONFIG_SH_KFR2R09)                   += mach-kfr2r09
+machdir-$(CONFIG_SH_ECOVEC)                    += mach-ecovec24
 machdir-$(CONFIG_SH_SDK7780)                   += mach-sdk7780
 machdir-$(CONFIG_SH_X3PROTO)                   += mach-x3proto
 machdir-$(CONFIG_SH_SH7763RDP)                 += mach-sh7763rdp
@@ -186,17 +188,27 @@ KBUILD_CFLAGS             += -pipe $(cflags-y)
 KBUILD_CPPFLAGS                += $(cflags-y)
 KBUILD_AFLAGS          += $(cflags-y)
 
+ifeq ($(CONFIG_MCOUNT),y)
+  KBUILD_CFLAGS += -pg
+endif
+
+ifeq ($(CONFIG_DWARF_UNWINDER),y)
+  KBUILD_CFLAGS += -fasynchronous-unwind-tables
+endif
+
 libs-$(CONFIG_SUPERH32)                := arch/sh/lib/ $(libs-y)
 libs-$(CONFIG_SUPERH64)                := arch/sh/lib64/ $(libs-y)
 
-PHONY += maketools FORCE
+BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.srec \
+              zImage vmlinux.srec romImage
+PHONY += maketools $(BOOT_TARGETS) FORCE
 
 maketools:  include/linux/version.h FORCE
        $(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h
 
 all: $(KBUILD_IMAGE)
 
-zImage uImage uImage.srec vmlinux.srec: vmlinux
+$(BOOT_TARGETS): vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 compressed: zImage
@@ -208,10 +220,14 @@ archclean:
        $(Q)$(MAKE) $(clean)=arch/sh/kernel/vsyscall
 
 define archhelp
-       @echo '* zImage                    - Compressed kernel image'
+       @echo '  zImage                    - Compressed kernel image'
+       @echo '  romImage                  - Compressed ROM image, if supported'
        @echo '  vmlinux.srec              - Create an ELF S-record'
-       @echo '  uImage                    - Create a bootable image for U-Boot'
-       @echo '  uImage.srec               - Create an S-record for U-Boot'
+       @echo '* uImage                    - Alias to bootable U-Boot image'
+       @echo '  uImage.srec               - Create an S-record for U-Boot'
+       @echo '* uImage.gz                 - Kernel-only image for U-Boot (gzip)'
+       @echo '  uImage.bz2                - Kernel-only image for U-Boot (bzip2)'
+       @echo '  uImage.lzma               - Kernel-only image for U-Boot (lzma)'
 endef
 
 CLEAN_FILES += include/asm-sh/machtypes.h
index 2b1af0e..aedd9de 100644 (file)
@@ -160,7 +160,6 @@ config SH_SH7785LCR
        bool "SH7785LCR"
        depends on CPU_SUBTYPE_SH7785
        select SYS_SUPPORTS_PCI
-       select IO_TRAPPED if MMU
 
 config SH_SH7785LCR_29BIT_PHYSMAPS
        bool "SH7785LCR 29bit physmaps"
@@ -171,6 +170,13 @@ config SH_SH7785LCR_29BIT_PHYSMAPS
          DIP switch(S2-5). If you set the DIP switch for S2-5 = ON,
          you can access all on-board device in 29bit address mode.
 
+config SH_SH7785LCR_PT
+       bool "SH7785LCR prototype board on 32-bit MMU mode"
+       depends on SH_SH7785LCR && 32BIT
+       default n
+       help
+         If you use prototype board, this option is enabled.
+
 config SH_URQUELL
        bool "Urquell"
        depends on CPU_SUBTYPE_SH7786
@@ -193,6 +199,20 @@ config SH_AP325RXA
          Renesas "AP-325RXA" support.
          Compatible with ALGO SYSTEM CO.,LTD. "AP-320A"
 
+config SH_KFR2R09
+       bool "KFR2R09"
+       depends on CPU_SUBTYPE_SH7724
+       select ARCH_REQUIRE_GPIOLIB
+       help
+         "Kit For R2R for 2009" support.
+
+config SH_ECOVEC
+       bool "EcoVec"
+       depends on CPU_SUBTYPE_SH7724
+       select ARCH_REQUIRE_GPIOLIB
+       help
+         Renesas "R0P7724LC0011/21RL (EcoVec)" support.
+
 config SH_SH7763RDP
        bool "SH7763RDP"
        depends on CPU_SUBTYPE_SH7763
index b9c88cc..19eea4a 100644 (file)
@@ -227,6 +227,9 @@ static struct platform_device lcdc_device = {
        .dev            = {
                .platform_data  = &lcdc_info,
        },
+       .archdata = {
+               .hwblk_id = HWBLK_LCDC,
+       },
 };
 
 static void camera_power(int val)
@@ -377,6 +380,9 @@ static struct platform_device ceu_device = {
        .dev            = {
                .platform_data  = &sh_mobile_ceu_info,
        },
+       .archdata = {
+               .hwblk_id = HWBLK_CEU,
+       },
 };
 
 struct spi_gpio_platform_data sdcard_cn3_platform_data = {
index 42410a1..e5a8a2f 100644 (file)
@@ -223,6 +223,19 @@ static struct platform_device sm501_device = {
        .resource       = sm501_resources,
 };
 
+static struct resource i2c_proto_resources[] = {
+       [0] = {
+               .start  = PCA9564_PROTO_32BIT_ADDR,
+               .end    = PCA9564_PROTO_32BIT_ADDR + PCA9564_SIZE - 1,
+               .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
+       },
+       [1] = {
+               .start  = 12,
+               .end    = 12,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
 static struct resource i2c_resources[] = {
        [0] = {
                .start  = PCA9564_ADDR,
@@ -271,6 +284,11 @@ static int __init sh7785lcr_devices_setup(void)
        i2c_register_board_info(0, sh7785lcr_i2c_devices,
                                ARRAY_SIZE(sh7785lcr_i2c_devices));
 
+       if (mach_is_sh7785lcr_pt()) {
+               i2c_device.resource = i2c_proto_resources;
+               i2c_device.num_resources = ARRAY_SIZE(i2c_proto_resources);
+       }
+
        return platform_add_devices(sh7785lcr_devices,
                                    ARRAY_SIZE(sh7785lcr_devices));
 }
diff --git a/arch/sh/boards/mach-ecovec24/Makefile b/arch/sh/boards/mach-ecovec24/Makefile
new file mode 100644 (file)
index 0000000..51f8521
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for the R0P7724LC0011/21RL (EcoVec)
+#
+# 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.
+#
+
+obj-y   := setup.o
\ No newline at end of file
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
new file mode 100644 (file)
index 0000000..428d118
--- /dev/null
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/usb/r8a66597.h>
+#include <video/sh_mobile_lcdc.h>
+#include <media/sh_mobile_ceu.h>
+#include <asm/heartbeat.h>
+#include <asm/sh_eth.h>
+#include <cpu/sh7724.h>
+
+/*
+ *  Address      Interface        BusWidth
+ *-----------------------------------------
+ *  0x0000_0000  uboot            16bit
+ *  0x0004_0000  Linux romImage   16bit
+ *  0x0014_0000  MTD for Linux    16bit
+ *  0x0400_0000  Internal I/O     16/32bit
+ *  0x0800_0000  DRAM             32bit
+ *  0x1800_0000  MFI              16bit
+ */
+
+/* Heartbeat */
+static unsigned char led_pos[] = { 0, 1, 2, 3 };
+static struct heartbeat_data heartbeat_data = {
+       .regsize = 8,
+       .nr_bits = 4,
+       .bit_pos = led_pos,
+};
+
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = 0xA405012C, /* PTG */
+               .end    = 0xA405012E - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .dev = {
+               .platform_data = &heartbeat_data,
+       },
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
+/* MTD */
+static struct mtd_partition nor_flash_partitions[] = {
+       {
+               .name = "boot loader",
+               .offset = 0,
+               .size = (5 * 1024 * 1024),
+               .mask_flags = MTD_CAP_ROM,
+       }, {
+               .name = "free-area",
+               .offset = MTDPART_OFS_APPEND,
+               .size = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct physmap_flash_data nor_flash_data = {
+       .width          = 2,
+       .parts          = nor_flash_partitions,
+       .nr_parts       = ARRAY_SIZE(nor_flash_partitions),
+};
+
+static struct resource nor_flash_resources[] = {
+       [0] = {
+               .name   = "NOR Flash",
+               .start  = 0x00000000,
+               .end    = 0x03ffffff,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device nor_flash_device = {
+       .name           = "physmap-flash",
+       .resource       = nor_flash_resources,
+       .num_resources  = ARRAY_SIZE(nor_flash_resources),
+       .dev            = {
+               .platform_data = &nor_flash_data,
+       },
+};
+
+/* SH Eth */
+#define SH_ETH_ADDR    (0xA4600000)
+#define SH_ETH_MAHR    (SH_ETH_ADDR + 0x1C0)
+#define SH_ETH_MALR    (SH_ETH_ADDR + 0x1C8)
+static struct resource sh_eth_resources[] = {
+       [0] = {
+               .start = SH_ETH_ADDR,
+               .end   = SH_ETH_ADDR + 0x1FC,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = 91,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+struct sh_eth_plat_data sh_eth_plat = {
+       .phy = 0x1f, /* SMSC LAN8700 */
+       .edmac_endian = EDMAC_LITTLE_ENDIAN,
+};
+
+static struct platform_device sh_eth_device = {
+       .name = "sh-eth",
+       .id     = 0,
+       .dev = {
+               .platform_data = &sh_eth_plat,
+       },
+       .num_resources = ARRAY_SIZE(sh_eth_resources),
+       .resource = sh_eth_resources,
+};
+
+/* USB0 host */
+void usb0_port_power(int port, int power)
+{
+       gpio_set_value(GPIO_PTB4, power);
+}
+
+static struct r8a66597_platdata usb0_host_data = {
+       .on_chip = 1,
+       .port_power = usb0_port_power,
+};
+
+static struct resource usb0_host_resources[] = {
+       [0] = {
+               .start  = 0xa4d80000,
+               .end    = 0xa4d80124 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 65,
+               .end    = 65,
+               .flags  = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+       },
+};
+
+static struct platform_device usb0_host_device = {
+       .name           = "r8a66597_hcd",
+       .id             = 0,
+       .dev = {
+               .dma_mask               = NULL,         /*  not use dma */
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &usb0_host_data,
+       },
+       .num_resources  = ARRAY_SIZE(usb0_host_resources),
+       .resource       = usb0_host_resources,
+};
+
+/*
+ * USB1
+ *
+ * CN5 can use both host/function,
+ * and we can determine it by checking PTB[3]
+ *
+ * This time only USB1 host is supported.
+ */
+void usb1_port_power(int port, int power)
+{
+       if (!gpio_get_value(GPIO_PTB3)) {
+               printk(KERN_ERR "USB1 function is not supported\n");
+               return;
+       }
+
+       gpio_set_value(GPIO_PTB5, power);
+}
+
+static struct r8a66597_platdata usb1_host_data = {
+       .on_chip = 1,
+       .port_power = usb1_port_power,
+};
+
+static struct resource usb1_host_resources[] = {
+       [0] = {
+               .start  = 0xa4d90000,
+               .end    = 0xa4d90124 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 66,
+               .end    = 66,
+               .flags  = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+       },
+};
+
+static struct platform_device usb1_host_device = {
+       .name           = "r8a66597_hcd",
+       .id             = 1,
+       .dev = {
+               .dma_mask               = NULL,         /*  not use dma */
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &usb1_host_data,
+       },
+       .num_resources  = ARRAY_SIZE(usb1_host_resources),
+       .resource       = usb1_host_resources,
+};
+
+/* LCDC */
+static struct sh_mobile_lcdc_info lcdc_info = {
+       .ch[0] = {
+               .interface_type = RGB18,
+               .chan = LCDC_CHAN_MAINLCD,
+               .bpp = 16,
+               .lcd_cfg = {
+                       .sync = 0, /* hsync and vsync are active low */
+               },
+               .lcd_size_cfg = { /* 7.0 inch */
+                       .width = 152,
+                       .height = 91,
+               },
+               .board_cfg = {
+               },
+       }
+};
+
+static struct resource lcdc_resources[] = {
+       [0] = {
+               .name   = "LCDC",
+               .start  = 0xfe940000,
+               .end    = 0xfe941fff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 106,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device lcdc_device = {
+       .name           = "sh_mobile_lcdc_fb",
+       .num_resources  = ARRAY_SIZE(lcdc_resources),
+       .resource       = lcdc_resources,
+       .dev            = {
+               .platform_data  = &lcdc_info,
+       },
+       .archdata = {
+               .hwblk_id = HWBLK_LCDC,
+       },
+};
+
+/* CEU0 */
+static struct sh_mobile_ceu_info sh_mobile_ceu0_info = {
+       .flags = SH_CEU_FLAG_USE_8BIT_BUS,
+};
+
+static struct resource ceu0_resources[] = {
+       [0] = {
+               .name   = "CEU0",
+               .start  = 0xfe910000,
+               .end    = 0xfe91009f,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 52,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device ceu0_device = {
+       .name           = "sh_mobile_ceu",
+       .id             = 0, /* "ceu0" clock */
+       .num_resources  = ARRAY_SIZE(ceu0_resources),
+       .resource       = ceu0_resources,
+       .dev    = {
+               .platform_data  = &sh_mobile_ceu0_info,
+       },
+       .archdata = {
+               .hwblk_id = HWBLK_CEU0,
+       },
+};
+
+/* CEU1 */
+static struct sh_mobile_ceu_info sh_mobile_ceu1_info = {
+       .flags = SH_CEU_FLAG_USE_8BIT_BUS,
+};
+
+static struct resource ceu1_resources[] = {
+       [0] = {
+               .name   = "CEU1",
+               .start  = 0xfe914000,
+               .end    = 0xfe91409f,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 63,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device ceu1_device = {
+       .name           = "sh_mobile_ceu",
+       .id             = 1, /* "ceu1" clock */
+       .num_resources  = ARRAY_SIZE(ceu1_resources),
+       .resource       = ceu1_resources,
+       .dev    = {
+               .platform_data  = &sh_mobile_ceu1_info,
+       },
+       .archdata = {
+               .hwblk_id = HWBLK_CEU1,
+       },
+};
+
+static struct platform_device *ecovec_devices[] __initdata = {
+       &heartbeat_device,
+       &nor_flash_device,
+       &sh_eth_device,
+       &usb0_host_device,
+       &usb1_host_device, /* USB1 host support */
+       &lcdc_device,
+       &ceu0_device,
+       &ceu1_device,
+};
+
+#define PORT_HIZA 0xA4050158
+#define IODRIVEA  0xA405018A
+static int __init devices_setup(void)
+{
+       /* enable SCIFA0 */
+       gpio_request(GPIO_FN_SCIF0_TXD, NULL);
+       gpio_request(GPIO_FN_SCIF0_RXD, NULL);
+
+       /* enable debug LED */
+       gpio_request(GPIO_PTG0, NULL);
+       gpio_request(GPIO_PTG1, NULL);
+       gpio_request(GPIO_PTG2, NULL);
+       gpio_request(GPIO_PTG3, NULL);
+       gpio_direction_output(GPIO_PTG0, 0);
+       gpio_direction_output(GPIO_PTG1, 0);
+       gpio_direction_output(GPIO_PTG2, 0);
+       gpio_direction_output(GPIO_PTG3, 0);
+
+       /* enable SH-Eth */
+       gpio_request(GPIO_PTA1, NULL);
+       gpio_direction_output(GPIO_PTA1, 1);
+       mdelay(20);
+
+       gpio_request(GPIO_FN_RMII_RXD0,    NULL);
+       gpio_request(GPIO_FN_RMII_RXD1,    NULL);
+       gpio_request(GPIO_FN_RMII_TXD0,    NULL);
+       gpio_request(GPIO_FN_RMII_TXD1,    NULL);
+       gpio_request(GPIO_FN_RMII_REF_CLK, NULL);
+       gpio_request(GPIO_FN_RMII_TX_EN,   NULL);
+       gpio_request(GPIO_FN_RMII_RX_ER,   NULL);
+       gpio_request(GPIO_FN_RMII_CRS_DV,  NULL);
+       gpio_request(GPIO_FN_MDIO,         NULL);
+       gpio_request(GPIO_FN_MDC,          NULL);
+       gpio_request(GPIO_FN_LNKSTA,       NULL);
+
+       /* enable USB */
+       gpio_request(GPIO_PTB3,  NULL);
+       gpio_request(GPIO_PTB4,  NULL);
+       gpio_request(GPIO_PTB5,  NULL);
+       gpio_direction_input(GPIO_PTB3);
+       gpio_direction_output(GPIO_PTB4, 0);
+       gpio_direction_output(GPIO_PTB5, 0);
+       ctrl_outw(0x0600, 0xa40501d4);
+       ctrl_outw(0x0600, 0xa4050192);
+
+       /* enable LCDC */
+       gpio_request(GPIO_FN_LCDD23,   NULL);
+       gpio_request(GPIO_FN_LCDD22,   NULL);
+       gpio_request(GPIO_FN_LCDD21,   NULL);
+       gpio_request(GPIO_FN_LCDD20,   NULL);
+       gpio_request(GPIO_FN_LCDD19,   NULL);
+       gpio_request(GPIO_FN_LCDD18,   NULL);
+       gpio_request(GPIO_FN_LCDD17,   NULL);
+       gpio_request(GPIO_FN_LCDD16,   NULL);
+       gpio_request(GPIO_FN_LCDD15,   NULL);
+       gpio_request(GPIO_FN_LCDD14,   NULL);
+       gpio_request(GPIO_FN_LCDD13,   NULL);
+       gpio_request(GPIO_FN_LCDD12,   NULL);
+       gpio_request(GPIO_FN_LCDD11,   NULL);
+       gpio_request(GPIO_FN_LCDD10,   NULL);
+       gpio_request(GPIO_FN_LCDD9,    NULL);
+       gpio_request(GPIO_FN_LCDD8,    NULL);
+       gpio_request(GPIO_FN_LCDD7,    NULL);
+       gpio_request(GPIO_FN_LCDD6,    NULL);
+       gpio_request(GPIO_FN_LCDD5,    NULL);
+       gpio_request(GPIO_FN_LCDD4,    NULL);
+       gpio_request(GPIO_FN_LCDD3,    NULL);
+       gpio_request(GPIO_FN_LCDD2,    NULL);
+       gpio_request(GPIO_FN_LCDD1,    NULL);
+       gpio_request(GPIO_FN_LCDD0,    NULL);
+       gpio_request(GPIO_FN_LCDDISP,  NULL);
+       gpio_request(GPIO_FN_LCDHSYN,  NULL);
+       gpio_request(GPIO_FN_LCDDCK,   NULL);
+       gpio_request(GPIO_FN_LCDVSYN,  NULL);
+       gpio_request(GPIO_FN_LCDDON,   NULL);
+       gpio_request(GPIO_FN_LCDLCLK,  NULL);
+       ctrl_outw((ctrl_inw(PORT_HIZA) & ~0x0001), PORT_HIZA);
+
+       gpio_request(GPIO_PTE6, NULL);
+       gpio_request(GPIO_PTU1, NULL);
+       gpio_request(GPIO_PTR1, NULL);
+       gpio_request(GPIO_PTA2, NULL);
+       gpio_direction_input(GPIO_PTE6);
+       gpio_direction_output(GPIO_PTU1, 0);
+       gpio_direction_output(GPIO_PTR1, 0);
+       gpio_direction_output(GPIO_PTA2, 0);
+
+       /* I/O buffer drive ability is low */
+       ctrl_outw((ctrl_inw(IODRIVEA) & ~0x00c0) | 0x0040 , IODRIVEA);
+
+       if (gpio_get_value(GPIO_PTE6)) {
+               /* DVI */
+               lcdc_info.clock_source                  = LCDC_CLK_EXTERNAL;
+               lcdc_info.ch[0].clock_divider           = 1,
+               lcdc_info.ch[0].lcd_cfg.name            = "DVI";
+               lcdc_info.ch[0].lcd_cfg.xres            = 1280;
+               lcdc_info.ch[0].lcd_cfg.yres            = 720;
+               lcdc_info.ch[0].lcd_cfg.left_margin     = 220;
+               lcdc_info.ch[0].lcd_cfg.right_margin    = 110;
+               lcdc_info.ch[0].lcd_cfg.hsync_len       = 40;
+               lcdc_info.ch[0].lcd_cfg.upper_margin    = 20;
+               lcdc_info.ch[0].lcd_cfg.lower_margin    = 5;
+               lcdc_info.ch[0].lcd_cfg.vsync_len       = 5;
+
+               gpio_set_value(GPIO_PTA2, 1);
+               gpio_set_value(GPIO_PTU1, 1);
+       } else {
+               /* Panel */
+
+               lcdc_info.clock_source                  = LCDC_CLK_PERIPHERAL;
+               lcdc_info.ch[0].clock_divider           = 2,
+               lcdc_info.ch[0].lcd_cfg.name            = "Panel";
+               lcdc_info.ch[0].lcd_cfg.xres            = 800;
+               lcdc_info.ch[0].lcd_cfg.yres            = 480;
+               lcdc_info.ch[0].lcd_cfg.left_margin     = 220;
+               lcdc_info.ch[0].lcd_cfg.right_margin    = 110;
+               lcdc_info.ch[0].lcd_cfg.hsync_len       = 70;
+               lcdc_info.ch[0].lcd_cfg.upper_margin    = 20;
+               lcdc_info.ch[0].lcd_cfg.lower_margin    = 5;
+               lcdc_info.ch[0].lcd_cfg.vsync_len       = 5;
+
+               gpio_set_value(GPIO_PTR1, 1);
+
+               /* FIXME
+                *
+                * LCDDON control is needed for Panel,
+                * but current sh_mobile_lcdc driver doesn't control it.
+                * It is temporary correspondence
+                */
+               gpio_request(GPIO_PTF4, NULL);
+               gpio_direction_output(GPIO_PTF4, 1);
+       }
+
+       /* enable CEU0 */
+       gpio_request(GPIO_FN_VIO0_D15, NULL);
+       gpio_request(GPIO_FN_VIO0_D14, NULL);
+       gpio_request(GPIO_FN_VIO0_D13, NULL);
+       gpio_request(GPIO_FN_VIO0_D12, NULL);
+       gpio_request(GPIO_FN_VIO0_D11, NULL);
+       gpio_request(GPIO_FN_VIO0_D10, NULL);
+       gpio_request(GPIO_FN_VIO0_D9,  NULL);
+       gpio_request(GPIO_FN_VIO0_D8,  NULL);
+       gpio_request(GPIO_FN_VIO0_D7,  NULL);
+       gpio_request(GPIO_FN_VIO0_D6,  NULL);
+       gpio_request(GPIO_FN_VIO0_D5,  NULL);
+       gpio_request(GPIO_FN_VIO0_D4,  NULL);
+       gpio_request(GPIO_FN_VIO0_D3,  NULL);
+       gpio_request(GPIO_FN_VIO0_D2,  NULL);
+       gpio_request(GPIO_FN_VIO0_D1,  NULL);
+       gpio_request(GPIO_FN_VIO0_D0,  NULL);
+       gpio_request(GPIO_FN_VIO0_VD,  NULL);
+       gpio_request(GPIO_FN_VIO0_CLK, NULL);
+       gpio_request(GPIO_FN_VIO0_FLD, NULL);
+       gpio_request(GPIO_FN_VIO0_HD,  NULL);
+       platform_resource_setup_memory(&ceu0_device, "ceu0", 4 << 20);
+
+       /* enable CEU1 */
+       gpio_request(GPIO_FN_VIO1_D7,  NULL);
+       gpio_request(GPIO_FN_VIO1_D6,  NULL);
+       gpio_request(GPIO_FN_VIO1_D5,  NULL);
+       gpio_request(GPIO_FN_VIO1_D4,  NULL);
+       gpio_request(GPIO_FN_VIO1_D3,  NULL);
+       gpio_request(GPIO_FN_VIO1_D2,  NULL);
+       gpio_request(GPIO_FN_VIO1_D1,  NULL);
+       gpio_request(GPIO_FN_VIO1_D0,  NULL);
+       gpio_request(GPIO_FN_VIO1_FLD, NULL);
+       gpio_request(GPIO_FN_VIO1_HD,  NULL);
+       gpio_request(GPIO_FN_VIO1_VD,  NULL);
+       gpio_request(GPIO_FN_VIO1_CLK, NULL);
+       platform_resource_setup_memory(&ceu1_device, "ceu1", 4 << 20);
+
+       return platform_add_devices(ecovec_devices,
+                                   ARRAY_SIZE(ecovec_devices));
+}
+device_initcall(devices_setup);
+
+static struct sh_machine_vector mv_ecovec __initmv = {
+       .mv_name        = "R0P7724 (EcoVec)",
+};
index 1639f89..566e69d 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/usb/r8a66597.h>
+#include <linux/usb/m66592.h>
 #include <net/ax88796.h>
 #include <asm/machvec.h>
 #include <mach/highlander.h>
@@ -60,6 +61,11 @@ static struct platform_device r8a66597_usb_host_device = {
        .resource       = r8a66597_usb_host_resources,
 };
 
+static struct m66592_platdata usbf_platdata = {
+       .xtal = M66592_PLATDATA_XTAL_24MHZ,
+       .vif = 1,
+};
+
 static struct resource m66592_usb_peripheral_resources[] = {
        [0] = {
                .name   = "m66592_udc",
@@ -81,6 +87,7 @@ static struct platform_device m66592_usb_peripheral_device = {
        .dev = {
                .dma_mask               = NULL,         /* don't use dma */
                .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &usbf_platdata,
        },
        .num_resources  = ARRAY_SIZE(m66592_usb_peripheral_resources),
        .resource       = m66592_usb_peripheral_resources,
diff --git a/arch/sh/boards/mach-kfr2r09/Makefile b/arch/sh/boards/mach-kfr2r09/Makefile
new file mode 100644 (file)
index 0000000..5d58678
--- /dev/null
@@ -0,0 +1,2 @@
+obj-y   := setup.o
+obj-$(CONFIG_FB_SH_MOBILE_LCDC)        +=  lcd_wqvga.o
diff --git a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
new file mode 100644 (file)
index 0000000..8ccb1cc
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * KFR2R09 LCD panel support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * Register settings based on the out-of-tree t33fb.c driver
+ * Copyright (C) 2008 Lineo Solutions, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <video/sh_mobile_lcdc.h>
+#include <mach/kfr2r09.h>
+#include <cpu/sh7724.h>
+
+/* The on-board LCD module is a Hitachi TX07D34VM0AAA. This module is made
+ * up of a 240x400 LCD hooked up to a R61517 driver IC. The driver IC is
+ * communicating with the main port of the LCDC using an 18-bit SYS interface.
+ *
+ * The device code for this LCD module is 0x01221517.
+ */
+
+static const unsigned char data_frame_if[] = {
+       0x02, /* WEMODE: 1=cont, 0=one-shot */
+       0x00, 0x00,
+       0x00, /* EPF, DFM */
+       0x02, /* RIM[1] : 1 (18bpp) */
+};
+
+static const unsigned char data_panel[] = {
+       0x0b,
+       0x63, /* 400 lines */
+       0x04, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00,
+};
+
+static const unsigned char data_timing[] = {
+       0x00, 0x00, 0x13, 0x08, 0x08,
+};
+
+static const unsigned char data_timing_src[] = {
+       0x11, 0x01, 0x00, 0x01,
+};
+
+static const unsigned char data_gamma[] = {
+       0x01, 0x02, 0x08, 0x23, 0x03, 0x0c, 0x00, 0x06, 0x00, 0x00,
+       0x01, 0x00, 0x0c, 0x23, 0x03, 0x08, 0x02, 0x06, 0x00, 0x00,
+};
+
+static const unsigned char data_power[] = {
+       0x07, 0xc5, 0xdc, 0x02, 0x33, 0x0a,
+};
+
+static unsigned long read_reg(void *sohandle,
+                             struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+       return so->read_data(sohandle);
+}
+
+static void write_reg(void *sohandle,
+                     struct sh_mobile_lcdc_sys_bus_ops *so,
+                     int i, unsigned long v)
+{
+       if (i)
+               so->write_data(sohandle, v); /* PTH4/LCDRS High [param, 17:0] */
+       else
+               so->write_index(sohandle, v); /* PTH4/LCDRS Low [cmd, 7:0] */
+}
+
+static void write_data(void *sohandle,
+                      struct sh_mobile_lcdc_sys_bus_ops *so,
+                      unsigned char const *data, int no_data)
+{
+       int i;
+
+       for (i = 0; i < no_data; i++)
+               write_reg(sohandle, so, 1, data[i]);
+}
+
+static unsigned long read_device_code(void *sohandle,
+                                     struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+       unsigned long device_code;
+
+       /* access protect OFF */
+       write_reg(sohandle, so, 0, 0xb0);
+       write_reg(sohandle, so, 1, 0x00);
+
+       /* deep standby OFF */
+       write_reg(sohandle, so, 0, 0xb1);
+       write_reg(sohandle, so, 1, 0x00);
+
+       /* device code command */
+       write_reg(sohandle, so, 0, 0xbf);
+       mdelay(50);
+
+       /* dummy read */
+       read_reg(sohandle, so);
+
+       /* read device code */
+       device_code = ((read_reg(sohandle, so) & 0xff) << 24);
+       device_code |= ((read_reg(sohandle, so) & 0xff) << 16);
+       device_code |= ((read_reg(sohandle, so) & 0xff) << 8);
+       device_code |= (read_reg(sohandle, so) & 0xff);
+
+       return device_code;
+}
+
+static void write_memory_start(void *sohandle,
+                              struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+       write_reg(sohandle, so, 0, 0x2c);
+}
+
+static void clear_memory(void *sohandle,
+                        struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+       int i;
+
+       /* write start */
+       write_memory_start(sohandle, so);
+
+       /* paint it black */
+       for (i = 0; i < (240 * 400); i++)
+               write_reg(sohandle, so, 1, 0x00);
+}
+
+static void display_on(void *sohandle,
+                      struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+       /* access protect off */
+       write_reg(sohandle, so, 0, 0xb0);
+       write_reg(sohandle, so, 1, 0x00);
+
+       /* exit deep standby mode */
+       write_reg(sohandle, so, 0, 0xb1);
+       write_reg(sohandle, so, 1, 0x00);
+
+       /* frame memory I/F */
+       write_reg(sohandle, so, 0, 0xb3);
+       write_data(sohandle, so, data_frame_if, ARRAY_SIZE(data_frame_if));
+
+       /* display mode and frame memory write mode */
+       write_reg(sohandle, so, 0, 0xb4);
+       write_reg(sohandle, so, 1, 0x00); /* DBI, internal clock */
+
+       /* panel */
+       write_reg(sohandle, so, 0, 0xc0);
+       write_data(sohandle, so, data_panel, ARRAY_SIZE(data_panel));
+
+       /* timing (normal) */
+       write_reg(sohandle, so, 0, 0xc1);
+       write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));
+
+       /* timing (partial) */
+       write_reg(sohandle, so, 0, 0xc2);
+       write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));
+
+       /* timing (idle) */
+       write_reg(sohandle, so, 0, 0xc3);
+       write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));
+
+       /* timing (source/VCOM/gate driving) */
+       write_reg(sohandle, so, 0, 0xc4);
+       write_data(sohandle, so, data_timing_src, ARRAY_SIZE(data_timing_src));
+
+       /* gamma (red) */
+       write_reg(sohandle, so, 0, 0xc8);
+       write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));
+
+       /* gamma (green) */
+       write_reg(sohandle, so, 0, 0xc9);
+       write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));
+
+       /* gamma (blue) */
+       write_reg(sohandle, so, 0, 0xca);
+       write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));
+
+       /* power (common) */
+       write_reg(sohandle, so, 0, 0xd0);
+       write_data(sohandle, so, data_power, ARRAY_SIZE(data_power));
+
+       /* VCOM */
+       write_reg(sohandle, so, 0, 0xd1);
+       write_reg(sohandle, so, 1, 0x00);
+       write_reg(sohandle, so, 1, 0x0f);
+       write_reg(sohandle, so, 1, 0x02);
+
+       /* power (normal) */
+       write_reg(sohandle, so, 0, 0xd2);
+       write_reg(sohandle, so, 1, 0x63);
+       write_reg(sohandle, so, 1, 0x24);
+
+       /* power (partial) */
+       write_reg(sohandle, so, 0, 0xd3);
+       write_reg(sohandle, so, 1, 0x63);
+       write_reg(sohandle, so, 1, 0x24);
+
+       /* power (idle) */
+       write_reg(sohandle, so, 0, 0xd4);
+       write_reg(sohandle, so, 1, 0x63);
+       write_reg(sohandle, so, 1, 0x24);
+
+       write_reg(sohandle, so, 0, 0xd8);
+       write_reg(sohandle, so, 1, 0x77);
+       write_reg(sohandle, so, 1, 0x77);
+
+       /* TE signal */
+       write_reg(sohandle, so, 0, 0x35);
+       write_reg(sohandle, so, 1, 0x00);
+
+       /* TE signal line */
+       write_reg(sohandle, so, 0, 0x44);
+       write_reg(sohandle, so, 1, 0x00);
+       write_reg(sohandle, so, 1, 0x00);
+
+       /* column address */
+       write_reg(sohandle, so, 0, 0x2a);
+       write_reg(sohandle, so, 1, 0x00);
+       write_reg(sohandle, so, 1, 0x00);
+       write_reg(sohandle, so, 1, 0x00);
+       write_reg(sohandle, so, 1, 0xef);
+
+       /* page address */
+       write_reg(sohandle, so, 0, 0x2b);
+       write_reg(sohandle, so, 1, 0x00);
+       write_reg(sohandle, so, 1, 0x00);
+       write_reg(sohandle, so, 1, 0x01);
+       write_reg(sohandle, so, 1, 0x8f);
+
+       /* exit sleep mode */
+       write_reg(sohandle, so, 0, 0x11);
+
+       mdelay(120);
+
+       /* clear vram */
+       clear_memory(sohandle, so);
+
+       /* display ON */
+       write_reg(sohandle, so, 0, 0x29);
+       mdelay(1);
+
+       write_memory_start(sohandle, so);
+}
+
+int kfr2r09_lcd_setup(void *board_data, void *sohandle,
+                     struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+       /* power on */
+       gpio_set_value(GPIO_PTF4, 0);  /* PROTECT/ -> L */
+       gpio_set_value(GPIO_PTE4, 0);  /* LCD_RST/ -> L */
+       gpio_set_value(GPIO_PTF4, 1);  /* PROTECT/ -> H */
+       udelay(1100);
+       gpio_set_value(GPIO_PTE4, 1);  /* LCD_RST/ -> H */
+       udelay(10);
+       gpio_set_value(GPIO_PTF4, 0);  /* PROTECT/ -> L */
+       mdelay(20);
+
+       if (read_device_code(sohandle, so) != 0x01221517)
+               return -ENODEV;
+
+       pr_info("KFR2R09 WQVGA LCD Module detected.\n");
+
+       display_on(sohandle, so);
+       return 0;
+}
+
+#define CTRL_CKSW       0x10
+#define CTRL_C10        0x20
+#define CTRL_CPSW       0x80
+#define MAIN_MLED4      0x40
+#define MAIN_MSW        0x80
+
+static int kfr2r09_lcd_backlight(int on)
+{
+       struct i2c_adapter *a;
+       struct i2c_msg msg;
+       unsigned char buf[2];
+       int ret;
+
+       a = i2c_get_adapter(0);
+       if (!a)
+               return -ENODEV;
+
+       buf[0] = 0x00;
+       if (on)
+               buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW;
+       else
+               buf[1] = 0;
+
+       msg.addr = 0x75;
+       msg.buf = buf;
+       msg.len = 2;
+       msg.flags = 0;
+       ret = i2c_transfer(a, &msg, 1);
+       if (ret != 1)
+               return -ENODEV;
+
+       buf[0] = 0x01;
+       if (on)
+               buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c;
+       else
+               buf[1] = 0;
+
+       msg.addr = 0x75;
+       msg.buf = buf;
+       msg.len = 2;
+       msg.flags = 0;
+       ret = i2c_transfer(a, &msg, 1);
+       if (ret != 1)
+               return -ENODEV;
+
+       return 0;
+}
+
+void kfr2r09_lcd_on(void *board_data)
+{
+       kfr2r09_lcd_backlight(1);
+}
+
+void kfr2r09_lcd_off(void *board_data)
+{
+       kfr2r09_lcd_backlight(0);
+}
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
new file mode 100644 (file)
index 0000000..7155be0
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * KFR2R09 board support code
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/onenand.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/usb/r8a66597.h>
+#include <video/sh_mobile_lcdc.h>
+#include <asm/clock.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/sh_keysc.h>
+#include <cpu/sh7724.h>
+#include <mach/kfr2r09.h>
+
+static struct mtd_partition kfr2r09_nor_flash_partitions[] =
+{
+       {
+               .name = "boot",
+               .offset = 0,
+               .size = (4 * 1024 * 1024),
+               .mask_flags = MTD_WRITEABLE,    /* Read-only */
+       },
+       {
+               .name = "other",
+               .offset = MTDPART_OFS_APPEND,
+               .size = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct physmap_flash_data kfr2r09_nor_flash_data = {
+       .width          = 2,
+       .parts          = kfr2r09_nor_flash_partitions,
+       .nr_parts       = ARRAY_SIZE(kfr2r09_nor_flash_partitions),
+};
+
+static struct resource kfr2r09_nor_flash_resources[] = {
+       [0] = {
+               .name           = "NOR Flash",
+               .start          = 0x00000000,
+               .end            = 0x03ffffff,
+               .flags          = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device kfr2r09_nor_flash_device = {
+       .name           = "physmap-flash",
+       .resource       = kfr2r09_nor_flash_resources,
+       .num_resources  = ARRAY_SIZE(kfr2r09_nor_flash_resources),
+       .dev            = {
+               .platform_data = &kfr2r09_nor_flash_data,
+       },
+};
+
+static struct resource kfr2r09_nand_flash_resources[] = {
+       [0] = {
+               .name           = "NAND Flash",
+               .start          = 0x10000000,
+               .end            = 0x1001ffff,
+               .flags          = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device kfr2r09_nand_flash_device = {
+       .name           = "onenand-flash",
+       .resource       = kfr2r09_nand_flash_resources,
+       .num_resources  = ARRAY_SIZE(kfr2r09_nand_flash_resources),
+};
+
+static struct sh_keysc_info kfr2r09_sh_keysc_info = {
+       .mode = SH_KEYSC_MODE_1, /* KEYOUT0->4, KEYIN0->4 */
+       .scan_timing = 3,
+       .delay = 10,
+       .keycodes = {
+               KEY_PHONE, KEY_CLEAR, KEY_MAIL, KEY_WWW, KEY_ENTER,
+               KEY_1, KEY_2, KEY_3, 0, KEY_UP,
+               KEY_4, KEY_5, KEY_6, 0, KEY_LEFT,
+               KEY_7, KEY_8, KEY_9, KEY_PROG1, KEY_RIGHT,
+               KEY_S, KEY_0, KEY_P, KEY_PROG2, KEY_DOWN,
+               0, 0, 0, 0, 0
+       },
+};
+
+static struct resource kfr2r09_sh_keysc_resources[] = {
+       [0] = {
+               .name   = "KEYSC",
+               .start  = 0x044b0000,
+               .end    = 0x044b000f,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 79,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device kfr2r09_sh_keysc_device = {
+       .name           = "sh_keysc",
+       .id             = 0, /* "keysc0" clock */
+       .num_resources  = ARRAY_SIZE(kfr2r09_sh_keysc_resources),
+       .resource       = kfr2r09_sh_keysc_resources,
+       .dev    = {
+               .platform_data  = &kfr2r09_sh_keysc_info,
+       },
+       .archdata = {
+               .hwblk_id = HWBLK_KEYSC,
+       },
+};
+
+static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
+       .clock_source = LCDC_CLK_BUS,
+       .ch[0] = {
+               .chan = LCDC_CHAN_MAINLCD,
+               .bpp = 16,
+               .interface_type = SYS18,
+               .clock_divider = 6,
+               .flags = LCDC_FLAGS_DWPOL,
+               .lcd_cfg = {
+                       .name = "TX07D34VM0AAA",
+                       .xres = 240,
+                       .yres = 400,
+                       .left_margin = 0,
+                       .right_margin = 16,
+                       .hsync_len = 8,
+                       .upper_margin = 0,
+                       .lower_margin = 1,
+                       .vsync_len = 1,
+                       .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               },
+               .lcd_size_cfg = {
+                       .width = 35,
+                       .height = 58,
+               },
+               .board_cfg = {
+                       .setup_sys = kfr2r09_lcd_setup,
+                       .display_on = kfr2r09_lcd_on,
+                       .display_off = kfr2r09_lcd_off,
+               },
+               .sys_bus_cfg = {
+                       .ldmt2r = 0x07010904,
+                       .ldmt3r = 0x14012914,
+                       /* set 1s delay to encourage fsync() */
+                       .deferred_io_msec = 1000,
+               },
+       }
+};
+
+static struct resource kfr2r09_sh_lcdc_resources[] = {
+       [0] = {
+               .name   = "LCDC",
+               .start  = 0xfe940000, /* P4-only space */
+               .end    = 0xfe941fff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 106,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device kfr2r09_sh_lcdc_device = {
+       .name           = "sh_mobile_lcdc_fb",
+       .num_resources  = ARRAY_SIZE(kfr2r09_sh_lcdc_resources),
+       .resource       = kfr2r09_sh_lcdc_resources,
+       .dev    = {
+               .platform_data  = &kfr2r09_sh_lcdc_info,
+       },
+       .archdata = {
+               .hwblk_id = HWBLK_LCDC,
+       },
+};
+
+static struct r8a66597_platdata kfr2r09_usb0_gadget_data = {
+       .on_chip = 1,
+};
+
+static struct resource kfr2r09_usb0_gadget_resources[] = {
+       [0] = {
+               .start  = 0x04d80000,
+               .end    = 0x04d80123,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 65,
+               .end    = 65,
+               .flags  = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+       },
+};
+
+static struct platform_device kfr2r09_usb0_gadget_device = {
+       .name           = "r8a66597_udc",
+       .id             = 0,
+       .dev = {
+               .dma_mask               = NULL,         /*  not use dma */
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data  = &kfr2r09_usb0_gadget_data,
+       },
+       .num_resources  = ARRAY_SIZE(kfr2r09_usb0_gadget_resources),
+       .resource       = kfr2r09_usb0_gadget_resources,
+};
+
+static struct platform_device *kfr2r09_devices[] __initdata = {
+       &kfr2r09_nor_flash_device,
+       &kfr2r09_nand_flash_device,
+       &kfr2r09_sh_keysc_device,
+       &kfr2r09_sh_lcdc_device,
+};
+
+#define BSC_CS0BCR 0xfec10004
+#define BSC_CS0WCR 0xfec10024
+#define BSC_CS4BCR 0xfec10010
+#define BSC_CS4WCR 0xfec10030
+#define PORT_MSELCRB 0xa4050182
+
+#ifdef CONFIG_I2C
+static int kfr2r09_usb0_gadget_i2c_setup(void)
+{
+       struct i2c_adapter *a;
+       struct i2c_msg msg;
+       unsigned char buf[2];
+       int ret;
+
+       a = i2c_get_adapter(0);
+       if (!a)
+               return -ENODEV;
+
+       /* set bit 1 (the second bit) of chip at 0x09, register 0x13 */
+       buf[0] = 0x13;
+       msg.addr = 0x09;
+       msg.buf = buf;
+       msg.len = 1;
+       msg.flags = 0;
+       ret = i2c_transfer(a, &msg, 1);
+       if (ret != 1)
+               return -ENODEV;
+
+       buf[0] = 0;
+       msg.addr = 0x09;
+       msg.buf = buf;
+       msg.len = 1;
+       msg.flags = I2C_M_RD;
+       ret = i2c_transfer(a, &msg, 1);
+       if (ret != 1)
+               return -ENODEV;
+
+       buf[1] = buf[0] | (1 << 1);
+       buf[0] = 0x13;
+       msg.addr = 0x09;
+       msg.buf = buf;
+       msg.len = 2;
+       msg.flags = 0;
+       ret = i2c_transfer(a, &msg, 1);
+       if (ret != 1)
+               return -ENODEV;
+
+       return 0;
+}
+#else
+static int kfr2r09_usb0_gadget_i2c_setup(void)
+{
+       return -ENODEV;
+}
+#endif
+
+static int kfr2r09_usb0_gadget_setup(void)
+{
+       int plugged_in;
+
+       gpio_request(GPIO_PTN4, NULL); /* USB_DET */
+       gpio_direction_input(GPIO_PTN4);
+       plugged_in = gpio_get_value(GPIO_PTN4);
+       if (!plugged_in)
+               return -ENODEV; /* no cable plugged in */
+
+       if (kfr2r09_usb0_gadget_i2c_setup() != 0)
+               return -ENODEV; /* unable to configure using i2c */
+
+       ctrl_outw((ctrl_inw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB);
+       gpio_request(GPIO_FN_PDSTATUS, NULL); /* R-standby disables USB clock */
+       gpio_request(GPIO_PTV6, NULL); /* USBCLK_ON */
+       gpio_direction_output(GPIO_PTV6, 1); /* USBCLK_ON = H */
+       msleep(20); /* wait 20ms to let the clock settle */
+       clk_enable(clk_get(NULL, "usb0"));
+       ctrl_outw(0x0600, 0xa40501d4);
+
+       return 0;
+}
+
+static int __init kfr2r09_devices_setup(void)
+{
+       /* enable SCIF1 serial port for YC401 console support */
+       gpio_request(GPIO_FN_SCIF1_RXD, NULL);
+       gpio_request(GPIO_FN_SCIF1_TXD, NULL);
+
+       /* setup NOR flash at CS0 */
+       ctrl_outl(0x36db0400, BSC_CS0BCR);
+       ctrl_outl(0x00000500, BSC_CS0WCR);
+
+       /* setup NAND flash at CS4 */
+       ctrl_outl(0x36db0400, BSC_CS4BCR);
+       ctrl_outl(0x00000500, BSC_CS4WCR);
+
+       /* setup KEYSC pins */
+       gpio_request(GPIO_FN_KEYOUT0, NULL);
+       gpio_request(GPIO_FN_KEYOUT1, NULL);
+       gpio_request(GPIO_FN_KEYOUT2, NULL);
+       gpio_request(GPIO_FN_KEYOUT3, NULL);
+       gpio_request(GPIO_FN_KEYOUT4_IN6, NULL);
+       gpio_request(GPIO_FN_KEYIN0, NULL);
+       gpio_request(GPIO_FN_KEYIN1, NULL);
+       gpio_request(GPIO_FN_KEYIN2, NULL);
+       gpio_request(GPIO_FN_KEYIN3, NULL);
+       gpio_request(GPIO_FN_KEYIN4, NULL);
+       gpio_request(GPIO_FN_KEYOUT5_IN5, NULL);
+
+       /* setup LCDC pins for SYS panel */
+       gpio_request(GPIO_FN_LCDD17, NULL);
+       gpio_request(GPIO_FN_LCDD16, NULL);
+       gpio_request(GPIO_FN_LCDD15, NULL);
+       gpio_request(GPIO_FN_LCDD14, NULL);
+       gpio_request(GPIO_FN_LCDD13, NULL);
+       gpio_request(GPIO_FN_LCDD12, NULL);
+       gpio_request(GPIO_FN_LCDD11, NULL);
+       gpio_request(GPIO_FN_LCDD10, NULL);
+       gpio_request(GPIO_FN_LCDD9, NULL);
+       gpio_request(GPIO_FN_LCDD8, NULL);
+       gpio_request(GPIO_FN_LCDD7, NULL);
+       gpio_request(GPIO_FN_LCDD6, NULL);
+       gpio_request(GPIO_FN_LCDD5, NULL);
+       gpio_request(GPIO_FN_LCDD4, NULL);
+       gpio_request(GPIO_FN_LCDD3, NULL);
+       gpio_request(GPIO_FN_LCDD2, NULL);
+       gpio_request(GPIO_FN_LCDD1, NULL);
+       gpio_request(GPIO_FN_LCDD0, NULL);
+       gpio_request(GPIO_FN_LCDRS, NULL); /* LCD_RS */
+       gpio_request(GPIO_FN_LCDCS, NULL); /* LCD_CS/ */
+       gpio_request(GPIO_FN_LCDRD, NULL); /* LCD_RD/ */
+       gpio_request(GPIO_FN_LCDWR, NULL); /* LCD_WR/ */
+       gpio_request(GPIO_FN_LCDVSYN, NULL); /* LCD_VSYNC */
+       gpio_request(GPIO_PTE4, NULL); /* LCD_RST/ */
+       gpio_direction_output(GPIO_PTE4, 1);
+       gpio_request(GPIO_PTF4, NULL); /* PROTECT/ */
+       gpio_direction_output(GPIO_PTF4, 1);
+       gpio_request(GPIO_PTU0, NULL); /* LEDSTDBY/ */
+       gpio_direction_output(GPIO_PTU0, 1);
+
+       /* setup USB function */
+       if (kfr2r09_usb0_gadget_setup() == 0)
+               platform_device_register(&kfr2r09_usb0_gadget_device);
+
+       return platform_add_devices(kfr2r09_devices,
+                                   ARRAY_SIZE(kfr2r09_devices));
+}
+device_initcall(kfr2r09_devices_setup);
+
+/* Return the board specific boot mode pin configuration */
+static int kfr2r09_mode_pins(void)
+{
+       /* MD0=1, MD1=1, MD2=0: Clock Mode 3
+        * MD3=0: 16-bit Area0 Bus Width
+        * MD5=1: Little Endian
+        * MD8=1: Test Mode Disabled
+        */
+       return MODE_PIN0 | MODE_PIN1 | MODE_PIN5 | MODE_PIN8;
+}
+
+/*
+ * The Machine Vector
+ */
+static struct sh_machine_vector mv_kfr2r09 __initmv = {
+       .mv_name                = "kfr2r09",
+       .mv_mode_pins           = kfr2r09_mode_pins,
+};
index f9b2e4d..be8f0d9 100644 (file)
@@ -98,6 +98,9 @@ static struct platform_device sh_keysc_device = {
        .dev    = {
                .platform_data  = &sh_keysc_info,
        },
+       .archdata = {
+               .hwblk_id = HWBLK_KEYSC,
+       },
 };
 
 static struct mtd_partition migor_nor_flash_partitions[] =
@@ -292,6 +295,9 @@ static struct platform_device migor_lcdc_device = {
        .dev    = {
                .platform_data  = &sh_mobile_lcdc_info,
        },
+       .archdata = {
+               .hwblk_id = HWBLK_LCDC,
+       },
 };
 
 static struct clk *camera_clk;
@@ -379,6 +385,9 @@ static struct platform_device migor_ceu_device = {
        .dev    = {
                .platform_data  = &sh_mobile_ceu_info,
        },
+       .archdata = {
+               .hwblk_id = HWBLK_CEU,
+       },
 };
 
 struct spi_gpio_platform_data sdcard_cn9_platform_data = {
index af84904..3637407 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/io.h>
 #include <asm/heartbeat.h>
 #include <asm/sh_keysc.h>
+#include <cpu/sh7722.h>
 
 /* Heartbeat */
 static struct heartbeat_data heartbeat_data = {
@@ -137,6 +138,9 @@ static struct platform_device sh_keysc_device = {
        .dev    = {
                .platform_data  = &sh_keysc_info,
        },
+       .archdata = {
+               .hwblk_id = HWBLK_KEYSC,
+       },
 };
 
 static struct platform_device *se7722_devices[] __initdata = {
index 15456a0..1876c83 100644 (file)
  * SW41 : abxx xxxx  -> a = 0 : Analog  monitor
  *                          1 : Digital monitor
  *                      b = 0 : VGA
- *                          1 : SVGA
+ *                          1 : 720p
+ */
+
+/*
+ * about 720p
+ *
+ * When you use 1280 x 720 lcdc output,
+ * you should change OSC6 lcdc clock from 25.175MHz to 74.25MHz,
+ * and change SW41 to use 720p
  */
 
 /* Heartbeat */
@@ -174,6 +182,9 @@ static struct platform_device lcdc_device = {
        .dev            = {
                .platform_data  = &lcdc_info,
        },
+       .archdata = {
+               .hwblk_id = HWBLK_LCDC,
+       },
 };
 
 /* CEU0 */
@@ -205,6 +216,9 @@ static struct platform_device ceu0_device = {
        .dev    = {
                .platform_data  = &sh_mobile_ceu0_info,
        },
+       .archdata = {
+               .hwblk_id = HWBLK_CEU0,
+       },
 };
 
 /* CEU1 */
@@ -236,6 +250,9 @@ static struct platform_device ceu1_device = {
        .dev    = {
                .platform_data  = &sh_mobile_ceu1_info,
        },
+       .archdata = {
+               .hwblk_id = HWBLK_CEU1,
+       },
 };
 
 /* KEYSC in SoC (Needs SW33-2 set to ON) */
@@ -274,6 +291,9 @@ static struct platform_device keysc_device = {
        .dev    = {
                .platform_data  = &keysc_info,
        },
+       .archdata = {
+               .hwblk_id = HWBLK_KEYSC,
+       },
 };
 
 /* SH Eth */
@@ -302,15 +322,19 @@ static struct platform_device sh_eth_device = {
        },
        .num_resources = ARRAY_SIZE(sh_eth_resources),
        .resource = sh_eth_resources,
+       .archdata = {
+               .hwblk_id = HWBLK_ETHER,
+       },
 };
 
 static struct r8a66597_platdata sh7724_usb0_host_data = {
+       .on_chip = 1,
 };
 
 static struct resource sh7724_usb0_host_resources[] = {
        [0] = {
                .start  = 0xa4d80000,
-               .end    = 0xa4d800ff,
+               .end    = 0xa4d80124 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -330,6 +354,38 @@ static struct platform_device sh7724_usb0_host_device = {
        },
        .num_resources  = ARRAY_SIZE(sh7724_usb0_host_resources),
        .resource       = sh7724_usb0_host_resources,
+       .archdata = {
+               .hwblk_id = HWBLK_USB0,
+       },
+};
+
+static struct r8a66597_platdata sh7724_usb1_gadget_data = {
+       .on_chip = 1,
+};
+
+static struct resource sh7724_usb1_gadget_resources[] = {
+       [0] = {
+               .start  = 0xa4d90000,
+               .end    = 0xa4d90123,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 66,
+               .end    = 66,
+               .flags  = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+       },
+};
+
+static struct platform_device sh7724_usb1_gadget_device = {
+       .name           = "r8a66597_udc",
+       .id             = 1, /* USB1 */
+       .dev = {
+               .dma_mask               = NULL,         /*  not use dma */
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &sh7724_usb1_gadget_data,
+       },
+       .num_resources  = ARRAY_SIZE(sh7724_usb1_gadget_resources),
+       .resource       = sh7724_usb1_gadget_resources,
 };
 
 static struct platform_device *ms7724se_devices[] __initdata = {
@@ -342,6 +398,7 @@ static struct platform_device *ms7724se_devices[] __initdata = {
        &keysc_device,
        &sh_eth_device,
        &sh7724_usb0_host_device,
+       &sh7724_usb1_gadget_device,
 };
 
 #define EEPROM_OP   0xBA206000
@@ -421,9 +478,38 @@ static int __init devices_setup(void)
        /* turn on USB clocks, use external clock */
        ctrl_outw((ctrl_inw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB);
 
+#ifdef CONFIG_PM
+       /* Let LED9 show STATUS2 */
+       gpio_request(GPIO_FN_STATUS2, NULL);
+
+       /* Lit LED10 show STATUS0 */
+       gpio_request(GPIO_FN_STATUS0, NULL);
+
+       /* Lit LED11 show PDSTATUS */
+       gpio_request(GPIO_FN_PDSTATUS, NULL);
+#else
+       /* Lit LED9 */
+       gpio_request(GPIO_PTJ6, NULL);
+       gpio_direction_output(GPIO_PTJ6, 1);
+       gpio_export(GPIO_PTJ6, 0);
+
+       /* Lit LED10 */
+       gpio_request(GPIO_PTJ5, NULL);
+       gpio_direction_output(GPIO_PTJ5, 1);
+       gpio_export(GPIO_PTJ5, 0);
+
+       /* Lit LED11 */
+       gpio_request(GPIO_PTJ7, NULL);
+       gpio_direction_output(GPIO_PTJ7, 1);
+       gpio_export(GPIO_PTJ7, 0);
+#endif
+
        /* enable USB0 port */
        ctrl_outw(0x0600, 0xa40501d4);
 
+       /* enable USB1 port */
+       ctrl_outw(0x0600, 0xa4050192);
+
        /* enable IRQ 0,1,2 */
        gpio_request(GPIO_FN_INTC_IRQ0, NULL);
        gpio_request(GPIO_FN_INTC_IRQ1, NULL);
@@ -546,15 +632,15 @@ static int __init devices_setup(void)
        sh_eth_init();
 
        if (sw & SW41_B) {
-               /* SVGA */
-               lcdc_info.ch[0].lcd_cfg.xres         = 800;
-               lcdc_info.ch[0].lcd_cfg.yres         = 600;
-               lcdc_info.ch[0].lcd_cfg.left_margin  = 142;
-               lcdc_info.ch[0].lcd_cfg.right_margin = 52;
-               lcdc_info.ch[0].lcd_cfg.hsync_len    = 96;
-               lcdc_info.ch[0].lcd_cfg.upper_margin = 24;
-               lcdc_info.ch[0].lcd_cfg.lower_margin = 2;
-               lcdc_info.ch[0].lcd_cfg.vsync_len    = 2;
+               /* 720p */
+               lcdc_info.ch[0].lcd_cfg.xres         = 1280;
+               lcdc_info.ch[0].lcd_cfg.yres         = 720;
+               lcdc_info.ch[0].lcd_cfg.left_margin  = 220;
+               lcdc_info.ch[0].lcd_cfg.right_margin = 110;
+               lcdc_info.ch[0].lcd_cfg.hsync_len    = 40;
+               lcdc_info.ch[0].lcd_cfg.upper_margin = 20;
+               lcdc_info.ch[0].lcd_cfg.lower_margin = 5;
+               lcdc_info.ch[0].lcd_cfg.vsync_len    = 5;
        } else {
                /* VGA */
                lcdc_info.ch[0].lcd_cfg.xres         = 640;
index 8913ae3..efe4cb9 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/usb/r8a66597.h>
+#include <linux/usb/m66592.h>
 #include <asm/ilsel.h>
 
 static struct resource heartbeat_resources[] = {
@@ -89,6 +90,11 @@ static struct platform_device r8a66597_usb_host_device = {
        .resource       = r8a66597_usb_host_resources,
 };
 
+static struct m66592_platdata usbf_platdata = {
+       .xtal = M66592_PLATDATA_XTAL_24MHZ,
+       .vif = 1,
+};
+
 static struct resource m66592_usb_peripheral_resources[] = {
        [0] = {
                .name   = "m66592_udc",
@@ -109,6 +115,7 @@ static struct platform_device m66592_usb_peripheral_device = {
        .dev = {
                .dma_mask               = NULL,         /* don't use dma */
                .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &usbf_platdata,
        },
        .num_resources  = ARRAY_SIZE(m66592_usb_peripheral_resources),
        .resource       = m66592_usb_peripheral_resources,
index aad5edd..541087d 100644 (file)
@@ -1,4 +1,3 @@
 zImage
-vmlinux.srec
-uImage
-uImage.srec
+vmlinux*
+uImage*
index 78efb04..a131687 100644 (file)
@@ -20,8 +20,13 @@ CONFIG_BOOT_LINK_OFFSET      ?= 0x00800000
 CONFIG_ZERO_PAGE_OFFSET        ?= 0x00001000
 CONFIG_ENTRY_OFFSET    ?= 0x00001000
 
-targets := zImage vmlinux.srec uImage uImage.srec
-subdir- := compressed
+suffix-$(CONFIG_KERNEL_GZIP)  := gz
+suffix-$(CONFIG_KERNEL_BZIP2) := bz2
+suffix-$(CONFIG_KERNEL_LZMA)  := lzma
+
+targets := zImage vmlinux.srec romImage uImage uImage.srec uImage.gz uImage.bz2 uImage.lzma
+extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma
+subdir- := compressed romimage
 
 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
        $(call if_changed,objcopy)
@@ -30,6 +35,13 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
 $(obj)/compressed/vmlinux: FORCE
        $(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
+$(obj)/romImage: $(obj)/romimage/vmlinux FORCE
+       $(call if_changed,objcopy)
+       @echo '  Kernel: $@ is ready'
+
+$(obj)/romimage/vmlinux: $(obj)/zImage FORCE
+       $(Q)$(MAKE) $(build)=$(obj)/romimage $@
+
 KERNEL_MEMORY := 0x00000000
 ifeq ($(CONFIG_PMB_FIXED),y)
 KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
@@ -40,9 +52,6 @@ KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
                     $$[$(CONFIG_MEMORY_START)]')
 endif
 
-export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
-       CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY
-
 KERNEL_LOAD    := $(shell /bin/bash -c 'printf "0x%08x" \
                     $$[$(CONFIG_PAGE_OFFSET)  + \
                        $(KERNEL_MEMORY) + \
@@ -55,19 +64,30 @@ KERNEL_ENTRY        := $(shell /bin/bash -c 'printf "0x%08x" \
 
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sh -O linux -T kernel \
-                  -C gzip -a $(KERNEL_LOAD) -e $(KERNEL_ENTRY) \
+                  -C $(2) -a $(KERNEL_LOAD) -e $(KERNEL_ENTRY) \
                   -n 'Linux-$(KERNELRELEASE)' -d $< $@
 
-$(obj)/uImage: $(obj)/vmlinux.bin.gz FORCE
-       $(call if_changed,uimage)
-       @echo '  Image $@ is ready'
-
 $(obj)/vmlinux.bin: vmlinux FORCE
        $(call if_changed,objcopy)
 
 $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
        $(call if_changed,gzip)
 
+$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE
+       $(call if_changed,bzip2)
+
+$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
+       $(call if_changed,lzma)
+
+$(obj)/uImage.bz2: $(obj)/vmlinux.bin.bz2
+       $(call if_changed,uimage,bzip2)
+
+$(obj)/uImage.gz: $(obj)/vmlinux.bin.gz
+       $(call if_changed,uimage,gzip)
+
+$(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma
+       $(call if_changed,uimage,lzma)
+
 OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec
 $(obj)/vmlinux.srec: $(obj)/compressed/vmlinux
        $(call if_changed,objcopy)
@@ -76,5 +96,9 @@ OBJCOPYFLAGS_uImage.srec := -I binary -O srec
 $(obj)/uImage.srec: $(obj)/uImage
        $(call if_changed,objcopy)
 
-clean-files    += uImage uImage.srec vmlinux.srec \
-                  vmlinux.bin vmlinux.bin.gz
+$(obj)/uImage: $(obj)/uImage.$(suffix-y)
+       @ln -sf $(notdir $<) $@
+       @echo '  Image $@ is ready'
+
+export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
+       CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY suffix-y
diff --git a/arch/sh/boot/compressed/.gitignore b/arch/sh/boot/compressed/.gitignore
new file mode 100644 (file)
index 0000000..2374a83
--- /dev/null
@@ -0,0 +1 @@
+vmlinux.bin.*
index 9531bf1..6182eca 100644 (file)
@@ -5,9 +5,10 @@
 #
 
 targets                := vmlinux vmlinux.bin vmlinux.bin.gz \
-                  head_$(BITS).o misc_$(BITS).o piggy.o
+                  vmlinux.bin.bz2 vmlinux.bin.lzma \
+                  head_$(BITS).o misc.o piggy.o
 
-OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc_$(BITS).o $(obj)/cache.o
+OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o
 
 ifdef CONFIG_SH_STANDARD_BIOS
 OBJECTS += $(obj)/../../kernel/sh_bios.o
@@ -23,7 +24,7 @@ IMAGE_OFFSET  := $(shell /bin/bash -c 'printf "0x%08x" \
 
 LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
 
-ifeq ($(CONFIG_FUNCTION_TRACER),y)
+ifeq ($(CONFIG_MCOUNT),y)
 ORIG_CFLAGS := $(KBUILD_CFLAGS)
 KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
@@ -38,10 +39,18 @@ $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
 $(obj)/vmlinux.bin: vmlinux FORCE
        $(call if_changed,objcopy)
 
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+vmlinux.bin.all-y := $(obj)/vmlinux.bin
+
+$(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) FORCE
        $(call if_changed,gzip)
+$(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) FORCE
+       $(call if_changed,bzip2)
+$(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE
+       $(call if_changed,lzma)
 
 OBJCOPYFLAGS += -R .empty_zero_page
 
-$(obj)/piggy.o: $(obj)/piggy.S $(obj)/vmlinux.bin.gz FORCE
-       $(call if_changed,as_o_S)
+LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T
+
+$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) FORCE
+       $(call if_changed,ld)
index 06ac31f..02a3093 100644 (file)
@@ -22,7 +22,7 @@ startup:
        bt      clear_bss
        sub     r0, r2
        mov.l   bss_start_addr, r0
-       mov     #0xe0, r1
+       mov     #0xffffffe0, r1
        and     r1, r0                  ! align cache line
        mov.l   text_start_addr, r3
        mov     r0, r1
diff --git a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c
new file mode 100644 (file)
index 0000000..fd56a71
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * arch/sh/boot/compressed/misc.c
+ *
+ * This is a collection of several routines from gzip-1.0.3
+ * adapted for Linux.
+ *
+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ *
+ * Adapted for SH by Stuart Menefy, Aug 1999
+ *
+ * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
+ */
+
+#include <asm/uaccess.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/sh_bios.h>
+
+/*
+ * gzip declarations
+ */
+
+#define STATIC static
+
+#undef memset
+#undef memcpy
+#define memzero(s, n)     memset ((s), 0, (n))
+
+/* cache.c */
+#define CACHE_ENABLE      0
+#define CACHE_DISABLE     1
+int cache_control(unsigned int command);
+
+extern char input_data[];
+extern int input_len;
+static unsigned char *output;
+
+static void error(char *m);
+
+int puts(const char *);
+
+extern int _text;              /* Defined in vmlinux.lds.S */
+extern int _end;
+static unsigned long free_mem_ptr;
+static unsigned long free_mem_end_ptr;
+
+#ifdef CONFIG_HAVE_KERNEL_BZIP2
+#define HEAP_SIZE      0x400000
+#else
+#define HEAP_SIZE      0x10000
+#endif
+
+#ifdef CONFIG_KERNEL_GZIP
+#include "../../../../lib/decompress_inflate.c"
+#endif
+
+#ifdef CONFIG_KERNEL_BZIP2
+#include "../../../../lib/decompress_bunzip2.c"
+#endif
+
+#ifdef CONFIG_KERNEL_LZMA
+#include "../../../../lib/decompress_unlzma.c"
+#endif
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+size_t strlen(const char *s)
+{
+       int i = 0;
+
+       while (*s++)
+               i++;
+       return i;
+}
+
+int puts(const char *s)
+{
+       int len = strlen(s);
+       sh_bios_console_write(s, len);
+       return len;
+}
+#else
+int puts(const char *s)
+{
+       /* This should be updated to use the sh-sci routines */
+       return 0;
+}
+#endif
+
+void* memset(void* s, int c, size_t n)
+{
+       int i;
+       char *ss = (char*)s;
+
+       for (i=0;i<n;i++) ss[i] = c;
+       return s;
+}
+
+void* memcpy(void* __dest, __const void* __src,
+                           size_t __n)
+{
+       int i;
+       char *d = (char *)__dest, *s = (char *)__src;
+
+       for (i=0;i<__n;i++) d[i] = s[i];
+       return __dest;
+}
+
+static void error(char *x)
+{
+       puts("\n\n");
+       puts(x);
+       puts("\n\n -- System halted");
+
+       while(1);       /* Halt */
+}
+
+#ifdef CONFIG_SUPERH64
+#define stackalign     8
+#else
+#define stackalign     4
+#endif
+
+#define STACK_SIZE (4096)
+long __attribute__ ((aligned(stackalign))) user_stack[STACK_SIZE];
+long *stack_start = &user_stack[STACK_SIZE];
+
+void decompress_kernel(void)
+{
+       unsigned long output_addr;
+
+#ifdef CONFIG_SUPERH64
+       output_addr = (CONFIG_MEMORY_START + 0x2000);
+#else
+       output_addr = PHYSADDR((unsigned long)&_text+PAGE_SIZE);
+#ifdef CONFIG_29BIT
+       output_addr |= P2SEG;
+#endif
+#endif
+
+       output = (unsigned char *)output_addr;
+       free_mem_ptr = (unsigned long)&_end;
+       free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
+
+       puts("Uncompressing Linux... ");
+       cache_control(CACHE_ENABLE);
+       decompress(input_data, input_len, NULL, NULL, output, NULL, error);
+       cache_control(CACHE_DISABLE);
+       puts("Ok, booting the kernel.\n");
+}
diff --git a/arch/sh/boot/compressed/misc_32.c b/arch/sh/boot/compressed/misc_32.c
deleted file mode 100644 (file)
index efdba6b..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * arch/sh/boot/compressed/misc.c
- *
- * This is a collection of several routines from gzip-1.0.3
- * adapted for Linux.
- *
- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
- *
- * Adapted for SH by Stuart Menefy, Aug 1999
- *
- * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
- */
-
-#include <asm/uaccess.h>
-#include <asm/addrspace.h>
-#include <asm/page.h>
-#ifdef CONFIG_SH_STANDARD_BIOS
-#include <asm/sh_bios.h>
-#endif
-
-/*
- * gzip declarations
- */
-
-#define OF(args)  args
-#define STATIC static
-
-#undef memset
-#undef memcpy
-#define memzero(s, n)     memset ((s), 0, (n))
-
-typedef unsigned char  uch;
-typedef unsigned short ush;
-typedef unsigned long  ulg;
-
-#define WSIZE 0x8000           /* Window size must be at least 32k, */
-                               /* and a power of two */
-
-static uch *inbuf;          /* input buffer */
-static uch window[WSIZE];    /* Sliding window buffer */
-
-static unsigned insize = 0;  /* valid bytes in inbuf */
-static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0;  /* bytes in output buffer */
-
-/* gzip flag byte */
-#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
-#define COMMENT      0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
-#define RESERVED     0xC0 /* bit 6,7:   reserved */
-
-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* Diagnostic functions */
-#ifdef DEBUG
-#  define Assert(cond,msg) {if(!(cond)) error(msg);}
-#  define Trace(x) fprintf x
-#  define Tracev(x) {if (verbose) fprintf x ;}
-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-static int  fill_inbuf(void);
-static void flush_window(void);
-static void error(char *m);
-
-extern char input_data[];
-extern int input_len;
-
-static long bytes_out = 0;
-static uch *output_data;
-static unsigned long output_ptr = 0;
-
-static void error(char *m);
-
-int puts(const char *);
-
-extern int _text;              /* Defined in vmlinux.lds.S */
-extern int _end;
-static unsigned long free_mem_ptr;
-static unsigned long free_mem_end_ptr;
-
-#define HEAP_SIZE             0x10000
-
-#include "../../../../lib/inflate.c"
-
-#ifdef CONFIG_SH_STANDARD_BIOS
-size_t strlen(const char *s)
-{
-       int i = 0;
-
-       while (*s++)
-               i++;
-       return i;
-}
-
-int puts(const char *s)
-{
-       int len = strlen(s);
-       sh_bios_console_write(s, len);
-       return len;
-}
-#else
-int puts(const char *s)
-{
-       /* This should be updated to use the sh-sci routines */
-       return 0;
-}
-#endif
-
-void* memset(void* s, int c, size_t n)
-{
-       int i;
-       char *ss = (char*)s;
-
-       for (i=0;i<n;i++) ss[i] = c;
-       return s;
-}
-
-void* memcpy(void* __dest, __const void* __src,
-                           size_t __n)
-{
-       int i;
-       char *d = (char *)__dest, *s = (char *)__src;
-
-       for (i=0;i<__n;i++) d[i] = s[i];
-       return __dest;
-}
-
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-static int fill_inbuf(void)
-{
-       if (insize != 0) {
-               error("ran out of input data");
-       }
-
-       inbuf = input_data;
-       insize = input_len;
-       inptr = 1;
-       return inbuf[0];
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-static void flush_window(void)
-{
-    ulg c = crc;         /* temporary variable */
-    unsigned n;
-    uch *in, *out, ch;
-
-    in = window;
-    out = &output_data[output_ptr];
-    for (n = 0; n < outcnt; n++) {
-           ch = *out++ = *in++;
-           c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
-    }
-    crc = c;
-    bytes_out += (ulg)outcnt;
-    output_ptr += (ulg)outcnt;
-    outcnt = 0;
-}
-
-static void error(char *x)
-{
-       puts("\n\n");
-       puts(x);
-       puts("\n\n -- System halted");
-
-       while(1);       /* Halt */
-}
-
-#define STACK_SIZE (4096)
-long user_stack [STACK_SIZE];
-long* stack_start = &user_stack[STACK_SIZE];
-
-void decompress_kernel(void)
-{
-       output_data = NULL;
-       output_ptr = PHYSADDR((unsigned long)&_text+PAGE_SIZE);
-#ifdef CONFIG_29BIT
-       output_ptr |= P2SEG;
-#endif
-       free_mem_ptr = (unsigned long)&_end;
-       free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
-
-       makecrc();
-       puts("Uncompressing Linux... ");
-       gunzip();
-       puts("Ok, booting the kernel.\n");
-}
diff --git a/arch/sh/boot/compressed/misc_64.c b/arch/sh/boot/compressed/misc_64.c
deleted file mode 100644 (file)
index 2941657..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * arch/sh/boot/compressed/misc_64.c
- *
- * This is a collection of several routines from gzip-1.0.3
- * adapted for Linux.
- *
- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
- *
- * Adapted for SHmedia from sh by Stuart Menefy, May 2002
- */
-
-#include <asm/uaccess.h>
-
-/* cache.c */
-#define CACHE_ENABLE      0
-#define CACHE_DISABLE     1
-int cache_control(unsigned int command);
-
-/*
- * gzip declarations
- */
-
-#define OF(args)  args
-#define STATIC static
-
-#undef memset
-#undef memcpy
-#define memzero(s, n)     memset ((s), 0, (n))
-
-typedef unsigned char uch;
-typedef unsigned short ush;
-typedef unsigned long ulg;
-
-#define WSIZE 0x8000           /* Window size must be at least 32k, */
-                               /* and a power of two */
-
-static uch *inbuf;             /* input buffer */
-static uch window[WSIZE];      /* Sliding window buffer */
-
-static unsigned insize = 0;    /* valid bytes in inbuf */
-static unsigned inptr = 0;     /* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0;    /* bytes in output buffer */
-
-/* gzip flag byte */
-#define ASCII_FLAG   0x01      /* bit 0 set: file probably ASCII text */
-#define CONTINUATION 0x02      /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD  0x04      /* bit 2 set: extra field present */
-#define ORIG_NAME    0x08      /* bit 3 set: original file name present */
-#define COMMENT      0x10      /* bit 4 set: file comment present */
-#define ENCRYPTED    0x20      /* bit 5 set: file is encrypted */
-#define RESERVED     0xC0      /* bit 6,7:   reserved */
-
-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* Diagnostic functions */
-#ifdef DEBUG
-#  define Assert(cond,msg) {if(!(cond)) error(msg);}
-#  define Trace(x) fprintf x
-#  define Tracev(x) {if (verbose) fprintf x ;}
-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-static int fill_inbuf(void);
-static void flush_window(void);
-static void error(char *m);
-
-extern char input_data[];
-extern int input_len;
-
-static long bytes_out = 0;
-static uch *output_data;
-static unsigned long output_ptr = 0;
-
-static void error(char *m);
-
-static void puts(const char *);
-
-extern int _text;              /* Defined in vmlinux.lds.S */
-extern int _end;
-static unsigned long free_mem_ptr;
-static unsigned long free_mem_end_ptr;
-
-#define HEAP_SIZE             0x10000
-
-#include "../../../../lib/inflate.c"
-
-void puts(const char *s)
-{
-}
-
-void *memset(void *s, int c, size_t n)
-{
-       int i;
-       char *ss = (char *) s;
-
-       for (i = 0; i < n; i++)
-               ss[i] = c;
-       return s;
-}
-
-void *memcpy(void *__dest, __const void *__src, size_t __n)
-{
-       int i;
-       char *d = (char *) __dest, *s = (char *) __src;
-
-       for (i = 0; i < __n; i++)
-               d[i] = s[i];
-       return __dest;
-}
-
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-static int fill_inbuf(void)
-{
-       if (insize != 0) {
-               error("ran out of input data\n");
-       }
-
-       inbuf = input_data;
-       insize = input_len;
-       inptr = 1;
-       return inbuf[0];
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-static void flush_window(void)
-{
-       ulg c = crc;            /* temporary variable */
-       unsigned n;
-       uch *in, *out, ch;
-
-       in = window;
-       out = &output_data[output_ptr];
-       for (n = 0; n < outcnt; n++) {
-               ch = *out++ = *in++;
-               c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8);
-       }
-       crc = c;
-       bytes_out += (ulg) outcnt;
-       output_ptr += (ulg) outcnt;
-       outcnt = 0;
-       puts(".");
-}
-
-static void error(char *x)
-{
-       puts("\n\n");
-       puts(x);
-       puts("\n\n -- System halted");
-
-       while (1) ;             /* Halt */
-}
-
-#define STACK_SIZE (4096)
-long __attribute__ ((aligned(8))) user_stack[STACK_SIZE];
-long *stack_start = &user_stack[STACK_SIZE];
-
-void decompress_kernel(void)
-{
-       output_data = (uch *) (CONFIG_MEMORY_START + 0x2000);
-       free_mem_ptr = (unsigned long) &_end;
-       free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
-
-       makecrc();
-       puts("Uncompressing Linux... ");
-       cache_control(CACHE_ENABLE);
-       gunzip();
-       puts("\n");
-
-#if 0
-       /* When booting from ROM may want to do something like this if the
-        * boot loader doesn't.
-        */
-
-       /* Set up the parameters and command line */
-       {
-               volatile unsigned int *parambase =
-                   (int *) (CONFIG_MEMORY_START + 0x1000);
-
-               parambase[0] = 0x1;     /* MOUNT_ROOT_RDONLY */
-               parambase[1] = 0x0;     /* RAMDISK_FLAGS */
-               parambase[2] = 0x0200;  /* ORIG_ROOT_DEV */
-               parambase[3] = 0x0;     /* LOADER_TYPE */
-               parambase[4] = 0x0;     /* INITRD_START */
-               parambase[5] = 0x0;     /* INITRD_SIZE */
-               parambase[6] = 0;
-
-               strcpy((char *) ((int) parambase + 0x100),
-                      "console=ttySC0,38400");
-       }
-#endif
-
-       puts("Ok, booting the kernel.\n");
-
-       cache_control(CACHE_DISABLE);
-}
diff --git a/arch/sh/boot/compressed/piggy.S b/arch/sh/boot/compressed/piggy.S
deleted file mode 100644 (file)
index 5660719..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-       .global input_len, input_data
-       .data
-input_len:
-       .long   input_data_end - input_data
-input_data:
-       .incbin "arch/sh/boot/compressed/vmlinux.bin.gz"
-input_data_end:
-       .end
diff --git a/arch/sh/boot/compressed/vmlinux.scr b/arch/sh/boot/compressed/vmlinux.scr
new file mode 100644 (file)
index 0000000..f02382a
--- /dev/null
@@ -0,0 +1,10 @@
+SECTIONS
+{
+  .rodata.compressed : {
+       input_len = .;
+       LONG(input_data_end - input_data) input_data = .;
+       *(.data)
+       output_len = . - 4;
+       input_data_end = .;
+       }
+}
diff --git a/arch/sh/boot/romimage/Makefile b/arch/sh/boot/romimage/Makefile
new file mode 100644 (file)
index 0000000..5806eee
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# linux/arch/sh/boot/romimage/Makefile
+#
+# create an image suitable for burning to flash from zImage
+#
+
+targets                := vmlinux head.o
+
+OBJECTS = $(obj)/head.o
+LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext 0 -e romstart
+
+$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
+       $(call if_changed,ld)
+       @:
+
+LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T
+
+$(obj)/piggy.o: $(obj)/vmlinux.scr arch/sh/boot/zImage FORCE
+       $(call if_changed,ld)
diff --git a/arch/sh/boot/romimage/head.S b/arch/sh/boot/romimage/head.S
new file mode 100644 (file)
index 0000000..219bc62
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ *  linux/arch/sh/boot/romimage/head.S
+ *
+ * Board specific setup code, executed before zImage loader
+ */
+
+.text
+       .global romstart
+romstart:
+#include <mach/romimage.h>
diff --git a/arch/sh/boot/romimage/vmlinux.scr b/arch/sh/boot/romimage/vmlinux.scr
new file mode 100644 (file)
index 0000000..287c08f
--- /dev/null
@@ -0,0 +1,6 @@
+SECTIONS
+{
+  .text : {
+       *(.data)
+       }
+}
diff --git a/arch/sh/configs/ecovec24_defconfig b/arch/sh/configs/ecovec24_defconfig
new file mode 100644 (file)
index 0000000..2050a76
--- /dev/null
@@ -0,0 +1,1558 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc7
+# Wed Aug 26 09:09:07 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX2=y
+CONFIG_ARCH_SHMOBILE=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+CONFIG_CPU_SUBTYPE_SH7724=y
+# CONFIG_CPU_SUBTYPE_SH7757 is not set
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH7786 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_29BIT=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+
+#
+# Cache configuration
+#
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+# CONFIG_SH_7724_SOLUTION_ENGINE is not set
+# CONFIG_SH_KFR2R09 is not set
+CONFIG_SH_ECOVEC=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TIMER_TMU=y
+# CONFIG_SH_TIMER_CMT is not set
+CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_SECCOMP=y
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=tty0, console=ttySC0,115200 root=/dev/nfs ip=dhcp mem=120M memchunk.vpu=4m"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HIBERNATION is not set
+CONFIG_PM_RUNTIME=y
+# CONFIG_CPU_IDLE is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+CONFIG_MDIO_BITBANG=y
+# CONFIG_MDIO_GPIO is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_STNIC is not set
+CONFIG_SH_ETH=y
+# CONFIG_SMC91X is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+CONFIG_KEYBOARD_SH_KEYSC=y
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_SH_SCI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=y
+CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA9887=y
+CONFIG_MEDIA_TUNER_TEA5761=y
+CONFIG_MEDIA_TUNER_TEA5767=y
+CONFIG_MEDIA_TUNER_MT20XX=y
+CONFIG_MEDIA_TUNER_XC2028=y
+CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_MEDIA_TUNER_MC44S803=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEOBUF_GEN=y
+CONFIG_VIDEOBUF_DMA_CONTIG=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+CONFIG_SOC_CAMERA=y
+# CONFIG_SOC_CAMERA_MT9M001 is not set
+# CONFIG_SOC_CAMERA_MT9M111 is not set
+# CONFIG_SOC_CAMERA_MT9T031 is not set
+# CONFIG_SOC_CAMERA_MT9V022 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+# CONFIG_SOC_CAMERA_PLATFORM is not set
+# CONFIG_SOC_CAMERA_OV772X is not set
+CONFIG_VIDEO_SH_MOBILE_CEU=y
+# CONFIG_V4L_USB_DRIVERS is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=y
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_SH_MOBILE_LCDC=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_SUPERH_MONO is not set
+# CONFIG_LOGO_SUPERH_VGA16 is not set
+CONFIG_LOGO_SUPERH_CLUT224=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+CONFIG_USB_R8A66597_HCD=y
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_SPI=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+CONFIG_RTC_DRV_PCF8563=y
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SH is not set
+# CONFIG_RTC_DRV_GENERIC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_UBIFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FTRACE_SYSCALLS=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_DWARF_UNWINDER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff --git a/arch/sh/configs/kfr2r09-romimage_defconfig b/arch/sh/configs/kfr2r09-romimage_defconfig
new file mode 100644 (file)
index 0000000..c0f9263
--- /dev/null
@@ -0,0 +1,774 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc6
+# Thu Aug 20 15:09:16 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_INITRAMFS_COMPRESSION_NONE is not set
+CONFIG_INITRAMFS_COMPRESSION_GZIP=y
+# CONFIG_INITRAMFS_COMPRESSION_BZIP2 is not set
+# CONFIG_INITRAMFS_COMPRESSION_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+# CONFIG_BLOCK is not set
+# CONFIG_FREEZER is not set
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX2=y
+CONFIG_ARCH_SHMOBILE=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+CONFIG_CPU_SUBTYPE_SH7724=y
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH7786 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_29BIT=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+
+#
+# Cache configuration
+#
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+# CONFIG_SH_7724_SOLUTION_ENGINE is not set
+CONFIG_SH_KFR2R09=y
+# CONFIG_SH_ECOVEC is not set
+
+#
+# Timer and clock configuration
+#
+# CONFIG_SH_TIMER_TMU is not set
+CONFIG_SH_TIMER_CMT=y
+CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_SECCOMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,115200 quiet"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_CPU_IDLE is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+CONFIG_USB_GADGET_R8A66597=y
+CONFIG_USB_R8A66597=y
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+CONFIG_USB_CDC_COMPOSITE=y
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_FILE_LOCKING=y
+# CONFIG_FSNOTIFY is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FTRACE_SYSCALLS=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_DWARF_UNWINDER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff --git a/arch/sh/configs/kfr2r09_defconfig b/arch/sh/configs/kfr2r09_defconfig
new file mode 100644 (file)
index 0000000..cef6131
--- /dev/null
@@ -0,0 +1,1059 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc6
+# Thu Aug 20 21:58:52 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+# CONFIG_FREEZER is not set
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX2=y
+CONFIG_ARCH_SHMOBILE=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+CONFIG_CPU_SUBTYPE_SH7724=y
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH7786 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_29BIT=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+
+#
+# Cache configuration
+#
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+# CONFIG_SH_7724_SOLUTION_ENGINE is not set
+CONFIG_SH_KFR2R09=y
+# CONFIG_SH_ECOVEC is not set
+
+#
+# Timer and clock configuration
+#
+# CONFIG_SH_TIMER_TMU is not set
+CONFIG_SH_TIMER_CMT=y
+CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=tty0 console=ttySC1,115200"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_HIBERNATION is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+CONFIG_KEYBOARD_SH_KEYSC=y
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=y
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_SH_MOBILE_LCDC=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_SUPERH_MONO is not set
+CONFIG_LOGO_SUPERH_VGA16=y
+# CONFIG_LOGO_SUPERH_CLUT224 is not set
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+CONFIG_USB_GADGET_R8A66597=y
+CONFIG_USB_R8A66597=y
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+CONFIG_USB_CDC_COMPOSITE=y
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FTRACE_SYSCALLS=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_DWARF_UNWINDER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
index ca3c88a..2be2d75 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30
-# Thu Jun 18 13:11:58 2009
+# Linux kernel version: 2.6.31-rc6
+# Thu Aug 20 15:03:04 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
@@ -14,6 +14,7 @@ CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
 # CONFIG_GENERIC_GPIO is not set
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
@@ -28,7 +29,9 @@ CONFIG_HAVE_LATENCYTOP_SUPPORT=y
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_ARCH_NO_VIRT_TO_BUS=y
 CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -38,6 +41,12 @@ CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
 # CONFIG_SWAP is not set
 # CONFIG_SYSVIPC is not set
 # CONFIG_POSIX_MQUEUE is not set
@@ -86,10 +95,12 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
 
 #
 # Performance Counters
 #
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 # CONFIG_STRIP_ASM_SYMS is not set
@@ -106,6 +117,10 @@ CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
 CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
@@ -113,7 +128,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -534,7 +549,11 @@ CONFIG_HAVE_IDE=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
@@ -686,6 +705,11 @@ CONFIG_LEGACY_PTY_COUNT=256
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
@@ -732,7 +756,44 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
 CONFIG_RTC_LIB=y
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+CONFIG_RTC_DRV_DS1302=y
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SH is not set
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
@@ -754,6 +815,7 @@ CONFIG_EXT2_FS=y
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
 CONFIG_FILE_LOCKING=y
@@ -856,8 +918,11 @@ CONFIG_FRAME_WARN=1024
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FTRACE_SYSCALLS=y
 CONFIG_TRACING_SUPPORT=y
 # CONFIG_FTRACE is not set
 # CONFIG_DMA_API_DEBUG is not set
@@ -865,6 +930,7 @@ CONFIG_TRACING_SUPPORT=y
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_DWARF_UNWINDER is not set
 
 #
 # Security options
@@ -893,5 +959,6 @@ CONFIG_DECOMPRESS_GZIP=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
 CONFIG_GENERIC_ATOMIC64=y
index 63e9dd3..b91fa8d 100644 (file)
@@ -27,12 +27,12 @@ config NR_ONCHIP_DMA_CHANNELS
        default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R || \
                       CPU_SUBTYPE_SH7760
        default "12" if CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7780  || \
-                       CPU_SUBTYPE_SH7785
+                       CPU_SUBTYPE_SH7785 || CPU_SUBTYPE_SH7724
        default "6"
        help
          This allows you to specify the number of channels that the on-chip
-         DMAC supports. This will be 4 for SH7091/SH7750/SH7751 and 8 for the
-         SH7750R/SH7751R.
+         DMAC supports. This will be 4 for SH7750/SH7751/Sh7750S/SH7091 and 8 for the
+         SH7750R/SH7751R/SH7760, 12 for the SH7723/SH7780/SH7785/SH7724, default is 6.
 
 config NR_DMA_CHANNELS_BOOL
        depends on SH_DMA
index 938817e..a9339a6 100644 (file)
@@ -40,14 +40,19 @@ static inline void heartbeat_toggle_bit(struct heartbeat_data *hd,
        if (inverted)
                new = ~new;
 
+       new &= hd->mask;
+
        switch (hd->regsize) {
        case 32:
+               new |= ioread32(hd->base) & ~hd->mask;
                iowrite32(new, hd->base);
                break;
        case 16:
+               new |= ioread16(hd->base) & ~hd->mask;
                iowrite16(new, hd->base);
                break;
        default:
+               new |= ioread8(hd->base) & ~hd->mask;
                iowrite8(new, hd->base);
                break;
        }
@@ -72,6 +77,7 @@ static int heartbeat_drv_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct heartbeat_data *hd;
+       int i;
 
        if (unlikely(pdev->num_resources != 1)) {
                dev_err(&pdev->dev, "invalid number of resources\n");
@@ -107,6 +113,10 @@ static int heartbeat_drv_probe(struct platform_device *pdev)
                hd->nr_bits = ARRAY_SIZE(default_bit_pos);
        }
 
+       hd->mask = 0;
+       for (i = 0; i < hd->nr_bits; i++)
+               hd->mask |= (1 << hd->bit_pos[i]);
+
        if (!hd->regsize)
                hd->regsize = 8;        /* default access size */
 
index 9a1c423..c481df6 100644 (file)
@@ -295,6 +295,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                               vma->vm_page_prot);
 }
 
+#ifndef CONFIG_GENERIC_IOMAP
+
 static void __iomem *ioport_map_pci(struct pci_dev *dev,
                                    unsigned long port, unsigned int nr)
 {
@@ -346,6 +348,8 @@ void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
 }
 EXPORT_SYMBOL(pci_iounmap);
 
+#endif /* CONFIG_GENERIC_IOMAP */
+
 #ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(pcibios_resource_to_bus);
 EXPORT_SYMBOL(pcibios_bus_to_resource);
index 43910cd..e121c30 100644 (file)
@@ -1,6 +1,6 @@
 include include/asm-generic/Kbuild.asm
 
-header-y += cpu-features.h
+header-y += cachectl.h cpu-features.h
 
 unifdef-y += unistd_32.h
 unifdef-y += unistd_64.h
index c017180..d02c01b 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_SH_BUG_H
 
 #define TRAPA_BUG_OPCODE       0xc33e  /* trapa #0x3e */
+#define BUGFLAG_UNWINDER       (1 << 1)
 
 #ifdef CONFIG_GENERIC_BUG
 #define HAVE_ARCH_BUG
@@ -72,6 +73,36 @@ do {                                                 \
        unlikely(__ret_warn_on);                                \
 })
 
+#define UNWINDER_BUG()                                 \
+do {                                                   \
+       __asm__ __volatile__ (                          \
+               "1:\t.short %O0\n"                      \
+               _EMIT_BUG_ENTRY                         \
+                :                                      \
+                : "n" (TRAPA_BUG_OPCODE),              \
+                  "i" (__FILE__),                      \
+                  "i" (__LINE__),                      \
+                  "i" (BUGFLAG_UNWINDER),              \
+                  "i" (sizeof(struct bug_entry)));     \
+} while (0)
+
+#define UNWINDER_BUG_ON(x) ({                                  \
+       int __ret_unwinder_on = !!(x);                          \
+       if (__builtin_constant_p(__ret_unwinder_on)) {          \
+               if (__ret_unwinder_on)                          \
+                       UNWINDER_BUG();                         \
+       } else {                                                \
+               if (unlikely(__ret_unwinder_on))                \
+                       UNWINDER_BUG();                         \
+       }                                                       \
+       unlikely(__ret_unwinder_on);                            \
+})
+
+#else
+
+#define UNWINDER_BUG   BUG
+#define UNWINDER_BUG_ON        BUG_ON
+
 #endif /* CONFIG_GENERIC_BUG */
 
 #include <asm-generic/bug.h>
index 4924ff6..46260fc 100644 (file)
@@ -21,25 +21,25 @@ static void __init check_bugs(void)
 
        current_cpu_data.loops_per_jiffy = loops_per_jiffy;
 
-       switch (current_cpu_data.type) {
-       case CPU_SH7619:
+       switch (current_cpu_data.family) {
+       case CPU_FAMILY_SH2:
                *p++ = '2';
                break;
-       case CPU_SH7201 ... CPU_MXG:
+       case CPU_FAMILY_SH2A:
                *p++ = '2';
                *p++ = 'a';
                break;
-       case CPU_SH7705 ... CPU_SH7729:
+       case CPU_FAMILY_SH3:
                *p++ = '3';
                break;
-       case CPU_SH7750 ... CPU_SH4_501:
+       case CPU_FAMILY_SH4:
                *p++ = '4';
                break;
-       case CPU_SH7763 ... CPU_SHX3:
+       case CPU_FAMILY_SH4A:
                *p++ = '4';
                *p++ = 'a';
                break;
-       case CPU_SH7343 ... CPU_SH7366:
+       case CPU_FAMILY_SH4AL_DSP:
                *p++ = '4';
                *p++ = 'a';
                *p++ = 'l';
@@ -48,15 +48,15 @@ static void __init check_bugs(void)
                *p++ = 's';
                *p++ = 'p';
                break;
-       case CPU_SH5_101 ... CPU_SH5_103:
+       case CPU_FAMILY_SH5:
                *p++ = '6';
                *p++ = '4';
                break;
-       case CPU_SH_NONE:
+       case CPU_FAMILY_UNKNOWN:
                /*
-                * Specifically use CPU_SH_NONE rather than default:,
-                * so we're able to have the compiler whine about
-                * unhandled enumerations.
+                * Specifically use CPU_FAMILY_UNKNOWN rather than
+                * default:, so we're able to have the compiler whine
+                * about unhandled enumerations.
                 */
                break;
        }
diff --git a/arch/sh/include/asm/cachectl.h b/arch/sh/include/asm/cachectl.h
new file mode 100644 (file)
index 0000000..6ffb4b7
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _SH_CACHECTL_H
+#define _SH_CACHECTL_H
+
+/* Definitions for the cacheflush system call.  */
+
+#define CACHEFLUSH_D_INVAL     0x1     /* invalidate (without write back) */
+#define CACHEFLUSH_D_WB                0x2     /* write back (without invalidate) */
+#define CACHEFLUSH_D_PURGE     0x3     /* writeback and invalidate */
+
+#define CACHEFLUSH_I           0x4
+
+/*
+ * Options for cacheflush system call
+ */
+#define ICACHE CACHEFLUSH_I            /* flush instruction cache */
+#define DCACHE CACHEFLUSH_D_PURGE      /* writeback and flush data cache */
+#define BCACHE (ICACHE|DCACHE)         /* flush both caches */
+
+#endif /* _SH_CACHECTL_H */
index 4c5462d..c29918f 100644 (file)
@@ -3,45 +3,65 @@
 
 #ifdef __KERNEL__
 
-#ifdef CONFIG_CACHE_OFF
+#include <linux/mm.h>
+
 /*
- * Nothing to do when the cache is disabled, initial flush and explicit
- * disabling is handled at CPU init time.
+ * Cache flushing:
+ *
+ *  - flush_cache_all() flushes entire cache
+ *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_dup mm(mm) handles cache flushing when forking
+ *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
+ *  - flush_cache_range(vma, start, end) flushes a range of pages
  *
- * See arch/sh/kernel/cpu/init.c:cache_init().
+ *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
+ *  - flush_icache_range(start, end) flushes(invalidates) a range for icache
+ *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
+ *  - flush_cache_sigtramp(vaddr) flushes the signal trampoline
  */
-#define p3_cache_init()                                do { } while (0)
-#define flush_cache_all()                      do { } while (0)
-#define flush_cache_mm(mm)                     do { } while (0)
-#define flush_cache_dup_mm(mm)                 do { } while (0)
-#define flush_cache_range(vma, start, end)     do { } while (0)
-#define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
-#define flush_dcache_page(page)                        do { } while (0)
-#define flush_icache_range(start, end)         do { } while (0)
-#define flush_icache_page(vma,pg)              do { } while (0)
-#define flush_dcache_mmap_lock(mapping)                do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
-#define flush_cache_sigtramp(vaddr)            do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
-#define __flush_wback_region(start, size)      do { (void)(start); } while (0)
-#define __flush_purge_region(start, size)      do { (void)(start); } while (0)
-#define __flush_invalidate_region(start, size) do { (void)(start); } while (0)
-#else
-#include <cpu/cacheflush.h>
+extern void (*local_flush_cache_all)(void *args);
+extern void (*local_flush_cache_mm)(void *args);
+extern void (*local_flush_cache_dup_mm)(void *args);
+extern void (*local_flush_cache_page)(void *args);
+extern void (*local_flush_cache_range)(void *args);
+extern void (*local_flush_dcache_page)(void *args);
+extern void (*local_flush_icache_range)(void *args);
+extern void (*local_flush_icache_page)(void *args);
+extern void (*local_flush_cache_sigtramp)(void *args);
 
-/*
- * Consistent DMA requires that the __flush_xxx() primitives must be set
- * for any of the enabled non-coherent caches (most of the UP CPUs),
- * regardless of PIPT or VIPT cache configurations.
- */
+static inline void cache_noop(void *args) { }
+
+extern void (*__flush_wback_region)(void *start, int size);
+extern void (*__flush_purge_region)(void *start, int size);
+extern void (*__flush_invalidate_region)(void *start, int size);
+
+extern void flush_cache_all(void);
+extern void flush_cache_mm(struct mm_struct *mm);
+extern void flush_cache_dup_mm(struct mm_struct *mm);
+extern void flush_cache_page(struct vm_area_struct *vma,
+                               unsigned long addr, unsigned long pfn);
+extern void flush_cache_range(struct vm_area_struct *vma,
+                                unsigned long start, unsigned long end);
+extern void flush_dcache_page(struct page *page);
+extern void flush_icache_range(unsigned long start, unsigned long end);
+extern void flush_icache_page(struct vm_area_struct *vma,
+                                struct page *page);
+extern void flush_cache_sigtramp(unsigned long address);
+
+struct flusher_data {
+       struct vm_area_struct *vma;
+       unsigned long addr1, addr2;
+};
 
-/* Flush (write-back only) a region (smaller than a page) */
-extern void __flush_wback_region(void *start, int size);
-/* Flush (write-back & invalidate) a region (smaller than a page) */
-extern void __flush_purge_region(void *start, int size);
-/* Flush (invalidate only) a region (smaller than a page) */
-extern void __flush_invalidate_region(void *start, int size);
-#endif
+#define ARCH_HAS_FLUSH_ANON_PAGE
+extern void __flush_anon_page(struct page *page, unsigned long);
+
+static inline void flush_anon_page(struct vm_area_struct *vma,
+                                  struct page *page, unsigned long vmaddr)
+{
+       if (boot_cpu_data.dcache.n_aliases && PageAnon(page))
+               __flush_anon_page(page, vmaddr);
+}
 
 #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
 static inline void flush_kernel_dcache_page(struct page *page)
@@ -49,7 +69,6 @@ static inline void flush_kernel_dcache_page(struct page *page)
        flush_dcache_page(page);
 }
 
-#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_CACHE_OFF)
 extern void copy_to_user_page(struct vm_area_struct *vma,
        struct page *page, unsigned long vaddr, void *dst, const void *src,
        unsigned long len);
@@ -57,23 +76,20 @@ extern void copy_to_user_page(struct vm_area_struct *vma,
 extern void copy_from_user_page(struct vm_area_struct *vma,
        struct page *page, unsigned long vaddr, void *dst, const void *src,
        unsigned long len);
-#else
-#define copy_to_user_page(vma, page, vaddr, dst, src, len)     \
-       do {                                                    \
-               flush_cache_page(vma, vaddr, page_to_pfn(page));\
-               memcpy(dst, src, len);                          \
-               flush_icache_user_range(vma, page, vaddr, len); \
-       } while (0)
-
-#define copy_from_user_page(vma, page, vaddr, dst, src, len)   \
-       do {                                                    \
-               flush_cache_page(vma, vaddr, page_to_pfn(page));\
-               memcpy(dst, src, len);                          \
-       } while (0)
-#endif
 
 #define flush_cache_vmap(start, end)           flush_cache_all()
 #define flush_cache_vunmap(start, end)         flush_cache_all()
 
+#define flush_dcache_mmap_lock(mapping)                do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
+
+void kmap_coherent_init(void);
+void *kmap_coherent(struct page *page, unsigned long addr);
+void kunmap_coherent(void *kvaddr);
+
+#define PG_dcache_dirty        PG_arch_1
+
+void cpu_cache_init(void);
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHEFLUSH_H */
index 8688a88..b16debf 100644 (file)
@@ -3,7 +3,9 @@
  *
  * This file is released under the GPLv2
  */
-#include <asm-generic/device.h>
+
+struct dev_archdata {
+};
 
 struct platform_device;
 /* allocate contiguous memory chunk and fill in struct resource */
@@ -12,3 +14,15 @@ int platform_resource_setup_memory(struct platform_device *pdev,
 
 void plat_early_device_setup(void);
 
+#define PDEV_ARCHDATA_FLAG_INIT 0
+#define PDEV_ARCHDATA_FLAG_IDLE 1
+#define PDEV_ARCHDATA_FLAG_SUSP 2
+
+struct pdev_archdata {
+       int hwblk_id;
+#ifdef CONFIG_PM_RUNTIME
+       unsigned long flags;
+       struct list_head entry;
+       struct mutex mutex;
+#endif
+};
index 0c8f8e1..68a5f4c 100644 (file)
@@ -16,6 +16,7 @@
 
 /* DMAOR contorl: The DMAOR access size is different by CPU.*/
 #if defined(CONFIG_CPU_SUBTYPE_SH7723) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7724) || \
     defined(CONFIG_CPU_SUBTYPE_SH7780) || \
     defined(CONFIG_CPU_SUBTYPE_SH7785)
 #define dmaor_read_reg(n) \
diff --git a/arch/sh/include/asm/dwarf.h b/arch/sh/include/asm/dwarf.h
new file mode 100644 (file)
index 0000000..ced6795
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2009 Matt Fleming <matt@console-pimps.org>
+ *
+ * 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.
+ *
+ */
+#ifndef __ASM_SH_DWARF_H
+#define __ASM_SH_DWARF_H
+
+#ifdef CONFIG_DWARF_UNWINDER
+
+/*
+ * DWARF expression operations
+ */
+#define DW_OP_addr     0x03
+#define DW_OP_deref    0x06
+#define DW_OP_const1u  0x08
+#define DW_OP_const1s  0x09
+#define DW_OP_const2u  0x0a
+#define DW_OP_const2s  0x0b
+#define DW_OP_const4u  0x0c
+#define DW_OP_const4s  0x0d
+#define DW_OP_const8u  0x0e
+#define DW_OP_const8s  0x0f
+#define DW_OP_constu   0x10
+#define DW_OP_consts   0x11
+#define DW_OP_dup      0x12
+#define DW_OP_drop     0x13
+#define DW_OP_over     0x14
+#define DW_OP_pick     0x15
+#define DW_OP_swap     0x16
+#define DW_OP_rot      0x17
+#define DW_OP_xderef   0x18
+#define DW_OP_abs      0x19
+#define DW_OP_and      0x1a
+#define DW_OP_div      0x1b
+#define DW_OP_minus    0x1c
+#define DW_OP_mod      0x1d
+#define DW_OP_mul      0x1e
+#define DW_OP_neg      0x1f
+#define DW_OP_not      0x20
+#define DW_OP_or       0x21
+#define DW_OP_plus     0x22
+#define DW_OP_plus_uconst      0x23
+#define DW_OP_shl      0x24
+#define DW_OP_shr      0x25
+#define DW_OP_shra     0x26
+#define DW_OP_xor      0x27
+#define DW_OP_skip     0x2f
+#define DW_OP_bra      0x28
+#define DW_OP_eq       0x29
+#define DW_OP_ge       0x2a
+#define DW_OP_gt       0x2b
+#define DW_OP_le       0x2c
+#define DW_OP_lt       0x2d
+#define DW_OP_ne       0x2e
+#define DW_OP_lit0     0x30
+#define DW_OP_lit1     0x31
+#define DW_OP_lit2     0x32
+#define DW_OP_lit3     0x33
+#define DW_OP_lit4     0x34
+#define DW_OP_lit5     0x35
+#define DW_OP_lit6     0x36
+#define DW_OP_lit7     0x37
+#define DW_OP_lit8     0x38
+#define DW_OP_lit9     0x39
+#define DW_OP_lit10    0x3a
+#define DW_OP_lit11    0x3b
+#define DW_OP_lit12    0x3c
+#define DW_OP_lit13    0x3d
+#define DW_OP_lit14    0x3e
+#define DW_OP_lit15    0x3f
+#define DW_OP_lit16    0x40
+#define DW_OP_lit17    0x41
+#define DW_OP_lit18    0x42
+#define DW_OP_lit19    0x43
+#define DW_OP_lit20    0x44
+#define DW_OP_lit21    0x45
+#define DW_OP_lit22    0x46
+#define DW_OP_lit23    0x47
+#define DW_OP_lit24    0x48
+#define DW_OP_lit25    0x49
+#define DW_OP_lit26    0x4a
+#define DW_OP_lit27    0x4b
+#define DW_OP_lit28    0x4c
+#define DW_OP_lit29    0x4d
+#define DW_OP_lit30    0x4e
+#define DW_OP_lit31    0x4f
+#define DW_OP_reg0     0x50
+#define DW_OP_reg1     0x51
+#define DW_OP_reg2     0x52
+#define DW_OP_reg3     0x53
+#define DW_OP_reg4     0x54
+#define DW_OP_reg5     0x55
+#define DW_OP_reg6     0x56
+#define DW_OP_reg7     0x57
+#define DW_OP_reg8     0x58
+#define DW_OP_reg9     0x59
+#define DW_OP_reg10    0x5a
+#define DW_OP_reg11    0x5b
+#define DW_OP_reg12    0x5c
+#define DW_OP_reg13    0x5d
+#define DW_OP_reg14    0x5e
+#define DW_OP_reg15    0x5f
+#define DW_OP_reg16    0x60
+#define DW_OP_reg17    0x61
+#define DW_OP_reg18    0x62
+#define DW_OP_reg19    0x63
+#define DW_OP_reg20    0x64
+#define DW_OP_reg21    0x65
+#define DW_OP_reg22    0x66
+#define DW_OP_reg23    0x67
+#define DW_OP_reg24    0x68
+#define DW_OP_reg25    0x69
+#define DW_OP_reg26    0x6a
+#define DW_OP_reg27    0x6b
+#define DW_OP_reg28    0x6c
+#define DW_OP_reg29    0x6d
+#define DW_OP_reg30    0x6e
+#define DW_OP_reg31    0x6f
+#define DW_OP_breg0    0x70
+#define DW_OP_breg1    0x71
+#define DW_OP_breg2    0x72
+#define DW_OP_breg3    0x73
+#define DW_OP_breg4    0x74
+#define DW_OP_breg5    0x75
+#define DW_OP_breg6    0x76
+#define DW_OP_breg7    0x77
+#define DW_OP_breg8    0x78
+#define DW_OP_breg9    0x79
+#define DW_OP_breg10   0x7a
+#define DW_OP_breg11   0x7b
+#define DW_OP_breg12   0x7c
+#define DW_OP_breg13   0x7d
+#define DW_OP_breg14   0x7e
+#define DW_OP_breg15   0x7f
+#define DW_OP_breg16   0x80
+#define DW_OP_breg17   0x81
+#define DW_OP_breg18   0x82
+#define DW_OP_breg19   0x83
+#define DW_OP_breg20   0x84
+#define DW_OP_breg21   0x85
+#define DW_OP_breg22   0x86
+#define DW_OP_breg23   0x87
+#define DW_OP_breg24   0x88
+#define DW_OP_breg25   0x89
+#define DW_OP_breg26   0x8a
+#define DW_OP_breg27   0x8b
+#define DW_OP_breg28   0x8c
+#define DW_OP_breg29   0x8d
+#define DW_OP_breg30   0x8e
+#define DW_OP_breg31   0x8f
+#define DW_OP_regx     0x90
+#define DW_OP_fbreg    0x91
+#define DW_OP_bregx    0x92
+#define DW_OP_piece    0x93
+#define DW_OP_deref_size       0x94
+#define DW_OP_xderef_size      0x95
+#define DW_OP_nop      0x96
+#define DW_OP_push_object_address      0x97
+#define DW_OP_call2    0x98
+#define DW_OP_call4    0x99
+#define DW_OP_call_ref 0x9a
+#define DW_OP_form_tls_address 0x9b
+#define DW_OP_call_frame_cfa   0x9c
+#define DW_OP_bit_piece        0x9d
+#define DW_OP_lo_user  0xe0
+#define DW_OP_hi_user  0xff
+
+/*
+ * Addresses used in FDE entries in the .eh_frame section may be encoded
+ * using one of the following encodings.
+ */
+#define DW_EH_PE_absptr        0x00
+#define DW_EH_PE_omit  0xff
+#define DW_EH_PE_uleb128       0x01
+#define DW_EH_PE_udata2        0x02
+#define DW_EH_PE_udata4        0x03
+#define DW_EH_PE_udata8        0x04
+#define DW_EH_PE_sleb128       0x09
+#define DW_EH_PE_sdata2        0x0a
+#define DW_EH_PE_sdata4        0x0b
+#define DW_EH_PE_sdata8        0x0c
+#define DW_EH_PE_signed        0x09
+
+#define DW_EH_PE_pcrel 0x10
+
+/*
+ * The architecture-specific register number that contains the return
+ * address in the .debug_frame table.
+ */
+#define DWARF_ARCH_RA_REG      17
+
+#ifndef __ASSEMBLY__
+/*
+ * Read either the frame pointer (r14) or the stack pointer (r15).
+ * NOTE: this MUST be inlined.
+ */
+static __always_inline unsigned long dwarf_read_arch_reg(unsigned int reg)
+{
+       unsigned long value = 0;
+
+       switch (reg) {
+       case 14:
+               __asm__ __volatile__("mov r14, %0\n" : "=r" (value));
+               break;
+       case 15:
+               __asm__ __volatile__("mov r15, %0\n" : "=r" (value));
+               break;
+       default:
+               BUG();
+       }
+
+       return value;
+}
+
+/**
+ *     dwarf_cie - Common Information Entry
+ */
+struct dwarf_cie {
+       unsigned long length;
+       unsigned long cie_id;
+       unsigned char version;
+       const char *augmentation;
+       unsigned int code_alignment_factor;
+       int data_alignment_factor;
+
+       /* Which column in the rule table represents return addr of func. */
+       unsigned int return_address_reg;
+
+       unsigned char *initial_instructions;
+       unsigned char *instructions_end;
+
+       unsigned char encoding;
+
+       unsigned long cie_pointer;
+
+       struct list_head link;
+
+       unsigned long flags;
+#define DWARF_CIE_Z_AUGMENTATION       (1 << 0)
+};
+
+/**
+ *     dwarf_fde - Frame Description Entry
+ */
+struct dwarf_fde {
+       unsigned long length;
+       unsigned long cie_pointer;
+       struct dwarf_cie *cie;
+       unsigned long initial_location;
+       unsigned long address_range;
+       unsigned char *instructions;
+       unsigned char *end;
+       struct list_head link;
+};
+
+/**
+ *     dwarf_frame - DWARF information for a frame in the call stack
+ */
+struct dwarf_frame {
+       struct dwarf_frame *prev, *next;
+
+       unsigned long pc;
+
+       struct list_head reg_list;
+
+       unsigned long cfa;
+
+       /* Valid when DW_FRAME_CFA_REG_OFFSET is set in flags */
+       unsigned int cfa_register;
+       unsigned int cfa_offset;
+
+       /* Valid when DW_FRAME_CFA_REG_EXP is set in flags */
+       unsigned char *cfa_expr;
+       unsigned int cfa_expr_len;
+
+       unsigned long flags;
+#define DWARF_FRAME_CFA_REG_OFFSET     (1 << 0)
+#define DWARF_FRAME_CFA_REG_EXP                (1 << 1)
+
+       unsigned long return_addr;
+};
+
+/**
+ *     dwarf_reg - DWARF register
+ *     @flags: Describes how to calculate the value of this register
+ */
+struct dwarf_reg {
+       struct list_head link;
+
+       unsigned int number;
+
+       unsigned long addr;
+       unsigned long flags;
+#define DWARF_REG_OFFSET       (1 << 0)
+#define DWARF_VAL_OFFSET       (1 << 1)
+#define DWARF_UNDEFINED                (1 << 2)
+};
+
+/*
+ * Call Frame instruction opcodes.
+ */
+#define DW_CFA_advance_loc     0x40
+#define DW_CFA_offset          0x80
+#define DW_CFA_restore         0xc0
+#define DW_CFA_nop             0x00
+#define DW_CFA_set_loc         0x01
+#define DW_CFA_advance_loc1    0x02
+#define DW_CFA_advance_loc2    0x03
+#define DW_CFA_advance_loc4    0x04
+#define DW_CFA_offset_extended 0x05
+#define DW_CFA_restore_extended        0x06
+#define DW_CFA_undefined       0x07
+#define DW_CFA_same_value      0x08
+#define DW_CFA_register                0x09
+#define DW_CFA_remember_state  0x0a
+#define DW_CFA_restore_state   0x0b
+#define DW_CFA_def_cfa         0x0c
+#define DW_CFA_def_cfa_register        0x0d
+#define DW_CFA_def_cfa_offset  0x0e
+#define DW_CFA_def_cfa_expression      0x0f
+#define DW_CFA_expression      0x10
+#define DW_CFA_offset_extended_sf      0x11
+#define DW_CFA_def_cfa_sf      0x12
+#define DW_CFA_def_cfa_offset_sf       0x13
+#define DW_CFA_val_offset      0x14
+#define DW_CFA_val_offset_sf   0x15
+#define DW_CFA_val_expression  0x16
+#define DW_CFA_lo_user         0x1c
+#define DW_CFA_hi_user         0x3f
+
+/* GNU extension opcodes  */
+#define DW_CFA_GNU_args_size   0x2e
+#define DW_CFA_GNU_negative_offset_extended 0x2f
+
+/*
+ * Some call frame instructions encode their operands in the opcode. We
+ * need some helper functions to extract both the opcode and operands
+ * from an instruction.
+ */
+static inline unsigned int DW_CFA_opcode(unsigned long insn)
+{
+       return (insn & 0xc0);
+}
+
+static inline unsigned int DW_CFA_operand(unsigned long insn)
+{
+       return (insn & 0x3f);
+}
+
+#define DW_EH_FRAME_CIE        0               /* .eh_frame CIE IDs are 0 */
+#define DW_CIE_ID      0xffffffff
+#define DW64_CIE_ID    0xffffffffffffffffULL
+
+/*
+ * DWARF FDE/CIE length field values.
+ */
+#define DW_EXT_LO      0xfffffff0
+#define DW_EXT_HI      0xffffffff
+#define DW_EXT_DWARF64 DW_EXT_HI
+
+extern struct dwarf_frame *dwarf_unwind_stack(unsigned long,
+                                             struct dwarf_frame *);
+#endif /* !__ASSEMBLY__ */
+
+#define CFI_STARTPROC  .cfi_startproc
+#define CFI_ENDPROC    .cfi_endproc
+#define CFI_DEF_CFA    .cfi_def_cfa
+#define CFI_REGISTER   .cfi_register
+#define CFI_REL_OFFSET .cfi_rel_offset
+#define CFI_UNDEFINED  .cfi_undefined
+
+#else
+
+/*
+ * Use the asm comment character to ignore the rest of the line.
+ */
+#define CFI_IGNORE     !
+
+#define CFI_STARTPROC  CFI_IGNORE
+#define CFI_ENDPROC    CFI_IGNORE
+#define CFI_DEF_CFA    CFI_IGNORE
+#define CFI_REGISTER   CFI_IGNORE
+#define CFI_REL_OFFSET CFI_IGNORE
+#define CFI_UNDEFINED  CFI_IGNORE
+
+#ifndef __ASSEMBLY__
+static inline void dwarf_unwinder_init(void)
+{
+}
+#endif
+
+#endif /* CONFIG_DWARF_UNWINDER */
+
+#endif /* __ASM_SH_DWARF_H */
index 3a4752a..cc43a55 100644 (file)
@@ -7,7 +7,7 @@
        .endm
 
        .macro  sti
-       mov     #0xf0, r11
+       mov     #0xfffffff0, r11
        extu.b  r11, r11
        not     r11, r11
        stc     sr, r10
 #endif 
        .endm
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+       .macro  TRACE_IRQS_ON
+       mov.l   r0, @-r15
+       mov.l   r1, @-r15
+       mov.l   r2, @-r15
+       mov.l   r3, @-r15
+       mov.l   r4, @-r15
+       mov.l   r5, @-r15
+       mov.l   r6, @-r15
+       mov.l   r7, @-r15
+
+       mov.l   7834f, r0
+       jsr     @r0
+        nop
+
+       mov.l   @r15+, r7
+       mov.l   @r15+, r6
+       mov.l   @r15+, r5
+       mov.l   @r15+, r4
+       mov.l   @r15+, r3
+       mov.l   @r15+, r2
+       mov.l   @r15+, r1
+       mov.l   @r15+, r0
+       mov.l   7834f, r0
+
+       bra     7835f
+        nop
+       .balign 4
+7834:  .long   trace_hardirqs_on
+7835:
+       .endm
+       .macro  TRACE_IRQS_OFF
+
+       mov.l   r0, @-r15
+       mov.l   r1, @-r15
+       mov.l   r2, @-r15
+       mov.l   r3, @-r15
+       mov.l   r4, @-r15
+       mov.l   r5, @-r15
+       mov.l   r6, @-r15
+       mov.l   r7, @-r15
+
+       mov.l   7834f, r0
+       jsr     @r0
+        nop
+
+       mov.l   @r15+, r7
+       mov.l   @r15+, r6
+       mov.l   @r15+, r5
+       mov.l   @r15+, r4
+       mov.l   @r15+, r3
+       mov.l   @r15+, r2
+       mov.l   @r15+, r1
+       mov.l   @r15+, r0
+       mov.l   7834f, r0
+
+       bra     7835f
+        nop
+       .balign 4
+7834:  .long   trace_hardirqs_off
+7835:
+       .endm
+
+#else
+       .macro  TRACE_IRQS_ON
+       .endm
+
+       .macro  TRACE_IRQS_OFF
+       .endm
+#endif
+
 #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4)
 # define PREF(x)       pref    @x
 #else
 # define PREF(x)       nop
 #endif
+
+       /*
+        * Macro for use within assembly. Because the DWARF unwinder
+        * needs to use the frame register to unwind the stack, we
+        * need to setup r14 with the value of the stack pointer as
+        * the return address is usually on the stack somewhere.
+        */
+       .macro  setup_frame_reg
+#ifdef CONFIG_DWARF_UNWINDER
+       mov     r15, r14
+#endif
+       .endm
index 8fea7d8..12f3a31 100644 (file)
@@ -4,6 +4,7 @@
 #ifdef CONFIG_FUNCTION_TRACER
 
 #define MCOUNT_INSN_SIZE       4 /* sizeof mcount call */
+#define FTRACE_SYSCALL_MAX     NR_syscalls
 
 #ifndef __ASSEMBLY__
 extern void mcount(void);
@@ -11,10 +12,13 @@ extern void mcount(void);
 #define MCOUNT_ADDR            ((long)(mcount))
 
 #ifdef CONFIG_DYNAMIC_FTRACE
-#define CALLER_ADDR            ((long)(ftrace_caller))
+#define CALL_ADDR              ((long)(ftrace_call))
 #define STUB_ADDR              ((long)(ftrace_stub))
+#define GRAPH_ADDR             ((long)(ftrace_graph_call))
+#define CALLER_ADDR            ((long)(ftrace_caller))
 
-#define MCOUNT_INSN_OFFSET     ((STUB_ADDR - CALLER_ADDR) >> 1)
+#define MCOUNT_INSN_OFFSET     ((STUB_ADDR - CALL_ADDR) - 4)
+#define GRAPH_INSN_OFFSET      ((CALLER_ADDR - GRAPH_ADDR) - 4)
 
 struct dyn_arch_ftrace {
        /* No extra data needed on sh */
index 715ee23..a5be4af 100644 (file)
@@ -1,16 +1,9 @@
 #ifndef __ASM_SH_HARDIRQ_H
 #define __ASM_SH_HARDIRQ_H
 
-#include <linux/threads.h>
-#include <linux/irq.h>
-
-/* entry.S is sensitive to the offsets of these fields */
-typedef struct {
-       unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
-
 extern void ack_bad_irq(unsigned int irq);
+#define ack_bad_irq ack_bad_irq
+
+#include <asm-generic/hardirq.h>
 
 #endif /* __ASM_SH_HARDIRQ_H */
index 724a43e..caaafe5 100644 (file)
@@ -11,6 +11,7 @@ struct heartbeat_data {
        unsigned int nr_bits;
        struct timer_list timer;
        unsigned int regsize;
+       unsigned int mask;
        unsigned long flags;
 };
 
diff --git a/arch/sh/include/asm/hwblk.h b/arch/sh/include/asm/hwblk.h
new file mode 100644 (file)
index 0000000..5d3ccae
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef __ASM_SH_HWBLK_H
+#define __ASM_SH_HWBLK_H
+
+#include <asm/clock.h>
+#include <asm/io.h>
+
+#define HWBLK_CNT_USAGE 0
+#define HWBLK_CNT_IDLE 1
+#define HWBLK_CNT_DEVICES 2
+#define HWBLK_CNT_NR 3
+
+#define HWBLK_AREA_FLAG_PARENT (1 << 0) /* valid parent */
+
+#define HWBLK_AREA(_flags, _parent)            \
+{                                              \
+       .flags = _flags,                        \
+       .parent = _parent,                      \
+}
+
+struct hwblk_area {
+       int cnt[HWBLK_CNT_NR];
+       unsigned char parent;
+       unsigned char flags;
+};
+
+#define HWBLK(_mstp, _bit, _area)              \
+{                                              \
+       .mstp = (void __iomem *)_mstp,          \
+       .bit = _bit,                            \
+       .area = _area,                          \
+}
+
+struct hwblk {
+       void __iomem *mstp;
+       unsigned char bit;
+       unsigned char area;
+       int cnt[HWBLK_CNT_NR];
+};
+
+struct hwblk_info {
+       struct hwblk_area *areas;
+       int nr_areas;
+       struct hwblk *hwblks;
+       int nr_hwblks;
+};
+
+/* Should be defined by processor-specific code */
+int arch_hwblk_init(void);
+int arch_hwblk_sleep_mode(void);
+
+int hwblk_register(struct hwblk_info *info);
+int hwblk_init(void);
+
+void hwblk_enable(struct hwblk_info *info, int hwblk);
+void hwblk_disable(struct hwblk_info *info, int hwblk);
+
+void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int cnt);
+void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int cnt);
+
+/* allow clocks to enable and disable hardware blocks */
+#define SH_HWBLK_CLK(_name, _id, _parent, _hwblk, _flags)      \
+{                                                      \
+       .name           = _name,                        \
+       .id             = _id,                          \
+       .parent         = _parent,                      \
+       .arch_flags     = _hwblk,                       \
+       .flags          = _flags,                       \
+}
+
+int sh_hwblk_clk_register(struct clk *clks, int nr);
+
+#endif /* __ASM_SH_HWBLK_H */
index 2534814..5be45ea 100644 (file)
 
 static inline void ctrl_delay(void)
 {
-#ifdef P2SEG
+#ifdef CONFIG_CPU_SH4
+       __raw_readw(CCN_PVR);
+#elif defined(P2SEG)
        __raw_readw(P2SEG);
+#else
+#error "Need a dummy address for delay"
 #endif
 }
 
@@ -146,6 +150,7 @@ __BUILD_MEMORY_STRING(q, u64)
 #define readl_relaxed(a)       readl(a)
 #define readq_relaxed(a)       readq(a)
 
+#ifndef CONFIG_GENERIC_IOMAP
 /* Simple MMIO */
 #define ioread8(a)             __raw_readb(a)
 #define ioread16(a)            __raw_readw(a)
@@ -166,6 +171,15 @@ __BUILD_MEMORY_STRING(q, u64)
 #define iowrite8_rep(a, s, c)  __raw_writesb((a), (s), (c))
 #define iowrite16_rep(a, s, c) __raw_writesw((a), (s), (c))
 #define iowrite32_rep(a, s, c) __raw_writesl((a), (s), (c))
+#endif
+
+#define mmio_insb(p,d,c)       __raw_readsb(p,d,c)
+#define mmio_insw(p,d,c)       __raw_readsw(p,d,c)
+#define mmio_insl(p,d,c)       __raw_readsl(p,d,c)
+
+#define mmio_outsb(p,s,c)      __raw_writesb(p,s,c)
+#define mmio_outsw(p,s,c)      __raw_writesw(p,s,c)
+#define mmio_outsl(p,s,c)      __raw_writesl(p,s,c)
 
 /* synco on SH-4A, otherwise a nop */
 #define mmiowb()               wmb()
index 0b9f896..985219f 100644 (file)
@@ -4,6 +4,7 @@
 /* Grossly misnamed. */
 enum die_val {
        DIE_TRAP,
+       DIE_NMI,
        DIE_OOPS,
 };
 
index 72704ed..4235e22 100644 (file)
@@ -30,9 +30,6 @@ static inline void arch_kgdb_breakpoint(void)
        __asm__ __volatile__ ("trapa #0x3c\n");
 }
 
-/* State info */
-extern char in_nmi;            /* Debounce flag to prevent NMI reentry*/
-
 #define BUFMAX                 2048
 
 #define CACHE_FLUSH_IS_SAFE    1
diff --git a/arch/sh/include/asm/lmb.h b/arch/sh/include/asm/lmb.h
new file mode 100644 (file)
index 0000000..9b437f6
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH_LMB_H
+#define __ASM_SH_LMB_H
+
+#define LMB_REAL_LIMIT 0
+
+#endif /* __ASM_SH_LMB_H */
index 67d8946..41080b1 100644 (file)
@@ -69,7 +69,7 @@ static inline void get_mmu_context(struct mm_struct *mm, unsigned int cpu)
                 * We exhaust ASID of this version.
                 * Flush all TLB and start new cycle.
                 */
-               flush_tlb_all();
+               local_flush_tlb_all();
 
 #ifdef CONFIG_SUPERH64
                /*
index 49592c7..81bffc0 100644 (file)
@@ -50,26 +50,24 @@ extern unsigned long shm_align_mask;
 extern unsigned long max_low_pfn, min_low_pfn;
 extern unsigned long memory_start, memory_end;
 
-extern void clear_page(void *to);
+static inline unsigned long
+pages_do_alias(unsigned long addr1, unsigned long addr2)
+{
+       return (addr1 ^ addr2) & shm_align_mask;
+}
+
+
+#define clear_page(page)       memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, void *from);
 
-#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \
-       (defined(CONFIG_CPU_SH5) || defined(CONFIG_CPU_SH4) || \
-        defined(CONFIG_SH7705_CACHE_32KB))
 struct page;
 struct vm_area_struct;
-extern void clear_user_page(void *to, unsigned long address, struct page *page);
-extern void copy_user_page(void *to, void *from, unsigned long address,
-                          struct page *page);
-#if defined(CONFIG_CPU_SH4)
+
 extern void copy_user_highpage(struct page *to, struct page *from,
                               unsigned long vaddr, struct vm_area_struct *vma);
 #define __HAVE_ARCH_COPY_USER_HIGHPAGE
-#endif
-#else
-#define clear_user_page(page, vaddr, pg)       clear_page(page)
-#define copy_user_page(to, from, vaddr, pg)    copy_page(to, from)
-#endif
+extern void clear_user_highpage(struct page *page, unsigned long vaddr);
+#define clear_user_highpage    clear_user_highpage
 
 /*
  * These are used to make use of C type-checking..
index 2a011b1..4f3efa7 100644 (file)
@@ -36,6 +36,12 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 #define        NEFF_SIGN       (1LL << (NEFF - 1))
 #define        NEFF_MASK       (-1LL << NEFF)
 
+static inline unsigned long long neff_sign_extend(unsigned long val)
+{
+       unsigned long long extended = val;
+       return (extended & NEFF_SIGN) ? (extended | NEFF_MASK) : extended;
+}
+
 #ifdef CONFIG_29BIT
 #define NPHYS          29
 #else
@@ -133,27 +139,25 @@ typedef pte_t *pte_addr_t;
  */
 #define pgtable_cache_init()   do { } while (0)
 
-#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \
-       defined(CONFIG_SH7705_CACHE_32KB))
-struct mm_struct;
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
-#endif
-
 struct vm_area_struct;
-extern void update_mmu_cache(struct vm_area_struct * vma,
-                            unsigned long address, pte_t pte);
+
+extern void __update_cache(struct vm_area_struct *vma,
+                          unsigned long address, pte_t pte);
+extern void __update_tlb(struct vm_area_struct *vma,
+                        unsigned long address, pte_t pte);
+
+static inline void
+update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+{
+       __update_cache(vma, address, pte);
+       __update_tlb(vma, address, pte);
+}
+
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern void paging_init(void);
 extern void page_table_range_init(unsigned long start, unsigned long end,
                                  pgd_t *pgd);
 
-#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_CPU_SH4) && defined(CONFIG_MMU)
-extern void kmap_coherent_init(void);
-#else
-#define kmap_coherent_init()   do { } while (0)
-#endif
-
 /* arch/sh/mm/mmap.c */
 #define HAVE_ARCH_UNMAPPED_AREA
 #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
index 72ea209..c0d359c 100644 (file)
@@ -20,7 +20,7 @@
  * - Bit 9 is reserved by everyone and used by _PAGE_PROTNONE.
  *
  * - Bits 10 and 11 are low bits of the PPN that are reserved on >= 4K pages.
- *   Bit 10 is used for _PAGE_ACCESSED, bit 11 remains unused.
+ *   Bit 10 is used for _PAGE_ACCESSED, and bit 11 is used for _PAGE_SPECIAL.
  *
  * - On 29 bit platforms, bits 31 to 29 are used for the space attributes
  *   and timing control which (together with bit 0) are moved into the
@@ -52,6 +52,7 @@
 #define _PAGE_PROTNONE 0x200           /* software: if not present  */
 #define _PAGE_ACCESSED 0x400           /* software: page referenced */
 #define _PAGE_FILE     _PAGE_WT        /* software: pagecache or swap? */
+#define _PAGE_SPECIAL  0x800           /* software: special page */
 
 #define _PAGE_SZ_MASK  (_PAGE_SZ0 | _PAGE_SZ1)
 #define _PAGE_PR_MASK  (_PAGE_RW | _PAGE_USER)
 #define _PAGE_PCC_ATR8 0x60000000      /* Attribute Memory space, 8 bit bus */
 #define _PAGE_PCC_ATR16        0x60000001      /* Attribute Memory space, 6 bit bus */
 
+#ifndef CONFIG_X2TLB
+/* copy the ptea attributes */
+static inline unsigned long copy_ptea_attributes(unsigned long x)
+{
+       return  ((x >> 28) & 0xe) | (x & 0x1);
+}
+#endif
+
 /* Mask which drops unused bits from the PTEL value */
 #if defined(CONFIG_CPU_SH3)
 #define _PAGE_CLEAR_FLAGS      (_PAGE_PROTNONE | _PAGE_ACCESSED| \
 # define _PAGE_SZHUGE  (_PAGE_FLAGS_HARD)
 #endif
 
+/*
+ * Mask of bits that are to be preserved accross pgprot changes.
+ */
 #define _PAGE_CHG_MASK \
-       (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY)
+       (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | \
+        _PAGE_DIRTY | _PAGE_SPECIAL)
 
 #ifndef __ASSEMBLY__
 
@@ -328,7 +341,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
 #define pte_dirty(pte)         ((pte).pte_low & _PAGE_DIRTY)
 #define pte_young(pte)         ((pte).pte_low & _PAGE_ACCESSED)
 #define pte_file(pte)          ((pte).pte_low & _PAGE_FILE)
-#define pte_special(pte)       (0)
+#define pte_special(pte)       ((pte).pte_low & _PAGE_SPECIAL)
 
 #ifdef CONFIG_X2TLB
 #define pte_write(pte)         ((pte).pte_high & _PAGE_EXT_USER_WRITE)
@@ -358,8 +371,9 @@ PTE_BIT_FUNC(low, mkclean, &= ~_PAGE_DIRTY);
 PTE_BIT_FUNC(low, mkdirty, |= _PAGE_DIRTY);
 PTE_BIT_FUNC(low, mkold, &= ~_PAGE_ACCESSED);
 PTE_BIT_FUNC(low, mkyoung, |= _PAGE_ACCESSED);
+PTE_BIT_FUNC(low, mkspecial, |= _PAGE_SPECIAL);
 
-static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+#define __HAVE_ARCH_PTE_SPECIAL
 
 /*
  * Macro and implementation to make a page protection as uncachable.
@@ -394,13 +408,19 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address)     (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
-#define pgd_offset(mm, address)        ((mm)->pgd+pgd_index(address))
+#define pgd_offset(mm, address)        ((mm)->pgd + pgd_index(address))
+#define __pgd_offset(address)  pgd_index(address)
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address)  pgd_offset(&init_mm, address)
 
+#define __pud_offset(address)  (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
+#define __pmd_offset(address)  (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+
 /* Find an entry in the third-level page table.. */
 #define pte_index(address)     ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define __pte_offset(address)  pte_index(address)
+
 #define pte_offset_kernel(dir, address) \
        ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address))
 #define pte_offset_map(dir, address)           pte_offset_kernel(dir, address)
index c78990c..17cdbec 100644 (file)
@@ -60,6 +60,9 @@ static __inline__ void pmd_set(pmd_t *pmdp,pte_t *ptep)
 /* To find an entry in a kernel PGD. */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
+#define __pud_offset(address)  (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
+#define __pmd_offset(address)  (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+
 /*
  * PMD level access routines. Same notes as above.
  */
@@ -80,6 +83,8 @@ static __inline__ void pmd_set(pmd_t *pmdp,pte_t *ptep)
 #define pte_index(address) \
                ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 
+#define __pte_offset(address)  pte_index(address)
+
 #define pte_offset_kernel(dir, addr) \
                ((pte_t *) ((pmd_val(*(dir))) & PAGE_MASK) + pte_index((addr)))
 
index ff7daaf..017e0c1 100644 (file)
@@ -32,7 +32,7 @@ enum cpu_type {
 
        /* SH-4A types */
        CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SH7786,
-       CPU_SH7723, CPU_SH7724, CPU_SHX3,
+       CPU_SH7723, CPU_SH7724, CPU_SH7757, CPU_SHX3,
 
        /* SH4AL-DSP types */
        CPU_SH7343, CPU_SH7722, CPU_SH7366,
@@ -44,6 +44,17 @@ enum cpu_type {
        CPU_SH_NONE
 };
 
+enum cpu_family {
+       CPU_FAMILY_SH2,
+       CPU_FAMILY_SH2A,
+       CPU_FAMILY_SH3,
+       CPU_FAMILY_SH4,
+       CPU_FAMILY_SH4A,
+       CPU_FAMILY_SH4AL_DSP,
+       CPU_FAMILY_SH5,
+       CPU_FAMILY_UNKNOWN,
+};
+
 /*
  * TLB information structure
  *
@@ -61,7 +72,7 @@ struct tlb_info {
 };
 
 struct sh_cpuinfo {
-       unsigned int type;
+       unsigned int type, family;
        int cut_major, cut_minor;
        unsigned long loops_per_jiffy;
        unsigned long asid_cache;
index 01a4076..a78701d 100644 (file)
@@ -7,6 +7,7 @@ extern void __nosave_begin, __nosave_end;
 extern long __machvec_start, __machvec_end;
 extern char __uncached_start, __uncached_end;
 extern char _ebss[];
+extern char __start_eh_frame[], __stop_eh_frame[];
 
 #endif /* __ASM_SH_SECTIONS_H */
 
diff --git a/arch/sh/include/asm/stacktrace.h b/arch/sh/include/asm/stacktrace.h
new file mode 100644 (file)
index 0000000..7970182
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009  Matt Fleming
+ *
+ * Based on:
+ *     The x86 implementation - arch/x86/include/asm/stacktrace.h
+ */
+#ifndef _ASM_SH_STACKTRACE_H
+#define _ASM_SH_STACKTRACE_H
+
+/* Generic stack tracer with callbacks */
+
+struct stacktrace_ops {
+       void (*warning)(void *data, char *msg);
+       /* msg must contain %s for the symbol */
+       void (*warning_symbol)(void *data, char *msg, unsigned long symbol);
+       void (*address)(void *data, unsigned long address, int reliable);
+       /* On negative return stop dumping */
+       int (*stack)(void *data, char *name);
+};
+
+void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
+               unsigned long *stack,
+               const struct stacktrace_ops *ops, void *data);
+
+#endif /* _ASM_SH_STACKTRACE_H */
index b1b9953..5c8ea28 100644 (file)
@@ -10,6 +10,15 @@ struct swsusp_arch_regs {
        struct pt_regs user_regs;
        unsigned long bank1_regs[8];
 };
+
+void sh_mobile_call_standby(unsigned long mode);
+
+#ifdef CONFIG_CPU_IDLE
+void sh_mobile_setup_cpuidle(void);
+#else
+static inline void sh_mobile_setup_cpuidle(void) {}
+#endif
+
 #endif
 
 /* flags passed to assembly suspend code */
index 6f83f2c..7d80df4 100644 (file)
@@ -65,6 +65,7 @@ static inline void syscall_get_arguments(struct task_struct *task,
        case 3: args[2] = regs->regs[6];
        case 2: args[1] = regs->regs[5];
        case 1: args[0] = regs->regs[4];
+       case 0:
                break;
        default:
                BUG();
index ab79e1f..b5c5acd 100644 (file)
 
 #define AT_VECTOR_SIZE_ARCH 5 /* entries in ARCH_DLINFO */
 
-#if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5)
-#define __icbi()                       \
-{                                      \
-       unsigned long __addr;           \
-       __addr = 0xa8000000;            \
-       __asm__ __volatile__(           \
-               "icbi   %0\n\t"         \
-               : /* no output */       \
-               : "m" (__m(__addr)));   \
-}
-#endif
-
 /*
  * A brief note on ctrl_barrier(), the control register write barrier.
  *
@@ -44,7 +32,7 @@
 #define mb()           __asm__ __volatile__ ("synco": : :"memory")
 #define rmb()          mb()
 #define wmb()          __asm__ __volatile__ ("synco": : :"memory")
-#define ctrl_barrier() __icbi()
+#define ctrl_barrier() __icbi(0xa8000000)
 #define read_barrier_depends() do { } while(0)
 #else
 #define mb()           __asm__ __volatile__ ("": : :"memory")
@@ -181,6 +169,11 @@ BUILD_TRAP_HANDLER(breakpoint);
 BUILD_TRAP_HANDLER(singlestep);
 BUILD_TRAP_HANDLER(fpu_error);
 BUILD_TRAP_HANDLER(fpu_state_restore);
+BUILD_TRAP_HANDLER(nmi);
+
+#ifdef CONFIG_BUG
+extern void handle_BUG(struct pt_regs *);
+#endif
 
 #define arch_align_stack(x) (x)
 
index 6c68a51..607d413 100644 (file)
@@ -14,12 +14,12 @@ do {                                                                        \
                        (u32 *)&tsk->thread.dsp_status;                 \
        __asm__ __volatile__ (                                          \
                ".balign 4\n\t"                                         \
+               "movs.l @r2+, a0\n\t"                                   \
                "movs.l @r2+, a1\n\t"                                   \
                "movs.l @r2+, a0g\n\t"                                  \
                "movs.l @r2+, a1g\n\t"                                  \
                "movs.l @r2+, m0\n\t"                                   \
                "movs.l @r2+, m1\n\t"                                   \
-               "movs.l @r2+, a0\n\t"                                   \
                "movs.l @r2+, x0\n\t"                                   \
                "movs.l @r2+, x1\n\t"                                   \
                "movs.l @r2+, y0\n\t"                                   \
@@ -39,20 +39,20 @@ do {                                                                        \
                                                                        \
        __asm__ __volatile__ (                                          \
                ".balign 4\n\t"                                         \
-               "stc.l  mod, @-r2\n\t"                          \
+               "stc.l  mod, @-r2\n\t"                                  \
                "stc.l  re, @-r2\n\t"                                   \
                "stc.l  rs, @-r2\n\t"                                   \
-               "sts.l  dsr, @-r2\n\t"                          \
-               "sts.l  y1, @-r2\n\t"                                   \
-               "sts.l  y0, @-r2\n\t"                                   \
-               "sts.l  x1, @-r2\n\t"                                   \
-               "sts.l  x0, @-r2\n\t"                                   \
-               "sts.l  a0, @-r2\n\t"                                   \
-               ".word  0xf653          ! movs.l        a1, @-r2\n\t"   \
-               ".word  0xf6f3          ! movs.l        a0g, @-r2\n\t"  \
-               ".word  0xf6d3          ! movs.l        a1g, @-r2\n\t"  \
-               ".word  0xf6c3          ! movs.l        m0, @-r2\n\t"   \
-               ".word  0xf6e3          ! movs.l        m1, @-r2\n\t"   \
+               "sts.l  dsr, @-r2\n\t"                                  \
+               "movs.l y1, @-r2\n\t"                                   \
+               "movs.l y0, @-r2\n\t"                                   \
+               "movs.l x1, @-r2\n\t"                                   \
+               "movs.l x0, @-r2\n\t"                                   \
+               "movs.l m1, @-r2\n\t"                                   \
+               "movs.l m0, @-r2\n\t"                                   \
+               "movs.l a1g, @-r2\n\t"                                  \
+               "movs.l a0g, @-r2\n\t"                                  \
+               "movs.l a1, @-r2\n\t"                                   \
+               "movs.l a0, @-r2\n\t"                                   \
                : : "r" (__ts2));                                       \
 } while (0)
 
@@ -63,6 +63,16 @@ do {                                                                 \
 #define __restore_dsp(tsk)     do { } while (0)
 #endif
 
+#if defined(CONFIG_CPU_SH4A)
+#define __icbi(addr)   __asm__ __volatile__ ( "icbi @%0\n\t" : : "r" (addr))
+#else
+#define __icbi(addr)   mb()
+#endif
+
+#define __ocbp(addr)   __asm__ __volatile__ ( "ocbp @%0\n\t" : : "r" (addr))
+#define __ocbi(addr)   __asm__ __volatile__ ( "ocbi @%0\n\t" : : "r" (addr))
+#define __ocbwb(addr)  __asm__ __volatile__ ( "ocbwb @%0\n\t" : : "r" (addr))
+
 struct task_struct *__switch_to(struct task_struct *prev,
                                struct task_struct *next);
 
@@ -198,8 +208,13 @@ do {                                                       \
 })
 #endif
 
+static inline reg_size_t register_align(void *val)
+{
+       return (unsigned long)(signed long)val;
+}
+
 int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
-                           struct mem_access *ma);
+                           struct mem_access *ma, int);
 
 asmlinkage void do_address_error(struct pt_regs *regs,
                                 unsigned long writeaccess,
index 943acf5..8e4a03e 100644 (file)
@@ -37,4 +37,14 @@ do {                                                         \
 #define jump_to_uncached()     do { } while (0)
 #define back_to_cached()       do { } while (0)
 
+#define __icbi(addr)   __asm__ __volatile__ ( "icbi %0, 0\n\t" : : "r" (addr))
+#define __ocbp(addr)   __asm__ __volatile__ ( "ocbp %0, 0\n\t" : : "r" (addr))
+#define __ocbi(addr)   __asm__ __volatile__ ( "ocbi %0, 0\n\t" : : "r" (addr))
+#define __ocbwb(addr)  __asm__ __volatile__ ( "ocbwb %0, 0\n\t" : : "r" (addr))
+
+static inline reg_size_t register_align(void *val)
+{
+       return (unsigned long long)(signed long long)(signed long)val;
+}
+
 #endif /* __ASM_SH_SYSTEM_64_H */
index d570ac2..5123bca 100644 (file)
@@ -97,7 +97,7 @@ static inline struct thread_info *current_thread_info(void)
 
 extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
 extern void free_thread_info(struct thread_info *ti);
+
 #endif /* THREAD_SHIFT < PAGE_SHIFT */
 
 #endif /* __ASSEMBLY__ */
@@ -116,6 +116,7 @@ extern void free_thread_info(struct thread_info *ti);
 #define TIF_SYSCALL_AUDIT      5       /* syscall auditing active */
 #define TIF_SECCOMP            6       /* secure computing */
 #define TIF_NOTIFY_RESUME      7       /* callback before returning to user */
+#define TIF_SYSCALL_FTRACE     8       /* for ftrace syscall instrumentation */
 #define TIF_USEDFPU            16      /* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG     17      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             18
@@ -129,25 +130,27 @@ extern void free_thread_info(struct thread_info *ti);
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
+#define _TIF_SYSCALL_FTRACE    (1 << TIF_SYSCALL_FTRACE)
 #define _TIF_USEDFPU           (1 << TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
 #define _TIF_FREEZE            (1 << TIF_FREEZE)
 
 /*
- * _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within a byte, or we
+ * _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within 2 bytes, or we
  * blow the tst immediate size constraints and need to fix up
  * arch/sh/kernel/entry-common.S.
  */
 
 /* work to do in syscall trace */
 #define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
-                                _TIF_SYSCALL_AUDIT | _TIF_SECCOMP)
+                                _TIF_SYSCALL_AUDIT | _TIF_SECCOMP    | \
+                                _TIF_SYSCALL_FTRACE)
 
 /* work to do on any return to u-space */
 #define _TIF_ALLWORK_MASK      (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING      | \
                                 _TIF_NEED_RESCHED  | _TIF_SYSCALL_AUDIT   | \
                                 _TIF_SINGLESTEP    | _TIF_RESTORE_SIGMASK | \
-                                _TIF_NOTIFY_RESUME)
+                                _TIF_NOTIFY_RESUME | _TIF_SYSCALL_FTRACE)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK         (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
index c7f3c94..f8421f7 100644 (file)
 
 #ifdef CONFIG_SUPERH32
 typedef u16 insn_size_t;
+typedef u32 reg_size_t;
 #else
 typedef u32 insn_size_t;
+typedef u64 reg_size_t;
 #endif
 
 #endif /* __ASSEMBLY__ */
index 61d6ad9..925dd40 100644 (file)
 #define __NR_clone             120
 #define __NR_setdomainname     121
 #define __NR_uname             122
-#define __NR_modify_ldt                123
+#define __NR_cacheflush                123
 #define __NR_adjtimex          124
 #define __NR_mprotect          125
 #define __NR_sigprocmask       126
index a751699..2b84bc9 100644 (file)
 #define __NR_clone             120
 #define __NR_setdomainname     121
 #define __NR_uname             122
-#define __NR_modify_ldt                123
+#define __NR_cacheflush                123
 #define __NR_adjtimex          124
 #define __NR_mprotect          125
 #define __NR_sigprocmask       126
diff --git a/arch/sh/include/asm/unwinder.h b/arch/sh/include/asm/unwinder.h
new file mode 100644 (file)
index 0000000..1e65c07
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _LINUX_UNWINDER_H
+#define _LINUX_UNWINDER_H
+
+#include <asm/stacktrace.h>
+
+struct unwinder {
+       const char *name;
+       struct list_head list;
+       int rating;
+       void (*dump)(struct task_struct *, struct pt_regs *,
+                    unsigned long *, const struct stacktrace_ops *, void *);
+};
+
+extern int unwinder_init(void);
+extern int unwinder_register(struct unwinder *);
+
+extern void unwind_stack(struct task_struct *, struct pt_regs *,
+                        unsigned long *, const struct stacktrace_ops *,
+                        void *);
+
+extern void stack_reader_dump(struct task_struct *, struct pt_regs *,
+                             unsigned long *, const struct stacktrace_ops *,
+                             void *);
+
+/*
+ * Used by fault handling code to signal to the unwinder code that it
+ * should switch to a different unwinder.
+ */
+extern int unwinder_faulted;
+
+#endif /* _LINUX_UNWINDER_H */
diff --git a/arch/sh/include/asm/vmlinux.lds.h b/arch/sh/include/asm/vmlinux.lds.h
new file mode 100644 (file)
index 0000000..244ec4a
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __ASM_SH_VMLINUX_LDS_H
+#define __ASM_SH_VMLINUX_LDS_H
+
+#include <asm-generic/vmlinux.lds.h>
+
+#ifdef CONFIG_DWARF_UNWINDER
+#define DWARF_EH_FRAME                                                 \
+       .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) {                 \
+                 VMLINUX_SYMBOL(__start_eh_frame) = .;                 \
+                 *(.eh_frame)                                          \
+                 VMLINUX_SYMBOL(__stop_eh_frame) = .;                  \
+       }
+#else
+#define DWARF_EH_FRAME
+#endif
+
+#endif /* __ASM_SH_VMLINUX_LDS_H */
index f024fed..2fe7cee 100644 (file)
 #ifdef __KERNEL__
 
 #include <linux/types.h>
+#include <linux/io.h>
+
+#define WTCNT_HIGH     0x5a
+#define WTCSR_HIGH     0xa5
+
+#define WTCSR_CKS2     0x04
+#define WTCSR_CKS1     0x02
+#define WTCSR_CKS0     0x01
+
 #include <cpu/watchdog.h>
-#include <asm/io.h>
 
-/* 
+/*
  * See cpu-sh2/watchdog.h for explanation of this stupidity..
  */
 #ifndef WTCNT_R
 #  define WTCSR_R      WTCSR
 #endif
 
-#define WTCNT_HIGH     0x5a
-#define WTCSR_HIGH     0xa5
-
-#define WTCSR_CKS2     0x04
-#define WTCSR_CKS1     0x02
-#define WTCSR_CKS0     0x01
-
 /*
  * CKS0-2 supports a number of clock division ratios. At the time the watchdog
  * is enabled, it defaults to a 41 usec overflow period .. we overload this to
diff --git a/arch/sh/include/cpu-common/cpu/cacheflush.h b/arch/sh/include/cpu-common/cpu/cacheflush.h
deleted file mode 100644 (file)
index c3db00b..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * include/asm-sh/cpu-sh2/cacheflush.h
- *
- * Copyright (C) 2003 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.
- */
-#ifndef __ASM_CPU_SH2_CACHEFLUSH_H
-#define __ASM_CPU_SH2_CACHEFLUSH_H
-
-/*
- * Cache flushing:
- *
- *  - flush_cache_all() flushes entire cache
- *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
- *  - flush_cache_dup mm(mm) handles cache flushing when forking
- *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
- *  - flush_cache_range(vma, start, end) flushes a range of pages
- *
- *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
- *  - flush_icache_range(start, end) flushes(invalidates) a range for icache
- *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
- *
- *  Caches are indexed (effectively) by physical address on SH-2, so
- *  we don't need them.
- */
-#define flush_cache_all()                      do { } while (0)
-#define flush_cache_mm(mm)                     do { } while (0)
-#define flush_cache_dup_mm(mm)                 do { } while (0)
-#define flush_cache_range(vma, start, end)     do { } while (0)
-#define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
-#define flush_dcache_page(page)                        do { } while (0)
-#define flush_dcache_mmap_lock(mapping)                do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
-#define flush_icache_range(start, end)         do { } while (0)
-#define flush_icache_page(vma,pg)              do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
-#define flush_cache_sigtramp(vaddr)            do { } while (0)
-
-#define p3_cache_init()                                do { } while (0)
-
-#endif /* __ASM_CPU_SH2_CACHEFLUSH_H */
diff --git a/arch/sh/include/cpu-sh2a/cpu/cacheflush.h b/arch/sh/include/cpu-sh2a/cpu/cacheflush.h
deleted file mode 100644 (file)
index 3d3b920..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __ASM_CPU_SH2A_CACHEFLUSH_H
-#define __ASM_CPU_SH2A_CACHEFLUSH_H
-
-/* 
- * Cache flushing:
- *
- *  - flush_cache_all() flushes entire cache
- *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
- *  - flush_cache_dup mm(mm) handles cache flushing when forking
- *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
- *  - flush_cache_range(vma, start, end) flushes a range of pages
- *
- *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
- *  - flush_icache_range(start, end) flushes(invalidates) a range for icache
- *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
- *
- *  Caches are indexed (effectively) by physical address on SH-2, so
- *  we don't need them.
- */
-#define flush_cache_all()                      do { } while (0)
-#define flush_cache_mm(mm)                     do { } while (0)
-#define flush_cache_dup_mm(mm)                 do { } while (0)
-#define flush_cache_range(vma, start, end)     do { } while (0)
-#define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
-#define flush_dcache_page(page)                        do { } while (0)
-#define flush_dcache_mmap_lock(mapping)                do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
-void flush_icache_range(unsigned long start, unsigned long end);
-#define flush_icache_page(vma,pg)              do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
-#define flush_cache_sigtramp(vaddr)            do { } while (0)
-
-#define p3_cache_init()                                do { } while (0)
-#endif /* __ASM_CPU_SH2A_CACHEFLUSH_H */
diff --git a/arch/sh/include/cpu-sh3/cpu/cacheflush.h b/arch/sh/include/cpu-sh3/cpu/cacheflush.h
deleted file mode 100644 (file)
index 1ac27aa..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * include/asm-sh/cpu-sh3/cacheflush.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- *
- * 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.
- */
-#ifndef __ASM_CPU_SH3_CACHEFLUSH_H
-#define __ASM_CPU_SH3_CACHEFLUSH_H
-
-#if defined(CONFIG_SH7705_CACHE_32KB)
-/* SH7705 is an SH3 processor with 32KB cache. This has alias issues like the
- * SH4. Unlike the SH4 this is a unified cache so we need to do some work
- * in mmap when 'exec'ing a new binary
- */
- /* 32KB cache, 4kb PAGE sizes need to check bit 12 */
-#define CACHE_ALIAS 0x00001000
-
-#define PG_mapped      PG_arch_1
-
-void flush_cache_all(void);
-void flush_cache_mm(struct mm_struct *mm);
-#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
-void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-                              unsigned long end);
-void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
-void flush_dcache_page(struct page *pg);
-void flush_icache_range(unsigned long start, unsigned long end);
-void flush_icache_page(struct vm_area_struct *vma, struct page *page);
-
-#define flush_dcache_mmap_lock(mapping)                do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
-
-/* SH3 has unified cache so no special action needed here */
-#define flush_cache_sigtramp(vaddr)            do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
-
-#define p3_cache_init()                                do { } while (0)
-
-#else
-#include <cpu-common/cpu/cacheflush.h>
-#endif
-
-#endif /* __ASM_CPU_SH3_CACHEFLUSH_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/cacheflush.h b/arch/sh/include/cpu-sh4/cpu/cacheflush.h
deleted file mode 100644 (file)
index 065306d..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * include/asm-sh/cpu-sh4/cacheflush.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2003 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.
- */
-#ifndef __ASM_CPU_SH4_CACHEFLUSH_H
-#define __ASM_CPU_SH4_CACHEFLUSH_H
-
-/*
- *  Caches are broken on SH-4 (unless we use write-through
- *  caching; in which case they're only semi-broken),
- *  so we need them.
- */
-void flush_cache_all(void);
-void flush_dcache_all(void);
-void flush_cache_mm(struct mm_struct *mm);
-#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
-void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-                      unsigned long end);
-void flush_cache_page(struct vm_area_struct *vma, unsigned long addr,
-                     unsigned long pfn);
-void flush_dcache_page(struct page *pg);
-
-#define flush_dcache_mmap_lock(mapping)                do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
-
-void flush_icache_range(unsigned long start, unsigned long end);
-void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
-                            unsigned long addr, int len);
-
-#define flush_icache_page(vma,pg)              do { } while (0)
-
-/* Initialization of P3 area for copy_user_page */
-void p3_cache_init(void);
-
-#define PG_mapped      PG_arch_1
-
-#endif /* __ASM_CPU_SH4_CACHEFLUSH_H */
index 0ed5178..f0886bc 100644 (file)
@@ -16,7 +16,8 @@
 #define DMAE0_IRQ      38
 #define SH_DMAC_BASE0  0xFF608020
 #define SH_DMARS_BASE  0xFF609000
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7724)
 #define DMTE0_IRQ      48      /* DMAC0A*/
 #define DMTE4_IRQ      40      /* DMAC0B */
 #define DMTE6_IRQ      42
index ccf1d99..e1e9096 100644 (file)
 #define MSTPCR0                        0xa4150030
 #define MSTPCR1                        0xa4150034
 #define MSTPCR2                        0xa4150038
+#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
+#define        FRQCR                   0xffc80000
+#define        OSCCR                   0xffc80018
+#define        PLLCR                   0xffc80024
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
       defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define        FRQCR                   0xffc80000
index 738ea43..4856040 100644 (file)
@@ -221,4 +221,18 @@ enum {
        GPIO_FN_KEYOUT3, GPIO_FN_KEYOUT4_IN6, GPIO_FN_KEYOUT5_IN5,
 };
 
+enum {
+       HWBLK_UNKNOWN = 0,
+       HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_URAM, HWBLK_XYMEM,
+       HWBLK_INTC, HWBLK_DMAC, HWBLK_SHYWAY, HWBLK_HUDI,
+       HWBLK_UBC, HWBLK_TMU, HWBLK_CMT, HWBLK_RWDT, HWBLK_FLCTL,
+       HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2, HWBLK_SIO,
+       HWBLK_SIOF0, HWBLK_SIOF1, HWBLK_IIC, HWBLK_RTC,
+       HWBLK_TPU, HWBLK_IRDA, HWBLK_SDHI, HWBLK_SIM, HWBLK_KEYSC,
+       HWBLK_TSIF, HWBLK_USBF, HWBLK_2DG, HWBLK_SIU, HWBLK_VOU,
+       HWBLK_JPU, HWBLK_BEU, HWBLK_CEU, HWBLK_VEU, HWBLK_VPU,
+       HWBLK_LCDC,
+       HWBLK_NR,
+};
+
 #endif /* __ASM_SH7722_H__ */
index 14c8ca9..9b36fae 100644 (file)
@@ -265,4 +265,21 @@ enum {
        GPIO_FN_IDEA1, GPIO_FN_IDEA0,
 };
 
+enum {
+       HWBLK_UNKNOWN = 0,
+       HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_L2C, HWBLK_ILMEM, HWBLK_FPU,
+       HWBLK_INTC, HWBLK_DMAC0, HWBLK_SHYWAY,
+       HWBLK_HUDI, HWBLK_DBG, HWBLK_UBC, HWBLK_SUBC,
+       HWBLK_TMU0, HWBLK_CMT, HWBLK_RWDT, HWBLK_DMAC1, HWBLK_TMU1,
+       HWBLK_FLCTL,
+       HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2,
+       HWBLK_SCIF3, HWBLK_SCIF4, HWBLK_SCIF5,
+       HWBLK_MSIOF0, HWBLK_MSIOF1, HWBLK_MERAM, HWBLK_IIC, HWBLK_RTC,
+       HWBLK_ATAPI, HWBLK_ADC, HWBLK_TPU, HWBLK_IRDA, HWBLK_TSIF, HWBLK_ICB,
+       HWBLK_SDHI0, HWBLK_SDHI1, HWBLK_KEYSC, HWBLK_USB,
+       HWBLK_2DG, HWBLK_SIU, HWBLK_VEU2H1, HWBLK_VOU, HWBLK_BEU, HWBLK_CEU,
+       HWBLK_VEU2H0, HWBLK_VPU, HWBLK_LCDC,
+       HWBLK_NR,
+};
+
 #endif /* __ASM_SH7723_H__ */
index 66fd118..0cd1f71 100644 (file)
@@ -266,4 +266,21 @@ enum {
        GPIO_FN_INTC_IRQ1, GPIO_FN_INTC_IRQ0,
 };
 
+enum {
+       HWBLK_UNKNOWN = 0,
+       HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_RSMEM, HWBLK_ILMEM, HWBLK_L2C,
+       HWBLK_FPU, HWBLK_INTC, HWBLK_DMAC0, HWBLK_SHYWAY,
+       HWBLK_HUDI, HWBLK_DBG, HWBLK_UBC,
+       HWBLK_TMU0, HWBLK_CMT, HWBLK_RWDT, HWBLK_DMAC1, HWBLK_TMU1,
+       HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2, HWBLK_SCIF3,
+       HWBLK_SCIF4, HWBLK_SCIF5, HWBLK_MSIOF0, HWBLK_MSIOF1,
+       HWBLK_KEYSC, HWBLK_RTC, HWBLK_IIC0, HWBLK_IIC1,
+       HWBLK_MMC, HWBLK_ETHER, HWBLK_ATAPI, HWBLK_TPU, HWBLK_IRDA,
+       HWBLK_TSIF, HWBLK_USB1, HWBLK_USB0, HWBLK_2DG,
+       HWBLK_SDHI0, HWBLK_SDHI1, HWBLK_VEU1, HWBLK_CEU1, HWBLK_BEU1,
+       HWBLK_2DDMAC, HWBLK_SPU, HWBLK_JPU, HWBLK_VOU,
+       HWBLK_BEU0, HWBLK_CEU0, HWBLK_VEU0, HWBLK_VPU, HWBLK_LCDC,
+       HWBLK_NR,
+};
+
 #endif /* __ASM_SH7724_H__ */
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7757.h b/arch/sh/include/cpu-sh4/cpu/sh7757.h
new file mode 100644 (file)
index 0000000..f4d267e
--- /dev/null
@@ -0,0 +1,243 @@
+#ifndef __ASM_SH7757_H__
+#define __ASM_SH7757_H__
+
+enum {
+       /* PTA */
+       GPIO_PTA7, GPIO_PTA6, GPIO_PTA5, GPIO_PTA4,
+       GPIO_PTA3, GPIO_PTA2, GPIO_PTA1, GPIO_PTA0,
+
+       /* PTB */
+       GPIO_PTB7, GPIO_PTB6, GPIO_PTB5, GPIO_PTB4,
+       GPIO_PTB3, GPIO_PTB2, GPIO_PTB1, GPIO_PTB0,
+
+       /* PTC */
+       GPIO_PTC7, GPIO_PTC6, GPIO_PTC5, GPIO_PTC4,
+       GPIO_PTC3, GPIO_PTC2, GPIO_PTC1, GPIO_PTC0,
+
+       /* PTD */
+       GPIO_PTD7, GPIO_PTD6, GPIO_PTD5, GPIO_PTD4,
+       GPIO_PTD3, GPIO_PTD2, GPIO_PTD1, GPIO_PTD0,
+
+       /* PTE */
+       GPIO_PTE7, GPIO_PTE6, GPIO_PTE5, GPIO_PTE4,
+       GPIO_PTE3, GPIO_PTE2, GPIO_PTE1, GPIO_PTE0,
+
+       /* PTF */
+       GPIO_PTF7, GPIO_PTF6, GPIO_PTF5, GPIO_PTF4,
+       GPIO_PTF3, GPIO_PTF2, GPIO_PTF1, GPIO_PTF0,
+
+       /* PTG */
+       GPIO_PTG7, GPIO_PTG6, GPIO_PTG5, GPIO_PTG4,
+       GPIO_PTG3, GPIO_PTG2, GPIO_PTG1, GPIO_PTG0,
+
+       /* PTH */
+       GPIO_PTH7, GPIO_PTH6, GPIO_PTH5, GPIO_PTH4,
+       GPIO_PTH3, GPIO_PTH2, GPIO_PTH1, GPIO_PTH0,
+
+       /* PTI */
+       GPIO_PTI7, GPIO_PTI6, GPIO_PTI5, GPIO_PTI4,
+       GPIO_PTI3, GPIO_PTI2, GPIO_PTI1, GPIO_PTI0,
+
+       /* PTJ */
+       GPIO_PTJ7, GPIO_PTJ6, GPIO_PTJ5, GPIO_PTJ4,
+       GPIO_PTJ3, GPIO_PTJ2, GPIO_PTJ1, GPIO_PTJ0,
+
+       /* PTK */
+       GPIO_PTK7, GPIO_PTK6, GPIO_PTK5, GPIO_PTK4,
+       GPIO_PTK3, GPIO_PTK2, GPIO_PTK1, GPIO_PTK0,
+
+       /* PTL */
+       GPIO_PTL7, GPIO_PTL6, GPIO_PTL5, GPIO_PTL4,
+       GPIO_PTL3, GPIO_PTL2, GPIO_PTL1, GPIO_PTL0,
+
+       /* PTM */
+                  GPIO_PTM6, GPIO_PTM5, GPIO_PTM4,
+       GPIO_PTM3, GPIO_PTM2, GPIO_PTM1, GPIO_PTM0,
+
+       /* PTN */
+       GPIO_PTN7, GPIO_PTN6, GPIO_PTN5, GPIO_PTN4,
+       GPIO_PTN3, GPIO_PTN2, GPIO_PTN1, GPIO_PTN0,
+
+       /* PTO */
+       GPIO_PTO7, GPIO_PTO6, GPIO_PTO5, GPIO_PTO4,
+       GPIO_PTO3, GPIO_PTO2, GPIO_PTO1, GPIO_PTO0,
+
+       /* PTP */
+                  GPIO_PTP6, GPIO_PTP5, GPIO_PTP4,
+       GPIO_PTP3, GPIO_PTP2, GPIO_PTP1, GPIO_PTP0,
+
+       /* PTQ */
+                  GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4,
+       GPIO_PTQ3, GPIO_PTQ2, GPIO_PTQ1, GPIO_PTQ0,
+
+       /* PTR */
+       GPIO_PTR7, GPIO_PTR6, GPIO_PTR5, GPIO_PTR4,
+       GPIO_PTR3, GPIO_PTR2, GPIO_PTR1, GPIO_PTR0,
+
+       /* PTS */
+       GPIO_PTS7, GPIO_PTS6, GPIO_PTS5, GPIO_PTS4,
+       GPIO_PTS3, GPIO_PTS2, GPIO_PTS1, GPIO_PTS0,
+
+       /* PTT */
+                             GPIO_PTT5, GPIO_PTT4,
+       GPIO_PTT3, GPIO_PTT2, GPIO_PTT1, GPIO_PTT0,
+
+       /* PTU */
+       GPIO_PTU7, GPIO_PTU6, GPIO_PTU5, GPIO_PTU4,
+       GPIO_PTU3, GPIO_PTU2, GPIO_PTU1, GPIO_PTU0,
+
+       /* PTV */
+       GPIO_PTV7, GPIO_PTV6, GPIO_PTV5, GPIO_PTV4,
+       GPIO_PTV3, GPIO_PTV2, GPIO_PTV1, GPIO_PTV0,
+
+       /* PTW */
+       GPIO_PTW7, GPIO_PTW6, GPIO_PTW5, GPIO_PTW4,
+       GPIO_PTW3, GPIO_PTW2, GPIO_PTW1, GPIO_PTW0,
+
+       /* PTX */
+       GPIO_PTX7, GPIO_PTX6, GPIO_PTX5, GPIO_PTX4,
+       GPIO_PTX3, GPIO_PTX2, GPIO_PTX1, GPIO_PTX0,
+
+       /* PTY */
+       GPIO_PTY7, GPIO_PTY6, GPIO_PTY5, GPIO_PTY4,
+       GPIO_PTY3, GPIO_PTY2, GPIO_PTY1, GPIO_PTY0,
+
+       /* PTZ */
+       GPIO_PTZ7, GPIO_PTZ6, GPIO_PTZ5, GPIO_PTZ4,
+       GPIO_PTZ3, GPIO_PTZ2, GPIO_PTZ1, GPIO_PTZ0,
+
+
+       /* PTA (mobule: LBSC, CPG, LPC) */
+       GPIO_FN_BS,     GPIO_FN_RDWR,   GPIO_FN_WE1,    GPIO_FN_RDY,
+       GPIO_FN_MD10,   GPIO_FN_MD9,    GPIO_FN_MD8,
+       GPIO_FN_LGPIO7, GPIO_FN_LGPIO6, GPIO_FN_LGPIO5, GPIO_FN_LGPIO4,
+       GPIO_FN_LGPIO3, GPIO_FN_LGPIO2, GPIO_FN_LGPIO1, GPIO_FN_LGPIO0,
+
+       /* PTB (mobule: LBSC, EtherC, SIM, LPC) */
+       GPIO_FN_D15,    GPIO_FN_D14,    GPIO_FN_D13,    GPIO_FN_D12,
+       GPIO_FN_D11,    GPIO_FN_D10,    GPIO_FN_D9,     GPIO_FN_D8,
+       GPIO_FN_ET0_MDC,                GPIO_FN_ET0_MDIO,
+       GPIO_FN_ET1_MDC,                GPIO_FN_ET1_MDIO,
+       GPIO_FN_SIM_D,  GPIO_FN_SIM_CLK,                GPIO_FN_SIM_RST,
+       GPIO_FN_WPSZ1,  GPIO_FN_WPSZ0,  GPIO_FN_FWID,   GPIO_FN_FLSHSZ,
+       GPIO_FN_LPC_SPIEN,              GPIO_FN_BASEL,
+
+       /* PTC (mobule: SD) */
+       GPIO_FN_SD_WP,  GPIO_FN_SD_CD,  GPIO_FN_SD_CLK, GPIO_FN_SD_CMD,
+       GPIO_FN_SD_D3,  GPIO_FN_SD_D2,  GPIO_FN_SD_D1,  GPIO_FN_SD_D0,
+
+       /* PTD (mobule: INTC, SPI0, LBSC, CPG, ADC) */
+       GPIO_FN_IRQ7,   GPIO_FN_IRQ6,   GPIO_FN_IRQ5,   GPIO_FN_IRQ4,
+       GPIO_FN_IRQ3,   GPIO_FN_IRQ2,   GPIO_FN_IRQ1,   GPIO_FN_IRQ0,
+       GPIO_FN_MD6,    GPIO_FN_MD5,    GPIO_FN_MD3,    GPIO_FN_MD2,
+       GPIO_FN_MD1,    GPIO_FN_MD0,    GPIO_FN_ADTRG1, GPIO_FN_ADTRG0,
+
+       /* PTE (mobule: EtherC) */
+       GPIO_FN_ET0_CRS_DV,             GPIO_FN_ET0_TXD1,
+       GPIO_FN_ET0_TXD0,               GPIO_FN_ET0_TX_EN,
+       GPIO_FN_ET0_REF_CLK,            GPIO_FN_ET0_RXD1,
+       GPIO_FN_ET0_RXD0,               GPIO_FN_ET0_RX_ER,
+
+       /* PTF (mobule: EtherC) */
+       GPIO_FN_ET1_CRS_DV,             GPIO_FN_ET1_TXD1,
+       GPIO_FN_ET1_TXD0,               GPIO_FN_ET1_TX_EN,
+       GPIO_FN_ET1_REF_CLK,            GPIO_FN_ET1_RXD1,
+       GPIO_FN_ET1_RXD0,               GPIO_FN_ET1_RX_ER,
+
+       /* PTG (mobule: SYSTEM, PWMX, LPC) */
+       GPIO_FN_STATUS0,                GPIO_FN_STATUS1,
+       GPIO_FN_PWX0,   GPIO_FN_PWX1,   GPIO_FN_PWX2,   GPIO_FN_PWX3,
+       GPIO_FN_SERIRQ, GPIO_FN_CLKRUN, GPIO_FN_LPCPD,  GPIO_FN_LDRQ,
+
+       /* PTH (mobule: TMU, SCIF234, SPI1, SPI0) */
+       GPIO_FN_TCLK,   GPIO_FN_RXD4,   GPIO_FN_TXD4,
+       GPIO_FN_SP1_MOSI,               GPIO_FN_SP1_MISO,
+       GPIO_FN_SP1_SCK,                GPIO_FN_SP1_SCK_FB,
+       GPIO_FN_SP1_SS0,                GPIO_FN_SP1_SS1,
+       GPIO_FN_SP0_SS1,
+
+       /* PTI (mobule: INTC) */
+       GPIO_FN_IRQ15,  GPIO_FN_IRQ14,  GPIO_FN_IRQ13,  GPIO_FN_IRQ12,
+       GPIO_FN_IRQ11,  GPIO_FN_IRQ10,  GPIO_FN_IRQ9,   GPIO_FN_IRQ8,
+
+       /* PTJ (mobule: SCIF234, SERMUX) */
+       GPIO_FN_RXD3,   GPIO_FN_TXD3,   GPIO_FN_RXD2,   GPIO_FN_TXD2,
+       GPIO_FN_COM1_TXD,               GPIO_FN_COM1_RXD,
+       GPIO_FN_COM1_RTS,               GPIO_FN_COM1_CTS,
+
+       /* PTK (mobule: SERMUX) */
+       GPIO_FN_COM2_TXD,               GPIO_FN_COM2_RXD,
+       GPIO_FN_COM2_RTS,               GPIO_FN_COM2_CTS,
+       GPIO_FN_COM2_DTR,               GPIO_FN_COM2_DSR,
+       GPIO_FN_COM2_DCD,               GPIO_FN_COM2_RI,
+
+       /* PTL (mobule: SERMUX) */
+       GPIO_FN_RAC_TXD,                GPIO_FN_RAC_RXD,
+       GPIO_FN_RAC_RTS,                GPIO_FN_RAC_CTS,
+       GPIO_FN_RAC_DTR,                GPIO_FN_RAC_DSR,
+       GPIO_FN_RAC_DCD,                GPIO_FN_RAC_RI,
+
+       /* PTM (mobule: IIC, LPC) */
+       GPIO_FN_SDA6,   GPIO_FN_SCL6,   GPIO_FN_SDA7,   GPIO_FN_SCL7,
+       GPIO_FN_WP,     GPIO_FN_FMS0,   GPIO_FN_FMS1,
+
+       /* PTN (mobule: SCIF234, EVC) */
+       GPIO_FN_SCK2,   GPIO_FN_RTS4,   GPIO_FN_RTS3,   GPIO_FN_RTS2,
+       GPIO_FN_CTS4,   GPIO_FN_CTS3,   GPIO_FN_CTS2,
+       GPIO_FN_EVENT7, GPIO_FN_EVENT6, GPIO_FN_EVENT5, GPIO_FN_EVENT4,
+       GPIO_FN_EVENT3, GPIO_FN_EVENT2, GPIO_FN_EVENT1, GPIO_FN_EVENT0,
+
+       /* PTO (mobule: SGPIO) */
+       GPIO_FN_SGPIO0_CLK,             GPIO_FN_SGPIO0_LOAD,
+       GPIO_FN_SGPIO0_DI,              GPIO_FN_SGPIO0_DO,
+       GPIO_FN_SGPIO1_CLK,             GPIO_FN_SGPIO1_LOAD,
+       GPIO_FN_SGPIO1_DI,              GPIO_FN_SGPIO1_DO,
+
+       /* PTP (mobule: JMC, SCIF234) */
+       GPIO_FN_JMCTCK, GPIO_FN_JMCTMS, GPIO_FN_JMCTDO, GPIO_FN_JMCTDI,
+       GPIO_FN_JMCRST, GPIO_FN_SCK4,   GPIO_FN_SCK3,
+
+       /* PTQ (mobule: LPC) */
+       GPIO_FN_LAD3,   GPIO_FN_LAD2,   GPIO_FN_LAD1,   GPIO_FN_LAD0,
+       GPIO_FN_LFRAME, GPIO_FN_LRESET, GPIO_FN_LCLK,
+
+       /* PTR (mobule: GRA, IIC) */
+       GPIO_FN_DDC3,   GPIO_FN_DDC2,
+       GPIO_FN_SDA8,   GPIO_FN_SCL8,   GPIO_FN_SDA2,   GPIO_FN_SCL2,
+       GPIO_FN_SDA1,   GPIO_FN_SCL1,   GPIO_FN_SDA0,   GPIO_FN_SCL0,
+
+       /* PTS (mobule: GRA, IIC) */
+       GPIO_FN_DDC1,   GPIO_FN_DDC0,
+       GPIO_FN_SDA9,   GPIO_FN_SCL9,   GPIO_FN_SDA5,   GPIO_FN_SCL5,
+       GPIO_FN_SDA4,   GPIO_FN_SCL4,   GPIO_FN_SDA3,   GPIO_FN_SCL3,
+
+       /* PTT (mobule: SYSTEM, PWMX) */
+       GPIO_FN_AUDSYNC,                GPIO_FN_AUDCK,
+       GPIO_FN_AUDATA3,                GPIO_FN_AUDATA2,
+       GPIO_FN_AUDATA1,                GPIO_FN_AUDATA0,
+       GPIO_FN_PWX7,   GPIO_FN_PWX6,   GPIO_FN_PWX5,   GPIO_FN_PWX4,
+
+       /* PTU (mobule: LBSC, DMAC) */
+       GPIO_FN_CS6,    GPIO_FN_CS5,    GPIO_FN_CS4,    GPIO_FN_CS0,
+       GPIO_FN_RD,     GPIO_FN_WE0,    GPIO_FN_A25,    GPIO_FN_A24,
+       GPIO_FN_DREQ0,  GPIO_FN_DACK0,
+
+       /* PTV (mobule: LBSC, DMAC) */
+       GPIO_FN_A23,    GPIO_FN_A22,    GPIO_FN_A21,    GPIO_FN_A20,
+       GPIO_FN_A19,    GPIO_FN_A18,    GPIO_FN_A17,    GPIO_FN_A16,
+       GPIO_FN_TEND0,  GPIO_FN_DREQ1,  GPIO_FN_DACK1,  GPIO_FN_TEND1,
+
+       /* PTW (mobule: LBSC) */
+       GPIO_FN_A15,    GPIO_FN_A14,    GPIO_FN_A13,    GPIO_FN_A12,
+       GPIO_FN_A11,    GPIO_FN_A10,    GPIO_FN_A9,     GPIO_FN_A8,
+
+       /* PTX (mobule: LBSC) */
+       GPIO_FN_A7,     GPIO_FN_A6,     GPIO_FN_A5,     GPIO_FN_A4,
+       GPIO_FN_A3,     GPIO_FN_A2,     GPIO_FN_A1,     GPIO_FN_A0,
+
+       /* PTY (mobule: LBSC) */
+       GPIO_FN_D7,     GPIO_FN_D6,     GPIO_FN_D5,     GPIO_FN_D4,
+       GPIO_FN_D3,     GPIO_FN_D2,     GPIO_FN_D1,     GPIO_FN_D0,
+};
+
+#endif /* __ASM_SH7757_H__ */
diff --git a/arch/sh/include/cpu-sh5/cpu/cacheflush.h b/arch/sh/include/cpu-sh5/cpu/cacheflush.h
deleted file mode 100644 (file)
index 5a11f0b..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef __ASM_SH_CPU_SH5_CACHEFLUSH_H
-#define __ASM_SH_CPU_SH5_CACHEFLUSH_H
-
-#ifndef __ASSEMBLY__
-
-struct vm_area_struct;
-struct page;
-struct mm_struct;
-
-extern void flush_cache_all(void);
-extern void flush_cache_mm(struct mm_struct *mm);
-extern void flush_cache_sigtramp(unsigned long vaddr);
-extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-                             unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
-extern void flush_dcache_page(struct page *pg);
-extern void flush_icache_range(unsigned long start, unsigned long end);
-extern void flush_icache_user_range(struct vm_area_struct *vma,
-                                   struct page *page, unsigned long addr,
-                                   int len);
-
-#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
-
-#define flush_dcache_mmap_lock(mapping)                do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
-
-#define flush_icache_page(vma, page)   do { } while (0)
-void p3_cache_init(void);
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_SH_CPU_SH5_CACHEFLUSH_H */
-
diff --git a/arch/sh/include/mach-common/mach/migor.h b/arch/sh/include/mach-common/mach/migor.h
deleted file mode 100644 (file)
index e451f02..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef __ASM_SH_MIGOR_H
-#define __ASM_SH_MIGOR_H
-
-/*
- * linux/include/asm-sh/migor.h
- *
- * Copyright (C) 2008 Renesas Solutions
- *
- * Portions Copyright (C) 2007 Nobuhiro Iwamatsu
- *
- * 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.
- *
- */
-#include <asm/addrspace.h>
-
-/* GPIO */
-#define PORT_PACR 0xa4050100
-#define PORT_PDCR 0xa4050106
-#define PORT_PECR 0xa4050108
-#define PORT_PHCR 0xa405010e
-#define PORT_PJCR 0xa4050110
-#define PORT_PKCR 0xa4050112
-#define PORT_PLCR 0xa4050114
-#define PORT_PMCR 0xa4050116
-#define PORT_PRCR 0xa405011c
-#define PORT_PTCR 0xa4050140
-#define PORT_PUCR 0xa4050142
-#define PORT_PVCR 0xa4050144
-#define PORT_PWCR 0xa4050146
-#define PORT_PXCR 0xa4050148
-#define PORT_PYCR 0xa405014a
-#define PORT_PZCR 0xa405014c
-#define PORT_PADR 0xa4050120
-#define PORT_PHDR 0xa405012e
-#define PORT_PTDR 0xa4050160
-#define PORT_PWDR 0xa4050166
-
-#define PORT_HIZCRA 0xa4050158
-#define PORT_HIZCRC 0xa405015c
-
-#define PORT_MSELCRB 0xa4050182
-
-#define PORT_PSELA 0xa405014e
-#define PORT_PSELB 0xa4050150
-#define PORT_PSELC 0xa4050152
-#define PORT_PSELD 0xa4050154
-#define PORT_PSELE 0xa4050156
-
-#define PORT_HIZCRA 0xa4050158
-#define PORT_HIZCRB 0xa405015a
-#define PORT_HIZCRC 0xa405015c
-
-#define BSC_CS4BCR 0xfec10010
-#define BSC_CS6ABCR 0xfec1001c
-#define BSC_CS4WCR 0xfec10030
-
-#include <video/sh_mobile_lcdc.h>
-
-int migor_lcd_qvga_setup(void *board_data, void *sys_ops_handle,
-                        struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
-
-#endif /* __ASM_SH_MIGOR_H */
diff --git a/arch/sh/include/mach-common/mach/romimage.h b/arch/sh/include/mach-common/mach/romimage.h
new file mode 100644 (file)
index 0000000..267e241
--- /dev/null
@@ -0,0 +1 @@
+/* do nothing here by default */
index 90011d4..1292ae5 100644 (file)
@@ -35,6 +35,8 @@
 #define PCA9564_ADDR           0x06000000      /* I2C */
 #define PCA9564_SIZE           0x00000100
 
+#define PCA9564_PROTO_32BIT_ADDR       0x14000000
+
 #define SM107_MEM_ADDR         0x10000000
 #define SM107_MEM_SIZE         0x00e00000
 #define SM107_REG_ADDR         0x13e00000
diff --git a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
new file mode 100644 (file)
index 0000000..174374e
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __ASM_SH_KFR2R09_H
+#define __ASM_SH_KFR2R09_H
+
+#include <video/sh_mobile_lcdc.h>
+
+#ifdef CONFIG_FB_SH_MOBILE_LCDC
+void kfr2r09_lcd_on(void *board_data);
+void kfr2r09_lcd_off(void *board_data);
+int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle,
+                     struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
+#else
+static inline void kfr2r09_lcd_on(void *board_data) {}
+static inline void kfr2r09_lcd_off(void *board_data) {}
+static inline int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle,
+                                   struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
+{
+       return -ENODEV;
+}
+#endif
+
+#endif /* __ASM_SH_KFR2R09_H */
diff --git a/arch/sh/include/mach-kfr2r09/mach/partner-jet-setup.txt b/arch/sh/include/mach-kfr2r09/mach/partner-jet-setup.txt
new file mode 100644 (file)
index 0000000..a19ac31
--- /dev/null
@@ -0,0 +1,141 @@
+LIST "partner-jet-setup.txt - 20090729 Magnus Damm"
+LIST "set up enough of the kfr2r09 hardware to boot the kernel"
+
+LIST "zImage (RAM boot)"
+LIST "This script can be used to boot the kernel from RAM via JTAG:"
+LIST "> < partner-jet-setup.txt"
+LIST "> RD zImage, 0xa8800000"
+LIST "> G=0xa8800000"
+
+LIST "romImage (Flash boot)"
+LIST "Use the following command to burn the zImage to flash via JTAG:"
+LIST "> RD romImage, 0"
+
+LIST "--------------------------------"
+
+LIST "disable watchdog"
+EW 0xa4520004, 0xa507
+
+LIST "invalidate instruction cache"
+ED 0xff00001c, 0x00000800
+
+LIST "invalidate TLBs"
+ED 0xff000010, 0x00000004
+
+LIST "select mode for cs5 + cs6"
+ED 0xff800020, 0xa5a50001
+ED 0xfec10000, 0x0000001b
+
+LIST "setup clocks"
+ED 0xa4150004, 0x00000050
+ED 0xa4150000, 0x91053508
+WAIT 1
+ED 0xa4150050, 0x00000340
+ED 0xa4150024, 0x00005000
+
+LIST "setup pins"
+EB 0xa4050120, 0x00
+EB 0xa4050122, 0x00
+EB 0xa4050124, 0x00
+EB 0xa4050126, 0x00
+EB 0xa4050128, 0xA0
+EB 0xa405012A, 0x10
+EB 0xa405012C, 0x00
+EB 0xa405012E, 0x00
+EB 0xa4050130, 0x00
+EB 0xa4050132, 0x00
+EB 0xa4050134, 0x01
+EB 0xa4050136, 0x40
+EB 0xa4050138, 0x00
+EB 0xa405013A, 0x00
+EB 0xa405013C, 0x00
+EB 0xa405013E, 0x20
+EB 0xa4050160, 0x00
+EB 0xa4050162, 0x40
+EB 0xa4050164, 0x03
+EB 0xa4050166, 0x00
+EB 0xa4050168, 0x00
+EB 0xa405016A, 0x00
+EB 0xa405016C, 0x00
+
+EW 0xa405014E, 0x5660
+EW 0xa4050150, 0x0145
+EW 0xa4050152, 0x1550
+EW 0xa4050154, 0x0200
+EW 0xa4050156, 0x0040
+
+EW 0xa4050158, 0x0000
+EW 0xa405015a, 0x0000
+EW 0xa405015c, 0x0000
+EW 0xa405015e, 0x0000
+
+EW 0xa4050180, 0x0000
+EW 0xa4050182, 0x8002
+EW 0xa4050184, 0x0000
+
+EW 0xa405018a, 0x9991
+EW 0xa405018c, 0x8011
+EW 0xa405018e, 0x9550
+
+EW 0xa4050100, 0x0000
+EW 0xa4050102, 0x5540
+EW 0xa4050104, 0x0000
+EW 0xa4050106, 0x0000
+EW 0xa4050108, 0x4550
+EW 0xa405010a, 0x0130
+EW 0xa405010c, 0x0555
+EW 0xa405010e, 0x0000
+EW 0xa4050110, 0x0000
+EW 0xa4050112, 0xAAA8
+EW 0xa4050114, 0x8305
+EW 0xa4050116, 0x10F0
+EW 0xa4050118, 0x0F50
+EW 0xa405011a, 0x0000
+EW 0xa405011c, 0x0000
+EW 0xa405011e, 0x0555
+EW 0xa4050140, 0x0000
+EW 0xa4050142, 0x5141
+EW 0xa4050144, 0x5005
+EW 0xa4050146, 0xAAA9
+EW 0xa4050148, 0xFAA9
+EW 0xa405014a, 0x3000
+EW 0xa405014c, 0x0000
+
+LIST "setup sdram"
+ED 0xFD000108, 0x40000301
+ED 0xFD000020, 0x011B0002
+ED 0xFD000030, 0x03060E02
+ED 0xFD000034, 0x01020102
+ED 0xFD000038, 0x01090406
+ED 0xFD000008, 0x00000004
+ED 0xFD000040, 0x00000001
+ED 0xFD000040, 0x00000000
+ED 0xFD000018, 0x00000001
+
+WAIT 1
+
+ED 0xFD000014, 0x00000002
+ED 0xFD000060, 0x00000032
+ED 0xFD000060, 0x00020000
+ED 0xFD000014, 0x00000004
+ED 0xFD000014, 0x00000004
+ED 0xFD000010, 0x00000001
+ED 0xFD000044, 0x000004AF
+ED 0xFD000048, 0x20CF0037
+
+LIST "read 16 bytes from sdram"
+DD 0xa8000000, 0xa8000000, 1
+DD 0xa8000004, 0xa8000004, 1
+DD 0xa8000008, 0xa8000008, 1
+DD 0xa800000c, 0xa800000c, 1
+
+ED 0xFD000014, 0x00000002
+ED 0xFD000014, 0x00000004
+ED 0xFD000108, 0x40000300
+ED 0xFD000040, 0x00010000
+
+LIST "write to internal ram"
+ED 0xfd8007fc, 0
+
+LIST "setup cache"
+ED 0xff00001c, 0x0000090b
diff --git a/arch/sh/include/mach-kfr2r09/mach/romimage.h b/arch/sh/include/mach-kfr2r09/mach/romimage.h
new file mode 100644 (file)
index 0000000..39ee794
--- /dev/null
@@ -0,0 +1,88 @@
+/* kfr2r09 board specific boot code:
+ * converts the "partner-jet-script.txt" script into assembly
+ * the assembly code is the first code to be executed in the romImage
+ */
+
+/* The LIST command is used to include comments in the script */
+.macro LIST comment
+.endm
+
+/* The ED command is used to write a 32-bit word */
+.macro  ED, addr, data
+        mov.l 1f ,r1
+        mov.l 2f ,r0
+        mov.l r0, @r1
+       bra 3f
+        nop
+       .align 2
+1:     .long \addr
+2:     .long \data
+3:
+.endm
+
+/* The EW command is used to write a 16-bit word */
+.macro  EW, addr, data
+        mov.l 1f ,r1
+        mov.l 2f ,r0
+        mov.w r0, @r1
+       bra 3f
+        nop
+       .align 2
+1:     .long \addr
+2:     .long \data
+3:
+.endm
+
+/* The EB command is used to write an 8-bit word */
+.macro  EB, addr, data
+        mov.l 1f ,r1
+        mov.l 2f ,r0
+        mov.b r0, @r1
+       bra 3f
+        nop
+       .align 2
+1:     .long \addr
+2:     .long \data
+3:
+.endm
+
+/* The WAIT command is used to delay the execution */
+.macro  WAIT, time
+        mov.l  2f ,r3
+1:
+        nop
+        tst     r3, r3
+        bf/s    1b
+         dt      r3
+       bra     3f
+        nop
+       .align 2
+2:     .long \time * 100
+3:
+.endm
+
+/* The DD command is used to read a 32-bit word */
+.macro  DD, addr, addr2, nr
+        mov.l 1f ,r1
+        mov.l @r1, r0
+       bra 2f
+        nop
+       .align 2
+1:     .long \addr
+2:
+.endm
+
+#include "partner-jet-setup.txt"
+
+       /* execute icbi after enabling cache */
+       mov.l   1f, r0
+       icbi    @r0
+
+       /* jump to cached area */
+       mova    2f, r0
+       jmp     @r0
+        nop
+
+       .align 2
+1:     .long 0xa8000000
+2:
diff --git a/arch/sh/include/mach-migor/mach/migor.h b/arch/sh/include/mach-migor/mach/migor.h
new file mode 100644 (file)
index 0000000..cee6cb8
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __ASM_SH_MIGOR_H
+#define __ASM_SH_MIGOR_H
+
+#define PORT_MSELCRB 0xa4050182
+#define BSC_CS4BCR 0xfec10010
+#define BSC_CS6ABCR 0xfec1001c
+#define BSC_CS4WCR 0xfec10030
+
+#include <video/sh_mobile_lcdc.h>
+
+int migor_lcd_qvga_setup(void *board_data, void *sys_ops_handle,
+                        struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
+
+#endif /* __ASM_SH_MIGOR_H */
index 349d833..a2d0a40 100644 (file)
@@ -1,5 +1,41 @@
-ifeq ($(CONFIG_SUPERH32),y)
-include ${srctree}/arch/sh/kernel/Makefile_32
-else
-include ${srctree}/arch/sh/kernel/Makefile_64
+#
+# Makefile for the Linux/SuperH kernel.
+#
+
+extra-y        := head_$(BITS).o init_task.o vmlinux.lds
+
+ifdef CONFIG_FUNCTION_TRACER
+# Do not profile debug and lowlevel utilities
+CFLAGS_REMOVE_ftrace.o = -pg
 endif
+
+obj-y  := debugtraps.o dumpstack.o idle.o io.o io_generic.o irq.o      \
+          machvec.o nmi_debug.o process_$(BITS).o ptrace_$(BITS).o     \
+          setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o            \
+          syscalls_$(BITS).o time.o topology.o traps.o                 \
+          traps_$(BITS).o unwinder.o
+
+obj-y                          += cpu/
+obj-$(CONFIG_VSYSCALL)         += vsyscall/
+obj-$(CONFIG_SMP)              += smp.o
+obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
+obj-$(CONFIG_KGDB)             += kgdb.o
+obj-$(CONFIG_SH_CPU_FREQ)      += cpufreq.o
+obj-$(CONFIG_MODULES)          += sh_ksyms_$(BITS).o module.o
+obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
+obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
+obj-$(CONFIG_STACKTRACE)       += stacktrace.o
+obj-$(CONFIG_IO_TRAPPED)       += io_trapped.o
+obj-$(CONFIG_KPROBES)          += kprobes.o
+obj-$(CONFIG_GENERIC_GPIO)     += gpio.o
+obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o
+obj-$(CONFIG_FTRACE_SYSCALLS)  += ftrace.o
+obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
+obj-$(CONFIG_DUMP_CODE)                += disassemble.o
+obj-$(CONFIG_HIBERNATION)      += swsusp.o
+obj-$(CONFIG_DWARF_UNWINDER)   += dwarf.o
+
+obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += localtimer.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32
deleted file mode 100644 (file)
index 9411e3e..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Makefile for the Linux/SuperH kernel.
-#
-
-extra-y        := head_32.o init_task.o vmlinux.lds
-
-ifdef CONFIG_FUNCTION_TRACER
-# Do not profile debug and lowlevel utilities
-CFLAGS_REMOVE_ftrace.o = -pg
-endif
-
-obj-y  := debugtraps.o idle.o io.o io_generic.o irq.o                  \
-          machvec.o process_32.o ptrace_32.o setup.o signal_32.o       \
-          sys_sh.o sys_sh32.o syscalls_32.o time.o topology.o  \
-          traps.o traps_32.o
-
-obj-y                          += cpu/
-obj-$(CONFIG_VSYSCALL)         += vsyscall/
-obj-$(CONFIG_SMP)              += smp.o
-obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
-obj-$(CONFIG_KGDB)             += kgdb.o
-obj-$(CONFIG_SH_CPU_FREQ)      += cpufreq.o
-obj-$(CONFIG_MODULES)          += sh_ksyms_32.o module.o
-obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
-obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
-obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
-obj-$(CONFIG_STACKTRACE)       += stacktrace.o
-obj-$(CONFIG_IO_TRAPPED)       += io_trapped.o
-obj-$(CONFIG_KPROBES)          += kprobes.o
-obj-$(CONFIG_GENERIC_GPIO)     += gpio.o
-obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o
-obj-$(CONFIG_DUMP_CODE)                += disassemble.o
-obj-$(CONFIG_HIBERNATION)      += swsusp.o
-
-obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += localtimer.o
-
-EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64
deleted file mode 100644 (file)
index 67b9f6c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-extra-y        := head_64.o init_task.o vmlinux.lds
-
-obj-y  := debugtraps.o idle.o io.o io_generic.o irq.o machvec.o process_64.o \
-          ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \
-          syscalls_64.o time.o topology.o traps.o traps_64.o
-
-obj-y                          += cpu/
-obj-$(CONFIG_SMP)              += smp.o
-obj-$(CONFIG_SH_CPU_FREQ)      += cpufreq.o
-obj-$(CONFIG_MODULES)          += sh_ksyms_64.o module.o
-obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
-obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
-obj-$(CONFIG_STACKTRACE)       += stacktrace.o
-obj-$(CONFIG_IO_TRAPPED)       += io_trapped.o
-obj-$(CONFIG_GENERIC_GPIO)     += gpio.o
-
-obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += localtimer.o
-
-EXTRA_CFLAGS += -Werror
index 99aceb2..d218e80 100644 (file)
@@ -26,6 +26,7 @@ int main(void)
        DEFINE(TI_CPU,          offsetof(struct thread_info, cpu));
        DEFINE(TI_PRE_COUNT,    offsetof(struct thread_info, preempt_count));
        DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
+       DEFINE(TI_SIZE,         sizeof(struct thread_info));
 
 #ifdef CONFIG_HIBERNATION
        DEFINE(PBE_ADDRESS, offsetof(struct pbe, address));
index eecad7c..3d6b931 100644 (file)
@@ -19,4 +19,4 @@ obj-$(CONFIG_UBC_WAKEUP)      += ubc.o
 obj-$(CONFIG_SH_ADC)           += adc.o
 obj-$(CONFIG_SH_CLK_CPG)       += clock-cpg.o
 
-obj-y  += irq/ init.o clock.o
+obj-y  += irq/ init.o clock.o hwblk.o
diff --git a/arch/sh/kernel/cpu/hwblk.c b/arch/sh/kernel/cpu/hwblk.c
new file mode 100644 (file)
index 0000000..c0ad7d4
--- /dev/null
@@ -0,0 +1,155 @@
+#include <linux/clk.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <asm/suspend.h>
+#include <asm/hwblk.h>
+#include <asm/clock.h>
+
+static DEFINE_SPINLOCK(hwblk_lock);
+
+static void hwblk_area_mod_cnt(struct hwblk_info *info,
+                              int area, int counter, int value, int goal)
+{
+       struct hwblk_area *hap = info->areas + area;
+
+       hap->cnt[counter] += value;
+
+       if (hap->cnt[counter] != goal)
+               return;
+
+       if (hap->flags & HWBLK_AREA_FLAG_PARENT)
+               hwblk_area_mod_cnt(info, hap->parent, counter, value, goal);
+}
+
+
+static int __hwblk_mod_cnt(struct hwblk_info *info, int hwblk,
+                         int counter, int value, int goal)
+{
+       struct hwblk *hp = info->hwblks + hwblk;
+
+       hp->cnt[counter] += value;
+       if (hp->cnt[counter] == goal)
+               hwblk_area_mod_cnt(info, hp->area, counter, value, goal);
+
+       return hp->cnt[counter];
+}
+
+static void hwblk_mod_cnt(struct hwblk_info *info, int hwblk,
+                         int counter, int value, int goal)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hwblk_lock, flags);
+       __hwblk_mod_cnt(info, hwblk, counter, value, goal);
+       spin_unlock_irqrestore(&hwblk_lock, flags);
+}
+
+void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int counter)
+{
+       hwblk_mod_cnt(info, hwblk, counter, 1, 1);
+}
+
+void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int counter)
+{
+       hwblk_mod_cnt(info, hwblk, counter, -1, 0);
+}
+
+void hwblk_enable(struct hwblk_info *info, int hwblk)
+{
+       struct hwblk *hp = info->hwblks + hwblk;
+       unsigned long tmp;
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&hwblk_lock, flags);
+
+       ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, 1, 1);
+       if (ret == 1) {
+               tmp = __raw_readl(hp->mstp);
+               tmp &= ~(1 << hp->bit);
+               __raw_writel(tmp, hp->mstp);
+       }
+
+       spin_unlock_irqrestore(&hwblk_lock, flags);
+}
+
+void hwblk_disable(struct hwblk_info *info, int hwblk)
+{
+       struct hwblk *hp = info->hwblks + hwblk;
+       unsigned long tmp;
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&hwblk_lock, flags);
+
+       ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, -1, 0);
+       if (ret == 0) {
+               tmp = __raw_readl(hp->mstp);
+               tmp |= 1 << hp->bit;
+               __raw_writel(tmp, hp->mstp);
+       }
+
+       spin_unlock_irqrestore(&hwblk_lock, flags);
+}
+
+struct hwblk_info *hwblk_info;
+
+int __init hwblk_register(struct hwblk_info *info)
+{
+       hwblk_info = info;
+       return 0;
+}
+
+int __init __weak arch_hwblk_init(void)
+{
+       return 0;
+}
+
+int __weak arch_hwblk_sleep_mode(void)
+{
+       return SUSP_SH_SLEEP;
+}
+
+int __init hwblk_init(void)
+{
+       return arch_hwblk_init();
+}
+
+/* allow clocks to enable and disable hardware blocks */
+static int sh_hwblk_clk_enable(struct clk *clk)
+{
+       if (!hwblk_info)
+               return -ENOENT;
+
+       hwblk_enable(hwblk_info, clk->arch_flags);
+       return 0;
+}
+
+static void sh_hwblk_clk_disable(struct clk *clk)
+{
+       if (hwblk_info)
+               hwblk_disable(hwblk_info, clk->arch_flags);
+}
+
+static struct clk_ops sh_hwblk_clk_ops = {
+       .enable         = sh_hwblk_clk_enable,
+       .disable        = sh_hwblk_clk_disable,
+       .recalc         = followparent_recalc,
+};
+
+int __init sh_hwblk_clk_register(struct clk *clks, int nr)
+{
+       struct clk *clkp;
+       int ret = 0;
+       int k;
+
+       for (k = 0; !ret && (k < nr); k++) {
+               clkp = clks + k;
+               clkp->ops = &sh_hwblk_clk_ops;
+               ret |= clk_register(clkp);
+       }
+
+       return ret;
+}
index ad85421..e932ebe 100644 (file)
@@ -3,7 +3,7 @@
  *
  * CPU init code
  *
- * Copyright (C) 2002 - 2007  Paul Mundt
+ * Copyright (C) 2002 - 2009  Paul Mundt
  * Copyright (C) 2003  Richard Curnow
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -62,6 +62,37 @@ static void __init speculative_execution_init(void)
 #define speculative_execution_init()   do { } while (0)
 #endif
 
+#ifdef CONFIG_CPU_SH4A
+#define EXPMASK                        0xff2f0004
+#define EXPMASK_RTEDS          (1 << 0)
+#define EXPMASK_BRDSSLP                (1 << 1)
+#define EXPMASK_MMCAW          (1 << 4)
+
+static void __init expmask_init(void)
+{
+       unsigned long expmask = __raw_readl(EXPMASK);
+
+       /*
+        * Future proofing.
+        *
+        * Disable support for slottable sleep instruction
+        * and non-nop instructions in the rte delay slot.
+        */
+       expmask &= ~(EXPMASK_RTEDS | EXPMASK_BRDSSLP);
+
+       /*
+        * Enable associative writes to the memory-mapped cache array
+        * until the cache flush ops have been rewritten.
+        */
+       expmask |= EXPMASK_MMCAW;
+
+       __raw_writel(expmask, EXPMASK);
+       ctrl_barrier();
+}
+#else
+#define expmask_init() do { } while (0)
+#endif
+
 /* 2nd-level cache init */
 void __uses_jump_to_uncached __attribute__ ((weak)) l2_cache_init(void)
 {
@@ -268,11 +299,9 @@ asmlinkage void __init sh_cpu_init(void)
        cache_init();
 
        if (raw_smp_processor_id() == 0) {
-#ifdef CONFIG_MMU
                shm_align_mask = max_t(unsigned long,
                                       current_cpu_data.dcache.way_size - 1,
                                       PAGE_SIZE - 1);
-#endif
 
                /* Boot CPU sets the cache shape */
                detect_cache_shape();
@@ -321,4 +350,5 @@ asmlinkage void __init sh_cpu_init(void)
 #endif
 
        speculative_execution_init();
+       expmask_init();
 }
index 808d99a..c1508a9 100644 (file)
@@ -35,6 +35,7 @@ static void disable_ipr_irq(unsigned int irq)
        unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
        /* Set the priority in IPR to 0 */
        __raw_writew(__raw_readw(addr) & (0xffff ^ (0xf << p->shift)), addr);
+       (void)__raw_readw(addr);        /* Read back to flush write posting */
 }
 
 static void enable_ipr_irq(unsigned int irq)
index becc54c..c8a4331 100644 (file)
@@ -227,8 +227,9 @@ ENTRY(sh_bios_handler)
        mov.l   @r15+, r14
        add     #8,r15
        lds.l   @r15+, pr
+       mov.l   @r15+,r15
        rte
-        mov.l  @r15+,r15
+        nop
        .align  2
 1:     .long   gdb_vbr_vector
 #endif /* CONFIG_SH_STANDARD_BIOS */
index 5916d90..1db6d88 100644 (file)
@@ -29,6 +29,7 @@ int __init detect_cpu_and_cache_system(void)
         */
        boot_cpu_data.dcache.flags |= SH_CACHE_COMBINED;
        boot_cpu_data.icache = boot_cpu_data.dcache;
+       boot_cpu_data.family = CPU_FAMILY_SH2;
 
        return 0;
 }
index ab3903e..222742d 100644 (file)
@@ -176,8 +176,9 @@ ENTRY(sh_bios_handler)
        movml.l @r15+,r14
        add     #8,r15
        lds.l   @r15+, pr
+       mov.l   @r15+,r15
        rte
-        mov.l  @r15+,r15
+        nop
        .align  2
 1:     .long   gdb_vbr_vector
 #endif /* CONFIG_SH_STANDARD_BIOS */
index e098e2f..6825d65 100644 (file)
@@ -15,6 +15,8 @@
 
 int __init detect_cpu_and_cache_system(void)
 {
+       boot_cpu_data.family                    = CPU_FAMILY_SH2A;
+
        /* All SH-2A CPUs have support for 16 and 32-bit opcodes.. */
        boot_cpu_data.flags                     |= CPU_HAS_OP32;
 
index 3cb531f..0151933 100644 (file)
  *     syscall #
  *
  */
-#if defined(CONFIG_KGDB)
-NMI_VEC = 0x1c0                        ! Must catch early for debounce
-#endif
-
 /* Offsets to the stack */
 OFF_R0  =  0           /* Return value. New ABI also arg4 */
 OFF_R1  =  4           /* New ABI: arg5 */
@@ -71,7 +67,6 @@ OFF_PC  =  (16*4)
 OFF_SR =  (16*4+8)
 OFF_TRA        =  (16*4+6*4)
 
-
 #define k0     r0
 #define k1     r1
 #define k2     r2
@@ -113,34 +108,34 @@ OFF_TRA   =  (16*4+6*4)
 #if defined(CONFIG_MMU)
        .align  2
 ENTRY(tlb_miss_load)
-       bra     call_dpf
+       bra     call_handle_tlbmiss
         mov    #0, r5
 
        .align  2
 ENTRY(tlb_miss_store)
-       bra     call_dpf
+       bra     call_handle_tlbmiss
         mov    #1, r5
 
        .align  2
 ENTRY(initial_page_write)
-       bra     call_dpf
-        mov    #1, r5
+       bra     call_handle_tlbmiss
+        mov    #2, r5
 
        .align  2
 ENTRY(tlb_protection_violation_load)
-       bra     call_dpf
+       bra     call_do_page_fault
         mov    #0, r5
 
        .align  2
 ENTRY(tlb_protection_violation_store)
-       bra     call_dpf
+       bra     call_do_page_fault
         mov    #1, r5
 
-call_dpf:
+call_handle_tlbmiss:
+       setup_frame_reg
        mov.l   1f, r0
        mov     r5, r8
        mov.l   @r0, r6
-       mov     r6, r9
        mov.l   2f, r0
        sts     pr, r10
        jsr     @r0
@@ -151,16 +146,25 @@ call_dpf:
         lds    r10, pr
        rts
         nop
-0:     mov.l   3f, r0
-       mov     r9, r6
+0:
        mov     r8, r5
+call_do_page_fault:
+       mov.l   1f, r0
+       mov.l   @r0, r6
+
+       sti
+
+       mov.l   3f, r0
+       mov.l   4f, r1
+       mov     r15, r4
        jmp     @r0
-        mov    r15, r4
+        lds    r1, pr
 
        .align 2
 1:     .long   MMU_TEA
-2:     .long   __do_page_fault
+2:     .long   handle_tlbmiss
 3:     .long   do_page_fault
+4:     .long   ret_from_exception
 
        .align  2
 ENTRY(address_error_load)
@@ -256,7 +260,7 @@ restore_all:
        !
        ! Calculate new SR value
        mov     k3, k2                  ! original SR value
-       mov     #0xf0, k1
+       mov     #0xfffffff0, k1
        extu.b  k1, k1
        not     k1, k1
        and     k1, k2                  ! Mask original SR value
@@ -272,21 +276,12 @@ restore_all:
 6:     or      k0, k2                  ! Set the IMASK-bits
        ldc     k2, ssr
        !
-#if defined(CONFIG_KGDB)
-       ! Clear in_nmi
-       mov.l   6f, k0
-       mov     #0, k1
-       mov.b   k1, @k0
-#endif
        mov     k4, r15
        rte
         nop
 
        .align  2
 5:     .long   0x00001000      ! DSP
-#ifdef CONFIG_KGDB
-6:     .long   in_nmi
-#endif
 7:     .long   0x30000000
 
 ! common exception handler
@@ -478,23 +473,6 @@ ENTRY(save_low_regs)
 !
        .balign         512,0,512
 ENTRY(handle_interrupt)
-#if defined(CONFIG_KGDB)
-       mov.l   2f, k2
-       ! Debounce (filter nested NMI)
-       mov.l   @k2, k0
-       mov.l   9f, k1
-       cmp/eq  k1, k0
-       bf      11f
-       mov.l   10f, k1
-       tas.b   @k1
-       bt      11f
-       rte
-        nop
-       .align  2
-9:     .long   NMI_VEC
-10:    .long   in_nmi
-11:
-#endif /* defined(CONFIG_KGDB) */
        sts     pr, k3          ! save original pr value in k3
        mova    exception_data, k0
 
@@ -507,13 +485,49 @@ ENTRY(handle_interrupt)
        bsr     save_regs       ! needs original pr value in k3
         mov    #-1, k2         ! default vector kept in k2
 
+       setup_frame_reg
+
+       stc     sr, r0  ! get status register
+       shlr2   r0
+       and     #0x3c, r0
+       cmp/eq  #0x3c, r0
+       bf      9f
+       TRACE_IRQS_OFF
+9:
+
        ! Setup return address and jump to do_IRQ
        mov.l   4f, r9          ! fetch return address
        lds     r9, pr          ! put return address in pr
        mov.l   2f, r4
        mov.l   3f, r9
        mov.l   @r4, r4         ! pass INTEVT vector as arg0
+
+       shlr2   r4
+       shlr    r4
+       mov     r4, r0          ! save vector->jmp table offset for later
+
+       shlr2   r4              ! vector to IRQ# conversion
+       add     #-0x10, r4
+
+       cmp/pz  r4              ! is it a valid IRQ?
+       bt      10f
+
+       /*
+        * We got here as a result of taking the INTEVT path for something
+        * that isn't a valid hard IRQ, therefore we bypass the do_IRQ()
+        * path and special case the event dispatch instead.  This is the
+        * expected path for the NMI (and any other brilliantly implemented
+        * exception), which effectively wants regular exception dispatch
+        * but is unfortunately reported through INTEVT rather than
+        * EXPEVT.  Grr.
+        */
+       mov.l   6f, r9
+       mov.l   @(r0, r9), r9
        jmp     @r9
+        mov    r15, r8         ! trap handlers take saved regs in r8
+
+10:
+       jmp     @r9             ! Off to do_IRQ() we go.
         mov    r15, r5         ! pass saved registers as arg1
 
 ENTRY(exception_none)
index e5a0de3..46610c3 100644 (file)
@@ -48,9 +48,7 @@ ENTRY(exception_handling_table)
        .long   system_call     ! Unconditional Trap     /* 160 */
        .long   exception_error ! reserved_instruction (filled by trap_init) /* 180 */
        .long   exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
-ENTRY(nmi_slot)
-       .long   kgdb_handle_exception   /* 1C0 */       ! Allow trap to debugger
-ENTRY(user_break_point_trap)
+       .long   nmi_trap_handler        /* 1C0 */       ! Allow trap to debugger
        .long   break_point_trap        /* 1E0 */
 
        /*
index 10f2a76..f9c7df6 100644 (file)
@@ -107,5 +107,7 @@ int __uses_jump_to_uncached detect_cpu_and_cache_system(void)
        boot_cpu_data.dcache.flags |= SH_CACHE_COMBINED;
        boot_cpu_data.icache = boot_cpu_data.dcache;
 
+       boot_cpu_data.family = CPU_FAMILY_SH3;
+
        return 0;
 }
index 6c78d0a..d36f0c4 100644 (file)
@@ -57,8 +57,12 @@ int __init detect_cpu_and_cache_system(void)
         * Setup some generic flags we can probe on SH-4A parts
         */
        if (((pvr >> 16) & 0xff) == 0x10) {
-               if ((cvr & 0x10000000) == 0)
+               boot_cpu_data.family = CPU_FAMILY_SH4A;
+
+               if ((cvr & 0x10000000) == 0) {
                        boot_cpu_data.flags |= CPU_HAS_DSP;
+                       boot_cpu_data.family = CPU_FAMILY_SH4AL_DSP;
+               }
 
                boot_cpu_data.flags |= CPU_HAS_LLSC | CPU_HAS_PERF_COUNTER;
                boot_cpu_data.cut_major = pvr & 0x7f;
@@ -68,6 +72,7 @@ int __init detect_cpu_and_cache_system(void)
        } else {
                /* And some SH-4 defaults.. */
                boot_cpu_data.flags |= CPU_HAS_PTEA;
+               boot_cpu_data.family = CPU_FAMILY_SH4;
        }
 
        /* FPU detection works for everyone */
@@ -139,8 +144,15 @@ int __init detect_cpu_and_cache_system(void)
                }
                break;
        case 0x300b:
-               boot_cpu_data.type = CPU_SH7724;
-               boot_cpu_data.flags |= CPU_HAS_L2_CACHE;
+               switch (prr) {
+               case 0x20:
+                       boot_cpu_data.type = CPU_SH7724;
+                       boot_cpu_data.flags |= CPU_HAS_L2_CACHE;
+                       break;
+               case 0x50:
+                       boot_cpu_data.type = CPU_SH7757;
+                       break;
+               }
                break;
        case 0x4000:    /* 1st cut */
        case 0x4001:    /* 2nd cut */
@@ -172,9 +184,6 @@ int __init detect_cpu_and_cache_system(void)
                boot_cpu_data.icache.ways = 2;
                boot_cpu_data.dcache.ways = 2;
 
-               break;
-       default:
-               boot_cpu_data.type = CPU_SH_NONE;
                break;
        }
 
index ebdd391..490d5dc 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 # CPU subtype setup
+obj-$(CONFIG_CPU_SUBTYPE_SH7757)       += setup-sh7757.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7763)       += setup-sh7763.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7770)       += setup-sh7770.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7780)       += setup-sh7780.o
@@ -19,15 +20,16 @@ obj-$(CONFIG_CPU_SUBTYPE_SHX3)              += setup-shx3.o
 smp-$(CONFIG_CPU_SHX3)                 := smp-shx3.o
 
 # Primary on-chip clocks (common)
+clock-$(CONFIG_CPU_SUBTYPE_SH7757)     := clock-sh7757.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7763)     := clock-sh7763.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7770)     := clock-sh7770.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7780)     := clock-sh7780.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7785)     := clock-sh7785.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7786)     := clock-sh7786.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7343)     := clock-sh7343.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7722)     := clock-sh7722.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7723)     := clock-sh7723.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7724)     := clock-sh7724.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7722)     := clock-sh7722.o hwblk-sh7722.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7723)     := clock-sh7723.o hwblk-sh7723.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7724)     := clock-sh7724.o hwblk-sh7724.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7366)     := clock-sh7366.o
 clock-$(CONFIG_CPU_SUBTYPE_SHX3)       := clock-shx3.o
 
@@ -35,6 +37,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SHX3)      := clock-shx3.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7722)    := pinmux-sh7722.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7723)    := pinmux-sh7723.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7724)    := pinmux-sh7724.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7757)    := pinmux-sh7757.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7785)    := pinmux-sh7785.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7786)    := pinmux-sh7786.o
 
index 40f8593..ea38b55 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <asm/clock.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7722.h>
 
 /* SH7722 registers */
 #define FRQCR          0xa4150000
@@ -30,9 +32,6 @@
 #define SCLKBCR                0xa415000c
 #define IRDACLKCR      0xa4150018
 #define PLLCR          0xa4150024
-#define MSTPCR0                0xa4150030
-#define MSTPCR1                0xa4150034
-#define MSTPCR2                0xa4150038
 #define DLLFRQ         0xa4150050
 
 /* Fixed 32 KHz root clock for RTC and Power Management purposes */
@@ -140,35 +139,37 @@ struct clk div6_clks[] = {
        SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
 };
 
-#define MSTP(_str, _parent, _reg, _bit, _flags) \
-  SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags)
+#define R_CLK &r_clk
+#define P_CLK &div4_clks[DIV4_P]
+#define B_CLK &div4_clks[DIV4_B]
+#define U_CLK &div4_clks[DIV4_U]
 
 static struct clk mstp_clks[] = {
-       MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
-       MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
-       MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0),
-       MSTP("cmt0", &r_clk, MSTPCR0, 14, 0),
-       MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0),
-       MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0),
-       MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0),
-       MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0),
-       MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0),
-
-       MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0),
-       MSTP("rtc0", &r_clk, MSTPCR1, 8, 0),
-
-       MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0),
-       MSTP("keysc0", &r_clk, MSTPCR2, 14, 0),
-       MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0),
-       MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 9, 0),
-       MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0),
-       MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0),
-       MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT),
-       MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0),
-       MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0),
-       MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
-       MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
-       MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0),
+       SH_HWBLK_CLK("uram0", -1, U_CLK, HWBLK_URAM, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("xymem0", -1, B_CLK, HWBLK_XYMEM, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU, 0),
+       SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
+       SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
+       SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0),
+       SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
+       SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
+       SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
+
+       SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0),
+       SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
+
+       SH_HWBLK_CLK("sdhi0", -1, P_CLK, HWBLK_SDHI, 0),
+       SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
+       SH_HWBLK_CLK("usbf0", -1, P_CLK, HWBLK_USBF, 0),
+       SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
+       SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0),
+       SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
+       SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, 0),
+       SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0),
+       SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0),
+       SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU, 0),
+       SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, 0),
+       SH_HWBLK_CLK("lcdc0", -1, P_CLK, HWBLK_LCDC, 0),
 };
 
 int __init arch_clk_init(void)
@@ -191,7 +192,7 @@ int __init arch_clk_init(void)
                ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
 
        if (!ret)
-               ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+               ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
 
        return ret;
 }
index e67c267..20a31c2 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <asm/clock.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7723.h>
 
 /* SH7723 registers */
 #define FRQCR          0xa4150000
@@ -30,9 +32,6 @@
 #define SCLKBCR                0xa415000c
 #define IRDACLKCR      0xa4150018
 #define PLLCR          0xa4150024
-#define MSTPCR0                0xa4150030
-#define MSTPCR1                0xa4150034
-#define MSTPCR2                0xa4150038
 #define DLLFRQ         0xa4150050
 
 /* Fixed 32 KHz root clock for RTC and Power Management purposes */
@@ -140,60 +139,64 @@ struct clk div6_clks[] = {
        SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
 };
 
-#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \
-  SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT)
+#define R_CLK (&r_clk)
+#define P_CLK (&div4_clks[DIV4_P])
+#define B_CLK (&div4_clks[DIV4_B])
+#define U_CLK (&div4_clks[DIV4_U])
+#define I_CLK (&div4_clks[DIV4_I])
+#define SH_CLK (&div4_clks[DIV4_SH])
 
 static struct clk mstp_clks[] = {
        /* See page 60 of Datasheet V1.0: Overview -> Block Diagram */
-       MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0),
-       MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0),
-       MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0),
-       MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 28, 1, 1, 0),
-       MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0),
-       MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0),
-       MSTP("intc0", &div4_clks[DIV4_I], MSTPCR0, 22, 1, 1, 0),
-       MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1),
-       MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0),
-       MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0),
-       MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0),
-       MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0),
-       MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0),
-       MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0),
-       MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1),
-       MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 11, 0, 1, 0),
-       MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0),
-       MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0),
-       MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0),
-       MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0),
-       MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0),
-       MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0),
-       MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0),
-       MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0),
-       MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0),
-       MSTP("meram0", &div4_clks[DIV4_SH], MSTPCR0, 0, 1, 1, 0),
-
-       MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0),
-       MSTP("rtc0", &r_clk, MSTPCR1, 8, 0, 0, 0),
-
-       MSTP("atapi0", &div4_clks[DIV4_SH], MSTPCR2, 28, 0, 1, 0),
-       MSTP("adc0", &div4_clks[DIV4_P], MSTPCR2, 27, 0, 1, 0),
-       MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0),
-       MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0),
-       MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0),
-       MSTP("icb0", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1),
-       MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0),
-       MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0),
-       MSTP("keysc0", &r_clk, MSTPCR2, 14, 0, 0, 0),
-       MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 11, 0, 1, 0),
-       MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 10, 0, 1, 1),
-       MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0, 1, 0),
-       MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1),
-       MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1),
-       MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1),
-       MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1),
-       MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1),
-       MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1),
-       MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1),
+       SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("intc0", -1, I_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0),
+       SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0),
+       SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0),
+       SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0),
+       SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
+       SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
+       SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0),
+       SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0),
+       SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0),
+       SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
+       SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
+       SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
+       SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0),
+       SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0),
+       SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0),
+       SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0),
+       SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0),
+       SH_HWBLK_CLK("meram0", -1, SH_CLK, HWBLK_MERAM, 0),
+
+       SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0),
+       SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
+
+       SH_HWBLK_CLK("atapi0", -1, SH_CLK, HWBLK_ATAPI, 0),
+       SH_HWBLK_CLK("adc0", -1, P_CLK, HWBLK_ADC, 0),
+       SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0),
+       SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0),
+       SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0),
+       SH_HWBLK_CLK("icb0", -1, B_CLK, HWBLK_ICB, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0),
+       SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0),
+       SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
+       SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB, 0),
+       SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
+       SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0),
+       SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU2H1, 0),
+       SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
+       SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0),
+       SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0),
+       SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU2H0, 0),
+       SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, 0),
+       SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0),
 };
 
 int __init arch_clk_init(void)
@@ -216,7 +219,7 @@ int __init arch_clk_init(void)
                ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
 
        if (!ret)
-               ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+               ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
 
        return ret;
 }
index 5d5c9b9..dfe9192 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <asm/clock.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7724.h>
 
 /* SH7724 registers */
 #define FRQCRA         0xa4150000
@@ -31,9 +33,6 @@
 #define FCLKBCR                0xa415000c
 #define IRDACLKCR      0xa4150018
 #define PLLCR          0xa4150024
-#define MSTPCR0                0xa4150030
-#define MSTPCR1                0xa4150034
-#define MSTPCR2                0xa4150038
 #define SPUCLKCR       0xa415003c
 #define FLLFRQ         0xa4150050
 #define LSTATS         0xa4150060
@@ -128,7 +127,7 @@ struct clk *main_clks[] = {
        &div3_clk,
 };
 
-static int divisors[] = { 2, 0, 4, 6, 8, 12, 16, 0, 24, 32, 36, 48, 0, 72 };
+static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 0, 24, 32, 36, 48, 0, 72 };
 
 static struct clk_div_mult_table div4_table = {
        .divisors = divisors,
@@ -156,64 +155,67 @@ struct clk div6_clks[] = {
        SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, 0),
 };
 
-#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \
-  SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT)
+#define R_CLK (&r_clk)
+#define P_CLK (&div4_clks[DIV4_P])
+#define B_CLK (&div4_clks[DIV4_B])
+#define I_CLK (&div4_clks[DIV4_I])
+#define SH_CLK (&div4_clks[DIV4_SH])
 
 static struct clk mstp_clks[] = {
-       MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0),
-       MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0),
-       MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0),
-       MSTP("rs0", &div4_clks[DIV4_B], MSTPCR0, 28, 1, 1, 0),
-       MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0),
-       MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 26, 1, 1, 0),
-       MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0),
-       MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 1, 1, 0),
-       MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1),
-       MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0),
-       MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0),
-       MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0),
-       MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0),
-       MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0),
-       MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0),
-       MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1),
-       MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0),
-       MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0),
-       MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0),
-       MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0),
-       MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0),
-       MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0),
-       MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0),
-       MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0),
-       MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0),
-
-       MSTP("keysc0", &r_clk, MSTPCR1, 12, 0, 0, 0),
-       MSTP("rtc0", &r_clk, MSTPCR1, 11, 0, 0, 0),
-       MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0),
-       MSTP("i2c1", &div4_clks[DIV4_P], MSTPCR1, 8, 0, 1, 0),
-
-       MSTP("mmc0", &div4_clks[DIV4_B], MSTPCR2, 29, 0, 1, 0),
-       MSTP("eth0", &div4_clks[DIV4_B], MSTPCR2, 28, 0, 1, 0),
-       MSTP("atapi0", &div4_clks[DIV4_B], MSTPCR2, 26, 0, 1, 0),
-       MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0),
-       MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0),
-       MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0),
-       MSTP("usb1", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1),
-       MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 20, 0, 1, 1),
-       MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 19, 0, 1, 1),
-       MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0),
-       MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0),
-       MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 15, 1, 1, 1),
-       MSTP("ceu1", &div4_clks[DIV4_B], MSTPCR2, 13, 0, 1, 1),
-       MSTP("beu1", &div4_clks[DIV4_B], MSTPCR2, 12, 0, 1, 1),
-       MSTP("2ddmac0", &div4_clks[DIV4_SH], MSTPCR2, 10, 0, 1, 1),
-       MSTP("spu0", &div4_clks[DIV4_B], MSTPCR2, 9, 0, 1, 0),
-       MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1),
-       MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1),
-       MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1),
-       MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1),
-       MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1),
-       MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1),
-       MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1),
+       SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("rs0", -1, B_CLK, HWBLK_RSMEM, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("intc0", -1, P_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0),
+       SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT),
+       SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0),
+       SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0),
+       SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0),
+       SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
+       SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
+       SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0),
+       SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0),
+       SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
+       SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
+       SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
+       SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0),
+       SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0),
+       SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0),
+       SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0),
+       SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0),
+
+       SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
+       SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
+       SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC0, 0),
+       SH_HWBLK_CLK("i2c1", -1, P_CLK, HWBLK_IIC1, 0),
+
+       SH_HWBLK_CLK("mmc0", -1, B_CLK, HWBLK_MMC, 0),
+       SH_HWBLK_CLK("eth0", -1, B_CLK, HWBLK_ETHER, 0),
+       SH_HWBLK_CLK("atapi0", -1, B_CLK, HWBLK_ATAPI, 0),
+       SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0),
+       SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0),
+       SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0),
+       SH_HWBLK_CLK("usb1", -1, B_CLK, HWBLK_USB1, 0),
+       SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB0, 0),
+       SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
+       SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0),
+       SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0),
+       SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU1, 0),
+       SH_HWBLK_CLK("ceu1", -1, B_CLK, HWBLK_CEU1, 0),
+       SH_HWBLK_CLK("beu1", -1, B_CLK, HWBLK_BEU1, 0),
+       SH_HWBLK_CLK("2ddmac0", -1, SH_CLK, HWBLK_2DDMAC, 0),
+       SH_HWBLK_CLK("spu0", -1, B_CLK, HWBLK_SPU, 0),
+       SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, 0),
+       SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
+       SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU0, 0),
+       SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU0, 0),
+       SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU0, 0),
+       SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, 0),
+       SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0),
 };
 
 int __init arch_clk_init(void)
@@ -236,7 +238,7 @@ int __init arch_clk_init(void)
                ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
 
        if (!ret)
-               ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+               ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
 
        return ret;
 }
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
new file mode 100644 (file)
index 0000000..ddc235c
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-sh7757.c
+ *
+ * SH7757 support for the clock framework
+ *
+ *  Copyright (C) 2009  Renesas Solutions Corp.
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+
+static int ifc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1,
+                             16, 1, 1, 32, 1, 1, 1, 1 };
+static int sfc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1,
+                             16, 1, 1, 32, 1, 1, 1, 1 };
+static int bfc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1,
+                             16, 1, 1, 32, 1, 1, 1, 1 };
+static int p1fc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1,
+                              16, 1, 1, 32, 1, 1, 1, 1 };
+
+static void master_clk_init(struct clk *clk)
+{
+       clk->rate = CONFIG_SH_PCLK_FREQ * 16;
+}
+
+static struct clk_ops sh7757_master_clk_ops = {
+       .init           = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+       int idx = ctrl_inl(FRQCR) & 0x0000000f;
+       clk->rate = clk->parent->rate / p1fc_divisors[idx];
+}
+
+static struct clk_ops sh7757_module_clk_ops = {
+       .recalc         = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inl(FRQCR) >> 8) & 0x0000000f;
+       clk->rate = clk->parent->rate / bfc_divisors[idx];
+}
+
+static struct clk_ops sh7757_bus_clk_ops = {
+       .recalc         = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inl(FRQCR) >> 20) & 0x0000000f;
+       clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh7757_cpu_clk_ops = {
+       .recalc         = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7757_clk_ops[] = {
+       &sh7757_master_clk_ops,
+       &sh7757_module_clk_ops,
+       &sh7757_bus_clk_ops,
+       &sh7757_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+       if (idx < ARRAY_SIZE(sh7757_clk_ops))
+               *ops = sh7757_clk_ops[idx];
+}
+
+static void shyway_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inl(FRQCR) >> 12) & 0x0000000f;
+       clk->rate = clk->parent->rate / sfc_divisors[idx];
+}
+
+static struct clk_ops sh7757_shyway_clk_ops = {
+       .recalc         = shyway_clk_recalc,
+};
+
+static struct clk sh7757_shyway_clk = {
+       .name           = "shyway_clk",
+       .flags          = CLK_ENABLE_ON_INIT,
+       .ops            = &sh7757_shyway_clk_ops,
+};
+
+/*
+ * Additional sh7757-specific on-chip clocks that aren't already part of the
+ * clock framework
+ */
+static struct clk *sh7757_onchip_clocks[] = {
+       &sh7757_shyway_clk,
+};
+
+static int __init sh7757_clk_init(void)
+{
+       struct clk *clk = clk_get(NULL, "master_clk");
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(sh7757_onchip_clocks); i++) {
+               struct clk *clkp = sh7757_onchip_clocks[i];
+
+               clkp->parent = clk;
+               clk_register(clkp);
+               clk_enable(clkp);
+       }
+
+       /*
+        * Now that we have the rest of the clocks registered, we need to
+        * force the parent clock to propagate so that these clocks will
+        * automatically figure out their rate. We cheat by handing the
+        * parent clock its current rate and forcing child propagation.
+        */
+       clk_set_rate(clk, clk_get_rate(clk));
+
+       clk_put(clk);
+
+       return 0;
+}
+
+arch_initcall(sh7757_clk_init);
+
diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
new file mode 100644 (file)
index 0000000..a288b5d
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
+ *
+ * SH7722 hardware block support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/suspend.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7722.h>
+
+/* SH7722 registers */
+#define MSTPCR0                0xa4150030
+#define MSTPCR1                0xa4150034
+#define MSTPCR2                0xa4150038
+
+/* SH7722 Power Domains */
+enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
+static struct hwblk_area sh7722_hwblk_area[] = {
+       [CORE_AREA] = HWBLK_AREA(0, 0),
+       [CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
+       [SUB_AREA] = HWBLK_AREA(0, 0),
+};
+
+/* Table mapping HWBLK to Module Stop Bit and Power Domain */
+static struct hwblk sh7722_hwblk[HWBLK_NR] = {
+       [HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
+       [HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
+       [HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
+       [HWBLK_URAM] = HWBLK(MSTPCR0, 28, CORE_AREA),
+       [HWBLK_XYMEM] = HWBLK(MSTPCR0, 26, CORE_AREA),
+       [HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
+       [HWBLK_DMAC] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
+       [HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
+       [HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
+       [HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
+       [HWBLK_TMU] = HWBLK(MSTPCR0, 15, CORE_AREA),
+       [HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
+       [HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
+       [HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA),
+       [HWBLK_SCIF0] = HWBLK(MSTPCR0, 7, CORE_AREA),
+       [HWBLK_SCIF1] = HWBLK(MSTPCR0, 6, CORE_AREA),
+       [HWBLK_SCIF2] = HWBLK(MSTPCR0, 5, CORE_AREA),
+       [HWBLK_SIO] = HWBLK(MSTPCR0, 3, CORE_AREA),
+       [HWBLK_SIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
+       [HWBLK_SIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
+
+       [HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA),
+       [HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA),
+
+       [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
+       [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
+       [HWBLK_SDHI] = HWBLK(MSTPCR2, 18, CORE_AREA),
+       [HWBLK_SIM] = HWBLK(MSTPCR2, 16, CORE_AREA),
+       [HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA),
+       [HWBLK_TSIF] = HWBLK(MSTPCR2, 13, SUB_AREA),
+       [HWBLK_USBF] = HWBLK(MSTPCR2, 11, CORE_AREA),
+       [HWBLK_2DG] = HWBLK(MSTPCR2, 9, CORE_AREA_BM),
+       [HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA),
+       [HWBLK_JPU] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
+       [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
+       [HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
+       [HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
+       [HWBLK_VEU] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
+       [HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
+       [HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
+};
+
+static struct hwblk_info sh7722_hwblk_info = {
+       .areas = sh7722_hwblk_area,
+       .nr_areas = ARRAY_SIZE(sh7722_hwblk_area),
+       .hwblks = sh7722_hwblk,
+       .nr_hwblks = ARRAY_SIZE(sh7722_hwblk),
+};
+
+int arch_hwblk_sleep_mode(void)
+{
+       if (!sh7722_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
+               return SUSP_SH_STANDBY | SUSP_SH_SF;
+
+       if (!sh7722_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
+               return SUSP_SH_SLEEP | SUSP_SH_SF;
+
+       return SUSP_SH_SLEEP;
+}
+
+int __init arch_hwblk_init(void)
+{
+       return hwblk_register(&sh7722_hwblk_info);
+}
diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
new file mode 100644 (file)
index 0000000..a7f4684
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
+ *
+ * SH7723 hardware block support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/suspend.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7723.h>
+
+/* SH7723 registers */
+#define MSTPCR0                0xa4150030
+#define MSTPCR1                0xa4150034
+#define MSTPCR2                0xa4150038
+
+/* SH7723 Power Domains */
+enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
+static struct hwblk_area sh7723_hwblk_area[] = {
+       [CORE_AREA] = HWBLK_AREA(0, 0),
+       [CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
+       [SUB_AREA] = HWBLK_AREA(0, 0),
+};
+
+/* Table mapping HWBLK to Module Stop Bit and Power Domain */
+static struct hwblk sh7723_hwblk[HWBLK_NR] = {
+       [HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
+       [HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
+       [HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
+       [HWBLK_L2C] = HWBLK(MSTPCR0, 28, CORE_AREA),
+       [HWBLK_ILMEM] = HWBLK(MSTPCR0, 27, CORE_AREA),
+       [HWBLK_FPU] = HWBLK(MSTPCR0, 24, CORE_AREA),
+       [HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
+       [HWBLK_DMAC0] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
+       [HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
+       [HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
+       [HWBLK_DBG] = HWBLK(MSTPCR0, 18, CORE_AREA),
+       [HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
+       [HWBLK_SUBC] = HWBLK(MSTPCR0, 16, CORE_AREA),
+       [HWBLK_TMU0] = HWBLK(MSTPCR0, 15, CORE_AREA),
+       [HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
+       [HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
+       [HWBLK_DMAC1] = HWBLK(MSTPCR0, 12, CORE_AREA_BM),
+       [HWBLK_TMU1] = HWBLK(MSTPCR0, 11, CORE_AREA),
+       [HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA),
+       [HWBLK_SCIF0] = HWBLK(MSTPCR0, 9, CORE_AREA),
+       [HWBLK_SCIF1] = HWBLK(MSTPCR0, 8, CORE_AREA),
+       [HWBLK_SCIF2] = HWBLK(MSTPCR0, 7, CORE_AREA),
+       [HWBLK_SCIF3] = HWBLK(MSTPCR0, 6, CORE_AREA),
+       [HWBLK_SCIF4] = HWBLK(MSTPCR0, 5, CORE_AREA),
+       [HWBLK_SCIF5] = HWBLK(MSTPCR0, 4, CORE_AREA),
+       [HWBLK_MSIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
+       [HWBLK_MSIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
+       [HWBLK_MERAM] = HWBLK(MSTPCR0, 0, CORE_AREA),
+
+       [HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA),
+       [HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA),
+
+       [HWBLK_ATAPI] = HWBLK(MSTPCR2, 28, CORE_AREA_BM),
+       [HWBLK_ADC] = HWBLK(MSTPCR2, 27, CORE_AREA),
+       [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
+       [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
+       [HWBLK_TSIF] = HWBLK(MSTPCR2, 22, CORE_AREA),
+       [HWBLK_ICB] = HWBLK(MSTPCR2, 21, CORE_AREA_BM),
+       [HWBLK_SDHI0] = HWBLK(MSTPCR2, 18, CORE_AREA),
+       [HWBLK_SDHI1] = HWBLK(MSTPCR2, 17, CORE_AREA),
+       [HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA),
+       [HWBLK_USB] = HWBLK(MSTPCR2, 11, CORE_AREA),
+       [HWBLK_2DG] = HWBLK(MSTPCR2, 10, CORE_AREA_BM),
+       [HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA),
+       [HWBLK_VEU2H1] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
+       [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
+       [HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
+       [HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
+       [HWBLK_VEU2H0] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
+       [HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
+       [HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
+};
+
+static struct hwblk_info sh7723_hwblk_info = {
+       .areas = sh7723_hwblk_area,
+       .nr_areas = ARRAY_SIZE(sh7723_hwblk_area),
+       .hwblks = sh7723_hwblk,
+       .nr_hwblks = ARRAY_SIZE(sh7723_hwblk),
+};
+
+int arch_hwblk_sleep_mode(void)
+{
+       if (!sh7723_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
+               return SUSP_SH_STANDBY | SUSP_SH_SF;
+
+       if (!sh7723_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
+               return SUSP_SH_SLEEP | SUSP_SH_SF;
+
+       return SUSP_SH_SLEEP;
+}
+
+int __init arch_hwblk_init(void)
+{
+       return hwblk_register(&sh7723_hwblk_info);
+}
diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c
new file mode 100644 (file)
index 0000000..1613ad6
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c
+ *
+ * SH7724 hardware block support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/suspend.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7724.h>
+
+/* SH7724 registers */
+#define MSTPCR0                0xa4150030
+#define MSTPCR1                0xa4150034
+#define MSTPCR2                0xa4150038
+
+/* SH7724 Power Domains */
+enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
+static struct hwblk_area sh7724_hwblk_area[] = {
+       [CORE_AREA] = HWBLK_AREA(0, 0),
+       [CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
+       [SUB_AREA] = HWBLK_AREA(0, 0),
+};
+
+/* Table mapping HWBLK to Module Stop Bit and Power Domain */
+static struct hwblk sh7724_hwblk[HWBLK_NR] = {
+       [HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
+       [HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
+       [HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
+       [HWBLK_RSMEM] = HWBLK(MSTPCR0, 28, CORE_AREA),
+       [HWBLK_ILMEM] = HWBLK(MSTPCR0, 27, CORE_AREA),
+       [HWBLK_L2C] = HWBLK(MSTPCR0, 26, CORE_AREA),
+       [HWBLK_FPU] = HWBLK(MSTPCR0, 24, CORE_AREA),
+       [HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
+       [HWBLK_DMAC0] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
+       [HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
+       [HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
+       [HWBLK_DBG] = HWBLK(MSTPCR0, 18, CORE_AREA),
+       [HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
+       [HWBLK_TMU0] = HWBLK(MSTPCR0, 15, CORE_AREA),
+       [HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
+       [HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
+       [HWBLK_DMAC1] = HWBLK(MSTPCR0, 12, CORE_AREA_BM),
+       [HWBLK_TMU1] = HWBLK(MSTPCR0, 10, CORE_AREA),
+       [HWBLK_SCIF0] = HWBLK(MSTPCR0, 9, CORE_AREA),
+       [HWBLK_SCIF1] = HWBLK(MSTPCR0, 8, CORE_AREA),
+       [HWBLK_SCIF2] = HWBLK(MSTPCR0, 7, CORE_AREA),
+       [HWBLK_SCIF3] = HWBLK(MSTPCR0, 6, CORE_AREA),
+       [HWBLK_SCIF4] = HWBLK(MSTPCR0, 5, CORE_AREA),
+       [HWBLK_SCIF5] = HWBLK(MSTPCR0, 4, CORE_AREA),
+       [HWBLK_MSIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
+       [HWBLK_MSIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
+
+       [HWBLK_KEYSC] = HWBLK(MSTPCR1, 12, SUB_AREA),
+       [HWBLK_RTC] = HWBLK(MSTPCR1, 11, SUB_AREA),
+       [HWBLK_IIC0] = HWBLK(MSTPCR1, 9, CORE_AREA),
+       [HWBLK_IIC1] = HWBLK(MSTPCR1, 8, CORE_AREA),
+
+       [HWBLK_MMC] = HWBLK(MSTPCR2, 29, CORE_AREA),
+       [HWBLK_ETHER] = HWBLK(MSTPCR2, 28, CORE_AREA_BM),
+       [HWBLK_ATAPI] = HWBLK(MSTPCR2, 26, CORE_AREA_BM),
+       [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
+       [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
+       [HWBLK_TSIF] = HWBLK(MSTPCR2, 22, CORE_AREA),
+       [HWBLK_USB1] = HWBLK(MSTPCR2, 21, CORE_AREA),
+       [HWBLK_USB0] = HWBLK(MSTPCR2, 20, CORE_AREA),
+       [HWBLK_2DG] = HWBLK(MSTPCR2, 19, CORE_AREA_BM),
+       [HWBLK_SDHI0] = HWBLK(MSTPCR2, 18, CORE_AREA),
+       [HWBLK_SDHI1] = HWBLK(MSTPCR2, 17, CORE_AREA),
+       [HWBLK_VEU1] = HWBLK(MSTPCR2, 15, CORE_AREA_BM),
+       [HWBLK_CEU1] = HWBLK(MSTPCR2, 13, CORE_AREA_BM),
+       [HWBLK_BEU1] = HWBLK(MSTPCR2, 12, CORE_AREA_BM),
+       [HWBLK_2DDMAC] = HWBLK(MSTPCR2, 10, CORE_AREA_BM),
+       [HWBLK_SPU] = HWBLK(MSTPCR2, 9, CORE_AREA_BM),
+       [HWBLK_JPU] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
+       [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
+       [HWBLK_BEU0] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
+       [HWBLK_CEU0] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
+       [HWBLK_VEU0] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
+       [HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
+       [HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
+};
+
+static struct hwblk_info sh7724_hwblk_info = {
+       .areas = sh7724_hwblk_area,
+       .nr_areas = ARRAY_SIZE(sh7724_hwblk_area),
+       .hwblks = sh7724_hwblk,
+       .nr_hwblks = ARRAY_SIZE(sh7724_hwblk),
+};
+
+int arch_hwblk_sleep_mode(void)
+{
+       if (!sh7724_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
+               return SUSP_SH_STANDBY | SUSP_SH_SF;
+
+       if (!sh7724_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
+               return SUSP_SH_SLEEP | SUSP_SH_SF;
+
+       return SUSP_SH_SLEEP;
+}
+
+int __init arch_hwblk_init(void)
+{
+       return hwblk_register(&sh7724_hwblk_info);
+}
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c
new file mode 100644 (file)
index 0000000..ed23b15
--- /dev/null
@@ -0,0 +1,2019 @@
+/*
+ * SH7757 (A0 step) Pinmux
+ *
+ *  Copyright (C) 2009  Renesas Solutions Corp.
+ *
+ *  Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * Based on SH7757 Pinmux
+ *  Copyright (C) 2008  Magnus Damm
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <cpu/sh7757.h>
+
+enum {
+       PINMUX_RESERVED = 0,
+
+       PINMUX_DATA_BEGIN,
+       PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
+       PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA,
+       PTB7_DATA, PTB6_DATA, PTB5_DATA, PTB4_DATA,
+       PTB3_DATA, PTB2_DATA, PTB1_DATA, PTB0_DATA,
+       PTC7_DATA, PTC6_DATA, PTC5_DATA, PTC4_DATA,
+       PTC3_DATA, PTC2_DATA, PTC1_DATA, PTC0_DATA,
+       PTD7_DATA, PTD6_DATA, PTD5_DATA, PTD4_DATA,
+       PTD3_DATA, PTD2_DATA, PTD1_DATA, PTD0_DATA,
+       PTE7_DATA, PTE6_DATA, PTE5_DATA, PTE4_DATA,
+       PTE3_DATA, PTE2_DATA, PTE1_DATA, PTE0_DATA,
+       PTF7_DATA, PTF6_DATA, PTF5_DATA, PTF4_DATA,
+       PTF3_DATA, PTF2_DATA, PTF1_DATA, PTF0_DATA,
+       PTG7_DATA, PTG6_DATA, PTG5_DATA, PTG4_DATA,
+       PTG3_DATA, PTG2_DATA, PTG1_DATA, PTG0_DATA,
+       PTH7_DATA, PTH6_DATA, PTH5_DATA, PTH4_DATA,
+       PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA,
+       PTI7_DATA, PTI6_DATA, PTI5_DATA, PTI4_DATA,
+       PTI3_DATA, PTI2_DATA, PTI1_DATA, PTI0_DATA,
+       PTJ7_DATA, PTJ6_DATA, PTJ5_DATA, PTJ4_DATA,
+       PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA,
+       PTK7_DATA, PTK6_DATA, PTK5_DATA, PTK4_DATA,
+       PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA,
+       PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+       PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA,
+       PTM6_DATA, PTM5_DATA, PTM4_DATA,
+       PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA,
+       PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+       PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA,
+       PTO7_DATA, PTO6_DATA, PTO5_DATA, PTO4_DATA,
+       PTO3_DATA, PTO2_DATA, PTO1_DATA, PTO0_DATA,
+       PTP6_DATA, PTP5_DATA, PTP4_DATA,
+       PTP3_DATA, PTP2_DATA, PTP1_DATA, PTP0_DATA,
+       PTQ6_DATA, PTQ5_DATA, PTQ4_DATA,
+       PTQ3_DATA, PTQ2_DATA, PTQ1_DATA, PTQ0_DATA,
+       PTR7_DATA, PTR6_DATA, PTR5_DATA, PTR4_DATA,
+       PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA,
+       PTS7_DATA, PTS6_DATA, PTS5_DATA, PTS4_DATA,
+       PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA,
+       PTT5_DATA, PTT4_DATA,
+       PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA,
+       PTU7_DATA, PTU6_DATA, PTU5_DATA, PTU4_DATA,
+       PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA,
+       PTV7_DATA, PTV6_DATA, PTV5_DATA, PTV4_DATA,
+       PTV3_DATA, PTV2_DATA, PTV1_DATA, PTV0_DATA,
+       PTW7_DATA, PTW6_DATA, PTW5_DATA, PTW4_DATA,
+       PTW3_DATA, PTW2_DATA, PTW1_DATA, PTW0_DATA,
+       PTX7_DATA, PTX6_DATA, PTX5_DATA, PTX4_DATA,
+       PTX3_DATA, PTX2_DATA, PTX1_DATA, PTX0_DATA,
+       PTY7_DATA, PTY6_DATA, PTY5_DATA, PTY4_DATA,
+       PTY3_DATA, PTY2_DATA, PTY1_DATA, PTY0_DATA,
+       PTZ7_DATA, PTZ6_DATA, PTZ5_DATA, PTZ4_DATA,
+       PTZ3_DATA, PTZ2_DATA, PTZ1_DATA, PTZ0_DATA,
+       PINMUX_DATA_END,
+
+       PINMUX_INPUT_BEGIN,
+       PTA7_IN, PTA6_IN, PTA5_IN, PTA4_IN,
+       PTA3_IN, PTA2_IN, PTA1_IN, PTA0_IN,
+       PTB7_IN, PTB6_IN, PTB5_IN, PTB4_IN,
+       PTB3_IN, PTB2_IN, PTB1_IN, PTB0_IN,
+       PTC7_IN, PTC6_IN, PTC5_IN, PTC4_IN,
+       PTC3_IN, PTC2_IN, PTC1_IN, PTC0_IN,
+       PTD7_IN, PTD6_IN, PTD5_IN, PTD4_IN,
+       PTD3_IN, PTD2_IN, PTD1_IN, PTD0_IN,
+       PTE7_IN, PTE6_IN, PTE5_IN, PTE4_IN,
+       PTE3_IN, PTE2_IN, PTE1_IN, PTE0_IN,
+       PTF7_IN, PTF6_IN, PTF5_IN, PTF4_IN,
+       PTF3_IN, PTF2_IN, PTF1_IN, PTF0_IN,
+       PTG7_IN, PTG6_IN, PTG5_IN, PTG4_IN,
+       PTG3_IN, PTG2_IN, PTG1_IN, PTG0_IN,
+       PTH7_IN, PTH6_IN, PTH5_IN, PTH4_IN,
+       PTH3_IN, PTH2_IN, PTH1_IN, PTH0_IN,
+       PTI7_IN, PTI6_IN, PTI5_IN, PTI4_IN,
+       PTI3_IN, PTI2_IN, PTI1_IN, PTI0_IN,
+       PTJ7_IN, PTJ6_IN, PTJ5_IN, PTJ4_IN,
+       PTJ3_IN, PTJ2_IN, PTJ1_IN, PTJ0_IN,
+       PTK7_IN, PTK6_IN, PTK5_IN, PTK4_IN,
+       PTK3_IN, PTK2_IN, PTK1_IN, PTK0_IN,
+       PTL7_IN, PTL6_IN, PTL5_IN, PTL4_IN,
+       PTL3_IN, PTL2_IN, PTL1_IN, PTL0_IN,
+       PTM6_IN, PTM5_IN, PTM4_IN,
+       PTM3_IN, PTM2_IN, PTM1_IN, PTM0_IN,
+       PTN7_IN, PTN6_IN, PTN5_IN, PTN4_IN,
+       PTN3_IN, PTN2_IN, PTN1_IN, PTN0_IN,
+       PTO7_IN, PTO6_IN, PTO5_IN, PTO4_IN,
+       PTO3_IN, PTO2_IN, PTO1_IN, PTO0_IN,
+       PTP6_IN, PTP5_IN, PTP4_IN,
+       PTP3_IN, PTP2_IN, PTP1_IN, PTP0_IN,
+       PTQ6_IN, PTQ5_IN, PTQ4_IN,
+       PTQ3_IN, PTQ2_IN, PTQ1_IN, PTQ0_IN,
+       PTR7_IN, PTR6_IN, PTR5_IN, PTR4_IN,
+       PTR3_IN, PTR2_IN, PTR1_IN, PTR0_IN,
+       PTS7_IN, PTS6_IN, PTS5_IN, PTS4_IN,
+       PTS3_IN, PTS2_IN, PTS1_IN, PTS0_IN,
+       PTT5_IN, PTT4_IN,
+       PTT3_IN, PTT2_IN, PTT1_IN, PTT0_IN,
+       PTU7_IN, PTU6_IN, PTU5_IN, PTU4_IN,
+       PTU3_IN, PTU2_IN, PTU1_IN, PTU0_IN,
+       PTV7_IN, PTV6_IN, PTV5_IN, PTV4_IN,
+       PTV3_IN, PTV2_IN, PTV1_IN, PTV0_IN,
+       PTW7_IN, PTW6_IN, PTW5_IN, PTW4_IN,
+       PTW3_IN, PTW2_IN, PTW1_IN, PTW0_IN,
+       PTX7_IN, PTX6_IN, PTX5_IN, PTX4_IN,
+       PTX3_IN, PTX2_IN, PTX1_IN, PTX0_IN,
+       PTY7_IN, PTY6_IN, PTY5_IN, PTY4_IN,
+       PTY3_IN, PTY2_IN, PTY1_IN, PTY0_IN,
+       PTZ7_IN, PTZ6_IN, PTZ5_IN, PTZ4_IN,
+       PTZ3_IN, PTZ2_IN, PTZ1_IN, PTZ0_IN,
+       PINMUX_INPUT_END,
+
+       PINMUX_INPUT_PULLUP_BEGIN,
+       PTU7_IN_PU, PTU6_IN_PU, PTU5_IN_PU, PTU4_IN_PU,
+       PTU3_IN_PU, PTU2_IN_PU, PTU1_IN_PU, PTU0_IN_PU,
+       PTV7_IN_PU, PTV6_IN_PU, PTV5_IN_PU, PTV4_IN_PU,
+       PTV3_IN_PU, PTV2_IN_PU, PTV1_IN_PU, PTV0_IN_PU,
+       PTW7_IN_PU, PTW6_IN_PU, PTW5_IN_PU, PTW4_IN_PU,
+       PTW3_IN_PU, PTW2_IN_PU, PTW1_IN_PU, PTW0_IN_PU,
+       PTX7_IN_PU, PTX6_IN_PU, PTX5_IN_PU, PTX4_IN_PU,
+       PTX3_IN_PU, PTX2_IN_PU, PTX1_IN_PU, PTX0_IN_PU,
+       PTY7_IN_PU, PTY6_IN_PU, PTY5_IN_PU, PTY4_IN_PU,
+       PTY3_IN_PU, PTY2_IN_PU, PTY1_IN_PU, PTY0_IN_PU,
+       PINMUX_INPUT_PULLUP_END,
+
+       PINMUX_OUTPUT_BEGIN,
+       PTA7_OUT, PTA6_OUT, PTA5_OUT, PTA4_OUT,
+       PTA3_OUT, PTA2_OUT, PTA1_OUT, PTA0_OUT,
+       PTB7_OUT, PTB6_OUT, PTB5_OUT, PTB4_OUT,
+       PTB3_OUT, PTB2_OUT, PTB1_OUT, PTB0_OUT,
+       PTC7_OUT, PTC6_OUT, PTC5_OUT, PTC4_OUT,
+       PTC3_OUT, PTC2_OUT, PTC1_OUT, PTC0_OUT,
+       PTD7_OUT, PTD6_OUT, PTD5_OUT, PTD4_OUT,
+       PTD3_OUT, PTD2_OUT, PTD1_OUT, PTD0_OUT,
+       PTE7_OUT, PTE6_OUT, PTE5_OUT, PTE4_OUT,
+       PTE3_OUT, PTE2_OUT, PTE1_OUT, PTE0_OUT,
+       PTF7_OUT, PTF6_OUT, PTF5_OUT, PTF4_OUT,
+       PTF3_OUT, PTF2_OUT, PTF1_OUT, PTF0_OUT,
+       PTG7_OUT, PTG6_OUT, PTG5_OUT, PTG4_OUT,
+       PTG3_OUT, PTG2_OUT, PTG1_OUT, PTG0_OUT,
+       PTH7_OUT, PTH6_OUT, PTH5_OUT, PTH4_OUT,
+       PTH3_OUT, PTH2_OUT, PTH1_OUT, PTH0_OUT,
+       PTI7_OUT, PTI6_OUT, PTI5_OUT, PTI4_OUT,
+       PTI3_OUT, PTI2_OUT, PTI1_OUT, PTI0_OUT,
+       PTJ7_OUT, PTJ6_OUT, PTJ5_OUT, PTJ4_OUT,
+       PTJ3_OUT, PTJ2_OUT, PTJ1_OUT, PTJ0_OUT,
+       PTK7_OUT, PTK6_OUT, PTK5_OUT, PTK4_OUT,
+       PTK3_OUT, PTK2_OUT, PTK1_OUT, PTK0_OUT,
+       PTL7_OUT, PTL6_OUT, PTL5_OUT, PTL4_OUT,
+       PTL3_OUT, PTL2_OUT, PTL1_OUT, PTL0_OUT,
+       PTM6_OUT, PTM5_OUT, PTM4_OUT,
+       PTM3_OUT, PTM2_OUT, PTM1_OUT, PTM0_OUT,
+       PTN7_OUT, PTN6_OUT, PTN5_OUT, PTN4_OUT,
+       PTN3_OUT, PTN2_OUT, PTN1_OUT, PTN0_OUT,
+       PTO7_OUT, PTO6_OUT, PTO5_OUT, PTO4_OUT,
+       PTO3_OUT, PTO2_OUT, PTO1_OUT, PTO0_OUT,
+       PTP6_OUT, PTP5_OUT, PTP4_OUT,
+       PTP3_OUT, PTP2_OUT, PTP1_OUT, PTP0_OUT,
+       PTQ6_OUT, PTQ5_OUT, PTQ4_OUT,
+       PTQ3_OUT, PTQ2_OUT, PTQ1_OUT, PTQ0_OUT,
+       PTR7_OUT, PTR6_OUT, PTR5_OUT, PTR4_OUT,
+       PTR3_OUT, PTR2_OUT, PTR1_OUT, PTR0_OUT,
+       PTS7_OUT, PTS6_OUT, PTS5_OUT, PTS4_OUT,
+       PTS3_OUT, PTS2_OUT, PTS1_OUT, PTS0_OUT,
+       PTT5_OUT, PTT4_OUT,
+       PTT3_OUT, PTT2_OUT, PTT1_OUT, PTT0_OUT,
+       PTU7_OUT, PTU6_OUT, PTU5_OUT, PTU4_OUT,
+       PTU3_OUT, PTU2_OUT, PTU1_OUT, PTU0_OUT,
+       PTV7_OUT, PTV6_OUT, PTV5_OUT, PTV4_OUT,
+       PTV3_OUT, PTV2_OUT, PTV1_OUT, PTV0_OUT,
+       PTW7_OUT, PTW6_OUT, PTW5_OUT, PTW4_OUT,
+       PTW3_OUT, PTW2_OUT, PTW1_OUT, PTW0_OUT,
+       PTX7_OUT, PTX6_OUT, PTX5_OUT, PTX4_OUT,
+       PTX3_OUT, PTX2_OUT, PTX1_OUT, PTX0_OUT,
+       PTY7_OUT, PTY6_OUT, PTY5_OUT, PTY4_OUT,
+       PTY3_OUT, PTY2_OUT, PTY1_OUT, PTY0_OUT,
+       PTZ7_OUT, PTZ6_OUT, PTZ5_OUT, PTZ4_OUT,
+       PTZ3_OUT, PTZ2_OUT, PTZ1_OUT, PTZ0_OUT,
+       PINMUX_OUTPUT_END,
+
+       PINMUX_FUNCTION_BEGIN,
+       PTA7_FN, PTA6_FN, PTA5_FN, PTA4_FN,
+       PTA3_FN, PTA2_FN, PTA1_FN, PTA0_FN,
+       PTB7_FN, PTB6_FN, PTB5_FN, PTB4_FN,
+       PTB3_FN, PTB2_FN, PTB1_FN, PTB0_FN,
+       PTC7_FN, PTC6_FN, PTC5_FN, PTC4_FN,
+       PTC3_FN, PTC2_FN, PTC1_FN, PTC0_FN,
+       PTD7_FN, PTD6_FN, PTD5_FN, PTD4_FN,
+       PTD3_FN, PTD2_FN, PTD1_FN, PTD0_FN,
+       PTE7_FN, PTE6_FN, PTE5_FN, PTE4_FN,
+       PTE3_FN, PTE2_FN, PTE1_FN, PTE0_FN,
+       PTF7_FN, PTF6_FN, PTF5_FN, PTF4_FN,
+       PTF3_FN, PTF2_FN, PTF1_FN, PTF0_FN,
+       PTG7_FN, PTG6_FN, PTG5_FN, PTG4_FN,
+       PTG3_FN, PTG2_FN, PTG1_FN, PTG0_FN,
+       PTH7_FN, PTH6_FN, PTH5_FN, PTH4_FN,
+       PTH3_FN, PTH2_FN, PTH1_FN, PTH0_FN,
+       PTI7_FN, PTI6_FN, PTI5_FN, PTI4_FN,
+       PTI3_FN, PTI2_FN, PTI1_FN, PTI0_FN,
+       PTJ7_FN, PTJ6_FN, PTJ5_FN, PTJ4_FN,
+       PTJ3_FN, PTJ2_FN, PTJ1_FN, PTJ0_FN,
+       PTK7_FN, PTK6_FN, PTK5_FN, PTK4_FN,
+       PTK3_FN, PTK2_FN, PTK1_FN, PTK0_FN,
+       PTL7_FN, PTL6_FN, PTL5_FN, PTL4_FN,
+       PTL3_FN, PTL2_FN, PTL1_FN, PTL0_FN,
+       PTM6_FN, PTM5_FN, PTM4_FN,
+       PTM3_FN, PTM2_FN, PTM1_FN, PTM0_FN,
+       PTN7_FN, PTN6_FN, PTN5_FN, PTN4_FN,
+       PTN3_FN, PTN2_FN, PTN1_FN, PTN0_FN,
+       PTO7_FN, PTO6_FN, PTO5_FN, PTO4_FN,
+       PTO3_FN, PTO2_FN, PTO1_FN, PTO0_FN,
+       PTP6_FN, PTP5_FN, PTP4_FN,
+       PTP3_FN, PTP2_FN, PTP1_FN, PTP0_FN,
+       PTQ6_FN, PTQ5_FN, PTQ4_FN,
+       PTQ3_FN, PTQ2_FN, PTQ1_FN, PTQ0_FN,
+       PTR7_FN, PTR6_FN, PTR5_FN, PTR4_FN,
+       PTR3_FN, PTR2_FN, PTR1_FN, PTR0_FN,
+       PTS7_FN, PTS6_FN, PTS5_FN, PTS4_FN,
+       PTS3_FN, PTS2_FN, PTS1_FN, PTS0_FN,
+       PTT5_FN, PTT4_FN,
+       PTT3_FN, PTT2_FN, PTT1_FN, PTT0_FN,
+       PTU7_FN, PTU6_FN, PTU5_FN, PTU4_FN,
+       PTU3_FN, PTU2_FN, PTU1_FN, PTU0_FN,
+       PTV7_FN, PTV6_FN, PTV5_FN, PTV4_FN,
+       PTV3_FN, PTV2_FN, PTV1_FN, PTV0_FN,
+       PTW7_FN, PTW6_FN, PTW5_FN, PTW4_FN,
+       PTW3_FN, PTW2_FN, PTW1_FN, PTW0_FN,
+       PTX7_FN, PTX6_FN, PTX5_FN, PTX4_FN,
+       PTX3_FN, PTX2_FN, PTX1_FN, PTX0_FN,
+       PTY7_FN, PTY6_FN, PTY5_FN, PTY4_FN,
+       PTY3_FN, PTY2_FN, PTY1_FN, PTY0_FN,
+       PTZ7_FN, PTZ6_FN, PTZ5_FN, PTZ4_FN,
+       PTZ3_FN, PTZ2_FN, PTZ1_FN, PTZ0_FN,
+
+       PS0_15_FN1, PS0_15_FN3,
+       PS0_14_FN1, PS0_14_FN3,
+       PS0_13_FN1, PS0_13_FN3,
+       PS0_12_FN1, PS0_12_FN3,
+       PS0_7_FN1, PS0_7_FN2,
+       PS0_6_FN1, PS0_6_FN2,
+       PS0_5_FN1, PS0_5_FN2,
+       PS0_4_FN1, PS0_4_FN2,
+       PS0_3_FN1, PS0_3_FN2,
+       PS0_2_FN1, PS0_2_FN2,
+       PS0_1_FN1, PS0_1_FN2,
+
+       PS1_7_FN1, PS1_7_FN3,
+       PS1_6_FN1, PS1_6_FN3,
+
+       PS2_13_FN1, PS2_13_FN3,
+       PS2_12_FN1, PS2_12_FN3,
+       PS2_1_FN1, PS2_1_FN2,
+       PS2_0_FN1, PS2_0_FN2,
+
+       PS4_15_FN1, PS4_15_FN2,
+       PS4_14_FN1, PS4_14_FN2,
+       PS4_13_FN1, PS4_13_FN2,
+       PS4_12_FN1, PS4_12_FN2,
+       PS4_11_FN1, PS4_11_FN2,
+       PS4_10_FN1, PS4_10_FN2,
+       PS4_9_FN1, PS4_9_FN2,
+       PS4_3_FN1, PS4_3_FN2,
+       PS4_2_FN1, PS4_2_FN2,
+       PS4_1_FN1, PS4_1_FN2,
+       PS4_0_FN1, PS4_0_FN2,
+
+       PS5_9_FN1, PS5_9_FN2,
+       PS5_8_FN1, PS5_8_FN2,
+       PS5_7_FN1, PS5_7_FN2,
+       PS5_6_FN1, PS5_6_FN2,
+       PS5_5_FN1, PS5_5_FN2,
+       PS5_4_FN1, PS5_4_FN2,
+
+       /* AN15 to 8 : EVENT15 to 8 */
+       PS6_7_FN_AN, PS6_7_FN_EV,
+       PS6_6_FN_AN, PS6_6_FN_EV,
+       PS6_5_FN_AN, PS6_5_FN_EV,
+       PS6_4_FN_AN, PS6_4_FN_EV,
+       PS6_3_FN_AN, PS6_3_FN_EV,
+       PS6_2_FN_AN, PS6_2_FN_EV,
+       PS6_1_FN_AN, PS6_1_FN_EV,
+       PS6_0_FN_AN, PS6_0_FN_EV,
+
+       PINMUX_FUNCTION_END,
+
+       PINMUX_MARK_BEGIN,
+       /* PTA (mobule: LBSC, CPG, LPC) */
+       BS_MARK,        RDWR_MARK,      WE1_MARK,       RDY_MARK,
+       MD10_MARK,      MD9_MARK,       MD8_MARK,
+       LGPIO7_MARK,    LGPIO6_MARK,    LGPIO5_MARK,    LGPIO4_MARK,
+       LGPIO3_MARK,    LGPIO2_MARK,    LGPIO1_MARK,    LGPIO0_MARK,
+
+       /* PTB (mobule: LBSC, EtherC, SIM, LPC) */
+       D15_MARK,       D14_MARK,       D13_MARK,       D12_MARK,
+       D11_MARK,       D10_MARK,       D9_MARK,        D8_MARK,
+       ET0_MDC_MARK,   ET0_MDIO_MARK,  ET1_MDC_MARK,   ET1_MDIO_MARK,
+       SIM_D_MARK,     SIM_CLK_MARK,   SIM_RST_MARK,
+       WPSZ1_MARK,     WPSZ0_MARK,     FWID_MARK,      FLSHSZ_MARK,
+       LPC_SPIEN_MARK, BASEL_MARK,
+
+       /* PTC (mobule: SD) */
+       SD_WP_MARK,     SD_CD_MARK,     SD_CLK_MARK,    SD_CMD_MARK,
+       SD_D3_MARK,     SD_D2_MARK,     SD_D1_MARK,     SD_D0_MARK,
+
+       /* PTD (mobule: INTC, SPI0, LBSC, CPG, ADC) */
+       IRQ7_MARK,      IRQ6_MARK,      IRQ5_MARK,      IRQ4_MARK,
+       IRQ3_MARK,      IRQ2_MARK,      IRQ1_MARK,      IRQ0_MARK,
+       MD6_MARK,       MD5_MARK,       MD3_MARK,       MD2_MARK,
+       MD1_MARK,       MD0_MARK,       ADTRG1_MARK,    ADTRG0_MARK,
+
+       /* PTE (mobule: EtherC) */
+       ET0_CRS_DV_MARK,        ET0_TXD1_MARK,
+       ET0_TXD0_MARK,          ET0_TX_EN_MARK,
+       ET0_REF_CLK_MARK,       ET0_RXD1_MARK,
+       ET0_RXD0_MARK,          ET0_RX_ER_MARK,
+
+       /* PTF (mobule: EtherC) */
+       ET1_CRS_DV_MARK,        ET1_TXD1_MARK,
+       ET1_TXD0_MARK,          ET1_TX_EN_MARK,
+       ET1_REF_CLK_MARK,       ET1_RXD1_MARK,
+       ET1_RXD0_MARK,          ET1_RX_ER_MARK,
+
+       /* PTG (mobule: SYSTEM, PWMX, LPC) */
+       STATUS0_MARK,   STATUS1_MARK,
+       PWX0_MARK,      PWX1_MARK,      PWX2_MARK,      PWX3_MARK,
+       SERIRQ_MARK,    CLKRUN_MARK,    LPCPD_MARK,     LDRQ_MARK,
+
+       /* PTH (mobule: TMU, SCIF234, SPI1, SPI0) */
+       TCLK_MARK,      RXD4_MARK,      TXD4_MARK,
+       SP1_MOSI_MARK,  SP1_MISO_MARK,  SP1_SCK_MARK,   SP1_SCK_FB_MARK,
+       SP1_SS0_MARK,   SP1_SS1_MARK,   SP0_SS1_MARK,
+
+       /* PTI (mobule: INTC) */
+       IRQ15_MARK,     IRQ14_MARK,     IRQ13_MARK,     IRQ12_MARK,
+       IRQ11_MARK,     IRQ10_MARK,     IRQ9_MARK,      IRQ8_MARK,
+
+       /* PTJ (mobule: SCIF234, SERMUX) */
+       RXD3_MARK,      TXD3_MARK,      RXD2_MARK,      TXD2_MARK,
+       COM1_TXD_MARK,  COM1_RXD_MARK,  COM1_RTS_MARK,  COM1_CTS_MARK,
+
+       /* PTK (mobule: SERMUX) */
+       COM2_TXD_MARK,  COM2_RXD_MARK,  COM2_RTS_MARK,  COM2_CTS_MARK,
+       COM2_DTR_MARK,  COM2_DSR_MARK,  COM2_DCD_MARK,  COM2_RI_MARK,
+
+       /* PTL (mobule: SERMUX) */
+       RAC_TXD_MARK,   RAC_RXD_MARK,   RAC_RTS_MARK,   RAC_CTS_MARK,
+       RAC_DTR_MARK,   RAC_DSR_MARK,   RAC_DCD_MARK,   RAC_RI_MARK,
+
+       /* PTM (mobule: IIC, LPC) */
+       SDA6_MARK,      SCL6_MARK,      SDA7_MARK,      SCL7_MARK,
+       WP_MARK,        FMS0_MARK,      FMS1_MARK,
+
+       /* PTN (mobule: SCIF234, EVC) */
+       SCK2_MARK,      RTS4_MARK,      RTS3_MARK,      RTS2_MARK,
+       CTS4_MARK,      CTS3_MARK,      CTS2_MARK,
+       EVENT7_MARK,    EVENT6_MARK,    EVENT5_MARK,    EVENT4_MARK,
+       EVENT3_MARK,    EVENT2_MARK,    EVENT1_MARK,    EVENT0_MARK,
+
+       /* PTO (mobule: SGPIO) */
+       SGPIO0_CLK_MARK,        SGPIO0_LOAD_MARK,
+       SGPIO0_DI_MARK,         SGPIO0_DO_MARK,
+       SGPIO1_CLK_MARK,        SGPIO1_LOAD_MARK,
+       SGPIO1_DI_MARK,         SGPIO1_DO_MARK,
+
+       /* PTP (mobule: JMC, SCIF234) */
+       JMCTCK_MARK,    JMCTMS_MARK,    JMCTDO_MARK,    JMCTDI_MARK,
+       JMCRST_MARK,    SCK4_MARK,      SCK3_MARK,
+
+       /* PTQ (mobule: LPC) */
+       LAD3_MARK,      LAD2_MARK,      LAD1_MARK,      LAD0_MARK,
+       LFRAME_MARK,    LRESET_MARK,    LCLK_MARK,
+
+       /* PTR (mobule: GRA, IIC) */
+       DDC3_MARK,      DDC2_MARK,
+       SDA8_MARK,      SCL8_MARK,      SDA2_MARK,      SCL2_MARK,
+       SDA1_MARK,      SCL1_MARK,      SDA0_MARK,      SCL0_MARK,
+
+       /* PTS (mobule: GRA, IIC) */
+       DDC1_MARK,      DDC0_MARK,
+       SDA9_MARK,      SCL9_MARK,      SDA5_MARK,      SCL5_MARK,
+       SDA4_MARK,      SCL4_MARK,      SDA3_MARK,      SCL3_MARK,
+
+       /* PTT (mobule: SYSTEM, PWMX) */
+       AUDSYNC_MARK,           AUDCK_MARK,
+       AUDATA3_MARK,           AUDATA2_MARK,
+       AUDATA1_MARK,           AUDATA0_MARK,
+       PWX7_MARK,      PWX6_MARK,      PWX5_MARK,      PWX4_MARK,
+
+       /* PTU (mobule: LBSC, DMAC) */
+       CS6_MARK,       CS5_MARK,       CS4_MARK,       CS0_MARK,
+       RD_MARK,        WE0_MARK,       A25_MARK,       A24_MARK,
+       DREQ0_MARK,     DACK0_MARK,
+
+       /* PTV (mobule: LBSC, DMAC) */
+       A23_MARK,       A22_MARK,       A21_MARK,       A20_MARK,
+       A19_MARK,       A18_MARK,       A17_MARK,       A16_MARK,
+       TEND0_MARK,     DREQ1_MARK,     DACK1_MARK,     TEND1_MARK,
+
+       /* PTW (mobule: LBSC) */
+       A15_MARK,       A14_MARK,       A13_MARK,       A12_MARK,
+       A11_MARK,       A10_MARK,       A9_MARK,        A8_MARK,
+
+       /* PTX (mobule: LBSC) */
+       A7_MARK,        A6_MARK,        A5_MARK,        A4_MARK,
+       A3_MARK,        A2_MARK,        A1_MARK,        A0_MARK,
+
+       /* PTY (mobule: LBSC) */
+       D7_MARK,        D6_MARK,        D5_MARK,        D4_MARK,
+       D3_MARK,        D2_MARK,        D1_MARK,        D0_MARK,
+       PINMUX_MARK_END,
+};
+
+static pinmux_enum_t pinmux_data[] = {
+       /* PTA GPIO */
+       PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT),
+       PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT),
+       PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_OUT),
+       PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_OUT),
+       PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_OUT),
+       PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_OUT),
+       PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_OUT),
+       PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_OUT),
+
+       /* PTB GPIO */
+       PINMUX_DATA(PTB7_DATA, PTB7_IN, PTB7_OUT),
+       PINMUX_DATA(PTB6_DATA, PTB6_IN, PTB6_OUT),
+       PINMUX_DATA(PTB5_DATA, PTB5_IN, PTB5_OUT),
+       PINMUX_DATA(PTB4_DATA, PTB4_IN, PTB4_OUT),
+       PINMUX_DATA(PTB3_DATA, PTB3_IN, PTB3_OUT),
+       PINMUX_DATA(PTB2_DATA, PTB2_IN, PTB2_OUT),
+       PINMUX_DATA(PTB1_DATA, PTB1_IN, PTB1_OUT),
+       PINMUX_DATA(PTB0_DATA, PTB0_IN, PTB0_OUT),
+
+       /* PTC GPIO */
+       PINMUX_DATA(PTC7_DATA, PTC7_IN, PTC7_OUT),
+       PINMUX_DATA(PTC6_DATA, PTC6_IN, PTC6_OUT),
+       PINMUX_DATA(PTC5_DATA, PTC5_IN, PTC5_OUT),
+       PINMUX_DATA(PTC4_DATA, PTC4_IN, PTC4_OUT),
+       PINMUX_DATA(PTC3_DATA, PTC3_IN, PTC3_OUT),
+       PINMUX_DATA(PTC2_DATA, PTC2_IN, PTC2_OUT),
+       PINMUX_DATA(PTC1_DATA, PTC1_IN, PTC1_OUT),
+       PINMUX_DATA(PTC0_DATA, PTC0_IN, PTC0_OUT),
+
+       /* PTD GPIO */
+       PINMUX_DATA(PTD7_DATA, PTD7_IN, PTD7_OUT),
+       PINMUX_DATA(PTD6_DATA, PTD6_IN, PTD6_OUT),
+       PINMUX_DATA(PTD5_DATA, PTD5_IN, PTD5_OUT),
+       PINMUX_DATA(PTD4_DATA, PTD4_IN, PTD4_OUT),
+       PINMUX_DATA(PTD3_DATA, PTD3_IN, PTD3_OUT),
+       PINMUX_DATA(PTD2_DATA, PTD2_IN, PTD2_OUT),
+       PINMUX_DATA(PTD1_DATA, PTD1_IN, PTD1_OUT),
+       PINMUX_DATA(PTD0_DATA, PTD0_IN, PTD0_OUT),
+
+       /* PTE GPIO */
+       PINMUX_DATA(PTE5_DATA, PTE5_IN, PTE5_OUT),
+       PINMUX_DATA(PTE4_DATA, PTE4_IN, PTE4_OUT),
+       PINMUX_DATA(PTE3_DATA, PTE3_IN, PTE3_OUT),
+       PINMUX_DATA(PTE2_DATA, PTE2_IN, PTE2_OUT),
+       PINMUX_DATA(PTE1_DATA, PTE1_IN, PTE1_OUT),
+       PINMUX_DATA(PTE0_DATA, PTE0_IN, PTE0_OUT),
+
+       /* PTF GPIO */
+       PINMUX_DATA(PTF7_DATA, PTF7_IN, PTF7_OUT),
+       PINMUX_DATA(PTF6_DATA, PTF6_IN, PTF6_OUT),
+       PINMUX_DATA(PTF5_DATA, PTF5_IN, PTF5_OUT),
+       PINMUX_DATA(PTF4_DATA, PTF4_IN, PTF4_OUT),
+       PINMUX_DATA(PTF3_DATA, PTF3_IN, PTF3_OUT),
+       PINMUX_DATA(PTF2_DATA, PTF2_IN, PTF2_OUT),
+       PINMUX_DATA(PTF1_DATA, PTF1_IN, PTF1_OUT),
+       PINMUX_DATA(PTF0_DATA, PTF0_IN, PTF0_OUT),
+
+       /* PTG GPIO */
+       PINMUX_DATA(PTG7_DATA, PTG7_IN, PTG7_OUT),
+       PINMUX_DATA(PTG6_DATA, PTG6_IN, PTG6_OUT),
+       PINMUX_DATA(PTG5_DATA, PTG5_IN, PTG5_OUT),
+       PINMUX_DATA(PTG4_DATA, PTG4_IN, PTG4_OUT),
+       PINMUX_DATA(PTG3_DATA, PTG3_IN, PTG3_OUT),
+       PINMUX_DATA(PTG2_DATA, PTG2_IN, PTG2_OUT),
+       PINMUX_DATA(PTG1_DATA, PTG1_IN, PTG1_OUT),
+       PINMUX_DATA(PTG0_DATA, PTG0_IN, PTG0_OUT),
+
+       /* PTH GPIO */
+       PINMUX_DATA(PTH7_DATA, PTH7_IN, PTH7_OUT),
+       PINMUX_DATA(PTH6_DATA, PTH6_IN, PTH6_OUT),
+       PINMUX_DATA(PTH5_DATA, PTH5_IN, PTH5_OUT),
+       PINMUX_DATA(PTH4_DATA, PTH4_IN, PTH4_OUT),
+       PINMUX_DATA(PTH3_DATA, PTH3_IN, PTH3_OUT),
+       PINMUX_DATA(PTH2_DATA, PTH2_IN, PTH2_OUT),
+       PINMUX_DATA(PTH1_DATA, PTH1_IN, PTH1_OUT),
+       PINMUX_DATA(PTH0_DATA, PTH0_IN, PTH0_OUT),
+
+       /* PTI GPIO */
+       PINMUX_DATA(PTI7_DATA, PTI7_IN, PTI7_OUT),
+       PINMUX_DATA(PTI6_DATA, PTI6_IN, PTI6_OUT),
+       PINMUX_DATA(PTI5_DATA, PTI5_IN, PTI5_OUT),
+       PINMUX_DATA(PTI4_DATA, PTI4_IN, PTI4_OUT),
+       PINMUX_DATA(PTI3_DATA, PTI3_IN, PTI3_OUT),
+       PINMUX_DATA(PTI2_DATA, PTI2_IN, PTI2_OUT),
+       PINMUX_DATA(PTI1_DATA, PTI1_IN, PTI1_OUT),
+       PINMUX_DATA(PTI0_DATA, PTI0_IN, PTI0_OUT),
+
+       /* PTJ GPIO */
+       PINMUX_DATA(PTJ7_DATA, PTJ7_IN, PTJ7_OUT),
+       PINMUX_DATA(PTJ6_DATA, PTJ6_IN, PTJ6_OUT),
+       PINMUX_DATA(PTJ5_DATA, PTJ5_IN, PTJ5_OUT),
+       PINMUX_DATA(PTJ4_DATA, PTJ4_IN, PTJ4_OUT),
+       PINMUX_DATA(PTJ3_DATA, PTJ3_IN, PTJ3_OUT),
+       PINMUX_DATA(PTJ2_DATA, PTJ2_IN, PTJ2_OUT),
+       PINMUX_DATA(PTJ1_DATA, PTJ1_IN, PTJ1_OUT),
+       PINMUX_DATA(PTJ0_DATA, PTJ0_IN, PTJ0_OUT),
+
+       /* PTK GPIO */
+       PINMUX_DATA(PTK7_DATA, PTK7_IN, PTK7_OUT),
+       PINMUX_DATA(PTK6_DATA, PTK6_IN, PTK6_OUT),
+       PINMUX_DATA(PTK5_DATA, PTK5_IN, PTK5_OUT),
+       PINMUX_DATA(PTK4_DATA, PTK4_IN, PTK4_OUT),
+       PINMUX_DATA(PTK3_DATA, PTK3_IN, PTK3_OUT),
+       PINMUX_DATA(PTK2_DATA, PTK2_IN, PTK2_OUT),
+       PINMUX_DATA(PTK1_DATA, PTK1_IN, PTK1_OUT),
+       PINMUX_DATA(PTK0_DATA, PTK0_IN, PTK0_OUT),
+
+       /* PTL GPIO */
+       PINMUX_DATA(PTL7_DATA, PTL7_IN, PTL7_OUT),
+       PINMUX_DATA(PTL6_DATA, PTL6_IN, PTL6_OUT),
+       PINMUX_DATA(PTL5_DATA, PTL5_IN, PTL5_OUT),
+       PINMUX_DATA(PTL4_DATA, PTL4_IN, PTL4_OUT),
+       PINMUX_DATA(PTL3_DATA, PTL3_IN, PTL3_OUT),
+       PINMUX_DATA(PTL2_DATA, PTL2_IN, PTL2_OUT),
+       PINMUX_DATA(PTL1_DATA, PTL1_IN, PTL1_OUT),
+       PINMUX_DATA(PTL0_DATA, PTL0_IN, PTL0_OUT),
+
+       /* PTM GPIO */
+       PINMUX_DATA(PTM6_DATA, PTM6_IN, PTM6_OUT),
+       PINMUX_DATA(PTM5_DATA, PTM5_IN, PTM5_OUT),
+       PINMUX_DATA(PTM4_DATA, PTM4_IN, PTM4_OUT),
+       PINMUX_DATA(PTM3_DATA, PTM3_IN, PTM3_OUT),
+       PINMUX_DATA(PTM2_DATA, PTM2_IN, PTM2_OUT),
+       PINMUX_DATA(PTM1_DATA, PTM1_IN, PTM1_OUT),
+       PINMUX_DATA(PTM0_DATA, PTM0_IN, PTM0_OUT),
+
+       /* PTN GPIO */
+       PINMUX_DATA(PTN7_DATA, PTN7_IN, PTN7_OUT),
+       PINMUX_DATA(PTN6_DATA, PTN6_IN, PTN6_OUT),
+       PINMUX_DATA(PTN5_DATA, PTN5_IN, PTN5_OUT),
+       PINMUX_DATA(PTN4_DATA, PTN4_IN, PTN4_OUT),
+       PINMUX_DATA(PTN3_DATA, PTN3_IN, PTN3_OUT),
+       PINMUX_DATA(PTN2_DATA, PTN2_IN, PTN2_OUT),
+       PINMUX_DATA(PTN1_DATA, PTN1_IN, PTN1_OUT),
+       PINMUX_DATA(PTN0_DATA, PTN0_IN, PTN0_OUT),
+
+       /* PTO GPIO */
+       PINMUX_DATA(PTO7_DATA, PTO7_IN, PTO7_OUT),
+       PINMUX_DATA(PTO6_DATA, PTO6_IN, PTO6_OUT),
+       PINMUX_DATA(PTO5_DATA, PTO5_IN, PTO5_OUT),
+       PINMUX_DATA(PTO4_DATA, PTO4_IN, PTO4_OUT),
+       PINMUX_DATA(PTO3_DATA, PTO3_IN, PTO3_OUT),
+       PINMUX_DATA(PTO2_DATA, PTO2_IN, PTO2_OUT),
+       PINMUX_DATA(PTO1_DATA, PTO1_IN, PTO1_OUT),
+       PINMUX_DATA(PTO0_DATA, PTO0_IN, PTO0_OUT),
+
+       /* PTQ GPIO */
+       PINMUX_DATA(PTQ6_DATA, PTQ6_IN, PTQ6_OUT),
+       PINMUX_DATA(PTQ5_DATA, PTQ5_IN, PTQ5_OUT),
+       PINMUX_DATA(PTQ4_DATA, PTQ4_IN, PTQ4_OUT),
+       PINMUX_DATA(PTQ3_DATA, PTQ3_IN, PTQ3_OUT),
+       PINMUX_DATA(PTQ2_DATA, PTQ2_IN, PTQ2_OUT),
+       PINMUX_DATA(PTQ1_DATA, PTQ1_IN, PTQ1_OUT),
+       PINMUX_DATA(PTQ0_DATA, PTQ0_IN, PTQ0_OUT),
+
+       /* PTR GPIO */
+       PINMUX_DATA(PTR7_DATA, PTR7_IN, PTR7_OUT),
+       PINMUX_DATA(PTR6_DATA, PTR6_IN, PTR6_OUT),
+       PINMUX_DATA(PTR5_DATA, PTR5_IN, PTR5_OUT),
+       PINMUX_DATA(PTR4_DATA, PTR4_IN, PTR4_OUT),
+       PINMUX_DATA(PTR3_DATA, PTR3_IN, PTR3_OUT),
+       PINMUX_DATA(PTR2_DATA, PTR2_IN, PTR2_OUT),
+       PINMUX_DATA(PTR1_DATA, PTR1_IN, PTR1_OUT),
+       PINMUX_DATA(PTR0_DATA, PTR0_IN, PTR0_OUT),
+
+       /* PTS GPIO */
+       PINMUX_DATA(PTS7_DATA, PTS7_IN, PTS7_OUT),
+       PINMUX_DATA(PTS6_DATA, PTS6_IN, PTS6_OUT),
+       PINMUX_DATA(PTS5_DATA, PTS5_IN, PTS5_OUT),
+       PINMUX_DATA(PTS4_DATA, PTS4_IN, PTS4_OUT),
+       PINMUX_DATA(PTS3_DATA, PTS3_IN, PTS3_OUT),
+       PINMUX_DATA(PTS2_DATA, PTS2_IN, PTS2_OUT),
+       PINMUX_DATA(PTS1_DATA, PTS1_IN, PTS1_OUT),
+       PINMUX_DATA(PTS0_DATA, PTS0_IN, PTS0_OUT),
+
+       /* PTT GPIO */
+       PINMUX_DATA(PTT5_DATA, PTT5_IN, PTT5_OUT),
+       PINMUX_DATA(PTT4_DATA, PTT4_IN, PTT4_OUT),
+       PINMUX_DATA(PTT3_DATA, PTT3_IN, PTT3_OUT),
+       PINMUX_DATA(PTT2_DATA, PTT2_IN, PTT2_OUT),
+       PINMUX_DATA(PTT1_DATA, PTT1_IN, PTT1_OUT),
+       PINMUX_DATA(PTT0_DATA, PTT0_IN, PTT0_OUT),
+
+       /* PTU GPIO */
+       PINMUX_DATA(PTU7_DATA, PTU7_IN, PTU7_OUT),
+       PINMUX_DATA(PTU6_DATA, PTU6_IN, PTU6_OUT),
+       PINMUX_DATA(PTU5_DATA, PTU5_IN, PTU5_OUT),
+       PINMUX_DATA(PTU4_DATA, PTU4_IN, PTU4_OUT),
+       PINMUX_DATA(PTU3_DATA, PTU3_IN, PTU3_OUT),
+       PINMUX_DATA(PTU2_DATA, PTU2_IN, PTU2_OUT),
+       PINMUX_DATA(PTU1_DATA, PTU1_IN, PTU1_OUT),
+       PINMUX_DATA(PTU0_DATA, PTU0_IN, PTU0_OUT),
+
+       /* PTV GPIO */
+       PINMUX_DATA(PTV7_DATA, PTV7_IN, PTV7_OUT),
+       PINMUX_DATA(PTV6_DATA, PTV6_IN, PTV6_OUT),
+       PINMUX_DATA(PTV5_DATA, PTV5_IN, PTV5_OUT),
+       PINMUX_DATA(PTV4_DATA, PTV4_IN, PTV4_OUT),
+       PINMUX_DATA(PTV3_DATA, PTV3_IN, PTV3_OUT),
+       PINMUX_DATA(PTV2_DATA, PTV2_IN, PTV2_OUT),
+       PINMUX_DATA(PTV1_DATA, PTV1_IN, PTV1_OUT),
+       PINMUX_DATA(PTV0_DATA, PTV0_IN, PTV0_OUT),
+
+       /* PTW GPIO */
+       PINMUX_DATA(PTW7_DATA, PTW7_IN, PTW7_OUT),
+       PINMUX_DATA(PTW6_DATA, PTW6_IN, PTW6_OUT),
+       PINMUX_DATA(PTW5_DATA, PTW5_IN, PTW5_OUT),
+       PINMUX_DATA(PTW4_DATA, PTW4_IN, PTW4_OUT),
+       PINMUX_DATA(PTW3_DATA, PTW3_IN, PTW3_OUT),
+       PINMUX_DATA(PTW2_DATA, PTW2_IN, PTW2_OUT),
+       PINMUX_DATA(PTW1_DATA, PTW1_IN, PTW1_OUT),
+       PINMUX_DATA(PTW0_DATA, PTW0_IN, PTW0_OUT),
+
+       /* PTX GPIO */
+       PINMUX_DATA(PTX7_DATA, PTX7_IN, PTX7_OUT),
+       PINMUX_DATA(PTX6_DATA, PTX6_IN, PTX6_OUT),
+       PINMUX_DATA(PTX5_DATA, PTX5_IN, PTX5_OUT),
+       PINMUX_DATA(PTX4_DATA, PTX4_IN, PTX4_OUT),
+       PINMUX_DATA(PTX3_DATA, PTX3_IN, PTX3_OUT),
+       PINMUX_DATA(PTX2_DATA, PTX2_IN, PTX2_OUT),
+       PINMUX_DATA(PTX1_DATA, PTX1_IN, PTX1_OUT),
+       PINMUX_DATA(PTX0_DATA, PTX0_IN, PTX0_OUT),
+
+       /* PTY GPIO */
+       PINMUX_DATA(PTY7_DATA, PTY7_IN, PTY7_OUT),
+       PINMUX_DATA(PTY6_DATA, PTY6_IN, PTY6_OUT),
+       PINMUX_DATA(PTY5_DATA, PTY5_IN, PTY5_OUT),
+       PINMUX_DATA(PTY4_DATA, PTY4_IN, PTY4_OUT),
+       PINMUX_DATA(PTY3_DATA, PTY3_IN, PTY3_OUT),
+       PINMUX_DATA(PTY2_DATA, PTY2_IN, PTY2_OUT),
+       PINMUX_DATA(PTY1_DATA, PTY1_IN, PTY1_OUT),
+       PINMUX_DATA(PTY0_DATA, PTY0_IN, PTY0_OUT),
+
+       /* PTZ GPIO */
+       PINMUX_DATA(PTZ7_DATA, PTZ7_IN, PTZ7_OUT),
+       PINMUX_DATA(PTZ6_DATA, PTZ6_IN, PTZ6_OUT),
+       PINMUX_DATA(PTZ5_DATA, PTZ5_IN, PTZ5_OUT),
+       PINMUX_DATA(PTZ4_DATA, PTZ4_IN, PTZ4_OUT),
+       PINMUX_DATA(PTZ3_DATA, PTZ3_IN, PTZ3_OUT),
+       PINMUX_DATA(PTZ2_DATA, PTZ2_IN, PTZ2_OUT),
+       PINMUX_DATA(PTZ1_DATA, PTZ1_IN, PTZ1_OUT),
+       PINMUX_DATA(PTZ0_DATA, PTZ0_IN, PTZ0_OUT),
+
+       /* PTA FN */
+       PINMUX_DATA(BS_MARK, PS0_15_FN1, PTA7_FN),
+       PINMUX_DATA(LGPIO7_MARK, PS0_15_FN3, PTA7_FN),
+       PINMUX_DATA(RDWR_MARK, PS0_14_FN1, PTA6_FN),
+       PINMUX_DATA(LGPIO6_MARK, PS0_14_FN3, PTA6_FN),
+       PINMUX_DATA(WE1_MARK, PS0_13_FN1, PTA5_FN),
+       PINMUX_DATA(LGPIO5_MARK, PS0_13_FN3, PTA5_FN),
+       PINMUX_DATA(RDY_MARK, PS0_12_FN1, PTA4_FN),
+       PINMUX_DATA(LGPIO4_MARK, PS0_12_FN3, PTA4_FN),
+       PINMUX_DATA(LGPIO3_MARK, PTA3_FN),
+       PINMUX_DATA(LGPIO2_MARK, PTA2_FN),
+       PINMUX_DATA(LGPIO1_MARK, PTA1_FN),
+       PINMUX_DATA(LGPIO0_MARK, PTA0_FN),
+
+       /* PTB FN */
+       PINMUX_DATA(D15_MARK, PS0_7_FN1, PTB7_FN),
+       PINMUX_DATA(ET0_MDC_MARK, PS0_7_FN2, PTB7_FN),
+       PINMUX_DATA(D14_MARK, PS0_6_FN1, PTB6_FN),
+       PINMUX_DATA(ET0_MDIO_MARK, PS0_6_FN2, PTB6_FN),
+       PINMUX_DATA(D13_MARK, PS0_5_FN1, PTB5_FN),
+       PINMUX_DATA(ET1_MDC_MARK, PS0_5_FN2, PTB5_FN),
+       PINMUX_DATA(D12_MARK, PS0_4_FN1, PTB4_FN),
+       PINMUX_DATA(ET1_MDIO_MARK, PS0_4_FN2, PTB4_FN),
+       PINMUX_DATA(D11_MARK, PS0_3_FN1, PTB3_FN),
+       PINMUX_DATA(SIM_D_MARK, PS0_3_FN2, PTB3_FN),
+       PINMUX_DATA(D10_MARK, PS0_2_FN1, PTB2_FN),
+       PINMUX_DATA(SIM_CLK_MARK, PS0_2_FN2, PTB2_FN),
+       PINMUX_DATA(D9_MARK, PS0_1_FN1, PTB1_FN),
+       PINMUX_DATA(SIM_RST_MARK, PS0_1_FN2, PTB1_FN),
+       PINMUX_DATA(D8_MARK, PTB0_FN),
+
+       /* PTC FN */
+       PINMUX_DATA(SD_WP_MARK, PTC7_FN),
+       PINMUX_DATA(SD_CD_MARK, PTC6_FN),
+       PINMUX_DATA(SD_CLK_MARK, PTC5_FN),
+       PINMUX_DATA(SD_CMD_MARK, PTC4_FN),
+       PINMUX_DATA(SD_D3_MARK, PTC3_FN),
+       PINMUX_DATA(SD_D2_MARK, PTC2_FN),
+       PINMUX_DATA(SD_D1_MARK, PTC1_FN),
+       PINMUX_DATA(SD_D0_MARK, PTC0_FN),
+
+       /* PTD FN */
+       PINMUX_DATA(IRQ7_MARK, PS1_7_FN1, PTD7_FN),
+       PINMUX_DATA(ADTRG1_MARK, PS1_7_FN3, PTD7_FN),
+       PINMUX_DATA(IRQ6_MARK, PS1_6_FN1, PTD6_FN),
+       PINMUX_DATA(ADTRG0_MARK, PS1_6_FN3, PTD6_FN),
+       PINMUX_DATA(IRQ5_MARK, PTD5_FN),
+       PINMUX_DATA(IRQ4_MARK, PTD4_FN),
+       PINMUX_DATA(IRQ3_MARK, PTD3_FN),
+       PINMUX_DATA(IRQ2_MARK, PTD2_FN),
+       PINMUX_DATA(IRQ1_MARK, PTD1_FN),
+       PINMUX_DATA(IRQ0_MARK, PTD0_FN),
+
+       /* PTE FN */
+       PINMUX_DATA(ET0_CRS_DV_MARK, PTE7_FN),
+       PINMUX_DATA(ET0_TXD1_MARK, PTE6_FN),
+       PINMUX_DATA(ET0_TXD0_MARK, PTE5_FN),
+       PINMUX_DATA(ET0_TX_EN_MARK, PTE4_FN),
+       PINMUX_DATA(ET0_REF_CLK_MARK, PTE3_FN),
+       PINMUX_DATA(ET0_RXD1_MARK, PTE2_FN),
+       PINMUX_DATA(ET0_RXD0_MARK, PTE1_FN),
+       PINMUX_DATA(ET0_RX_ER_MARK, PTE0_FN),
+
+       /* PTF FN */
+       PINMUX_DATA(ET1_CRS_DV_MARK, PTF7_FN),
+       PINMUX_DATA(ET1_TXD1_MARK, PTF6_FN),
+       PINMUX_DATA(ET1_TXD0_MARK, PTF5_FN),
+       PINMUX_DATA(ET1_TX_EN_MARK, PTF4_FN),
+       PINMUX_DATA(ET1_REF_CLK_MARK, PTF3_FN),
+       PINMUX_DATA(ET1_RXD1_MARK, PTF2_FN),
+       PINMUX_DATA(ET1_RXD0_MARK, PTF1_FN),
+       PINMUX_DATA(ET1_RX_ER_MARK, PTF0_FN),
+
+       /* PTG FN */
+       PINMUX_DATA(PWX0_MARK, PTG7_FN),
+       PINMUX_DATA(PWX1_MARK, PTG6_FN),
+       PINMUX_DATA(STATUS0_MARK, PS2_13_FN1, PTG5_FN),
+       PINMUX_DATA(PWX2_MARK, PS2_13_FN3, PTG5_FN),
+       PINMUX_DATA(STATUS1_MARK, PS2_12_FN1, PTG4_FN),
+       PINMUX_DATA(PWX3_MARK, PS2_12_FN3, PTG4_FN),
+       PINMUX_DATA(SERIRQ_MARK, PTG3_FN),
+       PINMUX_DATA(CLKRUN_MARK, PTG2_FN),
+       PINMUX_DATA(LPCPD_MARK, PTG1_FN),
+       PINMUX_DATA(LDRQ_MARK, PTG0_FN),
+
+       /* PTH FN */
+       PINMUX_DATA(SP1_MOSI_MARK, PTH7_FN),
+       PINMUX_DATA(SP1_MISO_MARK, PTH6_FN),
+       PINMUX_DATA(SP1_SCK_MARK, PTH5_FN),
+       PINMUX_DATA(SP1_SCK_FB_MARK, PTH4_FN),
+       PINMUX_DATA(SP1_SS0_MARK, PTH3_FN),
+       PINMUX_DATA(TCLK_MARK, PTH2_FN),
+       PINMUX_DATA(RXD4_MARK, PS2_1_FN1, PTH1_FN),
+       PINMUX_DATA(SP1_SS1_MARK, PS2_1_FN2, PTH1_FN),
+       PINMUX_DATA(TXD4_MARK, PS2_0_FN1, PTH0_FN),
+       PINMUX_DATA(SP0_SS1_MARK, PS2_0_FN2, PTH0_FN),
+
+       /* PTI FN */
+       PINMUX_DATA(IRQ15_MARK, PTI7_FN),
+       PINMUX_DATA(IRQ14_MARK, PTI6_FN),
+       PINMUX_DATA(IRQ13_MARK, PTI5_FN),
+       PINMUX_DATA(IRQ12_MARK, PTI4_FN),
+       PINMUX_DATA(IRQ11_MARK, PTI3_FN),
+       PINMUX_DATA(IRQ10_MARK, PTI2_FN),
+       PINMUX_DATA(IRQ9_MARK, PTI1_FN),
+       PINMUX_DATA(IRQ8_MARK, PTI0_FN),
+
+       /* PTJ FN */
+       PINMUX_DATA(RXD3_MARK, PTJ7_FN),
+       PINMUX_DATA(TXD3_MARK, PTJ6_FN),
+       PINMUX_DATA(RXD2_MARK, PTJ5_FN),
+       PINMUX_DATA(TXD2_MARK, PTJ4_FN),
+       PINMUX_DATA(COM1_TXD_MARK, PTJ3_FN),
+       PINMUX_DATA(COM1_RXD_MARK, PTJ2_FN),
+       PINMUX_DATA(COM1_RTS_MARK, PTJ1_FN),
+       PINMUX_DATA(COM1_CTS_MARK, PTJ0_FN),
+
+       /* PTK FN */
+       PINMUX_DATA(COM2_TXD_MARK, PTK7_FN),
+       PINMUX_DATA(COM2_RXD_MARK, PTK6_FN),
+       PINMUX_DATA(COM2_RTS_MARK, PTK5_FN),
+       PINMUX_DATA(COM2_CTS_MARK, PTK4_FN),
+       PINMUX_DATA(COM2_DTR_MARK, PTK3_FN),
+       PINMUX_DATA(COM2_DSR_MARK, PTK2_FN),
+       PINMUX_DATA(COM2_DCD_MARK, PTK1_FN),
+       PINMUX_DATA(COM2_RI_MARK, PTK0_FN),
+
+       /* PTL FN */
+       PINMUX_DATA(RAC_TXD_MARK, PTL7_FN),
+       PINMUX_DATA(RAC_RXD_MARK, PTL6_FN),
+       PINMUX_DATA(RAC_RTS_MARK, PTL5_FN),
+       PINMUX_DATA(RAC_CTS_MARK, PTL4_FN),
+       PINMUX_DATA(RAC_DTR_MARK, PTL3_FN),
+       PINMUX_DATA(RAC_DSR_MARK, PTL2_FN),
+       PINMUX_DATA(RAC_DCD_MARK, PTL1_FN),
+       PINMUX_DATA(RAC_RI_MARK, PTL0_FN),
+
+       /* PTM FN */
+       PINMUX_DATA(WP_MARK, PTM6_FN),
+       PINMUX_DATA(FMS0_MARK, PTM5_FN),
+       PINMUX_DATA(FMS1_MARK, PTM4_FN),
+       PINMUX_DATA(SDA6_MARK, PTM3_FN),
+       PINMUX_DATA(SCL6_MARK, PTM2_FN),
+       PINMUX_DATA(SDA7_MARK, PTM1_FN),
+       PINMUX_DATA(SCL7_MARK, PTM0_FN),
+
+       /* PTN FN */
+       PINMUX_DATA(SCK2_MARK, PS4_15_FN1, PTN7_FN),
+       PINMUX_DATA(EVENT7_MARK, PS4_15_FN2, PTN7_FN),
+       PINMUX_DATA(RTS4_MARK, PS4_14_FN1, PTN6_FN),
+       PINMUX_DATA(EVENT6_MARK, PS4_14_FN2, PTN6_FN),
+       PINMUX_DATA(RTS3_MARK, PS4_13_FN1, PTN5_FN),
+       PINMUX_DATA(EVENT5_MARK, PS4_13_FN2, PTN5_FN),
+       PINMUX_DATA(RTS2_MARK, PS4_12_FN1, PTN4_FN),
+       PINMUX_DATA(EVENT4_MARK, PS4_12_FN2, PTN4_FN),
+       PINMUX_DATA(CTS4_MARK, PS4_11_FN1, PTN3_FN),
+       PINMUX_DATA(EVENT3_MARK, PS4_11_FN2, PTN3_FN),
+       PINMUX_DATA(CTS3_MARK, PS4_10_FN1, PTN2_FN),
+       PINMUX_DATA(EVENT2_MARK, PS4_10_FN2, PTN2_FN),
+       PINMUX_DATA(CTS2_MARK, PS4_9_FN1, PTN1_FN),
+       PINMUX_DATA(EVENT1_MARK, PS4_9_FN2, PTN1_FN),
+       PINMUX_DATA(EVENT0_MARK, PTN0_FN),
+
+       /* PTO FN */
+       PINMUX_DATA(SGPIO0_CLK_MARK, PTO7_FN),
+       PINMUX_DATA(SGPIO0_LOAD_MARK, PTO6_FN),
+       PINMUX_DATA(SGPIO0_DI_MARK, PTO5_FN),
+       PINMUX_DATA(SGPIO0_DO_MARK, PTO4_FN),
+       PINMUX_DATA(SGPIO1_CLK_MARK, PTO3_FN),
+       PINMUX_DATA(SGPIO1_LOAD_MARK, PTO2_FN),
+       PINMUX_DATA(SGPIO1_DI_MARK, PTO1_FN),
+       PINMUX_DATA(SGPIO1_DO_MARK, PTO0_FN),
+
+       /* PTP FN */
+       PINMUX_DATA(JMCTCK_MARK, PTP6_FN),
+       PINMUX_DATA(JMCTMS_MARK, PTP5_FN),
+       PINMUX_DATA(JMCTDO_MARK, PTP4_FN),
+       PINMUX_DATA(JMCTDI_MARK, PTP3_FN),
+       PINMUX_DATA(JMCRST_MARK, PTP2_FN),
+       PINMUX_DATA(SCK4_MARK, PTP1_FN),
+       PINMUX_DATA(SCK3_MARK, PTP0_FN),
+
+       /* PTQ FN */
+       PINMUX_DATA(LAD3_MARK, PTQ6_FN),
+       PINMUX_DATA(LAD2_MARK, PTQ5_FN),
+       PINMUX_DATA(LAD1_MARK, PTQ4_FN),
+       PINMUX_DATA(LAD0_MARK, PTQ3_FN),
+       PINMUX_DATA(LFRAME_MARK, PTQ2_FN),
+       PINMUX_DATA(SCK4_MARK, PTQ1_FN),
+       PINMUX_DATA(SCK3_MARK, PTQ0_FN),
+
+       /* PTR FN */
+       PINMUX_DATA(SDA8_MARK, PTR7_FN),        /* DDC3? */
+       PINMUX_DATA(SCL8_MARK, PTR6_FN),        /* DDC2? */
+       PINMUX_DATA(SDA2_MARK, PTR5_FN),
+       PINMUX_DATA(SCL2_MARK, PTR4_FN),
+       PINMUX_DATA(SDA1_MARK, PTR3_FN),
+       PINMUX_DATA(SCL1_MARK, PTR2_FN),
+       PINMUX_DATA(SDA0_MARK, PTR1_FN),
+       PINMUX_DATA(SCL0_MARK, PTR0_FN),
+
+       /* PTS FN */
+       PINMUX_DATA(SDA9_MARK, PTS7_FN),        /* DDC1? */
+       PINMUX_DATA(SCL9_MARK, PTS6_FN),        /* DDC0? */
+       PINMUX_DATA(SDA5_MARK, PTS5_FN),
+       PINMUX_DATA(SCL5_MARK, PTS4_FN),
+       PINMUX_DATA(SDA4_MARK, PTS3_FN),
+       PINMUX_DATA(SCL4_MARK, PTS2_FN),
+       PINMUX_DATA(SDA3_MARK, PTS1_FN),
+       PINMUX_DATA(SCL3_MARK, PTS0_FN),
+
+       /* PTT FN */
+       PINMUX_DATA(AUDSYNC_MARK, PTS5_FN),
+       PINMUX_DATA(AUDCK_MARK, PTS4_FN),
+       PINMUX_DATA(AUDATA3_MARK, PS4_3_FN1, PTS3_FN),
+       PINMUX_DATA(PWX7_MARK, PS4_3_FN2, PTS3_FN),
+       PINMUX_DATA(AUDATA2_MARK, PS4_2_FN1, PTS2_FN),
+       PINMUX_DATA(PWX6_MARK, PS4_2_FN2, PTS2_FN),
+       PINMUX_DATA(AUDATA1_MARK, PS4_1_FN1, PTS1_FN),
+       PINMUX_DATA(PWX5_MARK, PS4_1_FN2, PTS1_FN),
+       PINMUX_DATA(AUDATA0_MARK, PS4_0_FN1, PTS0_FN),
+       PINMUX_DATA(PWX4_MARK, PS4_0_FN2, PTS0_FN),
+
+       /* PTU FN */
+       PINMUX_DATA(CS6_MARK, PTU7_FN),
+       PINMUX_DATA(CS5_MARK, PTU6_FN),
+       PINMUX_DATA(CS4_MARK, PTU5_FN),
+       PINMUX_DATA(CS0_MARK, PTU4_FN),
+       PINMUX_DATA(RD_MARK, PTU3_FN),
+       PINMUX_DATA(WE0_MARK, PTU2_FN),
+       PINMUX_DATA(A25_MARK, PS5_9_FN1, PTU1_FN),
+       PINMUX_DATA(DREQ0_MARK, PS5_9_FN2, PTU1_FN),
+       PINMUX_DATA(A24_MARK, PS5_8_FN1, PTU0_FN),
+       PINMUX_DATA(DACK0_MARK, PS5_8_FN2, PTU0_FN),
+
+       /* PTV FN */
+       PINMUX_DATA(A23_MARK, PS5_7_FN1, PTV7_FN),
+       PINMUX_DATA(TEND0_MARK, PS5_7_FN2, PTV7_FN),
+       PINMUX_DATA(A22_MARK, PS5_6_FN1, PTV6_FN),
+       PINMUX_DATA(DREQ1_MARK, PS5_6_FN2, PTV6_FN),
+       PINMUX_DATA(A21_MARK, PS5_5_FN1, PTV5_FN),
+       PINMUX_DATA(DACK1_MARK, PS5_5_FN2, PTV5_FN),
+       PINMUX_DATA(A20_MARK, PS5_4_FN1, PTV4_FN),
+       PINMUX_DATA(TEND1_MARK, PS5_4_FN2, PTV4_FN),
+       PINMUX_DATA(A19_MARK, PTV3_FN),
+       PINMUX_DATA(A18_MARK, PTV2_FN),
+       PINMUX_DATA(A17_MARK, PTV1_FN),
+       PINMUX_DATA(A16_MARK, PTV0_FN),
+
+       /* PTW FN */
+       PINMUX_DATA(A15_MARK, PTW7_FN),
+       PINMUX_DATA(A14_MARK, PTW6_FN),
+       PINMUX_DATA(A13_MARK, PTW5_FN),
+       PINMUX_DATA(A12_MARK, PTW4_FN),
+       PINMUX_DATA(A11_MARK, PTW3_FN),
+       PINMUX_DATA(A10_MARK, PTW2_FN),
+       PINMUX_DATA(A9_MARK, PTW1_FN),
+       PINMUX_DATA(A8_MARK, PTW0_FN),
+
+       /* PTX FN */
+       PINMUX_DATA(A7_MARK, PTX7_FN),
+       PINMUX_DATA(A6_MARK, PTX6_FN),
+       PINMUX_DATA(A5_MARK, PTX5_FN),
+       PINMUX_DATA(A4_MARK, PTX4_FN),
+       PINMUX_DATA(A3_MARK, PTX3_FN),
+       PINMUX_DATA(A2_MARK, PTX2_FN),
+       PINMUX_DATA(A1_MARK, PTX1_FN),
+       PINMUX_DATA(A0_MARK, PTX0_FN),
+
+       /* PTY FN */
+       PINMUX_DATA(D7_MARK, PTY7_FN),
+       PINMUX_DATA(D6_MARK, PTY6_FN),
+       PINMUX_DATA(D5_MARK, PTY5_FN),
+       PINMUX_DATA(D4_MARK, PTY4_FN),
+       PINMUX_DATA(D3_MARK, PTY3_FN),
+       PINMUX_DATA(D2_MARK, PTY2_FN),
+       PINMUX_DATA(D1_MARK, PTY1_FN),
+       PINMUX_DATA(D0_MARK, PTY0_FN),
+};
+
+static struct pinmux_gpio pinmux_gpios[] = {
+       /* PTA */
+       PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
+       PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
+       PINMUX_GPIO(GPIO_PTA5, PTA5_DATA),
+       PINMUX_GPIO(GPIO_PTA4, PTA4_DATA),
+       PINMUX_GPIO(GPIO_PTA3, PTA3_DATA),
+       PINMUX_GPIO(GPIO_PTA2, PTA2_DATA),
+       PINMUX_GPIO(GPIO_PTA1, PTA1_DATA),
+       PINMUX_GPIO(GPIO_PTA0, PTA0_DATA),
+
+       /* PTB */
+       PINMUX_GPIO(GPIO_PTB7, PTB7_DATA),
+       PINMUX_GPIO(GPIO_PTB6, PTB6_DATA),
+       PINMUX_GPIO(GPIO_PTB5, PTB5_DATA),
+       PINMUX_GPIO(GPIO_PTB4, PTB4_DATA),
+       PINMUX_GPIO(GPIO_PTB3, PTB3_DATA),
+       PINMUX_GPIO(GPIO_PTB2, PTB2_DATA),
+       PINMUX_GPIO(GPIO_PTB1, PTB1_DATA),
+       PINMUX_GPIO(GPIO_PTB0, PTB0_DATA),
+
+       /* PTC */
+       PINMUX_GPIO(GPIO_PTC7, PTC7_DATA),
+       PINMUX_GPIO(GPIO_PTC6, PTC6_DATA),
+       PINMUX_GPIO(GPIO_PTC5, PTC5_DATA),
+       PINMUX_GPIO(GPIO_PTC4, PTC4_DATA),
+       PINMUX_GPIO(GPIO_PTC3, PTC3_DATA),
+       PINMUX_GPIO(GPIO_PTC2, PTC2_DATA),
+       PINMUX_GPIO(GPIO_PTC1, PTC1_DATA),
+       PINMUX_GPIO(GPIO_PTC0, PTC0_DATA),
+
+       /* PTD */
+       PINMUX_GPIO(GPIO_PTD7, PTD7_DATA),
+       PINMUX_GPIO(GPIO_PTD6, PTD6_DATA),
+       PINMUX_GPIO(GPIO_PTD5, PTD5_DATA),
+       PINMUX_GPIO(GPIO_PTD4, PTD4_DATA),
+       PINMUX_GPIO(GPIO_PTD3, PTD3_DATA),
+       PINMUX_GPIO(GPIO_PTD2, PTD2_DATA),
+       PINMUX_GPIO(GPIO_PTD1, PTD1_DATA),
+       PINMUX_GPIO(GPIO_PTD0, PTD0_DATA),
+
+       /* PTE */
+       PINMUX_GPIO(GPIO_PTE7, PTE7_DATA),
+       PINMUX_GPIO(GPIO_PTE6, PTE6_DATA),
+       PINMUX_GPIO(GPIO_PTE5, PTE5_DATA),
+       PINMUX_GPIO(GPIO_PTE4, PTE4_DATA),
+       PINMUX_GPIO(GPIO_PTE3, PTE3_DATA),
+       PINMUX_GPIO(GPIO_PTE2, PTE2_DATA),
+       PINMUX_GPIO(GPIO_PTE1, PTE1_DATA),
+       PINMUX_GPIO(GPIO_PTE0, PTE0_DATA),
+
+       /* PTF */
+       PINMUX_GPIO(GPIO_PTF7, PTF7_DATA),
+       PINMUX_GPIO(GPIO_PTF6, PTF6_DATA),
+       PINMUX_GPIO(GPIO_PTF5, PTF5_DATA),
+       PINMUX_GPIO(GPIO_PTF4, PTF4_DATA),
+       PINMUX_GPIO(GPIO_PTF3, PTF3_DATA),
+       PINMUX_GPIO(GPIO_PTF2, PTF2_DATA),
+       PINMUX_GPIO(GPIO_PTF1, PTF1_DATA),
+       PINMUX_GPIO(GPIO_PTF0, PTF0_DATA),
+
+       /* PTG */
+       PINMUX_GPIO(GPIO_PTG7, PTG7_DATA),
+       PINMUX_GPIO(GPIO_PTG6, PTG6_DATA),
+       PINMUX_GPIO(GPIO_PTG5, PTG5_DATA),
+       PINMUX_GPIO(GPIO_PTG4, PTG4_DATA),
+       PINMUX_GPIO(GPIO_PTG3, PTG3_DATA),
+       PINMUX_GPIO(GPIO_PTG2, PTG2_DATA),
+       PINMUX_GPIO(GPIO_PTG1, PTG1_DATA),
+       PINMUX_GPIO(GPIO_PTG0, PTG0_DATA),
+
+       /* PTH */
+       PINMUX_GPIO(GPIO_PTH7, PTH7_DATA),
+       PINMUX_GPIO(GPIO_PTH6, PTH6_DATA),
+       PINMUX_GPIO(GPIO_PTH5, PTH5_DATA),
+       PINMUX_GPIO(GPIO_PTH4, PTH4_DATA),
+       PINMUX_GPIO(GPIO_PTH3, PTH3_DATA),
+       PINMUX_GPIO(GPIO_PTH2, PTH2_DATA),
+       PINMUX_GPIO(GPIO_PTH1, PTH1_DATA),
+       PINMUX_GPIO(GPIO_PTH0, PTH0_DATA),
+
+       /* PTI */
+       PINMUX_GPIO(GPIO_PTI7, PTI7_DATA),
+       PINMUX_GPIO(GPIO_PTI6, PTI6_DATA),
+       PINMUX_GPIO(GPIO_PTI5, PTI5_DATA),
+       PINMUX_GPIO(GPIO_PTI4, PTI4_DATA),
+       PINMUX_GPIO(GPIO_PTI3, PTI3_DATA),
+       PINMUX_GPIO(GPIO_PTI2, PTI2_DATA),
+       PINMUX_GPIO(GPIO_PTI1, PTI1_DATA),
+       PINMUX_GPIO(GPIO_PTI0, PTI0_DATA),
+
+       /* PTJ */
+       PINMUX_GPIO(GPIO_PTJ7, PTJ7_DATA),
+       PINMUX_GPIO(GPIO_PTJ6, PTJ6_DATA),
+       PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
+       PINMUX_GPIO(GPIO_PTJ4, PTJ4_DATA),
+       PINMUX_GPIO(GPIO_PTJ3, PTJ3_DATA),
+       PINMUX_GPIO(GPIO_PTJ2, PTJ2_DATA),
+       PINMUX_GPIO(GPIO_PTJ1, PTJ1_DATA),
+       PINMUX_GPIO(GPIO_PTJ0, PTJ0_DATA),
+
+       /* PTK */
+       PINMUX_GPIO(GPIO_PTK7, PTK7_DATA),
+       PINMUX_GPIO(GPIO_PTK6, PTK6_DATA),
+       PINMUX_GPIO(GPIO_PTK5, PTK5_DATA),
+       PINMUX_GPIO(GPIO_PTK4, PTK4_DATA),
+       PINMUX_GPIO(GPIO_PTK3, PTK3_DATA),
+       PINMUX_GPIO(GPIO_PTK2, PTK2_DATA),
+       PINMUX_GPIO(GPIO_PTK1, PTK1_DATA),
+       PINMUX_GPIO(GPIO_PTK0, PTK0_DATA),
+
+       /* PTL */
+       PINMUX_GPIO(GPIO_PTL7, PTL7_DATA),
+       PINMUX_GPIO(GPIO_PTL6, PTL6_DATA),
+       PINMUX_GPIO(GPIO_PTL5, PTL5_DATA),
+       PINMUX_GPIO(GPIO_PTL4, PTL4_DATA),
+       PINMUX_GPIO(GPIO_PTL3, PTL3_DATA),
+       PINMUX_GPIO(GPIO_PTL2, PTL2_DATA),
+       PINMUX_GPIO(GPIO_PTL1, PTL1_DATA),
+       PINMUX_GPIO(GPIO_PTL0, PTL0_DATA),
+
+       /* PTM */
+       PINMUX_GPIO(GPIO_PTM6, PTM6_DATA),
+       PINMUX_GPIO(GPIO_PTM5, PTM5_DATA),
+       PINMUX_GPIO(GPIO_PTM4, PTM4_DATA),
+       PINMUX_GPIO(GPIO_PTM3, PTM3_DATA),
+       PINMUX_GPIO(GPIO_PTM2, PTM2_DATA),
+       PINMUX_GPIO(GPIO_PTM1, PTM1_DATA),
+       PINMUX_GPIO(GPIO_PTM0, PTM0_DATA),
+
+       /* PTN */
+       PINMUX_GPIO(GPIO_PTN7, PTN7_DATA),
+       PINMUX_GPIO(GPIO_PTN6, PTN6_DATA),
+       PINMUX_GPIO(GPIO_PTN5, PTN5_DATA),
+       PINMUX_GPIO(GPIO_PTN4, PTN4_DATA),
+       PINMUX_GPIO(GPIO_PTN3, PTN3_DATA),
+       PINMUX_GPIO(GPIO_PTN2, PTN2_DATA),
+       PINMUX_GPIO(GPIO_PTN1, PTN1_DATA),
+       PINMUX_GPIO(GPIO_PTN0, PTN0_DATA),
+
+       /* PTO */
+       PINMUX_GPIO(GPIO_PTO7, PTO7_DATA),
+       PINMUX_GPIO(GPIO_PTO6, PTO6_DATA),
+       PINMUX_GPIO(GPIO_PTO5, PTO5_DATA),
+       PINMUX_GPIO(GPIO_PTO4, PTO4_DATA),
+       PINMUX_GPIO(GPIO_PTO3, PTO3_DATA),
+       PINMUX_GPIO(GPIO_PTO2, PTO2_DATA),
+       PINMUX_GPIO(GPIO_PTO1, PTO1_DATA),
+       PINMUX_GPIO(GPIO_PTO0, PTO0_DATA),
+
+       /* PTP */
+       PINMUX_GPIO(GPIO_PTP6, PTP6_DATA),
+       PINMUX_GPIO(GPIO_PTP5, PTP5_DATA),
+       PINMUX_GPIO(GPIO_PTP4, PTP4_DATA),
+       PINMUX_GPIO(GPIO_PTP3, PTP3_DATA),
+       PINMUX_GPIO(GPIO_PTP2, PTP2_DATA),
+       PINMUX_GPIO(GPIO_PTP1, PTP1_DATA),
+       PINMUX_GPIO(GPIO_PTP0, PTP0_DATA),
+
+       /* PTQ */
+       PINMUX_GPIO(GPIO_PTQ6, PTQ6_DATA),
+       PINMUX_GPIO(GPIO_PTQ5, PTQ5_DATA),
+       PINMUX_GPIO(GPIO_PTQ4, PTQ4_DATA),
+       PINMUX_GPIO(GPIO_PTQ3, PTQ3_DATA),
+       PINMUX_GPIO(GPIO_PTQ2, PTQ2_DATA),
+       PINMUX_GPIO(GPIO_PTQ1, PTQ1_DATA),
+       PINMUX_GPIO(GPIO_PTQ0, PTQ0_DATA),
+
+       /* PTR */
+       PINMUX_GPIO(GPIO_PTR7, PTR7_DATA),
+       PINMUX_GPIO(GPIO_PTR6, PTR6_DATA),
+       PINMUX_GPIO(GPIO_PTR5, PTR5_DATA),
+       PINMUX_GPIO(GPIO_PTR4, PTR4_DATA),
+       PINMUX_GPIO(GPIO_PTR3, PTR3_DATA),
+       PINMUX_GPIO(GPIO_PTR2, PTR2_DATA),
+       PINMUX_GPIO(GPIO_PTR1, PTR1_DATA),
+       PINMUX_GPIO(GPIO_PTR0, PTR0_DATA),
+
+       /* PTS */
+       PINMUX_GPIO(GPIO_PTS7, PTS7_DATA),
+       PINMUX_GPIO(GPIO_PTS6, PTS6_DATA),
+       PINMUX_GPIO(GPIO_PTS5, PTS5_DATA),
+       PINMUX_GPIO(GPIO_PTS4, PTS4_DATA),
+       PINMUX_GPIO(GPIO_PTS3, PTS3_DATA),
+       PINMUX_GPIO(GPIO_PTS2, PTS2_DATA),
+       PINMUX_GPIO(GPIO_PTS1, PTS1_DATA),
+       PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
+
+       /* PTT */
+       PINMUX_GPIO(GPIO_PTT5, PTT5_DATA),
+       PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
+       PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
+       PINMUX_GPIO(GPIO_PTT2, PTT2_DATA),
+       PINMUX_GPIO(GPIO_PTT1, PTT1_DATA),
+       PINMUX_GPIO(GPIO_PTT0, PTT0_DATA),
+
+       /* PTU */
+       PINMUX_GPIO(GPIO_PTU7, PTU7_DATA),
+       PINMUX_GPIO(GPIO_PTU6, PTU6_DATA),
+       PINMUX_GPIO(GPIO_PTU5, PTU5_DATA),
+       PINMUX_GPIO(GPIO_PTU4, PTU4_DATA),
+       PINMUX_GPIO(GPIO_PTU3, PTU3_DATA),
+       PINMUX_GPIO(GPIO_PTU2, PTU2_DATA),
+       PINMUX_GPIO(GPIO_PTU1, PTU1_DATA),
+       PINMUX_GPIO(GPIO_PTU0, PTU0_DATA),
+
+       /* PTV */
+       PINMUX_GPIO(GPIO_PTV7, PTV7_DATA),
+       PINMUX_GPIO(GPIO_PTV6, PTV6_DATA),
+       PINMUX_GPIO(GPIO_PTV5, PTV5_DATA),
+       PINMUX_GPIO(GPIO_PTV4, PTV4_DATA),
+       PINMUX_GPIO(GPIO_PTV3, PTV3_DATA),
+       PINMUX_GPIO(GPIO_PTV2, PTV2_DATA),
+       PINMUX_GPIO(GPIO_PTV1, PTV1_DATA),
+       PINMUX_GPIO(GPIO_PTV0, PTV0_DATA),
+
+       /* PTW */
+       PINMUX_GPIO(GPIO_PTW7, PTW7_DATA),
+       PINMUX_GPIO(GPIO_PTW6, PTW6_DATA),
+       PINMUX_GPIO(GPIO_PTW5, PTW5_DATA),
+       PINMUX_GPIO(GPIO_PTW4, PTW4_DATA),
+       PINMUX_GPIO(GPIO_PTW3, PTW3_DATA),
+       PINMUX_GPIO(GPIO_PTW2, PTW2_DATA),
+       PINMUX_GPIO(GPIO_PTW1, PTW1_DATA),
+       PINMUX_GPIO(GPIO_PTW0, PTW0_DATA),
+
+       /* PTX */
+       PINMUX_GPIO(GPIO_PTX7, PTX7_DATA),
+       PINMUX_GPIO(GPIO_PTX6, PTX6_DATA),
+       PINMUX_GPIO(GPIO_PTX5, PTX5_DATA),
+       PINMUX_GPIO(GPIO_PTX4, PTX4_DATA),
+       PINMUX_GPIO(GPIO_PTX3, PTX3_DATA),
+       PINMUX_GPIO(GPIO_PTX2, PTX2_DATA),
+       PINMUX_GPIO(GPIO_PTX1, PTX1_DATA),
+       PINMUX_GPIO(GPIO_PTX0, PTX0_DATA),
+
+       /* PTY */
+       PINMUX_GPIO(GPIO_PTY7, PTY7_DATA),
+       PINMUX_GPIO(GPIO_PTY6, PTY6_DATA),
+       PINMUX_GPIO(GPIO_PTY5, PTY5_DATA),
+       PINMUX_GPIO(GPIO_PTY4, PTY4_DATA),
+       PINMUX_GPIO(GPIO_PTY3, PTY3_DATA),
+       PINMUX_GPIO(GPIO_PTY2, PTY2_DATA),
+       PINMUX_GPIO(GPIO_PTY1, PTY1_DATA),
+       PINMUX_GPIO(GPIO_PTY0, PTY0_DATA),
+
+       /* PTZ */
+       PINMUX_GPIO(GPIO_PTZ7, PTZ7_DATA),
+       PINMUX_GPIO(GPIO_PTZ6, PTZ6_DATA),
+       PINMUX_GPIO(GPIO_PTZ5, PTZ5_DATA),
+       PINMUX_GPIO(GPIO_PTZ4, PTZ4_DATA),
+       PINMUX_GPIO(GPIO_PTZ3, PTZ3_DATA),
+       PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
+       PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
+       PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA),
+
+       /* PTA (mobule: LBSC, CPG, LPC) */
+       PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
+       PINMUX_GPIO(GPIO_FN_RDWR, RDWR_MARK),
+       PINMUX_GPIO(GPIO_FN_WE1, WE1_MARK),
+       PINMUX_GPIO(GPIO_FN_RDY, RDY_MARK),
+       PINMUX_GPIO(GPIO_FN_MD10, MD10_MARK),
+       PINMUX_GPIO(GPIO_FN_MD9, MD9_MARK),
+       PINMUX_GPIO(GPIO_FN_MD8, MD8_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO7, LGPIO7_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO6, LGPIO6_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO5, LGPIO5_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO4, LGPIO4_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO3, LGPIO3_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO2, LGPIO2_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO1, LGPIO1_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO0, LGPIO0_MARK),
+
+       /* PTB (mobule: LBSC, EtherC, SIM, LPC) */
+       PINMUX_GPIO(GPIO_FN_D15, D15_MARK),
+       PINMUX_GPIO(GPIO_FN_D14, D14_MARK),
+       PINMUX_GPIO(GPIO_FN_D13, D13_MARK),
+       PINMUX_GPIO(GPIO_FN_D12, D12_MARK),
+       PINMUX_GPIO(GPIO_FN_D11, D11_MARK),
+       PINMUX_GPIO(GPIO_FN_D10, D10_MARK),
+       PINMUX_GPIO(GPIO_FN_D9, D9_MARK),
+       PINMUX_GPIO(GPIO_FN_D8, D8_MARK),
+       PINMUX_GPIO(GPIO_FN_ET0_MDC, ET0_MDC_MARK),
+       PINMUX_GPIO(GPIO_FN_ET0_MDIO, ET0_MDIO_MARK),
+       PINMUX_GPIO(GPIO_FN_ET1_MDC, ET1_MDC_MARK),
+       PINMUX_GPIO(GPIO_FN_ET1_MDIO, ET1_MDIO_MARK),
+       PINMUX_GPIO(GPIO_FN_WPSZ1, WPSZ1_MARK),
+       PINMUX_GPIO(GPIO_FN_WPSZ0, WPSZ0_MARK),
+       PINMUX_GPIO(GPIO_FN_FWID, FWID_MARK),
+       PINMUX_GPIO(GPIO_FN_FLSHSZ, FLSHSZ_MARK),
+       PINMUX_GPIO(GPIO_FN_LPC_SPIEN, LPC_SPIEN_MARK),
+       PINMUX_GPIO(GPIO_FN_BASEL, BASEL_MARK),
+
+       /* PTC (mobule: SD) */
+       PINMUX_GPIO(GPIO_FN_SD_WP, SD_WP_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_CD, SD_CD_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_CLK, SD_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_CMD, SD_CMD_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_D3, SD_D3_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_D2, SD_D2_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_D1, SD_D1_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_D0, SD_D0_MARK),
+
+       /* PTD (mobule: INTC, SPI0, LBSC, CPG, ADC) */
+       PINMUX_GPIO(GPIO_FN_IRQ7, IRQ7_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ6, IRQ6_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ5, IRQ5_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ4, IRQ4_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ3, IRQ3_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ2, IRQ2_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ1, IRQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ0, IRQ0_MARK),
+       PINMUX_GPIO(GPIO_FN_MD6, MD6_MARK),
+       PINMUX_GPIO(GPIO_FN_MD5, MD5_MARK),
+       PINMUX_GPIO(GPIO_FN_MD3, MD3_MARK),
+       PINMUX_GPIO(GPIO_FN_MD2, MD2_MARK),
+       PINMUX_GPIO(GPIO_FN_MD1, MD1_MARK),
+       PINMUX_GPIO(GPIO_FN_MD0, MD0_MARK),
+       PINMUX_GPIO(GPIO_FN_ADTRG1, ADTRG1_MARK),
+       PINMUX_GPIO(GPIO_FN_ADTRG0, ADTRG0_MARK),
+
+       /* PTE (mobule: EtherC) */
+       PINMUX_GPIO(GPIO_FN_ET0_CRS_DV, ET0_CRS_DV_MARK),
+       PINMUX_GPIO(GPIO_FN_ET0_TXD1, ET0_TXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_ET0_TXD0, ET0_TXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_ET0_TX_EN, ET0_TX_EN_MARK),
+       PINMUX_GPIO(GPIO_FN_ET0_REF_CLK, ET0_REF_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_ET0_RXD1, ET0_RXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_ET0_RXD0, ET0_RXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_ET0_RX_ER, ET0_RX_ER_MARK),
+
+       /* PTF (mobule: EtherC) */
+       PINMUX_GPIO(GPIO_FN_ET1_CRS_DV, ET1_CRS_DV_MARK),
+       PINMUX_GPIO(GPIO_FN_ET1_TXD1, ET1_TXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_ET1_TXD0, ET1_TXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_ET1_TX_EN, ET1_TX_EN_MARK),
+       PINMUX_GPIO(GPIO_FN_ET1_REF_CLK, ET1_REF_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_ET1_RXD1, ET1_RXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_ET1_RXD0, ET1_RXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_ET1_RX_ER, ET1_RX_ER_MARK),
+
+       /* PTG (mobule: SYSTEM, PWMX, LPC) */
+       PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
+       PINMUX_GPIO(GPIO_FN_STATUS1, STATUS1_MARK),
+       PINMUX_GPIO(GPIO_FN_PWX0, PWX0_MARK),
+       PINMUX_GPIO(GPIO_FN_PWX1, PWX1_MARK),
+       PINMUX_GPIO(GPIO_FN_PWX2, PWX2_MARK),
+       PINMUX_GPIO(GPIO_FN_PWX3, PWX3_MARK),
+       PINMUX_GPIO(GPIO_FN_SERIRQ, SERIRQ_MARK),
+       PINMUX_GPIO(GPIO_FN_CLKRUN, CLKRUN_MARK),
+       PINMUX_GPIO(GPIO_FN_LPCPD, LPCPD_MARK),
+       PINMUX_GPIO(GPIO_FN_LDRQ, LDRQ_MARK),
+
+       /* PTH (mobule: TMU, SCIF234, SPI1, SPI0) */
+       PINMUX_GPIO(GPIO_FN_TCLK, TCLK_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD4, RXD4_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD4, TXD4_MARK),
+       PINMUX_GPIO(GPIO_FN_SP1_MOSI, SP1_MOSI_MARK),
+       PINMUX_GPIO(GPIO_FN_SP1_MISO, SP1_MISO_MARK),
+       PINMUX_GPIO(GPIO_FN_SP1_SCK, SP1_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SP1_SCK_FB, SP1_SCK_FB_MARK),
+       PINMUX_GPIO(GPIO_FN_SP1_SS0, SP1_SS0_MARK),
+       PINMUX_GPIO(GPIO_FN_SP1_SS1, SP1_SS1_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SS1, SP0_SS1_MARK),
+
+       /* PTI (mobule: INTC) */
+       PINMUX_GPIO(GPIO_FN_IRQ15, IRQ15_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ14, IRQ14_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ13, IRQ13_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ12, IRQ12_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ11, IRQ11_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ10, IRQ10_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ9, IRQ9_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ8, IRQ8_MARK),
+
+       /* PTJ (mobule: SCIF234, SERMUX) */
+       PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD3, TXD3_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK),
+       PINMUX_GPIO(GPIO_FN_COM1_TXD, COM1_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_COM1_RXD, COM1_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_COM1_RTS, COM1_RTS_MARK),
+       PINMUX_GPIO(GPIO_FN_COM1_CTS, COM1_CTS_MARK),
+
+       /* PTK (mobule: SERMUX) */
+       PINMUX_GPIO(GPIO_FN_COM2_TXD, COM2_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_COM2_RXD, COM2_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_COM2_RTS, COM2_RTS_MARK),
+       PINMUX_GPIO(GPIO_FN_COM2_CTS, COM2_CTS_MARK),
+       PINMUX_GPIO(GPIO_FN_COM2_DTR, COM2_DTR_MARK),
+       PINMUX_GPIO(GPIO_FN_COM2_DSR, COM2_DSR_MARK),
+       PINMUX_GPIO(GPIO_FN_COM2_DCD, COM2_DCD_MARK),
+       PINMUX_GPIO(GPIO_FN_COM2_RI, COM2_RI_MARK),
+
+       /* PTL (mobule: SERMUX) */
+       PINMUX_GPIO(GPIO_FN_RAC_TXD, RAC_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_RAC_RXD, RAC_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_RAC_RTS, RAC_RTS_MARK),
+       PINMUX_GPIO(GPIO_FN_RAC_CTS, RAC_CTS_MARK),
+       PINMUX_GPIO(GPIO_FN_RAC_DTR, RAC_DTR_MARK),
+       PINMUX_GPIO(GPIO_FN_RAC_DSR, RAC_DSR_MARK),
+       PINMUX_GPIO(GPIO_FN_RAC_DCD, RAC_DCD_MARK),
+       PINMUX_GPIO(GPIO_FN_RAC_RI, RAC_RI_MARK),
+
+       /* PTM (mobule: IIC, LPC) */
+       PINMUX_GPIO(GPIO_FN_SDA6, SDA6_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL6, SCL6_MARK),
+       PINMUX_GPIO(GPIO_FN_SDA7, SDA7_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL7, SCL7_MARK),
+       PINMUX_GPIO(GPIO_FN_WP, WP_MARK),
+       PINMUX_GPIO(GPIO_FN_FMS0, FMS0_MARK),
+       PINMUX_GPIO(GPIO_FN_FMS1, FMS1_MARK),
+
+       /* PTN (mobule: SCIF234, EVC) */
+       PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK),
+       PINMUX_GPIO(GPIO_FN_RTS4, RTS4_MARK),
+       PINMUX_GPIO(GPIO_FN_RTS3, RTS3_MARK),
+       PINMUX_GPIO(GPIO_FN_RTS2, RTS2_MARK),
+       PINMUX_GPIO(GPIO_FN_CTS4, CTS4_MARK),
+       PINMUX_GPIO(GPIO_FN_CTS3, CTS3_MARK),
+       PINMUX_GPIO(GPIO_FN_CTS2, CTS2_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT7, EVENT7_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT6, EVENT6_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT5, EVENT5_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT4, EVENT4_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT3, EVENT3_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT2, EVENT2_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT1, EVENT1_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT0, EVENT0_MARK),
+
+       /* PTO (mobule: SGPIO) */
+       PINMUX_GPIO(GPIO_FN_SGPIO0_CLK, SGPIO0_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO0_LOAD, SGPIO0_LOAD_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO0_DI, SGPIO0_DI_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO0_DO, SGPIO0_DO_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO1_CLK, SGPIO1_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO1_LOAD, SGPIO1_LOAD_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO1_DI, SGPIO1_DI_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO1_DO, SGPIO1_DO_MARK),
+
+       /* PTP (mobule: JMC, SCIF234) */
+       PINMUX_GPIO(GPIO_FN_JMCTCK, JMCTCK_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTMS, JMCTMS_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTDO, JMCTDO_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTDI, JMCTDI_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCRST, JMCRST_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK4, SCK4_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK),
+
+       /* PTQ (mobule: LPC) */
+       PINMUX_GPIO(GPIO_FN_LAD3, LAD3_MARK),
+       PINMUX_GPIO(GPIO_FN_LAD2, LAD2_MARK),
+       PINMUX_GPIO(GPIO_FN_LAD1, LAD1_MARK),
+       PINMUX_GPIO(GPIO_FN_LAD0, LAD0_MARK),
+       PINMUX_GPIO(GPIO_FN_LFRAME, LFRAME_MARK),
+       PINMUX_GPIO(GPIO_FN_LRESET, LRESET_MARK),
+       PINMUX_GPIO(GPIO_FN_LCLK, LCLK_MARK),
+
+       /* PTR (mobule: GRA, IIC) */
+       PINMUX_GPIO(GPIO_FN_DDC3, DDC3_MARK),
+       PINMUX_GPIO(GPIO_FN_DDC2, DDC2_MARK),
+       PINMUX_GPIO(GPIO_FN_SDA8, SDA8_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL8, SCL8_MARK),
+       PINMUX_GPIO(GPIO_FN_SDA2, SDA2_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL2, SCL2_MARK),
+       PINMUX_GPIO(GPIO_FN_SDA1, SDA1_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL1, SCL1_MARK),
+       PINMUX_GPIO(GPIO_FN_SDA0, SDA0_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL0, SCL0_MARK),
+
+       /* PTS (mobule: GRA, IIC) */
+       PINMUX_GPIO(GPIO_FN_DDC1, DDC1_MARK),
+       PINMUX_GPIO(GPIO_FN_DDC0, DDC0_MARK),
+       PINMUX_GPIO(GPIO_FN_SDA9, SDA9_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL9, SCL9_MARK),
+       PINMUX_GPIO(GPIO_FN_SDA5, SDA5_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL5, SCL5_MARK),
+       PINMUX_GPIO(GPIO_FN_SDA4, SDA4_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL4, SCL4_MARK),
+       PINMUX_GPIO(GPIO_FN_SDA3, SDA3_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL3, SCL3_MARK),
+
+       /* PTT (mobule: SYSTEM, PWMX) */
+       PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA3, AUDATA3_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA2, AUDATA2_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA1, AUDATA1_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA0, AUDATA0_MARK),
+       PINMUX_GPIO(GPIO_FN_PWX7, PWX7_MARK),
+       PINMUX_GPIO(GPIO_FN_PWX6, PWX6_MARK),
+       PINMUX_GPIO(GPIO_FN_PWX5, PWX5_MARK),
+       PINMUX_GPIO(GPIO_FN_PWX4, PWX4_MARK),
+
+       /* PTU (mobule: LBSC, DMAC) */
+       PINMUX_GPIO(GPIO_FN_CS6, CS6_MARK),
+       PINMUX_GPIO(GPIO_FN_CS5, CS5_MARK),
+       PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK),
+       PINMUX_GPIO(GPIO_FN_CS0, CS0_MARK),
+       PINMUX_GPIO(GPIO_FN_RD, RD_MARK),
+       PINMUX_GPIO(GPIO_FN_WE0, WE0_MARK),
+       PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
+       PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
+
+       /* PTV (mobule: LBSC, DMAC) */
+       PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
+       PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
+       PINMUX_GPIO(GPIO_FN_A21, A21_MARK),
+       PINMUX_GPIO(GPIO_FN_A20, A20_MARK),
+       PINMUX_GPIO(GPIO_FN_A19, A19_MARK),
+       PINMUX_GPIO(GPIO_FN_A18, A18_MARK),
+       PINMUX_GPIO(GPIO_FN_A17, A17_MARK),
+       PINMUX_GPIO(GPIO_FN_A16, A16_MARK),
+       PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
+       PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK),
+
+       /* PTW (mobule: LBSC) */
+       PINMUX_GPIO(GPIO_FN_A16, A16_MARK),
+       PINMUX_GPIO(GPIO_FN_A15, A15_MARK),
+       PINMUX_GPIO(GPIO_FN_A14, A14_MARK),
+       PINMUX_GPIO(GPIO_FN_A13, A13_MARK),
+       PINMUX_GPIO(GPIO_FN_A12, A12_MARK),
+       PINMUX_GPIO(GPIO_FN_A11, A11_MARK),
+       PINMUX_GPIO(GPIO_FN_A10, A10_MARK),
+       PINMUX_GPIO(GPIO_FN_A9, A9_MARK),
+       PINMUX_GPIO(GPIO_FN_A8, A8_MARK),
+
+       /* PTX (mobule: LBSC) */
+       PINMUX_GPIO(GPIO_FN_A7, A7_MARK),
+       PINMUX_GPIO(GPIO_FN_A6, A6_MARK),
+       PINMUX_GPIO(GPIO_FN_A5, A5_MARK),
+       PINMUX_GPIO(GPIO_FN_A4, A4_MARK),
+       PINMUX_GPIO(GPIO_FN_A3, A3_MARK),
+       PINMUX_GPIO(GPIO_FN_A2, A2_MARK),
+       PINMUX_GPIO(GPIO_FN_A1, A1_MARK),
+       PINMUX_GPIO(GPIO_FN_A0, A0_MARK),
+
+       /* PTY (mobule: LBSC) */
+       PINMUX_GPIO(GPIO_FN_D7, D7_MARK),
+       PINMUX_GPIO(GPIO_FN_D6, D6_MARK),
+       PINMUX_GPIO(GPIO_FN_D5, D5_MARK),
+       PINMUX_GPIO(GPIO_FN_D4, D4_MARK),
+       PINMUX_GPIO(GPIO_FN_D3, D3_MARK),
+       PINMUX_GPIO(GPIO_FN_D2, D2_MARK),
+       PINMUX_GPIO(GPIO_FN_D1, D1_MARK),
+       PINMUX_GPIO(GPIO_FN_D0, D0_MARK),
+ };
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+       { PINMUX_CFG_REG("PACR", 0xffec0000, 16, 2) {
+               PTA7_FN, PTA7_OUT, PTA7_IN, 0,
+               PTA6_FN, PTA6_OUT, PTA6_IN, 0,
+               PTA5_FN, PTA5_OUT, PTA5_IN, 0,
+               PTA4_FN, PTA4_OUT, PTA4_IN, 0,
+               PTA3_FN, PTA3_OUT, PTA3_IN, 0,
+               PTA2_FN, PTA2_OUT, PTA2_IN, 0,
+               PTA1_FN, PTA1_OUT, PTA1_IN, 0,
+               PTA0_FN, PTA0_OUT, PTA0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PBCR", 0xffec0002, 16, 2) {
+               PTB7_FN, PTB7_OUT, PTB7_IN, 0,
+               PTB6_FN, PTB6_OUT, PTB6_IN, 0,
+               PTB5_FN, PTB5_OUT, PTB5_IN, 0,
+               PTB4_FN, PTB4_OUT, PTB4_IN, 0,
+               PTB3_FN, PTB3_OUT, PTB3_IN, 0,
+               PTB2_FN, PTB2_OUT, PTB2_IN, 0,
+               PTB1_FN, PTB1_OUT, PTB1_IN, 0,
+               PTB0_FN, PTB0_OUT, PTB0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PCCR", 0xffec0004, 16, 2) {
+               PTC7_FN, PTC7_OUT, PTC7_IN, 0,
+               PTC6_FN, PTC6_OUT, PTC6_IN, 0,
+               PTC5_FN, PTC5_OUT, PTC5_IN, 0,
+               PTC4_FN, PTC4_OUT, PTC4_IN, 0,
+               PTC3_FN, PTC3_OUT, PTC3_IN, 0,
+               PTC2_FN, PTC2_OUT, PTC2_IN, 0,
+               PTC1_FN, PTC1_OUT, PTC1_IN, 0,
+               PTC0_FN, PTC0_OUT, PTC0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PDCR", 0xffec0006, 16, 2) {
+               PTD7_FN, PTD7_OUT, PTD7_IN, 0,
+               PTD6_FN, PTD6_OUT, PTD6_IN, 0,
+               PTD5_FN, PTD5_OUT, PTD5_IN, 0,
+               PTD4_FN, PTD4_OUT, PTD4_IN, 0,
+               PTD3_FN, PTD3_OUT, PTD3_IN, 0,
+               PTD2_FN, PTD2_OUT, PTD2_IN, 0,
+               PTD1_FN, PTD1_OUT, PTD1_IN, 0,
+               PTD0_FN, PTD0_OUT, PTD0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PECR", 0xffec0008, 16, 2) {
+               PTE7_FN, PTE7_OUT, PTE7_IN, 0,
+               PTE6_FN, PTE6_OUT, PTE6_IN, 0,
+               PTE5_FN, PTE5_OUT, PTE5_IN, 0,
+               PTE4_FN, PTE4_OUT, PTE4_IN, 0,
+               PTE3_FN, PTE3_OUT, PTE3_IN, 0,
+               PTE2_FN, PTE2_OUT, PTE2_IN, 0,
+               PTE1_FN, PTE1_OUT, PTE1_IN, 0,
+               PTE0_FN, PTE0_OUT, PTE0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PFCR", 0xffec000a, 16, 2) {
+               PTF7_FN, PTF7_OUT, PTF7_IN, 0,
+               PTF6_FN, PTF6_OUT, PTF6_IN, 0,
+               PTF5_FN, PTF5_OUT, PTF5_IN, 0,
+               PTF4_FN, PTF4_OUT, PTF4_IN, 0,
+               PTF3_FN, PTF3_OUT, PTF3_IN, 0,
+               PTF2_FN, PTF2_OUT, PTF2_IN, 0,
+               PTF1_FN, PTF1_OUT, PTF1_IN, 0,
+               PTF0_FN, PTF0_OUT, PTF0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PGCR", 0xffec000c, 16, 2) {
+               PTG7_FN, PTG7_OUT, PTG7_IN, 0,
+               PTG6_FN, PTG6_OUT, PTG6_IN, 0,
+               PTG5_FN, PTG5_OUT, PTG5_IN, 0,
+               PTG4_FN, PTG4_OUT, PTG4_IN, 0,
+               PTG3_FN, PTG3_OUT, PTG3_IN, 0,
+               PTG2_FN, PTG2_OUT, PTG2_IN, 0,
+               PTG1_FN, PTG1_OUT, PTG1_IN, 0,
+               PTG0_FN, PTG0_OUT, PTG0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PHCR", 0xffec000e, 16, 2) {
+               PTH7_FN, PTH7_OUT, PTH7_IN, 0,
+               PTH6_FN, PTH6_OUT, PTH6_IN, 0,
+               PTH5_FN, PTH5_OUT, PTH5_IN, 0,
+               PTH4_FN, PTH4_OUT, PTH4_IN, 0,
+               PTH3_FN, PTH3_OUT, PTH3_IN, 0,
+               PTH2_FN, PTH2_OUT, PTH2_IN, 0,
+               PTH1_FN, PTH1_OUT, PTH1_IN, 0,
+               PTH0_FN, PTH0_OUT, PTH0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PICR", 0xffec0010, 16, 2) {
+               PTI7_FN, PTI7_OUT, PTI7_IN, 0,
+               PTI6_FN, PTI6_OUT, PTI6_IN, 0,
+               PTI5_FN, PTI5_OUT, PTI5_IN, 0,
+               PTI4_FN, PTI4_OUT, PTI4_IN, 0,
+               PTI3_FN, PTI3_OUT, PTI3_IN, 0,
+               PTI2_FN, PTI2_OUT, PTI2_IN, 0,
+               PTI1_FN, PTI1_OUT, PTI1_IN, 0,
+               PTI0_FN, PTI0_OUT, PTI0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PJCR", 0xffec0012, 16, 2) {
+               PTJ7_FN, PTJ7_OUT, PTJ7_IN, 0,
+               PTJ6_FN, PTJ6_OUT, PTJ6_IN, 0,
+               PTJ5_FN, PTJ5_OUT, PTJ5_IN, 0,
+               PTJ4_FN, PTJ4_OUT, PTJ4_IN, 0,
+               PTJ3_FN, PTJ3_OUT, PTJ3_IN, 0,
+               PTJ2_FN, PTJ2_OUT, PTJ2_IN, 0,
+               PTJ1_FN, PTJ1_OUT, PTJ1_IN, 0,
+               PTJ0_FN, PTJ0_OUT, PTJ0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PKCR", 0xffec0014, 16, 2) {
+               PTK7_FN, PTK7_OUT, PTK7_IN, 0,
+               PTK6_FN, PTK6_OUT, PTK6_IN, 0,
+               PTK5_FN, PTK5_OUT, PTK5_IN, 0,
+               PTK4_FN, PTK4_OUT, PTK4_IN, 0,
+               PTK3_FN, PTK3_OUT, PTK3_IN, 0,
+               PTK2_FN, PTK2_OUT, PTK2_IN, 0,
+               PTK1_FN, PTK1_OUT, PTK1_IN, 0,
+               PTK0_FN, PTK0_OUT, PTK0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PLCR", 0xffec0016, 16, 2) {
+               PTL7_FN, PTL7_OUT, PTL7_IN, 0,
+               PTL6_FN, PTL6_OUT, PTL6_IN, 0,
+               PTL5_FN, PTL5_OUT, PTL5_IN, 0,
+               PTL4_FN, PTL4_OUT, PTL4_IN, 0,
+               PTL3_FN, PTL3_OUT, PTL3_IN, 0,
+               PTL2_FN, PTL2_OUT, PTL2_IN, 0,
+               PTL1_FN, PTL1_OUT, PTL1_IN, 0,
+               PTL0_FN, PTL0_OUT, PTL0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PMCR", 0xffec0018, 16, 2) {
+               0, 0, 0, 0,     /* reserved: always set 1 */
+               PTM6_FN, PTM6_OUT, PTM6_IN, 0,
+               PTM5_FN, PTM5_OUT, PTM5_IN, 0,
+               PTM4_FN, PTM4_OUT, PTM4_IN, 0,
+               PTM3_FN, PTM3_OUT, PTM3_IN, 0,
+               PTM2_FN, PTM2_OUT, PTM2_IN, 0,
+               PTM1_FN, PTM1_OUT, PTM1_IN, 0,
+               PTM0_FN, PTM0_OUT, PTM0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PNCR", 0xffec001a, 16, 2) {
+               PTN7_FN, PTN7_OUT, PTN7_IN, 0,
+               PTN6_FN, PTN6_OUT, PTN6_IN, 0,
+               PTN5_FN, PTN5_OUT, PTN5_IN, 0,
+               PTN4_FN, PTN4_OUT, PTN4_IN, 0,
+               PTN3_FN, PTN3_OUT, PTN3_IN, 0,
+               PTN2_FN, PTN2_OUT, PTN2_IN, 0,
+               PTN1_FN, PTN1_OUT, PTN1_IN, 0,
+               PTN0_FN, PTN0_OUT, PTN0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("POCR", 0xffec001c, 16, 2) {
+               PTO7_FN, PTO7_OUT, PTO7_IN, 0,
+               PTO6_FN, PTO6_OUT, PTO6_IN, 0,
+               PTO5_FN, PTO5_OUT, PTO5_IN, 0,
+               PTO4_FN, PTO4_OUT, PTO4_IN, 0,
+               PTO3_FN, PTO3_OUT, PTO3_IN, 0,
+               PTO2_FN, PTO2_OUT, PTO2_IN, 0,
+               PTO1_FN, PTO1_OUT, PTO1_IN, 0,
+               PTO0_FN, PTO0_OUT, PTO0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PPCR", 0xffec001e, 16, 2) {
+               0, 0, 0, 0,     /* reserved: always set 1 */
+               PTP6_FN, PTP6_OUT, PTP6_IN, 0,
+               PTP5_FN, PTP5_OUT, PTP5_IN, 0,
+               PTP4_FN, PTP4_OUT, PTP4_IN, 0,
+               PTP3_FN, PTP3_OUT, PTP3_IN, 0,
+               PTP2_FN, PTP2_OUT, PTP2_IN, 0,
+               PTP1_FN, PTP1_OUT, PTP1_IN, 0,
+               PTP0_FN, PTP0_OUT, PTP0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PQCR", 0xffec0020, 16, 2) {
+               0, 0, 0, 0,     /* reserved: always set 1 */
+               PTQ6_FN, PTQ6_OUT, PTQ6_IN, 0,
+               PTQ5_FN, PTQ5_OUT, PTQ5_IN, 0,
+               PTQ4_FN, PTQ4_OUT, PTQ4_IN, 0,
+               PTQ3_FN, PTQ3_OUT, PTQ3_IN, 0,
+               PTQ2_FN, PTQ2_OUT, PTQ2_IN, 0,
+               PTQ1_FN, PTQ1_OUT, PTQ1_IN, 0,
+               PTQ0_FN, PTQ0_OUT, PTQ0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PRCR", 0xffec0022, 16, 2) {
+               PTR7_FN, PTR7_OUT, PTR7_IN, 0,
+               PTR6_FN, PTR6_OUT, PTR6_IN, 0,
+               PTR5_FN, PTR5_OUT, PTR5_IN, 0,
+               PTR4_FN, PTR4_OUT, PTR4_IN, 0,
+               PTR3_FN, PTR3_OUT, PTR3_IN, 0,
+               PTR2_FN, PTR2_OUT, PTR2_IN, 0,
+               PTR1_FN, PTR1_OUT, PTR1_IN, 0,
+               PTR0_FN, PTR0_OUT, PTR0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PSCR", 0xffec0024, 16, 2) {
+               PTS7_FN, PTS7_OUT, PTS7_IN, 0,
+               PTS6_FN, PTS6_OUT, PTS6_IN, 0,
+               PTS5_FN, PTS5_OUT, PTS5_IN, 0,
+               PTS4_FN, PTS4_OUT, PTS4_IN, 0,
+               PTS3_FN, PTS3_OUT, PTS3_IN, 0,
+               PTS2_FN, PTS2_OUT, PTS2_IN, 0,
+               PTS1_FN, PTS1_OUT, PTS1_IN, 0,
+               PTS0_FN, PTS0_OUT, PTS0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PTCR", 0xffec0026, 16, 2) {
+               0, 0, 0, 0,     /* reserved: always set 1 */
+               0, 0, 0, 0,     /* reserved: always set 1 */
+               PTT5_FN, PTT5_OUT, PTT5_IN, 0,
+               PTT4_FN, PTT4_OUT, PTT4_IN, 0,
+               PTT3_FN, PTT3_OUT, PTT3_IN, 0,
+               PTT2_FN, PTT2_OUT, PTT2_IN, 0,
+               PTT1_FN, PTT1_OUT, PTT1_IN, 0,
+               PTT0_FN, PTT0_OUT, PTT0_IN, 0 }
+       },
+       { PINMUX_CFG_REG("PUCR", 0xffec0028, 16, 2) {
+               PTU7_FN, PTU7_OUT, PTU7_IN, PTU7_IN_PU,
+               PTU6_FN, PTU6_OUT, PTU6_IN, PTU6_IN_PU,
+               PTU5_FN, PTU5_OUT, PTU5_IN, PTU5_IN_PU,
+               PTU4_FN, PTU4_OUT, PTU4_IN, PTU4_IN_PU,
+               PTU3_FN, PTU3_OUT, PTU3_IN, PTU3_IN_PU,
+               PTU2_FN, PTU2_OUT, PTU2_IN, PTU2_IN_PU,
+               PTU1_FN, PTU1_OUT, PTU1_IN, PTU1_IN_PU,
+               PTU0_FN, PTU0_OUT, PTU0_IN, PTU0_IN_PU }
+       },
+       { PINMUX_CFG_REG("PVCR", 0xffec002a, 16, 2) {
+               PTV7_FN, PTV7_OUT, PTV7_IN, PTV7_IN_PU,
+               PTV6_FN, PTV6_OUT, PTV6_IN, PTV6_IN_PU,
+               PTV5_FN, PTV5_OUT, PTV5_IN, PTV5_IN_PU,
+               PTV4_FN, PTV4_OUT, PTV4_IN, PTV4_IN_PU,
+               PTV3_FN, PTV3_OUT, PTV3_IN, PTV3_IN_PU,
+               PTV2_FN, PTV2_OUT, PTV2_IN, PTV2_IN_PU,
+               PTV1_FN, PTV1_OUT, PTV1_IN, PTV1_IN_PU,
+               PTV0_FN, PTV0_OUT, PTV0_IN, PTV0_IN_PU }
+       },
+       { PINMUX_CFG_REG("PWCR", 0xffec002c, 16, 2) {
+               PTW7_FN, PTW7_OUT, PTW7_IN, PTW7_IN_PU,
+               PTW6_FN, PTW6_OUT, PTW6_IN, PTW6_IN_PU,
+               PTW5_FN, PTW5_OUT, PTW5_IN, PTW5_IN_PU,
+               PTW4_FN, PTW4_OUT, PTW4_IN, PTW4_IN_PU,
+               PTW3_FN, PTW3_OUT, PTW3_IN, PTW3_IN_PU,
+               PTW2_FN, PTW2_OUT, PTW2_IN, PTW2_IN_PU,
+               PTW1_FN, PTW1_OUT, PTW1_IN, PTW1_IN_PU,
+               PTW0_FN, PTW0_OUT, PTW0_IN, PTW0_IN_PU }
+       },
+       { PINMUX_CFG_REG("PXCR", 0xffec002e, 16, 2) {
+               PTX7_FN, PTX7_OUT, PTX7_IN, PTX7_IN_PU,
+               PTX6_FN, PTX6_OUT, PTX6_IN, PTX6_IN_PU,
+               PTX5_FN, PTX5_OUT, PTX5_IN, PTX5_IN_PU,
+               PTX4_FN, PTX4_OUT, PTX4_IN, PTX4_IN_PU,
+               PTX3_FN, PTX3_OUT, PTX3_IN, PTX3_IN_PU,
+               PTX2_FN, PTX2_OUT, PTX2_IN, PTX2_IN_PU,
+               PTX1_FN, PTX1_OUT, PTX1_IN, PTX1_IN_PU,
+               PTX0_FN, PTX0_OUT, PTX0_IN, PTX0_IN_PU }
+       },
+       { PINMUX_CFG_REG("PYCR", 0xffec0030, 16, 2) {
+               PTY7_FN, PTY7_OUT, PTY7_IN, PTY7_IN_PU,
+               PTY6_FN, PTY6_OUT, PTY6_IN, PTY6_IN_PU,
+               PTY5_FN, PTY5_OUT, PTY5_IN, PTY5_IN_PU,
+               PTY4_FN, PTY4_OUT, PTY4_IN, PTY4_IN_PU,
+               PTY3_FN, PTY3_OUT, PTY3_IN, PTY3_IN_PU,
+               PTY2_FN, PTY2_OUT, PTY2_IN, PTY2_IN_PU,
+               PTY1_FN, PTY1_OUT, PTY1_IN, PTY1_IN_PU,
+               PTY0_FN, PTY0_OUT, PTY0_IN, PTY0_IN_PU }
+       },
+       { PINMUX_CFG_REG("PZCR", 0xffec0032, 16, 2) {
+               0, PTZ7_OUT, PTZ7_IN, 0,
+               0, PTZ6_OUT, PTZ6_IN, 0,
+               0, PTZ5_OUT, PTZ5_IN, 0,
+               0, PTZ4_OUT, PTZ4_IN, 0,
+               0, PTZ3_OUT, PTZ3_IN, 0,
+               0, PTZ2_OUT, PTZ2_IN, 0,
+               0, PTZ1_OUT, PTZ1_IN, 0,
+               0, PTZ0_OUT, PTZ0_IN, 0 }
+       },
+
+       { PINMUX_CFG_REG("PSEL0", 0xffec0070, 16, 1) {
+               PS0_15_FN3, PS0_15_FN1,
+               PS0_14_FN3, PS0_14_FN1,
+               PS0_13_FN3, PS0_13_FN1,
+               PS0_12_FN3, PS0_12_FN1,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               PS0_7_FN2, PS0_7_FN1,
+               PS0_6_FN2, PS0_6_FN1,
+               PS0_5_FN2, PS0_5_FN1,
+               PS0_4_FN2, PS0_4_FN1,
+               PS0_3_FN2, PS0_3_FN1,
+               PS0_2_FN2, PS0_2_FN1,
+               PS0_1_FN2, PS0_1_FN1,
+               0, 0, }
+       },
+       { PINMUX_CFG_REG("PSEL1", 0xffec0072, 16, 1) {
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               PS1_7_FN1, PS1_7_FN3,
+               PS1_6_FN1, PS1_6_FN3,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0, }
+       },
+       { PINMUX_CFG_REG("PSEL2", 0xffec0074, 16, 1) {
+               0, 0,
+               0, 0,
+               PS2_13_FN3, PS2_13_FN1,
+               PS2_12_FN3, PS2_12_FN1,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               PS2_1_FN1, PS2_1_FN2,
+               PS2_0_FN1, PS2_0_FN2, }
+       },
+       { PINMUX_CFG_REG("PSEL4", 0xffec0078, 16, 1) {
+               PS4_15_FN2, PS4_15_FN1,
+               PS4_14_FN2, PS4_14_FN1,
+               PS4_13_FN2, PS4_13_FN1,
+               PS4_12_FN2, PS4_12_FN1,
+               PS4_11_FN2, PS4_11_FN1,
+               PS4_10_FN2, PS4_10_FN1,
+               PS4_9_FN2, PS4_9_FN1,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               PS4_3_FN2, PS4_3_FN1,
+               PS4_2_FN2, PS4_2_FN1,
+               PS4_1_FN2, PS4_1_FN1,
+               PS4_0_FN2, PS4_0_FN1, }
+       },
+       { PINMUX_CFG_REG("PSEL5", 0xffec007a, 16, 1) {
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               PS5_9_FN1, PS5_9_FN2,
+               PS5_8_FN1, PS5_8_FN2,
+               PS5_7_FN1, PS5_7_FN2,
+               PS5_6_FN1, PS5_6_FN2,
+               PS5_5_FN1, PS5_5_FN2,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0, }
+       },
+       { PINMUX_CFG_REG("PSEL6", 0xffec007c, 16, 1) {
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               PS6_7_FN_AN, PS6_7_FN_EV,
+               PS6_6_FN_AN, PS6_6_FN_EV,
+               PS6_5_FN_AN, PS6_5_FN_EV,
+               PS6_4_FN_AN, PS6_4_FN_EV,
+               PS6_3_FN_AN, PS6_3_FN_EV,
+               PS6_2_FN_AN, PS6_2_FN_EV,
+               PS6_1_FN_AN, PS6_1_FN_EV,
+               PS6_0_FN_AN, PS6_0_FN_EV, }
+       },
+       {}
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+       { PINMUX_DATA_REG("PADR", 0xffec0034, 8) {
+               PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
+               PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA }
+       },
+       { PINMUX_DATA_REG("PBDR", 0xffec0036, 8) {
+               PTB7_DATA, PTB6_DATA, PTB5_DATA, PTB4_DATA,
+               PTB3_DATA, PTB2_DATA, PTB1_DATA, PTB0_DATA }
+       },
+       { PINMUX_DATA_REG("PCDR", 0xffec0038, 8) {
+               PTC7_DATA, PTC6_DATA, PTC5_DATA, PTC4_DATA,
+               PTC3_DATA, PTC2_DATA, PTC1_DATA, PTC0_DATA }
+       },
+       { PINMUX_DATA_REG("PDDR", 0xffec003a, 8) {
+               PTD7_DATA, PTD6_DATA, PTD5_DATA, PTD4_DATA,
+               PTD3_DATA, PTD2_DATA, PTD1_DATA, PTD0_DATA }
+       },
+       { PINMUX_DATA_REG("PEDR", 0xffec003c, 8) {
+               PTE7_DATA, PTE6_DATA, PTE5_DATA, PTE4_DATA,
+               PTE3_DATA, PTE2_DATA, PTE1_DATA, PTE0_DATA }
+       },
+       { PINMUX_DATA_REG("PFDR", 0xffec003e, 8) {
+               PTF7_DATA, PTF6_DATA, PTF5_DATA, PTF4_DATA,
+               PTF3_DATA, PTF2_DATA, PTF1_DATA, PTF0_DATA }
+       },
+       { PINMUX_DATA_REG("PGDR", 0xffec0040, 8) {
+               PTG7_DATA, PTG6_DATA, PTG5_DATA, PTG4_DATA,
+               PTG3_DATA, PTG2_DATA, PTG1_DATA, PTG0_DATA }
+       },
+       { PINMUX_DATA_REG("PHDR", 0xffec0042, 8) {
+               PTH7_DATA, PTH6_DATA, PTH5_DATA, PTH4_DATA,
+               PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA }
+       },
+       { PINMUX_DATA_REG("PIDR", 0xffec0044, 8) {
+               PTI7_DATA, PTI6_DATA, PTI5_DATA, PTI4_DATA,
+               PTI3_DATA, PTI2_DATA, PTI1_DATA, PTI0_DATA }
+       },
+       { PINMUX_DATA_REG("PJDR", 0xffec0046, 8) {
+               PTJ7_DATA, PTJ6_DATA, PTJ5_DATA, PTJ4_DATA,
+               PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA }
+       },
+       { PINMUX_DATA_REG("PKDR", 0xffec0048, 8) {
+               PTK7_DATA, PTK6_DATA, PTK5_DATA, PTK4_DATA,
+               PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA }
+       },
+       { PINMUX_DATA_REG("PLDR", 0xffec004a, 8) {
+               PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+               PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA }
+       },
+       { PINMUX_DATA_REG("PMDR", 0xffec004c, 8) {
+               0, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+               PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA }
+       },
+       { PINMUX_DATA_REG("PNDR", 0xffec004e, 8) {
+               PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+               PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA }
+       },
+       { PINMUX_DATA_REG("PODR", 0xffec0050, 8) {
+               PTO7_DATA, PTO6_DATA, PTO5_DATA, PTO4_DATA,
+               PTO3_DATA, PTO2_DATA, PTO1_DATA, PTO0_DATA }
+       },
+       { PINMUX_DATA_REG("PPDR", 0xffec0052, 8) {
+               0, PTP6_DATA, PTP5_DATA, PTP4_DATA,
+               PTP3_DATA, PTP2_DATA, PTP1_DATA, PTP0_DATA }
+       },
+       { PINMUX_DATA_REG("PQDR", 0xffec0054, 8) {
+               0, PTQ6_DATA, PTQ5_DATA, PTQ4_DATA,
+               PTQ3_DATA, PTQ2_DATA, PTQ1_DATA, PTQ0_DATA }
+       },
+       { PINMUX_DATA_REG("PRDR", 0xffec0056, 8) {
+               PTR7_DATA, PTR6_DATA, PTR5_DATA, PTR4_DATA,
+               PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA }
+       },
+       { PINMUX_DATA_REG("PSDR", 0xffec0058, 8) {
+               PTS7_DATA, PTS6_DATA, PTS5_DATA, PTS4_DATA,
+               PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA }
+       },
+       { PINMUX_DATA_REG("PTDR", 0xffec005a, 8) {
+               0, 0, PTT5_DATA, PTT4_DATA,
+               PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA }
+       },
+       { PINMUX_DATA_REG("PUDR", 0xffec005c, 8) {
+               PTU7_DATA, PTU6_DATA, PTU5_DATA, PTU4_DATA,
+               PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA }
+       },
+       { PINMUX_DATA_REG("PVDR", 0xffec005e, 8) {
+               PTV7_DATA, PTV6_DATA, PTV5_DATA, PTV4_DATA,
+               PTV3_DATA, PTV2_DATA, PTV1_DATA, PTV0_DATA }
+       },
+       { PINMUX_DATA_REG("PWDR", 0xffec0060, 8) {
+               PTW7_DATA, PTW6_DATA, PTW5_DATA, PTW4_DATA,
+               PTW3_DATA, PTW2_DATA, PTW1_DATA, PTW0_DATA }
+       },
+       { PINMUX_DATA_REG("PXDR", 0xffec0062, 8) {
+               PTX7_DATA, PTX6_DATA, PTX5_DATA, PTX4_DATA,
+               PTX3_DATA, PTX2_DATA, PTX1_DATA, PTX0_DATA }
+       },
+       { PINMUX_DATA_REG("PYDR", 0xffec0064, 8) {
+               PTY7_DATA, PTY6_DATA, PTY5_DATA, PTY4_DATA,
+               PTY3_DATA, PTY2_DATA, PTY1_DATA, PTY0_DATA }
+       },
+       { PINMUX_DATA_REG("PZDR", 0xffec0066, 8) {
+               PTZ7_DATA, PTZ6_DATA, PTZ5_DATA, PTZ4_DATA,
+               PTZ3_DATA, PTZ2_DATA, PTZ1_DATA, PTZ0_DATA }
+       },
+       { },
+};
+
+static struct pinmux_info sh7757_pinmux_info = {
+       .name = "sh7757_pfc",
+       .reserved_id = PINMUX_RESERVED,
+       .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+       .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
+       .input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
+       .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
+       .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
+       .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+       .first_gpio = GPIO_PTA7,
+       .last_gpio = GPIO_FN_D0,
+
+       .gpios = pinmux_gpios,
+       .cfg_regs = pinmux_config_regs,
+       .data_regs = pinmux_data_regs,
+
+       .gpio_data = pinmux_data,
+       .gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+static int __init plat_pinmux_setup(void)
+{
+       return register_pinmux(&sh7757_pinmux_info);
+}
+
+arch_initcall(plat_pinmux_setup);
index 1a956b1..4a9010b 100644 (file)
@@ -40,7 +40,7 @@ static struct platform_device iic_device = {
 };
 
 static struct r8a66597_platdata r8a66597_data = {
-       /* This set zero to all members */
+       .on_chip = 1,
 };
 
 static struct resource usb_host_resources[] = {
index cda76eb..3509775 100644 (file)
 #include <linux/serial_sci.h>
 #include <linux/mm.h>
 #include <linux/uio_driver.h>
+#include <linux/usb/m66592.h>
 #include <linux/sh_timer.h>
 #include <asm/clock.h>
 #include <asm/mmzone.h>
+#include <cpu/sh7722.h>
 
 static struct resource rtc_resources[] = {
        [0] = {
@@ -45,11 +47,18 @@ static struct platform_device rtc_device = {
        .id             = -1,
        .num_resources  = ARRAY_SIZE(rtc_resources),
        .resource       = rtc_resources,
+       .archdata = {
+               .hwblk_id = HWBLK_RTC,
+       },
+};
+
+static struct m66592_platdata usbf_platdata = {
+       .on_chip = 1,
 };
 
 static struct resource usbf_resources[] = {
        [0] = {
-               .name   = "m66592_udc",
+               .name   = "USBF",
                .start  = 0x04480000,
                .end    = 0x044800FF,
                .flags  = IORESOURCE_MEM,
@@ -67,9 +76,13 @@ static struct platform_device usbf_device = {
        .dev = {
                .dma_mask               = NULL,
                .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &usbf_platdata,
        },
        .num_resources  = ARRAY_SIZE(usbf_resources),
        .resource       = usbf_resources,
+       .archdata = {
+               .hwblk_id = HWBLK_USBF,
+       },
 };
 
 static struct resource iic_resources[] = {
@@ -91,6 +104,9 @@ static struct platform_device iic_device = {
        .id             = 0, /* "i2c0" clock */
        .num_resources  = ARRAY_SIZE(iic_resources),
        .resource       = iic_resources,
+       .archdata = {
+               .hwblk_id = HWBLK_IIC,
+       },
 };
 
 static struct uio_info vpu_platform_data = {
@@ -119,6 +135,9 @@ static struct platform_device vpu_device = {
        },
        .resource       = vpu_resources,
        .num_resources  = ARRAY_SIZE(vpu_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_VPU,
+       },
 };
 
 static struct uio_info veu_platform_data = {
@@ -147,6 +166,9 @@ static struct platform_device veu_device = {
        },
        .resource       = veu_resources,
        .num_resources  = ARRAY_SIZE(veu_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_VEU,
+       },
 };
 
 static struct uio_info jpu_platform_data = {
@@ -175,6 +197,9 @@ static struct platform_device jpu_device = {
        },
        .resource       = jpu_resources,
        .num_resources  = ARRAY_SIZE(jpu_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_JPU,
+       },
 };
 
 static struct sh_timer_config cmt_platform_data = {
@@ -207,6 +232,9 @@ static struct platform_device cmt_device = {
        },
        .resource       = cmt_resources,
        .num_resources  = ARRAY_SIZE(cmt_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_CMT,
+       },
 };
 
 static struct sh_timer_config tmu0_platform_data = {
@@ -238,6 +266,9 @@ static struct platform_device tmu0_device = {
        },
        .resource       = tmu0_resources,
        .num_resources  = ARRAY_SIZE(tmu0_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU,
+       },
 };
 
 static struct sh_timer_config tmu1_platform_data = {
@@ -269,6 +300,9 @@ static struct platform_device tmu1_device = {
        },
        .resource       = tmu1_resources,
        .num_resources  = ARRAY_SIZE(tmu1_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU,
+       },
 };
 
 static struct sh_timer_config tmu2_platform_data = {
@@ -299,6 +333,9 @@ static struct platform_device tmu2_device = {
        },
        .resource       = tmu2_resources,
        .num_resources  = ARRAY_SIZE(tmu2_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU,
+       },
 };
 
 static struct plat_sci_port sci_platform_data[] = {
index b45dace..4caa5a7 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <asm/clock.h>
 #include <asm/mmzone.h>
+#include <cpu/sh7723.h>
 
 static struct uio_info vpu_platform_data = {
        .name = "VPU5",
@@ -45,6 +46,9 @@ static struct platform_device vpu_device = {
        },
        .resource       = vpu_resources,
        .num_resources  = ARRAY_SIZE(vpu_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_VPU,
+       },
 };
 
 static struct uio_info veu0_platform_data = {
@@ -73,6 +77,9 @@ static struct platform_device veu0_device = {
        },
        .resource       = veu0_resources,
        .num_resources  = ARRAY_SIZE(veu0_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_VEU2H0,
+       },
 };
 
 static struct uio_info veu1_platform_data = {
@@ -101,6 +108,9 @@ static struct platform_device veu1_device = {
        },
        .resource       = veu1_resources,
        .num_resources  = ARRAY_SIZE(veu1_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_VEU2H1,
+       },
 };
 
 static struct sh_timer_config cmt_platform_data = {
@@ -133,6 +143,9 @@ static struct platform_device cmt_device = {
        },
        .resource       = cmt_resources,
        .num_resources  = ARRAY_SIZE(cmt_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_CMT,
+       },
 };
 
 static struct sh_timer_config tmu0_platform_data = {
@@ -164,6 +177,9 @@ static struct platform_device tmu0_device = {
        },
        .resource       = tmu0_resources,
        .num_resources  = ARRAY_SIZE(tmu0_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU0,
+       },
 };
 
 static struct sh_timer_config tmu1_platform_data = {
@@ -195,6 +211,9 @@ static struct platform_device tmu1_device = {
        },
        .resource       = tmu1_resources,
        .num_resources  = ARRAY_SIZE(tmu1_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU0,
+       },
 };
 
 static struct sh_timer_config tmu2_platform_data = {
@@ -225,6 +244,9 @@ static struct platform_device tmu2_device = {
        },
        .resource       = tmu2_resources,
        .num_resources  = ARRAY_SIZE(tmu2_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU0,
+       },
 };
 
 static struct sh_timer_config tmu3_platform_data = {
@@ -255,6 +277,9 @@ static struct platform_device tmu3_device = {
        },
        .resource       = tmu3_resources,
        .num_resources  = ARRAY_SIZE(tmu3_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU1,
+       },
 };
 
 static struct sh_timer_config tmu4_platform_data = {
@@ -285,6 +310,9 @@ static struct platform_device tmu4_device = {
        },
        .resource       = tmu4_resources,
        .num_resources  = ARRAY_SIZE(tmu4_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU1,
+       },
 };
 
 static struct sh_timer_config tmu5_platform_data = {
@@ -315,6 +343,9 @@ static struct platform_device tmu5_device = {
        },
        .resource       = tmu5_resources,
        .num_resources  = ARRAY_SIZE(tmu5_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU1,
+       },
 };
 
 static struct plat_sci_port sci_platform_data[] = {
@@ -395,10 +426,13 @@ static struct platform_device rtc_device = {
        .id             = -1,
        .num_resources  = ARRAY_SIZE(rtc_resources),
        .resource       = rtc_resources,
+       .archdata = {
+               .hwblk_id = HWBLK_RTC,
+       },
 };
 
 static struct r8a66597_platdata r8a66597_data = {
-       /* This set zero to all members */
+       .on_chip = 1,
 };
 
 static struct resource sh7723_usb_host_resources[] = {
@@ -424,6 +458,9 @@ static struct platform_device sh7723_usb_host_device = {
        },
        .num_resources  = ARRAY_SIZE(sh7723_usb_host_resources),
        .resource       = sh7723_usb_host_resources,
+       .archdata = {
+               .hwblk_id = HWBLK_USB,
+       },
 };
 
 static struct resource iic_resources[] = {
@@ -445,6 +482,9 @@ static struct platform_device iic_device = {
        .id             = 0, /* "i2c0" clock */
        .num_resources  = ARRAY_SIZE(iic_resources),
        .resource       = iic_resources,
+       .archdata = {
+               .hwblk_id = HWBLK_IIC,
+       },
 };
 
 static struct platform_device *sh7723_devices[] __initdata = {
index a04edaa..f3851fd 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <asm/clock.h>
 #include <asm/mmzone.h>
+#include <cpu/sh7724.h>
 
 /* Serial */
 static struct plat_sci_port sci_platform_data[] = {
@@ -103,6 +104,9 @@ static struct platform_device rtc_device = {
        .id             = -1,
        .num_resources  = ARRAY_SIZE(rtc_resources),
        .resource       = rtc_resources,
+       .archdata = {
+               .hwblk_id = HWBLK_RTC,
+       },
 };
 
 /* I2C0 */
@@ -125,6 +129,9 @@ static struct platform_device iic0_device = {
        .id             = 0, /* "i2c0" clock */
        .num_resources  = ARRAY_SIZE(iic0_resources),
        .resource       = iic0_resources,
+       .archdata = {
+               .hwblk_id = HWBLK_IIC0,
+       },
 };
 
 /* I2C1 */
@@ -147,6 +154,9 @@ static struct platform_device iic1_device = {
        .id             = 1, /* "i2c1" clock */
        .num_resources  = ARRAY_SIZE(iic1_resources),
        .resource       = iic1_resources,
+       .archdata = {
+               .hwblk_id = HWBLK_IIC1,
+       },
 };
 
 /* VPU */
@@ -176,6 +186,9 @@ static struct platform_device vpu_device = {
        },
        .resource       = vpu_resources,
        .num_resources  = ARRAY_SIZE(vpu_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_VPU,
+       },
 };
 
 /* VEU0 */
@@ -205,6 +218,9 @@ static struct platform_device veu0_device = {
        },
        .resource       = veu0_resources,
        .num_resources  = ARRAY_SIZE(veu0_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_VEU0,
+       },
 };
 
 /* VEU1 */
@@ -234,6 +250,9 @@ static struct platform_device veu1_device = {
        },
        .resource       = veu1_resources,
        .num_resources  = ARRAY_SIZE(veu1_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_VEU1,
+       },
 };
 
 static struct sh_timer_config cmt_platform_data = {
@@ -266,6 +285,9 @@ static struct platform_device cmt_device = {
        },
        .resource       = cmt_resources,
        .num_resources  = ARRAY_SIZE(cmt_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_CMT,
+       },
 };
 
 static struct sh_timer_config tmu0_platform_data = {
@@ -297,6 +319,9 @@ static struct platform_device tmu0_device = {
        },
        .resource       = tmu0_resources,
        .num_resources  = ARRAY_SIZE(tmu0_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU0,
+       },
 };
 
 static struct sh_timer_config tmu1_platform_data = {
@@ -328,6 +353,9 @@ static struct platform_device tmu1_device = {
        },
        .resource       = tmu1_resources,
        .num_resources  = ARRAY_SIZE(tmu1_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU0,
+       },
 };
 
 static struct sh_timer_config tmu2_platform_data = {
@@ -358,6 +386,9 @@ static struct platform_device tmu2_device = {
        },
        .resource       = tmu2_resources,
        .num_resources  = ARRAY_SIZE(tmu2_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU0,
+       },
 };
 
 
@@ -389,6 +420,9 @@ static struct platform_device tmu3_device = {
        },
        .resource       = tmu3_resources,
        .num_resources  = ARRAY_SIZE(tmu3_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU1,
+       },
 };
 
 static struct sh_timer_config tmu4_platform_data = {
@@ -419,6 +453,9 @@ static struct platform_device tmu4_device = {
        },
        .resource       = tmu4_resources,
        .num_resources  = ARRAY_SIZE(tmu4_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU1,
+       },
 };
 
 static struct sh_timer_config tmu5_platform_data = {
@@ -449,6 +486,9 @@ static struct platform_device tmu5_device = {
        },
        .resource       = tmu5_resources,
        .num_resources  = ARRAY_SIZE(tmu5_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_TMU1,
+       },
 };
 
 /* JPU */
@@ -478,6 +518,9 @@ static struct platform_device jpu_device = {
        },
        .resource       = jpu_resources,
        .num_resources  = ARRAY_SIZE(jpu_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_JPU,
+       },
 };
 
 static struct platform_device *sh7724_devices[] __initdata = {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
new file mode 100644 (file)
index 0000000..c470e15
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ * SH7757 Setup
+ *
+ * Copyright (C) 2009  Renesas Solutions Corp.
+ *
+ *  based on setup-sh7785.c : Copyright (C) 2007  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.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_sci.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/sh_timer.h>
+
+static struct sh_timer_config tmu0_platform_data = {
+       .name = "TMU0",
+       .channel_offset = 0x04,
+       .timer_bit = 0,
+       .clk = "peripheral_clk",
+       .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+       [0] = {
+               .name   = "TMU0",
+               .start  = 0xfe430008,
+               .end    = 0xfe430013,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 28,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device tmu0_device = {
+       .name           = "sh_tmu",
+       .id             = 0,
+       .dev = {
+               .platform_data  = &tmu0_platform_data,
+       },
+       .resource       = tmu0_resources,
+       .num_resources  = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+       .name = "TMU1",
+       .channel_offset = 0x10,
+       .timer_bit = 1,
+       .clk = "peripheral_clk",
+       .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+       [0] = {
+               .name   = "TMU1",
+               .start  = 0xfe430014,
+               .end    = 0xfe43001f,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 29,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device tmu1_device = {
+       .name           = "sh_tmu",
+       .id             = 1,
+       .dev = {
+               .platform_data  = &tmu1_platform_data,
+       },
+       .resource       = tmu1_resources,
+       .num_resources  = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xfe4b0000,           /* SCIF2 */
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 40, 40, 40, 40 },
+       }, {
+               .mapbase        = 0xfe4c0000,           /* SCIF3 */
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 76, 76, 76, 76 },
+       }, {
+               .mapbase        = 0xfe4d0000,           /* SCIF4 */
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 104, 104, 104, 104 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7757_devices[] __initdata = {
+       &tmu0_device,
+       &tmu1_device,
+       &sci_device,
+};
+
+static int __init sh7757_devices_setup(void)
+{
+       return platform_add_devices(sh7757_devices,
+                                   ARRAY_SIZE(sh7757_devices));
+}
+arch_initcall(sh7757_devices_setup);
+
+enum {
+       UNUSED = 0,
+
+       /* interrupt sources */
+
+       IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH,
+       IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH,
+       IRL0_HLLL, IRL0_HLLH, IRL0_HLHL, IRL0_HLHH,
+       IRL0_HHLL, IRL0_HHLH, IRL0_HHHL,
+
+       IRL4_LLLL, IRL4_LLLH, IRL4_LLHL, IRL4_LLHH,
+       IRL4_LHLL, IRL4_LHLH, IRL4_LHHL, IRL4_LHHH,
+       IRL4_HLLL, IRL4_HLLH, IRL4_HLHL, IRL4_HLHH,
+       IRL4_HHLL, IRL4_HHLH, IRL4_HHHL,
+       IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+
+       SDHI,
+       DVC,
+       IRQ8, IRQ9, IRQ10,
+       WDT0,
+       TMU0, TMU1, TMU2, TMU2_TICPI,
+       HUDI,
+
+       ARC4,
+       DMAC0,
+       IRQ11,
+       SCIF2,
+       DMAC1_6,
+       USB0,
+       IRQ12,
+       JMC,
+       SPI1,
+       IRQ13, IRQ14,
+       USB1,
+       TMR01, TMR23, TMR45,
+       WDT1,
+       FRT,
+       LPC,
+       SCIF0, SCIF1, SCIF3,
+       PECI0I, PECI1I, PECI2I,
+       IRQ15,
+       ETHERC,
+       SPI0,
+       ADC1,
+       DMAC1_8,
+       SIM,
+       TMU3, TMU4, TMU5,
+       ADC0,
+       SCIF4,
+       IIC0_0, IIC0_1, IIC0_2, IIC0_3,
+       IIC1_0, IIC1_1, IIC1_2, IIC1_3,
+       IIC2_0, IIC2_1, IIC2_2, IIC2_3,
+       IIC3_0, IIC3_1, IIC3_2, IIC3_3,
+       IIC4_0, IIC4_1, IIC4_2, IIC4_3,
+       IIC5_0, IIC5_1, IIC5_2, IIC5_3,
+       IIC6_0, IIC6_1, IIC6_2, IIC6_3,
+       IIC7_0, IIC7_1, IIC7_2, IIC7_3,
+       IIC8_0, IIC8_1, IIC8_2, IIC8_3,
+       IIC9_0, IIC9_1, IIC9_2, IIC9_3,
+       PCIINTA,
+       PCIE,
+       SGPIO,
+
+       /* interrupt groups */
+
+       TMU012, TMU345,
+};
+
+static struct intc_vect vectors[] __initdata = {
+       INTC_VECT(SDHI, 0x480), INTC_VECT(SDHI, 0x04a0),
+       INTC_VECT(SDHI, 0x4c0),
+       INTC_VECT(DVC, 0x4e0),
+       INTC_VECT(IRQ8, 0x500), INTC_VECT(IRQ9, 0x520),
+       INTC_VECT(IRQ10, 0x540),
+       INTC_VECT(WDT0, 0x560),
+       INTC_VECT(TMU0, 0x580), INTC_VECT(TMU1, 0x5a0),
+       INTC_VECT(TMU2, 0x5c0), INTC_VECT(TMU2_TICPI, 0x5e0),
+       INTC_VECT(HUDI, 0x600),
+       INTC_VECT(ARC4, 0x620),
+       INTC_VECT(DMAC0, 0x640), INTC_VECT(DMAC0, 0x660),
+       INTC_VECT(DMAC0, 0x680), INTC_VECT(DMAC0, 0x6a0),
+       INTC_VECT(DMAC0, 0x6c0),
+       INTC_VECT(IRQ11, 0x6e0),
+       INTC_VECT(SCIF2, 0x700), INTC_VECT(SCIF2, 0x720),
+       INTC_VECT(SCIF2, 0x740), INTC_VECT(SCIF2, 0x760),
+       INTC_VECT(DMAC0, 0x780), INTC_VECT(DMAC0, 0x7a0),
+       INTC_VECT(DMAC1_6, 0x7c0), INTC_VECT(DMAC1_6, 0x7e0),
+       INTC_VECT(USB0, 0x840),
+       INTC_VECT(IRQ12, 0x880),
+       INTC_VECT(JMC, 0x8a0),
+       INTC_VECT(SPI1, 0x8c0),
+       INTC_VECT(IRQ13, 0x8e0), INTC_VECT(IRQ14, 0x900),
+       INTC_VECT(USB1, 0x920),
+       INTC_VECT(TMR01, 0xa00), INTC_VECT(TMR23, 0xa20),
+       INTC_VECT(TMR45, 0xa40),
+       INTC_VECT(WDT1, 0xa60),
+       INTC_VECT(FRT, 0xa80),
+       INTC_VECT(LPC, 0xaa0), INTC_VECT(LPC, 0xac0),
+       INTC_VECT(LPC, 0xae0), INTC_VECT(LPC, 0xb00),
+       INTC_VECT(LPC, 0xb20),
+       INTC_VECT(SCIF0, 0xb40), INTC_VECT(SCIF1, 0xb60),
+       INTC_VECT(SCIF3, 0xb80), INTC_VECT(SCIF3, 0xba0),
+       INTC_VECT(SCIF3, 0xbc0), INTC_VECT(SCIF3, 0xbe0),
+       INTC_VECT(PECI0I, 0xc00), INTC_VECT(PECI1I, 0xc20),
+       INTC_VECT(PECI2I, 0xc40),
+       INTC_VECT(IRQ15, 0xc60),
+       INTC_VECT(ETHERC, 0xc80), INTC_VECT(ETHERC, 0xca0),
+       INTC_VECT(SPI0, 0xcc0),
+       INTC_VECT(ADC1, 0xce0),
+       INTC_VECT(DMAC1_8, 0xd00), INTC_VECT(DMAC1_8, 0xd20),
+       INTC_VECT(DMAC1_8, 0xd40), INTC_VECT(DMAC1_8, 0xd60),
+       INTC_VECT(SIM, 0xd80), INTC_VECT(SIM, 0xda0),
+       INTC_VECT(SIM, 0xdc0), INTC_VECT(SIM, 0xde0),
+       INTC_VECT(TMU3, 0xe00), INTC_VECT(TMU4, 0xe20),
+       INTC_VECT(TMU5, 0xe40),
+       INTC_VECT(ADC0, 0xe60),
+       INTC_VECT(SCIF4, 0xf00), INTC_VECT(SCIF4, 0xf20),
+       INTC_VECT(SCIF4, 0xf40), INTC_VECT(SCIF4, 0xf60),
+       INTC_VECT(IIC0_0, 0x1400), INTC_VECT(IIC0_1, 0x1420),
+       INTC_VECT(IIC0_2, 0x1440), INTC_VECT(IIC0_3, 0x1460),
+       INTC_VECT(IIC1_0, 0x1480), INTC_VECT(IIC1_1, 0x14e0),
+       INTC_VECT(IIC1_2, 0x1500), INTC_VECT(IIC1_3, 0x1520),
+       INTC_VECT(IIC2_0, 0x1540), INTC_VECT(IIC2_1, 0x1560),
+       INTC_VECT(IIC2_2, 0x1580), INTC_VECT(IIC2_3, 0x1600),
+       INTC_VECT(IIC3_0, 0x1620), INTC_VECT(IIC3_1, 0x1640),
+       INTC_VECT(IIC3_2, 0x16e0), INTC_VECT(IIC3_3, 0x1700),
+       INTC_VECT(IIC4_0, 0x17c0), INTC_VECT(IIC4_1, 0x1800),
+       INTC_VECT(IIC4_2, 0x1820), INTC_VECT(IIC4_3, 0x1840),
+       INTC_VECT(IIC5_0, 0x1860), INTC_VECT(IIC5_1, 0x1880),
+       INTC_VECT(IIC5_2, 0x18a0), INTC_VECT(IIC5_3, 0x18c0),
+       INTC_VECT(IIC6_0, 0x18e0), INTC_VECT(IIC6_1, 0x1900),
+       INTC_VECT(IIC6_2, 0x1920), INTC_VECT(IIC6_3, 0x1980),
+       INTC_VECT(IIC7_0, 0x19a0), INTC_VECT(IIC7_1, 0x1a00),
+       INTC_VECT(IIC7_2, 0x1a20), INTC_VECT(IIC7_3, 0x1a40),
+       INTC_VECT(IIC8_0, 0x1a60), INTC_VECT(IIC8_1, 0x1a80),
+       INTC_VECT(IIC8_2, 0x1aa0), INTC_VECT(IIC8_3, 0x1b40),
+       INTC_VECT(IIC9_0, 0x1b60), INTC_VECT(IIC9_1, 0x1b80),
+       INTC_VECT(IIC9_2, 0x1c00), INTC_VECT(IIC9_3, 0x1c20),
+       INTC_VECT(PCIINTA, 0x1ce0),
+       INTC_VECT(PCIE, 0x1e00),
+       INTC_VECT(SGPIO, 0x1f80),
+       INTC_VECT(SGPIO, 0x1fa0),
+};
+
+static struct intc_group groups[] __initdata = {
+       INTC_GROUP(TMU012, TMU0, TMU1, TMU2, TMU2_TICPI),
+       INTC_GROUP(TMU345, TMU3, TMU4, TMU5),
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+       { 0xffd00044, 0xffd00064, 32, /* INTMSK0 / INTMSKCLR0 */
+         { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+
+       { 0xffd40080, 0xffd40084, 32, /* INTMSK2 / INTMSKCLR2 */
+         { IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH,
+           IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH,
+           IRL0_HLLL, IRL0_HLLH, IRL0_HLHL, IRL0_HLHH,
+           IRL0_HHLL, IRL0_HHLH, IRL0_HHHL, 0,
+           IRL4_LLLL, IRL4_LLLH, IRL4_LLHL, IRL4_LLHH,
+           IRL4_LHLL, IRL4_LHLH, IRL4_LHHL, IRL4_LHHH,
+           IRL4_HLLL, IRL4_HLLH, IRL4_HLHL, IRL4_HLHH,
+           IRL4_HHLL, IRL4_HHLH, IRL4_HHHL, 0, } },
+
+       { 0xffd40038, 0xffd4003c, 32, /* INT2MSKR / INT2MSKCR */
+         { 0, 0, 0, 0, 0, 0, 0, 0,
+           0, DMAC1_8, 0, PECI0I, LPC, FRT, WDT1, TMR45,
+           TMR23, TMR01, 0, 0, 0, 0, 0, DMAC0,
+           HUDI, 0, WDT0, SCIF3, SCIF2, SDHI, TMU345, TMU012
+            } },
+
+       { 0xffd400d0, 0xffd400d4, 32, /* INT2MSKR1 / INT2MSKCR1 */
+         { IRQ15, IRQ14, IRQ13, IRQ12, IRQ11, IRQ10, SCIF4, ETHERC,
+           IRQ9, IRQ8, SCIF1, SCIF0, USB0, 0, 0, USB1,
+           ADC1, 0, DMAC1_6, ADC0, SPI0, SIM, PECI2I, PECI1I,
+           ARC4, 0, SPI1, JMC, 0, 0, 0, DVC
+            } },
+
+       { 0xffd10038, 0xffd1003c, 32, /* INT2MSKR2 / INT2MSKCR2 */
+         { IIC4_1, IIC4_2, IIC5_0, 0, 0, 0, SGPIO, 0,
+           0, 0, 0, IIC9_2, IIC8_2, IIC8_1, IIC8_0, IIC7_3,
+           IIC7_2, IIC7_1, IIC6_3, IIC0_0, IIC0_1, IIC0_2, IIC0_3, IIC3_1,
+           IIC2_3, 0, IIC2_1, IIC9_1, IIC3_3, IIC1_0, PCIE, IIC2_2
+            } },
+
+       { 0xffd100d0, 0xff1400d4, 32, /* INT2MSKR3 / INT2MSKCR4 */
+         { 0, IIC6_1, IIC6_0, IIC5_1, IIC3_2, IIC2_0, 0, 0,
+           IIC1_3, IIC1_2, IIC9_0, IIC8_3, IIC4_3, IIC7_0, 0, IIC6_2,
+           PCIINTA, 0, IIC4_0, 0, 0, 0, 0, IIC9_3,
+           IIC3_0, 0, IIC5_3, IIC5_2, 0, 0, 0, IIC1_1
+            } },
+};
+
+#define INTPRI         0xffd00010
+#define INT2PRI0       0xffd40000
+#define INT2PRI1       0xffd40004
+#define INT2PRI2       0xffd40008
+#define INT2PRI3       0xffd4000c
+#define INT2PRI4       0xffd40010
+#define INT2PRI5       0xffd40014
+#define INT2PRI6       0xffd40018
+#define INT2PRI7       0xffd4001c
+#define INT2PRI8       0xffd400a0
+#define INT2PRI9       0xffd400a4
+#define INT2PRI10      0xffd400a8
+#define INT2PRI11      0xffd400ac
+#define INT2PRI12      0xffd400b0
+#define INT2PRI13      0xffd400b4
+#define INT2PRI14      0xffd400b8
+#define INT2PRI15      0xffd400bc
+#define INT2PRI16      0xffd10000
+#define INT2PRI17      0xffd10004
+#define INT2PRI18      0xffd10008
+#define INT2PRI19      0xffd1000c
+#define INT2PRI20      0xffd10010
+#define INT2PRI21      0xffd10014
+#define INT2PRI22      0xffd10018
+#define INT2PRI23      0xffd1001c
+#define INT2PRI24      0xffd100a0
+#define INT2PRI25      0xffd100a4
+#define INT2PRI26      0xffd100a8
+#define INT2PRI27      0xffd100ac
+#define INT2PRI28      0xffd100b0
+#define INT2PRI29      0xffd100b4
+#define INT2PRI30      0xffd100b8
+#define INT2PRI31      0xffd100bc
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+       { INTPRI, 0, 32, 4, { IRQ0, IRQ1, IRQ2, IRQ3,
+                             IRQ4, IRQ5, IRQ6, IRQ7 } },
+
+       { INT2PRI0, 0, 32, 8, { TMU0, TMU1, TMU2, TMU2_TICPI } },
+       { INT2PRI1, 0, 32, 8, { TMU3, TMU4, TMU5, SDHI } },
+       { INT2PRI2, 0, 32, 8, { SCIF2, SCIF3, WDT0, IRQ8 } },
+       { INT2PRI3, 0, 32, 8, { HUDI, DMAC0, ADC0, IRQ9 } },
+       { INT2PRI4, 0, 32, 8, { IRQ10, 0, TMR01, TMR23 } },
+       { INT2PRI5, 0, 32, 8, { TMR45, WDT1, FRT, LPC } },
+       { INT2PRI6, 0, 32, 8, { PECI0I, ETHERC, DMAC1_8, 0 } },
+       { INT2PRI7, 0, 32, 8, { SCIF4, 0, IRQ11, IRQ12 } },
+       { INT2PRI8, 0, 32, 8, { 0, 0, 0, DVC } },
+       { INT2PRI9, 0, 32, 8, { ARC4, 0, SPI1, JMC } },
+       { INT2PRI10, 0, 32, 8, { SPI0, SIM, PECI2I, PECI1I } },
+       { INT2PRI11, 0, 32, 8, { ADC1, IRQ13, DMAC1_6, IRQ14 } },
+       { INT2PRI12, 0, 32, 8, { USB0, 0, IRQ15, USB1 } },
+       { INT2PRI13, 0, 32, 8, { 0, 0, SCIF1, SCIF0 } },
+
+       { INT2PRI16, 0, 32, 8, { IIC2_2, 0, 0, 0 } },
+       { INT2PRI17, 0, 32, 8, { PCIE, 0, 0, IIC1_0 } },
+       { INT2PRI18, 0, 32, 8, { IIC3_3, IIC9_1, IIC2_1, IIC1_2 } },
+       { INT2PRI19, 0, 32, 8, { IIC2_3, IIC3_1, 0, IIC1_3 } },
+       { INT2PRI20, 0, 32, 8, { IIC2_0, IIC6_3, IIC7_1, IIC7_2 } },
+       { INT2PRI21, 0, 32, 8, { IIC7_3, IIC8_0, IIC8_1, IIC8_2 } },
+       { INT2PRI22, 0, 32, 8, { IIC9_2, 0, 0, 0 } },
+       { INT2PRI23, 0, 32, 8, { 0, SGPIO, IIC3_2, IIC5_1 } },
+       { INT2PRI24, 0, 32, 8, { 0, 0, 0, IIC1_1 } },
+       { INT2PRI25, 0, 32, 8, { IIC3_0, 0, IIC5_3, IIC5_2 } },
+       { INT2PRI26, 0, 32, 8, { 0, 0, 0, IIC9_3 } },
+       { INT2PRI27, 0, 32, 8, { PCIINTA, IIC6_0, IIC4_0, IIC6_1 } },
+       { INT2PRI28, 0, 32, 8, { IIC4_3, IIC7_0, 0, IIC6_2 } },
+       { INT2PRI29, 0, 32, 8, { 0, 0, IIC9_0, IIC8_3 } },
+       { INT2PRI30, 0, 32, 8, { IIC4_1, IIC4_2, IIC5_0, 0 } },
+       { INT2PRI31, 0, 32, 8, { IIC0_0, IIC0_1, IIC0_2, IIC0_3 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7757", vectors, groups,
+                        mask_registers, prio_registers, NULL);
+
+/* Support for external interrupt pins in IRQ mode */
+static struct intc_vect vectors_irq0123[] __initdata = {
+       INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280),
+       INTC_VECT(IRQ2, 0x2c0), INTC_VECT(IRQ3, 0x300),
+};
+
+static struct intc_vect vectors_irq4567[] __initdata = {
+       INTC_VECT(IRQ4, 0x340), INTC_VECT(IRQ5, 0x380),
+       INTC_VECT(IRQ6, 0x3c0), INTC_VECT(IRQ7, 0x200),
+};
+
+static struct intc_sense_reg sense_registers[] __initdata = {
+       { 0xffd0001c, 32, 2, /* ICR1 */   { IRQ0, IRQ1, IRQ2, IRQ3,
+                                           IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_mask_reg ack_registers[] __initdata = {
+       { 0xffd00024, 0, 32, /* INTREQ */
+         { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh7757-irq0123",
+                            vectors_irq0123, NULL, mask_registers,
+                            prio_registers, sense_registers, ack_registers);
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq4567, "sh7757-irq4567",
+                            vectors_irq4567, NULL, mask_registers,
+                            prio_registers, sense_registers, ack_registers);
+
+/* External interrupt pins in IRL mode */
+static struct intc_vect vectors_irl0123[] __initdata = {
+       INTC_VECT(IRL0_LLLL, 0x200), INTC_VECT(IRL0_LLLH, 0x220),
+       INTC_VECT(IRL0_LLHL, 0x240), INTC_VECT(IRL0_LLHH, 0x260),
+       INTC_VECT(IRL0_LHLL, 0x280), INTC_VECT(IRL0_LHLH, 0x2a0),
+       INTC_VECT(IRL0_LHHL, 0x2c0), INTC_VECT(IRL0_LHHH, 0x2e0),
+       INTC_VECT(IRL0_HLLL, 0x300), INTC_VECT(IRL0_HLLH, 0x320),
+       INTC_VECT(IRL0_HLHL, 0x340), INTC_VECT(IRL0_HLHH, 0x360),
+       INTC_VECT(IRL0_HHLL, 0x380), INTC_VECT(IRL0_HHLH, 0x3a0),
+       INTC_VECT(IRL0_HHHL, 0x3c0),
+};
+
+static struct intc_vect vectors_irl4567[] __initdata = {
+       INTC_VECT(IRL4_LLLL, 0xb00), INTC_VECT(IRL4_LLLH, 0xb20),
+       INTC_VECT(IRL4_LLHL, 0xb40), INTC_VECT(IRL4_LLHH, 0xb60),
+       INTC_VECT(IRL4_LHLL, 0xb80), INTC_VECT(IRL4_LHLH, 0xba0),
+       INTC_VECT(IRL4_LHHL, 0xbc0), INTC_VECT(IRL4_LHHH, 0xbe0),
+       INTC_VECT(IRL4_HLLL, 0xc00), INTC_VECT(IRL4_HLLH, 0xc20),
+       INTC_VECT(IRL4_HLHL, 0xc40), INTC_VECT(IRL4_HLHH, 0xc60),
+       INTC_VECT(IRL4_HHLL, 0xc80), INTC_VECT(IRL4_HHLH, 0xca0),
+       INTC_VECT(IRL4_HHHL, 0xcc0),
+};
+
+static DECLARE_INTC_DESC(intc_desc_irl0123, "sh7757-irl0123", vectors_irl0123,
+                        NULL, mask_registers, NULL, NULL);
+
+static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7757-irl4567", vectors_irl4567,
+                        NULL, mask_registers, NULL, NULL);
+
+#define INTC_ICR0      0xffd00000
+#define INTC_INTMSK0   0xffd00044
+#define INTC_INTMSK1   0xffd00048
+#define INTC_INTMSK2   0xffd40080
+#define INTC_INTMSKCLR1        0xffd00068
+#define INTC_INTMSKCLR2        0xffd40084
+
+void __init plat_irq_setup(void)
+{
+       /* disable IRQ3-0 + IRQ7-4 */
+       ctrl_outl(0xff000000, INTC_INTMSK0);
+
+       /* disable IRL3-0 + IRL7-4 */
+       ctrl_outl(0xc0000000, INTC_INTMSK1);
+       ctrl_outl(0xfffefffe, INTC_INTMSK2);
+
+       /* select IRL mode for IRL3-0 + IRL7-4 */
+       ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+
+       /* disable holding function, ie enable "SH-4 Mode" */
+       ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0);
+
+       register_intc_controller(&intc_desc);
+}
+
+void __init plat_irq_setup_pins(int mode)
+{
+       switch (mode) {
+       case IRQ_MODE_IRQ7654:
+               /* select IRQ mode for IRL7-4 */
+               ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00400000, INTC_ICR0);
+               register_intc_controller(&intc_desc_irq4567);
+               break;
+       case IRQ_MODE_IRQ3210:
+               /* select IRQ mode for IRL3-0 */
+               ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00800000, INTC_ICR0);
+               register_intc_controller(&intc_desc_irq0123);
+               break;
+       case IRQ_MODE_IRL7654:
+               /* enable IRL7-4 but don't provide any masking */
+               ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+               ctrl_outl(0x0000fffe, INTC_INTMSKCLR2);
+               break;
+       case IRQ_MODE_IRL3210:
+               /* enable IRL0-3 but don't provide any masking */
+               ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+               ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+               break;
+       case IRQ_MODE_IRL7654_MASK:
+               /* enable IRL7-4 and mask using cpu intc controller */
+               ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+               register_intc_controller(&intc_desc_irl4567);
+               break;
+       case IRQ_MODE_IRL3210_MASK:
+               /* enable IRL0-3 and mask using cpu intc controller */
+               ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+               register_intc_controller(&intc_desc_irl0123);
+               break;
+       default:
+               BUG();
+       }
+}
+
+void __init plat_mem_setup(void)
+{
+}
index 2b6b0d5..185ec39 100644 (file)
@@ -57,6 +57,8 @@ void __init plat_prepare_cpus(unsigned int max_cpus)
 {
        int i;
 
+       local_timer_setup(0);
+
        BUILD_BUG_ON(SMP_MSG_NR >= 8);
 
        for (i = 0; i < SMP_MSG_NR; i++)
index 92ad844..521d05b 100644 (file)
@@ -34,6 +34,8 @@ int __init detect_cpu_and_cache_system(void)
                /* CPU.VCR aliased at CIR address on SH5-101 */
                boot_cpu_data.type = CPU_SH5_101;
 
+       boot_cpu_data.family = CPU_FAMILY_SH5;
+
        /*
         * First, setup some sane values for the I-cache.
         */
index 08bfa7c..a39f88e 100644 (file)
@@ -4,3 +4,5 @@
 
 # Power Management & Sleep mode
 obj-$(CONFIG_PM)       += pm.o sleep.o
+obj-$(CONFIG_CPU_IDLE) += cpuidle.o
+obj-$(CONFIG_PM_RUNTIME)       += pm_runtime.o
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
new file mode 100644 (file)
index 0000000..1c504bd
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * arch/sh/kernel/cpu/shmobile/cpuidle.c
+ *
+ * Cpuidle support code for SuperH Mobile
+ *
+ *  Copyright (C) 2009 Magnus Damm
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+#include <linux/cpuidle.h>
+#include <asm/suspend.h>
+#include <asm/uaccess.h>
+#include <asm/hwblk.h>
+
+static unsigned long cpuidle_mode[] = {
+       SUSP_SH_SLEEP, /* regular sleep mode */
+       SUSP_SH_SLEEP | SUSP_SH_SF, /* sleep mode + self refresh */
+       SUSP_SH_STANDBY | SUSP_SH_SF, /* software standby mode + self refresh */
+};
+
+static int cpuidle_sleep_enter(struct cpuidle_device *dev,
+                              struct cpuidle_state *state)
+{
+       unsigned long allowed_mode = arch_hwblk_sleep_mode();
+       ktime_t before, after;
+       int requested_state = state - &dev->states[0];
+       int allowed_state;
+       int k;
+
+       /* convert allowed mode to allowed state */
+       for (k = ARRAY_SIZE(cpuidle_mode) - 1; k > 0; k--)
+               if (cpuidle_mode[k] == allowed_mode)
+                       break;
+
+       allowed_state = k;
+
+       /* take the following into account for sleep mode selection:
+        * - allowed_state: best mode allowed by hardware (clock deps)
+        * - requested_state: best mode allowed by software (latencies)
+        */
+       k = min_t(int, allowed_state, requested_state);
+
+       dev->last_state = &dev->states[k];
+       before = ktime_get();
+       sh_mobile_call_standby(cpuidle_mode[k]);
+       after = ktime_get();
+       return ktime_to_ns(ktime_sub(after, before)) >> 10;
+}
+
+static struct cpuidle_device cpuidle_dev;
+static struct cpuidle_driver cpuidle_driver = {
+       .name =         "sh_idle",
+       .owner =        THIS_MODULE,
+};
+
+void sh_mobile_setup_cpuidle(void)
+{
+       struct cpuidle_device *dev = &cpuidle_dev;
+       struct cpuidle_state *state;
+       int i;
+
+       cpuidle_register_driver(&cpuidle_driver);
+
+       for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
+               dev->states[i].name[0] = '\0';
+               dev->states[i].desc[0] = '\0';
+       }
+
+       i = CPUIDLE_DRIVER_STATE_START;
+
+       state = &dev->states[i++];
+       snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
+       strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
+       state->exit_latency = 1;
+       state->target_residency = 1 * 2;
+       state->power_usage = 3;
+       state->flags = 0;
+       state->flags |= CPUIDLE_FLAG_SHALLOW;
+       state->flags |= CPUIDLE_FLAG_TIME_VALID;
+       state->enter = cpuidle_sleep_enter;
+
+       dev->safe_state = state;
+
+       state = &dev->states[i++];
+       snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
+       strncpy(state->desc, "SuperH Sleep Mode [SF]", CPUIDLE_DESC_LEN);
+       state->exit_latency = 100;
+       state->target_residency = 1 * 2;
+       state->power_usage = 1;
+       state->flags = 0;
+       state->flags |= CPUIDLE_FLAG_TIME_VALID;
+       state->enter = cpuidle_sleep_enter;
+
+       state = &dev->states[i++];
+       snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
+       strncpy(state->desc, "SuperH Mobile Standby Mode [SF]", CPUIDLE_DESC_LEN);
+       state->exit_latency = 2300;
+       state->target_residency = 1 * 2;
+       state->power_usage = 1;
+       state->flags = 0;
+       state->flags |= CPUIDLE_FLAG_TIME_VALID;
+       state->enter = cpuidle_sleep_enter;
+
+       dev->state_count = i;
+
+       cpuidle_register_device(dev);
+}
index 8c067ad..ee3c2aa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c
+ * arch/sh/kernel/cpu/shmobile/pm.c
  *
  * Power management support code for SuperH Mobile
  *
  *
  * R-standby mode is unsupported, but will be added in the future
  * U-standby mode is low priority since it needs bootloader hacks
- *
- * All modes should be tied in with cpuidle. But before that can
- * happen we need to keep track of enabled hardware blocks so we
- * can avoid entering sleep modes that stop clocks to hardware
- * blocks that are in use even though the cpu core is idle.
  */
 
+#define ILRAM_BASE 0xe5200000
+
 extern const unsigned char sh_mobile_standby[];
 extern const unsigned int sh_mobile_standby_size;
 
-static void sh_mobile_call_standby(unsigned long mode)
+void sh_mobile_call_standby(unsigned long mode)
 {
-       extern void *vbr_base;
-       void *onchip_mem = (void *)0xe5200000; /* ILRAM */
-       void (*standby_onchip_mem)(unsigned long) = onchip_mem;
-
-       /* Note: Wake up from sleep may generate exceptions!
-        * Setup VBR to point to on-chip ram if self-refresh is
-        * going to be used.
-        */
-       if (mode & SUSP_SH_SF)
-               asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory");
-
-       /* Copy the assembly snippet to the otherwise ununsed ILRAM */
-       memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
-       wmb();
-       ctrl_barrier();
+       void *onchip_mem = (void *)ILRAM_BASE;
+       void (*standby_onchip_mem)(unsigned long, unsigned long) = onchip_mem;
 
        /* Let assembly snippet in on-chip memory handle the rest */
-       standby_onchip_mem(mode);
-
-       /* Put VBR back in System RAM again */
-       if (mode & SUSP_SH_SF)
-               asm volatile("ldc %0, vbr" : : "r" (&vbr_base) : "memory");
+       standby_onchip_mem(mode, ILRAM_BASE);
 }
 
 static int sh_pm_enter(suspend_state_t state)
@@ -85,7 +65,15 @@ static struct platform_suspend_ops sh_pm_ops = {
 
 static int __init sh_pm_init(void)
 {
+       void *onchip_mem = (void *)ILRAM_BASE;
+
+       /* Copy the assembly snippet to the otherwise ununsed ILRAM */
+       memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
+       wmb();
+       ctrl_barrier();
+
        suspend_set_ops(&sh_pm_ops);
+       sh_mobile_setup_cpuidle();
        return 0;
 }
 
diff --git a/arch/sh/kernel/cpu/shmobile/pm_runtime.c b/arch/sh/kernel/cpu/shmobile/pm_runtime.c
new file mode 100644 (file)
index 0000000..7c615b1
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * arch/sh/kernel/cpu/shmobile/pm_runtime.c
+ *
+ * Runtime PM support code for SuperH Mobile
+ *
+ *  Copyright (C) 2009 Magnus Damm
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <asm/hwblk.h>
+
+static DEFINE_SPINLOCK(hwblk_lock);
+static LIST_HEAD(hwblk_idle_list);
+static struct work_struct hwblk_work;
+
+extern struct hwblk_info *hwblk_info;
+
+static void platform_pm_runtime_not_idle(struct platform_device *pdev)
+{
+       unsigned long flags;
+
+       /* remove device from idle list */
+       spin_lock_irqsave(&hwblk_lock, flags);
+       if (test_bit(PDEV_ARCHDATA_FLAG_IDLE, &pdev->archdata.flags)) {
+               list_del(&pdev->archdata.entry);
+               __clear_bit(PDEV_ARCHDATA_FLAG_IDLE, &pdev->archdata.flags);
+       }
+       spin_unlock_irqrestore(&hwblk_lock, flags);
+}
+
+static int __platform_pm_runtime_resume(struct platform_device *pdev)
+{
+       struct device *d = &pdev->dev;
+       struct pdev_archdata *ad = &pdev->archdata;
+       int hwblk = ad->hwblk_id;
+       int ret = -ENOSYS;
+
+       dev_dbg(d, "__platform_pm_runtime_resume() [%d]\n", hwblk);
+
+       if (d->driver && d->driver->pm && d->driver->pm->runtime_resume) {
+               hwblk_enable(hwblk_info, hwblk);
+               ret = 0;
+
+               if (test_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags)) {
+                       ret = d->driver->pm->runtime_resume(d);
+                       if (!ret)
+                               clear_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags);
+                       else
+                               hwblk_disable(hwblk_info, hwblk);
+               }
+       }
+
+       dev_dbg(d, "__platform_pm_runtime_resume() [%d] - returns %d\n",
+               hwblk, ret);
+
+       return ret;
+}
+
+static int __platform_pm_runtime_suspend(struct platform_device *pdev)
+{
+       struct device *d = &pdev->dev;
+       struct pdev_archdata *ad = &pdev->archdata;
+       int hwblk = ad->hwblk_id;
+       int ret = -ENOSYS;
+
+       dev_dbg(d, "__platform_pm_runtime_suspend() [%d]\n", hwblk);
+
+       if (d->driver && d->driver->pm && d->driver->pm->runtime_suspend) {
+               BUG_ON(!test_bit(PDEV_ARCHDATA_FLAG_IDLE, &ad->flags));
+
+               hwblk_enable(hwblk_info, hwblk);
+               ret = d->driver->pm->runtime_suspend(d);
+               hwblk_disable(hwblk_info, hwblk);
+
+               if (!ret) {
+                       set_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags);
+                       platform_pm_runtime_not_idle(pdev);
+                       hwblk_cnt_dec(hwblk_info, hwblk, HWBLK_CNT_IDLE);
+               }
+       }
+
+       dev_dbg(d, "__platform_pm_runtime_suspend() [%d] - returns %d\n",
+               hwblk, ret);
+
+       return ret;
+}
+
+static void platform_pm_runtime_work(struct work_struct *work)
+{
+       struct platform_device *pdev;
+       unsigned long flags;
+       int ret;
+
+       /* go through the idle list and suspend one device at a time */
+       do {
+               spin_lock_irqsave(&hwblk_lock, flags);
+               if (list_empty(&hwblk_idle_list))
+                       pdev = NULL;
+               else
+                       pdev = list_first_entry(&hwblk_idle_list,
+                                               struct platform_device,
+                                               archdata.entry);
+               spin_unlock_irqrestore(&hwblk_lock, flags);
+
+               if (pdev) {
+                       mutex_lock(&pdev->archdata.mutex);
+                       ret = __platform_pm_runtime_suspend(pdev);
+
+                       /* at this point the platform device may be:
+                        * suspended: ret = 0, FLAG_SUSP set, clock stopped
+                        * failed: ret < 0, FLAG_IDLE set, clock stopped
+                        */
+                       mutex_unlock(&pdev->archdata.mutex);
+               } else {
+                       ret = -ENODEV;
+               }
+       } while (!ret);
+}
+
+/* this function gets called from cpuidle context when all devices in the
+ * main power domain are unused but some are counted as idle, ie the hwblk
+ * counter values are (HWBLK_CNT_USAGE == 0) && (HWBLK_CNT_IDLE != 0)
+ */
+void platform_pm_runtime_suspend_idle(void)
+{
+       queue_work(pm_wq, &hwblk_work);
+}
+
+int platform_pm_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pdev_archdata *ad = &pdev->archdata;
+       unsigned long flags;
+       int hwblk = ad->hwblk_id;
+       int ret = 0;
+
+       dev_dbg(dev, "platform_pm_runtime_suspend() [%d]\n", hwblk);
+
+       /* ignore off-chip platform devices */
+       if (!hwblk)
+               goto out;
+
+       /* interrupt context not allowed */
+       might_sleep();
+
+       /* catch misconfigured drivers not starting with resume */
+       if (test_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* serialize */
+       mutex_lock(&ad->mutex);
+
+       /* disable clock */
+       hwblk_disable(hwblk_info, hwblk);
+
+       /* put device on idle list */
+       spin_lock_irqsave(&hwblk_lock, flags);
+       list_add_tail(&pdev->archdata.entry, &hwblk_idle_list);
+       __set_bit(PDEV_ARCHDATA_FLAG_IDLE, &pdev->archdata.flags);
+       spin_unlock_irqrestore(&hwblk_lock, flags);
+
+       /* increase idle count */
+       hwblk_cnt_inc(hwblk_info, hwblk, HWBLK_CNT_IDLE);
+
+       /* at this point the platform device is:
+        * idle: ret = 0, FLAG_IDLE set, clock stopped
+        */
+       mutex_unlock(&ad->mutex);
+
+out:
+       dev_dbg(dev, "platform_pm_runtime_suspend() [%d] returns %d\n",
+               hwblk, ret);
+
+       return ret;
+}
+
+int platform_pm_runtime_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pdev_archdata *ad = &pdev->archdata;
+       int hwblk = ad->hwblk_id;
+       int ret = 0;
+
+       dev_dbg(dev, "platform_pm_runtime_resume() [%d]\n", hwblk);
+
+       /* ignore off-chip platform devices */
+       if (!hwblk)
+               goto out;
+
+       /* interrupt context not allowed */
+       might_sleep();
+
+       /* serialize */
+       mutex_lock(&ad->mutex);
+
+       /* make sure device is removed from idle list */
+       platform_pm_runtime_not_idle(pdev);
+
+       /* decrease idle count */
+       if (!test_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags) &&
+           !test_bit(PDEV_ARCHDATA_FLAG_SUSP, &pdev->archdata.flags))
+               hwblk_cnt_dec(hwblk_info, hwblk, HWBLK_CNT_IDLE);
+
+       /* resume the device if needed */
+       ret = __platform_pm_runtime_resume(pdev);
+
+       /* the driver has been initialized now, so clear the init flag */
+       clear_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
+
+       /* at this point the platform device may be:
+        * resumed: ret = 0, flags = 0, clock started
+        * failed: ret < 0, FLAG_SUSP set, clock stopped
+        */
+       mutex_unlock(&ad->mutex);
+out:
+       dev_dbg(dev, "platform_pm_runtime_resume() [%d] returns %d\n",
+               hwblk, ret);
+
+       return ret;
+}
+
+int platform_pm_runtime_idle(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       int hwblk = pdev->archdata.hwblk_id;
+       int ret = 0;
+
+       dev_dbg(dev, "platform_pm_runtime_idle() [%d]\n", hwblk);
+
+       /* ignore off-chip platform devices */
+       if (!hwblk)
+               goto out;
+
+       /* interrupt context not allowed, use pm_runtime_put()! */
+       might_sleep();
+
+       /* suspend synchronously to disable clocks immediately */
+       ret = pm_runtime_suspend(dev);
+out:
+       dev_dbg(dev, "platform_pm_runtime_idle() [%d] done!\n", hwblk);
+       return ret;
+}
+
+static int platform_bus_notify(struct notifier_block *nb,
+                              unsigned long action, void *data)
+{
+       struct device *dev = data;
+       struct platform_device *pdev = to_platform_device(dev);
+       int hwblk = pdev->archdata.hwblk_id;
+
+       /* ignore off-chip platform devices */
+       if (!hwblk)
+               return 0;
+
+       switch (action) {
+       case BUS_NOTIFY_ADD_DEVICE:
+               INIT_LIST_HEAD(&pdev->archdata.entry);
+               mutex_init(&pdev->archdata.mutex);
+               /* platform devices without drivers should be disabled */
+               hwblk_enable(hwblk_info, hwblk);
+               hwblk_disable(hwblk_info, hwblk);
+               /* make sure driver re-inits itself once */
+               __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
+               break;
+       /* TODO: add BUS_NOTIFY_BIND_DRIVER and increase idle count */
+       case BUS_NOTIFY_BOUND_DRIVER:
+               /* keep track of number of devices in use per hwblk */
+               hwblk_cnt_inc(hwblk_info, hwblk, HWBLK_CNT_DEVICES);
+               break;
+       case BUS_NOTIFY_UNBOUND_DRIVER:
+               /* keep track of number of devices in use per hwblk */
+               hwblk_cnt_dec(hwblk_info, hwblk, HWBLK_CNT_DEVICES);
+               /* make sure driver re-inits itself once */
+               __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
+               break;
+       case BUS_NOTIFY_DEL_DEVICE:
+               break;
+       }
+       return 0;
+}
+
+static struct notifier_block platform_bus_notifier = {
+       .notifier_call = platform_bus_notify
+};
+
+static int __init sh_pm_runtime_init(void)
+{
+       INIT_WORK(&hwblk_work, platform_pm_runtime_work);
+
+       bus_register_notifier(&platform_bus_type, &platform_bus_notifier);
+       return 0;
+}
+core_initcall(sh_pm_runtime_init);
index baf2d7d..a439e6c 100644 (file)
 #include <asm/asm-offsets.h>
 #include <asm/suspend.h>
 
+/*
+ * Kernel mode register usage, see entry.S:
+ *     k0      scratch
+ *     k1      scratch
+ *     k4      scratch
+ */
+#define k0     r0
+#define k1     r1
+#define k4     r4
+
 /* manage self-refresh and enter standby mode.
  * this code will be copied to on-chip memory and executed from there.
  */
 
        .balign         4096,0,4096
 ENTRY(sh_mobile_standby)
+
+       /* save original vbr */
+       stc     vbr, r1
+       mova    saved_vbr, r0
+       mov.l   r1, @r0
+
+       /* point vbr to our on-chip memory page */
+       ldc     r5, vbr
+
+       /* save return address */
+       mova    saved_spc, r0
+       sts     pr, r5
+       mov.l   r5, @r0
+
+       /* save sr */
+       mova    saved_sr, r0
+       stc     sr, r5
+       mov.l   r5, @r0
+
+       /* save mode flags */
+       mova    saved_mode, r0
+       mov.l   r4, @r0
+
+       /* put mode flags in r0 */
        mov     r4, r0
 
        tst     #SUSP_SH_SF, r0
        bt      skip_set_sf
 #ifdef CONFIG_CPU_SUBTYPE_SH7724
        /* DBSC: put memory in self-refresh mode */
-
        mov.l   dben_reg, r4
        mov.l   dben_data0, r1
        mov.l   r1, @r4
@@ -60,14 +93,6 @@ ENTRY(sh_mobile_standby)
 #endif
 
 skip_set_sf:
-       tst     #SUSP_SH_SLEEP, r0
-       bt      test_standby
-
-       /* set mode to "sleep mode" */
-       bra     do_sleep
-        mov    #0x00, r1
-
-test_standby:
        tst     #SUSP_SH_STANDBY, r0
        bt      test_rstandby
 
@@ -85,77 +110,107 @@ test_rstandby:
 
 test_ustandby:
        tst     #SUSP_SH_USTANDBY, r0
-       bt      done_sleep
+       bt      force_sleep
 
        /* set mode to "u-standby mode" */
-       mov     #0x10, r1
+       bra     do_sleep
+        mov    #0x10, r1
 
-       /* fall-through */
+force_sleep:
+
+       /* set mode to "sleep mode" */
+       mov     #0x00, r1
 
 do_sleep:
        /* setup and enter selected standby mode */
        mov.l   5f, r4
        mov.l   r1, @r4
+again:
        sleep
+       bra     again
+        nop
+
+restore_jump_vbr:
+       /* setup spc with return address to c code */
+       mov.l   saved_spc, k0
+       ldc     k0, spc
+
+       /* restore vbr */
+       mov.l   saved_vbr, k0
+       ldc     k0, vbr
+
+       /* setup ssr with saved sr */
+       mov.l   saved_sr, k0
+       ldc     k0, ssr
+
+       /* get mode flags */
+       mov.l   saved_mode, k0
 
 done_sleep:
        /* reset standby mode to sleep mode */
-       mov.l   5f, r4
-       mov     #0x00, r1
-       mov.l   r1, @r4
+       mov.l   5f, k4
+       mov     #0x00, k1
+       mov.l   k1, @k4
 
-       tst     #SUSP_SH_SF, r0
+       tst     #SUSP_SH_SF, k0
        bt      skip_restore_sf
 
 #ifdef CONFIG_CPU_SUBTYPE_SH7724
        /* DBSC: put memory in auto-refresh mode */
+       mov.l   dbrfpdn0_reg, k4
+       mov.l   dbrfpdn0_data0, k1
+       mov.l   k1, @k4
 
-       mov.l   dbrfpdn0_reg, r4
-       mov.l   dbrfpdn0_data0, r1
-       mov.l   r1, @r4
-
-       /* sleep 140 ns */
-       nop
+       nop /* sleep 140 ns */
        nop
        nop
        nop
 
-       mov.l   dbcmdcnt_reg, r4
-       mov.l   dbcmdcnt_data0, r1
-       mov.l   r1, @r4
+       mov.l   dbcmdcnt_reg, k4
+       mov.l   dbcmdcnt_data0, k1
+       mov.l   k1, @k4
 
-       mov.l   dbcmdcnt_reg, r4
-       mov.l   dbcmdcnt_data1, r1
-       mov.l   r1, @r4
+       mov.l   dbcmdcnt_reg, k4
+       mov.l   dbcmdcnt_data1, k1
+       mov.l   k1, @k4
 
-       mov.l   dben_reg, r4
-       mov.l   dben_data1, r1
-       mov.l   r1, @r4
+       mov.l   dben_reg, k4
+       mov.l   dben_data1, k1
+       mov.l   k1, @k4
 
-       mov.l   dbrfpdn0_reg, r4
-       mov.l   dbrfpdn0_data2, r1
-       mov.l   r1, @r4
+       mov.l   dbrfpdn0_reg, k4
+       mov.l   dbrfpdn0_data2, k1
+       mov.l   k1, @k4
 #else
        /* SBSC: set auto-refresh mode */
-       mov.l   1f, r4
-       mov.l   @r4, r2
-       mov.l   4f, r3
-       and     r3, r2
-       mov.l   r2, @r4
-       mov.l   6f, r4
-       mov.l   7f, r1
-       mov.l   8f, r2
-       mov.l   @r4, r3
-       mov     #-1, r4
-       add     r4, r3
-       or      r2, r3
-       mov.l   r3, @r1
+       mov.l   1f, k4
+       mov.l   @k4, k0
+       mov.l   4f, k1
+       and     k1, k0
+       mov.l   k0, @k4
+       mov.l   6f, k4
+       mov.l   8f, k0
+       mov.l   @k4, k1
+       mov     #-1, k4
+       add     k4, k1
+       or      k1, k0
+       mov.l   7f, k1
+       mov.l   k0, @k1
 #endif
 skip_restore_sf:
-       rts
+       /* jump to vbr vector */
+       mov.l   saved_vbr, k0
+       mov.l   offset_vbr, k4
+       add     k4, k0
+       jmp     @k0
         nop
 
        .balign 4
+saved_mode:    .long   0
+saved_spc:     .long   0
+saved_sr:      .long   0
+saved_vbr:     .long   0
+offset_vbr:    .long   0x600
 #ifdef CONFIG_CPU_SUBTYPE_SH7724
 dben_reg:      .long   0xfd000010 /* DBEN */
 dben_data0:    .long   0
@@ -178,12 +233,12 @@ dbcmdcnt_data1:   .long   4
 7:     .long   0xfe400018 /* RTCNT */
 8:     .long   0xa55a0000
 
+
 /* interrupt vector @ 0x600 */
        .balign         0x400,0,0x400
        .long   0xdeadbeef
        .balign         0x200,0,0x200
-       /* sh7722 will end up here in sleep mode */
-       rte
+       bra     restore_jump_vbr
         nop
 sh_mobile_standby_end:
 
diff --git a/arch/sh/kernel/dumpstack.c b/arch/sh/kernel/dumpstack.c
new file mode 100644 (file)
index 0000000..6f5ad15
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+ *  Copyright (C) 2009  Matt Fleming
+ */
+#include <linux/kallsyms.h>
+#include <linux/ftrace.h>
+#include <linux/debug_locks.h>
+#include <asm/unwinder.h>
+#include <asm/stacktrace.h>
+
+void printk_address(unsigned long address, int reliable)
+{
+       printk(" [<%p>] %s%pS\n", (void *) address,
+                       reliable ? "" : "? ", (void *) address);
+}
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+static void
+print_ftrace_graph_addr(unsigned long addr, void *data,
+                       const struct stacktrace_ops *ops,
+                       struct thread_info *tinfo, int *graph)
+{
+       struct task_struct *task = tinfo->task;
+       unsigned long ret_addr;
+       int index = task->curr_ret_stack;
+
+       if (addr != (unsigned long)return_to_handler)
+               return;
+
+       if (!task->ret_stack || index < *graph)
+               return;
+
+       index -= *graph;
+       ret_addr = task->ret_stack[index].ret;
+
+       ops->address(data, ret_addr, 1);
+
+       (*graph)++;
+}
+#else
+static inline void
+print_ftrace_graph_addr(unsigned long addr, void *data,
+                       const struct stacktrace_ops *ops,
+                       struct thread_info *tinfo, int *graph)
+{ }
+#endif
+
+void
+stack_reader_dump(struct task_struct *task, struct pt_regs *regs,
+                 unsigned long *sp, const struct stacktrace_ops *ops,
+                 void *data)
+{
+       struct thread_info *context;
+       int graph = 0;
+
+       context = (struct thread_info *)
+               ((unsigned long)sp & (~(THREAD_SIZE - 1)));
+
+       while (!kstack_end(sp)) {
+               unsigned long addr = *sp++;
+
+               if (__kernel_text_address(addr)) {
+                       ops->address(data, addr, 1);
+
+                       print_ftrace_graph_addr(addr, data, ops,
+                                               context, &graph);
+               }
+       }
+}
+
+static void
+print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+       printk(data);
+       print_symbol(msg, symbol);
+       printk("\n");
+}
+
+static void print_trace_warning(void *data, char *msg)
+{
+       printk("%s%s\n", (char *)data, msg);
+}
+
+static int print_trace_stack(void *data, char *name)
+{
+       printk("%s <%s> ", (char *)data, name);
+       return 0;
+}
+
+/*
+ * Print one address/symbol entries per line.
+ */
+static void print_trace_address(void *data, unsigned long addr, int reliable)
+{
+       printk(data);
+       printk_address(addr, reliable);
+}
+
+static const struct stacktrace_ops print_trace_ops = {
+       .warning = print_trace_warning,
+       .warning_symbol = print_trace_warning_symbol,
+       .stack = print_trace_stack,
+       .address = print_trace_address,
+};
+
+void show_trace(struct task_struct *tsk, unsigned long *sp,
+               struct pt_regs *regs)
+{
+       if (regs && user_mode(regs))
+               return;
+
+       printk("\nCall trace:\n");
+
+       unwind_stack(tsk, regs, sp, &print_trace_ops, "");
+
+       printk("\n");
+
+       if (!tsk)
+               tsk = current;
+
+       debug_show_held_locks(tsk);
+}
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
new file mode 100644 (file)
index 0000000..bc4d8d7
--- /dev/null
@@ -0,0 +1,972 @@
+/*
+ * Copyright (C) 2009 Matt Fleming <matt@console-pimps.org>
+ *
+ * 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.
+ *
+ * This is an implementation of a DWARF unwinder. Its main purpose is
+ * for generating stacktrace information. Based on the DWARF 3
+ * specification from http://www.dwarfstd.org.
+ *
+ * TODO:
+ *     - DWARF64 doesn't work.
+ *     - Registers with DWARF_VAL_OFFSET rules aren't handled properly.
+ */
+
+/* #define DEBUG */
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/mempool.h>
+#include <linux/mm.h>
+#include <asm/dwarf.h>
+#include <asm/unwinder.h>
+#include <asm/sections.h>
+#include <asm/unaligned.h>
+#include <asm/dwarf.h>
+#include <asm/stacktrace.h>
+
+/* Reserve enough memory for two stack frames */
+#define DWARF_FRAME_MIN_REQ    2
+/* ... with 4 registers per frame. */
+#define DWARF_REG_MIN_REQ      (DWARF_FRAME_MIN_REQ * 4)
+
+static struct kmem_cache *dwarf_frame_cachep;
+static mempool_t *dwarf_frame_pool;
+
+static struct kmem_cache *dwarf_reg_cachep;
+static mempool_t *dwarf_reg_pool;
+
+static LIST_HEAD(dwarf_cie_list);
+static DEFINE_SPINLOCK(dwarf_cie_lock);
+
+static LIST_HEAD(dwarf_fde_list);
+static DEFINE_SPINLOCK(dwarf_fde_lock);
+
+static struct dwarf_cie *cached_cie;
+
+/**
+ *     dwarf_frame_alloc_reg - allocate memory for a DWARF register
+ *     @frame: the DWARF frame whose list of registers we insert on
+ *     @reg_num: the register number
+ *
+ *     Allocate space for, and initialise, a dwarf reg from
+ *     dwarf_reg_pool and insert it onto the (unsorted) linked-list of
+ *     dwarf registers for @frame.
+ *
+ *     Return the initialised DWARF reg.
+ */
+static struct dwarf_reg *dwarf_frame_alloc_reg(struct dwarf_frame *frame,
+                                              unsigned int reg_num)
+{
+       struct dwarf_reg *reg;
+
+       reg = mempool_alloc(dwarf_reg_pool, GFP_ATOMIC);
+       if (!reg) {
+               printk(KERN_WARNING "Unable to allocate a DWARF register\n");
+               /*
+                * Let's just bomb hard here, we have no way to
+                * gracefully recover.
+                */
+               UNWINDER_BUG();
+       }
+
+       reg->number = reg_num;
+       reg->addr = 0;
+       reg->flags = 0;
+
+       list_add(&reg->link, &frame->reg_list);
+
+       return reg;
+}
+
+static void dwarf_frame_free_regs(struct dwarf_frame *frame)
+{
+       struct dwarf_reg *reg, *n;
+
+       list_for_each_entry_safe(reg, n, &frame->reg_list, link) {
+               list_del(&reg->link);
+               mempool_free(reg, dwarf_reg_pool);
+       }
+}
+
+/**
+ *     dwarf_frame_reg - return a DWARF register
+ *     @frame: the DWARF frame to search in for @reg_num
+ *     @reg_num: the register number to search for
+ *
+ *     Lookup and return the dwarf reg @reg_num for this frame. Return
+ *     NULL if @reg_num is an register invalid number.
+ */
+static struct dwarf_reg *dwarf_frame_reg(struct dwarf_frame *frame,
+                                        unsigned int reg_num)
+{
+       struct dwarf_reg *reg;
+
+       list_for_each_entry(reg, &frame->reg_list, link) {
+               if (reg->number == reg_num)
+                       return reg;
+       }
+
+       return NULL;
+}
+
+/**
+ *     dwarf_read_addr - read dwarf data
+ *     @src: source address of data
+ *     @dst: destination address to store the data to
+ *
+ *     Read 'n' bytes from @src, where 'n' is the size of an address on
+ *     the native machine. We return the number of bytes read, which
+ *     should always be 'n'. We also have to be careful when reading
+ *     from @src and writing to @dst, because they can be arbitrarily
+ *     aligned. Return 'n' - the number of bytes read.
+ */
+static inline int dwarf_read_addr(unsigned long *src, unsigned long *dst)
+{
+       u32 val = get_unaligned(src);
+       put_unaligned(val, dst);
+       return sizeof(unsigned long *);
+}
+
+/**
+ *     dwarf_read_uleb128 - read unsigned LEB128 data
+ *     @addr: the address where the ULEB128 data is stored
+ *     @ret: address to store the result
+ *
+ *     Decode an unsigned LEB128 encoded datum. The algorithm is taken
+ *     from Appendix C of the DWARF 3 spec. For information on the
+ *     encodings refer to section "7.6 - Variable Length Data". Return
+ *     the number of bytes read.
+ */
+static inline unsigned long dwarf_read_uleb128(char *addr, unsigned int *ret)
+{
+       unsigned int result;
+       unsigned char byte;
+       int shift, count;
+
+       result = 0;
+       shift = 0;
+       count = 0;
+
+       while (1) {
+               byte = __raw_readb(addr);
+               addr++;
+               count++;
+
+               result |= (byte & 0x7f) << shift;
+               shift += 7;
+
+               if (!(byte & 0x80))
+                       break;
+       }
+
+       *ret = result;
+
+       return count;
+}
+
+/**
+ *     dwarf_read_leb128 - read signed LEB128 data
+ *     @addr: the address of the LEB128 encoded data
+ *     @ret: address to store the result
+ *
+ *     Decode signed LEB128 data. The algorithm is taken from Appendix
+ *     C of the DWARF 3 spec. Return the number of bytes read.
+ */
+static inline unsigned long dwarf_read_leb128(char *addr, int *ret)
+{
+       unsigned char byte;
+       int result, shift;
+       int num_bits;
+       int count;
+
+       result = 0;
+       shift = 0;
+       count = 0;
+
+       while (1) {
+               byte = __raw_readb(addr);
+               addr++;
+               result |= (byte & 0x7f) << shift;
+               shift += 7;
+               count++;
+
+               if (!(byte & 0x80))
+                       break;
+       }
+
+       /* The number of bits in a signed integer. */
+       num_bits = 8 * sizeof(result);
+
+       if ((shift < num_bits) && (byte & 0x40))
+               result |= (-1 << shift);
+
+       *ret = result;
+
+       return count;
+}
+
+/**
+ *     dwarf_read_encoded_value - return the decoded value at @addr
+ *     @addr: the address of the encoded value
+ *     @val: where to write the decoded value
+ *     @encoding: the encoding with which we can decode @addr
+ *
+ *     GCC emits encoded address in the .eh_frame FDE entries. Decode
+ *     the value at @addr using @encoding. The decoded value is written
+ *     to @val and the number of bytes read is returned.
+ */
+static int dwarf_read_encoded_value(char *addr, unsigned long *val,
+                                   char encoding)
+{
+       unsigned long decoded_addr = 0;
+       int count = 0;
+
+       switch (encoding & 0x70) {
+       case DW_EH_PE_absptr:
+               break;
+       case DW_EH_PE_pcrel:
+               decoded_addr = (unsigned long)addr;
+               break;
+       default:
+               pr_debug("encoding=0x%x\n", (encoding & 0x70));
+               UNWINDER_BUG();
+       }
+
+       if ((encoding & 0x07) == 0x00)
+               encoding |= DW_EH_PE_udata4;
+
+       switch (encoding & 0x0f) {
+       case DW_EH_PE_sdata4:
+       case DW_EH_PE_udata4:
+               count += 4;
+               decoded_addr += get_unaligned((u32 *)addr);
+               __raw_writel(decoded_addr, val);
+               break;
+       default:
+               pr_debug("encoding=0x%x\n", encoding);
+               UNWINDER_BUG();
+       }
+
+       return count;
+}
+
+/**
+ *     dwarf_entry_len - return the length of an FDE or CIE
+ *     @addr: the address of the entry
+ *     @len: the length of the entry
+ *
+ *     Read the initial_length field of the entry and store the size of
+ *     the entry in @len. We return the number of bytes read. Return a
+ *     count of 0 on error.
+ */
+static inline int dwarf_entry_len(char *addr, unsigned long *len)
+{
+       u32 initial_len;
+       int count;
+
+       initial_len = get_unaligned((u32 *)addr);
+       count = 4;
+
+       /*
+        * An initial length field value in the range DW_LEN_EXT_LO -
+        * DW_LEN_EXT_HI indicates an extension, and should not be
+        * interpreted as a length. The only extension that we currently
+        * understand is the use of DWARF64 addresses.
+        */
+       if (initial_len >= DW_EXT_LO && initial_len <= DW_EXT_HI) {
+               /*
+                * The 64-bit length field immediately follows the
+                * compulsory 32-bit length field.
+                */
+               if (initial_len == DW_EXT_DWARF64) {
+                       *len = get_unaligned((u64 *)addr + 4);
+                       count = 12;
+               } else {
+                       printk(KERN_WARNING "Unknown DWARF extension\n");
+                       count = 0;
+               }
+       } else
+               *len = initial_len;
+
+       return count;
+}
+
+/**
+ *     dwarf_lookup_cie - locate the cie
+ *     @cie_ptr: pointer to help with lookup
+ */
+static struct dwarf_cie *dwarf_lookup_cie(unsigned long cie_ptr)
+{
+       struct dwarf_cie *cie;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dwarf_cie_lock, flags);
+
+       /*
+        * We've cached the last CIE we looked up because chances are
+        * that the FDE wants this CIE.
+        */
+       if (cached_cie && cached_cie->cie_pointer == cie_ptr) {
+               cie = cached_cie;
+               goto out;
+       }
+
+       list_for_each_entry(cie, &dwarf_cie_list, link) {
+               if (cie->cie_pointer == cie_ptr) {
+                       cached_cie = cie;
+                       break;
+               }
+       }
+
+       /* Couldn't find the entry in the list. */
+       if (&cie->link == &dwarf_cie_list)
+               cie = NULL;
+out:
+       spin_unlock_irqrestore(&dwarf_cie_lock, flags);
+       return cie;
+}
+
+/**
+ *     dwarf_lookup_fde - locate the FDE that covers pc
+ *     @pc: the program counter
+ */
+struct dwarf_fde *dwarf_lookup_fde(unsigned long pc)
+{
+       struct dwarf_fde *fde;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dwarf_fde_lock, flags);
+
+       list_for_each_entry(fde, &dwarf_fde_list, link) {
+               unsigned long start, end;
+
+               start = fde->initial_location;
+               end = fde->initial_location + fde->address_range;
+
+               if (pc >= start && pc < end)
+                       break;
+       }
+
+       /* Couldn't find the entry in the list. */
+       if (&fde->link == &dwarf_fde_list)
+               fde = NULL;
+
+       spin_unlock_irqrestore(&dwarf_fde_lock, flags);
+
+       return fde;
+}
+
+/**
+ *     dwarf_cfa_execute_insns - execute instructions to calculate a CFA
+ *     @insn_start: address of the first instruction
+ *     @insn_end: address of the last instruction
+ *     @cie: the CIE for this function
+ *     @fde: the FDE for this function
+ *     @frame: the instructions calculate the CFA for this frame
+ *     @pc: the program counter of the address we're interested in
+ *
+ *     Execute the Call Frame instruction sequence starting at
+ *     @insn_start and ending at @insn_end. The instructions describe
+ *     how to calculate the Canonical Frame Address of a stackframe.
+ *     Store the results in @frame.
+ */
+static int dwarf_cfa_execute_insns(unsigned char *insn_start,
+                                  unsigned char *insn_end,
+                                  struct dwarf_cie *cie,
+                                  struct dwarf_fde *fde,
+                                  struct dwarf_frame *frame,
+                                  unsigned long pc)
+{
+       unsigned char insn;
+       unsigned char *current_insn;
+       unsigned int count, delta, reg, expr_len, offset;
+       struct dwarf_reg *regp;
+
+       current_insn = insn_start;
+
+       while (current_insn < insn_end && frame->pc <= pc) {
+               insn = __raw_readb(current_insn++);
+
+               /*
+                * Firstly, handle the opcodes that embed their operands
+                * in the instructions.
+                */
+               switch (DW_CFA_opcode(insn)) {
+               case DW_CFA_advance_loc:
+                       delta = DW_CFA_operand(insn);
+                       delta *= cie->code_alignment_factor;
+                       frame->pc += delta;
+                       continue;
+                       /* NOTREACHED */
+               case DW_CFA_offset:
+                       reg = DW_CFA_operand(insn);
+                       count = dwarf_read_uleb128(current_insn, &offset);
+                       current_insn += count;
+                       offset *= cie->data_alignment_factor;
+                       regp = dwarf_frame_alloc_reg(frame, reg);
+                       regp->addr = offset;
+                       regp->flags |= DWARF_REG_OFFSET;
+                       continue;
+                       /* NOTREACHED */
+               case DW_CFA_restore:
+                       reg = DW_CFA_operand(insn);
+                       continue;
+                       /* NOTREACHED */
+               }
+
+               /*
+                * Secondly, handle the opcodes that don't embed their
+                * operands in the instruction.
+                */
+               switch (insn) {
+               case DW_CFA_nop:
+                       continue;
+               case DW_CFA_advance_loc1:
+                       delta = *current_insn++;
+                       frame->pc += delta * cie->code_alignment_factor;
+                       break;
+               case DW_CFA_advance_loc2:
+                       delta = get_unaligned((u16 *)current_insn);
+                       current_insn += 2;
+                       frame->pc += delta * cie->code_alignment_factor;
+                       break;
+               case DW_CFA_advance_loc4:
+                       delta = get_unaligned((u32 *)current_insn);
+                       current_insn += 4;
+                       frame->pc += delta * cie->code_alignment_factor;
+                       break;
+               case DW_CFA_offset_extended:
+                       count = dwarf_read_uleb128(current_insn, &reg);
+                       current_insn += count;
+                       count = dwarf_read_uleb128(current_insn, &offset);
+                       current_insn += count;
+                       offset *= cie->data_alignment_factor;
+                       break;
+               case DW_CFA_restore_extended:
+                       count = dwarf_read_uleb128(current_insn, &reg);
+                       current_insn += count;
+                       break;
+               case DW_CFA_undefined:
+                       count = dwarf_read_uleb128(current_insn, &reg);
+                       current_insn += count;
+                       regp = dwarf_frame_alloc_reg(frame, reg);
+                       regp->flags |= DWARF_UNDEFINED;
+                       break;
+               case DW_CFA_def_cfa:
+                       count = dwarf_read_uleb128(current_insn,
+                                                  &frame->cfa_register);
+                       current_insn += count;
+                       count = dwarf_read_uleb128(current_insn,
+                                                  &frame->cfa_offset);
+                       current_insn += count;
+
+                       frame->flags |= DWARF_FRAME_CFA_REG_OFFSET;
+                       break;
+               case DW_CFA_def_cfa_register:
+                       count = dwarf_read_uleb128(current_insn,
+                                                  &frame->cfa_register);
+                       current_insn += count;
+                       frame->flags |= DWARF_FRAME_CFA_REG_OFFSET;
+                       break;
+               case DW_CFA_def_cfa_offset:
+                       count = dwarf_read_uleb128(current_insn, &offset);
+                       current_insn += count;
+                       frame->cfa_offset = offset;
+                       break;
+               case DW_CFA_def_cfa_expression:
+                       count = dwarf_read_uleb128(current_insn, &expr_len);
+                       current_insn += count;
+
+                       frame->cfa_expr = current_insn;
+                       frame->cfa_expr_len = expr_len;
+                       current_insn += expr_len;
+
+                       frame->flags |= DWARF_FRAME_CFA_REG_EXP;
+                       break;
+               case DW_CFA_offset_extended_sf:
+                       count = dwarf_read_uleb128(current_insn, &reg);
+                       current_insn += count;
+                       count = dwarf_read_leb128(current_insn, &offset);
+                       current_insn += count;
+                       offset *= cie->data_alignment_factor;
+                       regp = dwarf_frame_alloc_reg(frame, reg);
+                       regp->flags |= DWARF_REG_OFFSET;
+                       regp->addr = offset;
+                       break;
+               case DW_CFA_val_offset:
+                       count = dwarf_read_uleb128(current_insn, &reg);
+                       current_insn += count;
+                       count = dwarf_read_leb128(current_insn, &offset);
+                       offset *= cie->data_alignment_factor;
+                       regp = dwarf_frame_alloc_reg(frame, reg);
+                       regp->flags |= DWARF_VAL_OFFSET;
+                       regp->addr = offset;
+                       break;
+               case DW_CFA_GNU_args_size:
+                       count = dwarf_read_uleb128(current_insn, &offset);
+                       current_insn += count;
+                       break;
+               case DW_CFA_GNU_negative_offset_extended:
+                       count = dwarf_read_uleb128(current_insn, &reg);
+                       current_insn += count;
+                       count = dwarf_read_uleb128(current_insn, &offset);
+                       offset *= cie->data_alignment_factor;
+
+                       regp = dwarf_frame_alloc_reg(frame, reg);
+                       regp->flags |= DWARF_REG_OFFSET;
+                       regp->addr = -offset;
+                       break;
+               default:
+                       pr_debug("unhandled DWARF instruction 0x%x\n", insn);
+                       UNWINDER_BUG();
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ *     dwarf_unwind_stack - recursively unwind the stack
+ *     @pc: address of the function to unwind
+ *     @prev: struct dwarf_frame of the previous stackframe on the callstack
+ *
+ *     Return a struct dwarf_frame representing the most recent frame
+ *     on the callstack. Each of the lower (older) stack frames are
+ *     linked via the "prev" member.
+ */
+struct dwarf_frame * dwarf_unwind_stack(unsigned long pc,
+                                       struct dwarf_frame *prev)
+{
+       struct dwarf_frame *frame;
+       struct dwarf_cie *cie;
+       struct dwarf_fde *fde;
+       struct dwarf_reg *reg;
+       unsigned long addr;
+
+       /*
+        * If this is the first invocation of this recursive function we
+        * need get the contents of a physical register to get the CFA
+        * in order to begin the virtual unwinding of the stack.
+        *
+        * NOTE: the return address is guaranteed to be setup by the
+        * time this function makes its first function call.
+        */
+       if (!pc && !prev)
+               pc = (unsigned long)current_text_addr();
+
+       frame = mempool_alloc(dwarf_frame_pool, GFP_ATOMIC);
+       if (!frame) {
+               printk(KERN_ERR "Unable to allocate a dwarf frame\n");
+               UNWINDER_BUG();
+       }
+
+       INIT_LIST_HEAD(&frame->reg_list);
+       frame->flags = 0;
+       frame->prev = prev;
+       frame->return_addr = 0;
+
+       fde = dwarf_lookup_fde(pc);
+       if (!fde) {
+               /*
+                * This is our normal exit path - the one that stops the
+                * recursion. There's two reasons why we might exit
+                * here,
+                *
+                *      a) pc has no asscociated DWARF frame info and so
+                *      we don't know how to unwind this frame. This is
+                *      usually the case when we're trying to unwind a
+                *      frame that was called from some assembly code
+                *      that has no DWARF info, e.g. syscalls.
+                *
+                *      b) the DEBUG info for pc is bogus. There's
+                *      really no way to distinguish this case from the
+                *      case above, which sucks because we could print a
+                *      warning here.
+                */
+               goto bail;
+       }
+
+       cie = dwarf_lookup_cie(fde->cie_pointer);
+
+       frame->pc = fde->initial_location;
+
+       /* CIE initial instructions */
+       dwarf_cfa_execute_insns(cie->initial_instructions,
+                               cie->instructions_end, cie, fde,
+                               frame, pc);
+
+       /* FDE instructions */
+       dwarf_cfa_execute_insns(fde->instructions, fde->end, cie,
+                               fde, frame, pc);
+
+       /* Calculate the CFA */
+       switch (frame->flags) {
+       case DWARF_FRAME_CFA_REG_OFFSET:
+               if (prev) {
+                       reg = dwarf_frame_reg(prev, frame->cfa_register);
+                       UNWINDER_BUG_ON(!reg);
+                       UNWINDER_BUG_ON(reg->flags != DWARF_REG_OFFSET);
+
+                       addr = prev->cfa + reg->addr;
+                       frame->cfa = __raw_readl(addr);
+
+               } else {
+                       /*
+                        * Again, this is the first invocation of this
+                        * recurisve function. We need to physically
+                        * read the contents of a register in order to
+                        * get the Canonical Frame Address for this
+                        * function.
+                        */
+                       frame->cfa = dwarf_read_arch_reg(frame->cfa_register);
+               }
+
+               frame->cfa += frame->cfa_offset;
+               break;
+       default:
+               UNWINDER_BUG();
+       }
+
+       reg = dwarf_frame_reg(frame, DWARF_ARCH_RA_REG);
+
+       /*
+        * If we haven't seen the return address register or the return
+        * address column is undefined then we must assume that this is
+        * the end of the callstack.
+        */
+       if (!reg || reg->flags == DWARF_UNDEFINED)
+               goto bail;
+
+       UNWINDER_BUG_ON(reg->flags != DWARF_REG_OFFSET);
+
+       addr = frame->cfa + reg->addr;
+       frame->return_addr = __raw_readl(addr);
+
+       return frame;
+
+bail:
+       dwarf_frame_free_regs(frame);
+       mempool_free(frame, dwarf_frame_pool);
+       return NULL;
+}
+
+static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
+                          unsigned char *end)
+{
+       struct dwarf_cie *cie;
+       unsigned long flags;
+       int count;
+
+       cie = kzalloc(sizeof(*cie), GFP_KERNEL);
+       if (!cie)
+               return -ENOMEM;
+
+       cie->length = len;
+
+       /*
+        * Record the offset into the .eh_frame section
+        * for this CIE. It allows this CIE to be
+        * quickly and easily looked up from the
+        * corresponding FDE.
+        */
+       cie->cie_pointer = (unsigned long)entry;
+
+       cie->version = *(char *)p++;
+       UNWINDER_BUG_ON(cie->version != 1);
+
+       cie->augmentation = p;
+       p += strlen(cie->augmentation) + 1;
+
+       count = dwarf_read_uleb128(p, &cie->code_alignment_factor);
+       p += count;
+
+       count = dwarf_read_leb128(p, &cie->data_alignment_factor);
+       p += count;
+
+       /*
+        * Which column in the rule table contains the
+        * return address?
+        */
+       if (cie->version == 1) {
+               cie->return_address_reg = __raw_readb(p);
+               p++;
+       } else {
+               count = dwarf_read_uleb128(p, &cie->return_address_reg);
+               p += count;
+       }
+
+       if (cie->augmentation[0] == 'z') {
+               unsigned int length, count;
+               cie->flags |= DWARF_CIE_Z_AUGMENTATION;
+
+               count = dwarf_read_uleb128(p, &length);
+               p += count;
+
+               UNWINDER_BUG_ON((unsigned char *)p > end);
+
+               cie->initial_instructions = p + length;
+               cie->augmentation++;
+       }
+
+       while (*cie->augmentation) {
+               /*
+                * "L" indicates a byte showing how the
+                * LSDA pointer is encoded. Skip it.
+                */
+               if (*cie->augmentation == 'L') {
+                       p++;
+                       cie->augmentation++;
+               } else if (*cie->augmentation == 'R') {
+                       /*
+                        * "R" indicates a byte showing
+                        * how FDE addresses are
+                        * encoded.
+                        */
+                       cie->encoding = *(char *)p++;
+                       cie->augmentation++;
+               } else if (*cie->augmentation == 'P') {
+                       /*
+                        * "R" indicates a personality
+                        * routine in the CIE
+                        * augmentation.
+                        */
+                       UNWINDER_BUG();
+               } else if (*cie->augmentation == 'S') {
+                       UNWINDER_BUG();
+               } else {
+                       /*
+                        * Unknown augmentation. Assume
+                        * 'z' augmentation.
+                        */
+                       p = cie->initial_instructions;
+                       UNWINDER_BUG_ON(!p);
+                       break;
+               }
+       }
+
+       cie->initial_instructions = p;
+       cie->instructions_end = end;
+
+       /* Add to list */
+       spin_lock_irqsave(&dwarf_cie_lock, flags);
+       list_add_tail(&cie->link, &dwarf_cie_list);
+       spin_unlock_irqrestore(&dwarf_cie_lock, flags);
+
+       return 0;
+}
+
+static int dwarf_parse_fde(void *entry, u32 entry_type,
+                          void *start, unsigned long len,
+                          unsigned char *end)
+{
+       struct dwarf_fde *fde;
+       struct dwarf_cie *cie;
+       unsigned long flags;
+       int count;
+       void *p = start;
+
+       fde = kzalloc(sizeof(*fde), GFP_KERNEL);
+       if (!fde)
+               return -ENOMEM;
+
+       fde->length = len;
+
+       /*
+        * In a .eh_frame section the CIE pointer is the
+        * delta between the address within the FDE
+        */
+       fde->cie_pointer = (unsigned long)(p - entry_type - 4);
+
+       cie = dwarf_lookup_cie(fde->cie_pointer);
+       fde->cie = cie;
+
+       if (cie->encoding)
+               count = dwarf_read_encoded_value(p, &fde->initial_location,
+                                                cie->encoding);
+       else
+               count = dwarf_read_addr(p, &fde->initial_location);
+
+       p += count;
+
+       if (cie->encoding)
+               count = dwarf_read_encoded_value(p, &fde->address_range,
+                                                cie->encoding & 0x0f);
+       else
+               count = dwarf_read_addr(p, &fde->address_range);
+
+       p += count;
+
+       if (fde->cie->flags & DWARF_CIE_Z_AUGMENTATION) {
+               unsigned int length;
+               count = dwarf_read_uleb128(p, &length);
+               p += count + length;
+       }
+
+       /* Call frame instructions. */
+       fde->instructions = p;
+       fde->end = end;
+
+       /* Add to list. */
+       spin_lock_irqsave(&dwarf_fde_lock, flags);
+       list_add_tail(&fde->link, &dwarf_fde_list);
+       spin_unlock_irqrestore(&dwarf_fde_lock, flags);
+
+       return 0;
+}
+
+static void dwarf_unwinder_dump(struct task_struct *task,
+                               struct pt_regs *regs,
+                               unsigned long *sp,
+                               const struct stacktrace_ops *ops,
+                               void *data)
+{
+       struct dwarf_frame *frame, *_frame;
+       unsigned long return_addr;
+
+       _frame = NULL;
+       return_addr = 0;
+
+       while (1) {
+               frame = dwarf_unwind_stack(return_addr, _frame);
+
+               if (_frame) {
+                       dwarf_frame_free_regs(_frame);
+                       mempool_free(_frame, dwarf_frame_pool);
+               }
+
+               _frame = frame;
+
+               if (!frame || !frame->return_addr)
+                       break;
+
+               return_addr = frame->return_addr;
+               ops->address(data, return_addr, 1);
+       }
+}
+
+static struct unwinder dwarf_unwinder = {
+       .name = "dwarf-unwinder",
+       .dump = dwarf_unwinder_dump,
+       .rating = 150,
+};
+
+static void dwarf_unwinder_cleanup(void)
+{
+       struct dwarf_cie *cie;
+       struct dwarf_fde *fde;
+
+       /*
+        * Deallocate all the memory allocated for the DWARF unwinder.
+        * Traverse all the FDE/CIE lists and remove and free all the
+        * memory associated with those data structures.
+        */
+       list_for_each_entry(cie, &dwarf_cie_list, link)
+               kfree(cie);
+
+       list_for_each_entry(fde, &dwarf_fde_list, link)
+               kfree(fde);
+
+       kmem_cache_destroy(dwarf_reg_cachep);
+       kmem_cache_destroy(dwarf_frame_cachep);
+}
+
+/**
+ *     dwarf_unwinder_init - initialise the dwarf unwinder
+ *
+ *     Build the data structures describing the .dwarf_frame section to
+ *     make it easier to lookup CIE and FDE entries. Because the
+ *     .eh_frame section is packed as tightly as possible it is not
+ *     easy to lookup the FDE for a given PC, so we build a list of FDE
+ *     and CIE entries that make it easier.
+ */
+static int __init dwarf_unwinder_init(void)
+{
+       u32 entry_type;
+       void *p, *entry;
+       int count, err = 0;
+       unsigned long len;
+       unsigned int c_entries, f_entries;
+       unsigned char *end;
+       INIT_LIST_HEAD(&dwarf_cie_list);
+       INIT_LIST_HEAD(&dwarf_fde_list);
+
+       c_entries = 0;
+       f_entries = 0;
+       entry = &__start_eh_frame;
+
+       dwarf_frame_cachep = kmem_cache_create("dwarf_frames",
+                       sizeof(struct dwarf_frame), 0,
+                       SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL);
+
+       dwarf_reg_cachep = kmem_cache_create("dwarf_regs",
+                       sizeof(struct dwarf_reg), 0,
+                       SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL);
+
+       dwarf_frame_pool = mempool_create(DWARF_FRAME_MIN_REQ,
+                                         mempool_alloc_slab,
+                                         mempool_free_slab,
+                                         dwarf_frame_cachep);
+
+       dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ,
+                                        mempool_alloc_slab,
+                                        mempool_free_slab,
+                                        dwarf_reg_cachep);
+
+       while ((char *)entry < __stop_eh_frame) {
+               p = entry;
+
+               count = dwarf_entry_len(p, &len);
+               if (count == 0) {
+                       /*
+                        * We read a bogus length field value. There is
+                        * nothing we can do here apart from disabling
+                        * the DWARF unwinder. We can't even skip this
+                        * entry and move to the next one because 'len'
+                        * tells us where our next entry is.
+                        */
+                       goto out;
+               } else
+                       p += count;
+
+               /* initial length does not include itself */
+               end = p + len;
+
+               entry_type = get_unaligned((u32 *)p);
+               p += 4;
+
+               if (entry_type == DW_EH_FRAME_CIE) {
+                       err = dwarf_parse_cie(entry, p, len, end);
+                       if (err < 0)
+                               goto out;
+                       else
+                               c_entries++;
+               } else {
+                       err = dwarf_parse_fde(entry, entry_type, p, len, end);
+                       if (err < 0)
+                               goto out;
+                       else
+                               f_entries++;
+               }
+
+               entry = (char *)entry + len + 4;
+       }
+
+       printk(KERN_INFO "DWARF unwinder initialised: read %u CIEs, %u FDEs\n",
+              c_entries, f_entries);
+
+       err = unwinder_register(&dwarf_unwinder);
+       if (err)
+               goto out;
+
+       return 0;
+
+out:
+       printk(KERN_ERR "Failed to initialise DWARF unwinder: %d\n", err);
+       dwarf_unwinder_cleanup();
+       return -EINVAL;
+}
+early_initcall(dwarf_unwinder_init);
index a952dcf..81a4614 100644 (file)
@@ -134,7 +134,7 @@ static void scif_sercon_init(char *s)
        sci_out(&scif_port, SCFCR, 0x0030);     /* TTRG=b'11 */
        sci_out(&scif_port, SCSCR, 0x0030);     /* TE, RE */
 }
-#elif defined(CONFIG_CPU_SH4)
+#elif defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3)
 #define DEFAULT_BAUD 115200
 /*
  * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
@@ -220,8 +220,7 @@ static int __init setup_early_printk(char *buf)
                early_console = &scif_console;
 
 #if !defined(CONFIG_SH_STANDARD_BIOS)
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721)
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3)
                scif_sercon_init(buf + 6);
 #endif
 #endif
index d62359c..68d9223 100644 (file)
  *     syscall #
  *
  */
+#include <asm/dwarf.h>
 
 #if defined(CONFIG_PREEMPT)
-#  define preempt_stop()       cli
+#  define preempt_stop()       cli ; TRACE_IRQS_OFF
 #else
 #  define preempt_stop()
 #  define resume_kernel                __restore_all
        .align  2
 ENTRY(exception_error)
        !
-#ifdef CONFIG_TRACE_IRQFLAGS
-       mov.l   2f, r0
-       jsr     @r0
-        nop
-#endif
+       TRACE_IRQS_ON
        sti
        mov.l   1f, r0
        jmp     @r0
@@ -67,18 +64,15 @@ ENTRY(exception_error)
 
        .align  2
 1:     .long   do_exception_error
-#ifdef CONFIG_TRACE_IRQFLAGS
-2:     .long   trace_hardirqs_on
-#endif
 
        .align  2
 ret_from_exception:
+       CFI_STARTPROC simple
+       CFI_DEF_CFA r14, 0
+       CFI_REL_OFFSET 17, 64
+       CFI_REL_OFFSET 15, 0
+       CFI_REL_OFFSET 14, 56
        preempt_stop()
-#ifdef CONFIG_TRACE_IRQFLAGS
-       mov.l   4f, r0
-       jsr     @r0
-        nop
-#endif
 ENTRY(ret_from_irq)
        !
        mov     #OFF_SR, r0
@@ -93,6 +87,7 @@ ENTRY(ret_from_irq)
         nop
 ENTRY(resume_kernel)
        cli
+       TRACE_IRQS_OFF
        mov.l   @(TI_PRE_COUNT,r8), r0  ! current_thread_info->preempt_count
        tst     r0, r0
        bf      noresched
@@ -103,8 +98,9 @@ need_resched:
 
        mov     #OFF_SR, r0
        mov.l   @(r0,r15), r0           ! get status register
-       and     #0xf0, r0               ! interrupts off (exception path)?
-       cmp/eq  #0xf0, r0
+       shlr    r0
+       and     #(0xf0>>1), r0          ! interrupts off (exception path)?
+       cmp/eq  #(0xf0>>1), r0
        bt      noresched
        mov.l   3f, r0
        jsr     @r0                     ! call preempt_schedule_irq
@@ -125,13 +121,9 @@ noresched:
 ENTRY(resume_userspace)
        ! r8: current_thread_info
        cli
-#ifdef CONFIG_TRACE_IRQFLAGS
-       mov.l   5f, r0
-       jsr     @r0
-        nop
-#endif
+       TRACE_IRQS_OfF
        mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
-       tst     #_TIF_WORK_MASK, r0
+       tst     #(_TIF_WORK_MASK & 0xff), r0
        bt/s    __restore_all
         tst    #_TIF_NEED_RESCHED, r0
 
@@ -156,14 +148,10 @@ work_resched:
        jsr     @r1                             ! schedule
         nop
        cli
-#ifdef CONFIG_TRACE_IRQFLAGS
-       mov.l   5f, r0
-       jsr     @r0
-        nop
-#endif
+       TRACE_IRQS_OFF
        !
        mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
-       tst     #_TIF_WORK_MASK, r0
+       tst     #(_TIF_WORK_MASK & 0xff), r0
        bt      __restore_all
        bra     work_pending
         tst    #_TIF_NEED_RESCHED, r0
@@ -172,23 +160,15 @@ work_resched:
 1:     .long   schedule
 2:     .long   do_notify_resume
 3:     .long   resume_userspace
-#ifdef CONFIG_TRACE_IRQFLAGS
-4:     .long   trace_hardirqs_on
-5:     .long   trace_hardirqs_off
-#endif
 
        .align  2
 syscall_exit_work:
        ! r0: current_thread_info->flags
        ! r8: current_thread_info
-       tst     #_TIF_WORK_SYSCALL_MASK, r0
+       tst     #(_TIF_WORK_SYSCALL_MASK & 0xff), r0
        bt/s    work_pending
         tst    #_TIF_NEED_RESCHED, r0
-#ifdef CONFIG_TRACE_IRQFLAGS
-       mov.l   5f, r0
-       jsr     @r0
-        nop
-#endif
+       TRACE_IRQS_ON
        sti
        mov     r15, r4
        mov.l   8f, r0                  ! do_syscall_trace_leave
@@ -226,12 +206,25 @@ syscall_trace_entry:
         mov.l  r0, @(OFF_R0,r15)       ! Return value
 
 __restore_all:
-       mov.l   1f, r0
+       mov     #OFF_SR, r0
+       mov.l   @(r0,r15), r0   ! get status register
+
+       shlr2   r0
+       and     #0x3c, r0
+       cmp/eq  #0x3c, r0
+       bt      1f
+       TRACE_IRQS_ON
+       bra     2f
+        nop
+1:
+       TRACE_IRQS_OFF
+2:
+       mov.l   3f, r0
        jmp     @r0
         nop
 
        .align  2
-1:     .long   restore_all
+3:     .long   restore_all
 
        .align  2
 syscall_badsys:                        ! Bad syscall number
@@ -259,6 +252,7 @@ debug_trap:
         nop
        bra     __restore_all
         nop
+       CFI_ENDPROC
 
        .align  2
 1:     .long   debug_trap_table
@@ -304,6 +298,7 @@ ret_from_fork:
  * system calls and debug traps through their respective jump tables.
  */
 ENTRY(system_call)
+       setup_frame_reg
 #if !defined(CONFIG_CPU_SH2)
        mov.l   1f, r9
        mov.l   @r9, r8         ! Read from TRA (Trap Address) Register
@@ -321,18 +316,18 @@ ENTRY(system_call)
        bt/s    debug_trap              ! it's a debug trap..
         nop
 
-#ifdef CONFIG_TRACE_IRQFLAGS
-       mov.l   5f, r10
-       jsr     @r10
-        nop
-#endif
+       TRACE_IRQS_ON
        sti
 
        !
        get_current_thread_info r8, r10
        mov.l   @(TI_FLAGS,r8), r8
-       mov     #_TIF_WORK_SYSCALL_MASK, r10
+       mov     #(_TIF_WORK_SYSCALL_MASK & 0xff), r10
+       mov     #(_TIF_WORK_SYSCALL_MASK >> 8), r9
        tst     r10, r8
+       shll8   r9
+       bf      syscall_trace_entry
+       tst     r9, r8
        bf      syscall_trace_entry
        !
        mov.l   2f, r8                  ! Number of syscalls
@@ -351,15 +346,15 @@ syscall_call:
        !
 syscall_exit:
        cli
-#ifdef CONFIG_TRACE_IRQFLAGS
-       mov.l   6f, r0
-       jsr     @r0
-        nop
-#endif
+       TRACE_IRQS_OFF
        !
        get_current_thread_info r8, r0
        mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
-       tst     #_TIF_ALLWORK_MASK, r0
+       tst     #(_TIF_ALLWORK_MASK & 0xff), r0
+       mov     #(_TIF_ALLWORK_MASK >> 8), r1
+       bf      syscall_exit_work
+       shlr8   r0
+       tst     r0, r1
        bf      syscall_exit_work
        bra     __restore_all
         nop
@@ -369,9 +364,5 @@ syscall_exit:
 #endif
 2:     .long   NR_syscalls
 3:     .long   sys_call_table
-#ifdef CONFIG_TRACE_IRQFLAGS
-5:     .long   trace_hardirqs_on
-6:     .long   trace_hardirqs_off
-#endif
 7:     .long   do_syscall_trace_enter
 8:     .long   do_syscall_trace_leave
index 066f37d..a3dcc6d 100644 (file)
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
 #include <asm/ftrace.h>
 #include <asm/cacheflush.h>
+#include <asm/unistd.h>
+#include <trace/syscall.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
 static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE];
 
 static unsigned char ftrace_nop[4];
@@ -131,3 +135,187 @@ int __init ftrace_dyn_arch_init(void *data)
 
        return 0;
 }
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#ifdef CONFIG_DYNAMIC_FTRACE
+extern void ftrace_graph_call(void);
+
+static int ftrace_mod(unsigned long ip, unsigned long old_addr,
+                     unsigned long new_addr)
+{
+       unsigned char code[MCOUNT_INSN_SIZE];
+
+       if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE))
+               return -EFAULT;
+
+       if (old_addr != __raw_readl((unsigned long *)code))
+               return -EINVAL;
+
+       __raw_writel(new_addr, ip);
+       return 0;
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+       unsigned long ip, old_addr, new_addr;
+
+       ip = (unsigned long)(&ftrace_graph_call) + GRAPH_INSN_OFFSET;
+       old_addr = (unsigned long)(&skip_trace);
+       new_addr = (unsigned long)(&ftrace_graph_caller);
+
+       return ftrace_mod(ip, old_addr, new_addr);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+       unsigned long ip, old_addr, new_addr;
+
+       ip = (unsigned long)(&ftrace_graph_call) + GRAPH_INSN_OFFSET;
+       old_addr = (unsigned long)(&ftrace_graph_caller);
+       new_addr = (unsigned long)(&skip_trace);
+
+       return ftrace_mod(ip, old_addr, new_addr);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+/*
+ * Hook the return address and push it in the stack of return addrs
+ * in the current thread info.
+ *
+ * This is the main routine for the function graph tracer. The function
+ * graph tracer essentially works like this:
+ *
+ * parent is the stack address containing self_addr's return address.
+ * We pull the real return address out of parent and store it in
+ * current's ret_stack. Then, we replace the return address on the stack
+ * with the address of return_to_handler. self_addr is the function that
+ * called mcount.
+ *
+ * When self_addr returns, it will jump to return_to_handler which calls
+ * ftrace_return_to_handler. ftrace_return_to_handler will pull the real
+ * return address off of current's ret_stack and jump to it.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
+{
+       unsigned long old;
+       int faulted, err;
+       struct ftrace_graph_ent trace;
+       unsigned long return_hooker = (unsigned long)&return_to_handler;
+
+       if (unlikely(atomic_read(&current->tracing_graph_pause)))
+               return;
+
+       /*
+        * Protect against fault, even if it shouldn't
+        * happen. This tool is too much intrusive to
+        * ignore such a protection.
+        */
+       __asm__ __volatile__(
+               "1:                                             \n\t"
+               "mov.l          @%2, %0                         \n\t"
+               "2:                                             \n\t"
+               "mov.l          %3, @%2                         \n\t"
+               "mov            #0, %1                          \n\t"
+               "3:                                             \n\t"
+               ".section .fixup, \"ax\"                        \n\t"
+               "4:                                             \n\t"
+               "mov.l          5f, %0                          \n\t"
+               "jmp            @%0                             \n\t"
+               " mov           #1, %1                          \n\t"
+               ".balign 4                                      \n\t"
+               "5:     .long 3b                                \n\t"
+               ".previous                                      \n\t"
+               ".section __ex_table,\"a\"                      \n\t"
+               ".long 1b, 4b                                   \n\t"
+               ".long 2b, 4b                                   \n\t"
+               ".previous                                      \n\t"
+               : "=&r" (old), "=r" (faulted)
+               : "r" (parent), "r" (return_hooker)
+       );
+
+       if (unlikely(faulted)) {
+               ftrace_graph_stop();
+               WARN_ON(1);
+               return;
+       }
+
+       err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0);
+       if (err == -EBUSY) {
+               __raw_writel(old, parent);
+               return;
+       }
+
+       trace.func = self_addr;
+
+       /* Only trace if the calling function expects to */
+       if (!ftrace_graph_entry(&trace)) {
+               current->curr_ret_stack--;
+               __raw_writel(old, parent);
+       }
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_FTRACE_SYSCALLS
+
+extern unsigned long __start_syscalls_metadata[];
+extern unsigned long __stop_syscalls_metadata[];
+extern unsigned long *sys_call_table;
+
+static struct syscall_metadata **syscalls_metadata;
+
+static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
+{
+       struct syscall_metadata *start;
+       struct syscall_metadata *stop;
+       char str[KSYM_SYMBOL_LEN];
+
+
+       start = (struct syscall_metadata *)__start_syscalls_metadata;
+       stop = (struct syscall_metadata *)__stop_syscalls_metadata;
+       kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
+
+       for ( ; start < stop; start++) {
+               if (start->name && !strcmp(start->name, str))
+                       return start;
+       }
+
+       return NULL;
+}
+
+struct syscall_metadata *syscall_nr_to_meta(int nr)
+{
+       if (!syscalls_metadata || nr >= FTRACE_SYSCALL_MAX || nr < 0)
+               return NULL;
+
+       return syscalls_metadata[nr];
+}
+
+void arch_init_ftrace_syscalls(void)
+{
+       int i;
+       struct syscall_metadata *meta;
+       unsigned long **psys_syscall_table = &sys_call_table;
+       static atomic_t refs;
+
+       if (atomic_inc_return(&refs) != 1)
+               goto end;
+
+       syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
+                                       FTRACE_SYSCALL_MAX, GFP_KERNEL);
+       if (!syscalls_metadata) {
+               WARN_ON(1);
+               return;
+       }
+
+       for (i = 0; i < FTRACE_SYSCALL_MAX; i++) {
+               meta = find_syscall_meta(psys_syscall_table[i]);
+               syscalls_metadata[i] = meta;
+       }
+       return;
+
+       /* Paranoid: avoid overflow */
+end:
+       atomic_dec(&refs);
+}
+#endif /* CONFIG_FTRACE_SYSCALLS */
index 4f85fff..4770c24 100644 (file)
@@ -1,12 +1,9 @@
 /*
- * linux/arch/sh/kernel/io.c
+ * arch/sh/kernel/io.c - Machine independent I/O functions.
  *
- * Copyright (C) 2000  Stuart Menefy
+ * Copyright (C) 2000 - 2009  Stuart Menefy
  * Copyright (C) 2005  Paul Mundt
  *
- * Provide real functions which expand to whatever the header file defined.
- * Also definitions of machine independent IO functions.
- *
  * 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.
 
 /*
  * Copy data from IO memory space to "real" memory space.
- * This needs to be optimized.
  */
 void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned long count)
 {
-       unsigned char *p = to;
-        while (count) {
-                count--;
-                *p = readb(from);
-                p++;
-                from++;
-        }
+       /*
+        * Would it be worthwhile doing byte and long transfers first
+        * to try and get aligned?
+        */
+#ifdef CONFIG_CPU_SH4
+       if ((count >= 0x20) &&
+            (((u32)to & 0x1f) == 0) && (((u32)from & 0x3) == 0)) {
+               int tmp2, tmp3, tmp4, tmp5, tmp6;
+
+               __asm__ __volatile__(
+                       "1:                     \n\t"
+                       "mov.l  @%7+, r0        \n\t"
+                       "mov.l  @%7+, %2        \n\t"
+                       "movca.l r0, @%0        \n\t"
+                       "mov.l  @%7+, %3        \n\t"
+                       "mov.l  @%7+, %4        \n\t"
+                       "mov.l  @%7+, %5        \n\t"
+                       "mov.l  @%7+, %6        \n\t"
+                       "mov.l  @%7+, r7        \n\t"
+                       "mov.l  @%7+, r0        \n\t"
+                       "mov.l  %2, @(0x04,%0)  \n\t"
+                       "mov    #0x20, %2       \n\t"
+                       "mov.l  %3, @(0x08,%0)  \n\t"
+                       "sub    %2, %1          \n\t"
+                       "mov.l  %4, @(0x0c,%0)  \n\t"
+                       "cmp/hi %1, %2          ! T if 32 > count       \n\t"
+                       "mov.l  %5, @(0x10,%0)  \n\t"
+                       "mov.l  %6, @(0x14,%0)  \n\t"
+                       "mov.l  r7, @(0x18,%0)  \n\t"
+                       "mov.l  r0, @(0x1c,%0)  \n\t"
+                       "bf.s   1b              \n\t"
+                       " add   #0x20, %0       \n\t"
+                       : "=&r" (to), "=&r" (count),
+                         "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4),
+                         "=&r" (tmp5), "=&r" (tmp6), "=&r" (from)
+                       : "7"(from), "0" (to), "1" (count)
+                       : "r0", "r7", "t", "memory");
+       }
+#endif
+
+       if ((((u32)to | (u32)from) & 0x3) == 0) {
+               for (; count > 3; count -= 4) {
+                       *(u32 *)to = *(volatile u32 *)from;
+                       to += 4;
+                       from += 4;
+               }
+       }
+
+       for (; count > 0; count--) {
+               *(u8 *)to = *(volatile u8 *)from;
+               to++;
+               from++;
+       }
+
+       mb();
 }
 EXPORT_SYMBOL(memcpy_fromio);
 
 /*
  * Copy data from "real" memory space to IO memory space.
- * This needs to be optimized.
  */
 void memcpy_toio(volatile void __iomem *to, const void *from, unsigned long count)
 {
-       const unsigned char *p = from;
-        while (count) {
-                count--;
-                writeb(*p, to);
-                p++;
-                to++;
-        }
+       if ((((u32)to | (u32)from) & 0x3) == 0) {
+               for ( ; count > 3; count -= 4) {
+                       *(volatile u32 *)to = *(u32 *)from;
+                       to += 4;
+                       from += 4;
+               }
+       }
+
+       for (; count > 0; count--) {
+               *(volatile u8 *)to = *(u8 *)from;
+               to++;
+               from++;
+       }
+
+       mb();
 }
 EXPORT_SYMBOL(memcpy_toio);
 
@@ -62,6 +113,8 @@ void memset_io(volatile void __iomem *dst, int c, unsigned long count)
 }
 EXPORT_SYMBOL(memset_io);
 
+#ifndef CONFIG_GENERIC_IOMAP
+
 void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
        void __iomem *ret;
@@ -79,3 +132,5 @@ void ioport_unmap(void __iomem *addr)
        sh_mv.mv_ioport_unmap(addr);
 }
 EXPORT_SYMBOL(ioport_unmap);
+
+#endif /* CONFIG_GENERIC_IOMAP */
index 5a7f554..4ff5072 100644 (file)
@@ -73,35 +73,19 @@ u32 generic_inl_p(unsigned long port)
 
 void generic_insb(unsigned long port, void *dst, unsigned long count)
 {
-       volatile u8 *port_addr;
-       u8 *buf = dst;
-
-       port_addr = (volatile u8 __force *)__ioport_map(port, 1);
-       while (count--)
-               *buf++ = *port_addr;
+       __raw_readsb(__ioport_map(port, 1), dst, count);
+       dummy_read();
 }
 
 void generic_insw(unsigned long port, void *dst, unsigned long count)
 {
-       volatile u16 *port_addr;
-       u16 *buf = dst;
-
-       port_addr = (volatile u16 __force *)__ioport_map(port, 2);
-       while (count--)
-               *buf++ = *port_addr;
-
+       __raw_readsw(__ioport_map(port, 2), dst, count);
        dummy_read();
 }
 
 void generic_insl(unsigned long port, void *dst, unsigned long count)
 {
-       volatile u32 *port_addr;
-       u32 *buf = dst;
-
-       port_addr = (volatile u32 __force *)__ioport_map(port, 4);
-       while (count--)
-               *buf++ = *port_addr;
-
+       __raw_readsl(__ioport_map(port, 4), dst, count);
        dummy_read();
 }
 
@@ -145,37 +129,19 @@ void generic_outl_p(u32 b, unsigned long port)
  */
 void generic_outsb(unsigned long port, const void *src, unsigned long count)
 {
-       volatile u8 *port_addr;
-       const u8 *buf = src;
-
-       port_addr = (volatile u8 __force *)__ioport_map(port, 1);
-
-       while (count--)
-               *port_addr = *buf++;
+       __raw_writesb(__ioport_map(port, 1), src, count);
+       dummy_read();
 }
 
 void generic_outsw(unsigned long port, const void *src, unsigned long count)
 {
-       volatile u16 *port_addr;
-       const u16 *buf = src;
-
-       port_addr = (volatile u16 __force *)__ioport_map(port, 2);
-
-       while (count--)
-               *port_addr = *buf++;
-
+       __raw_writesw(__ioport_map(port, 2), src, count);
        dummy_read();
 }
 
 void generic_outsl(unsigned long port, const void *src, unsigned long count)
 {
-       volatile u32 *port_addr;
-       const u32 *buf = src;
-
-       port_addr = (volatile u32 __force *)__ioport_map(port, 4);
-       while (count--)
-               *port_addr = *buf++;
-
+       __raw_writesl(__ioport_map(port, 4), src, count);
        dummy_read();
 }
 
index 77dfecb..69be603 100644 (file)
@@ -112,14 +112,15 @@ void __iomem *match_trapped_io_handler(struct list_head *list,
        struct trapped_io *tiop;
        struct resource *res;
        int k, len;
+       unsigned long flags;
 
-       spin_lock_irq(&trapped_lock);
+       spin_lock_irqsave(&trapped_lock, flags);
        list_for_each_entry(tiop, list, list) {
                voffs = 0;
                for (k = 0; k < tiop->num_resources; k++) {
                        res = tiop->resource + k;
                        if (res->start == offset) {
-                               spin_unlock_irq(&trapped_lock);
+                               spin_unlock_irqrestore(&trapped_lock, flags);
                                return tiop->virt_base + voffs;
                        }
 
@@ -127,7 +128,7 @@ void __iomem *match_trapped_io_handler(struct list_head *list,
                        voffs += roundup(len, PAGE_SIZE);
                }
        }
-       spin_unlock_irq(&trapped_lock);
+       spin_unlock_irqrestore(&trapped_lock, flags);
        return NULL;
 }
 EXPORT_SYMBOL_GPL(match_trapped_io_handler);
@@ -283,7 +284,8 @@ int handle_trapped_io(struct pt_regs *regs, unsigned long address)
                return 0;
        }
 
-       tmp = handle_unaligned_access(instruction, regs, &trapped_io_access);
+       tmp = handle_unaligned_access(instruction, regs,
+                                     &trapped_io_access, 1);
        set_fs(oldfs);
        return tmp == 0;
 }
index 3d09062..60f8af4 100644 (file)
@@ -114,24 +114,7 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
 #endif
 
        irq_enter();
-
-#ifdef CONFIG_DEBUG_STACKOVERFLOW
-       /* Debugging check for stack overflow: is there less than 1KB free? */
-       {
-               long sp;
-
-               __asm__ __volatile__ ("and r15, %0" :
-                                       "=r" (sp) : "0" (THREAD_SIZE - 1));
-
-               if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
-                       printk("do_IRQ: stack overflow: %ld\n",
-                              sp - sizeof(struct thread_info));
-                       dump_stack();
-               }
-       }
-#endif
-
-       irq = irq_demux(intc_evt2irq(irq));
+       irq = irq_demux(irq);
 
 #ifdef CONFIG_IRQSTACKS
        curctx = (union irq_ctx *)current_thread_info();
index 305aad7..3e532d0 100644 (file)
@@ -15,8 +15,6 @@
 #include <linux/io.h>
 #include <asm/cacheflush.h>
 
-char in_nmi = 0;       /* Set during NMI to prevent re-entry */
-
 /* Macros for single step instruction identification */
 #define OPCODE_BT(op)          (((op) & 0xff00) == 0x8900)
 #define OPCODE_BF(op)          (((op) & 0xff00) == 0x8b00)
@@ -195,8 +193,6 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
        regs->gbr = gdb_regs[GDB_GBR];
        regs->mach = gdb_regs[GDB_MACH];
        regs->macl = gdb_regs[GDB_MACL];
-
-       __asm__ __volatile__ ("ldc %0, vbr" : : "r" (gdb_regs[GDB_VBR]));
 }
 
 void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
index 96e8eae..0b04e7d 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/jiffies.h>
 #include <linux/percpu.h>
 #include <linux/clockchips.h>
+#include <linux/hardirq.h>
 #include <linux/irq.h>
 
 static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
@@ -33,7 +34,9 @@ void local_timer_interrupt(void)
 {
        struct clock_event_device *clk = &__get_cpu_var(local_clockevent);
 
+       irq_enter();
        clk->event_handler(clk);
+       irq_exit();
 }
 
 static void dummy_timer_set_mode(enum clock_event_mode mode,
@@ -46,8 +49,10 @@ void __cpuinit local_timer_setup(unsigned int cpu)
        struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
 
        clk->name               = "dummy_timer";
-       clk->features           = CLOCK_EVT_FEAT_DUMMY;
-       clk->rating             = 200;
+       clk->features           = CLOCK_EVT_FEAT_ONESHOT |
+                                 CLOCK_EVT_FEAT_PERIODIC |
+                                 CLOCK_EVT_FEAT_DUMMY;
+       clk->rating             = 400;
        clk->mult               = 1;
        clk->set_mode           = dummy_timer_set_mode;
        clk->broadcast          = smp_timer_broadcast;
diff --git a/arch/sh/kernel/nmi_debug.c b/arch/sh/kernel/nmi_debug.c
new file mode 100644 (file)
index 0000000..ff0abbd
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.h>
+#include <linux/kdebug.h>
+#include <linux/notifier.h>
+#include <linux/sched.h>
+#include <linux/hardirq.h>
+
+enum nmi_action {
+       NMI_SHOW_STATE  = 1 << 0,
+       NMI_SHOW_REGS   = 1 << 1,
+       NMI_DIE         = 1 << 2,
+       NMI_DEBOUNCE    = 1 << 3,
+};
+
+static unsigned long nmi_actions;
+
+static int nmi_debug_notify(struct notifier_block *self,
+               unsigned long val, void *data)
+{
+       struct die_args *args = data;
+
+       if (likely(val != DIE_NMI))
+               return NOTIFY_DONE;
+
+       if (nmi_actions & NMI_SHOW_STATE)
+               show_state();
+       if (nmi_actions & NMI_SHOW_REGS)
+               show_regs(args->regs);
+       if (nmi_actions & NMI_DEBOUNCE)
+               mdelay(10);
+       if (nmi_actions & NMI_DIE)
+               return NOTIFY_BAD;
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block nmi_debug_nb = {
+       .notifier_call = nmi_debug_notify,
+};
+
+static int __init nmi_debug_setup(char *str)
+{
+       char *p, *sep;
+
+       register_die_notifier(&nmi_debug_nb);
+
+       if (*str != '=')
+               return 0;
+
+       for (p = str + 1; *p; p = sep + 1) {
+               sep = strchr(p, ',');
+               if (sep)
+                       *sep = 0;
+               if (strcmp(p, "state") == 0)
+                       nmi_actions |= NMI_SHOW_STATE;
+               else if (strcmp(p, "regs") == 0)
+                       nmi_actions |= NMI_SHOW_REGS;
+               else if (strcmp(p, "debounce") == 0)
+                       nmi_actions |= NMI_DEBOUNCE;
+               else if (strcmp(p, "die") == 0)
+                       nmi_actions |= NMI_DIE;
+               else
+                       printk(KERN_WARNING "NMI: Unrecognized action `%s'\n",
+                               p);
+               if (!sep)
+                       break;
+       }
+
+       return 0;
+}
+__setup("nmi_debug", nmi_debug_setup);
index 92d7740..0673c47 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/tick.h>
 #include <linux/reboot.h>
 #include <linux/fs.h>
+#include <linux/ftrace.h>
 #include <linux/preempt.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/ubc.h>
 #include <asm/fpu.h>
 #include <asm/syscalls.h>
+#include <asm/watchdog.h>
 
 int ubc_usercnt = 0;
 
+#ifdef CONFIG_32BIT
+static void watchdog_trigger_immediate(void)
+{
+       sh_wdt_write_cnt(0xFF);
+       sh_wdt_write_csr(0xC2);
+}
+
+void machine_restart(char * __unused)
+{
+       local_irq_disable();
+
+       /* Use watchdog timer to trigger reset */
+       watchdog_trigger_immediate();
+
+       while (1)
+               cpu_sleep();
+}
+#else
 void machine_restart(char * __unused)
 {
        /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */
        asm volatile("ldc %0, sr\n\t"
                     "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001));
 }
+#endif
 
 void machine_halt(void)
 {
@@ -264,8 +285,8 @@ static void ubc_set_tracing(int asid, unsigned long pc)
  *     switch_to(x,y) should switch tasks from x to y.
  *
  */
-struct task_struct *__switch_to(struct task_struct *prev,
-                               struct task_struct *next)
+__notrace_funcgraph struct task_struct *
+__switch_to(struct task_struct *prev, struct task_struct *next)
 {
 #if defined(CONFIG_SH_FPU)
        unlazy_fpu(prev, task_pt_regs(prev));
index 24de742..1192398 100644 (file)
@@ -425,7 +425,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
                struct task_struct *p, struct pt_regs *regs)
 {
        struct pt_regs *childregs;
-       unsigned long long se;                  /* Sign extension */
 
 #ifdef CONFIG_SH_FPU
        if(last_task_used_math == current) {
@@ -441,11 +440,19 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 
        *childregs = *regs;
 
+       /*
+        * Sign extend the edited stack.
+        * Note that thread.pc and thread.pc will stay
+        * 32-bit wide and context switch must take care
+        * of NEFF sign extension.
+        */
        if (user_mode(regs)) {
-               childregs->regs[15] = usp;
+               childregs->regs[15] = neff_sign_extend(usp);
                p->thread.uregs = childregs;
        } else {
-               childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+               childregs->regs[15] =
+                       neff_sign_extend((unsigned long)task_stack_page(p) +
+                                        THREAD_SIZE);
        }
 
        childregs->regs[9] = 0; /* Set return value for child */
@@ -454,17 +461,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        p->thread.sp = (unsigned long) childregs;
        p->thread.pc = (unsigned long) ret_from_fork;
 
-       /*
-        * Sign extend the edited stack.
-         * Note that thread.pc and thread.pc will stay
-        * 32-bit wide and context switch must take care
-        * of NEFF sign extension.
-        */
-
-       se = childregs->regs[15];
-       se = (se & NEFF_SIGN) ? (se | NEFF_MASK) : se;
-       childregs->regs[15] = se;
-
        return 0;
 }
 
index 3392e83..f4f58e4 100644 (file)
@@ -34,6 +34,8 @@
 #include <asm/syscalls.h>
 #include <asm/fpu.h>
 
+#include <trace/syscall.h>
+
 /*
  * This routine will get a word off of the process kernel stack.
  */
@@ -459,6 +461,11 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
                 */
                ret = -1L;
 
+#ifdef CONFIG_FTRACE_SYSCALLS
+       if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+               ftrace_syscall_enter(regs);
+#endif
+
        if (unlikely(current->audit_context))
                audit_syscall_entry(audit_arch(), regs->regs[3],
                                    regs->regs[4], regs->regs[5],
@@ -475,6 +482,11 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
                audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
                                   regs->regs[0]);
 
+#ifdef CONFIG_FTRACE_SYSCALLS
+       if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+               ftrace_syscall_exit(regs);
+#endif
+
        step = test_thread_flag(TIF_SINGLESTEP);
        if (step || test_thread_flag(TIF_SYSCALL_TRACE))
                tracehook_report_syscall_exit(regs, step);
index dd38338..f9d44f8 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
+#include <linux/lmb.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/page.h>
@@ -48,6 +49,7 @@
 struct sh_cpuinfo cpu_data[NR_CPUS] __read_mostly = {
        [0] = {
                .type                   = CPU_SH_NONE,
+               .family                 = CPU_FAMILY_UNKNOWN,
                .loops_per_jiffy        = 10000000,
        },
 };
@@ -233,39 +235,45 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
 void __init setup_bootmem_allocator(unsigned long free_pfn)
 {
        unsigned long bootmap_size;
+       unsigned long bootmap_pages, bootmem_paddr;
+       u64 total_pages = (lmb_end_of_DRAM() - __MEMORY_START) >> PAGE_SHIFT;
+       int i;
+
+       bootmap_pages = bootmem_bootmap_pages(total_pages);
+
+       bootmem_paddr = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
 
        /*
         * Find a proper area for the bootmem bitmap. After this
         * bootstrap step all allocations (until the page allocator
         * is intact) must be done via bootmem_alloc().
         */
-       bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn,
+       bootmap_size = init_bootmem_node(NODE_DATA(0),
+                                        bootmem_paddr >> PAGE_SHIFT,
                                         min_low_pfn, max_low_pfn);
 
-       __add_active_range(0, min_low_pfn, max_low_pfn);
-       register_bootmem_low_pages();
-
-       node_set_online(0);
+       /* Add active regions with valid PFNs. */
+       for (i = 0; i < lmb.memory.cnt; i++) {
+               unsigned long start_pfn, end_pfn;
+               start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
+               end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
+               __add_active_range(0, start_pfn, end_pfn);
+       }
 
        /*
-        * Reserve the kernel text and
-        * Reserve the bootmem bitmap. We do this in two steps (first step
-        * was init_bootmem()), because this catches the (definitely buggy)
-        * case of us accidentally initializing the bootmem allocator with
-        * an invalid RAM area.
+        * Add all physical memory to the bootmem map and mark each
+        * area as present.
         */
-       reserve_bootmem(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
-                       (PFN_PHYS(free_pfn) + bootmap_size + PAGE_SIZE - 1) -
-                       (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET),
-                       BOOTMEM_DEFAULT);
+       register_bootmem_low_pages();
 
-       /*
-        * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
-        */
-       if (CONFIG_ZERO_PAGE_OFFSET != 0)
-               reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET,
+       /* Reserve the sections we're already using. */
+       for (i = 0; i < lmb.reserved.cnt; i++)
+               reserve_bootmem(lmb.reserved.region[i].base,
+                               lmb_size_bytes(&lmb.reserved, i),
                                BOOTMEM_DEFAULT);
 
+       node_set_online(0);
+
        sparse_memory_present_with_active_regions(0);
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -296,12 +304,37 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
 static void __init setup_memory(void)
 {
        unsigned long start_pfn;
+       u64 base = min_low_pfn << PAGE_SHIFT;
+       u64 size = (max_low_pfn << PAGE_SHIFT) - base;
 
        /*
         * Partially used pages are not usable - thus
         * we are rounding upwards:
         */
        start_pfn = PFN_UP(__pa(_end));
+
+       lmb_add(base, size);
+
+       /*
+        * Reserve the kernel text and
+        * Reserve the bootmem bitmap. We do this in two steps (first step
+        * was init_bootmem()), because this catches the (definitely buggy)
+        * case of us accidentally initializing the bootmem allocator with
+        * an invalid RAM area.
+        */
+       lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
+                   (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) -
+                   (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
+
+       /*
+        * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
+        */
+       if (CONFIG_ZERO_PAGE_OFFSET != 0)
+               lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET);
+
+       lmb_analyze();
+       lmb_dump_all();
+
        setup_bootmem_allocator(start_pfn);
 }
 #else
@@ -372,10 +405,14 @@ void __init setup_arch(char **cmdline_p)
        if (!memory_end)
                memory_end = memory_start + __MEMORY_SIZE;
 
-#ifdef CONFIG_CMDLINE_BOOL
+#ifdef CONFIG_CMDLINE_OVERWRITE
        strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line));
 #else
        strlcpy(command_line, COMMAND_LINE, sizeof(command_line));
+#ifdef CONFIG_CMDLINE_EXTEND
+       strlcat(command_line, " ", sizeof(command_line));
+       strlcat(command_line, CONFIG_CMDLINE, sizeof(command_line));
+#endif
 #endif
 
        /* Save unparsed command line copy for /proc/cmdline */
@@ -402,6 +439,7 @@ void __init setup_arch(char **cmdline_p)
        nodes_clear(node_online_map);
 
        /* Setup bootmem with available RAM */
+       lmb_init();
        setup_memory();
        sparse_init();
 
@@ -448,7 +486,7 @@ static const char *cpu_name[] = {
        [CPU_SH7763]    = "SH7763",     [CPU_SH7770]    = "SH7770",
        [CPU_SH7780]    = "SH7780",     [CPU_SH7781]    = "SH7781",
        [CPU_SH7343]    = "SH7343",     [CPU_SH7785]    = "SH7785",
-       [CPU_SH7786]    = "SH7786",
+       [CPU_SH7786]    = "SH7786",     [CPU_SH7757]    = "SH7757",
        [CPU_SH7722]    = "SH7722",     [CPU_SHX3]      = "SH-X3",
        [CPU_SH5_101]   = "SH5-101",    [CPU_SH5_103]   = "SH5-103",
        [CPU_MXG]       = "MX-G",       [CPU_SH7723]    = "SH7723",
index fcc5de3..8dbe26b 100644 (file)
@@ -101,20 +101,14 @@ EXPORT_SYMBOL(flush_cache_range);
 EXPORT_SYMBOL(flush_dcache_page);
 #endif
 
-#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \
-       (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB))
-EXPORT_SYMBOL(clear_user_page);
-#endif
-
-#ifdef CONFIG_FUNCTION_TRACER
-EXPORT_SYMBOL(mcount);
+#ifdef CONFIG_MCOUNT
+DECLARE_EXPORT(mcount);
 #endif
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_generic);
 #ifdef CONFIG_IPV6
 EXPORT_SYMBOL(csum_ipv6_magic);
 #endif
-EXPORT_SYMBOL(clear_page);
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(_ebss);
index f5bd156..d008e17 100644 (file)
@@ -30,14 +30,6 @@ extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(kernel_thread);
 
-#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU)
-EXPORT_SYMBOL(clear_user_page);
-#endif
-
-#ifndef CONFIG_CACHE_OFF
-EXPORT_SYMBOL(flush_dcache_page);
-#endif
-
 #ifdef CONFIG_VT
 EXPORT_SYMBOL(screen_info);
 #endif
@@ -52,7 +44,6 @@ EXPORT_SYMBOL(__get_user_asm_l);
 EXPORT_SYMBOL(__get_user_asm_q);
 EXPORT_SYMBOL(__strnlen_user);
 EXPORT_SYMBOL(__strncpy_from_user);
-EXPORT_SYMBOL(clear_page);
 EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(__copy_user);
index b5afbec..6010750 100644 (file)
@@ -40,6 +40,16 @@ struct fdpic_func_descriptor {
        unsigned long   GOT;
 };
 
+/*
+ * The following define adds a 64 byte gap between the signal
+ * stack frame and previous contents of the stack.  This allows
+ * frame unwinding in a function epilogue but only if a frame
+ * pointer is used in the function.  This is necessary because
+ * current gcc compilers (<4.3) do not generate unwind info on
+ * SH for function epilogues.
+ */
+#define UNWINDGUARD 64
+
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -327,7 +337,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
                        sp = current->sas_ss_sp + current->sas_ss_size;
        }
 
-       return (void __user *)((sp - frame_size) & -8ul);
+       return (void __user *)((sp - (frame_size+UNWINDGUARD)) & -8ul);
 }
 
 /* These symbols are defined with the addresses in the vsyscall page.
index 0663a0e..026fd1c 100644 (file)
@@ -561,13 +561,11 @@ static int setup_frame(int sig, struct k_sigaction *ka,
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
        if (ka->sa.sa_flags & SA_RESTORER) {
-               DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1;
-
                /*
                 * On SH5 all edited pointers are subject to NEFF
                 */
-               DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
-                       (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
+               DEREF_REG_PR = neff_sign_extend((unsigned long)
+                       ka->sa.sa_restorer | 0x1);
        } else {
                /*
                 * Different approach on SH5.
@@ -580,9 +578,8 @@ static int setup_frame(int sig, struct k_sigaction *ka,
                 * . being code, linker turns ShMedia bit on, always
                 *   dereference index -1.
                 */
-               DEREF_REG_PR = (unsigned long) frame->retcode | 0x01;
-               DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
-                       (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
+               DEREF_REG_PR = neff_sign_extend((unsigned long)
+                       frame->retcode | 0x01);
 
                if (__copy_to_user(frame->retcode,
                        (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
@@ -596,9 +593,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
         * Set up registers for signal handler.
         * All edited pointers are subject to NEFF.
         */
-       regs->regs[REG_SP] = (unsigned long) frame;
-       regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ?
-                (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
+       regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
        regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
 
         /* FIXME:
@@ -613,8 +608,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
        regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
        regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
 
-       regs->pc = (unsigned long) ka->sa.sa_handler;
-       regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc;
+       regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
 
        set_fs(USER_DS);
 
@@ -676,13 +670,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
        if (ka->sa.sa_flags & SA_RESTORER) {
-               DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1;
-
                /*
                 * On SH5 all edited pointers are subject to NEFF
                 */
-               DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
-                       (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
+               DEREF_REG_PR = neff_sign_extend((unsigned long)
+                       ka->sa.sa_restorer | 0x1);
        } else {
                /*
                 * Different approach on SH5.
@@ -695,15 +687,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                 * . being code, linker turns ShMedia bit on, always
                 *   dereference index -1.
                 */
-
-               DEREF_REG_PR = (unsigned long) frame->retcode | 0x01;
-               DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
-                       (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
+               DEREF_REG_PR = neff_sign_extend((unsigned long)
+                       frame->retcode | 0x01);
 
                if (__copy_to_user(frame->retcode,
                        (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
                        goto give_sigsegv;
 
+               /* Cohere the trampoline with the I-cache. */
                flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
        }
 
@@ -711,14 +702,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
         * Set up registers for signal handler.
         * All edited pointers are subject to NEFF.
         */
-       regs->regs[REG_SP] = (unsigned long) frame;
-       regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ?
-                (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
+       regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
        regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
        regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
        regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
-       regs->pc = (unsigned long) ka->sa.sa_handler;
-       regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc;
+       regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
 
        set_fs(USER_DS);
 
index 1a2a5eb..c2e45c4 100644 (file)
 #include <linux/stacktrace.h>
 #include <linux/thread_info.h>
 #include <linux/module.h>
+#include <asm/unwinder.h>
 #include <asm/ptrace.h>
+#include <asm/stacktrace.h>
+
+static void save_stack_warning(void *data, char *msg)
+{
+}
+
+static void
+save_stack_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+}
+
+static int save_stack_stack(void *data, char *name)
+{
+       return 0;
+}
 
 /*
  * Save stack-backtrace addresses into a stack_trace buffer.
  */
+static void save_stack_address(void *data, unsigned long addr, int reliable)
+{
+       struct stack_trace *trace = data;
+
+       if (!reliable)
+               return;
+
+       if (trace->skip > 0) {
+               trace->skip--;
+               return;
+       }
+
+       if (trace->nr_entries < trace->max_entries)
+               trace->entries[trace->nr_entries++] = addr;
+}
+
+static const struct stacktrace_ops save_stack_ops = {
+       .warning = save_stack_warning,
+       .warning_symbol = save_stack_warning_symbol,
+       .stack = save_stack_stack,
+       .address = save_stack_address,
+};
+
 void save_stack_trace(struct stack_trace *trace)
 {
        unsigned long *sp = (unsigned long *)current_stack_pointer;
 
-       while (!kstack_end(sp)) {
-               unsigned long addr = *sp++;
-
-               if (__kernel_text_address(addr)) {
-                       if (trace->skip > 0)
-                               trace->skip--;
-                       else
-                               trace->entries[trace->nr_entries++] = addr;
-                       if (trace->nr_entries >= trace->max_entries)
-                               break;
-               }
-       }
+       unwind_stack(current, NULL, sp,  &save_stack_ops, trace);
+       if (trace->nr_entries < trace->max_entries)
+               trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
 EXPORT_SYMBOL_GPL(save_stack_trace);
 
+static void
+save_stack_address_nosched(void *data, unsigned long addr, int reliable)
+{
+       struct stack_trace *trace = (struct stack_trace *)data;
+
+       if (!reliable)
+               return;
+
+       if (in_sched_functions(addr))
+               return;
+
+       if (trace->skip > 0) {
+               trace->skip--;
+               return;
+       }
+
+       if (trace->nr_entries < trace->max_entries)
+               trace->entries[trace->nr_entries++] = addr;
+}
+
+static const struct stacktrace_ops save_stack_ops_nosched = {
+       .warning = save_stack_warning,
+       .warning_symbol = save_stack_warning_symbol,
+       .stack = save_stack_stack,
+       .address = save_stack_address_nosched,
+};
+
 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 {
        unsigned long *sp = (unsigned long *)tsk->thread.sp;
 
-       while (!kstack_end(sp)) {
-               unsigned long addr = *sp++;
-
-               if (__kernel_text_address(addr)) {
-                       if (in_sched_functions(addr))
-                               break;
-                       if (trace->skip > 0)
-                               trace->skip--;
-                       else
-                               trace->entries[trace->nr_entries++] = addr;
-                       if (trace->nr_entries >= trace->max_entries)
-                               break;
-               }
-       }
+       unwind_stack(current, NULL, sp,  &save_stack_ops_nosched, trace);
+       if (trace->nr_entries < trace->max_entries)
+               trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
index 90d00e4..8aa5d1c 100644 (file)
@@ -25,6 +25,8 @@
 #include <asm/syscalls.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
+#include <asm/cacheflush.h>
+#include <asm/cachectl.h>
 
 static inline long
 do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
@@ -179,6 +181,47 @@ asmlinkage int sys_ipc(uint call, int first, int second,
        return -EINVAL;
 }
 
+/* sys_cacheflush -- flush (part of) the processor cache.  */
+asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op)
+{
+       struct vm_area_struct *vma;
+
+       if ((op <= 0) || (op > (CACHEFLUSH_D_PURGE|CACHEFLUSH_I)))
+               return -EINVAL;
+
+       /*
+        * Verify that the specified address region actually belongs
+        * to this process.
+        */
+       if (addr + len < addr)
+               return -EFAULT;
+
+       down_read(&current->mm->mmap_sem);
+       vma = find_vma (current->mm, addr);
+       if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) {
+               up_read(&current->mm->mmap_sem);
+               return -EFAULT;
+       }
+
+       switch (op & CACHEFLUSH_D_PURGE) {
+               case CACHEFLUSH_D_INVAL:
+                       __flush_invalidate_region((void *)addr, len);
+                       break;
+               case CACHEFLUSH_D_WB:
+                       __flush_wback_region((void *)addr, len);
+                       break;
+               case CACHEFLUSH_D_PURGE:
+                       __flush_purge_region((void *)addr, len);
+                       break;
+       }
+
+       if (op & CACHEFLUSH_I)
+               flush_cache_all();
+
+       up_read(&current->mm->mmap_sem);
+       return 0;
+}
+
 asmlinkage int sys_uname(struct old_utsname __user *name)
 {
        int err;
index f9e21fa..16ba225 100644 (file)
@@ -139,7 +139,7 @@ ENTRY(sys_call_table)
        .long sys_clone         /* 120 */
        .long sys_setdomainname
        .long sys_newuname
-       .long sys_ni_syscall    /* sys_modify_ldt */
+       .long sys_cacheflush    /* x86: sys_modify_ldt */
        .long sys_adjtimex
        .long sys_mprotect              /* 125 */
        .long sys_sigprocmask
index bf420b6..af6fb74 100644 (file)
@@ -143,7 +143,7 @@ sys_call_table:
        .long sys_clone                 /* 120 */
        .long sys_setdomainname
        .long sys_newuname
-       .long sys_ni_syscall    /* sys_modify_ldt */
+       .long sys_cacheflush    /* x86: sys_modify_ldt */
        .long sys_adjtimex
        .long sys_mprotect              /* 125 */
        .long sys_sigprocmask
index 9b352a1..632aff5 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/smp.h>
 #include <linux/rtc.h>
 #include <asm/clock.h>
+#include <asm/hwblk.h>
 #include <asm/rtc.h>
 
 /* Dummy RTC ops */
@@ -91,21 +92,8 @@ module_init(rtc_generic_init);
 
 void (*board_time_init)(void);
 
-void __init time_init(void)
+static void __init sh_late_time_init(void)
 {
-       if (board_time_init)
-               board_time_init();
-
-       clk_init();
-
-       rtc_sh_get_time(&xtime);
-       set_normalized_timespec(&wall_to_monotonic,
-                               -xtime.tv_sec, -xtime.tv_nsec);
-
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-       local_timer_setup(smp_processor_id());
-#endif
-
        /*
         * Make sure all compiled-in early timers register themselves.
         *
@@ -118,3 +106,18 @@ void __init time_init(void)
        early_platform_driver_register_all("earlytimer");
        early_platform_driver_probe("earlytimer", 2, 0);
 }
+
+void __init time_init(void)
+{
+       if (board_time_init)
+               board_time_init();
+
+       hwblk_init();
+       clk_init();
+
+       rtc_sh_get_time(&xtime);
+       set_normalized_timespec(&wall_to_monotonic,
+                               -xtime.tv_sec, -xtime.tv_nsec);
+
+       late_time_init = sh_late_time_init;
+}
index b3e0067..a8396f3 100644 (file)
@@ -5,18 +5,33 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/uaccess.h>
+#include <linux/hardirq.h>
+#include <asm/unwinder.h>
 #include <asm/system.h>
 
 #ifdef CONFIG_BUG
-static void handle_BUG(struct pt_regs *regs)
+void handle_BUG(struct pt_regs *regs)
 {
+       const struct bug_entry *bug;
+       unsigned long bugaddr = regs->pc;
        enum bug_trap_type tt;
-       tt = report_bug(regs->pc, regs);
+
+       if (!is_valid_bugaddr(bugaddr))
+               goto invalid;
+
+       bug = find_bug(bugaddr);
+
+       /* Switch unwinders when unwind_stack() is called */
+       if (bug->flags & BUGFLAG_UNWINDER)
+               unwinder_faulted = 1;
+
+       tt = report_bug(bugaddr, regs);
        if (tt == BUG_TRAP_TYPE_WARN) {
-               regs->pc += instruction_size(regs->pc);
+               regs->pc += instruction_size(bugaddr);
                return;
        }
 
+invalid:
        die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
 }
 
@@ -28,8 +43,10 @@ int is_valid_bugaddr(unsigned long addr)
                return 0;
        if (probe_kernel_address((insn_size_t *)addr, opcode))
                return 0;
+       if (opcode == TRAPA_BUG_OPCODE)
+               return 1;
 
-       return opcode == TRAPA_BUG_OPCODE;
+       return 0;
 }
 #endif
 
@@ -75,3 +92,23 @@ BUILD_TRAP_HANDLER(bug)
 
        force_sig(SIGTRAP, current);
 }
+
+BUILD_TRAP_HANDLER(nmi)
+{
+       TRAP_HANDLER_DECL;
+
+       nmi_enter();
+
+       switch (notify_die(DIE_NMI, "NMI", regs, 0, vec & 0xff, SIGINT)) {
+       case NOTIFY_OK:
+       case NOTIFY_STOP:
+               break;
+       case NOTIFY_BAD:
+               die("Fatal Non-Maskable Interrupt", regs, SIGINT);
+       default:
+               printk(KERN_ALERT "Got NMI, but nobody cared. Ignoring...\n");
+               break;
+       }
+
+       nmi_exit();
+}
index 2b77277..583ace5 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/kdebug.h>
 #include <linux/kexec.h>
 #include <linux/limits.h>
+#include <linux/proc_fs.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/fpu.h>
 #define TRAP_ILLEGAL_SLOT_INST 13
 #endif
 
+static unsigned long se_user;
+static unsigned long se_sys;
+static unsigned long se_skipped;
+static unsigned long se_half;
+static unsigned long se_word;
+static unsigned long se_dword;
+static unsigned long se_multi;
+/* bitfield: 1: warn 2: fixup 4: signal -> combinations 2|4 && 1|2|4 are not
+   valid! */
+static int se_usermode = 3;
+/* 0: no warning 1: print a warning message */
+static int se_kernmode_warn = 1;
+
+#ifdef CONFIG_PROC_FS
+static const char *se_usermode_action[] = {
+       "ignored",
+       "warn",
+       "fixup",
+       "fixup+warn",
+       "signal",
+       "signal+warn"
+};
+
+static int
+proc_alignment_read(char *page, char **start, off_t off, int count, int *eof,
+                   void *data)
+{
+       char *p = page;
+       int len;
+
+       p += sprintf(p, "User:\t\t%lu\n", se_user);
+       p += sprintf(p, "System:\t\t%lu\n", se_sys);
+       p += sprintf(p, "Skipped:\t%lu\n", se_skipped);
+       p += sprintf(p, "Half:\t\t%lu\n", se_half);
+       p += sprintf(p, "Word:\t\t%lu\n", se_word);
+       p += sprintf(p, "DWord:\t\t%lu\n", se_dword);
+       p += sprintf(p, "Multi:\t\t%lu\n", se_multi);
+       p += sprintf(p, "User faults:\t%i (%s)\n", se_usermode,
+                       se_usermode_action[se_usermode]);
+       p += sprintf(p, "Kernel faults:\t%i (fixup%s)\n", se_kernmode_warn,
+                       se_kernmode_warn ? "+warn" : "");
+
+       len = (p - page) - off;
+       if (len < 0)
+               len = 0;
+
+       *eof = (len <= count) ? 1 : 0;
+       *start = page + off;
+
+       return len;
+}
+
+static int proc_alignment_write(struct file *file, const char __user *buffer,
+                               unsigned long count, void *data)
+{
+       char mode;
+
+       if (count > 0) {
+               if (get_user(mode, buffer))
+                       return -EFAULT;
+               if (mode >= '0' && mode <= '5')
+                       se_usermode = mode - '0';
+       }
+       return count;
+}
+
+static int proc_alignment_kern_write(struct file *file, const char __user *buffer,
+                                    unsigned long count, void *data)
+{
+       char mode;
+
+       if (count > 0) {
+               if (get_user(mode, buffer))
+                       return -EFAULT;
+               if (mode >= '0' && mode <= '1')
+                       se_kernmode_warn = mode - '0';
+       }
+       return count;
+}
+#endif
+
 static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
 {
        unsigned long p;
@@ -136,6 +218,7 @@ static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
                        regs->pc = fixup->fixup;
                        return;
                }
+
                die(str, regs, err);
        }
 }
@@ -193,6 +276,13 @@ static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs,
 
        count = 1<<(instruction&3);
 
+       switch (count) {
+       case 1: se_half  += 1; break;
+       case 2: se_word  += 1; break;
+       case 4: se_dword += 1; break;
+       case 8: se_multi += 1; break; /* ??? */
+       }
+
        ret = -EFAULT;
        switch (instruction>>12) {
        case 0: /* mov.[bwl] to/from memory via r0+rn */
@@ -358,15 +448,8 @@ static inline int handle_delayslot(struct pt_regs *regs,
 #define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4)
 #define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4)
 
-/*
- * XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit
- * opcodes..
- */
-
-static int handle_unaligned_notify_count = 10;
-
 int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
-                           struct mem_access *ma)
+                           struct mem_access *ma, int expected)
 {
        u_int rm;
        int ret, index;
@@ -374,15 +457,13 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
        index = (instruction>>8)&15;    /* 0x0F00 */
        rm = regs->regs[index];
 
-       /* shout about the first ten userspace fixups */
-       if (user_mode(regs) && handle_unaligned_notify_count>0) {
-               handle_unaligned_notify_count--;
-
-               printk(KERN_NOTICE "Fixing up unaligned userspace access "
+       /* shout about fixups */
+       if (!expected && printk_ratelimit())
+               printk(KERN_NOTICE "Fixing up unaligned %s access "
                       "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
+                      user_mode(regs) ? "userspace" : "kernel",
                       current->comm, task_pid_nr(current),
                       (void *)regs->pc, instruction);
-       }
 
        ret = -EFAULT;
        switch (instruction&0xF000) {
@@ -538,6 +619,36 @@ asmlinkage void do_address_error(struct pt_regs *regs,
 
                local_irq_enable();
 
+               se_user += 1;
+
+#ifndef CONFIG_CPU_SH2A
+               set_fs(USER_DS);
+               if (copy_from_user(&instruction, (u16 *)(regs->pc & ~1), 2)) {
+                       set_fs(oldfs);
+                       goto uspace_segv;
+               }
+               set_fs(oldfs);
+
+               /* shout about userspace fixups */
+               if (se_usermode & 1)
+                       printk(KERN_NOTICE "Unaligned userspace access "
+                              "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
+                              current->comm, current->pid, (void *)regs->pc,
+                              instruction);
+#endif
+
+               if (se_usermode & 2)
+                       goto fixup;
+
+               if (se_usermode & 4)
+                       goto uspace_segv;
+               else {
+                       /* ignore */
+                       regs->pc += instruction_size(instruction);
+                       return;
+               }
+
+fixup:
                /* bad PC is not something we can fix */
                if (regs->pc & 1) {
                        si_code = BUS_ADRALN;
@@ -545,17 +656,8 @@ asmlinkage void do_address_error(struct pt_regs *regs,
                }
 
                set_fs(USER_DS);
-               if (copy_from_user(&instruction, (void __user *)(regs->pc),
-                                  sizeof(instruction))) {
-                       /* Argh. Fault on the instruction itself.
-                          This should never happen non-SMP
-                       */
-                       set_fs(oldfs);
-                       goto uspace_segv;
-               }
-
                tmp = handle_unaligned_access(instruction, regs,
-                                             &user_mem_access);
+                                             &user_mem_access, 0);
                set_fs(oldfs);
 
                if (tmp==0)
@@ -571,6 +673,14 @@ uspace_segv:
                info.si_addr = (void __user *)address;
                force_sig_info(SIGBUS, &info, current);
        } else {
+               se_sys += 1;
+
+               if (se_kernmode_warn)
+                       printk(KERN_NOTICE "Unaligned kernel access "
+                              "on behalf of \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
+                              current->comm, current->pid, (void *)regs->pc,
+                              instruction);
+
                if (regs->pc & 1)
                        die("unaligned program counter", regs, error_code);
 
@@ -584,7 +694,8 @@ uspace_segv:
                        die("insn faulting in do_address_error", regs, 0);
                }
 
-               handle_unaligned_access(instruction, regs, &user_mem_access);
+               handle_unaligned_access(instruction, regs,
+                                       &user_mem_access, 0);
                set_fs(oldfs);
        }
 }
@@ -858,30 +969,6 @@ void __init trap_init(void)
        per_cpu_trap_init();
 }
 
-void show_trace(struct task_struct *tsk, unsigned long *sp,
-               struct pt_regs *regs)
-{
-       unsigned long addr;
-
-       if (regs && user_mode(regs))
-               return;
-
-       printk("\nCall trace:\n");
-
-       while (!kstack_end(sp)) {
-               addr = *sp++;
-               if (kernel_text_address(addr))
-                       print_ip_sym(addr);
-       }
-
-       printk("\n");
-
-       if (!tsk)
-               tsk = current;
-
-       debug_show_held_locks(tsk);
-}
-
 void show_stack(struct task_struct *tsk, unsigned long *sp)
 {
        unsigned long stack;
@@ -904,3 +991,38 @@ void dump_stack(void)
        show_stack(NULL, NULL);
 }
 EXPORT_SYMBOL(dump_stack);
+
+#ifdef CONFIG_PROC_FS
+/*
+ * This needs to be done after sysctl_init, otherwise sys/ will be
+ * overwritten.  Actually, this shouldn't be in sys/ at all since
+ * it isn't a sysctl, and it doesn't contain sysctl information.
+ * We now locate it in /proc/cpu/alignment instead.
+ */
+static int __init alignment_init(void)
+{
+       struct proc_dir_entry *dir, *res;
+
+       dir = proc_mkdir("cpu", NULL);
+       if (!dir)
+               return -ENOMEM;
+
+       res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, dir);
+       if (!res)
+               return -ENOMEM;
+
+       res->read_proc = proc_alignment_read;
+       res->write_proc = proc_alignment_write;
+
+        res = create_proc_entry("kernel_alignment", S_IWUSR | S_IRUGO, dir);
+        if (!res)
+                return -ENOMEM;
+
+        res->read_proc = proc_alignment_read;
+        res->write_proc = proc_alignment_kern_write;
+
+       return 0;
+}
+
+fs_initcall(alignment_init);
+#endif
diff --git a/arch/sh/kernel/unwinder.c b/arch/sh/kernel/unwinder.c
new file mode 100644 (file)
index 0000000..468889d
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2009  Matt Fleming
+ *
+ * Based, in part, on kernel/time/clocksource.c.
+ *
+ * This file provides arbitration code for stack unwinders.
+ *
+ * Multiple stack unwinders can be available on a system, usually with
+ * the most accurate unwinder being the currently active one.
+ */
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <asm/unwinder.h>
+#include <asm/atomic.h>
+
+/*
+ * This is the most basic stack unwinder an architecture can
+ * provide. For architectures without reliable frame pointers, e.g.
+ * RISC CPUs, it can be implemented by looking through the stack for
+ * addresses that lie within the kernel text section.
+ *
+ * Other CPUs, e.g. x86, can use their frame pointer register to
+ * construct more accurate stack traces.
+ */
+static struct list_head unwinder_list;
+static struct unwinder stack_reader = {
+       .name = "stack-reader",
+       .dump = stack_reader_dump,
+       .rating = 50,
+       .list = {
+               .next = &unwinder_list,
+               .prev = &unwinder_list,
+       },
+};
+
+/*
+ * "curr_unwinder" points to the stack unwinder currently in use. This
+ * is the unwinder with the highest rating.
+ *
+ * "unwinder_list" is a linked-list of all available unwinders, sorted
+ * by rating.
+ *
+ * All modifications of "curr_unwinder" and "unwinder_list" must be
+ * performed whilst holding "unwinder_lock".
+ */
+static struct unwinder *curr_unwinder = &stack_reader;
+
+static struct list_head unwinder_list = {
+       .next = &stack_reader.list,
+       .prev = &stack_reader.list,
+};
+
+static DEFINE_SPINLOCK(unwinder_lock);
+
+/**
+ * select_unwinder - Select the best registered stack unwinder.
+ *
+ * Private function. Must hold unwinder_lock when called.
+ *
+ * Select the stack unwinder with the best rating. This is useful for
+ * setting up curr_unwinder.
+ */
+static struct unwinder *select_unwinder(void)
+{
+       struct unwinder *best;
+
+       if (list_empty(&unwinder_list))
+               return NULL;
+
+       best = list_entry(unwinder_list.next, struct unwinder, list);
+       if (best == curr_unwinder)
+               return NULL;
+
+       return best;
+}
+
+/*
+ * Enqueue the stack unwinder sorted by rating.
+ */
+static int unwinder_enqueue(struct unwinder *ops)
+{
+       struct list_head *tmp, *entry = &unwinder_list;
+
+       list_for_each(tmp, &unwinder_list) {
+               struct unwinder *o;
+
+               o = list_entry(tmp, struct unwinder, list);
+               if (o == ops)
+                       return -EBUSY;
+               /* Keep track of the place, where to insert */
+               if (o->rating >= ops->rating)
+                       entry = tmp;
+       }
+       list_add(&ops->list, entry);
+
+       return 0;
+}
+
+/**
+ * unwinder_register - Used to install new stack unwinder
+ * @u: unwinder to be registered
+ *
+ * Install the new stack unwinder on the unwinder list, which is sorted
+ * by rating.
+ *
+ * Returns -EBUSY if registration fails, zero otherwise.
+ */
+int unwinder_register(struct unwinder *u)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&unwinder_lock, flags);
+       ret = unwinder_enqueue(u);
+       if (!ret)
+               curr_unwinder = select_unwinder();
+       spin_unlock_irqrestore(&unwinder_lock, flags);
+
+       return ret;
+}
+
+int unwinder_faulted = 0;
+
+/*
+ * Unwind the call stack and pass information to the stacktrace_ops
+ * functions. Also handle the case where we need to switch to a new
+ * stack dumper because the current one faulted unexpectedly.
+ */
+void unwind_stack(struct task_struct *task, struct pt_regs *regs,
+                 unsigned long *sp, const struct stacktrace_ops *ops,
+                 void *data)
+{
+       unsigned long flags;
+
+       /*
+        * The problem with unwinders with high ratings is that they are
+        * inherently more complicated than the simple ones with lower
+        * ratings. We are therefore more likely to fault in the
+        * complicated ones, e.g. hitting BUG()s. If we fault in the
+        * code for the current stack unwinder we try to downgrade to
+        * one with a lower rating.
+        *
+        * Hopefully this will give us a semi-reliable stacktrace so we
+        * can diagnose why curr_unwinder->dump() faulted.
+        */
+       if (unwinder_faulted) {
+               spin_lock_irqsave(&unwinder_lock, flags);
+
+               /* Make sure no one beat us to changing the unwinder */
+               if (unwinder_faulted && !list_is_singular(&unwinder_list)) {
+                       list_del(&curr_unwinder->list);
+                       curr_unwinder = select_unwinder();
+
+                       unwinder_faulted = 0;
+               }
+
+               spin_unlock_irqrestore(&unwinder_lock, flags);
+       }
+
+       curr_unwinder->dump(task, regs, sp, ops, data);
+}
+EXPORT_SYMBOL_GPL(unwind_stack);
index f53c76a..1b7d9d5 100644 (file)
@@ -12,7 +12,7 @@ OUTPUT_ARCH(sh)
 
 #include <asm/thread_info.h>
 #include <asm/cache.h>
-#include <asm-generic/vmlinux.lds.h>
+#include <asm/vmlinux.lds.h>
 
 ENTRY(_start)
 SECTIONS
@@ -50,12 +50,7 @@ SECTIONS
                _etext = .;             /* End of text section */
        } = 0x0009
 
-       . = ALIGN(16);          /* Exception table */
-       __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
-               __start___ex_table = .;
-               *(__ex_table)
-               __stop___ex_table = .;
-       }
+       EXCEPTION_TABLE(16)
 
        NOTES
        RO_DATA(PAGE_SIZE)
@@ -71,69 +66,16 @@ SECTIONS
                __uncached_end = .;
        }
 
-       . = ALIGN(THREAD_SIZE);
-       .data : AT(ADDR(.data) - LOAD_OFFSET) {         /* Data */
-               *(.data.init_task)
-
-               . = ALIGN(L1_CACHE_BYTES);
-               *(.data.cacheline_aligned)
-
-               . = ALIGN(L1_CACHE_BYTES);
-               *(.data.read_mostly)
-
-               . = ALIGN(PAGE_SIZE);
-               *(.data.page_aligned)
-
-               __nosave_begin = .;
-               *(.data.nosave)
-               . = ALIGN(PAGE_SIZE);
-               __nosave_end = .;
-
-               DATA_DATA
-               CONSTRUCTORS
-       }
+       RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
 
        _edata = .;                     /* End of data section */
 
-       . = ALIGN(PAGE_SIZE);           /* Init code and data */
-       .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
-               __init_begin = .;
-               _sinittext = .;
-               INIT_TEXT
-               _einittext = .;
-       }
-
-       .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { INIT_DATA }
-
-       . = ALIGN(16);
-       .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
-               __setup_start = .;
-               *(.init.setup)
-               __setup_end = .;
-       }
-
-       .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
-               __initcall_start = .;
-               INITCALLS
-               __initcall_end = .;
-       }
-
-       .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
-               __con_initcall_start = .;
-               *(.con_initcall.init)
-               __con_initcall_end = .;
-       }
-
-       SECURITY_INIT
+       DWARF_EH_FRAME
 
-#ifdef CONFIG_BLK_DEV_INITRD
-       . = ALIGN(PAGE_SIZE);
-       .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
-               __initramfs_start = .;
-               *(.init.ramfs)
-               __initramfs_end = .;
-       }
-#endif
+       . = ALIGN(PAGE_SIZE);           /* Init code and data */
+       __init_begin = .;
+       INIT_TEXT_SECTION(PAGE_SIZE)
+       INIT_DATA_SECTION(16)
 
        . = ALIGN(4);
        .machvec.init : AT(ADDR(.machvec.init) - LOAD_OFFSET) {
@@ -152,16 +94,10 @@ SECTIONS
        .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { EXIT_DATA }
 
        . = ALIGN(PAGE_SIZE);
-       .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
-               __init_end = .;
-               __bss_start = .;                /* BSS */
-               *(.bss.page_aligned)
-               *(.bss)
-               *(COMMON)
-               . = ALIGN(4);
-               _ebss = .;                      /* uClinux MTD sucks */
-               _end = . ;
-       }
+       __init_end = .;
+       BSS_SECTION(0, PAGE_SIZE, 4)
+       _ebss = .;                      /* uClinux MTD sucks */
+       _end = . ;
 
        /*
         * When something in the kernel is NOT compiled as a module, the
@@ -170,7 +106,7 @@ SECTIONS
         * it's a module.
         */
        /DISCARD/ : {
-               *(.exitcall.exit)
+               EXIT_CALL
        }
 
        STABS_DEBUG
index aaea580..a969b47 100644 (file)
@@ -23,8 +23,8 @@ obj-y                         += io.o
 memcpy-y                       := memcpy.o
 memcpy-$(CONFIG_CPU_SH4)       := memcpy-sh4.o
 
-lib-$(CONFIG_MMU)              += copy_page.o clear_page.o
-lib-$(CONFIG_FUNCTION_TRACER)  += mcount.o
+lib-$(CONFIG_MMU)              += copy_page.o __clear_user.o
+lib-$(CONFIG_MCOUNT)           += mcount.o
 lib-y                          += $(memcpy-y) $(udivsi3-y)
 
 EXTRA_CFLAGS += -Werror
similarity index 75%
rename from arch/sh/lib/clear_page.S
rename to arch/sh/lib/__clear_user.S
index 8342bfb..db1dca7 100644 (file)
@@ -8,56 +8,10 @@
 #include <linux/linkage.h>
 #include <asm/page.h>
 
-/*
- * clear_page
- * @to: P1 address
- *
- * void clear_page(void *to)
- */
-
-/*
- * r0 --- scratch
- * r4 --- to
- * r5 --- to + PAGE_SIZE
- */
-ENTRY(clear_page)
-       mov     r4,r5
-       mov.l   .Llimit,r0
-       add     r0,r5
-       mov     #0,r0
-       !
-1:
-#if defined(CONFIG_CPU_SH4)
-       movca.l r0,@r4
-       mov     r4,r1
-#else
-       mov.l   r0,@r4
-#endif
-       add     #32,r4
-       mov.l   r0,@-r4
-       mov.l   r0,@-r4
-       mov.l   r0,@-r4
-       mov.l   r0,@-r4
-       mov.l   r0,@-r4
-       mov.l   r0,@-r4
-       mov.l   r0,@-r4
-#if defined(CONFIG_CPU_SH4)
-       ocbwb   @r1
-#endif
-       cmp/eq  r5,r4
-       bf/s    1b
-        add    #28,r4
-       !
-       rts
-        nop
-
-       .balign 4
-.Llimit:       .long   (PAGE_SIZE-28)
-
 ENTRY(__clear_user)
        !
        mov     #0, r0
-       mov     #0xe0, r1       ! 0xffffffe0
+       mov     #0xffffffe0, r1
        !
        ! r4..(r4+31)&~32          -------- not aligned [ Area 0 ]
        ! (r4+31)&~32..(r4+r5)&~32 -------- aligned     [ Area 1 ]
index 43de7e8..9d7b8bc 100644 (file)
@@ -30,7 +30,9 @@ ENTRY(copy_page)
        mov     r4,r10
        mov     r5,r11
        mov     r5,r8
-       mov.l   .Lpsz,r0
+       mov     #(PAGE_SIZE >> 10), r0
+       shll8   r0
+       shll2   r0
        add     r0,r8
        !
 1:     mov.l   @r11+,r0
@@ -43,7 +45,6 @@ ENTRY(copy_page)
        mov.l   @r11+,r7
 #if defined(CONFIG_CPU_SH4)
        movca.l r0,@r10
-       mov     r10,r0
 #else
        mov.l   r0,@r10
 #endif
@@ -55,9 +56,6 @@ ENTRY(copy_page)
        mov.l   r3,@-r10
        mov.l   r2,@-r10
        mov.l   r1,@-r10
-#if defined(CONFIG_CPU_SH4)
-       ocbwb   @r0
-#endif
        cmp/eq  r11,r8
        bf/s    1b
         add    #28,r10
@@ -68,9 +66,6 @@ ENTRY(copy_page)
        rts
         nop
 
-       .balign 4
-.Lpsz: .long   PAGE_SIZE
-
 /*
  * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
  * Return the number of bytes NOT copied
index f3ddd21..faa8f86 100644 (file)
@@ -21,13 +21,14 @@ void __delay(unsigned long loops)
 
 inline void __const_udelay(unsigned long xloops)
 {
+       xloops *= 4;
        __asm__("dmulu.l        %0, %2\n\t"
                "sts    mach, %0"
                : "=r" (xloops)
                : "0" (xloops),
-                 "r" (HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy)
+                 "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4))
                : "macl", "mach");
-       __delay(xloops);
+       __delay(++xloops);
 }
 
 void __udelay(unsigned long usecs)
index 110fbfe..84a5776 100644 (file)
@@ -1,14 +1,16 @@
 /*
  * arch/sh/lib/mcount.S
  *
- *  Copyright (C) 2008  Paul Mundt
- *  Copyright (C) 2008  Matt Fleming
+ *  Copyright (C) 2008, 2009  Paul Mundt
+ *  Copyright (C) 2008, 2009  Matt Fleming
  *
  * 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.
  */
 #include <asm/ftrace.h>
+#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
 
 #define MCOUNT_ENTER()         \
        mov.l   r4, @-r15;      \
        rts;                    \
         mov.l  @r15+, r4
 
+#ifdef CONFIG_STACK_DEBUG
+/*
+ * Perform diagnostic checks on the state of the kernel stack.
+ *
+ * Check for stack overflow. If there is less than 1KB free
+ * then it has overflowed.
+ *
+ * Make sure the stack pointer contains a valid address. Valid
+ * addresses for kernel stacks are anywhere after the bss
+ * (after _ebss) and anywhere in init_thread_union (init_stack).
+ */
+#define STACK_CHECK()                                  \
+       mov     #(THREAD_SIZE >> 10), r0;               \
+       shll8   r0;                                     \
+       shll2   r0;                                     \
+                                                       \
+       /* r1 = sp & (THREAD_SIZE - 1) */               \
+       mov     #-1, r1;                                \
+       add     r0, r1;                                 \
+       and     r15, r1;                                \
+                                                       \
+       mov     #TI_SIZE, r3;                           \
+       mov     #(STACK_WARN >> 8), r2;                 \
+       shll8   r2;                                     \
+       add     r3, r2;                                 \
+                                                       \
+       /* Is the stack overflowing? */                 \
+       cmp/hi  r2, r1;                                 \
+       bf      stack_panic;                            \
+                                                       \
+       /* If sp > _ebss then we're OK. */              \
+       mov.l   .L_ebss, r1;                            \
+       cmp/hi  r1, r15;                                \
+       bt      1f;                                     \
+                                                       \
+       /* If sp < init_stack, we're not OK. */         \
+       mov.l   .L_init_thread_union, r1;               \
+       cmp/hs  r1, r15;                                \
+       bf      stack_panic;                            \
+                                                       \
+       /* If sp > init_stack && sp < _ebss, not OK. */ \
+       add     r0, r1;                                 \
+       cmp/hs  r1, r15;                                \
+       bt      stack_panic;                            \
+1:
+#else
+#define STACK_CHECK()
+#endif /* CONFIG_STACK_DEBUG */
+
        .align 2
        .globl  _mcount
        .type   _mcount,@function
        .type   mcount,@function
 _mcount:
 mcount:
+       STACK_CHECK()
+
+#ifndef CONFIG_FUNCTION_TRACER
+       rts
+        nop
+#else
+#ifndef CONFIG_DYNAMIC_FTRACE
+       mov.l   .Lfunction_trace_stop, r0
+       mov.l   @r0, r0
+       tst     r0, r0
+       bf      ftrace_stub
+#endif
+
        MCOUNT_ENTER()
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -52,16 +116,69 @@ mcount_call:
        jsr     @r6
         nop
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       mov.l   .Lftrace_graph_return, r6
+       mov.l   .Lftrace_stub, r7
+       cmp/eq  r6, r7
+       bt      1f
+
+       mov.l   .Lftrace_graph_caller, r0
+       jmp     @r0
+        nop
+
+1:
+       mov.l   .Lftrace_graph_entry, r6
+       mov.l   .Lftrace_graph_entry_stub, r7
+       cmp/eq  r6, r7
+       bt      skip_trace
+
+       mov.l   .Lftrace_graph_caller, r0
+       jmp     @r0
+        nop
+
+       .align 2
+.Lftrace_graph_return:
+       .long   ftrace_graph_return
+.Lftrace_graph_entry:
+       .long   ftrace_graph_entry
+.Lftrace_graph_entry_stub:
+       .long   ftrace_graph_entry_stub
+.Lftrace_graph_caller:
+       .long   ftrace_graph_caller
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+       .globl skip_trace
 skip_trace:
        MCOUNT_LEAVE()
 
        .align 2
 .Lftrace_trace_function:
-       .long   ftrace_trace_function
+       .long   ftrace_trace_function
 
 #ifdef CONFIG_DYNAMIC_FTRACE
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * NOTE: Do not move either ftrace_graph_call or ftrace_caller
+ * as this will affect the calculation of GRAPH_INSN_OFFSET.
+ */
+       .globl ftrace_graph_call
+ftrace_graph_call:
+       mov.l   .Lskip_trace, r0
+       jmp     @r0
+        nop
+
+       .align 2
+.Lskip_trace:
+       .long   skip_trace
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
        .globl ftrace_caller
 ftrace_caller:
+       mov.l   .Lfunction_trace_stop, r0
+       mov.l   @r0, r0
+       tst     r0, r0
+       bf      ftrace_stub
+
        MCOUNT_ENTER()
 
        .globl ftrace_call
@@ -70,9 +187,18 @@ ftrace_call:
        jsr     @r6
         nop
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       bra     ftrace_graph_call
+        nop
+#else
        MCOUNT_LEAVE()
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
+       .align 2
+.Lfunction_trace_stop:
+       .long   function_trace_stop
+
 /*
  * NOTE: From here on the locations of the .Lftrace_stub label and
  * ftrace_stub itself are fixed. Adding additional data here will skew
@@ -80,7 +206,6 @@ ftrace_call:
  * Place new labels either after the ftrace_stub body, or before
  * ftrace_caller. You have been warned.
  */
-       .align 2
 .Lftrace_stub:
        .long   ftrace_stub
 
@@ -88,3 +213,98 @@ ftrace_call:
 ftrace_stub:
        rts
         nop
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       .globl  ftrace_graph_caller
+ftrace_graph_caller:
+       mov.l   2f, r0
+       mov.l   @r0, r0
+       tst     r0, r0
+       bt      1f
+
+       mov.l   3f, r1
+       jmp     @r1
+        nop
+1:
+       /*
+        * MCOUNT_ENTER() pushed 5 registers onto the stack, so
+        * the stack address containing our return address is
+        * r15 + 20.
+        */
+       mov     #20, r0
+       add     r15, r0
+       mov     r0, r4
+
+       mov.l   .Lprepare_ftrace_return, r0
+       jsr     @r0
+        nop
+
+       MCOUNT_LEAVE()
+
+       .align 2
+2:     .long   function_trace_stop
+3:     .long   skip_trace
+.Lprepare_ftrace_return:
+       .long   prepare_ftrace_return
+
+       .globl  return_to_handler
+return_to_handler:
+       /*
+        * Save the return values.
+        */
+       mov.l   r0, @-r15
+       mov.l   r1, @-r15
+
+       mov     #0, r4
+
+       mov.l   .Lftrace_return_to_handler, r0
+       jsr     @r0
+        nop
+
+       /*
+        * The return value from ftrace_return_handler has the real
+        * address that we should return to.
+        */
+       lds     r0, pr
+       mov.l   @r15+, r1
+       rts
+        mov.l  @r15+, r0
+
+
+       .align 2
+.Lftrace_return_to_handler:
+       .long   ftrace_return_to_handler
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#endif /* CONFIG_FUNCTION_TRACER */
+
+#ifdef CONFIG_STACK_DEBUG
+       .globl  stack_panic
+stack_panic:
+       mov.l   .Ldump_stack, r0
+       jsr     @r0
+        nop
+
+       mov.l   .Lpanic, r0
+       jsr     @r0
+        mov.l  .Lpanic_s, r4
+
+       rts
+        nop
+
+       .align 2
+.L_ebss:
+       .long   _ebss
+.L_init_thread_union:
+       .long   init_thread_union
+.Lpanic:
+       .long   panic
+.Lpanic_s:
+       .long   .Lpanic_str
+.Ldump_stack:
+       .long   dump_stack
+
+       .section        .rodata
+       .align 2
+.Lpanic_str:
+       .string "Stack error"
+#endif /* CONFIG_STACK_DEBUG */
index 334bb2d..1fee75a 100644 (file)
@@ -11,7 +11,7 @@
 
 # Panic should really be compiled as PIC
 lib-y  := udelay.o dbg.o panic.o memcpy.o memset.o \
-         copy_user_memcpy.o copy_page.o clear_page.o strcpy.o strlen.o
+         copy_user_memcpy.o copy_page.o strcpy.o strlen.o
 
 # Extracted from libgcc
 lib-y  += udivsi3.o udivdi3.o sdivsi3.o
diff --git a/arch/sh/lib64/clear_page.S b/arch/sh/lib64/clear_page.S
deleted file mode 100644 (file)
index 007ab48..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-   Copyright 2003 Richard Curnow, SuperH (UK) Ltd.
-
-   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.
-
-   Tight version of memset for the case of just clearing a page.  It turns out
-   that having the alloco's spaced out slightly due to the increment/branch
-   pair causes them to contend less for access to the cache.  Similarly,
-   keeping the stores apart from the allocos causes less contention.  => Do two
-   separate loops.  Do multiple stores per loop to amortise the
-   increment/branch cost a little.
-
-   Parameters:
-   r2 : source effective address (start of page)
-
-   Always clears 4096 bytes.
-
-   Note : alloco guarded by synco to avoid TAKum03020 erratum
-
-*/
-
-       .section .text..SHmedia32,"ax"
-       .little
-
-       .balign 8
-       .global clear_page
-clear_page:
-       pta/l 1f, tr1
-       pta/l 2f, tr2
-       ptabs/l r18, tr0
-
-       movi 4096, r7
-       add  r2, r7, r7
-       add  r2, r63, r6
-1:
-       alloco r6, 0
-       synco   ! TAKum03020
-       addi    r6, 32, r6
-       bgt/l   r7, r6, tr1
-
-       add  r2, r63, r6
-2:
-       st.q  r6,   0, r63
-       st.q  r6,   8, r63
-       st.q  r6,  16, r63
-       st.q  r6,  24, r63
-       addi r6, 32, r6
-       bgt/l r7, r6, tr2
-
-       blink tr0, r63
-
-
index 2795618..64dc1ad 100644 (file)
@@ -82,7 +82,7 @@ config 32BIT
 
 config PMB_ENABLE
        bool "Support 32-bit physical addressing through PMB"
-       depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785)
+       depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7757 || CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785)
        select 32BIT
        default y
        help
@@ -97,7 +97,7 @@ choice
 
 config PMB
        bool "PMB"
-       depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785)
+       depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7757 || CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785)
        select 32BIT
        help
          If you say Y here, physical addressing will be extended to
@@ -106,7 +106,8 @@ config PMB
 
 config PMB_FIXED
        bool "fixed PMB"
-       depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || \
+       depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7757 || \
+                                          CPU_SUBTYPE_SH7780 || \
                                           CPU_SUBTYPE_SH7785)
        select 32BIT
        help
index 9f4bc3d..3759bf8 100644 (file)
@@ -1,5 +1,65 @@
-ifeq ($(CONFIG_SUPERH32),y)
-include ${srctree}/arch/sh/mm/Makefile_32
-else
-include ${srctree}/arch/sh/mm/Makefile_64
+#
+# Makefile for the Linux SuperH-specific parts of the memory manager.
+#
+
+obj-y                  := cache.o init.o consistent.o mmap.o
+
+cacheops-$(CONFIG_CPU_SH2)             := cache-sh2.o
+cacheops-$(CONFIG_CPU_SH2A)            := cache-sh2a.o
+cacheops-$(CONFIG_CPU_SH3)             := cache-sh3.o
+cacheops-$(CONFIG_CPU_SH4)             := cache-sh4.o flush-sh4.o
+cacheops-$(CONFIG_CPU_SH5)             := cache-sh5.o flush-sh4.o
+cacheops-$(CONFIG_SH7705_CACHE_32KB)   += cache-sh7705.o
+
+obj-y                  += $(cacheops-y)
+
+mmu-y                  := nommu.o extable_32.o
+mmu-$(CONFIG_MMU)      := extable_$(BITS).o fault_$(BITS).o \
+                          ioremap_$(BITS).o kmap.o tlbflush_$(BITS).o
+
+obj-y                  += $(mmu-y)
+obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o
+
+ifdef CONFIG_DEBUG_FS
+obj-$(CONFIG_CPU_SH4)  += cache-debugfs.o
 endif
+
+ifdef CONFIG_MMU
+tlb-$(CONFIG_CPU_SH3)          := tlb-sh3.o
+tlb-$(CONFIG_CPU_SH4)          := tlb-sh4.o
+tlb-$(CONFIG_CPU_SH5)          := tlb-sh5.o
+tlb-$(CONFIG_CPU_HAS_PTEAEX)   := tlb-pteaex.o
+obj-y                          += $(tlb-y)
+endif
+
+obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
+obj-$(CONFIG_PMB)              += pmb.o
+obj-$(CONFIG_PMB_FIXED)                += pmb-fixed.o
+obj-$(CONFIG_NUMA)             += numa.o
+
+# 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
+# very few registers have been saved in the exception handler (for speed
+# reasons).
+# The caller save registers that have been saved and which can be used are
+# r2,r3,r4,r5 : argument passing
+# r15, r18 : SP and LINK
+# tr0-4 : allow all caller-save TR's.  The compiler seems to be able to make
+#         use of them, so it's probably beneficial to performance to save them
+#         and have them available for it.
+#
+# The resources not listed below are callee save, i.e. the compiler is free to
+# use any of them and will spill them to the stack itself.
+
+CFLAGS_fault_64.o += -ffixed-r7 \
+       -ffixed-r8 -ffixed-r9 -ffixed-r10 -ffixed-r11 -ffixed-r12 \
+       -ffixed-r13 -ffixed-r14 -ffixed-r16 -ffixed-r17 -ffixed-r19 \
+       -ffixed-r20 -ffixed-r21 -ffixed-r22 -ffixed-r23 \
+       -ffixed-r24 -ffixed-r25 -ffixed-r26 -ffixed-r27 \
+       -ffixed-r36 -ffixed-r37 -ffixed-r38 -ffixed-r39 -ffixed-r40 \
+       -ffixed-r41 -ffixed-r42 -ffixed-r43  \
+       -ffixed-r60 -ffixed-r61 -ffixed-r62 \
+       -fomit-frame-pointer
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32
deleted file mode 100644 (file)
index 986a1e0..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Makefile for the Linux SuperH-specific parts of the memory manager.
-#
-
-obj-y                  := init.o extable_32.o consistent.o mmap.o
-
-ifndef CONFIG_CACHE_OFF
-cache-$(CONFIG_CPU_SH2)                := cache-sh2.o
-cache-$(CONFIG_CPU_SH2A)       := cache-sh2a.o
-cache-$(CONFIG_CPU_SH3)                := cache-sh3.o
-cache-$(CONFIG_CPU_SH4)                := cache-sh4.o
-cache-$(CONFIG_SH7705_CACHE_32KB)      += cache-sh7705.o
-endif
-
-obj-y                  += $(cache-y)
-
-mmu-y                  := tlb-nommu.o pg-nommu.o
-mmu-$(CONFIG_MMU)      := fault_32.o tlbflush_32.o ioremap_32.o
-
-obj-y                  += $(mmu-y)
-obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o
-
-ifdef CONFIG_DEBUG_FS
-obj-$(CONFIG_CPU_SH4)  += cache-debugfs.o
-endif
-
-ifdef CONFIG_MMU
-tlb-$(CONFIG_CPU_SH3)          := tlb-sh3.o
-tlb-$(CONFIG_CPU_SH4)          := tlb-sh4.o
-tlb-$(CONFIG_CPU_HAS_PTEAEX)   := tlb-pteaex.o
-obj-y                          += $(tlb-y)
-ifndef CONFIG_CACHE_OFF
-obj-$(CONFIG_CPU_SH4)          += pg-sh4.o
-obj-$(CONFIG_SH7705_CACHE_32KB)        += pg-sh7705.o
-endif
-endif
-
-obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
-obj-$(CONFIG_PMB)              += pmb.o
-obj-$(CONFIG_PMB_FIXED)                += pmb-fixed.o
-obj-$(CONFIG_NUMA)             += numa.o
-
-EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/mm/Makefile_64 b/arch/sh/mm/Makefile_64
deleted file mode 100644 (file)
index 2863ffb..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# Makefile for the Linux SuperH-specific parts of the memory manager.
-#
-
-obj-y                  := init.o consistent.o mmap.o
-
-mmu-y                  := tlb-nommu.o pg-nommu.o extable_32.o
-mmu-$(CONFIG_MMU)      := fault_64.o ioremap_64.o tlbflush_64.o tlb-sh5.o \
-                          extable_64.o
-
-ifndef CONFIG_CACHE_OFF
-obj-y                  += cache-sh5.o
-endif
-
-obj-y                  += $(mmu-y)
-obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o
-
-obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
-obj-$(CONFIG_NUMA)             += numa.o
-
-EXTRA_CFLAGS += -Werror
-
-# 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
-# very few registers have been saved in the exception handler (for speed
-# reasons).
-# The caller save registers that have been saved and which can be used are
-# r2,r3,r4,r5 : argument passing
-# r15, r18 : SP and LINK
-# tr0-4 : allow all caller-save TR's.  The compiler seems to be able to make
-#         use of them, so it's probably beneficial to performance to save them
-#         and have them available for it.
-#
-# The resources not listed below are callee save, i.e. the compiler is free to
-# use any of them and will spill them to the stack itself.
-
-CFLAGS_fault_64.o += -ffixed-r7 \
-       -ffixed-r8 -ffixed-r9 -ffixed-r10 -ffixed-r11 -ffixed-r12 \
-       -ffixed-r13 -ffixed-r14 -ffixed-r16 -ffixed-r17 -ffixed-r19 \
-       -ffixed-r20 -ffixed-r21 -ffixed-r22 -ffixed-r23 \
-       -ffixed-r24 -ffixed-r25 -ffixed-r26 -ffixed-r27 \
-       -ffixed-r36 -ffixed-r37 -ffixed-r38 -ffixed-r39 -ffixed-r40 \
-       -ffixed-r41 -ffixed-r42 -ffixed-r43  \
-       -ffixed-r60 -ffixed-r61 -ffixed-r62 \
-       -fomit-frame-pointer
index c4e80d2..699a71f 100644 (file)
@@ -16,7 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/io.h>
 
-void __flush_wback_region(void *start, int size)
+static void sh2__flush_wback_region(void *start, int size)
 {
        unsigned long v;
        unsigned long begin, end;
@@ -37,7 +37,7 @@ void __flush_wback_region(void *start, int size)
        }
 }
 
-void __flush_purge_region(void *start, int size)
+static void sh2__flush_purge_region(void *start, int size)
 {
        unsigned long v;
        unsigned long begin, end;
@@ -51,7 +51,7 @@ void __flush_purge_region(void *start, int size)
                          CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);
 }
 
-void __flush_invalidate_region(void *start, int size)
+static void sh2__flush_invalidate_region(void *start, int size)
 {
 #ifdef CONFIG_CACHE_WRITEBACK
        /*
@@ -82,3 +82,10 @@ void __flush_invalidate_region(void *start, int size)
                          CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);
 #endif
 }
+
+void __init sh2_cache_init(void)
+{
+       __flush_wback_region            = sh2__flush_wback_region;
+       __flush_purge_region            = sh2__flush_purge_region;
+       __flush_invalidate_region       = sh2__flush_invalidate_region;
+}
index 24d86a7..975899d 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/cacheflush.h>
 #include <asm/io.h>
 
-void __flush_wback_region(void *start, int size)
+static void sh2a__flush_wback_region(void *start, int size)
 {
        unsigned long v;
        unsigned long begin, end;
@@ -44,7 +44,7 @@ void __flush_wback_region(void *start, int size)
        local_irq_restore(flags);
 }
 
-void __flush_purge_region(void *start, int size)
+static void sh2a__flush_purge_region(void *start, int size)
 {
        unsigned long v;
        unsigned long begin, end;
@@ -65,7 +65,7 @@ void __flush_purge_region(void *start, int size)
        local_irq_restore(flags);
 }
 
-void __flush_invalidate_region(void *start, int size)
+static void sh2a__flush_invalidate_region(void *start, int size)
 {
        unsigned long v;
        unsigned long begin, end;
@@ -97,13 +97,15 @@ void __flush_invalidate_region(void *start, int size)
 }
 
 /* WBack O-Cache and flush I-Cache */
-void flush_icache_range(unsigned long start, unsigned long end)
+static void sh2a_flush_icache_range(void *args)
 {
+       struct flusher_data *data = args;
+       unsigned long start, end;
        unsigned long v;
        unsigned long flags;
 
-       start = start & ~(L1_CACHE_BYTES-1);
-       end = (end + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1);
+       start = data->addr1 & ~(L1_CACHE_BYTES-1);
+       end = (data->addr2 + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1);
 
        local_irq_save(flags);
        jump_to_uncached();
@@ -127,3 +129,12 @@ void flush_icache_range(unsigned long start, unsigned long end)
        back_to_cached();
        local_irq_restore(flags);
 }
+
+void __init sh2a_cache_init(void)
+{
+       local_flush_icache_range        = sh2a_flush_icache_range;
+
+       __flush_wback_region            = sh2a__flush_wback_region;
+       __flush_purge_region            = sh2a__flush_purge_region;
+       __flush_invalidate_region       = sh2a__flush_invalidate_region;
+}
index 6d1dbec..faef80c 100644 (file)
@@ -32,7 +32,7 @@
  * SIZE: Size of the region.
  */
 
-void __flush_wback_region(void *start, int size)
+static void sh3__flush_wback_region(void *start, int size)
 {
        unsigned long v, j;
        unsigned long begin, end;
@@ -71,7 +71,7 @@ void __flush_wback_region(void *start, int size)
  * START: Virtual Address (U0, P1, or P3)
  * SIZE: Size of the region.
  */
-void __flush_purge_region(void *start, int size)
+static void sh3__flush_purge_region(void *start, int size)
 {
        unsigned long v;
        unsigned long begin, end;
@@ -90,11 +90,16 @@ void __flush_purge_region(void *start, int size)
        }
 }
 
-/*
- * No write back please
- *
- * Except I don't think there's any way to avoid the writeback. So we
- * just alias it to __flush_purge_region(). dwmw2.
- */
-void __flush_invalidate_region(void *start, int size)
-       __attribute__((alias("__flush_purge_region")));
+void __init sh3_cache_init(void)
+{
+       __flush_wback_region = sh3__flush_wback_region;
+       __flush_purge_region = sh3__flush_purge_region;
+
+       /*
+        * No write back please
+        *
+        * Except I don't think there's any way to avoid the writeback.
+        * So we just alias it to sh3__flush_purge_region(). dwmw2.
+        */
+       __flush_invalidate_region = sh3__flush_purge_region;
+}
index 5cfe08d..3ac4945 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mm.h>
 #include <linux/io.h>
 #include <linux/mutex.h>
+#include <linux/fs.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
 #define MAX_DCACHE_PAGES       64      /* XXX: Tune for ways */
 #define MAX_ICACHE_PAGES       32
 
-static void __flush_dcache_segment_1way(unsigned long start,
-                                       unsigned long extent);
-static void __flush_dcache_segment_2way(unsigned long start,
-                                       unsigned long extent);
-static void __flush_dcache_segment_4way(unsigned long start,
-                                       unsigned long extent);
-
 static void __flush_cache_4096(unsigned long addr, unsigned long phys,
                               unsigned long exec_offset);
 
@@ -43,155 +37,26 @@ static void __flush_cache_4096(unsigned long addr, unsigned long phys,
 static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) =
        (void (*)(unsigned long, unsigned long))0xdeadbeef;
 
-static void compute_alias(struct cache_info *c)
-{
-       c->alias_mask = ((c->sets - 1) << c->entry_shift) & ~(PAGE_SIZE - 1);
-       c->n_aliases = c->alias_mask ? (c->alias_mask >> PAGE_SHIFT) + 1 : 0;
-}
-
-static void __init emit_cache_params(void)
-{
-       printk("PVR=%08x CVR=%08x PRR=%08x\n",
-               ctrl_inl(CCN_PVR),
-               ctrl_inl(CCN_CVR),
-               ctrl_inl(CCN_PRR));
-       printk("I-cache : n_ways=%d n_sets=%d way_incr=%d\n",
-               boot_cpu_data.icache.ways,
-               boot_cpu_data.icache.sets,
-               boot_cpu_data.icache.way_incr);
-       printk("I-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
-               boot_cpu_data.icache.entry_mask,
-               boot_cpu_data.icache.alias_mask,
-               boot_cpu_data.icache.n_aliases);
-       printk("D-cache : n_ways=%d n_sets=%d way_incr=%d\n",
-               boot_cpu_data.dcache.ways,
-               boot_cpu_data.dcache.sets,
-               boot_cpu_data.dcache.way_incr);
-       printk("D-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
-               boot_cpu_data.dcache.entry_mask,
-               boot_cpu_data.dcache.alias_mask,
-               boot_cpu_data.dcache.n_aliases);
-
-       /*
-        * Emit Secondary Cache parameters if the CPU has a probed L2.
-        */
-       if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) {
-               printk("S-cache : n_ways=%d n_sets=%d way_incr=%d\n",
-                       boot_cpu_data.scache.ways,
-                       boot_cpu_data.scache.sets,
-                       boot_cpu_data.scache.way_incr);
-               printk("S-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
-                       boot_cpu_data.scache.entry_mask,
-                       boot_cpu_data.scache.alias_mask,
-                       boot_cpu_data.scache.n_aliases);
-       }
-
-       if (!__flush_dcache_segment_fn)
-               panic("unknown number of cache ways\n");
-}
-
-/*
- * SH-4 has virtually indexed and physically tagged cache.
- */
-void __init p3_cache_init(void)
-{
-       compute_alias(&boot_cpu_data.icache);
-       compute_alias(&boot_cpu_data.dcache);
-       compute_alias(&boot_cpu_data.scache);
-
-       switch (boot_cpu_data.dcache.ways) {
-       case 1:
-               __flush_dcache_segment_fn = __flush_dcache_segment_1way;
-               break;
-       case 2:
-               __flush_dcache_segment_fn = __flush_dcache_segment_2way;
-               break;
-       case 4:
-               __flush_dcache_segment_fn = __flush_dcache_segment_4way;
-               break;
-       default:
-               __flush_dcache_segment_fn = NULL;
-               break;
-       }
-
-       emit_cache_params();
-}
-
-/*
- * Write back the dirty D-caches, but not invalidate them.
- *
- * START: Virtual Address (U0, P1, or P3)
- * SIZE: Size of the region.
- */
-void __flush_wback_region(void *start, int size)
-{
-       unsigned long v;
-       unsigned long begin, end;
-
-       begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
-       end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
-               & ~(L1_CACHE_BYTES-1);
-       for (v = begin; v < end; v+=L1_CACHE_BYTES) {
-               asm volatile("ocbwb     %0"
-                            : /* no output */
-                            : "m" (__m(v)));
-       }
-}
-
-/*
- * Write back the dirty D-caches and invalidate them.
- *
- * START: Virtual Address (U0, P1, or P3)
- * SIZE: Size of the region.
- */
-void __flush_purge_region(void *start, int size)
-{
-       unsigned long v;
-       unsigned long begin, end;
-
-       begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
-       end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
-               & ~(L1_CACHE_BYTES-1);
-       for (v = begin; v < end; v+=L1_CACHE_BYTES) {
-               asm volatile("ocbp      %0"
-                            : /* no output */
-                            : "m" (__m(v)));
-       }
-}
-
-/*
- * No write back please
- */
-void __flush_invalidate_region(void *start, int size)
-{
-       unsigned long v;
-       unsigned long begin, end;
-
-       begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
-       end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
-               & ~(L1_CACHE_BYTES-1);
-       for (v = begin; v < end; v+=L1_CACHE_BYTES) {
-               asm volatile("ocbi      %0"
-                            : /* no output */
-                            : "m" (__m(v)));
-       }
-}
-
 /*
  * Write back the range of D-cache, and purge the I-cache.
  *
  * Called from kernel/module.c:sys_init_module and routine for a.out format,
  * signal handler code and kprobes code
  */
-void flush_icache_range(unsigned long start, unsigned long end)
+static void sh4_flush_icache_range(void *args)
 {
+       struct flusher_data *data = args;
        int icacheaddr;
+       unsigned long start, end;
        unsigned long flags, v;
        int i;
 
+       start = data->addr1;
+       end = data->addr2;
+
        /* If there are too many pages then just blow the caches */
         if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
-                flush_cache_all();
+                local_flush_cache_all(args);
        } else {
                /* selectively flush d-cache then invalidate the i-cache */
                /* this is inefficient, so only use for small ranges */
@@ -244,9 +109,17 @@ static inline void flush_cache_4096(unsigned long start,
  * Write back & invalidate the D-cache of the page.
  * (To avoid "alias" issues)
  */
-void flush_dcache_page(struct page *page)
+static void sh4_flush_dcache_page(void *arg)
 {
-       if (test_bit(PG_mapped, &page->flags)) {
+       struct page *page = arg;
+#ifndef CONFIG_SMP
+       struct address_space *mapping = page_mapping(page);
+
+       if (mapping && !mapping_mapped(mapping))
+               set_bit(PG_dcache_dirty, &page->flags);
+       else
+#endif
+       {
                unsigned long phys = PHYSADDR(page_address(page));
                unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
                int i, n;
@@ -282,13 +155,13 @@ static void __uses_jump_to_uncached flush_icache_all(void)
        local_irq_restore(flags);
 }
 
-void flush_dcache_all(void)
+static inline void flush_dcache_all(void)
 {
        (*__flush_dcache_segment_fn)(0UL, boot_cpu_data.dcache.way_size);
        wmb();
 }
 
-void flush_cache_all(void)
+static void sh4_flush_cache_all(void *unused)
 {
        flush_dcache_all();
        flush_icache_all();
@@ -380,8 +253,13 @@ loop_exit:
  *
  * Caller takes mm->mmap_sem.
  */
-void flush_cache_mm(struct mm_struct *mm)
+static void sh4_flush_cache_mm(void *arg)
 {
+       struct mm_struct *mm = arg;
+
+       if (cpu_context(smp_processor_id(), mm) == NO_CONTEXT)
+               return;
+
        /*
         * If cache is only 4k-per-way, there are never any 'aliases'.  Since
         * the cache is physically tagged, the data can just be left in there.
@@ -417,12 +295,21 @@ void flush_cache_mm(struct mm_struct *mm)
  * ADDR: Virtual Address (U0 address)
  * PFN: Physical page number
  */
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
-                     unsigned long pfn)
+static void sh4_flush_cache_page(void *args)
 {
-       unsigned long phys = pfn << PAGE_SHIFT;
+       struct flusher_data *data = args;
+       struct vm_area_struct *vma;
+       unsigned long address, pfn, phys;
        unsigned int alias_mask;
 
+       vma = data->vma;
+       address = data->addr1;
+       pfn = data->addr2;
+       phys = pfn << PAGE_SHIFT;
+
+       if (cpu_context(smp_processor_id(), vma->vm_mm) == NO_CONTEXT)
+               return;
+
        alias_mask = boot_cpu_data.dcache.alias_mask;
 
        /* We only need to flush D-cache when we have alias */
@@ -462,9 +349,19 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
  * Flushing the cache lines for U0 only isn't enough.
  * We need to flush for P1 too, which may contain aliases.
  */
-void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-                      unsigned long end)
+static void sh4_flush_cache_range(void *args)
 {
+       struct flusher_data *data = args;
+       struct vm_area_struct *vma;
+       unsigned long start, end;
+
+       vma = data->vma;
+       start = data->addr1;
+       end = data->addr2;
+
+       if (cpu_context(smp_processor_id(), vma->vm_mm) == NO_CONTEXT)
+               return;
+
        /*
         * If cache is only 4k-per-way, there are never any 'aliases'.  Since
         * the cache is physically tagged, the data can just be left in there.
@@ -492,20 +389,6 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
        }
 }
 
-/*
- * flush_icache_user_range
- * @vma: VMA of the process
- * @page: page
- * @addr: U0 address
- * @len: length of the range (< page size)
- */
-void flush_icache_user_range(struct vm_area_struct *vma,
-                            struct page *page, unsigned long addr, int len)
-{
-       flush_cache_page(vma, addr, page_to_pfn(page));
-       mb();
-}
-
 /**
  * __flush_cache_4096
  *
@@ -581,7 +464,49 @@ static void __flush_cache_4096(unsigned long addr, unsigned long phys,
  * Break the 1, 2 and 4 way variants of this out into separate functions to
  * avoid nearly all the overhead of having the conditional stuff in the function
  * bodies (+ the 1 and 2 way cases avoid saving any registers too).
+ *
+ * We want to eliminate unnecessary bus transactions, so this code uses
+ * a non-obvious technique.
+ *
+ * Loop over a cache way sized block of, one cache line at a time. For each
+ * line, use movca.a to cause the current cache line contents to be written
+ * back, but without reading anything from main memory. However this has the
+ * side effect that the cache is now caching that memory location. So follow
+ * this with a cache invalidate to mark the cache line invalid. And do all
+ * this with interrupts disabled, to avoid the cache line being accidently
+ * evicted while it is holding garbage.
+ *
+ * This also breaks in a number of circumstances:
+ * - if there are modifications to the region of memory just above
+ *   empty_zero_page (for example because a breakpoint has been placed
+ *   there), then these can be lost.
+ *
+ *   This is because the the memory address which the cache temporarily
+ *   caches in the above description is empty_zero_page. So the
+ *   movca.l hits the cache (it is assumed that it misses, or at least
+ *   isn't dirty), modifies the line and then invalidates it, losing the
+ *   required change.
+ *
+ * - If caches are disabled or configured in write-through mode, then
+ *   the movca.l writes garbage directly into memory.
  */
+static void __flush_dcache_segment_writethrough(unsigned long start,
+                                               unsigned long extent_per_way)
+{
+       unsigned long addr;
+       int i;
+
+       addr = CACHE_OC_ADDRESS_ARRAY | (start & cpu_data->dcache.entry_mask);
+
+       while (extent_per_way) {
+               for (i = 0; i < cpu_data->dcache.ways; i++)
+                       __raw_writel(0, addr + cpu_data->dcache.way_incr * i);
+
+               addr += cpu_data->dcache.linesz;
+               extent_per_way -= cpu_data->dcache.linesz;
+       }
+}
+
 static void __flush_dcache_segment_1way(unsigned long start,
                                        unsigned long extent_per_way)
 {
@@ -773,3 +698,47 @@ static void __flush_dcache_segment_4way(unsigned long start,
                a3 += linesz;
        } while (a0 < a0e);
 }
+
+extern void __weak sh4__flush_region_init(void);
+
+/*
+ * SH-4 has virtually indexed and physically tagged cache.
+ */
+void __init sh4_cache_init(void)
+{
+       unsigned int wt_enabled = !!(__raw_readl(CCR) & CCR_CACHE_WT);
+
+       printk("PVR=%08x CVR=%08x PRR=%08x\n",
+               ctrl_inl(CCN_PVR),
+               ctrl_inl(CCN_CVR),
+               ctrl_inl(CCN_PRR));
+
+       if (wt_enabled)
+               __flush_dcache_segment_fn = __flush_dcache_segment_writethrough;
+       else {
+               switch (boot_cpu_data.dcache.ways) {
+               case 1:
+                       __flush_dcache_segment_fn = __flush_dcache_segment_1way;
+                       break;
+               case 2:
+                       __flush_dcache_segment_fn = __flush_dcache_segment_2way;
+                       break;
+               case 4:
+                       __flush_dcache_segment_fn = __flush_dcache_segment_4way;
+                       break;
+               default:
+                       panic("unknown number of cache ways\n");
+                       break;
+               }
+       }
+
+       local_flush_icache_range        = sh4_flush_icache_range;
+       local_flush_dcache_page         = sh4_flush_dcache_page;
+       local_flush_cache_all           = sh4_flush_cache_all;
+       local_flush_cache_mm            = sh4_flush_cache_mm;
+       local_flush_cache_dup_mm        = sh4_flush_cache_mm;
+       local_flush_cache_page          = sh4_flush_cache_page;
+       local_flush_cache_range         = sh4_flush_cache_range;
+
+       sh4__flush_region_init();
+}
index 8676209..467ff8e 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 
+extern void __weak sh4__flush_region_init(void);
+
 /* Wired TLB entry for the D-cache */
 static unsigned long long dtlb_cache_slot;
 
-void __init p3_cache_init(void)
-{
-       /* Reserve a slot for dcache colouring in the DTLB */
-       dtlb_cache_slot = sh64_get_wired_dtlb_entry();
-}
-
-#ifdef CONFIG_DCACHE_DISABLED
-#define sh64_dcache_purge_all()                                        do { } while (0)
-#define sh64_dcache_purge_coloured_phy_page(paddr, eaddr)      do { } while (0)
-#define sh64_dcache_purge_user_range(mm, start, end)           do { } while (0)
-#define sh64_dcache_purge_phy_page(paddr)                      do { } while (0)
-#define sh64_dcache_purge_virt_page(mm, eaddr)                 do { } while (0)
-#endif
-
 /*
  * The following group of functions deal with mapping and unmapping a
  * temporary page into a DTLB slot that has been set aside for exclusive
@@ -56,7 +44,6 @@ static inline void sh64_teardown_dtlb_cache_slot(void)
        local_irq_enable();
 }
 
-#ifndef CONFIG_ICACHE_DISABLED
 static inline void sh64_icache_inv_all(void)
 {
        unsigned long long addr, flag, data;
@@ -214,52 +201,6 @@ static void sh64_icache_inv_user_page_range(struct mm_struct *mm,
        }
 }
 
-/*
- * Invalidate a small range of user context I-cache, not necessarily page
- * (or even cache-line) aligned.
- *
- * Since this is used inside ptrace, the ASID in the mm context typically
- * won't match current_asid.  We'll have to switch ASID to do this.  For
- * safety, and given that the range will be small, do all this under cli.
- *
- * Note, there is a hazard that the ASID in mm->context is no longer
- * actually associated with mm, i.e. if the mm->context has started a new
- * cycle since mm was last active.  However, this is just a performance
- * issue: all that happens is that we invalidate lines belonging to
- * another mm, so the owning process has to refill them when that mm goes
- * live again.  mm itself can't have any cache entries because there will
- * have been a flush_cache_all when the new mm->context cycle started.
- */
-static void sh64_icache_inv_user_small_range(struct mm_struct *mm,
-                                               unsigned long start, int len)
-{
-       unsigned long long eaddr = start;
-       unsigned long long eaddr_end = start + len;
-       unsigned long current_asid, mm_asid;
-       unsigned long flags;
-       unsigned long long epage_start;
-
-       /*
-        * Align to start of cache line.  Otherwise, suppose len==8 and
-        * start was at 32N+28 : the last 4 bytes wouldn't get invalidated.
-        */
-       eaddr = L1_CACHE_ALIGN(start);
-       eaddr_end = start + len;
-
-       mm_asid = cpu_asid(smp_processor_id(), mm);
-       local_irq_save(flags);
-       current_asid = switch_and_save_asid(mm_asid);
-
-       epage_start = eaddr & PAGE_MASK;
-
-       while (eaddr < eaddr_end) {
-               __asm__ __volatile__("icbi %0, 0" : : "r" (eaddr));
-               eaddr += L1_CACHE_BYTES;
-       }
-       switch_and_save_asid(current_asid);
-       local_irq_restore(flags);
-}
-
 static void sh64_icache_inv_current_user_range(unsigned long start, unsigned long end)
 {
        /* The icbi instruction never raises ITLBMISS.  i.e. if there's not a
@@ -287,9 +228,7 @@ static void sh64_icache_inv_current_user_range(unsigned long start, unsigned lon
                addr += L1_CACHE_BYTES;
        }
 }
-#endif /* !CONFIG_ICACHE_DISABLED */
 
-#ifndef CONFIG_DCACHE_DISABLED
 /* Buffer used as the target of alloco instructions to purge data from cache
    sets by natural eviction. -- RPC */
 #define DUMMY_ALLOCO_AREA_SIZE ((L1_CACHE_BYTES << 10) + (1024 * 4))
@@ -540,60 +479,11 @@ static void sh64_dcache_purge_user_range(struct mm_struct *mm,
        }
 }
 
-/*
- * Purge the range of addresses from the D-cache.
- *
- * The addresses lie in the superpage mapping. There's no harm if we
- * overpurge at either end - just a small performance loss.
- */
-void __flush_purge_region(void *start, int size)
-{
-       unsigned long long ullend, addr, aligned_start;
-
-       aligned_start = (unsigned long long)(signed long long)(signed long) start;
-       addr = L1_CACHE_ALIGN(aligned_start);
-       ullend = (unsigned long long) (signed long long) (signed long) start + size;
-
-       while (addr <= ullend) {
-               __asm__ __volatile__ ("ocbp %0, 0" : : "r" (addr));
-               addr += L1_CACHE_BYTES;
-       }
-}
-
-void __flush_wback_region(void *start, int size)
-{
-       unsigned long long ullend, addr, aligned_start;
-
-       aligned_start = (unsigned long long)(signed long long)(signed long) start;
-       addr = L1_CACHE_ALIGN(aligned_start);
-       ullend = (unsigned long long) (signed long long) (signed long) start + size;
-
-       while (addr < ullend) {
-               __asm__ __volatile__ ("ocbwb %0, 0" : : "r" (addr));
-               addr += L1_CACHE_BYTES;
-       }
-}
-
-void __flush_invalidate_region(void *start, int size)
-{
-       unsigned long long ullend, addr, aligned_start;
-
-       aligned_start = (unsigned long long)(signed long long)(signed long) start;
-       addr = L1_CACHE_ALIGN(aligned_start);
-       ullend = (unsigned long long) (signed long long) (signed long) start + size;
-
-       while (addr < ullend) {
-               __asm__ __volatile__ ("ocbi %0, 0" : : "r" (addr));
-               addr += L1_CACHE_BYTES;
-       }
-}
-#endif /* !CONFIG_DCACHE_DISABLED */
-
 /*
  * Invalidate the entire contents of both caches, after writing back to
  * memory any dirty data from the D-cache.
  */
-void flush_cache_all(void)
+static void sh5_flush_cache_all(void *unused)
 {
        sh64_dcache_purge_all();
        sh64_icache_inv_all();
@@ -620,7 +510,7 @@ void flush_cache_all(void)
  * I-cache.  This is similar to the lack of action needed in
  * flush_tlb_mm - see fault.c.
  */
-void flush_cache_mm(struct mm_struct *mm)
+static void sh5_flush_cache_mm(void *unused)
 {
        sh64_dcache_purge_all();
 }
@@ -632,13 +522,18 @@ void flush_cache_mm(struct mm_struct *mm)
  *
  * Note, 'end' is 1 byte beyond the end of the range to flush.
  */
-void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-                      unsigned long end)
+static void sh5_flush_cache_range(void *args)
 {
-       struct mm_struct *mm = vma->vm_mm;
+       struct flusher_data *data = args;
+       struct vm_area_struct *vma;
+       unsigned long start, end;
+
+       vma = data->vma;
+       start = data->addr1;
+       end = data->addr2;
 
-       sh64_dcache_purge_user_range(mm, start, end);
-       sh64_icache_inv_user_page_range(mm, start, end);
+       sh64_dcache_purge_user_range(vma->vm_mm, start, end);
+       sh64_icache_inv_user_page_range(vma->vm_mm, start, end);
 }
 
 /*
@@ -650,16 +545,23 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
  *
  * Note, this is called with pte lock held.
  */
-void flush_cache_page(struct vm_area_struct *vma, unsigned long eaddr,
-                     unsigned long pfn)
+static void sh5_flush_cache_page(void *args)
 {
+       struct flusher_data *data = args;
+       struct vm_area_struct *vma;
+       unsigned long eaddr, pfn;
+
+       vma = data->vma;
+       eaddr = data->addr1;
+       pfn = data->addr2;
+
        sh64_dcache_purge_phy_page(pfn << PAGE_SHIFT);
 
        if (vma->vm_flags & VM_EXEC)
                sh64_icache_inv_user_page(vma, eaddr);
 }
 
-void flush_dcache_page(struct page *page)
+static void sh5_flush_dcache_page(void *page)
 {
        sh64_dcache_purge_phy_page(page_to_phys(page));
        wmb();
@@ -673,162 +575,47 @@ void flush_dcache_page(struct page *page)
  * mapping, therefore it's guaranteed that there no cache entries for
  * the range in cache sets of the wrong colour.
  */
-void flush_icache_range(unsigned long start, unsigned long end)
+static void sh5_flush_icache_range(void *args)
 {
+       struct flusher_data *data = args;
+       unsigned long start, end;
+
+       start = data->addr1;
+       end = data->addr2;
+
        __flush_purge_region((void *)start, end);
        wmb();
        sh64_icache_inv_kernel_range(start, end);
 }
 
-/*
- * Flush the range of user (defined by vma->vm_mm) address space starting
- * at 'addr' for 'len' bytes from the cache.  The range does not straddle
- * a page boundary, the unique physical page containing the range is
- * 'page'.  This seems to be used mainly for invalidating an address
- * range following a poke into the program text through the ptrace() call
- * from another process (e.g. for BRK instruction insertion).
- */
-void flush_icache_user_range(struct vm_area_struct *vma,
-                       struct page *page, unsigned long addr, int len)
-{
-
-       sh64_dcache_purge_coloured_phy_page(page_to_phys(page), addr);
-       mb();
-
-       if (vma->vm_flags & VM_EXEC)
-               sh64_icache_inv_user_small_range(vma->vm_mm, addr, len);
-}
-
 /*
  * For the address range [start,end), write back the data from the
  * D-cache and invalidate the corresponding region of the I-cache for the
  * current process.  Used to flush signal trampolines on the stack to
  * make them executable.
  */
-void flush_cache_sigtramp(unsigned long vaddr)
+static void sh5_flush_cache_sigtramp(void *vaddr)
 {
-       unsigned long end = vaddr + L1_CACHE_BYTES;
+       unsigned long end = (unsigned long)vaddr + L1_CACHE_BYTES;
 
-       __flush_wback_region((void *)vaddr, L1_CACHE_BYTES);
+       __flush_wback_region(vaddr, L1_CACHE_BYTES);
        wmb();
-       sh64_icache_inv_current_user_range(vaddr, end);
+       sh64_icache_inv_current_user_range((unsigned long)vaddr, end);
 }
 
-#ifdef CONFIG_MMU
-/*
- * These *MUST* lie in an area of virtual address space that's otherwise
- * unused.
- */
-#define UNIQUE_EADDR_START 0xe0000000UL
-#define UNIQUE_EADDR_END   0xe8000000UL
-
-/*
- * Given a physical address paddr, and a user virtual address user_eaddr
- * which will eventually be mapped to it, create a one-off kernel-private
- * eaddr mapped to the same paddr.  This is used for creating special
- * destination pages for copy_user_page and clear_user_page.
- */
-static unsigned long sh64_make_unique_eaddr(unsigned long user_eaddr,
-                                           unsigned long paddr)
-{
-       static unsigned long current_pointer = UNIQUE_EADDR_START;
-       unsigned long coloured_pointer;
-
-       if (current_pointer == UNIQUE_EADDR_END) {
-               sh64_dcache_purge_all();
-               current_pointer = UNIQUE_EADDR_START;
-       }
-
-       coloured_pointer = (current_pointer & ~CACHE_OC_SYN_MASK) |
-                               (user_eaddr & CACHE_OC_SYN_MASK);
-       sh64_setup_dtlb_cache_slot(coloured_pointer, get_asid(), paddr);
-
-       current_pointer += (PAGE_SIZE << CACHE_OC_N_SYNBITS);
-
-       return coloured_pointer;
-}
-
-static void sh64_copy_user_page_coloured(void *to, void *from,
-                                        unsigned long address)
+void __init sh5_cache_init(void)
 {
-       void *coloured_to;
+       local_flush_cache_all           = sh5_flush_cache_all;
+       local_flush_cache_mm            = sh5_flush_cache_mm;
+       local_flush_cache_dup_mm        = sh5_flush_cache_mm;
+       local_flush_cache_page          = sh5_flush_cache_page;
+       local_flush_cache_range         = sh5_flush_cache_range;
+       local_flush_dcache_page         = sh5_flush_dcache_page;
+       local_flush_icache_range        = sh5_flush_icache_range;
+       local_flush_cache_sigtramp      = sh5_flush_cache_sigtramp;
 
-       /*
-        * Discard any existing cache entries of the wrong colour.  These are
-        * present quite often, if the kernel has recently used the page
-        * internally, then given it up, then it's been allocated to the user.
-        */
-       sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long)to);
-
-       coloured_to = (void *)sh64_make_unique_eaddr(address, __pa(to));
-       copy_page(from, coloured_to);
-
-       sh64_teardown_dtlb_cache_slot();
-}
-
-static void sh64_clear_user_page_coloured(void *to, unsigned long address)
-{
-       void *coloured_to;
-
-       /*
-        * Discard any existing kernel-originated lines of the wrong
-        * colour (as above)
-        */
-       sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long)to);
-
-       coloured_to = (void *)sh64_make_unique_eaddr(address, __pa(to));
-       clear_page(coloured_to);
-
-       sh64_teardown_dtlb_cache_slot();
-}
-
-/*
- * 'from' and 'to' are kernel virtual addresses (within the superpage
- * mapping of the physical RAM).  'address' is the user virtual address
- * where the copy 'to' will be mapped after.  This allows a custom
- * mapping to be used to ensure that the new copy is placed in the
- * right cache sets for the user to see it without having to bounce it
- * out via memory.  Note however : the call to flush_page_to_ram in
- * (generic)/mm/memory.c:(break_cow) undoes all this good work in that one
- * very important case!
- *
- * TBD : can we guarantee that on every call, any cache entries for
- * 'from' are in the same colour sets as 'address' also?  i.e. is this
- * always used just to deal with COW?  (I suspect not).
- *
- * There are two possibilities here for when the page 'from' was last accessed:
- * - by the kernel : this is OK, no purge required.
- * - by the/a user (e.g. for break_COW) : need to purge.
- *
- * If the potential user mapping at 'address' is the same colour as
- * 'from' there is no need to purge any cache lines from the 'from'
- * page mapped into cache sets of colour 'address'.  (The copy will be
- * accessing the page through 'from').
- */
-void copy_user_page(void *to, void *from, unsigned long address,
-                   struct page *page)
-{
-       if (((address ^ (unsigned long) from) & CACHE_OC_SYN_MASK) != 0)
-               sh64_dcache_purge_coloured_phy_page(__pa(from), address);
-
-       if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0)
-               copy_page(to, from);
-       else
-               sh64_copy_user_page_coloured(to, from, address);
-}
+       /* Reserve a slot for dcache colouring in the DTLB */
+       dtlb_cache_slot = sh64_get_wired_dtlb_entry();
 
-/*
- * 'to' is a kernel virtual address (within the superpage mapping of the
- * physical RAM).  'address' is the user virtual address where the 'to'
- * page will be mapped after.  This allows a custom mapping to be used to
- * ensure that the new copy is placed in the right cache sets for the
- * user to see it without having to bounce it out via memory.
- */
-void clear_user_page(void *to, unsigned long address, struct page *page)
-{
-       if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0)
-               clear_page(to);
-       else
-               sh64_clear_user_page_coloured(to, address);
+       sh4__flush_region_init();
 }
-#endif
index 22dacc7..6293f57 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/fs.h>
 #include <linux/threads.h>
 #include <asm/addrspace.h>
 #include <asm/page.h>
@@ -63,15 +64,21 @@ static inline void cache_wback_all(void)
  *
  * Called from kernel/module.c:sys_init_module and routine for a.out format.
  */
-void flush_icache_range(unsigned long start, unsigned long end)
+static void sh7705_flush_icache_range(void *args)
 {
+       struct flusher_data *data = args;
+       unsigned long start, end;
+
+       start = data->addr1;
+       end = data->addr2;
+
        __flush_wback_region((void *)start, end - start);
 }
 
 /*
  * Writeback&Invalidate the D-cache of the page
  */
-static void __uses_jump_to_uncached __flush_dcache_page(unsigned long phys)
+static void __flush_dcache_page(unsigned long phys)
 {
        unsigned long ways, waysize, addrstart;
        unsigned long flags;
@@ -126,13 +133,17 @@ static void __uses_jump_to_uncached __flush_dcache_page(unsigned long phys)
  * Write back & invalidate the D-cache of the page.
  * (To avoid "alias" issues)
  */
-void flush_dcache_page(struct page *page)
+static void sh7705_flush_dcache_page(void *page)
 {
-       if (test_bit(PG_mapped, &page->flags))
+       struct address_space *mapping = page_mapping(page);
+
+       if (mapping && !mapping_mapped(mapping))
+               set_bit(PG_dcache_dirty, &page->flags);
+       else
                __flush_dcache_page(PHYSADDR(page_address(page)));
 }
 
-void __uses_jump_to_uncached flush_cache_all(void)
+static void sh7705_flush_cache_all(void *args)
 {
        unsigned long flags;
 
@@ -144,44 +155,16 @@ void __uses_jump_to_uncached flush_cache_all(void)
        local_irq_restore(flags);
 }
 
-void flush_cache_mm(struct mm_struct *mm)
-{
-       /* Is there any good way? */
-       /* XXX: possibly call flush_cache_range for each vm area */
-       flush_cache_all();
-}
-
-/*
- * Write back and invalidate D-caches.
- *
- * START, END: Virtual Address (U0 address)
- *
- * NOTE: We need to flush the _physical_ page entry.
- * Flushing the cache lines for U0 only isn't enough.
- * We need to flush for P1 too, which may contain aliases.
- */
-void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-                      unsigned long end)
-{
-
-       /*
-        * We could call flush_cache_page for the pages of these range,
-        * but it's not efficient (scan the caches all the time...).
-        *
-        * We can't use A-bit magic, as there's the case we don't have
-        * valid entry on TLB.
-        */
-       flush_cache_all();
-}
-
 /*
  * Write back and invalidate I/D-caches for the page.
  *
  * ADDRESS: Virtual Address (U0 address)
  */
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
-                     unsigned long pfn)
+static void sh7705_flush_cache_page(void *args)
 {
+       struct flusher_data *data = args;
+       unsigned long pfn = data->addr2;
+
        __flush_dcache_page(pfn << PAGE_SHIFT);
 }
 
@@ -193,7 +176,19 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
  * Not entirely sure why this is necessary on SH3 with 32K cache but
  * without it we get occasional "Memory fault" when loading a program.
  */
-void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+static void sh7705_flush_icache_page(void *page)
 {
        __flush_purge_region(page_address(page), PAGE_SIZE);
 }
+
+void __init sh7705_cache_init(void)
+{
+       local_flush_icache_range        = sh7705_flush_icache_range;
+       local_flush_dcache_page         = sh7705_flush_dcache_page;
+       local_flush_cache_all           = sh7705_flush_cache_all;
+       local_flush_cache_mm            = sh7705_flush_cache_all;
+       local_flush_cache_dup_mm        = sh7705_flush_cache_all;
+       local_flush_cache_range         = sh7705_flush_cache_all;
+       local_flush_cache_page          = sh7705_flush_cache_page;
+       local_flush_icache_page         = sh7705_flush_icache_page;
+}
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
new file mode 100644 (file)
index 0000000..35c37b7
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * arch/sh/mm/cache.c
+ *
+ * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
+ * Copyright (C) 2002 - 2009  Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/fs.h>
+#include <linux/smp.h>
+#include <linux/highmem.h>
+#include <linux/module.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+void (*local_flush_cache_all)(void *args) = cache_noop;
+void (*local_flush_cache_mm)(void *args) = cache_noop;
+void (*local_flush_cache_dup_mm)(void *args) = cache_noop;
+void (*local_flush_cache_page)(void *args) = cache_noop;
+void (*local_flush_cache_range)(void *args) = cache_noop;
+void (*local_flush_dcache_page)(void *args) = cache_noop;
+void (*local_flush_icache_range)(void *args) = cache_noop;
+void (*local_flush_icache_page)(void *args) = cache_noop;
+void (*local_flush_cache_sigtramp)(void *args) = cache_noop;
+
+void (*__flush_wback_region)(void *start, int size);
+void (*__flush_purge_region)(void *start, int size);
+void (*__flush_invalidate_region)(void *start, int size);
+
+static inline void noop__flush_region(void *start, int size)
+{
+}
+
+static inline void cacheop_on_each_cpu(void (*func) (void *info), void *info,
+                                   int wait)
+{
+       preempt_disable();
+       smp_call_function(func, info, wait);
+       func(info);
+       preempt_enable();
+}
+
+void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
+                      unsigned long vaddr, void *dst, const void *src,
+                      unsigned long len)
+{
+       if (boot_cpu_data.dcache.n_aliases && page_mapped(page) &&
+           !test_bit(PG_dcache_dirty, &page->flags)) {
+               void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
+               memcpy(vto, src, len);
+               kunmap_coherent(vto);
+       } else {
+               memcpy(dst, src, len);
+               if (boot_cpu_data.dcache.n_aliases)
+                       set_bit(PG_dcache_dirty, &page->flags);
+       }
+
+       if (vma->vm_flags & VM_EXEC)
+               flush_cache_page(vma, vaddr, page_to_pfn(page));
+}
+
+void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
+                        unsigned long vaddr, void *dst, const void *src,
+                        unsigned long len)
+{
+       if (boot_cpu_data.dcache.n_aliases && page_mapped(page) &&
+           !test_bit(PG_dcache_dirty, &page->flags)) {
+               void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
+               memcpy(dst, vfrom, len);
+               kunmap_coherent(vfrom);
+       } else {
+               memcpy(dst, src, len);
+               if (boot_cpu_data.dcache.n_aliases)
+                       set_bit(PG_dcache_dirty, &page->flags);
+       }
+}
+
+void copy_user_highpage(struct page *to, struct page *from,
+                       unsigned long vaddr, struct vm_area_struct *vma)
+{
+       void *vfrom, *vto;
+
+       vto = kmap_atomic(to, KM_USER1);
+
+       if (boot_cpu_data.dcache.n_aliases && page_mapped(from) &&
+           !test_bit(PG_dcache_dirty, &from->flags)) {
+               vfrom = kmap_coherent(from, vaddr);
+               copy_page(vto, vfrom);
+               kunmap_coherent(vfrom);
+       } else {
+               vfrom = kmap_atomic(from, KM_USER0);
+               copy_page(vto, vfrom);
+               kunmap_atomic(vfrom, KM_USER0);
+       }
+
+       if (pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
+               __flush_purge_region(vto, PAGE_SIZE);
+
+       kunmap_atomic(vto, KM_USER1);
+       /* Make sure this page is cleared on other CPU's too before using it */
+       smp_wmb();
+}
+EXPORT_SYMBOL(copy_user_highpage);
+
+void clear_user_highpage(struct page *page, unsigned long vaddr)
+{
+       void *kaddr = kmap_atomic(page, KM_USER0);
+
+       clear_page(kaddr);
+
+       if (pages_do_alias((unsigned long)kaddr, vaddr & PAGE_MASK))
+               __flush_purge_region(kaddr, PAGE_SIZE);
+
+       kunmap_atomic(kaddr, KM_USER0);
+}
+EXPORT_SYMBOL(clear_user_highpage);
+
+void __update_cache(struct vm_area_struct *vma,
+                   unsigned long address, pte_t pte)
+{
+       struct page *page;
+       unsigned long pfn = pte_pfn(pte);
+
+       if (!boot_cpu_data.dcache.n_aliases)
+               return;
+
+       page = pfn_to_page(pfn);
+       if (pfn_valid(pfn) && page_mapping(page)) {
+               int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
+               if (dirty) {
+                       unsigned long addr = (unsigned long)page_address(page);
+
+                       if (pages_do_alias(addr, address & PAGE_MASK))
+                               __flush_purge_region((void *)addr, PAGE_SIZE);
+               }
+       }
+}
+
+void __flush_anon_page(struct page *page, unsigned long vmaddr)
+{
+       unsigned long addr = (unsigned long) page_address(page);
+
+       if (pages_do_alias(addr, vmaddr)) {
+               if (boot_cpu_data.dcache.n_aliases && page_mapped(page) &&
+                   !test_bit(PG_dcache_dirty, &page->flags)) {
+                       void *kaddr;
+
+                       kaddr = kmap_coherent(page, vmaddr);
+                       /* XXX.. For now kunmap_coherent() does a purge */
+                       /* __flush_purge_region((void *)kaddr, PAGE_SIZE); */
+                       kunmap_coherent(kaddr);
+               } else
+                       __flush_purge_region((void *)addr, PAGE_SIZE);
+       }
+}
+
+void flush_cache_all(void)
+{
+       cacheop_on_each_cpu(local_flush_cache_all, NULL, 1);
+}
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+       cacheop_on_each_cpu(local_flush_cache_mm, mm, 1);
+}
+
+void flush_cache_dup_mm(struct mm_struct *mm)
+{
+       cacheop_on_each_cpu(local_flush_cache_dup_mm, mm, 1);
+}
+
+void flush_cache_page(struct vm_area_struct *vma, unsigned long addr,
+                     unsigned long pfn)
+{
+       struct flusher_data data;
+
+       data.vma = vma;
+       data.addr1 = addr;
+       data.addr2 = pfn;
+
+       cacheop_on_each_cpu(local_flush_cache_page, (void *)&data, 1);
+}
+
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+                      unsigned long end)
+{
+       struct flusher_data data;
+
+       data.vma = vma;
+       data.addr1 = start;
+       data.addr2 = end;
+
+       cacheop_on_each_cpu(local_flush_cache_range, (void *)&data, 1);
+}
+
+void flush_dcache_page(struct page *page)
+{
+       cacheop_on_each_cpu(local_flush_dcache_page, page, 1);
+}
+
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+       struct flusher_data data;
+
+       data.vma = NULL;
+       data.addr1 = start;
+       data.addr2 = end;
+
+       cacheop_on_each_cpu(local_flush_icache_range, (void *)&data, 1);
+}
+
+void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+       /* Nothing uses the VMA, so just pass the struct page along */
+       cacheop_on_each_cpu(local_flush_icache_page, page, 1);
+}
+
+void flush_cache_sigtramp(unsigned long address)
+{
+       cacheop_on_each_cpu(local_flush_cache_sigtramp, (void *)address, 1);
+}
+
+static void compute_alias(struct cache_info *c)
+{
+       c->alias_mask = ((c->sets - 1) << c->entry_shift) & ~(PAGE_SIZE - 1);
+       c->n_aliases = c->alias_mask ? (c->alias_mask >> PAGE_SHIFT) + 1 : 0;
+}
+
+static void __init emit_cache_params(void)
+{
+       printk(KERN_NOTICE "I-cache : n_ways=%d n_sets=%d way_incr=%d\n",
+               boot_cpu_data.icache.ways,
+               boot_cpu_data.icache.sets,
+               boot_cpu_data.icache.way_incr);
+       printk(KERN_NOTICE "I-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
+               boot_cpu_data.icache.entry_mask,
+               boot_cpu_data.icache.alias_mask,
+               boot_cpu_data.icache.n_aliases);
+       printk(KERN_NOTICE "D-cache : n_ways=%d n_sets=%d way_incr=%d\n",
+               boot_cpu_data.dcache.ways,
+               boot_cpu_data.dcache.sets,
+               boot_cpu_data.dcache.way_incr);
+       printk(KERN_NOTICE "D-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
+               boot_cpu_data.dcache.entry_mask,
+               boot_cpu_data.dcache.alias_mask,
+               boot_cpu_data.dcache.n_aliases);
+
+       /*
+        * Emit Secondary Cache parameters if the CPU has a probed L2.
+        */
+       if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) {
+               printk(KERN_NOTICE "S-cache : n_ways=%d n_sets=%d way_incr=%d\n",
+                       boot_cpu_data.scache.ways,
+                       boot_cpu_data.scache.sets,
+                       boot_cpu_data.scache.way_incr);
+               printk(KERN_NOTICE "S-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
+                       boot_cpu_data.scache.entry_mask,
+                       boot_cpu_data.scache.alias_mask,
+                       boot_cpu_data.scache.n_aliases);
+       }
+}
+
+void __init cpu_cache_init(void)
+{
+       compute_alias(&boot_cpu_data.icache);
+       compute_alias(&boot_cpu_data.dcache);
+       compute_alias(&boot_cpu_data.scache);
+
+       __flush_wback_region            = noop__flush_region;
+       __flush_purge_region            = noop__flush_region;
+       __flush_invalidate_region       = noop__flush_region;
+
+       if (boot_cpu_data.family == CPU_FAMILY_SH2) {
+               extern void __weak sh2_cache_init(void);
+
+               sh2_cache_init();
+       }
+
+       if (boot_cpu_data.family == CPU_FAMILY_SH2A) {
+               extern void __weak sh2a_cache_init(void);
+
+               sh2a_cache_init();
+       }
+
+       if (boot_cpu_data.family == CPU_FAMILY_SH3) {
+               extern void __weak sh3_cache_init(void);
+
+               sh3_cache_init();
+
+               if ((boot_cpu_data.type == CPU_SH7705) &&
+                   (boot_cpu_data.dcache.sets == 512)) {
+                       extern void __weak sh7705_cache_init(void);
+
+                       sh7705_cache_init();
+               }
+       }
+
+       if ((boot_cpu_data.family == CPU_FAMILY_SH4) ||
+           (boot_cpu_data.family == CPU_FAMILY_SH4A) ||
+           (boot_cpu_data.family == CPU_FAMILY_SH4AL_DSP)) {
+               extern void __weak sh4_cache_init(void);
+
+               sh4_cache_init();
+       }
+
+       if (boot_cpu_data.family == CPU_FAMILY_SH5) {
+               extern void __weak sh5_cache_init(void);
+
+               sh5_cache_init();
+       }
+
+       emit_cache_params();
+}
index 7192594..781b413 100644 (file)
@@ -2,7 +2,7 @@
  * Page fault handler for SH with an MMU.
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2003 - 2008  Paul Mundt
+ *  Copyright (C) 2003 - 2009  Paul Mundt
  *
  *  Based on linux/arch/i386/mm/fault.c:
  *   Copyright (C) 1995  Linus Torvalds
@@ -25,18 +25,91 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap)
 {
        int ret = 0;
 
-#ifdef CONFIG_KPROBES
-       if (!user_mode(regs)) {
+       if (kprobes_built_in() && !user_mode(regs)) {
                preempt_disable();
                if (kprobe_running() && kprobe_fault_handler(regs, trap))
                        ret = 1;
                preempt_enable();
        }
-#endif
 
        return ret;
 }
 
+static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
+{
+       unsigned index = pgd_index(address);
+       pgd_t *pgd_k;
+       pud_t *pud, *pud_k;
+       pmd_t *pmd, *pmd_k;
+
+       pgd += index;
+       pgd_k = init_mm.pgd + index;
+
+       if (!pgd_present(*pgd_k))
+               return NULL;
+
+       pud = pud_offset(pgd, address);
+       pud_k = pud_offset(pgd_k, address);
+       if (!pud_present(*pud_k))
+               return NULL;
+
+       pmd = pmd_offset(pud, address);
+       pmd_k = pmd_offset(pud_k, address);
+       if (!pmd_present(*pmd_k))
+               return NULL;
+
+       if (!pmd_present(*pmd))
+               set_pmd(pmd, *pmd_k);
+       else {
+               /*
+                * The page tables are fully synchronised so there must
+                * be another reason for the fault. Return NULL here to
+                * signal that we have not taken care of the fault.
+                */
+               BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+               return NULL;
+       }
+
+       return pmd_k;
+}
+
+/*
+ * Handle a fault on the vmalloc or module mapping area
+ */
+static noinline int vmalloc_fault(unsigned long address)
+{
+       pgd_t *pgd_k;
+       pmd_t *pmd_k;
+       pte_t *pte_k;
+
+       /* Make sure we are in vmalloc/module/P3 area: */
+       if (!(address >= VMALLOC_START && address < P3_ADDR_MAX))
+               return -1;
+
+       /*
+        * Synchronize this task's top level page-table
+        * with the 'reference' page table.
+        *
+        * Do _not_ use "current" here. We might be inside
+        * an interrupt in the middle of a task switch..
+        */
+       pgd_k = get_TTB();
+       pmd_k = vmalloc_sync_one(pgd_k, address);
+       if (!pmd_k)
+               return -1;
+
+       pte_k = pte_offset_kernel(pmd_k, address);
+       if (!pte_present(*pte_k))
+               return -1;
+
+       return 0;
+}
+
+static int fault_in_kernel_space(unsigned long address)
+{
+       return address >= TASK_SIZE;
+}
+
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -46,6 +119,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
                                        unsigned long writeaccess,
                                        unsigned long address)
 {
+       unsigned long vec;
        struct task_struct *tsk;
        struct mm_struct *mm;
        struct vm_area_struct * vma;
@@ -53,59 +127,30 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        int fault;
        siginfo_t info;
 
-       /*
-        * We don't bother with any notifier callbacks here, as they are
-        * all handled through the __do_page_fault() fast-path.
-        */
-
        tsk = current;
+       mm = tsk->mm;
        si_code = SEGV_MAPERR;
+       vec = lookup_exception_vector();
 
-       if (unlikely(address >= TASK_SIZE)) {
-               /*
-                * Synchronize this task's top level page-table
-                * with the 'reference' page table.
-                *
-                * Do _not_ use "tsk" here. We might be inside
-                * an interrupt in the middle of a task switch..
-                */
-               int offset = pgd_index(address);
-               pgd_t *pgd, *pgd_k;
-               pud_t *pud, *pud_k;
-               pmd_t *pmd, *pmd_k;
-
-               pgd = get_TTB() + offset;
-               pgd_k = swapper_pg_dir + offset;
-
-               if (!pgd_present(*pgd)) {
-                       if (!pgd_present(*pgd_k))
-                               goto bad_area_nosemaphore;
-                       set_pgd(pgd, *pgd_k);
+       /*
+        * We fault-in kernel-space virtual memory on-demand. The
+        * 'reference' page table is init_mm.pgd.
+        *
+        * NOTE! We MUST NOT take any locks for this case. We may
+        * be in an interrupt or a critical region, and should
+        * only copy the information from the master page table,
+        * nothing more.
+        */
+       if (unlikely(fault_in_kernel_space(address))) {
+               if (vmalloc_fault(address) >= 0)
                        return;
-               }
-
-               pud = pud_offset(pgd, address);
-               pud_k = pud_offset(pgd_k, address);
-
-               if (!pud_present(*pud)) {
-                       if (!pud_present(*pud_k))
-                               goto bad_area_nosemaphore;
-                       set_pud(pud, *pud_k);
+               if (notify_page_fault(regs, vec))
                        return;
-               }
 
-               pmd = pmd_offset(pud, address);
-               pmd_k = pmd_offset(pud_k, address);
-               if (pmd_present(*pmd) || !pmd_present(*pmd_k))
-                       goto bad_area_nosemaphore;
-               set_pmd(pmd, *pmd_k);
-
-               return;
+               goto bad_area_nosemaphore;
        }
 
-       mm = tsk->mm;
-
-       if (unlikely(notify_page_fault(regs, lookup_exception_vector())))
+       if (unlikely(notify_page_fault(regs, vec)))
                return;
 
        /* Only enable interrupts if they were on before the fault */
@@ -115,8 +160,8 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
 
        /*
-        * If we're in an interrupt or have no user
-        * context, we must not take the fault..
+        * If we're in an interrupt, have no user context or are running
+        * in an atomic region then we must not take the fault:
         */
        if (in_atomic() || !mm)
                goto no_context;
@@ -132,10 +177,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
                goto bad_area;
        if (expand_stack(vma, address))
                goto bad_area;
-/*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
+
+       /*
+        * Ok, we have a good vm_area for this memory access, so
+        * we can handle it..
+        */
 good_area:
        si_code = SEGV_ACCERR;
        if (writeaccess) {
@@ -173,10 +219,10 @@ survive:
        up_read(&mm->mmap_sem);
        return;
 
-/*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
+       /*
       * Something tried to access memory that isn't in our memory map..
       * Fix it, but check if it's kernel or user first..
       */
 bad_area:
        up_read(&mm->mmap_sem);
 
@@ -272,16 +318,15 @@ do_sigbus:
 /*
  * Called with interrupts disabled.
  */
-asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
-                                        unsigned long writeaccess,
-                                        unsigned long address)
+asmlinkage int __kprobes
+handle_tlbmiss(struct pt_regs *regs, unsigned long writeaccess,
+              unsigned long address)
 {
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
        pte_t *pte;
        pte_t entry;
-       int ret = 1;
 
        /*
         * We don't take page faults for P1, P2, and parts of P4, these
@@ -292,40 +337,41 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
                pgd = pgd_offset_k(address);
        } else {
                if (unlikely(address >= TASK_SIZE || !current->mm))
-                       goto out;
+                       return 1;
 
                pgd = pgd_offset(current->mm, address);
        }
 
        pud = pud_offset(pgd, address);
        if (pud_none_or_clear_bad(pud))
-               goto out;
+               return 1;
        pmd = pmd_offset(pud, address);
        if (pmd_none_or_clear_bad(pmd))
-               goto out;
+               return 1;
        pte = pte_offset_kernel(pmd, address);
        entry = *pte;
        if (unlikely(pte_none(entry) || pte_not_present(entry)))
-               goto out;
+               return 1;
        if (unlikely(writeaccess && !pte_write(entry)))
-               goto out;
+               return 1;
 
        if (writeaccess)
                entry = pte_mkdirty(entry);
        entry = pte_mkyoung(entry);
 
+       set_pte(pte, entry);
+
 #if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SMP)
        /*
-        * ITLB is not affected by "ldtlb" instruction.
-        * So, we need to flush the entry by ourselves.
+        * SH-4 does not set MMUCR.RC to the corresponding TLB entry in
+        * the case of an initial page write exception, so we need to
+        * flush it in order to avoid potential TLB entry duplication.
         */
-       local_flush_tlb_one(get_asid(), address & PAGE_MASK);
+       if (writeaccess == 2)
+               local_flush_tlb_one(get_asid(), address & PAGE_MASK);
 #endif
 
-       set_pte(pte, entry);
        update_mmu_cache(NULL, address, entry);
 
-       ret = 0;
-out:
-       return ret;
+       return 0;
 }
index bd63b96..2b356ce 100644 (file)
@@ -56,16 +56,7 @@ inline void __do_tlb_refill(unsigned long address,
        /*
         * Set PTEH register
         */
-       pteh = address & MMU_VPN_MASK;
-
-       /* Sign extend based on neff. */
-#if (NEFF == 32)
-       /* Faster sign extension */
-       pteh = (unsigned long long)(signed long long)(signed long)pteh;
-#else
-       /* General case */
-       pteh = (pteh & NEFF_SIGN) ? (pteh | NEFF_MASK) : pteh;
-#endif
+       pteh = neff_sign_extend(address & MMU_VPN_MASK);
 
        /* Set the ASID. */
        pteh |= get_asid() << PTEH_ASID_SHIFT;
diff --git a/arch/sh/mm/flush-sh4.c b/arch/sh/mm/flush-sh4.c
new file mode 100644 (file)
index 0000000..cef4026
--- /dev/null
@@ -0,0 +1,108 @@
+#include <linux/mm.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+/*
+ * Write back the dirty D-caches, but not invalidate them.
+ *
+ * START: Virtual Address (U0, P1, or P3)
+ * SIZE: Size of the region.
+ */
+static void sh4__flush_wback_region(void *start, int size)
+{
+       reg_size_t aligned_start, v, cnt, end;
+
+       aligned_start = register_align(start);
+       v = aligned_start & ~(L1_CACHE_BYTES-1);
+       end = (aligned_start + size + L1_CACHE_BYTES-1)
+               & ~(L1_CACHE_BYTES-1);
+       cnt = (end - v) / L1_CACHE_BYTES;
+
+       while (cnt >= 8) {
+               __ocbwb(v); v += L1_CACHE_BYTES;
+               __ocbwb(v); v += L1_CACHE_BYTES;
+               __ocbwb(v); v += L1_CACHE_BYTES;
+               __ocbwb(v); v += L1_CACHE_BYTES;
+               __ocbwb(v); v += L1_CACHE_BYTES;
+               __ocbwb(v); v += L1_CACHE_BYTES;
+               __ocbwb(v); v += L1_CACHE_BYTES;
+               __ocbwb(v); v += L1_CACHE_BYTES;
+               cnt -= 8;
+       }
+
+       while (cnt) {
+               __ocbwb(v); v += L1_CACHE_BYTES;
+               cnt--;
+       }
+}
+
+/*
+ * Write back the dirty D-caches and invalidate them.
+ *
+ * START: Virtual Address (U0, P1, or P3)
+ * SIZE: Size of the region.
+ */
+static void sh4__flush_purge_region(void *start, int size)
+{
+       reg_size_t aligned_start, v, cnt, end;
+
+       aligned_start = register_align(start);
+       v = aligned_start & ~(L1_CACHE_BYTES-1);
+       end = (aligned_start + size + L1_CACHE_BYTES-1)
+               & ~(L1_CACHE_BYTES-1);
+       cnt = (end - v) / L1_CACHE_BYTES;
+
+       while (cnt >= 8) {
+               __ocbp(v); v += L1_CACHE_BYTES;
+               __ocbp(v); v += L1_CACHE_BYTES;
+               __ocbp(v); v += L1_CACHE_BYTES;
+               __ocbp(v); v += L1_CACHE_BYTES;
+               __ocbp(v); v += L1_CACHE_BYTES;
+               __ocbp(v); v += L1_CACHE_BYTES;
+               __ocbp(v); v += L1_CACHE_BYTES;
+               __ocbp(v); v += L1_CACHE_BYTES;
+               cnt -= 8;
+       }
+       while (cnt) {
+               __ocbp(v); v += L1_CACHE_BYTES;
+               cnt--;
+       }
+}
+
+/*
+ * No write back please
+ */
+static void sh4__flush_invalidate_region(void *start, int size)
+{
+       reg_size_t aligned_start, v, cnt, end;
+
+       aligned_start = register_align(start);
+       v = aligned_start & ~(L1_CACHE_BYTES-1);
+       end = (aligned_start + size + L1_CACHE_BYTES-1)
+               & ~(L1_CACHE_BYTES-1);
+       cnt = (end - v) / L1_CACHE_BYTES;
+
+       while (cnt >= 8) {
+               __ocbi(v); v += L1_CACHE_BYTES;
+               __ocbi(v); v += L1_CACHE_BYTES;
+               __ocbi(v); v += L1_CACHE_BYTES;
+               __ocbi(v); v += L1_CACHE_BYTES;
+               __ocbi(v); v += L1_CACHE_BYTES;
+               __ocbi(v); v += L1_CACHE_BYTES;
+               __ocbi(v); v += L1_CACHE_BYTES;
+               __ocbi(v); v += L1_CACHE_BYTES;
+               cnt -= 8;
+       }
+
+       while (cnt) {
+               __ocbi(v); v += L1_CACHE_BYTES;
+               cnt--;
+       }
+}
+
+void __init sh4__flush_region_init(void)
+{
+       __flush_wback_region            = sh4__flush_wback_region;
+       __flush_invalidate_region       = sh4__flush_invalidate_region;
+       __flush_purge_region            = sh4__flush_purge_region;
+}
index fe532ae..edc842f 100644 (file)
@@ -106,27 +106,31 @@ void __init page_table_range_init(unsigned long start, unsigned long end,
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
-       int pgd_idx;
+       pte_t *pte;
+       int i, j, k;
        unsigned long vaddr;
 
-       vaddr = start & PMD_MASK;
-       end = (end + PMD_SIZE - 1) & PMD_MASK;
-       pgd_idx = pgd_index(vaddr);
-       pgd = pgd_base + pgd_idx;
-
-       for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
-               BUG_ON(pgd_none(*pgd));
-               pud = pud_offset(pgd, 0);
-               BUG_ON(pud_none(*pud));
-               pmd = pmd_offset(pud, 0);
-
-               if (!pmd_present(*pmd)) {
-                       pte_t *pte_table;
-                       pte_table = (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
-                       pmd_populate_kernel(&init_mm, pmd, pte_table);
+       vaddr = start;
+       i = __pgd_offset(vaddr);
+       j = __pud_offset(vaddr);
+       k = __pmd_offset(vaddr);
+       pgd = pgd_base + i;
+
+       for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+               pud = (pud_t *)pgd;
+               for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
+                       pmd = (pmd_t *)pud;
+                       for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
+                               if (pmd_none(*pmd)) {
+                                       pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+                                       pmd_populate_kernel(&init_mm, pmd, pte);
+                                       BUG_ON(pte != pte_offset_kernel(pmd, 0));
+                               }
+                               vaddr += PMD_SIZE;
+                       }
+                       k = 0;
                }
-
-               vaddr += PMD_SIZE;
+               j = 0;
        }
 }
 #endif /* CONFIG_MMU */
@@ -137,7 +141,7 @@ void __init page_table_range_init(unsigned long start, unsigned long end,
 void __init paging_init(void)
 {
        unsigned long max_zone_pfns[MAX_NR_ZONES];
-       unsigned long vaddr;
+       unsigned long vaddr, end;
        int nid;
 
        /* We don't need to map the kernel through the TLB, as
@@ -155,7 +159,8 @@ void __init paging_init(void)
         * pte's will be filled in by __set_fixmap().
         */
        vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-       page_table_range_init(vaddr, 0, swapper_pg_dir);
+       end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK;
+       page_table_range_init(vaddr, end, swapper_pg_dir);
 
        kmap_coherent_init();
 
@@ -210,6 +215,9 @@ void __init mem_init(void)
                        high_memory = node_high_memory;
        }
 
+       /* Set this up early, so we can take care of the zero page */
+       cpu_cache_init();
+
        /* clear the zero-page */
        memset(empty_zero_page, 0, PAGE_SIZE);
        __flush_wback_region(empty_zero_page, PAGE_SIZE);
@@ -230,8 +238,6 @@ void __init mem_init(void)
                datasize >> 10,
                initsize >> 10);
 
-       p3_cache_init();
-
        /* Initialize the vDSO */
        vsyscall_init();
 }
index da2f418..c325061 100644 (file)
@@ -57,14 +57,6 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
        if (is_pci_memory_fixed_range(phys_addr, size))
                return (void __iomem *)phys_addr;
 
-#if !defined(CONFIG_PMB_FIXED)
-       /*
-        * Don't allow anybody to remap normal RAM that we're using..
-        */
-       if (phys_addr < virt_to_phys(high_memory))
-               return NULL;
-#endif
-
        /*
         * Mappings have to be page-aligned
         */
index 828c859..b16843d 100644 (file)
@@ -94,7 +94,6 @@ static struct resource *shmedia_find_resource(struct resource *root,
 static void __iomem *shmedia_alloc_io(unsigned long phys, unsigned long size,
                                      const char *name, unsigned long flags)
 {
-       static int printed_full;
        struct xresource *xres;
        struct resource *res;
        char *tack;
@@ -108,11 +107,8 @@ static void __iomem *shmedia_alloc_io(unsigned long phys, unsigned long size,
                tack = xres->xname;
                res = &xres->xres;
        } else {
-               if (!printed_full) {
-                       printk(KERN_NOTICE "%s: done with statics, "
+               printk_once(KERN_NOTICE "%s: done with statics, "
                               "switching to kmalloc\n", __func__);
-                       printed_full = 1;
-               }
                tlen = strlen(name);
                tack = kmalloc(sizeof(struct resource) + tlen + 1, GFP_KERNEL);
                if (!tack)
diff --git a/arch/sh/mm/kmap.c b/arch/sh/mm/kmap.c
new file mode 100644 (file)
index 0000000..16e01b5
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * arch/sh/mm/kmap.c
+ *
+ * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
+ * Copyright (C) 2002 - 2009  Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/fs.h>
+#include <linux/highmem.h>
+#include <linux/module.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+#define kmap_get_fixmap_pte(vaddr)                                     \
+       pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))
+
+static pte_t *kmap_coherent_pte;
+
+void __init kmap_coherent_init(void)
+{
+       unsigned long vaddr;
+
+       /* cache the first coherent kmap pte */
+       vaddr = __fix_to_virt(FIX_CMAP_BEGIN);
+       kmap_coherent_pte = kmap_get_fixmap_pte(vaddr);
+}
+
+void *kmap_coherent(struct page *page, unsigned long addr)
+{
+       enum fixed_addresses idx;
+       unsigned long vaddr;
+
+       BUG_ON(test_bit(PG_dcache_dirty, &page->flags));
+
+       pagefault_disable();
+
+       idx = FIX_CMAP_END -
+               ((addr & current_cpu_data.dcache.alias_mask) >> PAGE_SHIFT);
+       vaddr = __fix_to_virt(idx);
+
+       BUG_ON(!pte_none(*(kmap_coherent_pte - idx)));
+       set_pte(kmap_coherent_pte - idx, mk_pte(page, PAGE_KERNEL));
+
+       return (void *)vaddr;
+}
+
+void kunmap_coherent(void *kvaddr)
+{
+       if (kvaddr >= (void *)FIXADDR_START) {
+               unsigned long vaddr = (unsigned long)kvaddr & PAGE_MASK;
+               enum fixed_addresses idx = __virt_to_fix(vaddr);
+
+               /* XXX.. Kill this later, here for sanity at the moment.. */
+               __flush_purge_region((void *)vaddr, PAGE_SIZE);
+
+               pte_clear(&init_mm, vaddr, kmap_coherent_pte - idx);
+               local_flush_tlb_one(get_asid(), vaddr);
+       }
+
+       pagefault_enable();
+}
index 1b5fdfb..d2984fa 100644 (file)
 #include <asm/page.h>
 #include <asm/processor.h>
 
-#ifdef CONFIG_MMU
 unsigned long shm_align_mask = PAGE_SIZE - 1;  /* Sane caches */
 EXPORT_SYMBOL(shm_align_mask);
 
+#ifdef CONFIG_MMU
 /*
  * To avoid cache aliases, we map the shared page with same color.
  */
similarity index 54%
rename from arch/sh/mm/tlb-nommu.c
rename to arch/sh/mm/nommu.c
index 71c742b..ac16c05 100644 (file)
@@ -1,20 +1,41 @@
 /*
- * arch/sh/mm/tlb-nommu.c
+ * arch/sh/mm/nommu.c
  *
- * TLB Operations for MMUless SH.
+ * Various helper routines and stubs for MMUless SH.
  *
- * Copyright (C) 2002 Paul Mundt
+ * Copyright (C) 2002 - 2009 Paul Mundt
  *
  * Released under the terms of the GNU GPL v2.0.
  */
 #include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
 #include <linux/mm.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
 
 /*
  * Nothing too terribly exciting here ..
  */
+void copy_page(void *to, void *from)
+{
+       memcpy(to, from, PAGE_SIZE);
+}
+
+__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n)
+{
+       memcpy(to, from, n);
+       return 0;
+}
+
+__kernel_size_t __clear_user(void *to, __kernel_size_t n)
+{
+       memset(to, 0, n);
+       return 0;
+}
+
 void local_flush_tlb_all(void)
 {
        BUG();
@@ -46,8 +67,21 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
        BUG();
 }
 
-void update_mmu_cache(struct vm_area_struct * vma,
-                     unsigned long address, pte_t pte)
+void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+{
+}
+
+void __init kmap_coherent_init(void)
+{
+}
+
+void *kmap_coherent(struct page *page, unsigned long addr)
+{
+       BUG();
+       return NULL;
+}
+
+void kunmap_coherent(void *kvaddr)
 {
        BUG();
 }
index 095d93b..9b784fd 100644 (file)
@@ -9,6 +9,7 @@
  */
 #include <linux/module.h>
 #include <linux/bootmem.h>
+#include <linux/lmb.h>
 #include <linux/mm.h>
 #include <linux/numa.h>
 #include <linux/pfn.h>
@@ -26,6 +27,15 @@ EXPORT_SYMBOL_GPL(node_data);
 void __init setup_memory(void)
 {
        unsigned long free_pfn = PFN_UP(__pa(_end));
+       u64 base = min_low_pfn << PAGE_SHIFT;
+       u64 size = (max_low_pfn << PAGE_SHIFT) - min_low_pfn;
+
+       lmb_add(base, size);
+
+       /* Reserve the LMB regions used by the kernel, initrd, etc.. */
+       lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
+                   (PFN_PHYS(free_pfn) + PAGE_SIZE - 1) -
+                   (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
 
        /*
         * Node 0 sets up its pgdat at the first available pfn,
@@ -45,24 +55,23 @@ void __init setup_memory(void)
 
 void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
 {
-       unsigned long bootmap_pages, bootmap_start, bootmap_size;
-       unsigned long start_pfn, free_pfn, end_pfn;
+       unsigned long bootmap_pages;
+       unsigned long start_pfn, end_pfn;
+       unsigned long bootmem_paddr;
 
        /* Don't allow bogus node assignment */
        BUG_ON(nid > MAX_NUMNODES || nid == 0);
 
-       /*
-        * The free pfn starts at the beginning of the range, and is
-        * advanced as necessary for pgdat and node map allocations.
-        */
-       free_pfn = start_pfn = start >> PAGE_SHIFT;
+       start_pfn = start >> PAGE_SHIFT;
        end_pfn = end >> PAGE_SHIFT;
 
+       lmb_add(start, end - start);
+
        __add_active_range(nid, start_pfn, end_pfn);
 
        /* Node-local pgdat */
-       NODE_DATA(nid) = pfn_to_kaddr(free_pfn);
-       free_pfn += PFN_UP(sizeof(struct pglist_data));
+       NODE_DATA(nid) = __va(lmb_alloc_base(sizeof(struct pglist_data),
+                                            SMP_CACHE_BYTES, end_pfn));
        memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
 
        NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
@@ -71,16 +80,17 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
 
        /* Node-local bootmap */
        bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
-       bootmap_start = (unsigned long)pfn_to_kaddr(free_pfn);
-       bootmap_size = init_bootmem_node(NODE_DATA(nid), free_pfn, start_pfn,
-                                   end_pfn);
+       bootmem_paddr = lmb_alloc_base(bootmap_pages << PAGE_SHIFT,
+                                      PAGE_SIZE, end_pfn);
+       init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
+                         start_pfn, end_pfn);
 
        free_bootmem_with_active_regions(nid, end_pfn);
 
        /* Reserve the pgdat and bootmap space with the bootmem allocator */
        reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT,
                             sizeof(struct pglist_data), BOOTMEM_DEFAULT);
-       reserve_bootmem_node(NODE_DATA(nid), free_pfn << PAGE_SHIFT,
+       reserve_bootmem_node(NODE_DATA(nid), bootmem_paddr,
                             bootmap_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
 
        /* It's up */
diff --git a/arch/sh/mm/pg-nommu.c b/arch/sh/mm/pg-nommu.c
deleted file mode 100644 (file)
index 91ed4e6..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * arch/sh/mm/pg-nommu.c
- *
- * clear_page()/copy_page() implementation for MMUless SH.
- *
- * Copyright (C) 2003  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.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <asm/page.h>
-#include <asm/uaccess.h>
-
-void copy_page(void *to, void *from)
-{
-       memcpy(to, from, PAGE_SIZE);
-}
-
-void clear_page(void *to)
-{
-       memset(to, 0, PAGE_SIZE);
-}
-
-__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n)
-{
-       memcpy(to, from, n);
-       return 0;
-}
-
-__kernel_size_t __clear_user(void *to, __kernel_size_t n)
-{
-       memset(to, 0, n);
-       return 0;
-}
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
deleted file mode 100644 (file)
index 2fe14da..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * arch/sh/mm/pg-sh4.c
- *
- * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- * Copyright (C) 2002 - 2007  Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/fs.h>
-#include <linux/highmem.h>
-#include <linux/module.h>
-#include <asm/mmu_context.h>
-#include <asm/cacheflush.h>
-
-#define CACHE_ALIAS (current_cpu_data.dcache.alias_mask)
-
-#define kmap_get_fixmap_pte(vaddr)                                     \
-       pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))
-
-static pte_t *kmap_coherent_pte;
-
-void __init kmap_coherent_init(void)
-{
-       unsigned long vaddr;
-
-       /* cache the first coherent kmap pte */
-       vaddr = __fix_to_virt(FIX_CMAP_BEGIN);
-       kmap_coherent_pte = kmap_get_fixmap_pte(vaddr);
-}
-
-static inline void *kmap_coherent(struct page *page, unsigned long addr)
-{
-       enum fixed_addresses idx;
-       unsigned long vaddr, flags;
-       pte_t pte;
-
-       inc_preempt_count();
-
-       idx = (addr & current_cpu_data.dcache.alias_mask) >> PAGE_SHIFT;
-       vaddr = __fix_to_virt(FIX_CMAP_END - idx);
-       pte = mk_pte(page, PAGE_KERNEL);
-
-       local_irq_save(flags);
-       flush_tlb_one(get_asid(), vaddr);
-       local_irq_restore(flags);
-
-       update_mmu_cache(NULL, vaddr, pte);
-
-       set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte);
-
-       return (void *)vaddr;
-}
-
-static inline void kunmap_coherent(struct page *page)
-{
-       dec_preempt_count();
-       preempt_check_resched();
-}
-
-/*
- * clear_user_page
- * @to: P1 address
- * @address: U0 address to be mapped
- * @page: page (virt_to_page(to))
- */
-void clear_user_page(void *to, unsigned long address, struct page *page)
-{
-       __set_bit(PG_mapped, &page->flags);
-
-       clear_page(to);
-       if ((((address & PAGE_MASK) ^ (unsigned long)to) & CACHE_ALIAS))
-               __flush_wback_region(to, PAGE_SIZE);
-}
-
-void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
-                      unsigned long vaddr, void *dst, const void *src,
-                      unsigned long len)
-{
-       void *vto;
-
-       __set_bit(PG_mapped, &page->flags);
-
-       vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
-       memcpy(vto, src, len);
-       kunmap_coherent(vto);
-
-       if (vma->vm_flags & VM_EXEC)
-               flush_cache_page(vma, vaddr, page_to_pfn(page));
-}
-
-void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
-                        unsigned long vaddr, void *dst, const void *src,
-                        unsigned long len)
-{
-       void *vfrom;
-
-       __set_bit(PG_mapped, &page->flags);
-
-       vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
-       memcpy(dst, vfrom, len);
-       kunmap_coherent(vfrom);
-}
-
-void copy_user_highpage(struct page *to, struct page *from,
-                       unsigned long vaddr, struct vm_area_struct *vma)
-{
-       void *vfrom, *vto;
-
-       __set_bit(PG_mapped, &to->flags);
-
-       vto = kmap_atomic(to, KM_USER1);
-       vfrom = kmap_coherent(from, vaddr);
-       copy_page(vto, vfrom);
-       kunmap_coherent(vfrom);
-
-       if (((vaddr ^ (unsigned long)vto) & CACHE_ALIAS))
-               __flush_wback_region(vto, PAGE_SIZE);
-
-       kunmap_atomic(vto, KM_USER1);
-       /* Make sure this page is cleared on other CPU's too before using it */
-       smp_wmb();
-}
-EXPORT_SYMBOL(copy_user_highpage);
-
-/*
- * For SH-4, we have our own implementation for ptep_get_and_clear
- */
-pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-       pte_t pte = *ptep;
-
-       pte_clear(mm, addr, ptep);
-       if (!pte_not_present(pte)) {
-               unsigned long pfn = pte_pfn(pte);
-               if (pfn_valid(pfn)) {
-                       struct page *page = pfn_to_page(pfn);
-                       struct address_space *mapping = page_mapping(page);
-                       if (!mapping || !mapping_writably_mapped(mapping))
-                               __clear_bit(PG_mapped, &page->flags);
-               }
-       }
-       return pte;
-}
diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c
deleted file mode 100644 (file)
index eaf2514..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * arch/sh/mm/pg-sh7705.c
- *
- * Copyright (C) 1999, 2000  Niibe Yutaka
- * Copyright (C) 2004  Alex Song
- *
- * 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.
- *
- */
-
-#include <linux/init.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/threads.h>
-#include <linux/fs.h>
-#include <asm/addrspace.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/cache.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
-#include <asm/mmu_context.h>
-#include <asm/cacheflush.h>
-
-static inline void __flush_purge_virtual_region(void *p1, void *virt, int size)
-{
-       unsigned long v;
-       unsigned long begin, end;
-       unsigned long p1_begin;
-
-
-       begin = L1_CACHE_ALIGN((unsigned long)virt);
-       end = L1_CACHE_ALIGN((unsigned long)virt + size);
-
-       p1_begin = (unsigned long)p1 & ~(L1_CACHE_BYTES - 1);
-
-       /* do this the slow way as we may not have TLB entries
-        * for virt yet. */
-       for (v = begin; v < end; v += L1_CACHE_BYTES) {
-               unsigned long p;
-               unsigned long ways, addr;
-
-               p = __pa(p1_begin);
-
-               ways = current_cpu_data.dcache.ways;
-               addr = CACHE_OC_ADDRESS_ARRAY;
-
-               do {
-                       unsigned long data;
-
-                       addr |= (v & current_cpu_data.dcache.entry_mask);
-
-                       data = ctrl_inl(addr);
-                       if ((data & CACHE_PHYSADDR_MASK) ==
-                              (p & CACHE_PHYSADDR_MASK)) {
-                               data &= ~(SH_CACHE_UPDATED|SH_CACHE_VALID);
-                               ctrl_outl(data, addr);
-                       }
-
-                       addr += current_cpu_data.dcache.way_incr;
-               } while (--ways);
-
-               p1_begin += L1_CACHE_BYTES;
-       }
-}
-
-/*
- * clear_user_page
- * @to: P1 address
- * @address: U0 address to be mapped
- */
-void clear_user_page(void *to, unsigned long address, struct page *pg)
-{
-       struct page *page = virt_to_page(to);
-
-       __set_bit(PG_mapped, &page->flags);
-       if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
-               clear_page(to);
-               __flush_wback_region(to, PAGE_SIZE);
-       } else {
-               __flush_purge_virtual_region(to,
-                                            (void *)(address & 0xfffff000),
-                                            PAGE_SIZE);
-               clear_page(to);
-               __flush_wback_region(to, PAGE_SIZE);
-       }
-}
-
-/*
- * copy_user_page
- * @to: P1 address
- * @from: P1 address
- * @address: U0 address to be mapped
- */
-void copy_user_page(void *to, void *from, unsigned long address, struct page *pg)
-{
-       struct page *page = virt_to_page(to);
-
-
-       __set_bit(PG_mapped, &page->flags);
-       if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
-               copy_page(to, from);
-               __flush_wback_region(to, PAGE_SIZE);
-       } else {
-               __flush_purge_virtual_region(to,
-                                            (void *)(address & 0xfffff000),
-                                            PAGE_SIZE);
-               copy_page(to, from);
-               __flush_wback_region(to, PAGE_SIZE);
-       }
-}
-
-/*
- * For SH7705, we have our own implementation for ptep_get_and_clear
- * Copied from pg-sh4.c
- */
-pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-       pte_t pte = *ptep;
-
-       pte_clear(mm, addr, ptep);
-       if (!pte_not_present(pte)) {
-               unsigned long pfn = pte_pfn(pte);
-               if (pfn_valid(pfn)) {
-                       struct page *page = pfn_to_page(pfn);
-                       struct address_space *mapping = page_mapping(page);
-                       if (!mapping || !mapping_writably_mapped(mapping))
-                               __clear_bit(PG_mapped, &page->flags);
-               }
-       }
-
-       return pte;
-}
-
index 2aab3ea..409b7c2 100644 (file)
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
-void update_mmu_cache(struct vm_area_struct * vma,
-                     unsigned long address, pte_t pte)
+void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
-       unsigned long flags;
-       unsigned long pteval;
-       unsigned long vpn;
+       unsigned long flags, pteval, vpn;
 
-       /* Ptrace may call this routine. */
+       /*
+        * Handle debugger faulting in for debugee.
+        */
        if (vma && current->active_mm != vma->vm_mm)
                return;
 
-#ifndef CONFIG_CACHE_OFF
-       {
-               unsigned long pfn = pte_pfn(pte);
-
-               if (pfn_valid(pfn)) {
-                       struct page *page = pfn_to_page(pfn);
-
-                       if (!test_bit(PG_mapped, &page->flags)) {
-                               unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
-                               __flush_wback_region((void *)P1SEGADDR(phys),
-                                                    PAGE_SIZE);
-                               __set_bit(PG_mapped, &page->flags);
-                       }
-               }
-       }
-#endif
-
        local_irq_save(flags);
 
        /* Set PTEH register */
index 17cb7c3..ace8e6d 100644 (file)
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
-void update_mmu_cache(struct vm_area_struct * vma,
-                     unsigned long address, pte_t pte)
+void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
-       unsigned long flags;
-       unsigned long pteval;
-       unsigned long vpn;
+       unsigned long flags, pteval, vpn;
 
-       /* Ptrace may call this routine. */
+       /*
+        * Handle debugger faulting in for debugee.
+        */
        if (vma && current->active_mm != vma->vm_mm)
                return;
 
-#if defined(CONFIG_SH7705_CACHE_32KB)
-       {
-               struct page *page = pte_page(pte);
-               unsigned long pfn = pte_pfn(pte);
-
-               if (pfn_valid(pfn) && !test_bit(PG_mapped, &page->flags)) {
-                       unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
-
-                       __flush_wback_region((void *)P1SEGADDR(phys),
-                                            PAGE_SIZE);
-                       __set_bit(PG_mapped, &page->flags);
-               }
-       }
-#endif
-
        local_irq_save(flags);
 
        /* Set PTEH register */
@@ -93,4 +77,3 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page)
        for (i = 0; i < ways; i++)
                ctrl_outl(data, addr + (i << 8));
 }
-
index f0c7b73..8cf550e 100644 (file)
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
-void update_mmu_cache(struct vm_area_struct * vma,
-                     unsigned long address, pte_t pte)
+void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
-       unsigned long flags;
-       unsigned long pteval;
-       unsigned long vpn;
+       unsigned long flags, pteval, vpn;
 
-       /* Ptrace may call this routine. */
+       /*
+        * Handle debugger faulting in for debugee.
+        */
        if (vma && current->active_mm != vma->vm_mm)
                return;
 
-#ifndef CONFIG_CACHE_OFF
-       {
-               unsigned long pfn = pte_pfn(pte);
-
-               if (pfn_valid(pfn)) {
-                       struct page *page = pfn_to_page(pfn);
-
-                       if (!test_bit(PG_mapped, &page->flags)) {
-                               unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
-                               __flush_wback_region((void *)P1SEGADDR(phys),
-                                                    PAGE_SIZE);
-                               __set_bit(PG_mapped, &page->flags);
-                       }
-               }
-       }
-#endif
-
        local_irq_save(flags);
 
        /* Set PTEH register */
@@ -61,9 +43,12 @@ void update_mmu_cache(struct vm_area_struct * vma,
         */
        ctrl_outl(pte.pte_high, MMU_PTEA);
 #else
-       if (cpu_data->flags & CPU_HAS_PTEA)
-               /* TODO: make this look less hacky */
-               ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA);
+       if (cpu_data->flags & CPU_HAS_PTEA) {
+               /* The last 3 bits and the first one of pteval contains
+                * the PTEA timing control and space attribute bits
+                */
+               ctrl_outl(copy_ptea_attributes(pteval), MMU_PTEA);
+       }
 #endif
 
        /* Set PTEL register */
index dae1312..fdb64e4 100644 (file)
@@ -117,26 +117,15 @@ int sh64_put_wired_dtlb_entry(unsigned long long entry)
  * Load up a virtual<->physical translation for @eaddr<->@paddr in the
  * pre-allocated TLB slot @config_addr (see sh64_get_wired_dtlb_entry).
  */
-inline void sh64_setup_tlb_slot(unsigned long long config_addr,
-                               unsigned long eaddr,
-                               unsigned long asid,
-                               unsigned long paddr)
+void sh64_setup_tlb_slot(unsigned long long config_addr, unsigned long eaddr,
+                        unsigned long asid, unsigned long paddr)
 {
        unsigned long long pteh, ptel;
 
-       /* Sign extension */
-#if (NEFF == 32)
-       pteh = (unsigned long long)(signed long long)(signed long) eaddr;
-#else
-#error "Can't sign extend more than 32 bits yet"
-#endif
+       pteh = neff_sign_extend(eaddr);
        pteh &= PAGE_MASK;
        pteh |= (asid << PTEH_ASID_SHIFT) | PTEH_VALID;
-#if (NEFF == 32)
-       ptel = (unsigned long long)(signed long long)(signed long) paddr;
-#else
-#error "Can't sign extend more than 32 bits yet"
-#endif
+       ptel = neff_sign_extend(paddr);
        ptel &= PAGE_MASK;
        ptel |= (_PAGE_CACHABLE | _PAGE_READ | _PAGE_WRITE);
 
@@ -152,5 +141,5 @@ inline void sh64_setup_tlb_slot(unsigned long long config_addr,
  *
  * Teardown any existing mapping in the TLB slot @config_addr.
  */
-inline void sh64_teardown_tlb_slot(unsigned long long config_addr)
+void sh64_teardown_tlb_slot(unsigned long long config_addr)
        __attribute__ ((alias("__flush_tlb_slot")));
index 3ce40ea..2dcc485 100644 (file)
@@ -329,22 +329,6 @@ do_sigbus:
                goto no_context;
 }
 
-void update_mmu_cache(struct vm_area_struct * vma,
-                       unsigned long address, pte_t pte)
-{
-       /*
-        * This appears to get called once for every pte entry that gets
-        * established => I don't think it's efficient to try refilling the
-        * TLBs with the pages - some may not get accessed even.  Also, for
-        * executable pages, it is impossible to determine reliably here which
-        * TLB they should be mapped into (or both even).
-        *
-        * So, just do nothing here and handle faults on demand.  In the
-        * TLBMISS handling case, the refill is now done anyway after the pte
-        * has been fixed up, so that deals with most useful cases.
-        */
-}
-
 void local_flush_tlb_one(unsigned long asid, unsigned long page)
 {
        unsigned long long match, pteh=0, lpage;
@@ -353,7 +337,7 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page)
        /*
         * Sign-extend based on neff.
         */
-       lpage = (page & NEFF_SIGN) ? (page | NEFF_MASK) : page;
+       lpage = neff_sign_extend(page);
        match = (asid << PTEH_ASID_SHIFT) | PTEH_VALID;
        match |= lpage;
 
@@ -482,3 +466,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
         /* FIXME: Optimize this later.. */
         flush_tlb_all();
 }
+
+void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+{
+}
index 9499a29..2bc74de 100644 (file)
 #include <linux/sched.h>
 #include <linux/kallsyms.h>
 #include <linux/mm.h>
+#include <asm/unwinder.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 #include <asm/sections.h>
+#include <asm/stacktrace.h>
+
+static void backtrace_warning_symbol(void *data, char *msg,
+                                    unsigned long symbol)
+{
+       /* Ignore warnings */
+}
+
+static void backtrace_warning(void *data, char *msg)
+{
+       /* Ignore warnings */
+}
+
+static int backtrace_stack(void *data, char *name)
+{
+       /* Yes, we want all stacks */
+       return 0;
+}
+
+static void backtrace_address(void *data, unsigned long addr, int reliable)
+{
+       unsigned int *depth = data;
+
+       if ((*depth)--)
+               oprofile_add_trace(addr);
+}
+
+static struct stacktrace_ops backtrace_ops = {
+       .warning = backtrace_warning,
+       .warning_symbol = backtrace_warning_symbol,
+       .stack = backtrace_stack,
+       .address = backtrace_address,
+};
 
 /* Limit to stop backtracing too far. */
 static int backtrace_limit = 20;
@@ -47,50 +81,6 @@ user_backtrace(unsigned long *stackaddr, struct pt_regs *regs)
        return stackaddr;
 }
 
-/*
- * |             | /\ Higher addresses
- * |             |
- * --------------- stack base (address of current_thread_info)
- * | thread info |
- * .             .
- * |    stack    |
- * --------------- saved regs->regs[15] value if valid
- * .             .
- * --------------- struct pt_regs stored on stack (struct pt_regs *)
- * |             |
- * .             .
- * |             |
- * --------------- ???
- * |             |
- * |             | \/ Lower addresses
- *
- * Thus, &pt_regs <-> stack base restricts the valid(ish) fp values
- */
-static int valid_kernel_stack(unsigned long *stackaddr, struct pt_regs *regs)
-{
-       unsigned long stack = (unsigned long)regs;
-       unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE;
-
-       return ((unsigned long)stackaddr > stack) && ((unsigned long)stackaddr < stack_base);
-}
-
-static unsigned long *
-kernel_backtrace(unsigned long *stackaddr, struct pt_regs *regs)
-{
-       unsigned long addr;
-
-       /*
-        * If not a valid kernel address, keep going till we find one
-        * or the SP stops being a valid address.
-        */
-       do {
-               addr = *stackaddr++;
-               oprofile_add_trace(addr);
-       } while (valid_kernel_stack(stackaddr, regs));
-
-       return stackaddr;
-}
-
 void sh_backtrace(struct pt_regs * const regs, unsigned int depth)
 {
        unsigned long *stackaddr;
@@ -103,9 +93,9 @@ void sh_backtrace(struct pt_regs * const regs, unsigned int depth)
 
        stackaddr = (unsigned long *)regs->regs[15];
        if (!user_mode(regs)) {
-               while (depth-- && valid_kernel_stack(stackaddr, regs))
-                       stackaddr = kernel_backtrace(stackaddr, regs);
-
+               if (depth)
+                       unwind_stack(NULL, regs, stackaddr,
+                                    &backtrace_ops, &depth);
                return;
        }
 
index fec3a53..6639b25 100644 (file)
@@ -53,6 +53,9 @@ RSK7203                       SH_RSK7203
 AP325RXA               SH_AP325RXA
 SH7763RDP              SH_SH7763RDP
 SH7785LCR              SH_SH7785LCR
+SH7785LCR_PT           SH_SH7785LCR_PT
 URQUELL                        SH_URQUELL
 ESPT                   SH_ESPT
 POLARIS                        SH_POLARIS
+KFR2R09                        SH_KFR2R09
+ECOVEC                 SH_ECOVEC
index 3702e08..f3b85b6 100644 (file)
@@ -32,4 +32,7 @@ dev_archdata_get_node(const struct dev_archdata *ad)
        return ad->prom_node;
 }
 
+struct pdev_archdata {
+};
+
 #endif /* _ASM_SPARC_DEVICE_H */
index 4994a20..cee34e9 100644 (file)
@@ -13,4 +13,7 @@ struct dma_map_ops *dma_ops;
 #endif
 };
 
+struct pdev_archdata {
+};
+
 #endif /* _ASM_X86_DEVICE_H */
index f010687..7b34b3a 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/kthread.h>
 #include <linux/wait.h>
 #include <linux/async.h>
+#include <linux/pm_runtime.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -202,7 +203,10 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
        pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
                 drv->bus->name, __func__, dev_name(dev), drv->name);
 
+       pm_runtime_get_noresume(dev);
+       pm_runtime_barrier(dev);
        ret = really_probe(dev, drv);
+       pm_runtime_put_sync(dev);
 
        return ret;
 }
@@ -245,7 +249,9 @@ int device_attach(struct device *dev)
                        ret = 0;
                }
        } else {
+               pm_runtime_get_noresume(dev);
                ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
+               pm_runtime_put_sync(dev);
        }
        up(&dev->sem);
        return ret;
@@ -306,6 +312,9 @@ static void __device_release_driver(struct device *dev)
 
        drv = dev->driver;
        if (drv) {
+               pm_runtime_get_noresume(dev);
+               pm_runtime_barrier(dev);
+
                driver_sysfs_remove(dev);
 
                if (dev->bus)
@@ -324,6 +333,8 @@ static void __device_release_driver(struct device *dev)
                        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                                     BUS_NOTIFY_UNBOUND_DRIVER,
                                                     dev);
+
+               pm_runtime_put_sync(dev);
        }
 }
 
index 456594b..0f7d434 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/bootmem.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 
 #include "base.h"
 
@@ -625,30 +626,6 @@ static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
        return ret;
 }
 
-static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg)
-{
-       struct platform_driver *pdrv = to_platform_driver(dev->driver);
-       struct platform_device *pdev = to_platform_device(dev);
-       int ret = 0;
-
-       if (dev->driver && pdrv->suspend_late)
-               ret = pdrv->suspend_late(pdev, mesg);
-
-       return ret;
-}
-
-static int platform_legacy_resume_early(struct device *dev)
-{
-       struct platform_driver *pdrv = to_platform_driver(dev->driver);
-       struct platform_device *pdev = to_platform_device(dev);
-       int ret = 0;
-
-       if (dev->driver && pdrv->resume_early)
-               ret = pdrv->resume_early(pdev);
-
-       return ret;
-}
-
 static int platform_legacy_resume(struct device *dev)
 {
        struct platform_driver *pdrv = to_platform_driver(dev->driver);
@@ -680,6 +657,13 @@ static void platform_pm_complete(struct device *dev)
                drv->pm->complete(dev);
 }
 
+#else /* !CONFIG_PM_SLEEP */
+
+#define platform_pm_prepare            NULL
+#define platform_pm_complete           NULL
+
+#endif /* !CONFIG_PM_SLEEP */
+
 #ifdef CONFIG_SUSPEND
 
 static int platform_pm_suspend(struct device *dev)
@@ -711,8 +695,6 @@ static int platform_pm_suspend_noirq(struct device *dev)
        if (drv->pm) {
                if (drv->pm->suspend_noirq)
                        ret = drv->pm->suspend_noirq(dev);
-       } else {
-               ret = platform_legacy_suspend_late(dev, PMSG_SUSPEND);
        }
 
        return ret;
@@ -747,8 +729,6 @@ static int platform_pm_resume_noirq(struct device *dev)
        if (drv->pm) {
                if (drv->pm->resume_noirq)
                        ret = drv->pm->resume_noirq(dev);
-       } else {
-               ret = platform_legacy_resume_early(dev);
        }
 
        return ret;
@@ -794,8 +774,6 @@ static int platform_pm_freeze_noirq(struct device *dev)
        if (drv->pm) {
                if (drv->pm->freeze_noirq)
                        ret = drv->pm->freeze_noirq(dev);
-       } else {
-               ret = platform_legacy_suspend_late(dev, PMSG_FREEZE);
        }
 
        return ret;
@@ -830,8 +808,6 @@ static int platform_pm_thaw_noirq(struct device *dev)
        if (drv->pm) {
                if (drv->pm->thaw_noirq)
                        ret = drv->pm->thaw_noirq(dev);
-       } else {
-               ret = platform_legacy_resume_early(dev);
        }
 
        return ret;
@@ -866,8 +842,6 @@ static int platform_pm_poweroff_noirq(struct device *dev)
        if (drv->pm) {
                if (drv->pm->poweroff_noirq)
                        ret = drv->pm->poweroff_noirq(dev);
-       } else {
-               ret = platform_legacy_suspend_late(dev, PMSG_HIBERNATE);
        }
 
        return ret;
@@ -902,8 +876,6 @@ static int platform_pm_restore_noirq(struct device *dev)
        if (drv->pm) {
                if (drv->pm->restore_noirq)
                        ret = drv->pm->restore_noirq(dev);
-       } else {
-               ret = platform_legacy_resume_early(dev);
        }
 
        return ret;
@@ -922,7 +894,32 @@ static int platform_pm_restore_noirq(struct device *dev)
 
 #endif /* !CONFIG_HIBERNATION */
 
-static struct dev_pm_ops platform_dev_pm_ops = {
+#ifdef CONFIG_PM_RUNTIME
+
+int __weak platform_pm_runtime_suspend(struct device *dev)
+{
+       return -ENOSYS;
+};
+
+int __weak platform_pm_runtime_resume(struct device *dev)
+{
+       return -ENOSYS;
+};
+
+int __weak platform_pm_runtime_idle(struct device *dev)
+{
+       return -ENOSYS;
+};
+
+#else /* !CONFIG_PM_RUNTIME */
+
+#define platform_pm_runtime_suspend NULL
+#define platform_pm_runtime_resume NULL
+#define platform_pm_runtime_idle NULL
+
+#endif /* !CONFIG_PM_RUNTIME */
+
+static const struct dev_pm_ops platform_dev_pm_ops = {
        .prepare = platform_pm_prepare,
        .complete = platform_pm_complete,
        .suspend = platform_pm_suspend,
@@ -937,22 +934,17 @@ static struct dev_pm_ops platform_dev_pm_ops = {
        .thaw_noirq = platform_pm_thaw_noirq,
        .poweroff_noirq = platform_pm_poweroff_noirq,
        .restore_noirq = platform_pm_restore_noirq,
+       .runtime_suspend = platform_pm_runtime_suspend,
+       .runtime_resume = platform_pm_runtime_resume,
+       .runtime_idle = platform_pm_runtime_idle,
 };
 
-#define PLATFORM_PM_OPS_PTR    (&platform_dev_pm_ops)
-
-#else /* !CONFIG_PM_SLEEP */
-
-#define PLATFORM_PM_OPS_PTR    NULL
-
-#endif /* !CONFIG_PM_SLEEP */
-
 struct bus_type platform_bus_type = {
        .name           = "platform",
        .dev_attrs      = platform_dev_attrs,
        .match          = platform_match,
        .uevent         = platform_uevent,
-       .pm             = PLATFORM_PM_OPS_PTR,
+       .pm             = &platform_dev_pm_ops,
 };
 EXPORT_SYMBOL_GPL(platform_bus_type);
 
index 911208b..3ce3519 100644 (file)
@@ -1,5 +1,6 @@
 obj-$(CONFIG_PM)       += sysfs.o
 obj-$(CONFIG_PM_SLEEP) += main.o
+obj-$(CONFIG_PM_RUNTIME)       += runtime.o
 obj-$(CONFIG_PM_TRACE_RTC)     += trace.o
 
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
index 58a3e57..8699001 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/kallsyms.h>
 #include <linux/mutex.h>
 #include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/resume-trace.h>
 #include <linux/rwsem.h>
 #include <linux/interrupt.h>
@@ -48,6 +49,16 @@ static DEFINE_MUTEX(dpm_list_mtx);
  */
 static bool transition_started;
 
+/**
+ * device_pm_init - Initialize the PM-related part of a device object
+ * @dev: Device object being initialized.
+ */
+void device_pm_init(struct device *dev)
+{
+       dev->power.status = DPM_ON;
+       pm_runtime_init(dev);
+}
+
 /**
  *     device_pm_lock - lock the list of active devices used by the PM core
  */
@@ -105,6 +116,7 @@ void device_pm_remove(struct device *dev)
        mutex_lock(&dpm_list_mtx);
        list_del_init(&dev->power.entry);
        mutex_unlock(&dpm_list_mtx);
+       pm_runtime_remove(dev);
 }
 
 /**
@@ -157,8 +169,9 @@ void device_pm_move_last(struct device *dev)
  *     @ops:   PM operations to choose from.
  *     @state: PM transition of the system being carried out.
  */
-static int pm_op(struct device *dev, struct dev_pm_ops *ops,
-                       pm_message_t state)
+static int pm_op(struct device *dev,
+                const struct dev_pm_ops *ops,
+                pm_message_t state)
 {
        int error = 0;
 
@@ -220,7 +233,8 @@ static int pm_op(struct device *dev, struct dev_pm_ops *ops,
  *     The operation is executed with interrupts disabled by the only remaining
  *     functional CPU in the system.
  */
-static int pm_noirq_op(struct device *dev, struct dev_pm_ops *ops,
+static int pm_noirq_op(struct device *dev,
+                       const struct dev_pm_ops *ops,
                        pm_message_t state)
 {
        int error = 0;
@@ -510,6 +524,7 @@ static void dpm_complete(pm_message_t state)
                        mutex_unlock(&dpm_list_mtx);
 
                        device_complete(dev, state);
+                       pm_runtime_put_noidle(dev);
 
                        mutex_lock(&dpm_list_mtx);
                }
@@ -755,7 +770,14 @@ static int dpm_prepare(pm_message_t state)
                dev->power.status = DPM_PREPARING;
                mutex_unlock(&dpm_list_mtx);
 
-               error = device_prepare(dev, state);
+               pm_runtime_get_noresume(dev);
+               if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) {
+                       /* Wake-up requested during system sleep transition. */
+                       pm_runtime_put_noidle(dev);
+                       error = -EBUSY;
+               } else {
+                       error = device_prepare(dev, state);
+               }
 
                mutex_lock(&dpm_list_mtx);
                if (error) {
index c7cb4fc..b8fa1aa 100644 (file)
@@ -1,7 +1,14 @@
-static inline void device_pm_init(struct device *dev)
-{
-       dev->power.status = DPM_ON;
-}
+#ifdef CONFIG_PM_RUNTIME
+
+extern void pm_runtime_init(struct device *dev);
+extern void pm_runtime_remove(struct device *dev);
+
+#else /* !CONFIG_PM_RUNTIME */
+
+static inline void pm_runtime_init(struct device *dev) {}
+static inline void pm_runtime_remove(struct device *dev) {}
+
+#endif /* !CONFIG_PM_RUNTIME */
 
 #ifdef CONFIG_PM_SLEEP
 
@@ -16,23 +23,33 @@ static inline struct device *to_device(struct list_head *entry)
        return container_of(entry, struct device, power.entry);
 }
 
+extern void device_pm_init(struct device *dev);
 extern void device_pm_add(struct device *);
 extern void device_pm_remove(struct device *);
 extern void device_pm_move_before(struct device *, struct device *);
 extern void device_pm_move_after(struct device *, struct device *);
 extern void device_pm_move_last(struct device *);
 
-#else /* CONFIG_PM_SLEEP */
+#else /* !CONFIG_PM_SLEEP */
+
+static inline void device_pm_init(struct device *dev)
+{
+       pm_runtime_init(dev);
+}
+
+static inline void device_pm_remove(struct device *dev)
+{
+       pm_runtime_remove(dev);
+}
 
 static inline void device_pm_add(struct device *dev) {}
-static inline void device_pm_remove(struct device *dev) {}
 static inline void device_pm_move_before(struct device *deva,
                                         struct device *devb) {}
 static inline void device_pm_move_after(struct device *deva,
                                        struct device *devb) {}
 static inline void device_pm_move_last(struct device *dev) {}
 
-#endif
+#endif /* !CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_PM
 
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
new file mode 100644 (file)
index 0000000..38556f6
--- /dev/null
@@ -0,0 +1,1011 @@
+/*
+ * drivers/base/power/runtime.c - Helper functions for device run-time PM
+ *
+ * Copyright (c) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/sched.h>
+#include <linux/pm_runtime.h>
+#include <linux/jiffies.h>
+
+static int __pm_runtime_resume(struct device *dev, bool from_wq);
+static int __pm_request_idle(struct device *dev);
+static int __pm_request_resume(struct device *dev);
+
+/**
+ * pm_runtime_deactivate_timer - Deactivate given device's suspend timer.
+ * @dev: Device to handle.
+ */
+static void pm_runtime_deactivate_timer(struct device *dev)
+{
+       if (dev->power.timer_expires > 0) {
+               del_timer(&dev->power.suspend_timer);
+               dev->power.timer_expires = 0;
+       }
+}
+
+/**
+ * pm_runtime_cancel_pending - Deactivate suspend timer and cancel requests.
+ * @dev: Device to handle.
+ */
+static void pm_runtime_cancel_pending(struct device *dev)
+{
+       pm_runtime_deactivate_timer(dev);
+       /*
+        * In case there's a request pending, make sure its work function will
+        * return without doing anything.
+        */
+       dev->power.request = RPM_REQ_NONE;
+}
+
+/**
+ * __pm_runtime_idle - Notify device bus type if the device can be suspended.
+ * @dev: Device to notify the bus type about.
+ *
+ * This function must be called under dev->power.lock with interrupts disabled.
+ */
+static int __pm_runtime_idle(struct device *dev)
+       __releases(&dev->power.lock) __acquires(&dev->power.lock)
+{
+       int retval = 0;
+
+       dev_dbg(dev, "__pm_runtime_idle()!\n");
+
+       if (dev->power.runtime_error)
+               retval = -EINVAL;
+       else if (dev->power.idle_notification)
+               retval = -EINPROGRESS;
+       else if (atomic_read(&dev->power.usage_count) > 0
+           || dev->power.disable_depth > 0
+           || dev->power.runtime_status != RPM_ACTIVE)
+               retval = -EAGAIN;
+       else if (!pm_children_suspended(dev))
+               retval = -EBUSY;
+       if (retval)
+               goto out;
+
+       if (dev->power.request_pending) {
+               /*
+                * If an idle notification request is pending, cancel it.  Any
+                * other pending request takes precedence over us.
+                */
+               if (dev->power.request == RPM_REQ_IDLE) {
+                       dev->power.request = RPM_REQ_NONE;
+               } else if (dev->power.request != RPM_REQ_NONE) {
+                       retval = -EAGAIN;
+                       goto out;
+               }
+       }
+
+       dev->power.idle_notification = true;
+
+       if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) {
+               spin_unlock_irq(&dev->power.lock);
+
+               dev->bus->pm->runtime_idle(dev);
+
+               spin_lock_irq(&dev->power.lock);
+       }
+
+       dev->power.idle_notification = false;
+       wake_up_all(&dev->power.wait_queue);
+
+ out:
+       dev_dbg(dev, "__pm_runtime_idle() returns %d!\n", retval);
+
+       return retval;
+}
+
+/**
+ * pm_runtime_idle - Notify device bus type if the device can be suspended.
+ * @dev: Device to notify the bus type about.
+ */
+int pm_runtime_idle(struct device *dev)
+{
+       int retval;
+
+       spin_lock_irq(&dev->power.lock);
+       retval = __pm_runtime_idle(dev);
+       spin_unlock_irq(&dev->power.lock);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(pm_runtime_idle);
+
+/**
+ * __pm_runtime_suspend - Carry out run-time suspend of given device.
+ * @dev: Device to suspend.
+ * @from_wq: If set, the function has been called via pm_wq.
+ *
+ * Check if the device can be suspended and run the ->runtime_suspend() callback
+ * provided by its bus type.  If another suspend has been started earlier, wait
+ * for it to finish.  If an idle notification or suspend request is pending or
+ * scheduled, cancel it.
+ *
+ * This function must be called under dev->power.lock with interrupts disabled.
+ */
+int __pm_runtime_suspend(struct device *dev, bool from_wq)
+       __releases(&dev->power.lock) __acquires(&dev->power.lock)
+{
+       struct device *parent = NULL;
+       bool notify = false;
+       int retval = 0;
+
+       dev_dbg(dev, "__pm_runtime_suspend()%s!\n",
+               from_wq ? " from workqueue" : "");
+
+ repeat:
+       if (dev->power.runtime_error) {
+               retval = -EINVAL;
+               goto out;
+       }
+
+       /* Pending resume requests take precedence over us. */
+       if (dev->power.request_pending
+           && dev->power.request == RPM_REQ_RESUME) {
+               retval = -EAGAIN;
+               goto out;
+       }
+
+       /* Other scheduled or pending requests need to be canceled. */
+       pm_runtime_cancel_pending(dev);
+
+       if (dev->power.runtime_status == RPM_SUSPENDED)
+               retval = 1;
+       else if (dev->power.runtime_status == RPM_RESUMING
+           || dev->power.disable_depth > 0
+           || atomic_read(&dev->power.usage_count) > 0)
+               retval = -EAGAIN;
+       else if (!pm_children_suspended(dev))
+               retval = -EBUSY;
+       if (retval)
+               goto out;
+
+       if (dev->power.runtime_status == RPM_SUSPENDING) {
+               DEFINE_WAIT(wait);
+
+               if (from_wq) {
+                       retval = -EINPROGRESS;
+                       goto out;
+               }
+
+               /* Wait for the other suspend running in parallel with us. */
+               for (;;) {
+                       prepare_to_wait(&dev->power.wait_queue, &wait,
+                                       TASK_UNINTERRUPTIBLE);
+                       if (dev->power.runtime_status != RPM_SUSPENDING)
+                               break;
+
+                       spin_unlock_irq(&dev->power.lock);
+
+                       schedule();
+
+                       spin_lock_irq(&dev->power.lock);
+               }
+               finish_wait(&dev->power.wait_queue, &wait);
+               goto repeat;
+       }
+
+       dev->power.runtime_status = RPM_SUSPENDING;
+
+       if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
+               spin_unlock_irq(&dev->power.lock);
+
+               retval = dev->bus->pm->runtime_suspend(dev);
+
+               spin_lock_irq(&dev->power.lock);
+               dev->power.runtime_error = retval;
+       } else {
+               retval = -ENOSYS;
+       }
+
+       if (retval) {
+               dev->power.runtime_status = RPM_ACTIVE;
+               pm_runtime_cancel_pending(dev);
+               dev->power.deferred_resume = false;
+
+               if (retval == -EAGAIN || retval == -EBUSY) {
+                       notify = true;
+                       dev->power.runtime_error = 0;
+               }
+       } else {
+               dev->power.runtime_status = RPM_SUSPENDED;
+
+               if (dev->parent) {
+                       parent = dev->parent;
+                       atomic_add_unless(&parent->power.child_count, -1, 0);
+               }
+       }
+       wake_up_all(&dev->power.wait_queue);
+
+       if (dev->power.deferred_resume) {
+               dev->power.deferred_resume = false;
+               __pm_runtime_resume(dev, false);
+               retval = -EAGAIN;
+               goto out;
+       }
+
+       if (notify)
+               __pm_runtime_idle(dev);
+
+       if (parent && !parent->power.ignore_children) {
+               spin_unlock_irq(&dev->power.lock);
+
+               pm_request_idle(parent);
+
+               spin_lock_irq(&dev->power.lock);
+       }
+
+ out:
+       dev_dbg(dev, "__pm_runtime_suspend() returns %d!\n", retval);
+
+       return retval;
+}
+
+/**
+ * pm_runtime_suspend - Carry out run-time suspend of given device.
+ * @dev: Device to suspend.
+ */
+int pm_runtime_suspend(struct device *dev)
+{
+       int retval;
+
+       spin_lock_irq(&dev->power.lock);
+       retval = __pm_runtime_suspend(dev, false);
+       spin_unlock_irq(&dev->power.lock);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(pm_runtime_suspend);
+
+/**
+ * __pm_runtime_resume - Carry out run-time resume of given device.
+ * @dev: Device to resume.
+ * @from_wq: If set, the function has been called via pm_wq.
+ *
+ * Check if the device can be woken up and run the ->runtime_resume() callback
+ * provided by its bus type.  If another resume has been started earlier, wait
+ * for it to finish.  If there's a suspend running in parallel with this
+ * function, wait for it to finish and resume the device.  Cancel any scheduled
+ * or pending requests.
+ *
+ * This function must be called under dev->power.lock with interrupts disabled.
+ */
+int __pm_runtime_resume(struct device *dev, bool from_wq)
+       __releases(&dev->power.lock) __acquires(&dev->power.lock)
+{
+       struct device *parent = NULL;
+       int retval = 0;
+
+       dev_dbg(dev, "__pm_runtime_resume()%s!\n",
+               from_wq ? " from workqueue" : "");
+
+ repeat:
+       if (dev->power.runtime_error) {
+               retval = -EINVAL;
+               goto out;
+       }
+
+       pm_runtime_cancel_pending(dev);
+
+       if (dev->power.runtime_status == RPM_ACTIVE)
+               retval = 1;
+       else if (dev->power.disable_depth > 0)
+               retval = -EAGAIN;
+       if (retval)
+               goto out;
+
+       if (dev->power.runtime_status == RPM_RESUMING
+           || dev->power.runtime_status == RPM_SUSPENDING) {
+               DEFINE_WAIT(wait);
+
+               if (from_wq) {
+                       if (dev->power.runtime_status == RPM_SUSPENDING)
+                               dev->power.deferred_resume = true;
+                       retval = -EINPROGRESS;
+                       goto out;
+               }
+
+               /* Wait for the operation carried out in parallel with us. */
+               for (;;) {
+                       prepare_to_wait(&dev->power.wait_queue, &wait,
+                                       TASK_UNINTERRUPTIBLE);
+                       if (dev->power.runtime_status != RPM_RESUMING
+                           && dev->power.runtime_status != RPM_SUSPENDING)
+                               break;
+
+                       spin_unlock_irq(&dev->power.lock);
+
+                       schedule();
+
+                       spin_lock_irq(&dev->power.lock);
+               }
+               finish_wait(&dev->power.wait_queue, &wait);
+               goto repeat;
+       }
+
+       if (!parent && dev->parent) {
+               /*
+                * Increment the parent's resume counter and resume it if
+                * necessary.
+                */
+               parent = dev->parent;
+               spin_unlock_irq(&dev->power.lock);
+
+               pm_runtime_get_noresume(parent);
+
+               spin_lock_irq(&parent->power.lock);
+               /*
+                * We can resume if the parent's run-time PM is disabled or it
+                * is set to ignore children.
+                */
+               if (!parent->power.disable_depth
+                   && !parent->power.ignore_children) {
+                       __pm_runtime_resume(parent, false);
+                       if (parent->power.runtime_status != RPM_ACTIVE)
+                               retval = -EBUSY;
+               }
+               spin_unlock_irq(&parent->power.lock);
+
+               spin_lock_irq(&dev->power.lock);
+               if (retval)
+                       goto out;
+               goto repeat;
+       }
+
+       dev->power.runtime_status = RPM_RESUMING;
+
+       if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) {
+               spin_unlock_irq(&dev->power.lock);
+
+               retval = dev->bus->pm->runtime_resume(dev);
+
+               spin_lock_irq(&dev->power.lock);
+               dev->power.runtime_error = retval;
+       } else {
+               retval = -ENOSYS;
+       }
+
+       if (retval) {
+               dev->power.runtime_status = RPM_SUSPENDED;
+               pm_runtime_cancel_pending(dev);
+       } else {
+               dev->power.runtime_status = RPM_ACTIVE;
+               if (parent)
+                       atomic_inc(&parent->power.child_count);
+       }
+       wake_up_all(&dev->power.wait_queue);
+
+       if (!retval)
+               __pm_request_idle(dev);
+
+ out:
+       if (parent) {
+               spin_unlock_irq(&dev->power.lock);
+
+               pm_runtime_put(parent);
+
+               spin_lock_irq(&dev->power.lock);
+       }
+
+       dev_dbg(dev, "__pm_runtime_resume() returns %d!\n", retval);
+
+       return retval;
+}
+
+/**
+ * pm_runtime_resume - Carry out run-time resume of given device.
+ * @dev: Device to suspend.
+ */
+int pm_runtime_resume(struct device *dev)
+{
+       int retval;
+
+       spin_lock_irq(&dev->power.lock);
+       retval = __pm_runtime_resume(dev, false);
+       spin_unlock_irq(&dev->power.lock);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(pm_runtime_resume);
+
+/**
+ * pm_runtime_work - Universal run-time PM work function.
+ * @work: Work structure used for scheduling the execution of this function.
+ *
+ * Use @work to get the device object the work is to be done for, determine what
+ * is to be done and execute the appropriate run-time PM function.
+ */
+static void pm_runtime_work(struct work_struct *work)
+{
+       struct device *dev = container_of(work, struct device, power.work);
+       enum rpm_request req;
+
+       spin_lock_irq(&dev->power.lock);
+
+       if (!dev->power.request_pending)
+               goto out;
+
+       req = dev->power.request;
+       dev->power.request = RPM_REQ_NONE;
+       dev->power.request_pending = false;
+
+       switch (req) {
+       case RPM_REQ_NONE:
+               break;
+       case RPM_REQ_IDLE:
+               __pm_runtime_idle(dev);
+               break;
+       case RPM_REQ_SUSPEND:
+               __pm_runtime_suspend(dev, true);
+               break;
+       case RPM_REQ_RESUME:
+               __pm_runtime_resume(dev, true);
+               break;
+       }
+
+ out:
+       spin_unlock_irq(&dev->power.lock);
+}
+
+/**
+ * __pm_request_idle - Submit an idle notification request for given device.
+ * @dev: Device to handle.
+ *
+ * Check if the device's run-time PM status is correct for suspending the device
+ * and queue up a request to run __pm_runtime_idle() for it.
+ *
+ * This function must be called under dev->power.lock with interrupts disabled.
+ */
+static int __pm_request_idle(struct device *dev)
+{
+       int retval = 0;
+
+       if (dev->power.runtime_error)
+               retval = -EINVAL;
+       else if (atomic_read(&dev->power.usage_count) > 0
+           || dev->power.disable_depth > 0
+           || dev->power.runtime_status == RPM_SUSPENDED
+           || dev->power.runtime_status == RPM_SUSPENDING)
+               retval = -EAGAIN;
+       else if (!pm_children_suspended(dev))
+               retval = -EBUSY;
+       if (retval)
+               return retval;
+
+       if (dev->power.request_pending) {
+               /* Any requests other then RPM_REQ_IDLE take precedence. */
+               if (dev->power.request == RPM_REQ_NONE)
+                       dev->power.request = RPM_REQ_IDLE;
+               else if (dev->power.request != RPM_REQ_IDLE)
+                       retval = -EAGAIN;
+               return retval;
+       }
+
+       dev->power.request = RPM_REQ_IDLE;
+       dev->power.request_pending = true;
+       queue_work(pm_wq, &dev->power.work);
+
+       return retval;
+}
+
+/**
+ * pm_request_idle - Submit an idle notification request for given device.
+ * @dev: Device to handle.
+ */
+int pm_request_idle(struct device *dev)
+{
+       unsigned long flags;
+       int retval;
+
+       spin_lock_irqsave(&dev->power.lock, flags);
+       retval = __pm_request_idle(dev);
+       spin_unlock_irqrestore(&dev->power.lock, flags);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(pm_request_idle);
+
+/**
+ * __pm_request_suspend - Submit a suspend request for given device.
+ * @dev: Device to suspend.
+ *
+ * This function must be called under dev->power.lock with interrupts disabled.
+ */
+static int __pm_request_suspend(struct device *dev)
+{
+       int retval = 0;
+
+       if (dev->power.runtime_error)
+               return -EINVAL;
+
+       if (dev->power.runtime_status == RPM_SUSPENDED)
+               retval = 1;
+       else if (atomic_read(&dev->power.usage_count) > 0
+           || dev->power.disable_depth > 0)
+               retval = -EAGAIN;
+       else if (dev->power.runtime_status == RPM_SUSPENDING)
+               retval = -EINPROGRESS;
+       else if (!pm_children_suspended(dev))
+               retval = -EBUSY;
+       if (retval < 0)
+               return retval;
+
+       pm_runtime_deactivate_timer(dev);
+
+       if (dev->power.request_pending) {
+               /*
+                * Pending resume requests take precedence over us, but we can
+                * overtake any other pending request.
+                */
+               if (dev->power.request == RPM_REQ_RESUME)
+                       retval = -EAGAIN;
+               else if (dev->power.request != RPM_REQ_SUSPEND)
+                       dev->power.request = retval ?
+                                               RPM_REQ_NONE : RPM_REQ_SUSPEND;
+               return retval;
+       } else if (retval) {
+               return retval;
+       }
+
+       dev->power.request = RPM_REQ_SUSPEND;
+       dev->power.request_pending = true;
+       queue_work(pm_wq, &dev->power.work);
+
+       return 0;
+}
+
+/**
+ * pm_suspend_timer_fn - Timer function for pm_schedule_suspend().
+ * @data: Device pointer passed by pm_schedule_suspend().
+ *
+ * Check if the time is right and execute __pm_request_suspend() in that case.
+ */
+static void pm_suspend_timer_fn(unsigned long data)
+{
+       struct device *dev = (struct device *)data;
+       unsigned long flags;
+       unsigned long expires;
+
+       spin_lock_irqsave(&dev->power.lock, flags);
+
+       expires = dev->power.timer_expires;
+       /* If 'expire' is after 'jiffies' we've been called too early. */
+       if (expires > 0 && !time_after(expires, jiffies)) {
+               dev->power.timer_expires = 0;
+               __pm_request_suspend(dev);
+       }
+
+       spin_unlock_irqrestore(&dev->power.lock, flags);
+}
+
+/**
+ * pm_schedule_suspend - Set up a timer to submit a suspend request in future.
+ * @dev: Device to suspend.
+ * @delay: Time to wait before submitting a suspend request, in milliseconds.
+ */
+int pm_schedule_suspend(struct device *dev, unsigned int delay)
+{
+       unsigned long flags;
+       int retval = 0;
+
+       spin_lock_irqsave(&dev->power.lock, flags);
+
+       if (dev->power.runtime_error) {
+               retval = -EINVAL;
+               goto out;
+       }
+
+       if (!delay) {
+               retval = __pm_request_suspend(dev);
+               goto out;
+       }
+
+       pm_runtime_deactivate_timer(dev);
+
+       if (dev->power.request_pending) {
+               /*
+                * Pending resume requests take precedence over us, but any
+                * other pending requests have to be canceled.
+                */
+               if (dev->power.request == RPM_REQ_RESUME) {
+                       retval = -EAGAIN;
+                       goto out;
+               }
+               dev->power.request = RPM_REQ_NONE;
+       }
+
+       if (dev->power.runtime_status == RPM_SUSPENDED)
+               retval = 1;
+       else if (dev->power.runtime_status == RPM_SUSPENDING)
+               retval = -EINPROGRESS;
+       else if (atomic_read(&dev->power.usage_count) > 0
+           || dev->power.disable_depth > 0)
+               retval = -EAGAIN;
+       else if (!pm_children_suspended(dev))
+               retval = -EBUSY;
+       if (retval)
+               goto out;
+
+       dev->power.timer_expires = jiffies + msecs_to_jiffies(delay);
+       mod_timer(&dev->power.suspend_timer, dev->power.timer_expires);
+
+ out:
+       spin_unlock_irqrestore(&dev->power.lock, flags);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(pm_schedule_suspend);
+
+/**
+ * pm_request_resume - Submit a resume request for given device.
+ * @dev: Device to resume.
+ *
+ * This function must be called under dev->power.lock with interrupts disabled.
+ */
+static int __pm_request_resume(struct device *dev)
+{
+       int retval = 0;
+
+       if (dev->power.runtime_error)
+               return -EINVAL;
+
+       if (dev->power.runtime_status == RPM_ACTIVE)
+               retval = 1;
+       else if (dev->power.runtime_status == RPM_RESUMING)
+               retval = -EINPROGRESS;
+       else if (dev->power.disable_depth > 0)
+               retval = -EAGAIN;
+       if (retval < 0)
+               return retval;
+
+       pm_runtime_deactivate_timer(dev);
+
+       if (dev->power.request_pending) {
+               /* If non-resume request is pending, we can overtake it. */
+               dev->power.request = retval ? RPM_REQ_NONE : RPM_REQ_RESUME;
+               return retval;
+       } else if (retval) {
+               return retval;
+       }
+
+       dev->power.request = RPM_REQ_RESUME;
+       dev->power.request_pending = true;
+       queue_work(pm_wq, &dev->power.work);
+
+       return retval;
+}
+
+/**
+ * pm_request_resume - Submit a resume request for given device.
+ * @dev: Device to resume.
+ */
+int pm_request_resume(struct device *dev)
+{
+       unsigned long flags;
+       int retval;
+
+       spin_lock_irqsave(&dev->power.lock, flags);
+       retval = __pm_request_resume(dev);
+       spin_unlock_irqrestore(&dev->power.lock, flags);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(pm_request_resume);
+
+/**
+ * __pm_runtime_get - Reference count a device and wake it up, if necessary.
+ * @dev: Device to handle.
+ * @sync: If set and the device is suspended, resume it synchronously.
+ *
+ * Increment the usage count of the device and if it was zero previously,
+ * resume it or submit a resume request for it, depending on the value of @sync.
+ */
+int __pm_runtime_get(struct device *dev, bool sync)
+{
+       int retval = 1;
+
+       if (atomic_add_return(1, &dev->power.usage_count) == 1)
+               retval = sync ? pm_runtime_resume(dev) : pm_request_resume(dev);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(__pm_runtime_get);
+
+/**
+ * __pm_runtime_put - Decrement the device's usage counter and notify its bus.
+ * @dev: Device to handle.
+ * @sync: If the device's bus type is to be notified, do that synchronously.
+ *
+ * Decrement the usage count of the device and if it reaches zero, carry out a
+ * synchronous idle notification or submit an idle notification request for it,
+ * depending on the value of @sync.
+ */
+int __pm_runtime_put(struct device *dev, bool sync)
+{
+       int retval = 0;
+
+       if (atomic_dec_and_test(&dev->power.usage_count))
+               retval = sync ? pm_runtime_idle(dev) : pm_request_idle(dev);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(__pm_runtime_put);
+
+/**
+ * __pm_runtime_set_status - Set run-time PM status of a device.
+ * @dev: Device to handle.
+ * @status: New run-time PM status of the device.
+ *
+ * If run-time PM of the device is disabled or its power.runtime_error field is
+ * different from zero, the status may be changed either to RPM_ACTIVE, or to
+ * RPM_SUSPENDED, as long as that reflects the actual state of the device.
+ * However, if the device has a parent and the parent is not active, and the
+ * parent's power.ignore_children flag is unset, the device's status cannot be
+ * set to RPM_ACTIVE, so -EBUSY is returned in that case.
+ *
+ * If successful, __pm_runtime_set_status() clears the power.runtime_error field
+ * and the device parent's counter of unsuspended children is modified to
+ * reflect the new status.  If the new status is RPM_SUSPENDED, an idle
+ * notification request for the parent is submitted.
+ */
+int __pm_runtime_set_status(struct device *dev, unsigned int status)
+{
+       struct device *parent = dev->parent;
+       unsigned long flags;
+       bool notify_parent = false;
+       int error = 0;
+
+       if (status != RPM_ACTIVE && status != RPM_SUSPENDED)
+               return -EINVAL;
+
+       spin_lock_irqsave(&dev->power.lock, flags);
+
+       if (!dev->power.runtime_error && !dev->power.disable_depth) {
+               error = -EAGAIN;
+               goto out;
+       }
+
+       if (dev->power.runtime_status == status)
+               goto out_set;
+
+       if (status == RPM_SUSPENDED) {
+               /* It always is possible to set the status to 'suspended'. */
+               if (parent) {
+                       atomic_add_unless(&parent->power.child_count, -1, 0);
+                       notify_parent = !parent->power.ignore_children;
+               }
+               goto out_set;
+       }
+
+       if (parent) {
+               spin_lock_irq(&parent->power.lock);
+
+               /*
+                * It is invalid to put an active child under a parent that is
+                * not active, has run-time PM enabled and the
+                * 'power.ignore_children' flag unset.
+                */
+               if (!parent->power.disable_depth
+                   && !parent->power.ignore_children
+                   && parent->power.runtime_status != RPM_ACTIVE) {
+                       error = -EBUSY;
+               } else {
+                       if (dev->power.runtime_status == RPM_SUSPENDED)
+                               atomic_inc(&parent->power.child_count);
+               }
+
+               spin_unlock_irq(&parent->power.lock);
+
+               if (error)
+                       goto out;
+       }
+
+ out_set:
+       dev->power.runtime_status = status;
+       dev->power.runtime_error = 0;
+ out:
+       spin_unlock_irqrestore(&dev->power.lock, flags);
+
+       if (notify_parent)
+               pm_request_idle(parent);
+
+       return error;
+}
+EXPORT_SYMBOL_GPL(__pm_runtime_set_status);
+
+/**
+ * __pm_runtime_barrier - Cancel pending requests and wait for completions.
+ * @dev: Device to handle.
+ *
+ * Flush all pending requests for the device from pm_wq and wait for all
+ * run-time PM operations involving the device in progress to complete.
+ *
+ * Should be called under dev->power.lock with interrupts disabled.
+ */
+static void __pm_runtime_barrier(struct device *dev)
+{
+       pm_runtime_deactivate_timer(dev);
+
+       if (dev->power.request_pending) {
+               dev->power.request = RPM_REQ_NONE;
+               spin_unlock_irq(&dev->power.lock);
+
+               cancel_work_sync(&dev->power.work);
+
+               spin_lock_irq(&dev->power.lock);
+               dev->power.request_pending = false;
+       }
+
+       if (dev->power.runtime_status == RPM_SUSPENDING
+           || dev->power.runtime_status == RPM_RESUMING
+           || dev->power.idle_notification) {
+               DEFINE_WAIT(wait);
+
+               /* Suspend, wake-up or idle notification in progress. */
+               for (;;) {
+                       prepare_to_wait(&dev->power.wait_queue, &wait,
+                                       TASK_UNINTERRUPTIBLE);
+                       if (dev->power.runtime_status != RPM_SUSPENDING
+                           && dev->power.runtime_status != RPM_RESUMING
+                           && !dev->power.idle_notification)
+                               break;
+                       spin_unlock_irq(&dev->power.lock);
+
+                       schedule();
+
+                       spin_lock_irq(&dev->power.lock);
+               }
+               finish_wait(&dev->power.wait_queue, &wait);
+       }
+}
+
+/**
+ * pm_runtime_barrier - Flush pending requests and wait for completions.
+ * @dev: Device to handle.
+ *
+ * Prevent the device from being suspended by incrementing its usage counter and
+ * if there's a pending resume request for the device, wake the device up.
+ * Next, make sure that all pending requests for the device have been flushed
+ * from pm_wq and wait for all run-time PM operations involving the device in
+ * progress to complete.
+ *
+ * Return value:
+ * 1, if there was a resume request pending and the device had to be woken up,
+ * 0, otherwise
+ */
+int pm_runtime_barrier(struct device *dev)
+{
+       int retval = 0;
+
+       pm_runtime_get_noresume(dev);
+       spin_lock_irq(&dev->power.lock);
+
+       if (dev->power.request_pending
+           && dev->power.request == RPM_REQ_RESUME) {
+               __pm_runtime_resume(dev, false);
+               retval = 1;
+       }
+
+       __pm_runtime_barrier(dev);
+
+       spin_unlock_irq(&dev->power.lock);
+       pm_runtime_put_noidle(dev);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(pm_runtime_barrier);
+
+/**
+ * __pm_runtime_disable - Disable run-time PM of a device.
+ * @dev: Device to handle.
+ * @check_resume: If set, check if there's a resume request for the device.
+ *
+ * Increment power.disable_depth for the device and if was zero previously,
+ * cancel all pending run-time PM requests for the device and wait for all
+ * operations in progress to complete.  The device can be either active or
+ * suspended after its run-time PM has been disabled.
+ *
+ * If @check_resume is set and there's a resume request pending when
+ * __pm_runtime_disable() is called and power.disable_depth is zero, the
+ * function will wake up the device before disabling its run-time PM.
+ */
+void __pm_runtime_disable(struct device *dev, bool check_resume)
+{
+       spin_lock_irq(&dev->power.lock);
+
+       if (dev->power.disable_depth > 0) {
+               dev->power.disable_depth++;
+               goto out;
+       }
+
+       /*
+        * Wake up the device if there's a resume request pending, because that
+        * means there probably is some I/O to process and disabling run-time PM
+        * shouldn't prevent the device from processing the I/O.
+        */
+       if (check_resume && dev->power.request_pending
+           && dev->power.request == RPM_REQ_RESUME) {
+               /*
+                * Prevent suspends and idle notifications from being carried
+                * out after we have woken up the device.
+                */
+               pm_runtime_get_noresume(dev);
+
+               __pm_runtime_resume(dev, false);
+
+               pm_runtime_put_noidle(dev);
+       }
+
+       if (!dev->power.disable_depth++)
+               __pm_runtime_barrier(dev);
+
+ out:
+       spin_unlock_irq(&dev->power.lock);
+}
+EXPORT_SYMBOL_GPL(__pm_runtime_disable);
+
+/**
+ * pm_runtime_enable - Enable run-time PM of a device.
+ * @dev: Device to handle.
+ */
+void pm_runtime_enable(struct device *dev)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->power.lock, flags);
+
+       if (dev->power.disable_depth > 0)
+               dev->power.disable_depth--;
+       else
+               dev_warn(dev, "Unbalanced %s!\n", __func__);
+
+       spin_unlock_irqrestore(&dev->power.lock, flags);
+}
+EXPORT_SYMBOL_GPL(pm_runtime_enable);
+
+/**
+ * pm_runtime_init - Initialize run-time PM fields in given device object.
+ * @dev: Device object to initialize.
+ */
+void pm_runtime_init(struct device *dev)
+{
+       spin_lock_init(&dev->power.lock);
+
+       dev->power.runtime_status = RPM_SUSPENDED;
+       dev->power.idle_notification = false;
+
+       dev->power.disable_depth = 1;
+       atomic_set(&dev->power.usage_count, 0);
+
+       dev->power.runtime_error = 0;
+
+       atomic_set(&dev->power.child_count, 0);
+       pm_suspend_ignore_children(dev, false);
+
+       dev->power.request_pending = false;
+       dev->power.request = RPM_REQ_NONE;
+       dev->power.deferred_resume = false;
+       INIT_WORK(&dev->power.work, pm_runtime_work);
+
+       dev->power.timer_expires = 0;
+       setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn,
+                       (unsigned long)dev);
+
+       init_waitqueue_head(&dev->power.wait_queue);
+}
+
+/**
+ * pm_runtime_remove - Prepare for removing a device from device hierarchy.
+ * @dev: Device object being removed from device hierarchy.
+ */
+void pm_runtime_remove(struct device *dev)
+{
+       __pm_runtime_disable(dev, false);
+
+       /* Change the status back to 'suspended' to match the initial status. */
+       if (dev->power.runtime_status == RPM_ACTIVE)
+               pm_runtime_set_suspended(dev);
+}
index 98c9a84..933c143 100644 (file)
@@ -1399,8 +1399,9 @@ static void dw_shutdown(struct platform_device *pdev)
        clk_disable(dw->clk);
 }
 
-static int dw_suspend_late(struct platform_device *pdev, pm_message_t mesg)
+static int dw_suspend_noirq(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct dw_dma   *dw = platform_get_drvdata(pdev);
 
        dw_dma_off(platform_get_drvdata(pdev));
@@ -1408,23 +1409,27 @@ static int dw_suspend_late(struct platform_device *pdev, pm_message_t mesg)
        return 0;
 }
 
-static int dw_resume_early(struct platform_device *pdev)
+static int dw_resume_noirq(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct dw_dma   *dw = platform_get_drvdata(pdev);
 
        clk_enable(dw->clk);
        dma_writel(dw, CFG, DW_CFG_DMA_EN);
        return 0;
-
 }
 
+static struct dev_pm_ops dw_dev_pm_ops = {
+       .suspend_noirq = dw_suspend_noirq,
+       .resume_noirq = dw_resume_noirq,
+};
+
 static struct platform_driver dw_driver = {
        .remove         = __exit_p(dw_remove),
        .shutdown       = dw_shutdown,
-       .suspend_late   = dw_suspend_late,
-       .resume_early   = dw_resume_early,
        .driver = {
                .name   = "dw_dmac",
+               .pm     = &dw_dev_pm_ops,
        },
 };
 
index 88dab52..7837930 100644 (file)
@@ -1291,17 +1291,18 @@ static void txx9dmac_shutdown(struct platform_device *pdev)
        txx9dmac_off(ddev);
 }
 
-static int txx9dmac_suspend_late(struct platform_device *pdev,
-                                pm_message_t mesg)
+static int txx9dmac_suspend_noirq(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct txx9dmac_dev *ddev = platform_get_drvdata(pdev);
 
        txx9dmac_off(ddev);
        return 0;
 }
 
-static int txx9dmac_resume_early(struct platform_device *pdev)
+static int txx9dmac_resume_noirq(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct txx9dmac_dev *ddev = platform_get_drvdata(pdev);
        struct txx9dmac_platform_data *pdata = pdev->dev.platform_data;
        u32 mcr;
@@ -1314,6 +1315,11 @@ static int txx9dmac_resume_early(struct platform_device *pdev)
 
 }
 
+static struct dev_pm_ops txx9dmac_dev_pm_ops = {
+       .suspend_noirq = txx9dmac_suspend_noirq,
+       .resume_noirq = txx9dmac_resume_noirq,
+};
+
 static struct platform_driver txx9dmac_chan_driver = {
        .remove         = __exit_p(txx9dmac_chan_remove),
        .driver = {
@@ -1324,10 +1330,9 @@ static struct platform_driver txx9dmac_chan_driver = {
 static struct platform_driver txx9dmac_driver = {
        .remove         = __exit_p(txx9dmac_remove),
        .shutdown       = txx9dmac_shutdown,
-       .suspend_late   = txx9dmac_suspend_late,
-       .resume_early   = txx9dmac_resume_early,
        .driver = {
                .name   = "txx9dmac",
+               .pm     = &txx9dmac_dev_pm_ops,
        },
 };
 
index 762e1e5..0495557 100644 (file)
@@ -1134,35 +1134,44 @@ static int __exit i2c_pxa_remove(struct platform_device *dev)
 }
 
 #ifdef CONFIG_PM
-static int i2c_pxa_suspend_late(struct platform_device *dev, pm_message_t state)
+static int i2c_pxa_suspend_noirq(struct device *dev)
 {
-       struct pxa_i2c *i2c = platform_get_drvdata(dev);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pxa_i2c *i2c = platform_get_drvdata(pdev);
+
        clk_disable(i2c->clk);
+
        return 0;
 }
 
-static int i2c_pxa_resume_early(struct platform_device *dev)
+static int i2c_pxa_resume_noirq(struct device *dev)
 {
-       struct pxa_i2c *i2c = platform_get_drvdata(dev);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pxa_i2c *i2c = platform_get_drvdata(pdev);
 
        clk_enable(i2c->clk);
        i2c_pxa_reset(i2c);
 
        return 0;
 }
+
+static struct dev_pm_ops i2c_pxa_dev_pm_ops = {
+       .suspend_noirq = i2c_pxa_suspend_noirq,
+       .resume_noirq = i2c_pxa_resume_noirq,
+};
+
+#define I2C_PXA_DEV_PM_OPS (&i2c_pxa_dev_pm_ops)
 #else
-#define i2c_pxa_suspend_late NULL
-#define i2c_pxa_resume_early NULL
+#define I2C_PXA_DEV_PM_OPS NULL
 #endif
 
 static struct platform_driver i2c_pxa_driver = {
        .probe          = i2c_pxa_probe,
        .remove         = __exit_p(i2c_pxa_remove),
-       .suspend_late   = i2c_pxa_suspend_late,
-       .resume_early   = i2c_pxa_resume_early,
        .driver         = {
                .name   = "pxa2xx-i2c",
                .owner  = THIS_MODULE,
+               .pm     = I2C_PXA_DEV_PM_OPS,
        },
        .id_table       = i2c_pxa_id_table,
 };
index 20bb0ce..96aafb9 100644 (file)
@@ -946,17 +946,20 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-static int s3c24xx_i2c_suspend_late(struct platform_device *dev,
-                                   pm_message_t msg)
+static int s3c24xx_i2c_suspend_noirq(struct device *dev)
 {
-       struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
+
        i2c->suspended = 1;
+
        return 0;
 }
 
-static int s3c24xx_i2c_resume(struct platform_device *dev)
+static int s3c24xx_i2c_resume(struct device *dev)
 {
-       struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
 
        i2c->suspended = 0;
        s3c24xx_i2c_init(i2c);
@@ -964,9 +967,14 @@ static int s3c24xx_i2c_resume(struct platform_device *dev)
        return 0;
 }
 
+static struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
+       .suspend_noirq = s3c24xx_i2c_suspend_noirq,
+       .resume = s3c24xx_i2c_resume,
+};
+
+#define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops)
 #else
-#define s3c24xx_i2c_suspend_late NULL
-#define s3c24xx_i2c_resume NULL
+#define S3C24XX_DEV_PM_OPS NULL
 #endif
 
 /* device driver for platform bus bits */
@@ -985,12 +993,11 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
 static struct platform_driver s3c24xx_i2c_driver = {
        .probe          = s3c24xx_i2c_probe,
        .remove         = s3c24xx_i2c_remove,
-       .suspend_late   = s3c24xx_i2c_suspend_late,
-       .resume         = s3c24xx_i2c_resume,
        .id_table       = s3c24xx_driver_ids,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "s3c-i2c",
+               .pm     = S3C24XX_DEV_PM_OPS,
        },
 };
 
index 820487d..86a9d4e 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
 #include <linux/err.h>
+#include <linux/pm_runtime.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 
@@ -165,7 +166,8 @@ static void activate_ch(struct sh_mobile_i2c_data *pd)
        u_int32_t denom;
        u_int32_t tmp;
 
-       /* Make sure the clock is enabled */
+       /* Wake up device and enable clock */
+       pm_runtime_get_sync(pd->dev);
        clk_enable(pd->clk);
 
        /* Get clock rate after clock is enabled */
@@ -213,8 +215,9 @@ static void deactivate_ch(struct sh_mobile_i2c_data *pd)
        /* Disable channel */
        iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
 
-       /* Disable clock */
+       /* Disable clock and mark device as idle */
        clk_disable(pd->clk);
+       pm_runtime_put_sync(pd->dev);
 }
 
 static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
@@ -572,6 +575,19 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
                goto err_irq;
        }
 
+       /* Enable Runtime PM for this device.
+        *
+        * Also tell the Runtime PM core to ignore children
+        * for this device since it is valid for us to suspend
+        * this I2C master driver even though the slave devices
+        * on the I2C bus may not be suspended.
+        *
+        * The state of the I2C hardware bus is unaffected by
+        * the Runtime PM state.
+        */
+       pm_suspend_ignore_children(&dev->dev, true);
+       pm_runtime_enable(&dev->dev);
+
        /* setup the private data */
        adap = &pd->adap;
        i2c_set_adapdata(adap, pd);
@@ -614,14 +630,33 @@ static int sh_mobile_i2c_remove(struct platform_device *dev)
        iounmap(pd->reg);
        sh_mobile_i2c_hook_irqs(dev, 0);
        clk_put(pd->clk);
+       pm_runtime_disable(&dev->dev);
        kfree(pd);
        return 0;
 }
 
+static int sh_mobile_i2c_runtime_nop(struct device *dev)
+{
+       /* Runtime PM callback shared between ->runtime_suspend()
+        * and ->runtime_resume(). Simply returns success.
+        *
+        * This driver re-initializes all registers after
+        * pm_runtime_get_sync() anyway so there is no need
+        * to save and restore registers here.
+        */
+       return 0;
+}
+
+static struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = {
+       .runtime_suspend = sh_mobile_i2c_runtime_nop,
+       .runtime_resume = sh_mobile_i2c_runtime_nop,
+};
+
 static struct platform_driver sh_mobile_i2c_driver = {
        .driver         = {
                .name           = "i2c-sh_mobile",
                .owner          = THIS_MODULE,
+               .pm             = &sh_mobile_i2c_dev_pm_ops,
        },
        .probe          = sh_mobile_i2c_probe,
        .remove         = sh_mobile_i2c_remove,
index e86878d..61c47b8 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/videodev2.h>
-#include <linux/clk.h>
+#include <linux/pm_runtime.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
@@ -86,7 +86,6 @@ struct sh_mobile_ceu_dev {
 
        unsigned int irq;
        void __iomem *base;
-       struct clk *clk;
        unsigned long video_limit;
 
        /* lock used to protect videobuf */
@@ -361,7 +360,7 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
        if (ret)
                goto err;
 
-       clk_enable(pcdev->clk);
+       pm_runtime_get_sync(ici->dev);
 
        ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
        while (ceu_read(pcdev, CSTSR) & 1)
@@ -395,7 +394,7 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
        }
        spin_unlock_irqrestore(&pcdev->lock, flags);
 
-       clk_disable(pcdev->clk);
+       pm_runtime_put_sync(ici->dev);
 
        icd->ops->release(icd);
 
@@ -798,7 +797,6 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
        struct sh_mobile_ceu_dev *pcdev;
        struct resource *res;
        void __iomem *base;
-       char clk_name[8];
        unsigned int irq;
        int err = 0;
 
@@ -862,13 +860,9 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
                goto exit_release_mem;
        }
 
-       snprintf(clk_name, sizeof(clk_name), "ceu%d", pdev->id);
-       pcdev->clk = clk_get(&pdev->dev, clk_name);
-       if (IS_ERR(pcdev->clk)) {
-               dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
-               err = PTR_ERR(pcdev->clk);
-               goto exit_free_irq;
-       }
+       pm_suspend_ignore_children(&pdev->dev, true);
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_resume(&pdev->dev);
 
        pcdev->ici.priv = pcdev;
        pcdev->ici.dev = &pdev->dev;
@@ -878,12 +872,10 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
 
        err = soc_camera_host_register(&pcdev->ici);
        if (err)
-               goto exit_free_clk;
+               goto exit_free_irq;
 
        return 0;
 
-exit_free_clk:
-       clk_put(pcdev->clk);
 exit_free_irq:
        free_irq(pcdev->irq, pcdev);
 exit_release_mem:
@@ -904,7 +896,6 @@ static int sh_mobile_ceu_remove(struct platform_device *pdev)
                                        struct sh_mobile_ceu_dev, ici);
 
        soc_camera_host_unregister(soc_host);
-       clk_put(pcdev->clk);
        free_irq(pcdev->irq, pcdev);
        if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
                dma_release_declared_memory(&pdev->dev);
@@ -913,9 +904,27 @@ static int sh_mobile_ceu_remove(struct platform_device *pdev)
        return 0;
 }
 
+static int sh_mobile_ceu_runtime_nop(struct device *dev)
+{
+       /* Runtime PM callback shared between ->runtime_suspend()
+        * and ->runtime_resume(). Simply returns success.
+        *
+        * This driver re-initializes all registers after
+        * pm_runtime_get_sync() anyway so there is no need
+        * to save and restore registers here.
+        */
+       return 0;
+}
+
+static struct dev_pm_ops sh_mobile_ceu_dev_pm_ops = {
+       .runtime_suspend = sh_mobile_ceu_runtime_nop,
+       .runtime_resume = sh_mobile_ceu_runtime_nop,
+};
+
 static struct platform_driver sh_mobile_ceu_driver = {
        .driver         = {
                .name   = "sh_mobile_ceu",
+               .pm     = &sh_mobile_ceu_dev_pm_ops,
        },
        .probe          = sh_mobile_ceu_probe,
        .remove         = sh_mobile_ceu_remove,
index f99bc7f..a7eb727 100644 (file)
@@ -575,7 +575,7 @@ static void pci_pm_complete(struct device *dev)
 static int pci_pm_suspend(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
        if (pci_has_legacy_pm_support(pci_dev))
                return pci_legacy_suspend(dev, PMSG_SUSPEND);
@@ -613,7 +613,7 @@ static int pci_pm_suspend(struct device *dev)
 static int pci_pm_suspend_noirq(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
        if (pci_has_legacy_pm_support(pci_dev))
                return pci_legacy_suspend_late(dev, PMSG_SUSPEND);
@@ -672,7 +672,7 @@ static int pci_pm_resume_noirq(struct device *dev)
 static int pci_pm_resume(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
        int error = 0;
 
        /*
@@ -711,7 +711,7 @@ static int pci_pm_resume(struct device *dev)
 static int pci_pm_freeze(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
        if (pci_has_legacy_pm_support(pci_dev))
                return pci_legacy_suspend(dev, PMSG_FREEZE);
@@ -780,7 +780,7 @@ static int pci_pm_thaw_noirq(struct device *dev)
 static int pci_pm_thaw(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
        int error = 0;
 
        if (pci_has_legacy_pm_support(pci_dev))
@@ -799,7 +799,7 @@ static int pci_pm_thaw(struct device *dev)
 static int pci_pm_poweroff(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
        if (pci_has_legacy_pm_support(pci_dev))
                return pci_legacy_suspend(dev, PMSG_HIBERNATE);
@@ -872,7 +872,7 @@ static int pci_pm_restore_noirq(struct device *dev)
 static int pci_pm_restore(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
        int error = 0;
 
        /*
@@ -910,7 +910,7 @@ static int pci_pm_restore(struct device *dev)
 
 #endif /* !CONFIG_HIBERNATION */
 
-struct dev_pm_ops pci_dev_pm_ops = {
+const struct dev_pm_ops pci_dev_pm_ops = {
        .prepare = pci_pm_prepare,
        .complete = pci_pm_complete,
        .suspend = pci_pm_suspend,
index 1845566..d490628 100644 (file)
@@ -1,26 +1,25 @@
 /*
  * Dallas DS1302 RTC Support
  *
- *  Copyright (C) 2002  David McCullough
- *  Copyright (C) 2003 - 2007  Paul Mundt
+ *  Copyright (C) 2002 David McCullough
+ *  Copyright (C) 2003 - 2007 Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License version 2.  See the file "COPYING" in the main directory of
+ * License version 2. See the file "COPYING" in the main directory of
  * this archive for more details.
  */
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
-#include <linux/time.h>
 #include <linux/rtc.h>
-#include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/bcd.h>
 #include <asm/rtc.h>
 
 #define DRV_NAME       "rtc-ds1302"
-#define DRV_VERSION    "0.1.0"
+#define DRV_VERSION    "0.1.1"
 
 #define        RTC_CMD_READ    0x81            /* Read command */
 #define        RTC_CMD_WRITE   0x80            /* Write command */
 #error "Add support for your platform"
 #endif
 
-struct ds1302_rtc {
-       struct rtc_device *rtc_dev;
-       spinlock_t lock;
-};
-
 static void ds1302_sendbits(unsigned int val)
 {
        int i;
@@ -103,10 +97,6 @@ static void ds1302_writebyte(unsigned int addr, unsigned int val)
 
 static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-       struct ds1302_rtc *rtc = dev_get_drvdata(dev);
-
-       spin_lock_irq(&rtc->lock);
-
        tm->tm_sec      = bcd2bin(ds1302_readbyte(RTC_ADDR_SEC));
        tm->tm_min      = bcd2bin(ds1302_readbyte(RTC_ADDR_MIN));
        tm->tm_hour     = bcd2bin(ds1302_readbyte(RTC_ADDR_HOUR));
@@ -118,26 +108,17 @@ static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm)
        if (tm->tm_year < 70)
                tm->tm_year += 100;
 
-       spin_unlock_irq(&rtc->lock);
-
        dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
                "mday=%d, mon=%d, year=%d, wday=%d\n",
                __func__,
                tm->tm_sec, tm->tm_min, tm->tm_hour,
                tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);
 
-       if (rtc_valid_tm(tm) < 0)
-               dev_err(dev, "invalid date\n");
-
-       return 0;
+       return rtc_valid_tm(tm);
 }
 
 static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-       struct ds1302_rtc *rtc = dev_get_drvdata(dev);
-
-       spin_lock_irq(&rtc->lock);
-
        /* Stop RTC */
        ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
 
@@ -152,8 +133,6 @@ static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm)
        /* Start RTC */
        ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80);
 
-       spin_unlock_irq(&rtc->lock);
-
        return 0;
 }
 
@@ -170,9 +149,7 @@ static int ds1302_rtc_ioctl(struct device *dev, unsigned int cmd,
                if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int)))
                        return -EFAULT;
 
-               spin_lock_irq(&rtc->lock);
                ds1302_writebyte(RTC_ADDR_TCR, (0xa0 | tcs_val * 0xf));
-               spin_unlock_irq(&rtc->lock);
                return 0;
        }
 #endif
@@ -187,10 +164,9 @@ static struct rtc_class_ops ds1302_rtc_ops = {
        .ioctl          = ds1302_rtc_ioctl,
 };
 
-static int __devinit ds1302_rtc_probe(struct platform_device *pdev)
+static int __init ds1302_rtc_probe(struct platform_device *pdev)
 {
-       struct ds1302_rtc *rtc;
-       int ret;
+       struct rtc_device *rtc;
 
        /* Reset */
        set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
@@ -200,37 +176,23 @@ static int __devinit ds1302_rtc_probe(struct platform_device *pdev)
        if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42)
                return -ENODEV;
 
-       rtc = kzalloc(sizeof(struct ds1302_rtc), GFP_KERNEL);
-       if (unlikely(!rtc))
-               return -ENOMEM;
-
-       spin_lock_init(&rtc->lock);
-       rtc->rtc_dev = rtc_device_register("ds1302", &pdev->dev,
+       rtc = rtc_device_register("ds1302", &pdev->dev,
                                           &ds1302_rtc_ops, THIS_MODULE);
-       if (IS_ERR(rtc->rtc_dev)) {
-               ret = PTR_ERR(rtc->rtc_dev);
-               goto out;
-       }
+       if (IS_ERR(rtc))
+               return PTR_ERR(rtc);
 
        platform_set_drvdata(pdev, rtc);
 
        return 0;
-out:
-       kfree(rtc);
-       return ret;
 }
 
 static int __devexit ds1302_rtc_remove(struct platform_device *pdev)
 {
-       struct ds1302_rtc *rtc = platform_get_drvdata(pdev);
-
-       if (likely(rtc->rtc_dev))
-               rtc_device_unregister(rtc->rtc_dev);
+       struct rtc_device *rtc = platform_get_drvdata(pdev);
 
+       rtc_device_unregister(rtc);
        platform_set_drvdata(pdev, NULL);
 
-       kfree(rtc);
-
        return 0;
 }
 
@@ -239,13 +201,12 @@ static struct platform_driver ds1302_platform_driver = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
        },
-       .probe          = ds1302_rtc_probe,
-       .remove         = __devexit_p(ds1302_rtc_remove),
+       .remove         = __exit_p(ds1302_rtc_remove),
 };
 
 static int __init ds1302_rtc_init(void)
 {
-       return platform_driver_register(&ds1302_platform_driver);
+       return platform_driver_probe(&ds1302_platform_driver, ds1302_rtc_probe);
 }
 
 static void __exit ds1302_rtc_exit(void)
index d7310ad..39a2fcd 100644 (file)
@@ -29,7 +29,7 @@
 #include <asm/rtc.h>
 
 #define DRV_NAME       "sh-rtc"
-#define DRV_VERSION    "0.2.2"
+#define DRV_VERSION    "0.2.3"
 
 #define RTC_REG(r)     ((r) * rtc_reg_size)
 
@@ -215,7 +215,7 @@ static irqreturn_t sh_rtc_shared(int irq, void *dev_id)
        return IRQ_RETVAL(ret);
 }
 
-static inline void sh_rtc_setpie(struct device *dev, unsigned int enable)
+static int sh_rtc_irq_set_state(struct device *dev, int enable)
 {
        struct sh_rtc *rtc = dev_get_drvdata(dev);
        unsigned int tmp;
@@ -225,17 +225,22 @@ static inline void sh_rtc_setpie(struct device *dev, unsigned int enable)
        tmp = readb(rtc->regbase + RCR2);
 
        if (enable) {
+               rtc->periodic_freq |= PF_KOU;
                tmp &= ~RCR2_PEF;       /* Clear PES bit */
                tmp |= (rtc->periodic_freq & ~PF_HP);   /* Set PES2-0 */
-       } else
+       } else {
+               rtc->periodic_freq &= ~PF_KOU;
                tmp &= ~(RCR2_PESMASK | RCR2_PEF);
+       }
 
        writeb(tmp, rtc->regbase + RCR2);
 
        spin_unlock_irq(&rtc->lock);
+
+       return 0;
 }
 
-static inline int sh_rtc_setfreq(struct device *dev, unsigned int freq)
+static int sh_rtc_irq_set_freq(struct device *dev, int freq)
 {
        struct sh_rtc *rtc = dev_get_drvdata(dev);
        int tmp, ret = 0;
@@ -346,10 +351,6 @@ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
        unsigned int ret = 0;
 
        switch (cmd) {
-       case RTC_PIE_OFF:
-       case RTC_PIE_ON:
-               sh_rtc_setpie(dev, cmd == RTC_PIE_ON);
-               break;
        case RTC_AIE_OFF:
        case RTC_AIE_ON:
                sh_rtc_setaie(dev, cmd == RTC_AIE_ON);
@@ -362,13 +363,6 @@ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
                rtc->periodic_freq |= PF_OXS;
                sh_rtc_setcie(dev, 1);
                break;
-       case RTC_IRQP_READ:
-               ret = put_user(rtc->rtc_dev->irq_freq,
-                              (unsigned long __user *)arg);
-               break;
-       case RTC_IRQP_SET:
-               ret = sh_rtc_setfreq(dev, arg);
-               break;
        default:
                ret = -ENOIOCTLCMD;
        }
@@ -602,28 +596,6 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
        return 0;
 }
 
-static int sh_rtc_irq_set_state(struct device *dev, int enabled)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct sh_rtc *rtc = platform_get_drvdata(pdev);
-
-       if (enabled) {
-               rtc->periodic_freq |= PF_KOU;
-               return sh_rtc_ioctl(dev, RTC_PIE_ON, 0);
-       } else {
-               rtc->periodic_freq &= ~PF_KOU;
-               return sh_rtc_ioctl(dev, RTC_PIE_OFF, 0);
-       }
-}
-
-static int sh_rtc_irq_set_freq(struct device *dev, int freq)
-{
-       if (!is_power_of_2(freq))
-               return -EINVAL;
-
-       return sh_rtc_ioctl(dev, RTC_IRQP_SET, freq);
-}
-
 static struct rtc_class_ops sh_rtc_ops = {
        .ioctl          = sh_rtc_ioctl,
        .read_time      = sh_rtc_read_time,
@@ -635,7 +607,7 @@ static struct rtc_class_ops sh_rtc_ops = {
        .proc           = sh_rtc_proc,
 };
 
-static int __devinit sh_rtc_probe(struct platform_device *pdev)
+static int __init sh_rtc_probe(struct platform_device *pdev)
 {
        struct sh_rtc *rtc;
        struct resource *res;
@@ -702,13 +674,6 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
 
        clk_enable(rtc->clk);
 
-       rtc->rtc_dev = rtc_device_register("sh", &pdev->dev,
-                                          &sh_rtc_ops, THIS_MODULE);
-       if (IS_ERR(rtc->rtc_dev)) {
-               ret = PTR_ERR(rtc->rtc_dev);
-               goto err_unmap;
-       }
-
        rtc->capabilities = RTC_DEF_CAPABILITIES;
        if (pdev->dev.platform_data) {
                struct sh_rtc_platform_info *pinfo = pdev->dev.platform_data;
@@ -720,10 +685,6 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
                rtc->capabilities |= pinfo->capabilities;
        }
 
-       rtc->rtc_dev->max_user_freq = 256;
-
-       platform_set_drvdata(pdev, rtc);
-
        if (rtc->carry_irq <= 0) {
                /* register shared periodic/carry/alarm irq */
                ret = request_irq(rtc->periodic_irq, sh_rtc_shared,
@@ -767,13 +728,26 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
                }
        }
 
+       platform_set_drvdata(pdev, rtc);
+
        /* everything disabled by default */
-       rtc->periodic_freq = 0;
-       rtc->rtc_dev->irq_freq = 0;
-       sh_rtc_setpie(&pdev->dev, 0);
+       sh_rtc_irq_set_freq(&pdev->dev, 0);
+       sh_rtc_irq_set_state(&pdev->dev, 0);
        sh_rtc_setaie(&pdev->dev, 0);
        sh_rtc_setcie(&pdev->dev, 0);
 
+       rtc->rtc_dev = rtc_device_register("sh", &pdev->dev,
+                                          &sh_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc->rtc_dev)) {
+               ret = PTR_ERR(rtc->rtc_dev);
+               free_irq(rtc->periodic_irq, rtc);
+               free_irq(rtc->carry_irq, rtc);
+               free_irq(rtc->alarm_irq, rtc);
+               goto err_unmap;
+       }
+
+       rtc->rtc_dev->max_user_freq = 256;
+
        /* reset rtc to epoch 0 if time is invalid */
        if (rtc_read_time(rtc->rtc_dev, &r) < 0) {
                rtc_time_to_tm(0, &r);
@@ -795,14 +769,13 @@ err_badres:
        return ret;
 }
 
-static int __devexit sh_rtc_remove(struct platform_device *pdev)
+static int __exit sh_rtc_remove(struct platform_device *pdev)
 {
        struct sh_rtc *rtc = platform_get_drvdata(pdev);
 
-       if (likely(rtc->rtc_dev))
-               rtc_device_unregister(rtc->rtc_dev);
+       rtc_device_unregister(rtc->rtc_dev);
+       sh_rtc_irq_set_state(&pdev->dev, 0);
 
-       sh_rtc_setpie(&pdev->dev, 0);
        sh_rtc_setaie(&pdev->dev, 0);
        sh_rtc_setcie(&pdev->dev, 0);
 
@@ -813,9 +786,8 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev)
                free_irq(rtc->alarm_irq, rtc);
        }
 
-       release_resource(rtc->res);
-
        iounmap(rtc->regbase);
+       release_resource(rtc->res);
 
        clk_disable(rtc->clk);
        clk_put(rtc->clk);
@@ -867,13 +839,12 @@ static struct platform_driver sh_rtc_platform_driver = {
                .owner  = THIS_MODULE,
                .pm     = &sh_rtc_dev_pm_ops,
        },
-       .probe          = sh_rtc_probe,
-       .remove         = __devexit_p(sh_rtc_remove),
+       .remove         = __exit_p(sh_rtc_remove),
 };
 
 static int __init sh_rtc_init(void)
 {
-       return platform_driver_register(&sh_rtc_platform_driver);
+       return platform_driver_probe(&sh_rtc_platform_driver, sh_rtc_probe);
 }
 
 static void __exit sh_rtc_exit(void)
index 8e2feb5..32dc2fc 100644 (file)
@@ -272,7 +272,8 @@ static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
                __raw_writew(data, PSCR);
        }
 }
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
+#elif defined(CONFIG_CPU_SUBTYPE_SH7757) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7763) || \
       defined(CONFIG_CPU_SUBTYPE_SH7780) || \
       defined(CONFIG_CPU_SUBTYPE_SH7785) || \
       defined(CONFIG_CPU_SUBTYPE_SH7786) || \
@@ -662,10 +663,11 @@ static irqreturn_t sci_rx_interrupt(int irq, void *port)
 static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
 {
        struct uart_port *port = ptr;
+       unsigned long flags;
 
-       spin_lock_irq(&port->lock);
+       spin_lock_irqsave(&port->lock, flags);
        sci_transmit_chars(port);
-       spin_unlock_irq(&port->lock);
+       spin_unlock_irqrestore(&port->lock, flags);
 
        return IRQ_HANDLED;
 }
index 38072c1..3e2fcf9 100644 (file)
 #elif defined(CONFIG_H8S2678)
 # define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
 # 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 SCSCR_INIT(port)      0x38
+# define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763)
 # define SCSPTR0 0xffe00024 /* 16 bit SCIF */
 # define SCSPTR1 0xffe08024 /* 16 bit SCIF */
@@ -562,6 +569,16 @@ static inline int sci_rxd_in(struct uart_port *port)
                return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */
        return 1;
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+       if (port->mapbase == 0xfe4b0000)
+               return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0;
+       if (port->mapbase == 0xfe4c0000)
+               return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0;
+       if (port->mapbase == 0xfe4d0000)
+               return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0;
+}
 #elif defined(CONFIG_CPU_SUBTYPE_SH7760)
 static inline int sci_rxd_in(struct uart_port *port)
 {
index 3dd231a..559b5fe 100644 (file)
@@ -77,7 +77,7 @@ static unsigned long ack_handle[NR_IRQS];
 static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
 {
        struct irq_chip *chip = get_irq_chip(irq);
-       return (void *)((char *)chip - offsetof(struct intc_desc_int, chip));
+       return container_of(chip, struct intc_desc_int, chip);
 }
 
 static inline unsigned int set_field(unsigned int value,
@@ -95,16 +95,19 @@ static inline unsigned int set_field(unsigned int value,
 static void write_8(unsigned long addr, unsigned long h, unsigned long data)
 {
        __raw_writeb(set_field(0, data, h), addr);
+       (void)__raw_readb(addr);        /* Defeat write posting */
 }
 
 static void write_16(unsigned long addr, unsigned long h, unsigned long data)
 {
        __raw_writew(set_field(0, data, h), addr);
+       (void)__raw_readw(addr);        /* Defeat write posting */
 }
 
 static void write_32(unsigned long addr, unsigned long h, unsigned long data)
 {
        __raw_writel(set_field(0, data, h), addr);
+       (void)__raw_readl(addr);        /* Defeat write posting */
 }
 
 static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
@@ -112,6 +115,7 @@ static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
        unsigned long flags;
        local_irq_save(flags);
        __raw_writeb(set_field(__raw_readb(addr), data, h), addr);
+       (void)__raw_readb(addr);        /* Defeat write posting */
        local_irq_restore(flags);
 }
 
@@ -120,6 +124,7 @@ static void modify_16(unsigned long addr, unsigned long h, unsigned long data)
        unsigned long flags;
        local_irq_save(flags);
        __raw_writew(set_field(__raw_readw(addr), data, h), addr);
+       (void)__raw_readw(addr);        /* Defeat write posting */
        local_irq_restore(flags);
 }
 
@@ -128,6 +133,7 @@ static void modify_32(unsigned long addr, unsigned long h, unsigned long data)
        unsigned long flags;
        local_irq_save(flags);
        __raw_writel(set_field(__raw_readl(addr), data, h), addr);
+       (void)__raw_readl(addr);        /* Defeat write posting */
        local_irq_restore(flags);
 }
 
@@ -657,16 +663,9 @@ static unsigned int __init save_reg(struct intc_desc_int *d,
        return 0;
 }
 
-static unsigned char *intc_evt2irq_table;
-
-unsigned int intc_evt2irq(unsigned int vector)
+static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc)
 {
-       unsigned int irq = evt2irq(vector);
-
-       if (intc_evt2irq_table && intc_evt2irq_table[irq])
-               irq = intc_evt2irq_table[irq];
-
-       return irq;
+       generic_handle_irq((unsigned int)get_irq_data(irq));
 }
 
 void __init register_intc_controller(struct intc_desc *desc)
@@ -739,50 +738,48 @@ void __init register_intc_controller(struct intc_desc *desc)
 
        BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
 
-       /* keep the first vector only if same enum is used multiple times */
+       /* register the vectors one by one */
        for (i = 0; i < desc->nr_vectors; i++) {
                struct intc_vect *vect = desc->vectors + i;
-               int first_irq = evt2irq(vect->vect);
+               unsigned int irq = evt2irq(vect->vect);
+               struct irq_desc *irq_desc;
 
                if (!vect->enum_id)
                        continue;
 
+               irq_desc = irq_to_desc_alloc_node(irq, numa_node_id());
+               if (unlikely(!irq_desc)) {
+                       pr_info("can't get irq_desc for %d\n", irq);
+                       continue;
+               }
+
+               intc_register_irq(desc, d, vect->enum_id, irq);
+
                for (k = i + 1; k < desc->nr_vectors; k++) {
                        struct intc_vect *vect2 = desc->vectors + k;
+                       unsigned int irq2 = evt2irq(vect2->vect);
 
                        if (vect->enum_id != vect2->enum_id)
                                continue;
 
-                       vect2->enum_id = 0;
-
-                       if (!intc_evt2irq_table)
-                               intc_evt2irq_table = kzalloc(NR_IRQS, GFP_NOWAIT);
-
-                       if (!intc_evt2irq_table) {
-                               pr_warning("intc: cannot allocate evt2irq!\n");
+                       /*
+                        * In the case of multi-evt handling and sparse
+                        * IRQ support, each vector still needs to have
+                        * its own backing irq_desc.
+                        */
+                       irq_desc = irq_to_desc_alloc_node(irq2, numa_node_id());
+                       if (unlikely(!irq_desc)) {
+                               pr_info("can't get irq_desc for %d\n", irq2);
                                continue;
                        }
 
-                       intc_evt2irq_table[evt2irq(vect2->vect)] = first_irq;
-               }
-       }
-
-       /* register the vectors one by one */
-       for (i = 0; i < desc->nr_vectors; i++) {
-               struct intc_vect *vect = desc->vectors + i;
-               unsigned int irq = evt2irq(vect->vect);
-               struct irq_desc *irq_desc;
-
-               if (!vect->enum_id)
-                       continue;
+                       vect2->enum_id = 0;
 
-               irq_desc = irq_to_desc_alloc_node(irq, numa_node_id());
-               if (unlikely(!irq_desc)) {
-                       printk(KERN_INFO "can not get irq_desc for %d\n", irq);
-                       continue;
+                       /* redirect this interrupts to the first one */
+                       set_irq_chip_and_handler_name(irq2, &d->chip,
+                                       intc_redirect_irq, "redirect");
+                       set_irq_data(irq2, (void *)irq);
                }
-
-               intc_register_irq(desc, d, vect->enum_id, irq);
        }
 }
 
index 3f06818..02347c5 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
 #include <linux/stringify.h>
+#include <linux/pm_runtime.h>
 
 #define DRIVER_NAME "uio_pdrv_genirq"
 
@@ -27,8 +28,27 @@ struct uio_pdrv_genirq_platdata {
        struct uio_info *uioinfo;
        spinlock_t lock;
        unsigned long flags;
+       struct platform_device *pdev;
 };
 
+static int uio_pdrv_genirq_open(struct uio_info *info, struct inode *inode)
+{
+       struct uio_pdrv_genirq_platdata *priv = info->priv;
+
+       /* Wait until the Runtime PM code has woken up the device */
+       pm_runtime_get_sync(&priv->pdev->dev);
+       return 0;
+}
+
+static int uio_pdrv_genirq_release(struct uio_info *info, struct inode *inode)
+{
+       struct uio_pdrv_genirq_platdata *priv = info->priv;
+
+       /* Tell the Runtime PM code that the device has become idle */
+       pm_runtime_put_sync(&priv->pdev->dev);
+       return 0;
+}
+
 static irqreturn_t uio_pdrv_genirq_handler(int irq, struct uio_info *dev_info)
 {
        struct uio_pdrv_genirq_platdata *priv = dev_info->priv;
@@ -97,6 +117,7 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
        priv->uioinfo = uioinfo;
        spin_lock_init(&priv->lock);
        priv->flags = 0; /* interrupt is enabled to begin with */
+       priv->pdev = pdev;
 
        uiomem = &uioinfo->mem[0];
 
@@ -136,8 +157,17 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
        uioinfo->irq_flags |= IRQF_DISABLED;
        uioinfo->handler = uio_pdrv_genirq_handler;
        uioinfo->irqcontrol = uio_pdrv_genirq_irqcontrol;
+       uioinfo->open = uio_pdrv_genirq_open;
+       uioinfo->release = uio_pdrv_genirq_release;
        uioinfo->priv = priv;
 
+       /* Enable Runtime PM for this device:
+        * The device starts in suspended state to allow the hardware to be
+        * turned off by default. The Runtime PM bus code should power on the
+        * hardware and enable clocks at open().
+        */
+       pm_runtime_enable(&pdev->dev);
+
        ret = uio_register_device(&pdev->dev, priv->uioinfo);
        if (ret) {
                dev_err(&pdev->dev, "unable to register uio device\n");
@@ -157,16 +187,40 @@ static int uio_pdrv_genirq_remove(struct platform_device *pdev)
        struct uio_pdrv_genirq_platdata *priv = platform_get_drvdata(pdev);
 
        uio_unregister_device(priv->uioinfo);
+       pm_runtime_disable(&pdev->dev);
        kfree(priv);
        return 0;
 }
 
+static int uio_pdrv_genirq_runtime_nop(struct device *dev)
+{
+       /* Runtime PM callback shared between ->runtime_suspend()
+        * and ->runtime_resume(). Simply returns success.
+        *
+        * In this driver pm_runtime_get_sync() and pm_runtime_put_sync()
+        * are used at open() and release() time. This allows the
+        * Runtime PM code to turn off power to the device while the
+        * device is unused, ie before open() and after release().
+        *
+        * This Runtime PM callback does not need to save or restore
+        * any registers since user space is responsbile for hardware
+        * register reinitialization after open().
+        */
+       return 0;
+}
+
+static struct dev_pm_ops uio_pdrv_genirq_dev_pm_ops = {
+       .runtime_suspend = uio_pdrv_genirq_runtime_nop,
+       .runtime_resume = uio_pdrv_genirq_runtime_nop,
+};
+
 static struct platform_driver uio_pdrv_genirq = {
        .probe = uio_pdrv_genirq_probe,
        .remove = uio_pdrv_genirq_remove,
        .driver = {
                .name = DRIVER_NAME,
                .owner = THIS_MODULE,
+               .pm = &uio_pdrv_genirq_dev_pm_ops,
        },
 };
 
index 7f8e83a..9f986b4 100644 (file)
@@ -251,6 +251,24 @@ config USB_PXA25X_SMALL
        default y if USB_ETH
        default y if USB_G_SERIAL
 
+config USB_GADGET_R8A66597
+       boolean "Renesas R8A66597 USB Peripheral Controller"
+       select USB_GADGET_DUALSPEED
+       help
+          R8A66597 is a discrete USB host and peripheral controller chip that
+          supports both full and high speed USB 2.0 data transfers.
+          It has nine configurable endpoints, and endpoint zero.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "r8a66597_udc" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_R8A66597
+       tristate
+       depends on USB_GADGET_R8A66597
+       default USB_GADGET
+       select USB_GADGET_SELECTED
+
 config USB_GADGET_PXA27X
        boolean "PXA 27x"
        depends on ARCH_PXA && (PXA27x || PXA3xx)
@@ -360,16 +378,6 @@ config USB_M66592
        default USB_GADGET
        select USB_GADGET_SELECTED
 
-config SUPERH_BUILT_IN_M66592
-       boolean "Enable SuperH built-in USB like the M66592"
-       depends on USB_GADGET_M66592 && CPU_SUBTYPE_SH7722
-       help
-          SH7722 has USB like the M66592.
-
-          The transfer rate is very slow when use "Ethernet Gadget".
-          However, this problem is improved if change a value of
-          NET_IP_ALIGN to 4.
-
 #
 # Controllers available only in discrete form (and all PCI controllers)
 #
index e6017e6..9d7b87c 100644 (file)
@@ -23,6 +23,7 @@ ifeq ($(CONFIG_ARCH_MXC),y)
 fsl_usb2_udc-objs              += fsl_mx3_udc.o
 endif
 obj-$(CONFIG_USB_M66592)       += m66592-udc.o
+obj-$(CONFIG_USB_R8A66597)     += r8a66597-udc.o
 obj-$(CONFIG_USB_FSL_QE)       += fsl_qe_udc.o
 obj-$(CONFIG_USB_CI13XXX)      += ci13xxx_udc.o
 obj-$(CONFIG_USB_S3C_HSOTG)    += s3c-hsotg.o
index 8e0e9a0..f2d270b 100644 (file)
 // CONFIG_USB_GADGET_AU1X00
 // ...
 
+#ifdef CONFIG_USB_GADGET_R8A66597
+#define        gadget_is_r8a66597(g)   !strcmp("r8a66597_udc", (g)->name)
+#else
+#define        gadget_is_r8a66597(g)   0
+#endif
+
 
 /**
  * usb_gadget_controller_number - support bcdDevice id convention
@@ -239,6 +245,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
                return 0x23;
        else if (gadget_is_langwell(gadget))
                return 0x24;
+       else if (gadget_is_r8a66597(gadget))
+               return 0x25;
        return -ENOENT;
 }
 
index 43dcf9e..a8c8543 100644 (file)
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
-
+#include <linux/err.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 
 #include "m66592-udc.h"
 
-
 MODULE_DESCRIPTION("M66592 USB gadget driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yoshihiro Shimoda");
 MODULE_ALIAS("platform:m66592_udc");
 
-#define DRIVER_VERSION "18 Oct 2007"
-
-/* module parameters */
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
-static unsigned short endian = M66592_LITTLE;
-module_param(endian, ushort, 0644);
-MODULE_PARM_DESC(endian, "data endian: big=0, little=0 (default=0)");
-#else
-static unsigned short clock = M66592_XTAL24;
-module_param(clock, ushort, 0644);
-MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
-               "(default=16384)");
-
-static unsigned short vif = M66592_LDRV;
-module_param(vif, ushort, 0644);
-MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0 (default=32768)");
-
-static unsigned short endian;
-module_param(endian, ushort, 0644);
-MODULE_PARM_DESC(endian, "data endian: big=256, little=0 (default=0)");
-
-static unsigned short irq_sense = M66592_INTL;
-module_param(irq_sense, ushort, 0644);
-MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 "
-               "(default=2)");
-#endif
+#define DRIVER_VERSION "21 July 2009"
 
 static const char udc_name[] = "m66592_udc";
 static const char *m66592_ep_name[] = {
@@ -244,6 +218,7 @@ static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
 static inline void pipe_change(struct m66592 *m66592, u16 pipenum)
 {
        struct m66592_ep *ep = m66592->pipenum2ep[pipenum];
+       unsigned short mbw;
 
        if (ep->use_dma)
                return;
@@ -252,7 +227,12 @@ static inline void pipe_change(struct m66592 *m66592, u16 pipenum)
 
        ndelay(450);
 
-       m66592_bset(m66592, M66592_MBW, ep->fifosel);
+       if (m66592->pdata->on_chip)
+               mbw = M66592_MBW_32;
+       else
+               mbw = M66592_MBW_16;
+
+       m66592_bset(m66592, mbw, ep->fifosel);
 }
 
 static int pipe_buffer_setting(struct m66592 *m66592,
@@ -276,24 +256,27 @@ static int pipe_buffer_setting(struct m66592 *m66592,
                buf_bsize = 0;
                break;
        case M66592_BULK:
-               bufnum = m66592->bi_bufnum +
-                        (info->pipe - M66592_BASE_PIPENUM_BULK) * 16;
-               m66592->bi_bufnum += 16;
+               /* isochronous pipes may be used as bulk pipes */
+               if (info->pipe > M66592_BASE_PIPENUM_BULK)
+                       bufnum = info->pipe - M66592_BASE_PIPENUM_BULK;
+               else
+                       bufnum = info->pipe - M66592_BASE_PIPENUM_ISOC;
+
+               bufnum = M66592_BASE_BUFNUM + (bufnum * 16);
                buf_bsize = 7;
                pipecfg |= M66592_DBLB;
                if (!info->dir_in)
                        pipecfg |= M66592_SHTNAK;
                break;
        case M66592_ISO:
-               bufnum = m66592->bi_bufnum +
+               bufnum = M66592_BASE_BUFNUM +
                         (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
-               m66592->bi_bufnum += 16;
                buf_bsize = 7;
                break;
        }
-       if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
-               pr_err("m66592 pipe memory is insufficient(%d)\n",
-                               m66592->bi_bufnum);
+
+       if (buf_bsize && ((bufnum + 16) >= M66592_MAX_BUFNUM)) {
+               pr_err("m66592 pipe memory is insufficient\n");
                return -ENOMEM;
        }
 
@@ -313,17 +296,6 @@ static void pipe_buffer_release(struct m66592 *m66592,
        if (info->pipe == 0)
                return;
 
-       switch (info->type) {
-       case M66592_BULK:
-               if (is_bulk_pipe(info->pipe))
-                       m66592->bi_bufnum -= 16;
-               break;
-       case M66592_ISO:
-               if (is_isoc_pipe(info->pipe))
-                       m66592->bi_bufnum -= 16;
-               break;
-       }
-
        if (is_bulk_pipe(info->pipe)) {
                m66592->bulk--;
        } else if (is_interrupt_pipe(info->pipe))
@@ -340,6 +312,7 @@ static void pipe_buffer_release(struct m66592 *m66592,
 static void pipe_initialize(struct m66592_ep *ep)
 {
        struct m66592 *m66592 = ep->m66592;
+       unsigned short mbw;
 
        m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel);
 
@@ -351,7 +324,12 @@ static void pipe_initialize(struct m66592_ep *ep)
 
                ndelay(450);
 
-               m66592_bset(m66592, M66592_MBW, ep->fifosel);
+               if (m66592->pdata->on_chip)
+                       mbw = M66592_MBW_32;
+               else
+                       mbw = M66592_MBW_16;
+
+               m66592_bset(m66592, mbw, ep->fifosel);
        }
 }
 
@@ -367,15 +345,13 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
                        ep->fifosel = M66592_D0FIFOSEL;
                        ep->fifoctr = M66592_D0FIFOCTR;
                        ep->fifotrn = M66592_D0FIFOTRN;
-#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
-               } else if (m66592->num_dma == 1) {
+               } else if (!m66592->pdata->on_chip && m66592->num_dma == 1) {
                        m66592->num_dma++;
                        ep->use_dma = 1;
                        ep->fifoaddr = M66592_D1FIFO;
                        ep->fifosel = M66592_D1FIFOSEL;
                        ep->fifoctr = M66592_D1FIFOCTR;
                        ep->fifotrn = M66592_D1FIFOTRN;
-#endif
                } else {
                        ep->use_dma = 0;
                        ep->fifoaddr = M66592_CFIFO;
@@ -620,76 +596,120 @@ static void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
        }
 }
 
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
 static void init_controller(struct m66592 *m66592)
 {
-       m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);         /* High spd */
-       m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
-       m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
-       m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+       unsigned int endian;
 
-       /* This is a workaound for SH7722 2nd cut */
-       m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
-       m66592_bset(m66592, 0x1000, M66592_TESTMODE);
-       m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
+       if (m66592->pdata->on_chip) {
+               if (m66592->pdata->endian)
+                       endian = 0; /* big endian */
+               else
+                       endian = M66592_LITTLE; /* little endian */
 
-       m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
+               m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */
+               m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
+               m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+               m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
 
-       m66592_write(m66592, 0, M66592_CFBCFG);
-       m66592_write(m66592, 0, M66592_D0FBCFG);
-       m66592_bset(m66592, endian, M66592_CFBCFG);
-       m66592_bset(m66592, endian, M66592_D0FBCFG);
-}
-#else  /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
-static void init_controller(struct m66592 *m66592)
-{
-       m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
-                       M66592_PINCFG);
-       m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);         /* High spd */
-       m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, M66592_SYSCFG);
+               /* This is a workaound for SH7722 2nd cut */
+               m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
+               m66592_bset(m66592, 0x1000, M66592_TESTMODE);
+               m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
 
-       m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
-       m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
-       m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+               m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
+
+               m66592_write(m66592, 0, M66592_CFBCFG);
+               m66592_write(m66592, 0, M66592_D0FBCFG);
+               m66592_bset(m66592, endian, M66592_CFBCFG);
+               m66592_bset(m66592, endian, M66592_D0FBCFG);
+       } else {
+               unsigned int clock, vif, irq_sense;
+
+               if (m66592->pdata->endian)
+                       endian = M66592_BIGEND; /* big endian */
+               else
+                       endian = 0; /* little endian */
+
+               if (m66592->pdata->vif)
+                       vif = M66592_LDRV; /* 3.3v */
+               else
+                       vif = 0; /* 1.5v */
+
+               switch (m66592->pdata->xtal) {
+               case M66592_PLATDATA_XTAL_12MHZ:
+                       clock = M66592_XTAL12;
+                       break;
+               case M66592_PLATDATA_XTAL_24MHZ:
+                       clock = M66592_XTAL24;
+                       break;
+               case M66592_PLATDATA_XTAL_48MHZ:
+                       clock = M66592_XTAL48;
+                       break;
+               default:
+                       pr_warning("m66592-udc: xtal configuration error\n");
+                       clock = 0;
+               }
+
+               switch (m66592->irq_trigger) {
+               case IRQF_TRIGGER_LOW:
+                       irq_sense = M66592_INTL;
+                       break;
+               case IRQF_TRIGGER_FALLING:
+                       irq_sense = 0;
+                       break;
+               default:
+                       pr_warning("m66592-udc: irq trigger config error\n");
+                       irq_sense = 0;
+               }
 
-       m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+               m66592_bset(m66592,
+                           (vif & M66592_LDRV) | (endian & M66592_BIGEND),
+                           M66592_PINCFG);
+               m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */
+               m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL,
+                           M66592_SYSCFG);
+               m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
+               m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+               m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+
+               m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
 
-       msleep(3);
+               msleep(3);
 
-       m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
+               m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
 
-       msleep(1);
+               msleep(1);
 
-       m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
+               m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
 
-       m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
-       m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
-                       M66592_DMA0CFG);
+               m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
+               m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
+                            M66592_DMA0CFG);
+       }
 }
-#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 
 static void disable_controller(struct m66592 *m66592)
 {
-#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
-       m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
-       udelay(1);
-       m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
-       udelay(1);
-       m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
-       udelay(1);
-       m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
-#endif
+       if (!m66592->pdata->on_chip) {
+               m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
+               udelay(1);
+               m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
+               udelay(1);
+               m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
+               udelay(1);
+               m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
+       }
 }
 
 static void m66592_start_xclock(struct m66592 *m66592)
 {
-#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
        u16 tmp;
 
-       tmp = m66592_read(m66592, M66592_SYSCFG);
-       if (!(tmp & M66592_XCKE))
-               m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
-#endif
+       if (!m66592->pdata->on_chip) {
+               tmp = m66592_read(m66592, M66592_SYSCFG);
+               if (!(tmp & M66592_XCKE))
+                       m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+       }
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1177,8 +1197,7 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
        intsts0 = m66592_read(m66592, M66592_INTSTS0);
        intenb0 = m66592_read(m66592, M66592_INTENB0);
 
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
-       if (!intsts0 && !intenb0) {
+       if (m66592->pdata->on_chip && !intsts0 && !intenb0) {
                /*
                 * When USB clock stops, it cannot read register. Even if a
                 * clock stops, the interrupt occurs. So this driver turn on
@@ -1188,7 +1207,6 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
                intsts0 = m66592_read(m66592, M66592_INTSTS0);
                intenb0 = m66592_read(m66592, M66592_INTENB0);
        }
-#endif
 
        savepipe = m66592_read(m66592, M66592_CFIFOSEL);
 
@@ -1534,9 +1552,11 @@ static int __exit m66592_remove(struct platform_device *pdev)
        iounmap(m66592->reg);
        free_irq(platform_get_irq(pdev, 0), m66592);
        m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
-       clk_disable(m66592->clk);
-       clk_put(m66592->clk);
+#ifdef CONFIG_HAVE_CLK
+       if (m66592->pdata->on_chip) {
+               clk_disable(m66592->clk);
+               clk_put(m66592->clk);
+       }
 #endif
        kfree(m66592);
        return 0;
@@ -1548,11 +1568,10 @@ static void nop_completion(struct usb_ep *ep, struct usb_request *r)
 
 static int __init m66592_probe(struct platform_device *pdev)
 {
-       struct resource *res;
-       int irq;
+       struct resource *res, *ires;
        void __iomem *reg = NULL;
        struct m66592 *m66592 = NULL;
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
+#ifdef CONFIG_HAVE_CLK
        char clk_name[8];
 #endif
        int ret = 0;
@@ -1565,10 +1584,11 @@ static int __init m66592_probe(struct platform_device *pdev)
                goto clean_up;
        }
 
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
+       ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!ires) {
                ret = -ENODEV;
-               pr_err("platform_get_irq error.\n");
+               dev_err(&pdev->dev,
+                       "platform_get_resource IORESOURCE_IRQ error.\n");
                goto clean_up;
        }
 
@@ -1579,6 +1599,12 @@ static int __init m66592_probe(struct platform_device *pdev)
                goto clean_up;
        }
 
+       if (pdev->dev.platform_data == NULL) {
+               dev_err(&pdev->dev, "no platform data\n");
+               ret = -ENODEV;
+               goto clean_up;
+       }
+
        /* initialize ucd */
        m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
        if (m66592 == NULL) {
@@ -1586,6 +1612,9 @@ static int __init m66592_probe(struct platform_device *pdev)
                goto clean_up;
        }
 
+       m66592->pdata = pdev->dev.platform_data;
+       m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
+
        spin_lock_init(&m66592->lock);
        dev_set_drvdata(&pdev->dev, m66592);
 
@@ -1603,24 +1632,25 @@ static int __init m66592_probe(struct platform_device *pdev)
        m66592->timer.data = (unsigned long)m66592;
        m66592->reg = reg;
 
-       m66592->bi_bufnum = M66592_BASE_BUFNUM;
-
-       ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
+       ret = request_irq(ires->start, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
                        udc_name, m66592);
        if (ret < 0) {
                pr_err("request_irq error (%d)\n", ret);
                goto clean_up;
        }
 
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
-       snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id);
-       m66592->clk = clk_get(&pdev->dev, clk_name);
-       if (IS_ERR(m66592->clk)) {
-               dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
-               ret = PTR_ERR(m66592->clk);
-               goto clean_up2;
+#ifdef CONFIG_HAVE_CLK
+       if (m66592->pdata->on_chip) {
+               snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id);
+               m66592->clk = clk_get(&pdev->dev, clk_name);
+               if (IS_ERR(m66592->clk)) {
+                       dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
+                               clk_name);
+                       ret = PTR_ERR(m66592->clk);
+                       goto clean_up2;
+               }
+               clk_enable(m66592->clk);
        }
-       clk_enable(m66592->clk);
 #endif
        INIT_LIST_HEAD(&m66592->gadget.ep_list);
        m66592->gadget.ep0 = &m66592->ep[0].ep;
@@ -1662,12 +1692,14 @@ static int __init m66592_probe(struct platform_device *pdev)
        return 0;
 
 clean_up3:
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
-       clk_disable(m66592->clk);
-       clk_put(m66592->clk);
+#ifdef CONFIG_HAVE_CLK
+       if (m66592->pdata->on_chip) {
+               clk_disable(m66592->clk);
+               clk_put(m66592->clk);
+       }
 clean_up2:
 #endif
-       free_irq(irq, m66592);
+       free_irq(ires->start, m66592);
 clean_up:
        if (m66592) {
                if (m66592->ep0_req)
index 286ce07..8b960de 100644 (file)
 #ifndef __M66592_UDC_H__
 #define __M66592_UDC_H__
 
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
+#ifdef CONFIG_HAVE_CLK
 #include <linux/clk.h>
 #endif
 
+#include <linux/usb/m66592.h>
+
 #define M66592_SYSCFG          0x00
 #define M66592_XTAL            0xC000  /* b15-14: Crystal selection */
 #define   M66592_XTAL48                 0x8000         /* 48MHz */
 #define   M66592_P_TST_J        0x0001         /* PERI TEST J */
 #define   M66592_P_TST_NORMAL   0x0000         /* PERI Normal Mode */
 
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+/* built-in registers */
 #define M66592_CFBCFG          0x0A
 #define M66592_D0FBCFG         0x0C
 #define M66592_LITTLE          0x0100  /* b8: Little endian mode */
-#else
+/* external chip case */
 #define M66592_PINCFG          0x0A
 #define M66592_LDRV            0x8000  /* b15: Drive Current Adjust */
 #define M66592_BIGEND          0x0100  /* b8: Big endian mode */
 #define M66592_PKTM            0x0020  /* b5: Packet mode */
 #define M66592_DENDE           0x0010  /* b4: Dend enable */
 #define M66592_OBUS            0x0004  /* b2: OUTbus mode */
-#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 
+/* common case */
 #define M66592_CFIFO           0x10
 #define M66592_D0FIFO          0x14
 #define M66592_D1FIFO          0x18
 #define M66592_REW             0x4000  /* b14: Buffer rewind */
 #define M66592_DCLRM           0x2000  /* b13: DMA buffer clear mode */
 #define M66592_DREQE           0x1000  /* b12: DREQ output enable */
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
-#define M66592_MBW             0x0800  /* b11: Maximum bit width for FIFO */
-#else
-#define M66592_MBW             0x0400  /* b10: Maximum bit width for FIFO */
-#define   M66592_MBW_8          0x0000   /*  8bit */
-#define   M66592_MBW_16                 0x0400   /* 16bit */
-#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
+#define M66592_MBW_8           0x0000   /*  8bit */
+#define M66592_MBW_16          0x0400   /* 16bit */
+#define M66592_MBW_32          0x0800   /* 32bit */
 #define M66592_TRENB           0x0200  /* b9: Transaction counter enable */
 #define M66592_TRCLR           0x0100  /* b8: Transaction counter clear */
 #define M66592_DEZPM           0x0080  /* b7: Zero-length packet mode */
@@ -480,9 +478,11 @@ struct m66592_ep {
 struct m66592 {
        spinlock_t              lock;
        void __iomem            *reg;
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
+#ifdef CONFIG_HAVE_CLK
        struct clk *clk;
 #endif
+       struct m66592_platdata  *pdata;
+       unsigned long           irq_trigger;
 
        struct usb_gadget               gadget;
        struct usb_gadget_driver        *driver;
@@ -506,7 +506,6 @@ struct m66592 {
        int interrupt;
        int isochronous;
        int num_dma;
-       int bi_bufnum;  /* bulk and isochronous's bufnum */
 };
 
 #define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
@@ -547,13 +546,13 @@ static inline void m66592_read_fifo(struct m66592 *m66592,
 {
        unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
 
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
-       len = (len + 3) / 4;
-       insl(fifoaddr, buf, len);
-#else
-       len = (len + 1) / 2;
-       insw(fifoaddr, buf, len);
-#endif
+       if (m66592->pdata->on_chip) {
+               len = (len + 3) / 4;
+               insl(fifoaddr, buf, len);
+       } else {
+               len = (len + 1) / 2;
+               insw(fifoaddr, buf, len);
+       }
 }
 
 static inline void m66592_write(struct m66592 *m66592, u16 val,
@@ -567,33 +566,34 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
                void *buf, unsigned long len)
 {
        unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
-       unsigned long count;
-       unsigned char *pb;
-       int i;
-
-       count = len / 4;
-       outsl(fifoaddr, buf, count);
-
-       if (len & 0x00000003) {
-               pb = buf + count * 4;
-               for (i = 0; i < (len & 0x00000003); i++) {
-                       if (m66592_read(m66592, M66592_CFBCFG)) /* little */
-                               outb(pb[i], fifoaddr + (3 - i));
-                       else
-                               outb(pb[i], fifoaddr + i);
+
+       if (m66592->pdata->on_chip) {
+               unsigned long count;
+               unsigned char *pb;
+               int i;
+
+               count = len / 4;
+               outsl(fifoaddr, buf, count);
+
+               if (len & 0x00000003) {
+                       pb = buf + count * 4;
+                       for (i = 0; i < (len & 0x00000003); i++) {
+                               if (m66592_read(m66592, M66592_CFBCFG)) /* le */
+                                       outb(pb[i], fifoaddr + (3 - i));
+                               else
+                                       outb(pb[i], fifoaddr + i);
+                       }
+               }
+       } else {
+               unsigned long odd = len & 0x0001;
+
+               len = len / 2;
+               outsw(fifoaddr, buf, len);
+               if (odd) {
+                       unsigned char *p = buf + len*2;
+                       outb(*p, fifoaddr);
                }
        }
-#else
-       unsigned long odd = len & 0x0001;
-
-       len = len / 2;
-       outsw(fifoaddr, buf, len);
-       if (odd) {
-               unsigned char *p = buf + len*2;
-               outb(*p, fifoaddr);
-       }
-#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 }
 
 static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
new file mode 100644 (file)
index 0000000..e220fb8
--- /dev/null
@@ -0,0 +1,1689 @@
+/*
+ * R8A66597 UDC (USB gadget)
+ *
+ * Copyright (C) 2006-2009 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include "r8a66597-udc.h"
+
+#define DRIVER_VERSION "2009-08-18"
+
+static const char udc_name[] = "r8a66597_udc";
+static const char *r8a66597_ep_name[] = {
+       "ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7",
+       "ep8", "ep9",
+};
+
+static void disable_controller(struct r8a66597 *r8a66597);
+static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req);
+static void irq_packet_write(struct r8a66597_ep *ep,
+                               struct r8a66597_request *req);
+static int r8a66597_queue(struct usb_ep *_ep, struct usb_request *_req,
+                       gfp_t gfp_flags);
+
+static void transfer_complete(struct r8a66597_ep *ep,
+               struct r8a66597_request *req, int status);
+
+/*-------------------------------------------------------------------------*/
+static inline u16 get_usb_speed(struct r8a66597 *r8a66597)
+{
+       return r8a66597_read(r8a66597, DVSTCTR0) & RHST;
+}
+
+static void enable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum,
+               unsigned long reg)
+{
+       u16 tmp;
+
+       tmp = r8a66597_read(r8a66597, INTENB0);
+       r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE,
+                       INTENB0);
+       r8a66597_bset(r8a66597, (1 << pipenum), reg);
+       r8a66597_write(r8a66597, tmp, INTENB0);
+}
+
+static void disable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum,
+               unsigned long reg)
+{
+       u16 tmp;
+
+       tmp = r8a66597_read(r8a66597, INTENB0);
+       r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE,
+                       INTENB0);
+       r8a66597_bclr(r8a66597, (1 << pipenum), reg);
+       r8a66597_write(r8a66597, tmp, INTENB0);
+}
+
+static void r8a66597_usb_connect(struct r8a66597 *r8a66597)
+{
+       r8a66597_bset(r8a66597, CTRE, INTENB0);
+       r8a66597_bset(r8a66597, BEMPE | BRDYE, INTENB0);
+
+       r8a66597_bset(r8a66597, DPRPU, SYSCFG0);
+}
+
+static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
+{
+       r8a66597_bclr(r8a66597, CTRE, INTENB0);
+       r8a66597_bclr(r8a66597, BEMPE | BRDYE, INTENB0);
+       r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
+
+       r8a66597->gadget.speed = USB_SPEED_UNKNOWN;
+       spin_unlock(&r8a66597->lock);
+       r8a66597->driver->disconnect(&r8a66597->gadget);
+       spin_lock(&r8a66597->lock);
+
+       disable_controller(r8a66597);
+       INIT_LIST_HEAD(&r8a66597->ep[0].queue);
+}
+
+static inline u16 control_reg_get_pid(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       u16 pid = 0;
+       unsigned long offset;
+
+       if (pipenum == 0)
+               pid = r8a66597_read(r8a66597, DCPCTR) & PID;
+       else if (pipenum < R8A66597_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               pid = r8a66597_read(r8a66597, offset) & PID;
+       } else
+               printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+
+       return pid;
+}
+
+static inline void control_reg_set_pid(struct r8a66597 *r8a66597, u16 pipenum,
+               u16 pid)
+{
+       unsigned long offset;
+
+       if (pipenum == 0)
+               r8a66597_mdfy(r8a66597, pid, PID, DCPCTR);
+       else if (pipenum < R8A66597_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               r8a66597_mdfy(r8a66597, pid, PID, offset);
+       } else
+               printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+}
+
+static inline void pipe_start(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       control_reg_set_pid(r8a66597, pipenum, PID_BUF);
+}
+
+static inline void pipe_stop(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       control_reg_set_pid(r8a66597, pipenum, PID_NAK);
+}
+
+static inline void pipe_stall(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       control_reg_set_pid(r8a66597, pipenum, PID_STALL);
+}
+
+static inline u16 control_reg_get(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       u16 ret = 0;
+       unsigned long offset;
+
+       if (pipenum == 0)
+               ret = r8a66597_read(r8a66597, DCPCTR);
+       else if (pipenum < R8A66597_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               ret = r8a66597_read(r8a66597, offset);
+       } else
+               printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+
+       return ret;
+}
+
+static inline void control_reg_sqclr(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       unsigned long offset;
+
+       pipe_stop(r8a66597, pipenum);
+
+       if (pipenum == 0)
+               r8a66597_bset(r8a66597, SQCLR, DCPCTR);
+       else if (pipenum < R8A66597_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               r8a66597_bset(r8a66597, SQCLR, offset);
+       } else
+               printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum);
+}
+
+static inline int get_buffer_size(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       u16 tmp;
+       int size;
+
+       if (pipenum == 0) {
+               tmp = r8a66597_read(r8a66597, DCPCFG);
+               if ((tmp & R8A66597_CNTMD) != 0)
+                       size = 256;
+               else {
+                       tmp = r8a66597_read(r8a66597, DCPMAXP);
+                       size = tmp & MAXP;
+               }
+       } else {
+               r8a66597_write(r8a66597, pipenum, PIPESEL);
+               tmp = r8a66597_read(r8a66597, PIPECFG);
+               if ((tmp & R8A66597_CNTMD) != 0) {
+                       tmp = r8a66597_read(r8a66597, PIPEBUF);
+                       size = ((tmp >> 10) + 1) * 64;
+               } else {
+                       tmp = r8a66597_read(r8a66597, PIPEMAXP);
+                       size = tmp & MXPS;
+               }
+       }
+
+       return size;
+}
+
+static inline unsigned short mbw_value(struct r8a66597 *r8a66597)
+{
+       if (r8a66597->pdata->on_chip)
+               return MBW_32;
+       else
+               return MBW_16;
+}
+
+static inline void pipe_change(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum];
+
+       if (ep->use_dma)
+               return;
+
+       r8a66597_mdfy(r8a66597, pipenum, CURPIPE, ep->fifosel);
+
+       ndelay(450);
+
+       r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel);
+}
+
+static int pipe_buffer_setting(struct r8a66597 *r8a66597,
+               struct r8a66597_pipe_info *info)
+{
+       u16 bufnum = 0, buf_bsize = 0;
+       u16 pipecfg = 0;
+
+       if (info->pipe == 0)
+               return -EINVAL;
+
+       r8a66597_write(r8a66597, info->pipe, PIPESEL);
+
+       if (info->dir_in)
+               pipecfg |= R8A66597_DIR;
+       pipecfg |= info->type;
+       pipecfg |= info->epnum;
+       switch (info->type) {
+       case R8A66597_INT:
+               bufnum = 4 + (info->pipe - R8A66597_BASE_PIPENUM_INT);
+               buf_bsize = 0;
+               break;
+       case R8A66597_BULK:
+               /* isochronous pipes may be used as bulk pipes */
+               if (info->pipe > R8A66597_BASE_PIPENUM_BULK)
+                       bufnum = info->pipe - R8A66597_BASE_PIPENUM_BULK;
+               else
+                       bufnum = info->pipe - R8A66597_BASE_PIPENUM_ISOC;
+
+               bufnum = R8A66597_BASE_BUFNUM + (bufnum * 16);
+               buf_bsize = 7;
+               pipecfg |= R8A66597_DBLB;
+               if (!info->dir_in)
+                       pipecfg |= R8A66597_SHTNAK;
+               break;
+       case R8A66597_ISO:
+               bufnum = R8A66597_BASE_BUFNUM +
+                        (info->pipe - R8A66597_BASE_PIPENUM_ISOC) * 16;
+               buf_bsize = 7;
+               break;
+       }
+
+       if (buf_bsize && ((bufnum + 16) >= R8A66597_MAX_BUFNUM)) {
+               pr_err(KERN_ERR "r8a66597 pipe memory is insufficient\n");
+               return -ENOMEM;
+       }
+
+       r8a66597_write(r8a66597, pipecfg, PIPECFG);
+       r8a66597_write(r8a66597, (buf_bsize << 10) | (bufnum), PIPEBUF);
+       r8a66597_write(r8a66597, info->maxpacket, PIPEMAXP);
+       if (info->interval)
+               info->interval--;
+       r8a66597_write(r8a66597, info->interval, PIPEPERI);
+
+       return 0;
+}
+
+static void pipe_buffer_release(struct r8a66597 *r8a66597,
+                               struct r8a66597_pipe_info *info)
+{
+       if (info->pipe == 0)
+               return;
+
+       if (is_bulk_pipe(info->pipe))
+               r8a66597->bulk--;
+       else if (is_interrupt_pipe(info->pipe))
+               r8a66597->interrupt--;
+       else if (is_isoc_pipe(info->pipe)) {
+               r8a66597->isochronous--;
+               if (info->type == R8A66597_BULK)
+                       r8a66597->bulk--;
+       } else
+               printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n",
+                               info->pipe);
+}
+
+static void pipe_initialize(struct r8a66597_ep *ep)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+
+       r8a66597_mdfy(r8a66597, 0, CURPIPE, ep->fifosel);
+
+       r8a66597_write(r8a66597, ACLRM, ep->pipectr);
+       r8a66597_write(r8a66597, 0, ep->pipectr);
+       r8a66597_write(r8a66597, SQCLR, ep->pipectr);
+       if (ep->use_dma) {
+               r8a66597_mdfy(r8a66597, ep->pipenum, CURPIPE, ep->fifosel);
+
+               ndelay(450);
+
+               r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel);
+       }
+}
+
+static void r8a66597_ep_setting(struct r8a66597 *r8a66597,
+                               struct r8a66597_ep *ep,
+                               const struct usb_endpoint_descriptor *desc,
+                               u16 pipenum, int dma)
+{
+       ep->use_dma = 0;
+       ep->fifoaddr = CFIFO;
+       ep->fifosel = CFIFOSEL;
+       ep->fifoctr = CFIFOCTR;
+       ep->fifotrn = 0;
+
+       ep->pipectr = get_pipectr_addr(pipenum);
+       ep->pipenum = pipenum;
+       ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+       r8a66597->pipenum2ep[pipenum] = ep;
+       r8a66597->epaddr2ep[desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK]
+               = ep;
+       INIT_LIST_HEAD(&ep->queue);
+}
+
+static void r8a66597_ep_release(struct r8a66597_ep *ep)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+       u16 pipenum = ep->pipenum;
+
+       if (pipenum == 0)
+               return;
+
+       if (ep->use_dma)
+               r8a66597->num_dma--;
+       ep->pipenum = 0;
+       ep->busy = 0;
+       ep->use_dma = 0;
+}
+
+static int alloc_pipe_config(struct r8a66597_ep *ep,
+               const struct usb_endpoint_descriptor *desc)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+       struct r8a66597_pipe_info info;
+       int dma = 0;
+       unsigned char *counter;
+       int ret;
+
+       ep->desc = desc;
+
+       if (ep->pipenum)        /* already allocated pipe  */
+               return 0;
+
+       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_BULK:
+               if (r8a66597->bulk >= R8A66597_MAX_NUM_BULK) {
+                       if (r8a66597->isochronous >= R8A66597_MAX_NUM_ISOC) {
+                               printk(KERN_ERR "bulk pipe is insufficient\n");
+                               return -ENODEV;
+                       } else {
+                               info.pipe = R8A66597_BASE_PIPENUM_ISOC
+                                               + r8a66597->isochronous;
+                               counter = &r8a66597->isochronous;
+                       }
+               } else {
+                       info.pipe = R8A66597_BASE_PIPENUM_BULK + r8a66597->bulk;
+                       counter = &r8a66597->bulk;
+               }
+               info.type = R8A66597_BULK;
+               dma = 1;
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               if (r8a66597->interrupt >= R8A66597_MAX_NUM_INT) {
+                       printk(KERN_ERR "interrupt pipe is insufficient\n");
+                       return -ENODEV;
+               }
+               info.pipe = R8A66597_BASE_PIPENUM_INT + r8a66597->interrupt;
+               info.type = R8A66597_INT;
+               counter = &r8a66597->interrupt;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               if (r8a66597->isochronous >= R8A66597_MAX_NUM_ISOC) {
+                       printk(KERN_ERR "isochronous pipe is insufficient\n");
+                       return -ENODEV;
+               }
+               info.pipe = R8A66597_BASE_PIPENUM_ISOC + r8a66597->isochronous;
+               info.type = R8A66597_ISO;
+               counter = &r8a66597->isochronous;
+               break;
+       default:
+               printk(KERN_ERR "unexpect xfer type\n");
+               return -EINVAL;
+       }
+       ep->type = info.type;
+
+       info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+       info.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+       info.interval = desc->bInterval;
+       if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+               info.dir_in = 1;
+       else
+               info.dir_in = 0;
+
+       ret = pipe_buffer_setting(r8a66597, &info);
+       if (ret < 0) {
+               printk(KERN_ERR "pipe_buffer_setting fail\n");
+               return ret;
+       }
+
+       (*counter)++;
+       if ((counter == &r8a66597->isochronous) && info.type == R8A66597_BULK)
+               r8a66597->bulk++;
+
+       r8a66597_ep_setting(r8a66597, ep, desc, info.pipe, dma);
+       pipe_initialize(ep);
+
+       return 0;
+}
+
+static int free_pipe_config(struct r8a66597_ep *ep)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+       struct r8a66597_pipe_info info;
+
+       info.pipe = ep->pipenum;
+       info.type = ep->type;
+       pipe_buffer_release(r8a66597, &info);
+       r8a66597_ep_release(ep);
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static void pipe_irq_enable(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       enable_irq_ready(r8a66597, pipenum);
+       enable_irq_nrdy(r8a66597, pipenum);
+}
+
+static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       disable_irq_ready(r8a66597, pipenum);
+       disable_irq_nrdy(r8a66597, pipenum);
+}
+
+/* if complete is true, gadget driver complete function is not call */
+static void control_end(struct r8a66597 *r8a66597, unsigned ccpl)
+{
+       r8a66597->ep[0].internal_ccpl = ccpl;
+       pipe_start(r8a66597, 0);
+       r8a66597_bset(r8a66597, CCPL, DCPCTR);
+}
+
+static void start_ep0_write(struct r8a66597_ep *ep,
+                               struct r8a66597_request *req)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+
+       pipe_change(r8a66597, ep->pipenum);
+       r8a66597_mdfy(r8a66597, ISEL, (ISEL | CURPIPE), CFIFOSEL);
+       r8a66597_write(r8a66597, BCLR, ep->fifoctr);
+       if (req->req.length == 0) {
+               r8a66597_bset(r8a66597, BVAL, ep->fifoctr);
+               pipe_start(r8a66597, 0);
+               transfer_complete(ep, req, 0);
+       } else {
+               r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
+               irq_ep0_write(ep, req);
+       }
+}
+
+static void start_packet_write(struct r8a66597_ep *ep,
+                               struct r8a66597_request *req)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+       u16 tmp;
+
+       pipe_change(r8a66597, ep->pipenum);
+       disable_irq_empty(r8a66597, ep->pipenum);
+       pipe_start(r8a66597, ep->pipenum);
+
+       tmp = r8a66597_read(r8a66597, ep->fifoctr);
+       if (unlikely((tmp & FRDY) == 0))
+               pipe_irq_enable(r8a66597, ep->pipenum);
+       else
+               irq_packet_write(ep, req);
+}
+
+static void start_packet_read(struct r8a66597_ep *ep,
+                               struct r8a66597_request *req)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+       u16 pipenum = ep->pipenum;
+
+       if (ep->pipenum == 0) {
+               r8a66597_mdfy(r8a66597, 0, (ISEL | CURPIPE), CFIFOSEL);
+               r8a66597_write(r8a66597, BCLR, ep->fifoctr);
+               pipe_start(r8a66597, pipenum);
+               pipe_irq_enable(r8a66597, pipenum);
+       } else {
+               if (ep->use_dma) {
+                       r8a66597_bset(r8a66597, TRCLR, ep->fifosel);
+                       pipe_change(r8a66597, pipenum);
+                       r8a66597_bset(r8a66597, TRENB, ep->fifosel);
+                       r8a66597_write(r8a66597,
+                               (req->req.length + ep->ep.maxpacket - 1)
+                                       / ep->ep.maxpacket,
+                               ep->fifotrn);
+               }
+               pipe_start(r8a66597, pipenum);  /* trigger once */
+               pipe_irq_enable(r8a66597, pipenum);
+       }
+}
+
+static void start_packet(struct r8a66597_ep *ep, struct r8a66597_request *req)
+{
+       if (ep->desc->bEndpointAddress & USB_DIR_IN)
+               start_packet_write(ep, req);
+       else
+               start_packet_read(ep, req);
+}
+
+static void start_ep0(struct r8a66597_ep *ep, struct r8a66597_request *req)
+{
+       u16 ctsq;
+
+       ctsq = r8a66597_read(ep->r8a66597, INTSTS0) & CTSQ;
+
+       switch (ctsq) {
+       case CS_RDDS:
+               start_ep0_write(ep, req);
+               break;
+       case CS_WRDS:
+               start_packet_read(ep, req);
+               break;
+
+       case CS_WRND:
+               control_end(ep->r8a66597, 0);
+               break;
+       default:
+               printk(KERN_ERR "start_ep0: unexpect ctsq(%x)\n", ctsq);
+               break;
+       }
+}
+
+static void init_controller(struct r8a66597 *r8a66597)
+{
+       u16 vif = r8a66597->pdata->vif ? LDRV : 0;
+       u16 irq_sense = r8a66597->irq_sense_low ? INTL : 0;
+       u16 endian = r8a66597->pdata->endian ? BIGEND : 0;
+
+       if (r8a66597->pdata->on_chip) {
+               r8a66597_bset(r8a66597, 0x04, SYSCFG1);
+               r8a66597_bset(r8a66597, HSE, SYSCFG0);
+
+               r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+               r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
+               r8a66597_bset(r8a66597, USBE, SYSCFG0);
+
+               r8a66597_bset(r8a66597, SCKE, SYSCFG0);
+
+               r8a66597_bset(r8a66597, irq_sense, INTENB1);
+               r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR,
+                               DMA0CFG);
+       } else {
+               r8a66597_bset(r8a66597, vif | endian, PINCFG);
+               r8a66597_bset(r8a66597, HSE, SYSCFG0);          /* High spd */
+               r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata),
+                               XTAL, SYSCFG0);
+
+               r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+               r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
+               r8a66597_bset(r8a66597, USBE, SYSCFG0);
+
+               r8a66597_bset(r8a66597, XCKE, SYSCFG0);
+
+               msleep(3);
+
+               r8a66597_bset(r8a66597, PLLC, SYSCFG0);
+
+               msleep(1);
+
+               r8a66597_bset(r8a66597, SCKE, SYSCFG0);
+
+               r8a66597_bset(r8a66597, irq_sense, INTENB1);
+               r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR,
+                              DMA0CFG);
+       }
+}
+
+static void disable_controller(struct r8a66597 *r8a66597)
+{
+       if (r8a66597->pdata->on_chip) {
+               r8a66597_bset(r8a66597, SCKE, SYSCFG0);
+
+               /* disable interrupts */
+               r8a66597_write(r8a66597, 0, INTENB0);
+               r8a66597_write(r8a66597, 0, INTENB1);
+               r8a66597_write(r8a66597, 0, BRDYENB);
+               r8a66597_write(r8a66597, 0, BEMPENB);
+               r8a66597_write(r8a66597, 0, NRDYENB);
+
+               /* clear status */
+               r8a66597_write(r8a66597, 0, BRDYSTS);
+               r8a66597_write(r8a66597, 0, NRDYSTS);
+               r8a66597_write(r8a66597, 0, BEMPSTS);
+
+               r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+               r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+
+       } else {
+               r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+               udelay(1);
+               r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+               udelay(1);
+               udelay(1);
+               r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+       }
+}
+
+static void r8a66597_start_xclock(struct r8a66597 *r8a66597)
+{
+       u16 tmp;
+
+       if (!r8a66597->pdata->on_chip) {
+               tmp = r8a66597_read(r8a66597, SYSCFG0);
+               if (!(tmp & XCKE))
+                       r8a66597_bset(r8a66597, XCKE, SYSCFG0);
+       }
+}
+
+static struct r8a66597_request *get_request_from_ep(struct r8a66597_ep *ep)
+{
+       return list_entry(ep->queue.next, struct r8a66597_request, queue);
+}
+
+/*-------------------------------------------------------------------------*/
+static void transfer_complete(struct r8a66597_ep *ep,
+               struct r8a66597_request *req, int status)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
+{
+       int restart = 0;
+
+       if (unlikely(ep->pipenum == 0)) {
+               if (ep->internal_ccpl) {
+                       ep->internal_ccpl = 0;
+                       return;
+               }
+       }
+
+       list_del_init(&req->queue);
+       if (ep->r8a66597->gadget.speed == USB_SPEED_UNKNOWN)
+               req->req.status = -ESHUTDOWN;
+       else
+               req->req.status = status;
+
+       if (!list_empty(&ep->queue))
+               restart = 1;
+
+       spin_unlock(&ep->r8a66597->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&ep->r8a66597->lock);
+
+       if (restart) {
+               req = get_request_from_ep(ep);
+               if (ep->desc)
+                       start_packet(ep, req);
+       }
+}
+
+static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req)
+{
+       int i;
+       u16 tmp;
+       unsigned bufsize;
+       size_t size;
+       void *buf;
+       u16 pipenum = ep->pipenum;
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+
+       pipe_change(r8a66597, pipenum);
+       r8a66597_bset(r8a66597, ISEL, ep->fifosel);
+
+       i = 0;
+       do {
+               tmp = r8a66597_read(r8a66597, ep->fifoctr);
+               if (i++ > 100000) {
+                       printk(KERN_ERR "pipe0 is busy. maybe cpu i/o bus"
+                               "conflict. please power off this controller.");
+                       return;
+               }
+               ndelay(1);
+       } while ((tmp & FRDY) == 0);
+
+       /* prepare parameters */
+       bufsize = get_buffer_size(r8a66597, pipenum);
+       buf = req->req.buf + req->req.actual;
+       size = min(bufsize, req->req.length - req->req.actual);
+
+       /* write fifo */
+       if (req->req.buf) {
+               if (size > 0)
+                       r8a66597_write_fifo(r8a66597, ep->fifoaddr, buf, size);
+               if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
+                       r8a66597_bset(r8a66597, BVAL, ep->fifoctr);
+       }
+
+       /* update parameters */
+       req->req.actual += size;
+
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
+               disable_irq_ready(r8a66597, pipenum);
+               disable_irq_empty(r8a66597, pipenum);
+       } else {
+               disable_irq_ready(r8a66597, pipenum);
+               enable_irq_empty(r8a66597, pipenum);
+       }
+       pipe_start(r8a66597, pipenum);
+}
+
+static void irq_packet_write(struct r8a66597_ep *ep,
+                               struct r8a66597_request *req)
+{
+       u16 tmp;
+       unsigned bufsize;
+       size_t size;
+       void *buf;
+       u16 pipenum = ep->pipenum;
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+
+       pipe_change(r8a66597, pipenum);
+       tmp = r8a66597_read(r8a66597, ep->fifoctr);
+       if (unlikely((tmp & FRDY) == 0)) {
+               pipe_stop(r8a66597, pipenum);
+               pipe_irq_disable(r8a66597, pipenum);
+               printk(KERN_ERR "write fifo not ready. pipnum=%d\n", pipenum);
+               return;
+       }
+
+       /* prepare parameters */
+       bufsize = get_buffer_size(r8a66597, pipenum);
+       buf = req->req.buf + req->req.actual;
+       size = min(bufsize, req->req.length - req->req.actual);
+
+       /* write fifo */
+       if (req->req.buf) {
+               r8a66597_write_fifo(r8a66597, ep->fifoaddr, buf, size);
+               if ((size == 0)
+                               || ((size % ep->ep.maxpacket) != 0)
+                               || ((bufsize != ep->ep.maxpacket)
+                                       && (bufsize > size)))
+                       r8a66597_bset(r8a66597, BVAL, ep->fifoctr);
+       }
+
+       /* update parameters */
+       req->req.actual += size;
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
+               disable_irq_ready(r8a66597, pipenum);
+               enable_irq_empty(r8a66597, pipenum);
+       } else {
+               disable_irq_empty(r8a66597, pipenum);
+               pipe_irq_enable(r8a66597, pipenum);
+       }
+}
+
+static void irq_packet_read(struct r8a66597_ep *ep,
+                               struct r8a66597_request *req)
+{
+       u16 tmp;
+       int rcv_len, bufsize, req_len;
+       int size;
+       void *buf;
+       u16 pipenum = ep->pipenum;
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+       int finish = 0;
+
+       pipe_change(r8a66597, pipenum);
+       tmp = r8a66597_read(r8a66597, ep->fifoctr);
+       if (unlikely((tmp & FRDY) == 0)) {
+               req->req.status = -EPIPE;
+               pipe_stop(r8a66597, pipenum);
+               pipe_irq_disable(r8a66597, pipenum);
+               printk(KERN_ERR "read fifo not ready");
+               return;
+       }
+
+       /* prepare parameters */
+       rcv_len = tmp & DTLN;
+       bufsize = get_buffer_size(r8a66597, pipenum);
+
+       buf = req->req.buf + req->req.actual;
+       req_len = req->req.length - req->req.actual;
+       if (rcv_len < bufsize)
+               size = min(rcv_len, req_len);
+       else
+               size = min(bufsize, req_len);
+
+       /* update parameters */
+       req->req.actual += size;
+
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
+               pipe_stop(r8a66597, pipenum);
+               pipe_irq_disable(r8a66597, pipenum);
+               finish = 1;
+       }
+
+       /* read fifo */
+       if (req->req.buf) {
+               if (size == 0)
+                       r8a66597_write(r8a66597, BCLR, ep->fifoctr);
+               else
+                       r8a66597_read_fifo(r8a66597, ep->fifoaddr, buf, size);
+
+       }
+
+       if ((ep->pipenum != 0) && finish)
+               transfer_complete(ep, req, 0);
+}
+
+static void irq_pipe_ready(struct r8a66597 *r8a66597, u16 status, u16 enb)
+{
+       u16 check;
+       u16 pipenum;
+       struct r8a66597_ep *ep;
+       struct r8a66597_request *req;
+
+       if ((status & BRDY0) && (enb & BRDY0)) {
+               r8a66597_write(r8a66597, ~BRDY0, BRDYSTS);
+               r8a66597_mdfy(r8a66597, 0, CURPIPE, CFIFOSEL);
+
+               ep = &r8a66597->ep[0];
+               req = get_request_from_ep(ep);
+               irq_packet_read(ep, req);
+       } else {
+               for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+                       check = 1 << pipenum;
+                       if ((status & check) && (enb & check)) {
+                               r8a66597_write(r8a66597, ~check, BRDYSTS);
+                               ep = r8a66597->pipenum2ep[pipenum];
+                               req = get_request_from_ep(ep);
+                               if (ep->desc->bEndpointAddress & USB_DIR_IN)
+                                       irq_packet_write(ep, req);
+                               else
+                                       irq_packet_read(ep, req);
+                       }
+               }
+       }
+}
+
+static void irq_pipe_empty(struct r8a66597 *r8a66597, u16 status, u16 enb)
+{
+       u16 tmp;
+       u16 check;
+       u16 pipenum;
+       struct r8a66597_ep *ep;
+       struct r8a66597_request *req;
+
+       if ((status & BEMP0) && (enb & BEMP0)) {
+               r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
+
+               ep = &r8a66597->ep[0];
+               req = get_request_from_ep(ep);
+               irq_ep0_write(ep, req);
+       } else {
+               for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+                       check = 1 << pipenum;
+                       if ((status & check) && (enb & check)) {
+                               r8a66597_write(r8a66597, ~check, BEMPSTS);
+                               tmp = control_reg_get(r8a66597, pipenum);
+                               if ((tmp & INBUFM) == 0) {
+                                       disable_irq_empty(r8a66597, pipenum);
+                                       pipe_irq_disable(r8a66597, pipenum);
+                                       pipe_stop(r8a66597, pipenum);
+                                       ep = r8a66597->pipenum2ep[pipenum];
+                                       req = get_request_from_ep(ep);
+                                       if (!list_empty(&ep->queue))
+                                               transfer_complete(ep, req, 0);
+                               }
+                       }
+               }
+       }
+}
+
+static void get_status(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
+{
+       struct r8a66597_ep *ep;
+       u16 pid;
+       u16 status = 0;
+       u16 w_index = le16_to_cpu(ctrl->wIndex);
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               status = 1 << USB_DEVICE_SELF_POWERED;
+               break;
+       case USB_RECIP_INTERFACE:
+               status = 0;
+               break;
+       case USB_RECIP_ENDPOINT:
+               ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
+               pid = control_reg_get_pid(r8a66597, ep->pipenum);
+               if (pid == PID_STALL)
+                       status = 1 << USB_ENDPOINT_HALT;
+               else
+                       status = 0;
+               break;
+       default:
+               pipe_stall(r8a66597, 0);
+               return;         /* exit */
+       }
+
+       r8a66597->ep0_data = cpu_to_le16(status);
+       r8a66597->ep0_req->buf = &r8a66597->ep0_data;
+       r8a66597->ep0_req->length = 2;
+       /* AV: what happens if we get called again before that gets through? */
+       spin_unlock(&r8a66597->lock);
+       r8a66597_queue(r8a66597->gadget.ep0, r8a66597->ep0_req, GFP_KERNEL);
+       spin_lock(&r8a66597->lock);
+}
+
+static void clear_feature(struct r8a66597 *r8a66597,
+                               struct usb_ctrlrequest *ctrl)
+{
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               control_end(r8a66597, 1);
+               break;
+       case USB_RECIP_INTERFACE:
+               control_end(r8a66597, 1);
+               break;
+       case USB_RECIP_ENDPOINT: {
+               struct r8a66597_ep *ep;
+               struct r8a66597_request *req;
+               u16 w_index = le16_to_cpu(ctrl->wIndex);
+
+               ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
+               if (!ep->wedge) {
+                       pipe_stop(r8a66597, ep->pipenum);
+                       control_reg_sqclr(r8a66597, ep->pipenum);
+                       spin_unlock(&r8a66597->lock);
+                       usb_ep_clear_halt(&ep->ep);
+                       spin_lock(&r8a66597->lock);
+               }
+
+               control_end(r8a66597, 1);
+
+               req = get_request_from_ep(ep);
+               if (ep->busy) {
+                       ep->busy = 0;
+                       if (list_empty(&ep->queue))
+                               break;
+                       start_packet(ep, req);
+               } else if (!list_empty(&ep->queue))
+                       pipe_start(r8a66597, ep->pipenum);
+               }
+               break;
+       default:
+               pipe_stall(r8a66597, 0);
+               break;
+       }
+}
+
+static void set_feature(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
+{
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               control_end(r8a66597, 1);
+               break;
+       case USB_RECIP_INTERFACE:
+               control_end(r8a66597, 1);
+               break;
+       case USB_RECIP_ENDPOINT: {
+               struct r8a66597_ep *ep;
+               u16 w_index = le16_to_cpu(ctrl->wIndex);
+
+               ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
+               pipe_stall(r8a66597, ep->pipenum);
+
+               control_end(r8a66597, 1);
+               }
+               break;
+       default:
+               pipe_stall(r8a66597, 0);
+               break;
+       }
+}
+
+/* if return value is true, call class driver's setup() */
+static int setup_packet(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
+{
+       u16 *p = (u16 *)ctrl;
+       unsigned long offset = USBREQ;
+       int i, ret = 0;
+
+       /* read fifo */
+       r8a66597_write(r8a66597, ~VALID, INTSTS0);
+
+       for (i = 0; i < 4; i++)
+               p[i] = r8a66597_read(r8a66597, offset + i*2);
+
+       /* check request */
+       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+               switch (ctrl->bRequest) {
+               case USB_REQ_GET_STATUS:
+                       get_status(r8a66597, ctrl);
+                       break;
+               case USB_REQ_CLEAR_FEATURE:
+                       clear_feature(r8a66597, ctrl);
+                       break;
+               case USB_REQ_SET_FEATURE:
+                       set_feature(r8a66597, ctrl);
+                       break;
+               default:
+                       ret = 1;
+                       break;
+               }
+       } else
+               ret = 1;
+       return ret;
+}
+
+static void r8a66597_update_usb_speed(struct r8a66597 *r8a66597)
+{
+       u16 speed = get_usb_speed(r8a66597);
+
+       switch (speed) {
+       case HSMODE:
+               r8a66597->gadget.speed = USB_SPEED_HIGH;
+               break;
+       case FSMODE:
+               r8a66597->gadget.speed = USB_SPEED_FULL;
+               break;
+       default:
+               r8a66597->gadget.speed = USB_SPEED_UNKNOWN;
+               printk(KERN_ERR "USB speed unknown\n");
+       }
+}
+
+static void irq_device_state(struct r8a66597 *r8a66597)
+{
+       u16 dvsq;
+
+       dvsq = r8a66597_read(r8a66597, INTSTS0) & DVSQ;
+       r8a66597_write(r8a66597, ~DVST, INTSTS0);
+
+       if (dvsq == DS_DFLT) {
+               /* bus reset */
+               r8a66597->driver->disconnect(&r8a66597->gadget);
+               r8a66597_update_usb_speed(r8a66597);
+       }
+       if (r8a66597->old_dvsq == DS_CNFG && dvsq != DS_CNFG)
+               r8a66597_update_usb_speed(r8a66597);
+       if ((dvsq == DS_CNFG || dvsq == DS_ADDS)
+                       && r8a66597->gadget.speed == USB_SPEED_UNKNOWN)
+               r8a66597_update_usb_speed(r8a66597);
+
+       r8a66597->old_dvsq = dvsq;
+}
+
+static void irq_control_stage(struct r8a66597 *r8a66597)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
+{
+       struct usb_ctrlrequest ctrl;
+       u16 ctsq;
+
+       ctsq = r8a66597_read(r8a66597, INTSTS0) & CTSQ;
+       r8a66597_write(r8a66597, ~CTRT, INTSTS0);
+
+       switch (ctsq) {
+       case CS_IDST: {
+               struct r8a66597_ep *ep;
+               struct r8a66597_request *req;
+               ep = &r8a66597->ep[0];
+               req = get_request_from_ep(ep);
+               transfer_complete(ep, req, 0);
+               }
+               break;
+
+       case CS_RDDS:
+       case CS_WRDS:
+       case CS_WRND:
+               if (setup_packet(r8a66597, &ctrl)) {
+                       spin_unlock(&r8a66597->lock);
+                       if (r8a66597->driver->setup(&r8a66597->gadget, &ctrl)
+                               < 0)
+                               pipe_stall(r8a66597, 0);
+                       spin_lock(&r8a66597->lock);
+               }
+               break;
+       case CS_RDSS:
+       case CS_WRSS:
+               control_end(r8a66597, 0);
+               break;
+       default:
+               printk(KERN_ERR "ctrl_stage: unexpect ctsq(%x)\n", ctsq);
+               break;
+       }
+}
+
+static irqreturn_t r8a66597_irq(int irq, void *_r8a66597)
+{
+       struct r8a66597 *r8a66597 = _r8a66597;
+       u16 intsts0;
+       u16 intenb0;
+       u16 brdysts, nrdysts, bempsts;
+       u16 brdyenb, nrdyenb, bempenb;
+       u16 savepipe;
+       u16 mask0;
+
+       spin_lock(&r8a66597->lock);
+
+       intsts0 = r8a66597_read(r8a66597, INTSTS0);
+       intenb0 = r8a66597_read(r8a66597, INTENB0);
+
+       savepipe = r8a66597_read(r8a66597, CFIFOSEL);
+
+       mask0 = intsts0 & intenb0;
+       if (mask0) {
+               brdysts = r8a66597_read(r8a66597, BRDYSTS);
+               nrdysts = r8a66597_read(r8a66597, NRDYSTS);
+               bempsts = r8a66597_read(r8a66597, BEMPSTS);
+               brdyenb = r8a66597_read(r8a66597, BRDYENB);
+               nrdyenb = r8a66597_read(r8a66597, NRDYENB);
+               bempenb = r8a66597_read(r8a66597, BEMPENB);
+
+               if (mask0 & VBINT) {
+                       r8a66597_write(r8a66597,  0xffff & ~VBINT,
+                                       INTSTS0);
+                       r8a66597_start_xclock(r8a66597);
+
+                       /* start vbus sampling */
+                       r8a66597->old_vbus = r8a66597_read(r8a66597, INTSTS0)
+                                       & VBSTS;
+                       r8a66597->scount = R8A66597_MAX_SAMPLING;
+
+                       mod_timer(&r8a66597->timer,
+                                       jiffies + msecs_to_jiffies(50));
+               }
+               if (intsts0 & DVSQ)
+                       irq_device_state(r8a66597);
+
+               if ((intsts0 & BRDY) && (intenb0 & BRDYE)
+                               && (brdysts & brdyenb))
+                       irq_pipe_ready(r8a66597, brdysts, brdyenb);
+               if ((intsts0 & BEMP) && (intenb0 & BEMPE)
+                               && (bempsts & bempenb))
+                       irq_pipe_empty(r8a66597, bempsts, bempenb);
+
+               if (intsts0 & CTRT)
+                       irq_control_stage(r8a66597);
+       }
+
+       r8a66597_write(r8a66597, savepipe, CFIFOSEL);
+
+       spin_unlock(&r8a66597->lock);
+       return IRQ_HANDLED;
+}
+
+static void r8a66597_timer(unsigned long _r8a66597)
+{
+       struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
+       unsigned long flags;
+       u16 tmp;
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+       tmp = r8a66597_read(r8a66597, SYSCFG0);
+       if (r8a66597->scount > 0) {
+               tmp = r8a66597_read(r8a66597, INTSTS0) & VBSTS;
+               if (tmp == r8a66597->old_vbus) {
+                       r8a66597->scount--;
+                       if (r8a66597->scount == 0) {
+                               if (tmp == VBSTS)
+                                       r8a66597_usb_connect(r8a66597);
+                               else
+                                       r8a66597_usb_disconnect(r8a66597);
+                       } else {
+                               mod_timer(&r8a66597->timer,
+                                       jiffies + msecs_to_jiffies(50));
+                       }
+               } else {
+                       r8a66597->scount = R8A66597_MAX_SAMPLING;
+                       r8a66597->old_vbus = tmp;
+                       mod_timer(&r8a66597->timer,
+                                       jiffies + msecs_to_jiffies(50));
+               }
+       }
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+static int r8a66597_enable(struct usb_ep *_ep,
+                        const struct usb_endpoint_descriptor *desc)
+{
+       struct r8a66597_ep *ep;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+       return alloc_pipe_config(ep, desc);
+}
+
+static int r8a66597_disable(struct usb_ep *_ep)
+{
+       struct r8a66597_ep *ep;
+       struct r8a66597_request *req;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+       BUG_ON(!ep);
+
+       while (!list_empty(&ep->queue)) {
+               req = get_request_from_ep(ep);
+               spin_lock_irqsave(&ep->r8a66597->lock, flags);
+               transfer_complete(ep, req, -ECONNRESET);
+               spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+       }
+
+       pipe_irq_disable(ep->r8a66597, ep->pipenum);
+       return free_pipe_config(ep);
+}
+
+static struct usb_request *r8a66597_alloc_request(struct usb_ep *_ep,
+                                               gfp_t gfp_flags)
+{
+       struct r8a66597_request *req;
+
+       req = kzalloc(sizeof(struct r8a66597_request), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void r8a66597_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct r8a66597_request *req;
+
+       req = container_of(_req, struct r8a66597_request, req);
+       kfree(req);
+}
+
+static int r8a66597_queue(struct usb_ep *_ep, struct usb_request *_req,
+                       gfp_t gfp_flags)
+{
+       struct r8a66597_ep *ep;
+       struct r8a66597_request *req;
+       unsigned long flags;
+       int request = 0;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+       req = container_of(_req, struct r8a66597_request, req);
+
+       if (ep->r8a66597->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&ep->r8a66597->lock, flags);
+
+       if (list_empty(&ep->queue))
+               request = 1;
+
+       list_add_tail(&req->queue, &ep->queue);
+       req->req.actual = 0;
+       req->req.status = -EINPROGRESS;
+
+       if (ep->desc == NULL)   /* control */
+               start_ep0(ep, req);
+       else {
+               if (request && !ep->busy)
+                       start_packet(ep, req);
+       }
+
+       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+
+       return 0;
+}
+
+static int r8a66597_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct r8a66597_ep *ep;
+       struct r8a66597_request *req;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+       req = container_of(_req, struct r8a66597_request, req);
+
+       spin_lock_irqsave(&ep->r8a66597->lock, flags);
+       if (!list_empty(&ep->queue))
+               transfer_complete(ep, req, -ECONNRESET);
+       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+
+       return 0;
+}
+
+static int r8a66597_set_halt(struct usb_ep *_ep, int value)
+{
+       struct r8a66597_ep *ep;
+       struct r8a66597_request *req;
+       unsigned long flags;
+       int ret = 0;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+       req = get_request_from_ep(ep);
+
+       spin_lock_irqsave(&ep->r8a66597->lock, flags);
+       if (!list_empty(&ep->queue)) {
+               ret = -EAGAIN;
+               goto out;
+       }
+       if (value) {
+               ep->busy = 1;
+               pipe_stall(ep->r8a66597, ep->pipenum);
+       } else {
+               ep->busy = 0;
+               ep->wedge = 0;
+               pipe_stop(ep->r8a66597, ep->pipenum);
+       }
+
+out:
+       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+       return ret;
+}
+
+static int r8a66597_set_wedge(struct usb_ep *_ep)
+{
+       struct r8a66597_ep *ep;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+
+       if (!ep || !ep->desc)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->r8a66597->lock, flags);
+       ep->wedge = 1;
+       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+
+       return usb_ep_set_halt(_ep);
+}
+
+static void r8a66597_fifo_flush(struct usb_ep *_ep)
+{
+       struct r8a66597_ep *ep;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+       spin_lock_irqsave(&ep->r8a66597->lock, flags);
+       if (list_empty(&ep->queue) && !ep->busy) {
+               pipe_stop(ep->r8a66597, ep->pipenum);
+               r8a66597_bclr(ep->r8a66597, BCLR, ep->fifoctr);
+       }
+       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+}
+
+static struct usb_ep_ops r8a66597_ep_ops = {
+       .enable         = r8a66597_enable,
+       .disable        = r8a66597_disable,
+
+       .alloc_request  = r8a66597_alloc_request,
+       .free_request   = r8a66597_free_request,
+
+       .queue          = r8a66597_queue,
+       .dequeue        = r8a66597_dequeue,
+
+       .set_halt       = r8a66597_set_halt,
+       .set_wedge      = r8a66597_set_wedge,
+       .fifo_flush     = r8a66597_fifo_flush,
+};
+
+/*-------------------------------------------------------------------------*/
+static struct r8a66597 *the_controller;
+
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+       struct r8a66597 *r8a66597 = the_controller;
+       int retval;
+
+       if (!driver
+                       || driver->speed != USB_SPEED_HIGH
+                       || !driver->bind
+                       || !driver->setup)
+               return -EINVAL;
+       if (!r8a66597)
+               return -ENODEV;
+       if (r8a66597->driver)
+               return -EBUSY;
+
+       /* hook up the driver */
+       driver->driver.bus = NULL;
+       r8a66597->driver = driver;
+       r8a66597->gadget.dev.driver = &driver->driver;
+
+       retval = device_add(&r8a66597->gadget.dev);
+       if (retval) {
+               printk(KERN_ERR "device_add error (%d)\n", retval);
+               goto error;
+       }
+
+       retval = driver->bind(&r8a66597->gadget);
+       if (retval) {
+               printk(KERN_ERR "bind to driver error (%d)\n", retval);
+               device_del(&r8a66597->gadget.dev);
+               goto error;
+       }
+
+       r8a66597_bset(r8a66597, VBSE, INTENB0);
+       if (r8a66597_read(r8a66597, INTSTS0) & VBSTS) {
+               r8a66597_start_xclock(r8a66597);
+               /* start vbus sampling */
+               r8a66597->old_vbus = r8a66597_read(r8a66597,
+                                        INTSTS0) & VBSTS;
+               r8a66597->scount = R8A66597_MAX_SAMPLING;
+               mod_timer(&r8a66597->timer, jiffies + msecs_to_jiffies(50));
+       }
+
+       return 0;
+
+error:
+       r8a66597->driver = NULL;
+       r8a66597->gadget.dev.driver = NULL;
+
+       return retval;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+       struct r8a66597 *r8a66597 = the_controller;
+       unsigned long flags;
+
+       if (driver != r8a66597->driver || !driver->unbind)
+               return -EINVAL;
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+       if (r8a66597->gadget.speed != USB_SPEED_UNKNOWN)
+               r8a66597_usb_disconnect(r8a66597);
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+
+       r8a66597_bclr(r8a66597, VBSE, INTENB0);
+
+       driver->unbind(&r8a66597->gadget);
+
+       init_controller(r8a66597);
+       disable_controller(r8a66597);
+
+       device_del(&r8a66597->gadget.dev);
+       r8a66597->driver = NULL;
+       return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/*-------------------------------------------------------------------------*/
+static int r8a66597_get_frame(struct usb_gadget *_gadget)
+{
+       struct r8a66597 *r8a66597 = gadget_to_r8a66597(_gadget);
+       return r8a66597_read(r8a66597, FRMNUM) & 0x03FF;
+}
+
+static struct usb_gadget_ops r8a66597_gadget_ops = {
+       .get_frame              = r8a66597_get_frame,
+};
+
+static int __exit r8a66597_remove(struct platform_device *pdev)
+{
+       struct r8a66597         *r8a66597 = dev_get_drvdata(&pdev->dev);
+
+       del_timer_sync(&r8a66597->timer);
+       iounmap((void *)r8a66597->reg);
+       free_irq(platform_get_irq(pdev, 0), r8a66597);
+       r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
+#ifdef CONFIG_HAVE_CLK
+       if (r8a66597->pdata->on_chip) {
+               clk_disable(r8a66597->clk);
+               clk_put(r8a66597->clk);
+       }
+#endif
+       kfree(r8a66597);
+       return 0;
+}
+
+static void nop_completion(struct usb_ep *ep, struct usb_request *r)
+{
+}
+
+static int __init r8a66597_probe(struct platform_device *pdev)
+{
+#ifdef CONFIG_HAVE_CLK
+       char clk_name[8];
+#endif
+       struct resource *res, *ires;
+       int irq;
+       void __iomem *reg = NULL;
+       struct r8a66597 *r8a66597 = NULL;
+       int ret = 0;
+       int i;
+       unsigned long irq_trigger;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               printk(KERN_ERR "platform_get_resource error.\n");
+               goto clean_up;
+       }
+
+       ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       irq = ires->start;
+       irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
+
+       if (irq < 0) {
+               ret = -ENODEV;
+               printk(KERN_ERR "platform_get_irq error.\n");
+               goto clean_up;
+       }
+
+       reg = ioremap(res->start, resource_size(res));
+       if (reg == NULL) {
+               ret = -ENOMEM;
+               printk(KERN_ERR "ioremap error.\n");
+               goto clean_up;
+       }
+
+       /* initialize ucd */
+       r8a66597 = kzalloc(sizeof(struct r8a66597), GFP_KERNEL);
+       if (r8a66597 == NULL) {
+               printk(KERN_ERR "kzalloc error\n");
+               goto clean_up;
+       }
+
+       spin_lock_init(&r8a66597->lock);
+       dev_set_drvdata(&pdev->dev, r8a66597);
+       r8a66597->pdata = pdev->dev.platform_data;
+       r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
+
+       r8a66597->gadget.ops = &r8a66597_gadget_ops;
+       device_initialize(&r8a66597->gadget.dev);
+       dev_set_name(&r8a66597->gadget.dev, "gadget");
+       r8a66597->gadget.is_dualspeed = 1;
+       r8a66597->gadget.dev.parent = &pdev->dev;
+       r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask;
+       r8a66597->gadget.dev.release = pdev->dev.release;
+       r8a66597->gadget.name = udc_name;
+
+       init_timer(&r8a66597->timer);
+       r8a66597->timer.function = r8a66597_timer;
+       r8a66597->timer.data = (unsigned long)r8a66597;
+       r8a66597->reg = (unsigned long)reg;
+
+#ifdef CONFIG_HAVE_CLK
+       if (r8a66597->pdata->on_chip) {
+               snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
+               r8a66597->clk = clk_get(&pdev->dev, clk_name);
+               if (IS_ERR(r8a66597->clk)) {
+                       dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
+                               clk_name);
+                       ret = PTR_ERR(r8a66597->clk);
+                       goto clean_up;
+               }
+               clk_enable(r8a66597->clk);
+       }
+#endif
+
+       disable_controller(r8a66597); /* make sure controller is disabled */
+
+       ret = request_irq(irq, r8a66597_irq, IRQF_DISABLED | IRQF_SHARED,
+                       udc_name, r8a66597);
+       if (ret < 0) {
+               printk(KERN_ERR "request_irq error (%d)\n", ret);
+               goto clean_up2;
+       }
+
+       INIT_LIST_HEAD(&r8a66597->gadget.ep_list);
+       r8a66597->gadget.ep0 = &r8a66597->ep[0].ep;
+       INIT_LIST_HEAD(&r8a66597->gadget.ep0->ep_list);
+       for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) {
+               struct r8a66597_ep *ep = &r8a66597->ep[i];
+
+               if (i != 0) {
+                       INIT_LIST_HEAD(&r8a66597->ep[i].ep.ep_list);
+                       list_add_tail(&r8a66597->ep[i].ep.ep_list,
+                                       &r8a66597->gadget.ep_list);
+               }
+               ep->r8a66597 = r8a66597;
+               INIT_LIST_HEAD(&ep->queue);
+               ep->ep.name = r8a66597_ep_name[i];
+               ep->ep.ops = &r8a66597_ep_ops;
+               ep->ep.maxpacket = 512;
+       }
+       r8a66597->ep[0].ep.maxpacket = 64;
+       r8a66597->ep[0].pipenum = 0;
+       r8a66597->ep[0].fifoaddr = CFIFO;
+       r8a66597->ep[0].fifosel = CFIFOSEL;
+       r8a66597->ep[0].fifoctr = CFIFOCTR;
+       r8a66597->ep[0].fifotrn = 0;
+       r8a66597->ep[0].pipectr = get_pipectr_addr(0);
+       r8a66597->pipenum2ep[0] = &r8a66597->ep[0];
+       r8a66597->epaddr2ep[0] = &r8a66597->ep[0];
+
+       the_controller = r8a66597;
+
+       r8a66597->ep0_req = r8a66597_alloc_request(&r8a66597->ep[0].ep,
+                                                       GFP_KERNEL);
+       if (r8a66597->ep0_req == NULL)
+               goto clean_up3;
+       r8a66597->ep0_req->complete = nop_completion;
+
+       init_controller(r8a66597);
+
+       dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
+       return 0;
+
+clean_up3:
+       free_irq(irq, r8a66597);
+clean_up2:
+#ifdef CONFIG_HAVE_CLK
+       if (r8a66597->pdata->on_chip) {
+               clk_disable(r8a66597->clk);
+               clk_put(r8a66597->clk);
+       }
+#endif
+clean_up:
+       if (r8a66597) {
+               if (r8a66597->ep0_req)
+                       r8a66597_free_request(&r8a66597->ep[0].ep,
+                                               r8a66597->ep0_req);
+               kfree(r8a66597);
+       }
+       if (reg)
+               iounmap(reg);
+
+       return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+static struct platform_driver r8a66597_driver = {
+       .remove =       __exit_p(r8a66597_remove),
+       .driver         = {
+               .name = (char *) udc_name,
+       },
+};
+
+static int __init r8a66597_udc_init(void)
+{
+       return platform_driver_probe(&r8a66597_driver, r8a66597_probe);
+}
+module_init(r8a66597_udc_init);
+
+static void __exit r8a66597_udc_cleanup(void)
+{
+       platform_driver_unregister(&r8a66597_driver);
+}
+module_exit(r8a66597_udc_cleanup);
+
+MODULE_DESCRIPTION("R8A66597 USB gadget driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h
new file mode 100644 (file)
index 0000000..03087e7
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * R8A66597 UDC
+ *
+ * Copyright (C) 2007-2009 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __R8A66597_H__
+#define __R8A66597_H__
+
+#ifdef CONFIG_HAVE_CLK
+#include <linux/clk.h>
+#endif
+
+#include <linux/usb/r8a66597.h>
+
+#define R8A66597_MAX_SAMPLING  10
+
+#define R8A66597_MAX_NUM_PIPE  8
+#define R8A66597_MAX_NUM_BULK  3
+#define R8A66597_MAX_NUM_ISOC  2
+#define R8A66597_MAX_NUM_INT   2
+
+#define R8A66597_BASE_PIPENUM_BULK     3
+#define R8A66597_BASE_PIPENUM_ISOC     1
+#define R8A66597_BASE_PIPENUM_INT      6
+
+#define R8A66597_BASE_BUFNUM   6
+#define R8A66597_MAX_BUFNUM    0x4F
+
+#define is_bulk_pipe(pipenum)  \
+       ((pipenum >= R8A66597_BASE_PIPENUM_BULK) && \
+        (pipenum < (R8A66597_BASE_PIPENUM_BULK + R8A66597_MAX_NUM_BULK)))
+#define is_interrupt_pipe(pipenum)     \
+       ((pipenum >= R8A66597_BASE_PIPENUM_INT) && \
+        (pipenum < (R8A66597_BASE_PIPENUM_INT + R8A66597_MAX_NUM_INT)))
+#define is_isoc_pipe(pipenum)  \
+       ((pipenum >= R8A66597_BASE_PIPENUM_ISOC) && \
+        (pipenum < (R8A66597_BASE_PIPENUM_ISOC + R8A66597_MAX_NUM_ISOC)))
+
+struct r8a66597_pipe_info {
+       u16     pipe;
+       u16     epnum;
+       u16     maxpacket;
+       u16     type;
+       u16     interval;
+       u16     dir_in;
+};
+
+struct r8a66597_request {
+       struct usb_request      req;
+       struct list_head        queue;
+};
+
+struct r8a66597_ep {
+       struct usb_ep           ep;
+       struct r8a66597         *r8a66597;
+
+       struct list_head        queue;
+       unsigned                busy:1;
+       unsigned                wedge:1;
+       unsigned                internal_ccpl:1;        /* use only control */
+
+       /* this member can able to after r8a66597_enable */
+       unsigned                use_dma:1;
+       u16                     pipenum;
+       u16                     type;
+       const struct usb_endpoint_descriptor    *desc;
+       /* register address */
+       unsigned char           fifoaddr;
+       unsigned char           fifosel;
+       unsigned char           fifoctr;
+       unsigned char           fifotrn;
+       unsigned char           pipectr;
+};
+
+struct r8a66597 {
+       spinlock_t              lock;
+       unsigned long           reg;
+
+#ifdef CONFIG_HAVE_CLK
+       struct clk *clk;
+#endif
+       struct r8a66597_platdata        *pdata;
+
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+
+       struct r8a66597_ep      ep[R8A66597_MAX_NUM_PIPE];
+       struct r8a66597_ep      *pipenum2ep[R8A66597_MAX_NUM_PIPE];
+       struct r8a66597_ep      *epaddr2ep[16];
+
+       struct timer_list       timer;
+       struct usb_request      *ep0_req;       /* for internal request */
+       u16                     ep0_data;       /* for internal request */
+       u16                     old_vbus;
+       u16                     scount;
+       u16                     old_dvsq;
+
+       /* pipe config */
+       unsigned char bulk;
+       unsigned char interrupt;
+       unsigned char isochronous;
+       unsigned char num_dma;
+
+       unsigned irq_sense_low:1;
+};
+
+#define gadget_to_r8a66597(_gadget)    \
+               container_of(_gadget, struct r8a66597, gadget)
+#define r8a66597_to_gadget(r8a66597) (&r8a66597->gadget)
+
+static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
+{
+       return inw(r8a66597->reg + offset);
+}
+
+static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
+                                     unsigned long offset, u16 *buf,
+                                     int len)
+{
+       if (r8a66597->pdata->on_chip) {
+               unsigned long fifoaddr = r8a66597->reg + offset;
+               unsigned long count;
+               union {
+                       unsigned long dword;
+                       unsigned char byte[4];
+               } data;
+               unsigned char *pb;
+               int i;
+
+               count = len / 4;
+               insl(fifoaddr, buf, count);
+
+               if (len & 0x00000003) {
+                       data.dword = inl(fifoaddr);
+                       pb = (unsigned char *)buf + count * 4;
+                       for (i = 0; i < (len & 0x00000003); i++)
+                               pb[i] = data.byte[i];
+               }
+       } else {
+               len = (len + 1) / 2;
+               insw(r8a66597->reg + offset, buf, len);
+       }
+}
+
+static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
+                                 unsigned long offset)
+{
+       outw(val, r8a66597->reg + offset);
+}
+
+static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+                                      unsigned long offset, u16 *buf,
+                                      int len)
+{
+       unsigned long fifoaddr = r8a66597->reg + offset;
+
+       if (r8a66597->pdata->on_chip) {
+               unsigned long count;
+               unsigned char *pb;
+               int i;
+
+               count = len / 4;
+               outsl(fifoaddr, buf, count);
+
+               if (len & 0x00000003) {
+                       pb = (unsigned char *)buf + count * 4;
+                       for (i = 0; i < (len & 0x00000003); i++) {
+                               if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
+                                       outb(pb[i], fifoaddr + i);
+                               else
+                                       outb(pb[i], fifoaddr + 3 - i);
+                       }
+               }
+       } else {
+               int odd = len & 0x0001;
+
+               len = len / 2;
+               outsw(fifoaddr, buf, len);
+               if (unlikely(odd)) {
+                       buf = &buf[len];
+                       outb((unsigned char)*buf, fifoaddr);
+               }
+       }
+}
+
+static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
+                                u16 val, u16 pat, unsigned long offset)
+{
+       u16 tmp;
+       tmp = r8a66597_read(r8a66597, offset);
+       tmp = tmp & (~pat);
+       tmp = tmp | val;
+       r8a66597_write(r8a66597, tmp, offset);
+}
+
+static inline u16 get_xtal_from_pdata(struct r8a66597_platdata *pdata)
+{
+       u16 clock = 0;
+
+       switch (pdata->xtal) {
+       case R8A66597_PLATDATA_XTAL_12MHZ:
+               clock = XTAL12;
+               break;
+       case R8A66597_PLATDATA_XTAL_24MHZ:
+               clock = XTAL24;
+               break;
+       case R8A66597_PLATDATA_XTAL_48MHZ:
+               clock = XTAL48;
+               break;
+       default:
+               printk(KERN_ERR "r8a66597: platdata clock is wrong.\n");
+               break;
+       }
+
+       return clock;
+}
+
+#define r8a66597_bclr(r8a66597, val, offset)   \
+                       r8a66597_mdfy(r8a66597, 0, val, offset)
+#define r8a66597_bset(r8a66597, val, offset)   \
+                       r8a66597_mdfy(r8a66597, val, 0, offset)
+
+#define get_pipectr_addr(pipenum)      (PIPE1CTR + (pipenum - 1) * 2)
+
+#define enable_irq_ready(r8a66597, pipenum)    \
+       enable_pipe_irq(r8a66597, pipenum, BRDYENB)
+#define disable_irq_ready(r8a66597, pipenum)   \
+       disable_pipe_irq(r8a66597, pipenum, BRDYENB)
+#define enable_irq_empty(r8a66597, pipenum)    \
+       enable_pipe_irq(r8a66597, pipenum, BEMPENB)
+#define disable_irq_empty(r8a66597, pipenum)   \
+       disable_pipe_irq(r8a66597, pipenum, BEMPENB)
+#define enable_irq_nrdy(r8a66597, pipenum)     \
+       enable_pipe_irq(r8a66597, pipenum, NRDYENB)
+#define disable_irq_nrdy(r8a66597, pipenum)    \
+       disable_pipe_irq(r8a66597, pipenum, NRDYENB)
+
+#endif /* __R8A66597_H__ */
+
index 1a920c7..f21ca7d 100644 (file)
@@ -336,13 +336,6 @@ config USB_R8A66597_HCD
          To compile this driver as a module, choose M here: the
          module will be called r8a66597-hcd.
 
-config SUPERH_ON_CHIP_R8A66597
-       boolean "Enable SuperH on-chip R8A66597 USB"
-       depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7724)
-       help
-          This driver enables support for the on-chip R8A66597 in the
-          SH7366, SH7723 and SH7724 processors.
-
 config USB_WHCI_HCD
        tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
        depends on EXPERIMENTAL
index e18f749..749b537 100644 (file)
@@ -91,43 +91,43 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
        u16 tmp;
        int i = 0;
 
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-#if defined(CONFIG_HAVE_CLK)
-       clk_enable(r8a66597->clk);
+       if (r8a66597->pdata->on_chip) {
+#ifdef CONFIG_HAVE_CLK
+               clk_enable(r8a66597->clk);
 #endif
-       do {
-               r8a66597_write(r8a66597, SCKE, SYSCFG0);
-               tmp = r8a66597_read(r8a66597, SYSCFG0);
-               if (i++ > 1000) {
-                       printk(KERN_ERR "r8a66597: register access fail.\n");
-                       return -ENXIO;
-               }
-       } while ((tmp & SCKE) != SCKE);
-       r8a66597_write(r8a66597, 0x04, 0x02);
-#else
-       do {
-               r8a66597_write(r8a66597, USBE, SYSCFG0);
-               tmp = r8a66597_read(r8a66597, SYSCFG0);
-               if (i++ > 1000) {
-                       printk(KERN_ERR "r8a66597: register access fail.\n");
-                       return -ENXIO;
-               }
-       } while ((tmp & USBE) != USBE);
-       r8a66597_bclr(r8a66597, USBE, SYSCFG0);
-       r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata), XTAL,
-                       SYSCFG0);
+               do {
+                       r8a66597_write(r8a66597, SCKE, SYSCFG0);
+                       tmp = r8a66597_read(r8a66597, SYSCFG0);
+                       if (i++ > 1000) {
+                               printk(KERN_ERR "r8a66597: reg access fail.\n");
+                               return -ENXIO;
+                       }
+               } while ((tmp & SCKE) != SCKE);
+               r8a66597_write(r8a66597, 0x04, 0x02);
+       } else {
+               do {
+                       r8a66597_write(r8a66597, USBE, SYSCFG0);
+                       tmp = r8a66597_read(r8a66597, SYSCFG0);
+                       if (i++ > 1000) {
+                               printk(KERN_ERR "r8a66597: reg access fail.\n");
+                               return -ENXIO;
+                       }
+               } while ((tmp & USBE) != USBE);
+               r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+               r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata),
+                             XTAL, SYSCFG0);
 
-       i = 0;
-       r8a66597_bset(r8a66597, XCKE, SYSCFG0);
-       do {
-               msleep(1);
-               tmp = r8a66597_read(r8a66597, SYSCFG0);
-               if (i++ > 500) {
-                       printk(KERN_ERR "r8a66597: register access fail.\n");
-                       return -ENXIO;
-               }
-       } while ((tmp & SCKE) != SCKE);
-#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
+               i = 0;
+               r8a66597_bset(r8a66597, XCKE, SYSCFG0);
+               do {
+                       msleep(1);
+                       tmp = r8a66597_read(r8a66597, SYSCFG0);
+                       if (i++ > 500) {
+                               printk(KERN_ERR "r8a66597: reg access fail.\n");
+                               return -ENXIO;
+                       }
+               } while ((tmp & SCKE) != SCKE);
+       }
 
        return 0;
 }
@@ -136,15 +136,16 @@ static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
 {
        r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
        udelay(1);
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-#if defined(CONFIG_HAVE_CLK)
-       clk_disable(r8a66597->clk);
-#endif
-#else
-       r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
-       r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
-       r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+
+       if (r8a66597->pdata->on_chip) {
+#ifdef CONFIG_HAVE_CLK
+               clk_disable(r8a66597->clk);
 #endif
+       } else {
+               r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+               r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+               r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+       }
 }
 
 static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
@@ -205,7 +206,7 @@ static int enable_controller(struct r8a66597 *r8a66597)
 
        r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1);
 
-       for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+       for (port = 0; port < r8a66597->max_root_hub; port++)
                r8a66597_enable_port(r8a66597, port);
 
        return 0;
@@ -218,7 +219,7 @@ static void disable_controller(struct r8a66597 *r8a66597)
        r8a66597_write(r8a66597, 0, INTENB0);
        r8a66597_write(r8a66597, 0, INTSTS0);
 
-       for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+       for (port = 0; port < r8a66597->max_root_hub; port++)
                r8a66597_disable_port(r8a66597, port);
 
        r8a66597_clock_disable(r8a66597);
@@ -249,11 +250,12 @@ static int is_hub_limit(char *devpath)
        return ((strlen(devpath) >= 4) ? 1 : 0);
 }
 
-static void get_port_number(char *devpath, u16 *root_port, u16 *hub_port)
+static void get_port_number(struct r8a66597 *r8a66597,
+                           char *devpath, u16 *root_port, u16 *hub_port)
 {
        if (root_port) {
                *root_port = (devpath[0] & 0x0F) - 1;
-               if (*root_port >= R8A66597_MAX_ROOT_HUB)
+               if (*root_port >= r8a66597->max_root_hub)
                        printk(KERN_ERR "r8a66597: Illegal root port number.\n");
        }
        if (hub_port)
@@ -355,7 +357,8 @@ static int make_r8a66597_device(struct r8a66597 *r8a66597,
        INIT_LIST_HEAD(&dev->device_list);
        list_add_tail(&dev->device_list, &r8a66597->child_device);
 
-       get_port_number(urb->dev->devpath, &dev->root_port, &dev->hub_port);
+       get_port_number(r8a66597, urb->dev->devpath,
+                       &dev->root_port, &dev->hub_port);
        if (!is_child_device(urb->dev->devpath))
                r8a66597->root_hub[dev->root_port].dev = dev;
 
@@ -420,7 +423,7 @@ static void free_usb_address(struct r8a66597 *r8a66597,
        list_del(&dev->device_list);
        kfree(dev);
 
-       for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+       for (port = 0; port < r8a66597->max_root_hub; port++) {
                if (r8a66597->root_hub[port].dev == dev) {
                        r8a66597->root_hub[port].dev = NULL;
                        break;
@@ -495,10 +498,20 @@ static void r8a66597_pipe_toggle(struct r8a66597 *r8a66597,
                r8a66597_bset(r8a66597, SQCLR, pipe->pipectr);
 }
 
+static inline unsigned short mbw_value(struct r8a66597 *r8a66597)
+{
+       if (r8a66597->pdata->on_chip)
+               return MBW_32;
+       else
+               return MBW_16;
+}
+
 /* this function must be called with interrupt disabled */
 static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum)
 {
-       r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
+       unsigned short mbw = mbw_value(r8a66597);
+
+       r8a66597_mdfy(r8a66597, mbw | pipenum, mbw | CURPIPE, CFIFOSEL);
        r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum);
 }
 
@@ -506,11 +519,13 @@ static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum)
 static inline void fifo_change_from_pipe(struct r8a66597 *r8a66597,
                                         struct r8a66597_pipe *pipe)
 {
+       unsigned short mbw = mbw_value(r8a66597);
+
        cfifo_change(r8a66597, 0);
-       r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D0FIFOSEL);
-       r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D1FIFOSEL);
+       r8a66597_mdfy(r8a66597, mbw | 0, mbw | CURPIPE, D0FIFOSEL);
+       r8a66597_mdfy(r8a66597, mbw | 0, mbw | CURPIPE, D1FIFOSEL);
 
-       r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum, MBW | CURPIPE,
+       r8a66597_mdfy(r8a66597, mbw | pipe->info.pipenum, mbw | CURPIPE,
                      pipe->fifosel);
        r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE, pipe->info.pipenum);
 }
@@ -742,9 +757,13 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
                                     struct r8a66597_pipe *pipe,
                                     struct urb *urb)
 {
-#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
        int i;
        struct r8a66597_pipe_info *info = &pipe->info;
+       unsigned short mbw = mbw_value(r8a66597);
+
+       /* pipe dma is only for external controlles */
+       if (r8a66597->pdata->on_chip)
+               return;
 
        if ((pipe->info.pipenum != 0) && (info->type != R8A66597_INT)) {
                for (i = 0; i < R8A66597_MAX_DMA_CHANNEL; i++) {
@@ -763,8 +782,8 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
                        set_pipe_reg_addr(pipe, i);
 
                        cfifo_change(r8a66597, 0);
-                       r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum,
-                                     MBW | CURPIPE, pipe->fifosel);
+                       r8a66597_mdfy(r8a66597, mbw | pipe->info.pipenum,
+                                     mbw | CURPIPE, pipe->fifosel);
 
                        r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE,
                                          pipe->info.pipenum);
@@ -772,7 +791,6 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
                        break;
                }
        }
-#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
 }
 
 /* this function must be called with interrupt disabled */
@@ -1769,7 +1787,7 @@ static void r8a66597_timer(unsigned long _r8a66597)
 
        spin_lock_irqsave(&r8a66597->lock, flags);
 
-       for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+       for (port = 0; port < r8a66597->max_root_hub; port++)
                r8a66597_root_hub_control(r8a66597, port);
 
        spin_unlock_irqrestore(&r8a66597->lock, flags);
@@ -1807,7 +1825,7 @@ static void set_address_zero(struct r8a66597 *r8a66597, struct urb *urb)
        u16 root_port, hub_port;
 
        if (usb_address == 0) {
-               get_port_number(urb->dev->devpath,
+               get_port_number(r8a66597, urb->dev->devpath,
                                &root_port, &hub_port);
                set_devadd_reg(r8a66597, 0,
                               get_r8a66597_usb_speed(urb->dev->speed),
@@ -2082,7 +2100,7 @@ static int r8a66597_hub_status_data(struct usb_hcd *hcd, char *buf)
 
        *buf = 0;       /* initialize (no change) */
 
-       for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++) {
+       for (i = 0; i < r8a66597->max_root_hub; i++) {
                if (r8a66597->root_hub[i].port & 0xffff0000)
                        *buf |= 1 << (i + 1);
        }
@@ -2097,11 +2115,11 @@ static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597,
 {
        desc->bDescriptorType = 0x29;
        desc->bHubContrCurrent = 0;
-       desc->bNbrPorts = R8A66597_MAX_ROOT_HUB;
+       desc->bNbrPorts = r8a66597->max_root_hub;
        desc->bDescLength = 9;
        desc->bPwrOn2PwrGood = 0;
        desc->wHubCharacteristics = cpu_to_le16(0x0011);
-       desc->bitmap[0] = ((1 << R8A66597_MAX_ROOT_HUB) - 1) << 1;
+       desc->bitmap[0] = ((1 << r8a66597->max_root_hub) - 1) << 1;
        desc->bitmap[1] = ~0;
 }
 
@@ -2129,7 +2147,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                }
                break;
        case ClearPortFeature:
-               if (wIndex > R8A66597_MAX_ROOT_HUB)
+               if (wIndex > r8a66597->max_root_hub)
                        goto error;
                if (wLength != 0)
                        goto error;
@@ -2162,12 +2180,12 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                *buf = 0x00;
                break;
        case GetPortStatus:
-               if (wIndex > R8A66597_MAX_ROOT_HUB)
+               if (wIndex > r8a66597->max_root_hub)
                        goto error;
                *(__le32 *)buf = cpu_to_le32(rh->port);
                break;
        case SetPortFeature:
-               if (wIndex > R8A66597_MAX_ROOT_HUB)
+               if (wIndex > r8a66597->max_root_hub)
                        goto error;
                if (wLength != 0)
                        goto error;
@@ -2216,7 +2234,7 @@ static int r8a66597_bus_suspend(struct usb_hcd *hcd)
 
        dbg("%s", __func__);
 
-       for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+       for (port = 0; port < r8a66597->max_root_hub; port++) {
                struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
                unsigned long dvstctr_reg = get_dvstctr_reg(port);
 
@@ -2247,7 +2265,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
 
        dbg("%s", __func__);
 
-       for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+       for (port = 0; port < r8a66597->max_root_hub; port++) {
                struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
                unsigned long dvstctr_reg = get_dvstctr_reg(port);
 
@@ -2305,16 +2323,16 @@ static struct hc_driver r8a66597_hc_driver = {
 };
 
 #if defined(CONFIG_PM)
-static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
+static int r8a66597_suspend(struct device *dev)
 {
-       struct r8a66597         *r8a66597 = dev_get_drvdata(&pdev->dev);
+       struct r8a66597         *r8a66597 = dev_get_drvdata(dev);
        int port;
 
        dbg("%s", __func__);
 
        disable_controller(r8a66597);
 
-       for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+       for (port = 0; port < r8a66597->max_root_hub; port++) {
                struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
 
                rh->port = 0x00000000;
@@ -2323,9 +2341,9 @@ static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
        return 0;
 }
 
-static int r8a66597_resume(struct platform_device *pdev)
+static int r8a66597_resume(struct device *dev)
 {
-       struct r8a66597         *r8a66597 = dev_get_drvdata(&pdev->dev);
+       struct r8a66597         *r8a66597 = dev_get_drvdata(dev);
        struct usb_hcd          *hcd = r8a66597_to_hcd(r8a66597);
 
        dbg("%s", __func__);
@@ -2335,9 +2353,17 @@ static int r8a66597_resume(struct platform_device *pdev)
 
        return 0;
 }
+
+static struct dev_pm_ops r8a66597_dev_pm_ops = {
+       .suspend = r8a66597_suspend,
+       .resume = r8a66597_resume,
+       .poweroff = r8a66597_suspend,
+       .restore = r8a66597_resume,
+};
+
+#define R8A66597_DEV_PM_OPS    (&r8a66597_dev_pm_ops)
 #else  /* if defined(CONFIG_PM) */
-#define r8a66597_suspend       NULL
-#define r8a66597_resume                NULL
+#define R8A66597_DEV_PM_OPS    NULL
 #endif
 
 static int __init_or_module r8a66597_remove(struct platform_device *pdev)
@@ -2348,8 +2374,9 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev)
        del_timer_sync(&r8a66597->rh_timer);
        usb_remove_hcd(hcd);
        iounmap((void *)r8a66597->reg);
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
-       clk_put(r8a66597->clk);
+#ifdef CONFIG_HAVE_CLK
+       if (r8a66597->pdata->on_chip)
+               clk_put(r8a66597->clk);
 #endif
        usb_put_hcd(hcd);
        return 0;
@@ -2357,7 +2384,7 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev)
 
 static int __devinit r8a66597_probe(struct platform_device *pdev)
 {
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
+#ifdef CONFIG_HAVE_CLK
        char clk_name[8];
 #endif
        struct resource *res = NULL, *ires;
@@ -2419,15 +2446,20 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)
        r8a66597->pdata = pdev->dev.platform_data;
        r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
-       snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
-       r8a66597->clk = clk_get(&pdev->dev, clk_name);
-       if (IS_ERR(r8a66597->clk)) {
-               dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
-               ret = PTR_ERR(r8a66597->clk);
-               goto clean_up2;
-       }
+       if (r8a66597->pdata->on_chip) {
+#ifdef CONFIG_HAVE_CLK
+               snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
+               r8a66597->clk = clk_get(&pdev->dev, clk_name);
+               if (IS_ERR(r8a66597->clk)) {
+                       dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
+                               clk_name);
+                       ret = PTR_ERR(r8a66597->clk);
+                       goto clean_up2;
+               }
 #endif
+               r8a66597->max_root_hub = 1;
+       } else
+               r8a66597->max_root_hub = 2;
 
        spin_lock_init(&r8a66597->lock);
        init_timer(&r8a66597->rh_timer);
@@ -2457,8 +2489,9 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)
        return 0;
 
 clean_up3:
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
-       clk_put(r8a66597->clk);
+#ifdef CONFIG_HAVE_CLK
+       if (r8a66597->pdata->on_chip)
+               clk_put(r8a66597->clk);
 clean_up2:
 #endif
        usb_put_hcd(hcd);
@@ -2473,11 +2506,10 @@ clean_up:
 static struct platform_driver r8a66597_driver = {
        .probe =        r8a66597_probe,
        .remove =       r8a66597_remove,
-       .suspend =      r8a66597_suspend,
-       .resume =       r8a66597_resume,
        .driver         = {
                .name = (char *) hcd_name,
                .owner  = THIS_MODULE,
+               .pm     = R8A66597_DEV_PM_OPS,
        },
 };
 
index d72680b..228e3fb 100644 (file)
 #ifndef __R8A66597_H__
 #define __R8A66597_H__
 
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
+#ifdef CONFIG_HAVE_CLK
 #include <linux/clk.h>
 #endif
 
 #include <linux/usb/r8a66597.h>
 
-#define SYSCFG0                0x00
-#define SYSCFG1                0x02
-#define SYSSTS0                0x04
-#define SYSSTS1                0x06
-#define DVSTCTR0       0x08
-#define DVSTCTR1       0x0A
-#define TESTMODE       0x0C
-#define PINCFG         0x0E
-#define DMA0CFG                0x10
-#define DMA1CFG                0x12
-#define CFIFO          0x14
-#define D0FIFO         0x18
-#define D1FIFO         0x1C
-#define CFIFOSEL       0x20
-#define CFIFOCTR       0x22
-#define CFIFOSIE       0x24
-#define D0FIFOSEL      0x28
-#define D0FIFOCTR      0x2A
-#define D1FIFOSEL      0x2C
-#define D1FIFOCTR      0x2E
-#define INTENB0                0x30
-#define INTENB1                0x32
-#define INTENB2                0x34
-#define BRDYENB                0x36
-#define NRDYENB                0x38
-#define BEMPENB                0x3A
-#define SOFCFG         0x3C
-#define INTSTS0                0x40
-#define INTSTS1                0x42
-#define INTSTS2                0x44
-#define BRDYSTS                0x46
-#define NRDYSTS                0x48
-#define BEMPSTS                0x4A
-#define FRMNUM         0x4C
-#define UFRMNUM                0x4E
-#define USBADDR                0x50
-#define USBREQ         0x54
-#define USBVAL         0x56
-#define USBINDX                0x58
-#define USBLENG                0x5A
-#define DCPCFG         0x5C
-#define DCPMAXP                0x5E
-#define DCPCTR         0x60
-#define PIPESEL                0x64
-#define PIPECFG                0x68
-#define PIPEBUF                0x6A
-#define PIPEMAXP       0x6C
-#define PIPEPERI       0x6E
-#define PIPE1CTR       0x70
-#define PIPE2CTR       0x72
-#define PIPE3CTR       0x74
-#define PIPE4CTR       0x76
-#define PIPE5CTR       0x78
-#define PIPE6CTR       0x7A
-#define PIPE7CTR       0x7C
-#define PIPE8CTR       0x7E
-#define PIPE9CTR       0x80
-#define PIPE1TRE       0x90
-#define PIPE1TRN       0x92
-#define PIPE2TRE       0x94
-#define PIPE2TRN       0x96
-#define PIPE3TRE       0x98
-#define PIPE3TRN       0x9A
-#define PIPE4TRE       0x9C
-#define        PIPE4TRN        0x9E
-#define        PIPE5TRE        0xA0
-#define        PIPE5TRN        0xA2
-#define DEVADD0                0xD0
-#define DEVADD1                0xD2
-#define DEVADD2                0xD4
-#define DEVADD3                0xD6
-#define DEVADD4                0xD8
-#define DEVADD5                0xDA
-#define DEVADD6                0xDC
-#define DEVADD7                0xDE
-#define DEVADD8                0xE0
-#define DEVADD9                0xE2
-#define DEVADDA                0xE4
-
-/* System Configuration Control Register */
-#define        XTAL            0xC000  /* b15-14: Crystal selection */
-#define          XTAL48         0x8000   /* 48MHz */
-#define          XTAL24         0x4000   /* 24MHz */
-#define          XTAL12         0x0000   /* 12MHz */
-#define        XCKE            0x2000  /* b13: External clock enable */
-#define        PLLC            0x0800  /* b11: PLL control */
-#define        SCKE            0x0400  /* b10: USB clock enable */
-#define        PCSDIS          0x0200  /* b9: not CS wakeup */
-#define        LPSME           0x0100  /* b8: Low power sleep mode */
-#define        HSE             0x0080  /* b7: Hi-speed enable */
-#define        DCFM            0x0040  /* b6: Controller function select  */
-#define        DRPD            0x0020  /* b5: D+/- pull down control */
-#define        DPRPU           0x0010  /* b4: D+ pull up control */
-#define        USBE            0x0001  /* b0: USB module operation enable */
-
-/* System Configuration Status Register */
-#define        OVCBIT          0x8000  /* b15-14: Over-current bit */
-#define        OVCMON          0xC000  /* b15-14: Over-current monitor */
-#define        SOFEA           0x0020  /* b5: SOF monitor */
-#define        IDMON           0x0004  /* b3: ID-pin monitor */
-#define        LNST            0x0003  /* b1-0: D+, D- line status */
-#define          SE1            0x0003   /* SE1 */
-#define          FS_KSTS        0x0002   /* Full-Speed K State */
-#define          FS_JSTS        0x0001   /* Full-Speed J State */
-#define          LS_JSTS        0x0002   /* Low-Speed J State */
-#define          LS_KSTS        0x0001   /* Low-Speed K State */
-#define          SE0            0x0000   /* SE0 */
-
-/* Device State Control Register */
-#define        EXTLP0          0x0400  /* b10: External port */
-#define        VBOUT           0x0200  /* b9: VBUS output */
-#define        WKUP            0x0100  /* b8: Remote wakeup */
-#define        RWUPE           0x0080  /* b7: Remote wakeup sense */
-#define        USBRST          0x0040  /* b6: USB reset enable */
-#define        RESUME          0x0020  /* b5: Resume enable */
-#define        UACT            0x0010  /* b4: USB bus enable */
-#define        RHST            0x0007  /* b1-0: Reset handshake status */
-#define          HSPROC         0x0004   /* HS handshake is processing */
-#define          HSMODE         0x0003   /* Hi-Speed mode */
-#define          FSMODE         0x0002   /* Full-Speed mode */
-#define          LSMODE         0x0001   /* Low-Speed mode */
-#define          UNDECID        0x0000   /* Undecided */
-
-/* Test Mode Register */
-#define        UTST                    0x000F  /* b3-0: Test select */
-#define          H_TST_PACKET           0x000C   /* HOST TEST Packet */
-#define          H_TST_SE0_NAK          0x000B   /* HOST TEST SE0 NAK */
-#define          H_TST_K                0x000A   /* HOST TEST K */
-#define          H_TST_J                0x0009   /* HOST TEST J */
-#define          H_TST_NORMAL           0x0000   /* HOST Normal Mode */
-#define          P_TST_PACKET           0x0004   /* PERI TEST Packet */
-#define          P_TST_SE0_NAK          0x0003   /* PERI TEST SE0 NAK */
-#define          P_TST_K                0x0002   /* PERI TEST K */
-#define          P_TST_J                0x0001   /* PERI TEST J */
-#define          P_TST_NORMAL           0x0000   /* PERI Normal Mode */
-
-/* Data Pin Configuration Register */
-#define        LDRV                    0x8000  /* b15: Drive Current Adjust */
-#define          VIF1                    0x0000                /* VIF = 1.8V */
-#define          VIF3                    0x8000                /* VIF = 3.3V */
-#define        INTA                    0x0001  /* b1: USB INT-pin active */
-
-/* DMAx Pin Configuration Register */
-#define        DREQA                   0x4000  /* b14: Dreq active select */
-#define        BURST                   0x2000  /* b13: Burst mode */
-#define        DACKA                   0x0400  /* b10: Dack active select */
-#define        DFORM                   0x0380  /* b9-7: DMA mode select */
-#define          CPU_ADR_RD_WR          0x0000   /* Address + RD/WR mode (CPU bus) */
-#define          CPU_DACK_RD_WR         0x0100   /* DACK + RD/WR mode (CPU bus) */
-#define          CPU_DACK_ONLY          0x0180   /* DACK only mode (CPU bus) */
-#define          SPLIT_DACK_ONLY        0x0200   /* DACK only mode (SPLIT bus) */
-#define        DENDA                   0x0040  /* b6: Dend active select */
-#define        PKTM                    0x0020  /* b5: Packet mode */
-#define        DENDE                   0x0010  /* b4: Dend enable */
-#define        OBUS                    0x0004  /* b2: OUTbus mode */
-
-/* CFIFO/DxFIFO Port Select Register */
-#define        RCNT            0x8000  /* b15: Read count mode */
-#define        REW             0x4000  /* b14: Buffer rewind */
-#define        DCLRM           0x2000  /* b13: DMA buffer clear mode */
-#define        DREQE           0x1000  /* b12: DREQ output enable */
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-#define        MBW             0x0800
-#else
-#define        MBW             0x0400  /* b10: Maximum bit width for FIFO access */
-#endif
-#define          MBW_8          0x0000   /*  8bit */
-#define          MBW_16         0x0400   /* 16bit */
-#define        BIGEND          0x0100  /* b8: Big endian mode */
-#define          BYTE_LITTLE    0x0000         /* little dendian */
-#define          BYTE_BIG       0x0100         /* big endifan */
-#define        ISEL            0x0020  /* b5: DCP FIFO port direction select */
-#define        CURPIPE         0x000F  /* b2-0: PIPE select */
-
-/* CFIFO/DxFIFO Port Control Register */
-#define        BVAL            0x8000  /* b15: Buffer valid flag */
-#define        BCLR            0x4000  /* b14: Buffer clear */
-#define        FRDY            0x2000  /* b13: FIFO ready */
-#define        DTLN            0x0FFF  /* b11-0: FIFO received data length */
-
-/* Interrupt Enable Register 0 */
-#define        VBSE    0x8000  /* b15: VBUS interrupt */
-#define        RSME    0x4000  /* b14: Resume interrupt */
-#define        SOFE    0x2000  /* b13: Frame update interrupt */
-#define        DVSE    0x1000  /* b12: Device state transition interrupt */
-#define        CTRE    0x0800  /* b11: Control transfer stage transition interrupt */
-#define        BEMPE   0x0400  /* b10: Buffer empty interrupt */
-#define        NRDYE   0x0200  /* b9: Buffer not ready interrupt */
-#define        BRDYE   0x0100  /* b8: Buffer ready interrupt */
-
-/* Interrupt Enable Register 1 */
-#define        OVRCRE          0x8000  /* b15: Over-current interrupt */
-#define        BCHGE           0x4000  /* b14: USB us chenge interrupt */
-#define        DTCHE           0x1000  /* b12: Detach sense interrupt */
-#define        ATTCHE          0x0800  /* b11: Attach sense interrupt */
-#define        EOFERRE         0x0040  /* b6: EOF error interrupt */
-#define        SIGNE           0x0020  /* b5: SETUP IGNORE interrupt */
-#define        SACKE           0x0010  /* b4: SETUP ACK interrupt */
-
-/* BRDY Interrupt Enable/Status Register */
-#define        BRDY9           0x0200  /* b9: PIPE9 */
-#define        BRDY8           0x0100  /* b8: PIPE8 */
-#define        BRDY7           0x0080  /* b7: PIPE7 */
-#define        BRDY6           0x0040  /* b6: PIPE6 */
-#define        BRDY5           0x0020  /* b5: PIPE5 */
-#define        BRDY4           0x0010  /* b4: PIPE4 */
-#define        BRDY3           0x0008  /* b3: PIPE3 */
-#define        BRDY2           0x0004  /* b2: PIPE2 */
-#define        BRDY1           0x0002  /* b1: PIPE1 */
-#define        BRDY0           0x0001  /* b1: PIPE0 */
-
-/* NRDY Interrupt Enable/Status Register */
-#define        NRDY9           0x0200  /* b9: PIPE9 */
-#define        NRDY8           0x0100  /* b8: PIPE8 */
-#define        NRDY7           0x0080  /* b7: PIPE7 */
-#define        NRDY6           0x0040  /* b6: PIPE6 */
-#define        NRDY5           0x0020  /* b5: PIPE5 */
-#define        NRDY4           0x0010  /* b4: PIPE4 */
-#define        NRDY3           0x0008  /* b3: PIPE3 */
-#define        NRDY2           0x0004  /* b2: PIPE2 */
-#define        NRDY1           0x0002  /* b1: PIPE1 */
-#define        NRDY0           0x0001  /* b1: PIPE0 */
-
-/* BEMP Interrupt Enable/Status Register */
-#define        BEMP9           0x0200  /* b9: PIPE9 */
-#define        BEMP8           0x0100  /* b8: PIPE8 */
-#define        BEMP7           0x0080  /* b7: PIPE7 */
-#define        BEMP6           0x0040  /* b6: PIPE6 */
-#define        BEMP5           0x0020  /* b5: PIPE5 */
-#define        BEMP4           0x0010  /* b4: PIPE4 */
-#define        BEMP3           0x0008  /* b3: PIPE3 */
-#define        BEMP2           0x0004  /* b2: PIPE2 */
-#define        BEMP1           0x0002  /* b1: PIPE1 */
-#define        BEMP0           0x0001  /* b0: PIPE0 */
-
-/* SOF Pin Configuration Register */
-#define        TRNENSEL        0x0100  /* b8: Select transaction enable period */
-#define        BRDYM           0x0040  /* b6: BRDY clear timing */
-#define        INTL            0x0020  /* b5: Interrupt sense select */
-#define        EDGESTS         0x0010  /* b4:  */
-#define        SOFMODE         0x000C  /* b3-2: SOF pin select */
-#define          SOF_125US      0x0008   /* SOF OUT 125us Frame Signal */
-#define          SOF_1MS        0x0004   /* SOF OUT 1ms Frame Signal */
-#define          SOF_DISABLE    0x0000   /* SOF OUT Disable */
-
-/* Interrupt Status Register 0 */
-#define        VBINT   0x8000  /* b15: VBUS interrupt */
-#define        RESM    0x4000  /* b14: Resume interrupt */
-#define        SOFR    0x2000  /* b13: SOF frame update interrupt */
-#define        DVST    0x1000  /* b12: Device state transition interrupt */
-#define        CTRT    0x0800  /* b11: Control transfer stage transition interrupt */
-#define        BEMP    0x0400  /* b10: Buffer empty interrupt */
-#define        NRDY    0x0200  /* b9: Buffer not ready interrupt */
-#define        BRDY    0x0100  /* b8: Buffer ready interrupt */
-#define        VBSTS   0x0080  /* b7: VBUS input port */
-#define        DVSQ    0x0070  /* b6-4: Device state */
-#define          DS_SPD_CNFG    0x0070   /* Suspend Configured */
-#define          DS_SPD_ADDR    0x0060   /* Suspend Address */
-#define          DS_SPD_DFLT    0x0050   /* Suspend Default */
-#define          DS_SPD_POWR    0x0040   /* Suspend Powered */
-#define          DS_SUSP        0x0040   /* Suspend */
-#define          DS_CNFG        0x0030   /* Configured */
-#define          DS_ADDS        0x0020   /* Address */
-#define          DS_DFLT        0x0010   /* Default */
-#define          DS_POWR        0x0000   /* Powered */
-#define        DVSQS           0x0030  /* b5-4: Device state */
-#define        VALID           0x0008  /* b3: Setup packet detected flag */
-#define        CTSQ            0x0007  /* b2-0: Control transfer stage */
-#define          CS_SQER        0x0006   /* Sequence error */
-#define          CS_WRND        0x0005   /* Control write nodata status stage */
-#define          CS_WRSS        0x0004   /* Control write status stage */
-#define          CS_WRDS        0x0003   /* Control write data stage */
-#define          CS_RDSS        0x0002   /* Control read status stage */
-#define          CS_RDDS        0x0001   /* Control read data stage */
-#define          CS_IDST        0x0000   /* Idle or setup stage */
-
-/* Interrupt Status Register 1 */
-#define        OVRCR           0x8000  /* b15: Over-current interrupt */
-#define        BCHG            0x4000  /* b14: USB bus chenge interrupt */
-#define        DTCH            0x1000  /* b12: Detach sense interrupt */
-#define        ATTCH           0x0800  /* b11: Attach sense interrupt */
-#define        EOFERR          0x0040  /* b6: EOF-error interrupt */
-#define        SIGN            0x0020  /* b5: Setup ignore interrupt */
-#define        SACK            0x0010  /* b4: Setup acknowledge interrupt */
-
-/* Frame Number Register */
-#define        OVRN            0x8000  /* b15: Overrun error */
-#define        CRCE            0x4000  /* b14: Received data error */
-#define        FRNM            0x07FF  /* b10-0: Frame number */
-
-/* Micro Frame Number Register */
-#define        UFRNM           0x0007  /* b2-0: Micro frame number */
-
-/* Default Control Pipe Maxpacket Size Register */
-/* Pipe Maxpacket Size Register */
-#define        DEVSEL  0xF000  /* b15-14: Device address select */
-#define        MAXP    0x007F  /* b6-0: Maxpacket size of default control pipe */
-
-/* Default Control Pipe Control Register */
-#define        BSTS            0x8000  /* b15: Buffer status */
-#define        SUREQ           0x4000  /* b14: Send USB request  */
-#define        CSCLR           0x2000  /* b13: complete-split status clear */
-#define        CSSTS           0x1000  /* b12: complete-split status */
-#define        SUREQCLR        0x0800  /* b11: stop setup request */
-#define        SQCLR           0x0100  /* b8: Sequence toggle bit clear */
-#define        SQSET           0x0080  /* b7: Sequence toggle bit set */
-#define        SQMON           0x0040  /* b6: Sequence toggle bit monitor */
-#define        PBUSY           0x0020  /* b5: pipe busy */
-#define        PINGE           0x0010  /* b4: ping enable */
-#define        CCPL            0x0004  /* b2: Enable control transfer complete */
-#define        PID             0x0003  /* b1-0: Response PID */
-#define          PID_STALL11    0x0003   /* STALL */
-#define          PID_STALL      0x0002   /* STALL */
-#define          PID_BUF        0x0001   /* BUF */
-#define          PID_NAK        0x0000   /* NAK */
-
-/* Pipe Window Select Register */
-#define        PIPENM          0x0007  /* b2-0: Pipe select */
-
-/* Pipe Configuration Register */
-#define        R8A66597_TYP    0xC000  /* b15-14: Transfer type */
-#define          R8A66597_ISO   0xC000           /* Isochronous */
-#define          R8A66597_INT   0x8000           /* Interrupt */
-#define          R8A66597_BULK  0x4000           /* Bulk */
-#define        R8A66597_BFRE   0x0400  /* b10: Buffer ready interrupt mode select */
-#define        R8A66597_DBLB   0x0200  /* b9: Double buffer mode select */
-#define        R8A66597_CNTMD  0x0100  /* b8: Continuous transfer mode select */
-#define        R8A66597_SHTNAK 0x0080  /* b7: Transfer end NAK */
-#define        R8A66597_DIR    0x0010  /* b4: Transfer direction select */
-#define        R8A66597_EPNUM  0x000F  /* b3-0: Eendpoint number select */
-
-/* Pipe Buffer Configuration Register */
-#define        BUFSIZE         0x7C00  /* b14-10: Pipe buffer size */
-#define        BUFNMB          0x007F  /* b6-0: Pipe buffer number */
-#define        PIPE0BUF        256
-#define        PIPExBUF        64
-
-/* Pipe Maxpacket Size Register */
-#define        MXPS            0x07FF  /* b10-0: Maxpacket size */
-
-/* Pipe Cycle Configuration Register */
-#define        IFIS    0x1000  /* b12: Isochronous in-buffer flush mode select */
-#define        IITV    0x0007  /* b2-0: Isochronous interval */
-
-/* Pipex Control Register */
-#define        BSTS    0x8000  /* b15: Buffer status */
-#define        INBUFM  0x4000  /* b14: IN buffer monitor (Only for PIPE1 to 5) */
-#define        CSCLR   0x2000  /* b13: complete-split status clear */
-#define        CSSTS   0x1000  /* b12: complete-split status */
-#define        ATREPM  0x0400  /* b10: Auto repeat mode */
-#define        ACLRM   0x0200  /* b9: Out buffer auto clear mode */
-#define        SQCLR   0x0100  /* b8: Sequence toggle bit clear */
-#define        SQSET   0x0080  /* b7: Sequence toggle bit set */
-#define        SQMON   0x0040  /* b6: Sequence toggle bit monitor */
-#define        PBUSY   0x0020  /* b5: pipe busy */
-#define        PID     0x0003  /* b1-0: Response PID */
-
-/* PIPExTRE */
-#define        TRENB           0x0200  /* b9: Transaction counter enable */
-#define        TRCLR           0x0100  /* b8: Transaction counter clear */
-
-/* PIPExTRN */
-#define        TRNCNT          0xFFFF  /* b15-0: Transaction counter */
-
-/* DEVADDx */
-#define        UPPHUB          0x7800
-#define        HUBPORT         0x0700
-#define        USBSPD          0x00C0
-#define        RTPORT          0x0001
-
 #define R8A66597_MAX_NUM_PIPE          10
 #define R8A66597_BUF_BSIZE             8
 #define R8A66597_MAX_DEVICE            10
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-#define R8A66597_MAX_ROOT_HUB          1
-#else
 #define R8A66597_MAX_ROOT_HUB          2
-#endif
 #define R8A66597_MAX_SAMPLING          5
 #define R8A66597_RH_POLL_TIME          10
 #define R8A66597_MAX_DMA_CHANNEL       2
@@ -487,7 +113,7 @@ struct r8a66597_root_hub {
 struct r8a66597 {
        spinlock_t lock;
        unsigned long reg;
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
+#ifdef CONFIG_HAVE_CLK
        struct clk *clk;
 #endif
        struct r8a66597_platdata        *pdata;
@@ -504,6 +130,7 @@ struct r8a66597 {
        unsigned short interval_map;
        unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
        unsigned char dma_map;
+       unsigned int max_root_hub;
 
        struct list_head child_device;
        unsigned long child_connect_map[4];
@@ -550,21 +177,22 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
                                      unsigned long offset, u16 *buf,
                                      int len)
 {
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
        unsigned long fifoaddr = r8a66597->reg + offset;
        unsigned long count;
 
-       count = len / 4;
-       insl(fifoaddr, buf, count);
+       if (r8a66597->pdata->on_chip) {
+               count = len / 4;
+               insl(fifoaddr, buf, count);
 
-       if (len & 0x00000003) {
-               unsigned long tmp = inl(fifoaddr);
-               memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03);
+               if (len & 0x00000003) {
+                       unsigned long tmp = inl(fifoaddr);
+                       memcpy((unsigned char *)buf + count * 4, &tmp,
+                              len & 0x03);
+               }
+       } else {
+               len = (len + 1) / 2;
+               insw(fifoaddr, buf, len);
        }
-#else
-       len = (len + 1) / 2;
-       insw(r8a66597->reg + offset, buf, len);
-#endif
 }
 
 static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
@@ -578,33 +206,33 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
                                       int len)
 {
        unsigned long fifoaddr = r8a66597->reg + offset;
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
        unsigned long count;
        unsigned char *pb;
        int i;
 
-       count = len / 4;
-       outsl(fifoaddr, buf, count);
+       if (r8a66597->pdata->on_chip) {
+               count = len / 4;
+               outsl(fifoaddr, buf, count);
+
+               if (len & 0x00000003) {
+                       pb = (unsigned char *)buf + count * 4;
+                       for (i = 0; i < (len & 0x00000003); i++) {
+                               if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
+                                       outb(pb[i], fifoaddr + i);
+                               else
+                                       outb(pb[i], fifoaddr + 3 - i);
+                       }
+               }
+       } else {
+               int odd = len & 0x0001;
 
-       if (len & 0x00000003) {
-               pb = (unsigned char *)buf + count * 4;
-               for (i = 0; i < (len & 0x00000003); i++) {
-                       if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
-                               outb(pb[i], fifoaddr + i);
-                       else
-                               outb(pb[i], fifoaddr + 3 - i);
+               len = len / 2;
+               outsw(fifoaddr, buf, len);
+               if (unlikely(odd)) {
+                       buf = &buf[len];
+                       outb((unsigned char)*buf, fifoaddr);
                }
        }
-#else
-       int odd = len & 0x0001;
-
-       len = len / 2;
-       outsw(fifoaddr, buf, len);
-       if (unlikely(odd)) {
-               buf = &buf[len];
-               outb((unsigned char)*buf, fifoaddr);
-       }
-#endif
 }
 
 static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
index c7c1ca0..1d26bed 100644 (file)
@@ -2167,8 +2167,9 @@ static int __devexit musb_remove(struct platform_device *pdev)
 
 #ifdef CONFIG_PM
 
-static int musb_suspend(struct platform_device *pdev, pm_message_t message)
+static int musb_suspend(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        unsigned long   flags;
        struct musb     *musb = dev_to_musb(&pdev->dev);
 
@@ -2195,8 +2196,9 @@ static int musb_suspend(struct platform_device *pdev, pm_message_t message)
        return 0;
 }
 
-static int musb_resume_early(struct platform_device *pdev)
+static int musb_resume_noirq(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct musb     *musb = dev_to_musb(&pdev->dev);
 
        if (!musb->clock)
@@ -2214,9 +2216,14 @@ static int musb_resume_early(struct platform_device *pdev)
        return 0;
 }
 
+static struct dev_pm_ops musb_dev_pm_ops = {
+       .suspend        = musb_suspend,
+       .resume_noirq   = musb_resume_noirq,
+};
+
+#define MUSB_DEV_PM_OPS (&musb_dev_pm_ops)
 #else
-#define        musb_suspend    NULL
-#define        musb_resume_early       NULL
+#define        MUSB_DEV_PM_OPS NULL
 #endif
 
 static struct platform_driver musb_driver = {
@@ -2224,11 +2231,10 @@ static struct platform_driver musb_driver = {
                .name           = (char *)musb_driver_name,
                .bus            = &platform_bus_type,
                .owner          = THIS_MODULE,
+               .pm             = MUSB_DEV_PM_OPS,
        },
        .remove         = __devexit_p(musb_remove),
        .shutdown       = musb_shutdown,
-       .suspend        = musb_suspend,
-       .resume_early   = musb_resume_early,
 };
 
 /*-------------------------------------------------------------------------*/
index 3b54b39..7e2c977 100644 (file)
@@ -1867,7 +1867,7 @@ config FB_W100
 
 config FB_SH_MOBILE_LCDC
        tristate "SuperH Mobile LCDC framebuffer support"
-       depends on FB && SUPERH
+       depends on FB && SUPERH && HAVE_CLK
        select FB_SYS_FILLRECT
        select FB_SYS_COPYAREA
        select FB_SYS_IMAGEBLIT
index 07f22b6..1cb5213 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mm.h>
 #include <linux/fb.h>
 #include <linux/clk.h>
+#include <linux/pm_runtime.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 
 #define PALETTE_NR 16
 
-struct sh_mobile_lcdc_priv;
-struct sh_mobile_lcdc_chan {
-       struct sh_mobile_lcdc_priv *lcdc;
-       unsigned long *reg_offs;
-       unsigned long ldmt1r_value;
-       unsigned long enabled; /* ME and SE in LDCNT2R */
-       struct sh_mobile_lcdc_chan_cfg cfg;
-       u32 pseudo_palette[PALETTE_NR];
-       struct fb_info *info;
-       dma_addr_t dma_handle;
-       struct fb_deferred_io defio;
-       struct scatterlist *sglist;
-       unsigned long frame_end;
-       wait_queue_head_t frame_end_wait;
-};
-
-struct sh_mobile_lcdc_priv {
-       void __iomem *base;
-       int irq;
-#ifdef CONFIG_HAVE_CLK
-       atomic_t clk_usecnt;
-       struct clk *dot_clk;
-       struct clk *clk;
-#endif
-       unsigned long lddckr;
-       struct sh_mobile_lcdc_chan ch[2];
-       int started;
-};
-
 /* shared registers */
 #define _LDDCKR 0x410
 #define _LDDCKSTPR 0x414
@@ -65,11 +37,23 @@ struct sh_mobile_lcdc_priv {
 #define _LDDWAR 0x900
 #define _LDDRAR 0x904
 
+/* shared registers and their order for context save/restore */
+static int lcdc_shared_regs[] = {
+       _LDDCKR,
+       _LDDCKSTPR,
+       _LDINTR,
+       _LDDDSR,
+       _LDCNT1R,
+       _LDCNT2R,
+};
+#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
+
 /* per-channel registers */
 enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
-       LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR };
+       LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
+       NR_CH_REGS };
 
-static unsigned long lcdc_offs_mainlcd[] = {
+static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
        [LDDCKPAT1R] = 0x400,
        [LDDCKPAT2R] = 0x404,
        [LDMT1R] = 0x418,
@@ -87,7 +71,7 @@ static unsigned long lcdc_offs_mainlcd[] = {
        [LDPMR] = 0x460,
 };
 
-static unsigned long lcdc_offs_sublcd[] = {
+static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
        [LDDCKPAT1R] = 0x408,
        [LDDCKPAT2R] = 0x40c,
        [LDMT1R] = 0x600,
@@ -112,6 +96,35 @@ static unsigned long lcdc_offs_sublcd[] = {
 #define LDINTR_FE      0x00000400
 #define LDINTR_FS      0x00000004
 
+struct sh_mobile_lcdc_priv;
+struct sh_mobile_lcdc_chan {
+       struct sh_mobile_lcdc_priv *lcdc;
+       unsigned long *reg_offs;
+       unsigned long ldmt1r_value;
+       unsigned long enabled; /* ME and SE in LDCNT2R */
+       struct sh_mobile_lcdc_chan_cfg cfg;
+       u32 pseudo_palette[PALETTE_NR];
+       unsigned long saved_ch_regs[NR_CH_REGS];
+       struct fb_info *info;
+       dma_addr_t dma_handle;
+       struct fb_deferred_io defio;
+       struct scatterlist *sglist;
+       unsigned long frame_end;
+       wait_queue_head_t frame_end_wait;
+};
+
+struct sh_mobile_lcdc_priv {
+       void __iomem *base;
+       int irq;
+       atomic_t hw_usecnt;
+       struct device *dev;
+       struct clk *dot_clk;
+       unsigned long lddckr;
+       struct sh_mobile_lcdc_chan ch[2];
+       unsigned long saved_shared_regs[NR_SHARED_REGS];
+       int started;
+};
+
 static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
                            int reg_nr, unsigned long data)
 {
@@ -156,6 +169,7 @@ static void lcdc_sys_write_index(void *handle, unsigned long data)
        lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000);
        lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
        lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+       lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
 }
 
 static void lcdc_sys_write_data(void *handle, unsigned long data)
@@ -165,6 +179,7 @@ static void lcdc_sys_write_data(void *handle, unsigned long data)
        lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000);
        lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
        lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+       lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
 }
 
 static unsigned long lcdc_sys_read_data(void *handle)
@@ -175,8 +190,9 @@ static unsigned long lcdc_sys_read_data(void *handle)
        lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
        lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
        udelay(1);
+       lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
 
-       return lcdc_read(ch->lcdc, _LDDRDR) & 0xffff;
+       return lcdc_read(ch->lcdc, _LDDRDR) & 0x3ffff;
 }
 
 struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
@@ -185,11 +201,10 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
        lcdc_sys_read_data,
 };
 
-#ifdef CONFIG_HAVE_CLK
 static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
 {
-       if (atomic_inc_and_test(&priv->clk_usecnt)) {
-               clk_enable(priv->clk);
+       if (atomic_inc_and_test(&priv->hw_usecnt)) {
+               pm_runtime_get_sync(priv->dev);
                if (priv->dot_clk)
                        clk_enable(priv->dot_clk);
        }
@@ -197,16 +212,12 @@ static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
 
 static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
 {
-       if (atomic_sub_return(1, &priv->clk_usecnt) == -1) {
+       if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
                if (priv->dot_clk)
                        clk_disable(priv->dot_clk);
-               clk_disable(priv->clk);
+               pm_runtime_put(priv->dev);
        }
 }
-#else
-static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) {}
-static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {}
-#endif
 
 static int sh_mobile_lcdc_sginit(struct fb_info *info,
                                  struct list_head *pagelist)
@@ -520,7 +531,6 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
                board_cfg = &ch->cfg.board_cfg;
                if (board_cfg->display_off)
                        board_cfg->display_off(board_cfg->board_data);
-
        }
 
        /* stop the lcdc */
@@ -579,9 +589,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
                                       int clock_source,
                                       struct sh_mobile_lcdc_priv *priv)
 {
-#ifdef CONFIG_HAVE_CLK
-       char clk_name[8];
-#endif
        char *str;
        int icksel;
 
@@ -595,25 +602,21 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
 
        priv->lddckr = icksel << 16;
 
-#ifdef CONFIG_HAVE_CLK
-       atomic_set(&priv->clk_usecnt, -1);
-       snprintf(clk_name, sizeof(clk_name), "lcdc%d", pdev->id);
-       priv->clk = clk_get(&pdev->dev, clk_name);
-       if (IS_ERR(priv->clk)) {
-               dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
-               return PTR_ERR(priv->clk);
-       }
-       
        if (str) {
                priv->dot_clk = clk_get(&pdev->dev, str);
                if (IS_ERR(priv->dot_clk)) {
                        dev_err(&pdev->dev, "cannot get dot clock %s\n", str);
-                       clk_put(priv->clk);
                        return PTR_ERR(priv->dot_clk);
                }
        }
-#endif
-
+       atomic_set(&priv->hw_usecnt, -1);
+
+       /* Runtime PM support involves two step for this driver:
+        * 1) Enable Runtime PM
+        * 2) Force Runtime PM Resume since hardware is accessed from probe()
+        */
+       pm_runtime_enable(priv->dev);
+       pm_runtime_resume(priv->dev);
        return 0;
 }
 
@@ -731,9 +734,59 @@ static int sh_mobile_lcdc_resume(struct device *dev)
        return sh_mobile_lcdc_start(platform_get_drvdata(pdev));
 }
 
+static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev);
+       struct sh_mobile_lcdc_chan *ch;
+       int k, n;
+
+       /* save per-channel registers */
+       for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
+               ch = &p->ch[k];
+               if (!ch->enabled)
+                       continue;
+               for (n = 0; n < NR_CH_REGS; n++)
+                       ch->saved_ch_regs[n] = lcdc_read_chan(ch, n);
+       }
+
+       /* save shared registers */
+       for (n = 0; n < NR_SHARED_REGS; n++)
+               p->saved_shared_regs[n] = lcdc_read(p, lcdc_shared_regs[n]);
+
+       /* turn off LCDC hardware */
+       lcdc_write(p, _LDCNT1R, 0);
+       return 0;
+}
+
+static int sh_mobile_lcdc_runtime_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev);
+       struct sh_mobile_lcdc_chan *ch;
+       int k, n;
+
+       /* restore per-channel registers */
+       for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
+               ch = &p->ch[k];
+               if (!ch->enabled)
+                       continue;
+               for (n = 0; n < NR_CH_REGS; n++)
+                       lcdc_write_chan(ch, n, ch->saved_ch_regs[n]);
+       }
+
+       /* restore shared registers */
+       for (n = 0; n < NR_SHARED_REGS; n++)
+               lcdc_write(p, lcdc_shared_regs[n], p->saved_shared_regs[n]);
+
+       return 0;
+}
+
 static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
        .suspend = sh_mobile_lcdc_suspend,
        .resume = sh_mobile_lcdc_resume,
+       .runtime_suspend = sh_mobile_lcdc_runtime_suspend,
+       .runtime_resume = sh_mobile_lcdc_runtime_resume,
 };
 
 static int sh_mobile_lcdc_remove(struct platform_device *pdev);
@@ -778,6 +831,7 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
        }
 
        priv->irq = i;
+       priv->dev = &pdev->dev;
        platform_set_drvdata(pdev, priv);
        pdata = pdev->dev.platform_data;
 
@@ -947,11 +1001,10 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
                framebuffer_release(info);
        }
 
-#ifdef CONFIG_HAVE_CLK
        if (priv->dot_clk)
                clk_put(priv->dot_clk);
-       clk_put(priv->clk);
-#endif
+
+       pm_runtime_disable(priv->dev);
 
        if (priv->base)
                iounmap(priv->base);
index c17c960..d7c76bb 100644 (file)
@@ -9,4 +9,7 @@
 struct dev_archdata {
 };
 
+struct pdev_archdata {
+};
+
 #endif /* _ASM_GENERIC_DEVICE_H */
index aebb810..a286429 100644 (file)
@@ -62,7 +62,7 @@ struct bus_type {
        int (*suspend)(struct device *dev, pm_message_t state);
        int (*resume)(struct device *dev);
 
-       struct dev_pm_ops *pm;
+       const struct dev_pm_ops *pm;
 
        struct bus_type_private *p;
 };
@@ -132,7 +132,7 @@ struct device_driver {
        int (*resume) (struct device *dev);
        struct attribute_group **groups;
 
-       struct dev_pm_ops *pm;
+       const struct dev_pm_ops *pm;
 
        struct driver_private *p;
 };
@@ -200,7 +200,8 @@ struct class {
        int (*suspend)(struct device *dev, pm_message_t state);
        int (*resume)(struct device *dev);
 
-       struct dev_pm_ops *pm;
+       const struct dev_pm_ops *pm;
+
        struct class_private *p;
 };
 
@@ -291,7 +292,7 @@ struct device_type {
        char *(*nodename)(struct device *dev);
        void (*release)(struct device *dev);
 
-       struct dev_pm_ops *pm;
+       const struct dev_pm_ops *pm;
 };
 
 /* interface for exporting device attributes */
index 8dc5123..3c6675c 100644 (file)
@@ -22,6 +22,9 @@ struct platform_device {
        struct resource * resource;
 
        struct platform_device_id       *id_entry;
+
+       /* arch specific additions */
+       struct pdev_archdata    archdata;
 };
 
 #define platform_get_device_id(pdev)   ((pdev)->id_entry)
@@ -57,8 +60,6 @@ struct platform_driver {
        int (*remove)(struct platform_device *);
        void (*shutdown)(struct platform_device *);
        int (*suspend)(struct platform_device *, pm_message_t state);
-       int (*suspend_late)(struct platform_device *, pm_message_t state);
-       int (*resume_early)(struct platform_device *);
        int (*resume)(struct platform_device *);
        struct device_driver driver;
        struct platform_device_id *id_table;
index b3f7476..2b6e20d 100644 (file)
 #define _LINUX_PM_H
 
 #include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
 
 /*
  * Callbacks for platform drivers to implement.
@@ -165,6 +169,28 @@ typedef struct pm_message {
  * It is allowed to unregister devices while the above callbacks are being
  * executed.  However, it is not allowed to unregister a device from within any
  * of its own callbacks.
+ *
+ * There also are the following callbacks related to run-time power management
+ * of devices:
+ *
+ * @runtime_suspend: Prepare the device for a condition in which it won't be
+ *     able to communicate with the CPU(s) and RAM due to power management.
+ *     This need not mean that the device should be put into a low power state.
+ *     For example, if the device is behind a link which is about to be turned
+ *     off, the device may remain at full power.  If the device does go to low
+ *     power and if device_may_wakeup(dev) is true, remote wake-up (i.e., a
+ *     hardware mechanism allowing the device to request a change of its power
+ *     state, such as PCI PME) should be enabled for it.
+ *
+ * @runtime_resume: Put the device into the fully active state in response to a
+ *     wake-up event generated by hardware or at the request of software.  If
+ *     necessary, put the device into the full power state and restore its
+ *     registers, so that it is fully operational.
+ *
+ * @runtime_idle: Device appears to be inactive and it might be put into a low
+ *     power state if all of the necessary conditions are satisfied.  Check
+ *     these conditions and handle the device as appropriate, possibly queueing
+ *     a suspend request for it.  The return value is ignored by the PM core.
  */
 
 struct dev_pm_ops {
@@ -182,6 +208,9 @@ struct dev_pm_ops {
        int (*thaw_noirq)(struct device *dev);
        int (*poweroff_noirq)(struct device *dev);
        int (*restore_noirq)(struct device *dev);
+       int (*runtime_suspend)(struct device *dev);
+       int (*runtime_resume)(struct device *dev);
+       int (*runtime_idle)(struct device *dev);
 };
 
 /**
@@ -315,14 +344,80 @@ enum dpm_state {
        DPM_OFF_IRQ,
 };
 
+/**
+ * Device run-time power management status.
+ *
+ * These status labels are used internally by the PM core to indicate the
+ * current status of a device with respect to the PM core operations.  They do
+ * not reflect the actual power state of the device or its status as seen by the
+ * driver.
+ *
+ * RPM_ACTIVE          Device is fully operational.  Indicates that the device
+ *                     bus type's ->runtime_resume() callback has completed
+ *                     successfully.
+ *
+ * RPM_SUSPENDED       Device bus type's ->runtime_suspend() callback has
+ *                     completed successfully.  The device is regarded as
+ *                     suspended.
+ *
+ * RPM_RESUMING                Device bus type's ->runtime_resume() callback is being
+ *                     executed.
+ *
+ * RPM_SUSPENDING      Device bus type's ->runtime_suspend() callback is being
+ *                     executed.
+ */
+
+enum rpm_status {
+       RPM_ACTIVE = 0,
+       RPM_RESUMING,
+       RPM_SUSPENDED,
+       RPM_SUSPENDING,
+};
+
+/**
+ * Device run-time power management request types.
+ *
+ * RPM_REQ_NONE                Do nothing.
+ *
+ * RPM_REQ_IDLE                Run the device bus type's ->runtime_idle() callback
+ *
+ * RPM_REQ_SUSPEND     Run the device bus type's ->runtime_suspend() callback
+ *
+ * RPM_REQ_RESUME      Run the device bus type's ->runtime_resume() callback
+ */
+
+enum rpm_request {
+       RPM_REQ_NONE = 0,
+       RPM_REQ_IDLE,
+       RPM_REQ_SUSPEND,
+       RPM_REQ_RESUME,
+};
+
 struct dev_pm_info {
        pm_message_t            power_state;
-       unsigned                can_wakeup:1;
-       unsigned                should_wakeup:1;
+       unsigned int            can_wakeup:1;
+       unsigned int            should_wakeup:1;
        enum dpm_state          status;         /* Owned by the PM core */
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_SLEEP
        struct list_head        entry;
 #endif
+#ifdef CONFIG_PM_RUNTIME
+       struct timer_list       suspend_timer;
+       unsigned long           timer_expires;
+       struct work_struct      work;
+       wait_queue_head_t       wait_queue;
+       spinlock_t              lock;
+       atomic_t                usage_count;
+       atomic_t                child_count;
+       unsigned int            disable_depth:3;
+       unsigned int            ignore_children:1;
+       unsigned int            idle_notification:1;
+       unsigned int            request_pending:1;
+       unsigned int            deferred_resume:1;
+       enum rpm_request        request;
+       enum rpm_status         runtime_status;
+       int                     runtime_error;
+#endif
 };
 
 /*
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
new file mode 100644 (file)
index 0000000..4408704
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * pm_runtime.h - Device run-time power management helper functions.
+ *
+ * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>
+ *
+ * This file is released under the GPLv2.
+ */
+
+#ifndef _LINUX_PM_RUNTIME_H
+#define _LINUX_PM_RUNTIME_H
+
+#include <linux/device.h>
+#include <linux/pm.h>
+
+#ifdef CONFIG_PM_RUNTIME
+
+extern struct workqueue_struct *pm_wq;
+
+extern int pm_runtime_idle(struct device *dev);
+extern int pm_runtime_suspend(struct device *dev);
+extern int pm_runtime_resume(struct device *dev);
+extern int pm_request_idle(struct device *dev);
+extern int pm_schedule_suspend(struct device *dev, unsigned int delay);
+extern int pm_request_resume(struct device *dev);
+extern int __pm_runtime_get(struct device *dev, bool sync);
+extern int __pm_runtime_put(struct device *dev, bool sync);
+extern int __pm_runtime_set_status(struct device *dev, unsigned int status);
+extern int pm_runtime_barrier(struct device *dev);
+extern void pm_runtime_enable(struct device *dev);
+extern void __pm_runtime_disable(struct device *dev, bool check_resume);
+
+static inline bool pm_children_suspended(struct device *dev)
+{
+       return dev->power.ignore_children
+               || !atomic_read(&dev->power.child_count);
+}
+
+static inline void pm_suspend_ignore_children(struct device *dev, bool enable)
+{
+       dev->power.ignore_children = enable;
+}
+
+static inline void pm_runtime_get_noresume(struct device *dev)
+{
+       atomic_inc(&dev->power.usage_count);
+}
+
+static inline void pm_runtime_put_noidle(struct device *dev)
+{
+       atomic_add_unless(&dev->power.usage_count, -1, 0);
+}
+
+#else /* !CONFIG_PM_RUNTIME */
+
+static inline int pm_runtime_idle(struct device *dev) { return -ENOSYS; }
+static inline int pm_runtime_suspend(struct device *dev) { return -ENOSYS; }
+static inline int pm_runtime_resume(struct device *dev) { return 0; }
+static inline int pm_request_idle(struct device *dev) { return -ENOSYS; }
+static inline int pm_schedule_suspend(struct device *dev, unsigned int delay)
+{
+       return -ENOSYS;
+}
+static inline int pm_request_resume(struct device *dev) { return 0; }
+static inline int __pm_runtime_get(struct device *dev, bool sync) { return 1; }
+static inline int __pm_runtime_put(struct device *dev, bool sync) { return 0; }
+static inline int __pm_runtime_set_status(struct device *dev,
+                                           unsigned int status) { return 0; }
+static inline int pm_runtime_barrier(struct device *dev) { return 0; }
+static inline void pm_runtime_enable(struct device *dev) {}
+static inline void __pm_runtime_disable(struct device *dev, bool c) {}
+
+static inline bool pm_children_suspended(struct device *dev) { return false; }
+static inline void pm_suspend_ignore_children(struct device *dev, bool en) {}
+static inline void pm_runtime_get_noresume(struct device *dev) {}
+static inline void pm_runtime_put_noidle(struct device *dev) {}
+
+#endif /* !CONFIG_PM_RUNTIME */
+
+static inline int pm_runtime_get(struct device *dev)
+{
+       return __pm_runtime_get(dev, false);
+}
+
+static inline int pm_runtime_get_sync(struct device *dev)
+{
+       return __pm_runtime_get(dev, true);
+}
+
+static inline int pm_runtime_put(struct device *dev)
+{
+       return __pm_runtime_put(dev, false);
+}
+
+static inline int pm_runtime_put_sync(struct device *dev)
+{
+       return __pm_runtime_put(dev, true);
+}
+
+static inline int pm_runtime_set_active(struct device *dev)
+{
+       return __pm_runtime_set_status(dev, RPM_ACTIVE);
+}
+
+static inline void pm_runtime_set_suspended(struct device *dev)
+{
+       __pm_runtime_set_status(dev, RPM_SUSPENDED);
+}
+
+static inline void pm_runtime_disable(struct device *dev)
+{
+       __pm_runtime_disable(dev, true);
+}
+
+#endif
index eb1423a..68e212f 100644 (file)
@@ -85,7 +85,6 @@ struct intc_desc symbol __initdata = {                                        \
 }
 #endif
 
-unsigned int intc_evt2irq(unsigned int vector);
 void __init register_intc_controller(struct intc_desc *desc);
 int intc_set_priority(unsigned int irq, unsigned int prio);
 
diff --git a/include/linux/usb/m66592.h b/include/linux/usb/m66592.h
new file mode 100644 (file)
index 0000000..cda9625
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * M66592 driver platform data
+ *
+ * Copyright (C) 2009  Renesas Solutions Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __LINUX_USB_M66592_H
+#define __LINUX_USB_M66592_H
+
+#define M66592_PLATDATA_XTAL_12MHZ     0x01
+#define M66592_PLATDATA_XTAL_24MHZ     0x02
+#define M66592_PLATDATA_XTAL_48MHZ     0x03
+
+struct m66592_platdata {
+       /* one = on chip controller, zero = external controller */
+       unsigned        on_chip:1;
+
+       /* one = big endian, zero = little endian */
+       unsigned        endian:1;
+
+       /* (external controller only) M66592_PLATDATA_XTAL_nnMHZ */
+       unsigned        xtal:2;
+
+       /* (external controller only) one = 3.3V, zero = 1.5V */
+       unsigned        vif:1;
+
+};
+
+#endif /* __LINUX_USB_M66592_H */
+
index e9f0384..26d2167 100644 (file)
 #define R8A66597_PLATDATA_XTAL_48MHZ   0x03
 
 struct r8a66597_platdata {
-       /* This ops can controll port power instead of DVSTCTR register. */
+       /* This callback can control port power instead of DVSTCTR register. */
        void (*port_power)(int port, int power);
 
+       /* set one = on chip controller, set zero = external controller */
+       unsigned        on_chip:1;
+
        /* (external controller only) set R8A66597_PLATDATA_XTAL_nnMHZ */
        unsigned        xtal:2;
 
@@ -40,5 +43,373 @@ struct r8a66597_platdata {
        /* set one = big endian, set zero = little endian */
        unsigned        endian:1;
 };
-#endif
+
+/* Register definitions */
+#define SYSCFG0                0x00
+#define SYSCFG1                0x02
+#define SYSSTS0                0x04
+#define SYSSTS1                0x06
+#define DVSTCTR0       0x08
+#define DVSTCTR1       0x0A
+#define TESTMODE       0x0C
+#define PINCFG         0x0E
+#define DMA0CFG                0x10
+#define DMA1CFG                0x12
+#define CFIFO          0x14
+#define D0FIFO         0x18
+#define D1FIFO         0x1C
+#define CFIFOSEL       0x20
+#define CFIFOCTR       0x22
+#define CFIFOSIE       0x24
+#define D0FIFOSEL      0x28
+#define D0FIFOCTR      0x2A
+#define D1FIFOSEL      0x2C
+#define D1FIFOCTR      0x2E
+#define INTENB0                0x30
+#define INTENB1                0x32
+#define INTENB2                0x34
+#define BRDYENB                0x36
+#define NRDYENB                0x38
+#define BEMPENB                0x3A
+#define SOFCFG         0x3C
+#define INTSTS0                0x40
+#define INTSTS1                0x42
+#define INTSTS2                0x44
+#define BRDYSTS                0x46
+#define NRDYSTS                0x48
+#define BEMPSTS                0x4A
+#define FRMNUM         0x4C
+#define UFRMNUM                0x4E
+#define USBADDR                0x50
+#define USBREQ         0x54
+#define USBVAL         0x56
+#define USBINDX                0x58
+#define USBLENG                0x5A
+#define DCPCFG         0x5C
+#define DCPMAXP                0x5E
+#define DCPCTR         0x60
+#define PIPESEL                0x64
+#define PIPECFG                0x68
+#define PIPEBUF                0x6A
+#define PIPEMAXP       0x6C
+#define PIPEPERI       0x6E
+#define PIPE1CTR       0x70
+#define PIPE2CTR       0x72
+#define PIPE3CTR       0x74
+#define PIPE4CTR       0x76
+#define PIPE5CTR       0x78
+#define PIPE6CTR       0x7A
+#define PIPE7CTR       0x7C
+#define PIPE8CTR       0x7E
+#define PIPE9CTR       0x80
+#define PIPE1TRE       0x90
+#define PIPE1TRN       0x92
+#define PIPE2TRE       0x94
+#define PIPE2TRN       0x96
+#define PIPE3TRE       0x98
+#define PIPE3TRN       0x9A
+#define PIPE4TRE       0x9C
+#define        PIPE4TRN        0x9E
+#define        PIPE5TRE        0xA0
+#define        PIPE5TRN        0xA2
+#define DEVADD0                0xD0
+#define DEVADD1                0xD2
+#define DEVADD2                0xD4
+#define DEVADD3                0xD6
+#define DEVADD4                0xD8
+#define DEVADD5                0xDA
+#define DEVADD6                0xDC
+#define DEVADD7                0xDE
+#define DEVADD8                0xE0
+#define DEVADD9                0xE2
+#define DEVADDA                0xE4
+
+/* System Configuration Control Register */
+#define        XTAL            0xC000  /* b15-14: Crystal selection */
+#define          XTAL48         0x8000   /* 48MHz */
+#define          XTAL24         0x4000   /* 24MHz */
+#define          XTAL12         0x0000   /* 12MHz */
+#define        XCKE            0x2000  /* b13: External clock enable */
+#define        PLLC            0x0800  /* b11: PLL control */
+#define        SCKE            0x0400  /* b10: USB clock enable */
+#define        PCSDIS          0x0200  /* b9: not CS wakeup */
+#define        LPSME           0x0100  /* b8: Low power sleep mode */
+#define        HSE             0x0080  /* b7: Hi-speed enable */
+#define        DCFM            0x0040  /* b6: Controller function select  */
+#define        DRPD            0x0020  /* b5: D+/- pull down control */
+#define        DPRPU           0x0010  /* b4: D+ pull up control */
+#define        USBE            0x0001  /* b0: USB module operation enable */
+
+/* System Configuration Status Register */
+#define        OVCBIT          0x8000  /* b15-14: Over-current bit */
+#define        OVCMON          0xC000  /* b15-14: Over-current monitor */
+#define        SOFEA           0x0020  /* b5: SOF monitor */
+#define        IDMON           0x0004  /* b3: ID-pin monitor */
+#define        LNST            0x0003  /* b1-0: D+, D- line status */
+#define          SE1            0x0003   /* SE1 */
+#define          FS_KSTS        0x0002   /* Full-Speed K State */
+#define          FS_JSTS        0x0001   /* Full-Speed J State */
+#define          LS_JSTS        0x0002   /* Low-Speed J State */
+#define          LS_KSTS        0x0001   /* Low-Speed K State */
+#define          SE0            0x0000   /* SE0 */
+
+/* Device State Control Register */
+#define        EXTLP0          0x0400  /* b10: External port */
+#define        VBOUT           0x0200  /* b9: VBUS output */
+#define        WKUP            0x0100  /* b8: Remote wakeup */
+#define        RWUPE           0x0080  /* b7: Remote wakeup sense */
+#define        USBRST          0x0040  /* b6: USB reset enable */
+#define        RESUME          0x0020  /* b5: Resume enable */
+#define        UACT            0x0010  /* b4: USB bus enable */
+#define        RHST            0x0007  /* b1-0: Reset handshake status */
+#define          HSPROC         0x0004   /* HS handshake is processing */
+#define          HSMODE         0x0003   /* Hi-Speed mode */
+#define          FSMODE         0x0002   /* Full-Speed mode */
+#define          LSMODE         0x0001   /* Low-Speed mode */
+#define          UNDECID        0x0000   /* Undecided */
+
+/* Test Mode Register */
+#define        UTST                    0x000F  /* b3-0: Test select */
+#define          H_TST_PACKET           0x000C   /* HOST TEST Packet */
+#define          H_TST_SE0_NAK          0x000B   /* HOST TEST SE0 NAK */
+#define          H_TST_K                0x000A   /* HOST TEST K */
+#define          H_TST_J                0x0009   /* HOST TEST J */
+#define          H_TST_NORMAL           0x0000   /* HOST Normal Mode */
+#define          P_TST_PACKET           0x0004   /* PERI TEST Packet */
+#define          P_TST_SE0_NAK          0x0003   /* PERI TEST SE0 NAK */
+#define          P_TST_K                0x0002   /* PERI TEST K */
+#define          P_TST_J                0x0001   /* PERI TEST J */
+#define          P_TST_NORMAL           0x0000   /* PERI Normal Mode */
+
+/* Data Pin Configuration Register */
+#define        LDRV                    0x8000  /* b15: Drive Current Adjust */
+#define          VIF1                    0x0000                /* VIF = 1.8V */
+#define          VIF3                    0x8000                /* VIF = 3.3V */
+#define        INTA                    0x0001  /* b1: USB INT-pin active */
+
+/* DMAx Pin Configuration Register */
+#define        DREQA                   0x4000  /* b14: Dreq active select */
+#define        BURST                   0x2000  /* b13: Burst mode */
+#define        DACKA                   0x0400  /* b10: Dack active select */
+#define        DFORM                   0x0380  /* b9-7: DMA mode select */
+#define          CPU_ADR_RD_WR          0x0000   /* Address + RD/WR mode (CPU bus) */
+#define          CPU_DACK_RD_WR         0x0100   /* DACK + RD/WR mode (CPU bus) */
+#define          CPU_DACK_ONLY          0x0180   /* DACK only mode (CPU bus) */
+#define          SPLIT_DACK_ONLY        0x0200   /* DACK only mode (SPLIT bus) */
+#define        DENDA                   0x0040  /* b6: Dend active select */
+#define        PKTM                    0x0020  /* b5: Packet mode */
+#define        DENDE                   0x0010  /* b4: Dend enable */
+#define        OBUS                    0x0004  /* b2: OUTbus mode */
+
+/* CFIFO/DxFIFO Port Select Register */
+#define        RCNT            0x8000  /* b15: Read count mode */
+#define        REW             0x4000  /* b14: Buffer rewind */
+#define        DCLRM           0x2000  /* b13: DMA buffer clear mode */
+#define        DREQE           0x1000  /* b12: DREQ output enable */
+#define          MBW_8          0x0000   /*  8bit */
+#define          MBW_16         0x0400   /* 16bit */
+#define          MBW_32         0x0800   /* 32bit */
+#define        BIGEND          0x0100  /* b8: Big endian mode */
+#define          BYTE_LITTLE    0x0000         /* little dendian */
+#define          BYTE_BIG       0x0100         /* big endifan */
+#define        ISEL            0x0020  /* b5: DCP FIFO port direction select */
+#define        CURPIPE         0x000F  /* b2-0: PIPE select */
+
+/* CFIFO/DxFIFO Port Control Register */
+#define        BVAL            0x8000  /* b15: Buffer valid flag */
+#define        BCLR            0x4000  /* b14: Buffer clear */
+#define        FRDY            0x2000  /* b13: FIFO ready */
+#define        DTLN            0x0FFF  /* b11-0: FIFO received data length */
+
+/* Interrupt Enable Register 0 */
+#define        VBSE    0x8000  /* b15: VBUS interrupt */
+#define        RSME    0x4000  /* b14: Resume interrupt */
+#define        SOFE    0x2000  /* b13: Frame update interrupt */
+#define        DVSE    0x1000  /* b12: Device state transition interrupt */
+#define        CTRE    0x0800  /* b11: Control transfer stage transition interrupt */
+#define        BEMPE   0x0400  /* b10: Buffer empty interrupt */
+#define        NRDYE   0x0200  /* b9: Buffer not ready interrupt */
+#define        BRDYE   0x0100  /* b8: Buffer ready interrupt */
+
+/* Interrupt Enable Register 1 */
+#define        OVRCRE          0x8000  /* b15: Over-current interrupt */
+#define        BCHGE           0x4000  /* b14: USB us chenge interrupt */
+#define        DTCHE           0x1000  /* b12: Detach sense interrupt */
+#define        ATTCHE          0x0800  /* b11: Attach sense interrupt */
+#define        EOFERRE         0x0040  /* b6: EOF error interrupt */
+#define        SIGNE           0x0020  /* b5: SETUP IGNORE interrupt */
+#define        SACKE           0x0010  /* b4: SETUP ACK interrupt */
+
+/* BRDY Interrupt Enable/Status Register */
+#define        BRDY9           0x0200  /* b9: PIPE9 */
+#define        BRDY8           0x0100  /* b8: PIPE8 */
+#define        BRDY7           0x0080  /* b7: PIPE7 */
+#define        BRDY6           0x0040  /* b6: PIPE6 */
+#define        BRDY5           0x0020  /* b5: PIPE5 */
+#define        BRDY4           0x0010  /* b4: PIPE4 */
+#define        BRDY3           0x0008  /* b3: PIPE3 */
+#define        BRDY2           0x0004  /* b2: PIPE2 */
+#define        BRDY1           0x0002  /* b1: PIPE1 */
+#define        BRDY0           0x0001  /* b1: PIPE0 */
+
+/* NRDY Interrupt Enable/Status Register */
+#define        NRDY9           0x0200  /* b9: PIPE9 */
+#define        NRDY8           0x0100  /* b8: PIPE8 */
+#define        NRDY7           0x0080  /* b7: PIPE7 */
+#define        NRDY6           0x0040  /* b6: PIPE6 */
+#define        NRDY5           0x0020  /* b5: PIPE5 */
+#define        NRDY4           0x0010  /* b4: PIPE4 */
+#define        NRDY3           0x0008  /* b3: PIPE3 */
+#define        NRDY2           0x0004  /* b2: PIPE2 */
+#define        NRDY1           0x0002  /* b1: PIPE1 */
+#define        NRDY0           0x0001  /* b1: PIPE0 */
+
+/* BEMP Interrupt Enable/Status Register */
+#define        BEMP9           0x0200  /* b9: PIPE9 */
+#define        BEMP8           0x0100  /* b8: PIPE8 */
+#define        BEMP7           0x0080  /* b7: PIPE7 */
+#define        BEMP6           0x0040  /* b6: PIPE6 */
+#define        BEMP5           0x0020  /* b5: PIPE5 */
+#define        BEMP4           0x0010  /* b4: PIPE4 */
+#define        BEMP3           0x0008  /* b3: PIPE3 */
+#define        BEMP2           0x0004  /* b2: PIPE2 */
+#define        BEMP1           0x0002  /* b1: PIPE1 */
+#define        BEMP0           0x0001  /* b0: PIPE0 */
+
+/* SOF Pin Configuration Register */
+#define        TRNENSEL        0x0100  /* b8: Select transaction enable period */
+#define        BRDYM           0x0040  /* b6: BRDY clear timing */
+#define        INTL            0x0020  /* b5: Interrupt sense select */
+#define        EDGESTS         0x0010  /* b4:  */
+#define        SOFMODE         0x000C  /* b3-2: SOF pin select */
+#define          SOF_125US      0x0008   /* SOF OUT 125us Frame Signal */
+#define          SOF_1MS        0x0004   /* SOF OUT 1ms Frame Signal */
+#define          SOF_DISABLE    0x0000   /* SOF OUT Disable */
+
+/* Interrupt Status Register 0 */
+#define        VBINT   0x8000  /* b15: VBUS interrupt */
+#define        RESM    0x4000  /* b14: Resume interrupt */
+#define        SOFR    0x2000  /* b13: SOF frame update interrupt */
+#define        DVST    0x1000  /* b12: Device state transition interrupt */
+#define        CTRT    0x0800  /* b11: Control transfer stage transition interrupt */
+#define        BEMP    0x0400  /* b10: Buffer empty interrupt */
+#define        NRDY    0x0200  /* b9: Buffer not ready interrupt */
+#define        BRDY    0x0100  /* b8: Buffer ready interrupt */
+#define        VBSTS   0x0080  /* b7: VBUS input port */
+#define        DVSQ    0x0070  /* b6-4: Device state */
+#define          DS_SPD_CNFG    0x0070   /* Suspend Configured */
+#define          DS_SPD_ADDR    0x0060   /* Suspend Address */
+#define          DS_SPD_DFLT    0x0050   /* Suspend Default */
+#define          DS_SPD_POWR    0x0040   /* Suspend Powered */
+#define          DS_SUSP        0x0040   /* Suspend */
+#define          DS_CNFG        0x0030   /* Configured */
+#define          DS_ADDS        0x0020   /* Address */
+#define          DS_DFLT        0x0010   /* Default */
+#define          DS_POWR        0x0000   /* Powered */
+#define        DVSQS           0x0030  /* b5-4: Device state */
+#define        VALID           0x0008  /* b3: Setup packet detected flag */
+#define        CTSQ            0x0007  /* b2-0: Control transfer stage */
+#define          CS_SQER        0x0006   /* Sequence error */
+#define          CS_WRND        0x0005   /* Control write nodata status stage */
+#define          CS_WRSS        0x0004   /* Control write status stage */
+#define          CS_WRDS        0x0003   /* Control write data stage */
+#define          CS_RDSS        0x0002   /* Control read status stage */
+#define          CS_RDDS        0x0001   /* Control read data stage */
+#define          CS_IDST        0x0000   /* Idle or setup stage */
+
+/* Interrupt Status Register 1 */
+#define        OVRCR           0x8000  /* b15: Over-current interrupt */
+#define        BCHG            0x4000  /* b14: USB bus chenge interrupt */
+#define        DTCH            0x1000  /* b12: Detach sense interrupt */
+#define        ATTCH           0x0800  /* b11: Attach sense interrupt */
+#define        EOFERR          0x0040  /* b6: EOF-error interrupt */
+#define        SIGN            0x0020  /* b5: Setup ignore interrupt */
+#define        SACK            0x0010  /* b4: Setup acknowledge interrupt */
+
+/* Frame Number Register */
+#define        OVRN            0x8000  /* b15: Overrun error */
+#define        CRCE            0x4000  /* b14: Received data error */
+#define        FRNM            0x07FF  /* b10-0: Frame number */
+
+/* Micro Frame Number Register */
+#define        UFRNM           0x0007  /* b2-0: Micro frame number */
+
+/* Default Control Pipe Maxpacket Size Register */
+/* Pipe Maxpacket Size Register */
+#define        DEVSEL  0xF000  /* b15-14: Device address select */
+#define        MAXP    0x007F  /* b6-0: Maxpacket size of default control pipe */
+
+/* Default Control Pipe Control Register */
+#define        BSTS            0x8000  /* b15: Buffer status */
+#define        SUREQ           0x4000  /* b14: Send USB request  */
+#define        CSCLR           0x2000  /* b13: complete-split status clear */
+#define        CSSTS           0x1000  /* b12: complete-split status */
+#define        SUREQCLR        0x0800  /* b11: stop setup request */
+#define        SQCLR           0x0100  /* b8: Sequence toggle bit clear */
+#define        SQSET           0x0080  /* b7: Sequence toggle bit set */
+#define        SQMON           0x0040  /* b6: Sequence toggle bit monitor */
+#define        PBUSY           0x0020  /* b5: pipe busy */
+#define        PINGE           0x0010  /* b4: ping enable */
+#define        CCPL            0x0004  /* b2: Enable control transfer complete */
+#define        PID             0x0003  /* b1-0: Response PID */
+#define          PID_STALL11    0x0003   /* STALL */
+#define          PID_STALL      0x0002   /* STALL */
+#define          PID_BUF        0x0001   /* BUF */
+#define          PID_NAK        0x0000   /* NAK */
+
+/* Pipe Window Select Register */
+#define        PIPENM          0x0007  /* b2-0: Pipe select */
+
+/* Pipe Configuration Register */
+#define        R8A66597_TYP    0xC000  /* b15-14: Transfer type */
+#define          R8A66597_ISO   0xC000           /* Isochronous */
+#define          R8A66597_INT   0x8000           /* Interrupt */
+#define          R8A66597_BULK  0x4000           /* Bulk */
+#define        R8A66597_BFRE   0x0400  /* b10: Buffer ready interrupt mode select */
+#define        R8A66597_DBLB   0x0200  /* b9: Double buffer mode select */
+#define        R8A66597_CNTMD  0x0100  /* b8: Continuous transfer mode select */
+#define        R8A66597_SHTNAK 0x0080  /* b7: Transfer end NAK */
+#define        R8A66597_DIR    0x0010  /* b4: Transfer direction select */
+#define        R8A66597_EPNUM  0x000F  /* b3-0: Eendpoint number select */
+
+/* Pipe Buffer Configuration Register */
+#define        BUFSIZE         0x7C00  /* b14-10: Pipe buffer size */
+#define        BUFNMB          0x007F  /* b6-0: Pipe buffer number */
+#define        PIPE0BUF        256
+#define        PIPExBUF        64
+
+/* Pipe Maxpacket Size Register */
+#define        MXPS            0x07FF  /* b10-0: Maxpacket size */
+
+/* Pipe Cycle Configuration Register */
+#define        IFIS    0x1000  /* b12: Isochronous in-buffer flush mode select */
+#define        IITV    0x0007  /* b2-0: Isochronous interval */
+
+/* Pipex Control Register */
+#define        BSTS    0x8000  /* b15: Buffer status */
+#define        INBUFM  0x4000  /* b14: IN buffer monitor (Only for PIPE1 to 5) */
+#define        CSCLR   0x2000  /* b13: complete-split status clear */
+#define        CSSTS   0x1000  /* b12: complete-split status */
+#define        ATREPM  0x0400  /* b10: Auto repeat mode */
+#define        ACLRM   0x0200  /* b9: Out buffer auto clear mode */
+#define        SQCLR   0x0100  /* b8: Sequence toggle bit clear */
+#define        SQSET   0x0080  /* b7: Sequence toggle bit set */
+#define        SQMON   0x0040  /* b6: Sequence toggle bit monitor */
+#define        PBUSY   0x0020  /* b5: pipe busy */
+#define        PID     0x0003  /* b1-0: Response PID */
+
+/* PIPExTRE */
+#define        TRENB           0x0200  /* b9: Transaction counter enable */
+#define        TRCLR           0x0100  /* b8: Transaction counter clear */
+
+/* PIPExTRN */
+#define        TRNCNT          0xFFFF  /* b15-0: Transaction counter */
+
+/* DEVADDx */
+#define        UPPHUB          0x7800
+#define        HUBPORT         0x0700
+#define        USBSPD          0x00C0
+#define        RTPORT          0x0001
+
+#endif /* __LINUX_USB_R8A66597_H */
 
index 72067cb..91e09d3 100644 (file)
@@ -208,3 +208,17 @@ config APM_EMULATION
          random kernel OOPSes or reboots that don't seem to be related to
          anything, try disabling/enabling this option (or disabling/enabling
          APM in your BIOS).
+
+config PM_RUNTIME
+       bool "Run-time PM core functionality"
+       depends on PM
+       ---help---
+         Enable functionality allowing I/O devices to be put into energy-saving
+         (low power) states at run time (or autosuspended) after a specified
+         period of inactivity and woken up in response to a hardware-generated
+         wake-up event or a driver's request.
+
+         Hardware support is generally required for this functionality to work
+         and the bus type drivers of the buses the devices are on are
+         responsible for the actual handling of the autosuspend requests and
+         wake-up events.
index f710e36..347d2cc 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kobject.h>
 #include <linux/string.h>
 #include <linux/resume-trace.h>
+#include <linux/workqueue.h>
 
 #include "power.h"
 
@@ -217,8 +218,24 @@ static struct attribute_group attr_group = {
        .attrs = g,
 };
 
+#ifdef CONFIG_PM_RUNTIME
+struct workqueue_struct *pm_wq;
+
+static int __init pm_start_workqueue(void)
+{
+       pm_wq = create_freezeable_workqueue("pm");
+
+       return pm_wq ? 0 : -ENOMEM;
+}
+#else
+static inline int pm_start_workqueue(void) { return 0; }
+#endif
+
 static int __init pm_init(void)
 {
+       int error = pm_start_workqueue();
+       if (error)
+               return error;
        power_kobj = kobject_create_and_add("power", NULL);
        if (!power_kobj)
                return -ENOMEM;