* Re: [PATCH] ARM: Kota2 mach-type update fix
From: Rafael J. Wysocki @ 2011-12-01 9:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111122060857.23951.50598.sendpatchset@w520>
On Tuesday, November 22, 2011, Magnus Damm wrote:
> From: Magnus Damm <damm@opensource.se>
>
> This patch adds kota2 to the in-kernel ARM mach-type file.
>
> Basic board support is included in 3.2-rc and the mach-type
> has been registered in the ARM machine repository as
>
> 3616 Renesas SH-Mobile kota2.x Board kota2 Yusuke Goda mainlined
>
> The file arch/arm/tools/mach-types is however missing Kota2
> which makes build of sh73a0 based boards fail with:
>
> arch/arm/mach-shmobile/platsmp.c: In function 'shmobile_smp_get_core_count':
> arch/arm/mach-shmobile/platsmp.c:28:2: error: implicit declaration of function 'machine_is_kota2'
> make[1]: *** [arch/arm/mach-shmobile/platsmp.o] Error 1
>
> arch/arm/mach-shmobile/board-kota2.c:448:136: error: 'MACH_TYPE_KOTA2' undeclared here (not in a function)
> make[1]: *** [arch/arm/mach-shmobile/board-kota2.o] Error 1
> make: *** [arch/arm/mach-shmobile] Error 2
>
> Signed-off-by: Magnus Damm <damm@opensource.se>
This patch is necessary to fix build of the Linus' tree for me with both
CONFIG_ARCH_SH73A0 and CONFIG_SMP set.
Tested-by: Rafael J. Wysocki <rjw@sisk.pl>
Thanks,
Rafael
> ---
>
> I propose that Paul Mundt merges this patch together with other
> SH-Mobile ARM related fixes.
>
> arch/arm/tools/mach-types | 1 +
> 1 file changed, 1 insertion(+)
>
> --- 0001/arch/arm/tools/mach-types
> +++ work/arch/arm/tools/mach-types 2011-11-14 16:55:38.000000000 +0900
> @@ -1123,5 +1123,6 @@ blissc MACH_BLISSC BLISSC 3491
> thales_adc MACH_THALES_ADC THALES_ADC 3492
> ubisys_p9d_evp MACH_UBISYS_P9D_EVP UBISYS_P9D_EVP 3493
> atdgp318 MACH_ATDGP318 ATDGP318 3494
> +kota2 MACH_KOTA2 KOTA2 3616
> smdk4212 MACH_SMDK4212 SMDK4212 3638
> smdk4412 MACH_SMDK4412 SMDK4412 3765
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
^ permalink raw reply
* [Update 3x][PATCH 4/7] PM / Runtime: Use device PM QoS constraints (v2)
From: Rafael J. Wysocki @ 2011-11-30 23:20 UTC (permalink / raw)
To: Linux PM list
Cc: LKML, Linux-sh list, Magnus Damm, Guennadi Liakhovetski,
Kevin Hilman, jean.pihet
In-Reply-To: <201111191500.34517.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
Make the runtime PM core use device PM QoS constraints to check if
it is allowed to suspend a given device, so that an error code is
returned if the device's own PM QoS constraint is negative or one of
its children has already been suspended for too long. If this is
not the case, the maximum estimated time the device is allowed to be
suspended, computed as the minimum of the device's PM QoS constraint
and the PM QoS constraints of its children (reduced by the difference
between the current time and their suspend times) is stored in a new
device's PM field power.max_time_suspended_ns that can be used by
the device's subsystem or PM domain to decide whether or not to put
the device into lower-power (and presumably higher-latency) states
later (if the constraint is 0, which means "no constraint", the
power.max_time_suspended_ns is set to -1).
Additionally, the time of execution of the subsystem-level
.runtime_suspend() callback for the device is recorded in the new
power.suspend_time field for later use by the device's subsystem or
PM domain along with power.max_time_suspended_ns (it also is used
by the core code when the device's parent is suspended).
Introduce a new helper function,
pm_runtime_update_max_time_suspended(), allowing subsystems and PM
domains (or device drivers) to update the power.max_time_suspended_ns
field, for example after changing the power state of a suspended
device.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
Hi,
I had to rework the patch so that device_for_each_child() was not
run under dev->power.lock, which caused lockdep to complain loudly.
Thanks,
Rafael
---
drivers/base/power/qos.c | 24 ++++--
drivers/base/power/runtime.c | 148 +++++++++++++++++++++++++++++++++++++------
include/linux/pm.h | 2
include/linux/pm_qos.h | 3
include/linux/pm_runtime.h | 5 +
5 files changed, 154 insertions(+), 28 deletions(-)
Index: linux/include/linux/pm.h
=================================--- linux.orig/include/linux/pm.h
+++ linux/include/linux/pm.h
@@ -521,6 +521,8 @@ struct dev_pm_info {
unsigned long active_jiffies;
unsigned long suspended_jiffies;
unsigned long accounting_timestamp;
+ ktime_t suspend_time;
+ s64 max_time_suspended_ns;
#endif
struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */
struct pm_qos_constraints *constraints;
Index: linux/drivers/base/power/runtime.c
=================================--- linux.orig/drivers/base/power/runtime.c
+++ linux/drivers/base/power/runtime.c
@@ -279,6 +279,47 @@ static int rpm_callback(int (*cb)(struct
return retval != -EACCES ? retval : -EIO;
}
+struct rpm_qos_data {
+ ktime_t time_now;
+ s64 constraint_ns;
+};
+
+/**
+ * rpm_update_qos_constraint - Update a given PM QoS constraint data.
+ * @dev: Device whose timing data to use.
+ * @data: PM QoS constraint data to update.
+ *
+ * Use the suspend timing data of @dev to update PM QoS constraint data pointed
+ * to by @data.
+ */
+static int rpm_update_qos_constraint(struct device *dev, void *data)
+{
+ struct rpm_qos_data *qos = data;
+ unsigned long flags;
+ s64 delta_ns;
+ int ret = 0;
+
+ spin_lock_irqsave(&dev->power.lock, flags);
+
+ if (dev->power.max_time_suspended_ns < 0)
+ goto out;
+
+ delta_ns = dev->power.max_time_suspended_ns -
+ ktime_to_ns(ktime_sub(qos->time_now, dev->power.suspend_time));
+ if (delta_ns <= 0) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (qos->constraint_ns > delta_ns || qos->constraint_ns = 0)
+ qos->constraint_ns = delta_ns;
+
+ out:
+ spin_unlock_irqrestore(&dev->power.lock, flags);
+
+ return ret;
+}
+
/**
* rpm_suspend - Carry out runtime suspend of given device.
* @dev: Device to suspend.
@@ -305,6 +346,7 @@ static int rpm_suspend(struct device *de
{
int (*callback)(struct device *);
struct device *parent = NULL;
+ struct rpm_qos_data qos;
int retval;
trace_rpm_suspend(dev, rpmflags);
@@ -400,8 +442,38 @@ static int rpm_suspend(struct device *de
goto out;
}
+ qos.constraint_ns = __dev_pm_qos_read_value(dev);
+ if (qos.constraint_ns < 0) {
+ /* Negative constraint means "never suspend". */
+ retval = -EPERM;
+ goto out;
+ }
+ qos.constraint_ns *= NSEC_PER_USEC;
+ qos.time_now = ktime_get();
+
__update_runtime_status(dev, RPM_SUSPENDING);
+ if (!dev->power.ignore_children) {
+ if (dev->power.irq_safe)
+ spin_unlock(&dev->power.lock);
+ else
+ spin_unlock_irq(&dev->power.lock);
+
+ retval = device_for_each_child(dev, &qos,
+ rpm_update_qos_constraint);
+
+ if (dev->power.irq_safe)
+ spin_lock(&dev->power.lock);
+ else
+ spin_lock_irq(&dev->power.lock);
+
+ if (retval)
+ goto fail;
+ }
+
+ dev->power.suspend_time = qos.time_now;
+ dev->power.max_time_suspended_ns = qos.constraint_ns ? : -1;
+
if (dev->pm_domain)
callback = dev->pm_domain->ops.runtime_suspend;
else if (dev->type && dev->type->pm)
@@ -414,27 +486,9 @@ static int rpm_suspend(struct device *de
callback = NULL;
retval = rpm_callback(callback, dev);
- if (retval) {
- __update_runtime_status(dev, RPM_ACTIVE);
- dev->power.deferred_resume = false;
- if (retval = -EAGAIN || retval = -EBUSY) {
- dev->power.runtime_error = 0;
+ if (retval)
+ goto fail;
- /*
- * If the callback routine failed an autosuspend, and
- * if the last_busy time has been updated so that there
- * is a new autosuspend expiration time, automatically
- * reschedule another autosuspend.
- */
- if ((rpmflags & RPM_AUTO) &&
- pm_runtime_autosuspend_expiration(dev) != 0)
- goto repeat;
- } else {
- pm_runtime_cancel_pending(dev);
- }
- wake_up_all(&dev->power.wait_queue);
- goto out;
- }
no_callback:
__update_runtime_status(dev, RPM_SUSPENDED);
pm_runtime_deactivate_timer(dev);
@@ -466,6 +520,29 @@ static int rpm_suspend(struct device *de
trace_rpm_return_int(dev, _THIS_IP_, retval);
return retval;
+
+ fail:
+ __update_runtime_status(dev, RPM_ACTIVE);
+ dev->power.suspend_time = ktime_set(0, 0);
+ dev->power.max_time_suspended_ns = -1;
+ dev->power.deferred_resume = false;
+ if (retval = -EAGAIN || retval = -EBUSY) {
+ dev->power.runtime_error = 0;
+
+ /*
+ * If the callback routine failed an autosuspend, and
+ * if the last_busy time has been updated so that there
+ * is a new autosuspend expiration time, automatically
+ * reschedule another autosuspend.
+ */
+ if ((rpmflags & RPM_AUTO) &&
+ pm_runtime_autosuspend_expiration(dev) != 0)
+ goto repeat;
+ } else {
+ pm_runtime_cancel_pending(dev);
+ }
+ wake_up_all(&dev->power.wait_queue);
+ goto out;
}
/**
@@ -620,6 +697,9 @@ static int rpm_resume(struct device *dev
if (dev->power.no_callbacks)
goto no_callback; /* Assume success. */
+ dev->power.suspend_time = ktime_set(0, 0);
+ dev->power.max_time_suspended_ns = -1;
+
__update_runtime_status(dev, RPM_RESUMING);
if (dev->pm_domain)
@@ -1279,6 +1359,9 @@ void pm_runtime_init(struct device *dev)
setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn,
(unsigned long)dev);
+ dev->power.suspend_time = ktime_set(0, 0);
+ dev->power.max_time_suspended_ns = -1;
+
init_waitqueue_head(&dev->power.wait_queue);
}
@@ -1296,3 +1379,28 @@ void pm_runtime_remove(struct device *de
if (dev->power.irq_safe && dev->parent)
pm_runtime_put_sync(dev->parent);
}
+
+/**
+ * pm_runtime_update_max_time_suspended - Update device's suspend time data.
+ * @dev: Device to handle.
+ * @delta_ns: Value to subtract from the device's max_time_suspended_ns field.
+ *
+ * Update the device's power.max_time_suspended_ns field by subtracting
+ * @delta_ns from it. The resulting value of power.max_time_suspended_ns is
+ * never negative.
+ */
+void pm_runtime_update_max_time_suspended(struct device *dev, s64 delta_ns)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->power.lock, flags);
+
+ if (delta_ns > 0 && dev->power.max_time_suspended_ns > 0) {
+ if (dev->power.max_time_suspended_ns > delta_ns)
+ dev->power.max_time_suspended_ns -= delta_ns;
+ else
+ dev->power.max_time_suspended_ns = 0;
+ }
+
+ spin_unlock_irqrestore(&dev->power.lock, flags);
+}
Index: linux/include/linux/pm_runtime.h
=================================--- linux.orig/include/linux/pm_runtime.h
+++ linux/include/linux/pm_runtime.h
@@ -45,6 +45,8 @@ extern void pm_runtime_irq_safe(struct d
extern void __pm_runtime_use_autosuspend(struct device *dev, bool use);
extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
+extern void pm_runtime_update_max_time_suspended(struct device *dev,
+ s64 delta_ns);
static inline bool pm_children_suspended(struct device *dev)
{
@@ -148,6 +150,9 @@ static inline void pm_runtime_set_autosu
static inline unsigned long pm_runtime_autosuspend_expiration(
struct device *dev) { return 0; }
+static inline void pm_runtime_update_max_time_suspended(struct device *dev,
+ s64 delta_ns) {}
+
#endif /* !CONFIG_PM_RUNTIME */
static inline int pm_runtime_idle(struct device *dev)
Index: linux/drivers/base/power/qos.c
=================================--- linux.orig/drivers/base/power/qos.c
+++ linux/drivers/base/power/qos.c
@@ -47,21 +47,29 @@ static DEFINE_MUTEX(dev_pm_qos_mtx);
static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
/**
- * dev_pm_qos_read_value - Get PM QoS constraint for a given device.
+ * __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
+ * @dev: Device to get the PM QoS constraint value for.
+ *
+ * This routine must be called with dev->power.lock held.
+ */
+s32 __dev_pm_qos_read_value(struct device *dev)
+{
+ struct pm_qos_constraints *c = dev->power.constraints;
+
+ return c ? pm_qos_read_value(c) : 0;
+}
+
+/**
+ * dev_pm_qos_read_value - Get PM QoS constraint for a given device (locked).
* @dev: Device to get the PM QoS constraint value for.
*/
s32 dev_pm_qos_read_value(struct device *dev)
{
- struct pm_qos_constraints *c;
unsigned long flags;
- s32 ret = 0;
+ s32 ret;
spin_lock_irqsave(&dev->power.lock, flags);
-
- c = dev->power.constraints;
- if (c)
- ret = pm_qos_read_value(c);
-
+ ret = __dev_pm_qos_read_value(dev);
spin_unlock_irqrestore(&dev->power.lock, flags);
return ret;
Index: linux/include/linux/pm_qos.h
=================================--- linux.orig/include/linux/pm_qos.h
+++ linux/include/linux/pm_qos.h
@@ -78,6 +78,7 @@ int pm_qos_remove_notifier(int pm_qos_cl
int pm_qos_request_active(struct pm_qos_request *req);
s32 pm_qos_read_value(struct pm_qos_constraints *c);
+s32 __dev_pm_qos_read_value(struct device *dev);
s32 dev_pm_qos_read_value(struct device *dev);
int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
s32 value);
@@ -119,6 +120,8 @@ static inline int pm_qos_request_active(
static inline s32 pm_qos_read_value(struct pm_qos_constraints *c)
{ return 0; }
+static inline s32 __dev_pm_qos_read_value(struct device *dev)
+ { return 0; }
static inline s32 dev_pm_qos_read_value(struct device *dev)
{ return 0; }
static inline int dev_pm_qos_add_request(struct device *dev,
^ permalink raw reply
* Re: [PATCH (sh-2.6)] sh: do not export syscalls that are actually not implemented
From: Mike Frysinger @ 2011-11-30 20:56 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <1322685809-15587-1-git-send-email-carmelo.amoroso@st.com>
[-- Attachment #1: Type: Text/Plain, Size: 273 bytes --]
On Wednesday 30 November 2011 15:43:29 Carmelo AMOROSO wrote:
> Avoid user space to erroneously assume that a syscall is implemented
> by picking __NR_xxx from kernel headers that are actually mapped
> to sys_ni_syscall.
Acked-by: Mike Frysinger <vapier@gentoo.org>
-mike
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* [PATCH (sh-2.6)] sh: do not export syscalls that are actually not implemented
From: Carmelo AMOROSO @ 2011-11-30 20:43 UTC (permalink / raw)
To: linux-sh
Avoid user space to erroneously assume that a syscall is implemented
by picking __NR_xxx from kernel headers that are actually mapped
to sys_ni_syscall.
The following interfaces have been removed
sycall | #
---------------------------
__NR_break | 17
__NR_stty | 31
__NR_gtty | 32
__NR_prof | 44
__NR_lock | 53
__NR_mpxi | 56
__NR_ulimit | 58
__NR_oldolduname | 59
__NR_select | 82
__NR_profil | 98
__NR_ioperm | 101
__NR_iopl | 110
__NR_idle | 112
__NR_vm86old | 113
__NR_create_module | 127
__NR_get_kernel_syms | 130
__NR_afs_syscall | 137
__NR_vm86 | 166
__NR_query_module | 167
__NR_streams1 | 188
__NR_streams2 | 189
__NR_set_thread_area | 243
__NR_get_thread_area | 244
__NR_vserver | 273
---------------------------
Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
---
arch/sh/include/asm/unistd_32.h | 53 ++++++++++++++++++++-------------------
1 files changed, 27 insertions(+), 26 deletions(-)
diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h
index 3432008..c7ee965 100644
--- a/arch/sh/include/asm/unistd_32.h
+++ b/arch/sh/include/asm/unistd_32.h
@@ -26,7 +26,7 @@
#define __NR_mknod 14
#define __NR_chmod 15
#define __NR_lchown 16
-#define __NR_break 17
+ /* 17 __NR_break obsolete */
#define __NR_oldstat 18
#define __NR_lseek 19
#define __NR_getpid 20
@@ -40,11 +40,11 @@
#define __NR_oldfstat 28
#define __NR_pause 29
#define __NR_utime 30
-#define __NR_stty 31
-#define __NR_gtty 32
+ /* 31 __NR_stty obsolete */
+ /* 32 __NR_gtty obsolete */
#define __NR_access 33
#define __NR_nice 34
-#define __NR_ftime 35
+ /* 35 __NR_ftime 35 obsolete */
#define __NR_sync 36
#define __NR_kill 37
#define __NR_rename 38
@@ -53,7 +53,7 @@
#define __NR_dup 41
#define __NR_pipe 42
#define __NR_times 43
-#define __NR_prof 44
+ /* 44 __NR_prof obsolete */
#define __NR_brk 45
#define __NR_setgid 46
#define __NR_getgid 47
@@ -62,13 +62,13 @@
#define __NR_getegid 50
#define __NR_acct 51
#define __NR_umount2 52
-#define __NR_lock 53
+ /* 53 __NR_lock obsolete */
#define __NR_ioctl 54
#define __NR_fcntl 55
-#define __NR_mpx 56
+ /* 56 __NR_mpxi obsolete */
#define __NR_setpgid 57
-#define __NR_ulimit 58
-#define __NR_oldolduname 59
+ /* 58 __NR_ulimit obsolete */
+ /* 59 __NR_oldolduname obsolete */
#define __NR_umask 60
#define __NR_chroot 61
#define __NR_ustat 62
@@ -91,7 +91,7 @@
#define __NR_settimeofday 79
#define __NR_getgroups 80
#define __NR_setgroups 81
-#define __NR_select 82
+ /* 82 __NR_select obsolete */
#define __NR_symlink 83
#define __NR_oldlstat 84
#define __NR_readlink 85
@@ -107,10 +107,10 @@
#define __NR_fchown 95
#define __NR_getpriority 96
#define __NR_setpriority 97
-#define __NR_profil 98
+ /* 98 __NR_profil obsolete */
#define __NR_statfs 99
#define __NR_fstatfs 100
-#define __NR_ioperm 101
+ /* 101 __NR_ioperm obsolete */
#define __NR_socketcall 102
#define __NR_syslog 103
#define __NR_setitimer 104
@@ -119,10 +119,10 @@
#define __NR_lstat 107
#define __NR_fstat 108
#define __NR_olduname 109
-#define __NR_iopl 110
+ /* 110 __NR_iopl obsolete */
#define __NR_vhangup 111
-#define __NR_idle 112
-#define __NR_vm86old 113
+ /* 112 __NR_idle obsolete */
+ /* 113 __NR_vm86old obsolete */
#define __NR_wait4 114
#define __NR_swapoff 115
#define __NR_sysinfo 116
@@ -136,17 +136,17 @@
#define __NR_adjtimex 124
#define __NR_mprotect 125
#define __NR_sigprocmask 126
-#define __NR_create_module 127
+ /* 127 __NR_create_module obsolete */
#define __NR_init_module 128
#define __NR_delete_module 129
-#define __NR_get_kernel_syms 130
+ /* 130 __NR_get_kernel_syms obsolete */
#define __NR_quotactl 131
#define __NR_getpgid 132
#define __NR_fchdir 133
#define __NR_bdflush 134
#define __NR_sysfs 135
#define __NR_personality 136
-#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
+ /* 137 __NR_afs_syscall obsolete */
#define __NR_setfsuid 138
#define __NR_setfsgid 139
#define __NR__llseek 140
@@ -175,8 +175,8 @@
#define __NR_mremap 163
#define __NR_setresuid 164
#define __NR_getresuid 165
-#define __NR_vm86 166
-#define __NR_query_module 167
+ /* 166 __NR_vm86 obsolete */
+ /* 167 __NR_query_module obsolete */
#define __NR_poll 168
#define __NR_nfsservctl 169
#define __NR_setresgid 170
@@ -197,8 +197,8 @@
#define __NR_capset 185
#define __NR_sigaltstack 186
#define __NR_sendfile 187
-#define __NR_streams1 188 /* some people actually want it */
-#define __NR_streams2 189 /* some people actually want it */
+ /* 188 __NR_streams1 obsolete */
+ /* 189 __NR_streams2 obsolete */
#define __NR_vfork 190
#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */
#define __NR_mmap2 192
@@ -231,6 +231,7 @@
#define __NR_madvise 219
#define __NR_getdents64 220
#define __NR_fcntl64 221
+/* 222 is unused */
/* 223 is unused */
#define __NR_gettid 224
#define __NR_readahead 225
@@ -251,15 +252,15 @@
#define __NR_futex 240
#define __NR_sched_setaffinity 241
#define __NR_sched_getaffinity 242
-#define __NR_set_thread_area 243
-#define __NR_get_thread_area 244
+ /* 243 __NR_set_thread_area obsolete */
+ /* 244 __NR_get_thread_area obsolete */
#define __NR_io_setup 245
#define __NR_io_destroy 246
#define __NR_io_getevents 247
#define __NR_io_submit 248
#define __NR_io_cancel 249
#define __NR_fadvise64 250
-
+/* 251 unused */
#define __NR_exit_group 252
#define __NR_lookup_dcookie 253
#define __NR_epoll_create 254
@@ -281,7 +282,7 @@
#define __NR_tgkill 270
#define __NR_utimes 271
#define __NR_fadvise64_64 272
-#define __NR_vserver 273
+ /* 273 __NR_vserver obsolete */
#define __NR_mbind 274
#define __NR_get_mempolicy 275
#define __NR_set_mempolicy 276
--
1.7.4.4
^ permalink raw reply related
* [PATCH] mmc: sh_mmcif: process requests asynchronously
From: Guennadi Liakhovetski @ 2011-11-30 15:07 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-sh, Chris Ball, Magnus Damm
This patch converts the sh_mmcif MMC host driver to process requests
asynchronously instead of waiting in its .request() method for completion.
This is achieved by using threaded IRQs.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 824fee5..d077da4 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -123,6 +124,11 @@
#define MASK_MRBSYTO (1 << 1)
#define MASK_MRSPTO (1 << 0)
+#define START_CMD_MASK (MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \
+ MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \
+ MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | \
+ MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO)
+
/* CE_HOST_STS1 */
#define STS1_CMDSEQ (1 << 31)
@@ -162,19 +169,38 @@ enum mmcif_state {
STATE_IOS,
};
+enum mmcif_wait_for {
+ MMCIF_WAIT_FOR_REQUEST,
+ MMCIF_WAIT_FOR_CMD,
+ MMCIF_WAIT_FOR_MREAD,
+ MMCIF_WAIT_FOR_MWRITE,
+ MMCIF_WAIT_FOR_READ,
+ MMCIF_WAIT_FOR_WRITE,
+ MMCIF_WAIT_FOR_READ_END,
+ MMCIF_WAIT_FOR_WRITE_END,
+ MMCIF_WAIT_FOR_STOP,
+};
+
struct sh_mmcif_host {
struct mmc_host *mmc;
struct mmc_data *data;
+ struct mmc_request *mrq;
struct platform_device *pd;
struct clk *hclk;
unsigned int clk;
int bus_width;
bool sd_error;
+ bool dying;
long timeout;
void __iomem *addr;
- struct completion intr_wait;
+ u32 *pio_ptr;
+ spinlock_t lock; /* protect host->state */
enum mmcif_state state;
- spinlock_t lock;
+ enum mmcif_wait_for wait_for;
+ struct delayed_work timeout_work;
+ size_t blocksize;
+ int sg_idx;
+ int sg_blkidx;
bool power;
bool card_present;
@@ -409,7 +435,7 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host)
static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
{
u32 state1, state2;
- int ret, timeout = 10000000;
+ int ret, timeout;
host->sd_error = false;
@@ -421,155 +447,97 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
if (state1 & STS1_CMDSEQ) {
sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK);
sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, ~CMD_CTRL_BREAK);
- while (1) {
- timeout--;
- if (timeout < 0) {
- dev_err(&host->pd->dev,
- "Forceed end of command sequence timeout err\n");
- return -EIO;
- }
+ for (timeout = 10000000; timeout; timeout--) {
if (!(sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1)
- & STS1_CMDSEQ))
+ & STS1_CMDSEQ))
break;
mdelay(1);
}
+ if (!timeout) {
+ dev_err(&host->pd->dev,
+ "Forceed end of command sequence timeout err\n");
+ return -EIO;
+ }
sh_mmcif_sync_reset(host);
dev_dbg(&host->pd->dev, "Forced end of command sequence\n");
return -EIO;
}
if (state2 & STS2_CRC_ERR) {
- dev_dbg(&host->pd->dev, ": Happened CRC error\n");
+ dev_dbg(&host->pd->dev, ": CRC error\n");
ret = -EIO;
} else if (state2 & STS2_TIMEOUT_ERR) {
- dev_dbg(&host->pd->dev, ": Happened Timeout error\n");
+ dev_dbg(&host->pd->dev, ": Timeout\n");
ret = -ETIMEDOUT;
} else {
- dev_dbg(&host->pd->dev, ": Happened End/Index error\n");
+ dev_dbg(&host->pd->dev, ": End/Index error\n");
ret = -EIO;
}
return ret;
}
-static int sh_mmcif_single_read(struct sh_mmcif_host *host,
- struct mmc_request *mrq)
+static void sh_mmcif_single_read(struct sh_mmcif_host *host,
+ struct mmc_request *mrq)
{
- struct mmc_data *data = mrq->data;
- long time;
- u32 blocksize, i, *p = sg_virt(data->sg);
+ host->blocksize = (sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) &
+ BLOCK_SIZE_MASK) + 3;
+
+ host->wait_for = MMCIF_WAIT_FOR_READ;
+ schedule_delayed_work(&host->timeout_work, host->timeout);
/* buf read enable */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
- if (time <= 0 || host->sd_error)
- return sh_mmcif_error_manage(host);
-
- blocksize = (BLOCK_SIZE_MASK &
- sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
- for (i = 0; i < blocksize / 4; i++)
- *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA);
-
- /* buffer read end */
- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
- if (time <= 0 || host->sd_error)
- return sh_mmcif_error_manage(host);
-
- return 0;
}
-static int sh_mmcif_multi_read(struct sh_mmcif_host *host,
- struct mmc_request *mrq)
+static void sh_mmcif_multi_read(struct sh_mmcif_host *host,
+ struct mmc_request *mrq)
{
struct mmc_data *data = mrq->data;
- long time;
- u32 blocksize, i, j, sec, *p;
-
- blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr,
- MMCIF_CE_BLOCK_SET);
- for (j = 0; j < data->sg_len; j++) {
- p = sg_virt(data->sg);
- for (sec = 0; sec < data->sg->length / blocksize; sec++) {
- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
- /* buf read enable */
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
-
- if (time <= 0 || host->sd_error)
- return sh_mmcif_error_manage(host);
-
- for (i = 0; i < blocksize / 4; i++)
- *p++ = sh_mmcif_readl(host->addr,
- MMCIF_CE_DATA);
- }
- if (j < data->sg_len - 1)
- data->sg++;
- }
- return 0;
+
+ if (!data->sg_len || !data->sg->length)
+ return;
+
+ host->blocksize = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) &
+ BLOCK_SIZE_MASK;
+
+ host->wait_for = MMCIF_WAIT_FOR_MREAD;
+ host->sg_idx = 0;
+ host->sg_blkidx = 0;
+ host->pio_ptr = sg_virt(data->sg);
+ schedule_delayed_work(&host->timeout_work, host->timeout);
+ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
}
-static int sh_mmcif_single_write(struct sh_mmcif_host *host,
+static void sh_mmcif_single_write(struct sh_mmcif_host *host,
struct mmc_request *mrq)
{
- struct mmc_data *data = mrq->data;
- long time;
- u32 blocksize, i, *p = sg_virt(data->sg);
+ host->blocksize = (sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) &
+ BLOCK_SIZE_MASK) + 3;
- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
+ host->wait_for = MMCIF_WAIT_FOR_WRITE;
+ schedule_delayed_work(&host->timeout_work, host->timeout);
/* buf write enable */
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
- if (time <= 0 || host->sd_error)
- return sh_mmcif_error_manage(host);
-
- blocksize = (BLOCK_SIZE_MASK &
- sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
- for (i = 0; i < blocksize / 4; i++)
- sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++);
-
- /* buffer write end */
- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
-
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
- if (time <= 0 || host->sd_error)
- return sh_mmcif_error_manage(host);
-
- return 0;
+ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
}
-static int sh_mmcif_multi_write(struct sh_mmcif_host *host,
- struct mmc_request *mrq)
+static void sh_mmcif_multi_write(struct sh_mmcif_host *host,
+ struct mmc_request *mrq)
{
struct mmc_data *data = mrq->data;
- long time;
- u32 i, sec, j, blocksize, *p;
- blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr,
- MMCIF_CE_BLOCK_SET);
-
- for (j = 0; j < data->sg_len; j++) {
- p = sg_virt(data->sg);
- for (sec = 0; sec < data->sg->length / blocksize; sec++) {
- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
- /* buf write enable*/
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
+ if (!data->sg_len || !data->sg->length)
+ return;
- if (time <= 0 || host->sd_error)
- return sh_mmcif_error_manage(host);
+ host->blocksize = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) &
+ BLOCK_SIZE_MASK;
- for (i = 0; i < blocksize / 4; i++)
- sh_mmcif_writel(host->addr,
- MMCIF_CE_DATA, *p++);
- }
- if (j < data->sg_len - 1)
- data->sg++;
- }
- return 0;
+ host->wait_for = MMCIF_WAIT_FOR_MWRITE;
+ host->sg_idx = 0;
+ host->sg_blkidx = 0;
+ host->pio_ptr = sg_virt(data->sg);
+ schedule_delayed_work(&host->timeout_work, host->timeout);
+ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
}
static void sh_mmcif_get_response(struct sh_mmcif_host *host,
@@ -666,57 +634,48 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
}
static int sh_mmcif_data_trans(struct sh_mmcif_host *host,
- struct mmc_request *mrq, u32 opc)
+ struct mmc_request *mrq, u32 opc)
{
- int ret;
-
switch (opc) {
case MMC_READ_MULTIPLE_BLOCK:
- ret = sh_mmcif_multi_read(host, mrq);
- break;
+ sh_mmcif_multi_read(host, mrq);
+ return 0;
case MMC_WRITE_MULTIPLE_BLOCK:
- ret = sh_mmcif_multi_write(host, mrq);
- break;
+ sh_mmcif_multi_write(host, mrq);
+ return 0;
case MMC_WRITE_BLOCK:
- ret = sh_mmcif_single_write(host, mrq);
- break;
+ sh_mmcif_single_write(host, mrq);
+ return 0;
case MMC_READ_SINGLE_BLOCK:
case MMC_SEND_EXT_CSD:
- ret = sh_mmcif_single_read(host, mrq);
- break;
- default:
- dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc);
- ret = -EINVAL;
- break;
+ sh_mmcif_single_read(host, mrq);
+ return 0;
}
- return ret;
+ dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc);
+ return -EINVAL;
}
static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
- struct mmc_request *mrq, struct mmc_command *cmd)
+ struct mmc_request *mrq)
{
- long time;
- int ret = 0, mask = 0;
+ struct mmc_command *cmd = mrq->cmd;
u32 opc = cmd->opcode;
+ u32 mask;
switch (opc) {
- /* respons busy check */
+ /* response busy check */
case MMC_SWITCH:
case MMC_STOP_TRANSMISSION:
case MMC_SET_WRITE_PROT:
case MMC_CLR_WRITE_PROT:
case MMC_ERASE:
case MMC_GEN_CMD:
- mask = MASK_MRBSYE;
+ mask = START_CMD_MASK | MASK_MRBSYE;
break;
default:
- mask = MASK_MCRSPE;
+ mask = START_CMD_MASK | MASK_MCRSPE;
break;
}
- mask |= MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR |
- MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR |
- MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO |
- MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO;
if (host->data) {
sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0);
@@ -732,61 +691,14 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
/* set cmd */
sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc);
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
- if (time <= 0) {
- cmd->error = sh_mmcif_error_manage(host);
- return;
- }
- if (host->sd_error) {
- switch (cmd->opcode) {
- case MMC_ALL_SEND_CID:
- case MMC_SELECT_CARD:
- case MMC_APP_CMD:
- cmd->error = -ETIMEDOUT;
- break;
- default:
- dev_dbg(&host->pd->dev, "Cmd(d'%d) err\n",
- cmd->opcode);
- cmd->error = sh_mmcif_error_manage(host);
- break;
- }
- host->sd_error = false;
- return;
- }
- if (!(cmd->flags & MMC_RSP_PRESENT)) {
- cmd->error = 0;
- return;
- }
- sh_mmcif_get_response(host, cmd);
- if (host->data) {
- if (!host->dma_active) {
- ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
- } else {
- long time - wait_for_completion_interruptible_timeout(&host->dma_complete,
- host->timeout);
- if (!time)
- ret = -ETIMEDOUT;
- else if (time < 0)
- ret = time;
- sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC,
- BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
- host->dma_active = false;
- }
- if (ret < 0)
- mrq->data->bytes_xfered = 0;
- else
- mrq->data->bytes_xfered - mrq->data->blocks * mrq->data->blksz;
- }
- cmd->error = ret;
+ host->wait_for = MMCIF_WAIT_FOR_CMD;
+ schedule_delayed_work(&host->timeout_work, host->timeout);
}
static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host,
- struct mmc_request *mrq, struct mmc_command *cmd)
+ struct mmc_request *mrq)
{
- long time;
+ struct mmc_command *cmd = mrq->stop;
if (mrq->cmd->opcode = MMC_READ_MULTIPLE_BLOCK)
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE);
@@ -798,14 +710,8 @@ static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host,
return;
}
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
- if (time <= 0 || host->sd_error) {
- cmd->error = sh_mmcif_error_manage(host);
- return;
- }
- sh_mmcif_get_cmd12response(host, cmd);
- cmd->error = 0;
+ host->wait_for = MMCIF_WAIT_FOR_STOP;
+ schedule_delayed_work(&host->timeout_work, host->timeout);
}
static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -813,6 +719,8 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
struct sh_mmcif_host *host = mmc_priv(mmc);
unsigned long flags;
+ dev_info(mmc->parent, "%s(%u), data %p\n", __func__, mrq->cmd->opcode, mrq->data);
+
spin_lock_irqsave(&host->lock, flags);
if (host->state != STATE_IDLE) {
spin_unlock_irqrestore(&host->lock, flags);
@@ -844,23 +752,11 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
default:
break;
}
+
+ host->mrq = mrq;
host->data = mrq->data;
- if (mrq->data) {
- if (mrq->data->flags & MMC_DATA_READ) {
- if (host->chan_rx)
- sh_mmcif_start_dma_rx(host);
- } else {
- if (host->chan_tx)
- sh_mmcif_start_dma_tx(host);
- }
- }
- sh_mmcif_start_cmd(host, mrq, mrq->cmd);
- host->data = NULL;
- if (!mrq->cmd->error && mrq->stop)
- sh_mmcif_stop_cmd(host, mrq, mrq->stop);
- host->state = STATE_IDLE;
- mmc_request_done(mmc, mrq);
+ sh_mmcif_start_cmd(host, mrq);
}
static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -935,9 +831,268 @@ static struct mmc_host_ops sh_mmcif_ops = {
.get_cd = sh_mmcif_get_cd,
};
-static void sh_mmcif_detect(struct mmc_host *mmc)
+static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
+{
+ struct mmc_command *cmd = host->mrq->cmd;
+ long time;
+
+ if (host->sd_error) {
+ switch (cmd->opcode) {
+ case MMC_ALL_SEND_CID:
+ case MMC_SELECT_CARD:
+ case MMC_APP_CMD:
+ cmd->error = -ETIMEDOUT;
+ host->sd_error = false;
+ break;
+ default:
+ cmd->error = sh_mmcif_error_manage(host);
+ dev_dbg(&host->pd->dev, "Cmd(d'%d) error %d\n",
+ cmd->opcode, cmd->error);
+ break;
+ }
+ return false;
+ }
+ if (!(cmd->flags & MMC_RSP_PRESENT)) {
+ cmd->error = 0;
+ return false;
+ }
+
+ sh_mmcif_get_response(host, cmd);
+
+ if (!host->data)
+ return false;
+
+ if (host->mrq->data->flags & MMC_DATA_READ) {
+ if (host->chan_rx)
+ sh_mmcif_start_dma_rx(host);
+ } else {
+ if (host->chan_tx)
+ sh_mmcif_start_dma_tx(host);
+ }
+
+ if (!host->dma_active) {
+ host->data->error = sh_mmcif_data_trans(host, host->mrq, cmd->opcode);
+ if (!host->data->error)
+ return true;
+ return false;
+ }
+
+ /* Running in the IRQ thread, can sleep */
+ time = wait_for_completion_interruptible_timeout(&host->dma_complete,
+ host->timeout);
+ if (host->sd_error) {
+ /* Woken up by an error IRQ: abort DMA */
+ if (host->data->flags & MMC_DATA_READ)
+ dmaengine_terminate_all(host->chan_rx);
+ else
+ dmaengine_terminate_all(host->chan_tx);
+ host->data->error = sh_mmcif_error_manage(host);
+ } else if (!time) {
+ host->data->error = -ETIMEDOUT;
+ } else if (time < 0) {
+ host->data->error = time;
+ }
+ sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC,
+ BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
+ host->dma_active = false;
+
+ if (host->data->error)
+ host->data->bytes_xfered = 0;
+
+ return false;
+}
+
+static bool sh_mmcif_next_block(struct sh_mmcif_host *host, u32 *p)
{
- mmc_detect_change(mmc, 0);
+ struct mmc_data *data = host->mrq->data;
+
+ host->sg_blkidx += host->blocksize;
+
+ /* data->sg->length must be a multiple of host->blocksize? */
+ BUG_ON(host->sg_blkidx > data->sg->length);
+
+ if (host->sg_blkidx = data->sg->length) {
+ host->sg_blkidx = 0;
+ if (++host->sg_idx < data->sg_len)
+ host->pio_ptr = sg_virt(++data->sg);
+ } else {
+ host->pio_ptr = p;
+ }
+
+ if (host->sg_idx = data->sg_len)
+ return false;
+
+ return true;
+}
+
+static bool sh_mmcif_mread_block(struct sh_mmcif_host *host)
+{
+ struct mmc_data *data = host->mrq->data;
+ u32 *p = host->pio_ptr;
+ int i;
+
+ if (host->sd_error) {
+ data->error = sh_mmcif_error_manage(host);
+ return false;
+ }
+
+ BUG_ON(!data->sg->length);
+
+ for (i = 0; i < host->blocksize / 4; i++)
+ *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA);
+
+ if (!sh_mmcif_next_block(host, p))
+ return false;
+
+ schedule_delayed_work(&host->timeout_work, host->timeout);
+ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
+
+ return true;
+}
+
+static bool sh_mmcif_mwrite_block(struct sh_mmcif_host *host)
+{
+ struct mmc_data *data = host->mrq->data;
+ u32 *p = host->pio_ptr;
+ int i;
+
+ if (host->sd_error) {
+ data->error = sh_mmcif_error_manage(host);
+ return false;
+ }
+
+ BUG_ON(!data->sg->length);
+
+ for (i = 0; i < host->blocksize / 4; i++)
+ sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++);
+
+ if (!sh_mmcif_next_block(host, p))
+ return false;
+
+ schedule_delayed_work(&host->timeout_work, host->timeout);
+ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
+
+ return true;
+}
+
+static bool sh_mmcif_read_block(struct sh_mmcif_host *host)
+{
+ struct mmc_data *data = host->mrq->data;
+ u32 *p = sg_virt(data->sg);
+ int i;
+
+ if (host->sd_error) {
+ data->error = sh_mmcif_error_manage(host);
+ return false;
+ }
+
+ for (i = 0; i < host->blocksize / 4; i++)
+ *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA);
+
+ /* buffer read end */
+ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
+ host->wait_for = MMCIF_WAIT_FOR_READ_END;
+
+ return true;
+}
+
+static bool sh_mmcif_write_block(struct sh_mmcif_host *host)
+{
+ struct mmc_data *data = host->mrq->data;
+ u32 *p = sg_virt(data->sg);
+ int i;
+
+ if (host->sd_error) {
+ data->error = sh_mmcif_error_manage(host);
+ return false;
+ }
+
+ for (i = 0; i < host->blocksize / 4; i++)
+ sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++);
+
+ /* buffer write end */
+ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
+ host->wait_for = MMCIF_WAIT_FOR_WRITE_END;
+
+ return true;
+}
+
+static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
+{
+ struct sh_mmcif_host *host = dev_id;
+ struct mmc_request *mrq = host->mrq;
+
+ cancel_delayed_work_sync(&host->timeout_work);
+
+ /*
+ * All handlers return true, if processing continues, and false, if the
+ * request has to be completed - successfully or not
+ */
+ switch (host->wait_for) {
+ case MMCIF_WAIT_FOR_REQUEST:
+ /* We're too late, the timeout has already kicked in */
+ return IRQ_HANDLED;
+ case MMCIF_WAIT_FOR_CMD:
+ if (sh_mmcif_end_cmd(host))
+ /* Wait for data */
+ return IRQ_HANDLED;
+ break;
+ case MMCIF_WAIT_FOR_MREAD:
+ if (sh_mmcif_mread_block(host))
+ /* Wait for more data */
+ return IRQ_HANDLED;
+ break;
+ case MMCIF_WAIT_FOR_READ:
+ if (sh_mmcif_read_block(host))
+ /* Wait for data end */
+ return IRQ_HANDLED;
+ break;
+ case MMCIF_WAIT_FOR_MWRITE:
+ if (sh_mmcif_mwrite_block(host))
+ /* Wait data to write */
+ return IRQ_HANDLED;
+ break;
+ case MMCIF_WAIT_FOR_WRITE:
+ if (sh_mmcif_write_block(host))
+ /* Wait for data end */
+ return IRQ_HANDLED;
+ break;
+ case MMCIF_WAIT_FOR_STOP:
+ if (host->sd_error) {
+ mrq->stop->error = sh_mmcif_error_manage(host);
+ break;
+ }
+ sh_mmcif_get_cmd12response(host, mrq->stop);
+ mrq->stop->error = 0;
+ break;
+ case MMCIF_WAIT_FOR_READ_END:
+ case MMCIF_WAIT_FOR_WRITE_END:
+ if (host->sd_error)
+ mrq->data->error = sh_mmcif_error_manage(host);
+ break;
+ default:
+ BUG();
+ }
+
+ if (host->wait_for != MMCIF_WAIT_FOR_STOP) {
+ host->data = NULL;
+
+ if (!mrq->cmd->error && mrq->data && !mrq->data->error)
+ mrq->data->bytes_xfered + mrq->data->blocks * mrq->data->blksz;
+
+ if (mrq->stop && !mrq->cmd->error && (!mrq->data || !mrq->data->error)) {
+ sh_mmcif_stop_cmd(host, mrq);
+ if (!mrq->stop->error)
+ return IRQ_HANDLED;
+ }
+ }
+
+ host->wait_for = MMCIF_WAIT_FOR_REQUEST;
+ host->state = STATE_IDLE;
+ mmc_request_done(host->mmc, mrq);
+
+ return IRQ_HANDLED;
}
static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
@@ -991,14 +1146,58 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
host->sd_error = true;
dev_dbg(&host->pd->dev, "int err state = %08x\n", state);
}
- if (state & ~(INT_CMD12RBE | INT_CMD12CRE))
- complete(&host->intr_wait);
- else
+ if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) {
+ if (host->dma_active)
+ mmcif_dma_complete(host);
+ else
+ return IRQ_WAKE_THREAD;
+ } else {
dev_dbg(&host->pd->dev, "Unexpected IRQ 0x%x\n", state);
+ }
return IRQ_HANDLED;
}
+static void mmcif_timeout_work(struct work_struct *work)
+{
+ struct delayed_work *d = container_of(work, struct delayed_work, work);
+ struct sh_mmcif_host *host = container_of(d, struct sh_mmcif_host, timeout_work);
+ struct mmc_request *mrq = host->mrq;
+
+ if (host->dying)
+ /* Don't run after mmc_remove_host() */
+ return;
+
+ /*
+ * Handle races with cancel_delayed_work(), unless
+ * cancel_delayed_work_sync() is used
+ */
+ switch (host->wait_for) {
+ case MMCIF_WAIT_FOR_CMD:
+ mrq->cmd->error = sh_mmcif_error_manage(host);
+ break;
+ case MMCIF_WAIT_FOR_STOP:
+ mrq->stop->error = sh_mmcif_error_manage(host);
+ break;
+ case MMCIF_WAIT_FOR_MREAD:
+ case MMCIF_WAIT_FOR_MWRITE:
+ case MMCIF_WAIT_FOR_READ:
+ case MMCIF_WAIT_FOR_WRITE:
+ case MMCIF_WAIT_FOR_READ_END:
+ case MMCIF_WAIT_FOR_WRITE_END:
+ host->data->error = sh_mmcif_error_manage(host);
+ break;
+ default:
+ BUG();
+ }
+
+ host->state = STATE_IDLE;
+ host->wait_for = MMCIF_WAIT_FOR_REQUEST;
+ host->data = NULL;
+ host->mrq = NULL;
+ mmc_request_done(host->mmc, mrq);
+}
+
static int __devinit sh_mmcif_probe(struct platform_device *pdev)
{
int ret = 0, irq[2];
@@ -1052,7 +1251,6 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
host->clk = clk_get_rate(host->hclk);
host->pd = pdev;
- init_completion(&host->intr_wait);
spin_lock_init(&host->lock);
mmc->ops = &sh_mmcif_ops;
@@ -1089,19 +1287,21 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
- ret = request_irq(irq[0], sh_mmcif_intr, 0, "sh_mmc:error", host);
+ ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);
if (ret) {
dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n");
goto clean_up3;
}
- ret = request_irq(irq[1], sh_mmcif_intr, 0, "sh_mmc:int", host);
+ ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host);
if (ret) {
free_irq(irq[0], host);
dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
goto clean_up3;
}
- sh_mmcif_detect(host->mmc);
+ INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
+
+ mmc_detect_change(host->mmc, 0);
dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION);
dev_dbg(&pdev->dev, "chip ver H'%04x\n",
@@ -1127,11 +1327,19 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
struct sh_mmcif_host *host = platform_get_drvdata(pdev);
int irq[2];
+ host->dying = true;
pm_runtime_get_sync(&pdev->dev);
mmc_remove_host(host->mmc);
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
+ /*
+ * FIXME: cancel_delayed_work(_sync)() and free_irq() race with the
+ * mmc_remove_host() call above. But swapping order doesn't help either
+ * (a query on the linux-mmc mailing list didn't bring any replies).
+ */
+ cancel_delayed_work_sync(&host->timeout_work);
+
if (host->addr)
iounmap(host->addr);
^ permalink raw reply related
* Re: [PATCH] sh: sh2a: Optimise cache flush for writethrough mode.
From: phil.edworthy @ 2011-11-30 9:56 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <1322637713-15227-1-git-send-email-phil.edworthy@renesas.com>
Hi Paul,
> Subject: Re: [PATCH] sh: sh2a: Optimise cache flush for writethrough
mode.
>
> On Wed, Nov 30, 2011 at 07:21:53AM +0000, Phil Edworthy wrote:
> > When the operand cache is set to writethough mode, there is no
> > need to flush data.
> >
> > Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
>
> What about the other routines?
>
> You are presumably stipulating that any access to the OC address array
> outside of cacheline invalidation should be omitted for write-through
> cache mode, which suggests that quite a lot of the file in question can
> simply be nopped out.
>
> At the very least sh2a__flush_wback_region() could deal with the same
> treatment. For the invalidation routines you presumably still need the
> V-bit clearing, though.
>
> sh2a__flush_invalidate_region() also bears closer inspection.
It's worth mentioning that this patch is essentially a work around for an
issue with write-back mode. sh2a_flush_icache_range is passed a large
address range which takes ages to flush/invalidate. For write-back mode,
instead of indexing on the address, perhaps we can walk through all the
cache entries and check for an address match. That's for another day...
I agree that the other functions can be improved. I ignored them as the
main performance issue is with sh2a_flush_icache_range. I wasn't entirely
sure when some of the other functions are used. Are
sh2a__flush_wback_region and sh2a__flush_purge_region purely OC related?
And sh2a__flush_invalidate_region and sh2a_flush_icache_range work on both
the IC and OC?
Phil
^ permalink raw reply
* Re: [PATCH] sh: sh2a: Optimise cache flush for writethrough mode.
From: Paul Mundt @ 2011-11-30 9:17 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <1322637713-15227-1-git-send-email-phil.edworthy@renesas.com>
On Wed, Nov 30, 2011 at 07:21:53AM +0000, Phil Edworthy wrote:
> When the operand cache is set to writethough mode, there is no
> need to flush data.
>
> Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
What about the other routines?
You are presumably stipulating that any access to the OC address array
outside of cacheline invalidation should be omitted for write-through
cache mode, which suggests that quite a lot of the file in question can
simply be nopped out.
At the very least sh2a__flush_wback_region() could deal with the same
treatment. For the invalidation routines you presumably still need the
V-bit clearing, though.
sh2a__flush_invalidate_region() also bears closer inspection.
^ permalink raw reply
* [PATCH] sh: sh2a: Optimise cache flush for writethrough mode.
From: Phil Edworthy @ 2011-11-30 7:21 UTC (permalink / raw)
To: linux-sh
When the operand cache is set to writethough mode, there is no
need to flush data.
Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
arch/sh/mm/cache-sh2a.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/sh/mm/cache-sh2a.c b/arch/sh/mm/cache-sh2a.c
index 1f51225..56bb5f2 100644
--- a/arch/sh/mm/cache-sh2a.c
+++ b/arch/sh/mm/cache-sh2a.c
@@ -112,6 +112,7 @@ static void sh2a_flush_icache_range(void *args)
for (v = start; v < end; v+=L1_CACHE_BYTES) {
unsigned long addr = (v & 0x000007f0);
+#ifdef CONFIG_CACHE_WRITEBACK
int way;
/* O-Cache writeback */
for (way = 0; way < 4; way++) {
@@ -121,6 +122,7 @@ static void sh2a_flush_icache_range(void *args)
__raw_writel(data, CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
}
}
+#endif
/* I-Cache invalidate */
__raw_writel(addr,
CACHE_IC_ADDRESS_ARRAY | addr | 0x00000008);
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH 2/2 v5] net/smsc911x: Add regulator support
From: David Miller @ 2011-11-29 23:37 UTC (permalink / raw)
To: robert.marklund
Cc: netdev, steve.glendinning, mathieu.poirier, lethal, linux-sh,
s.hauer, tony, linux-omap, vapier, uclinux-dist-devel,
linus.walleij
In-Reply-To: <1322132587-2049-1-git-send-email-robert.marklund@stericsson.com>
From: Robert Marklund <robert.marklund@stericsson.com>
Date: Thu, 24 Nov 2011 12:03:07 +0100
> Add some basic regulator support for the power pins, as needed
> by the ST-Ericsson Snowball platform that powers up the SMSC911
> chip using an external regulator.
>
> Platforms that use regulators and the smsc911x and have no defined
> regulator for the smsc911x and claim complete regulator
> constraints with no dummy regulators will need to provide it, for
> example using a fixed voltage regulator. It appears that this may
> affect (apart from Ux500 Snowball) possibly these archs/machines
> that from some grep:s appear to define both CONFIG_SMSC911X and
> CONFIG_REGULATOR:
>
> - ARM Freescale mx3 and OMAP 2 plus, Raumfeld machines
> - Blackfin
> - Super-H
>
> Cc: Paul Mundt <lethal@linux-sh.org>
> Cc: linux-sh@vger.kernel.org
> Cc: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Tony Lindgren <tony@atomide.com>
> Cc: linux-omap@vger.kernel.org
> Cc: Mike Frysinger <vapier@gentoo.org>
> Cc: uclinux-dist-devel@blackfin.uclinux.org
> Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Robert Marklund <robert.marklund@stericsson.com>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH 0/3] Change ARCH_NR_GPIO into a Kconfig variable
From: Russell King - ARM Linux @ 2011-11-29 9:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdY-YL0RSY4+nL36sM9WwX+VbMkJP54djrCwYCQmw9AFEw@mail.gmail.com>
On Tue, Nov 29, 2011 at 09:40:27AM +0100, Linus Walleij wrote:
> On Tue, Nov 29, 2011 at 7:46 AM, Peter De Schrijver
> <pdeschrijver@nvidia.com> wrote:
> > On Thu, Nov 03, 2011 at 06:00:44PM +0100, Peter De Schrijver wrote:
> >> This patchset converts ARCH_NR_GPIO to a Kconfig variable as suggested by
> >> Russel King. It also converts some platforms to the new model.
> >>
> >> Peter De Schrijver (3):
> >> ARM: ARCH_NR_GPIO: Make ARCH_NR_GPIO a Kconfig variable
> >> ARM: mach-shmobile: Use CONFIG_ARCH_NR_GPIO
> >> ARM: mach-ux500 Use CONFIG_ARCH_NR_GPIO
> >
> > Ping? What should we do with this?
>
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
>
> Put it into Russell's patch tracker.
Or we could wait for Grant to reappear and take it.
^ permalink raw reply
* Re: [PATCH 0/3] Change ARCH_NR_GPIO into a Kconfig variable
From: Linus Walleij @ 2011-11-29 8:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111129064630.GW19069@tbergstrom-lnx.Nvidia.com>
On Tue, Nov 29, 2011 at 7:46 AM, Peter De Schrijver
<pdeschrijver@nvidia.com> wrote:
> On Thu, Nov 03, 2011 at 06:00:44PM +0100, Peter De Schrijver wrote:
>> This patchset converts ARCH_NR_GPIO to a Kconfig variable as suggested by
>> Russel King. It also converts some platforms to the new model.
>>
>> Peter De Schrijver (3):
>> ARM: ARCH_NR_GPIO: Make ARCH_NR_GPIO a Kconfig variable
>> ARM: mach-shmobile: Use CONFIG_ARCH_NR_GPIO
>> ARM: mach-ux500 Use CONFIG_ARCH_NR_GPIO
>
> Ping? What should we do with this?
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Put it into Russell's patch tracker.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 0/3] Change ARCH_NR_GPIO into a Kconfig variable
From: Peter De Schrijver @ 2011-11-29 6:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1320339647-30255-1-git-send-email-pdeschrijver@nvidia.com>
On Thu, Nov 03, 2011 at 06:00:44PM +0100, Peter De Schrijver wrote:
> This patchset converts ARCH_NR_GPIO to a Kconfig variable as suggested by
> Russel King. It also converts some platforms to the new model.
>
> Peter De Schrijver (3):
> ARM: ARCH_NR_GPIO: Make ARCH_NR_GPIO a Kconfig variable
> ARM: mach-shmobile: Use CONFIG_ARCH_NR_GPIO
> ARM: mach-ux500 Use CONFIG_ARCH_NR_GPIO
Ping? What should we do with this?
Cheers,
Peter.
^ permalink raw reply
* [Update][PATCH] PM / Domains: Make it possible to assign names to generic PM domains
From: Rafael J. Wysocki @ 2011-11-28 21:38 UTC (permalink / raw)
To: Linux PM list; +Cc: LKML, Linux-sh list, Magnus Damm
In-Reply-To: <201111272153.53008.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
Add a name member pointer to struct generic_pm_domain and use it in
diagnostic messages regarding the domain power-off and power-on
latencies. Update the ARM shmobile SH7372 code to assign names to
the PM domains used by it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
Hi,
This version of the patch avoids adding a new member to
struct generic_pm_domain.
Thanks,
Rafael
---
arch/arm/mach-shmobile/pm-sh7372.c | 16 ++++++++++++----
drivers/base/power/domain.c | 14 ++++++++++++--
include/linux/pm_domain.h | 1 +
3 files changed, 25 insertions(+), 6 deletions(-)
Index: linux/drivers/base/power/domain.c
=================================--- linux.orig/drivers/base/power/domain.c
+++ linux/drivers/base/power/domain.c
@@ -209,8 +209,13 @@ int __pm_genpd_poweron(struct generic_pm
goto err;
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
- if (elapsed_ns > genpd->power_on_latency_ns)
+ if (elapsed_ns > genpd->power_on_latency_ns) {
genpd->power_on_latency_ns = elapsed_ns;
+ if (genpd->name)
+ pr_warning("%s: Power-on latency exceeded, "
+ "new value %lld ns\n", genpd->name,
+ elapsed_ns);
+ }
}
genpd_set_active(genpd);
@@ -428,8 +433,13 @@ static int pm_genpd_poweroff(struct gene
}
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
- if (elapsed_ns > genpd->power_off_latency_ns)
+ if (elapsed_ns > genpd->power_off_latency_ns) {
genpd->power_off_latency_ns = elapsed_ns;
+ if (genpd->name)
+ pr_warning("%s: Power-off latency exceeded, "
+ "new value %lld ns\n", genpd->name,
+ elapsed_ns);
+ }
}
genpd->status = GPD_STATE_POWER_OFF;
Index: linux/include/linux/pm_domain.h
=================================--- linux.orig/include/linux/pm_domain.h
+++ linux/include/linux/pm_domain.h
@@ -49,6 +49,7 @@ struct generic_pm_domain {
struct mutex lock;
struct dev_power_governor *gov;
struct work_struct power_off_work;
+ char *name;
unsigned int in_progress; /* Number of devices being suspended now */
atomic_t sd_count; /* Number of subdomains with power "on" */
enum gpd_status status; /* Current state of the domain */
Index: linux/arch/arm/mach-shmobile/pm-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/pm-sh7372.c
+++ linux/arch/arm/mach-shmobile/pm-sh7372.c
@@ -101,8 +101,8 @@ static int pd_power_down(struct generic_
}
if (!sh7372_pd->no_debug)
- pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
- mask, __raw_readl(PSTR));
+ pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
+ genpd->name, mask, __raw_readl(PSTR));
return 0;
}
@@ -133,8 +133,8 @@ static int __pd_power_up(struct sh7372_p
ret = -EIO;
if (!sh7372_pd->no_debug)
- pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
- mask, __raw_readl(PSTR));
+ pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
+ sh7372_pd->genpd.name, mask, __raw_readl(PSTR));
out:
if (ret = 0 && sh7372_pd->resume && do_resume)
@@ -233,18 +233,22 @@ void sh7372_pm_add_subdomain(struct sh73
}
struct sh7372_pm_domain sh7372_a4lc = {
+ .genpd.name = "A4LC",
.bit_shift = 1,
};
struct sh7372_pm_domain sh7372_a4mp = {
+ .genpd.name = "A4MP",
.bit_shift = 2,
};
struct sh7372_pm_domain sh7372_d4 = {
+ .genpd.name = "D4",
.bit_shift = 3,
};
struct sh7372_pm_domain sh7372_a4r = {
+ .genpd.name = "A4R",
.bit_shift = 5,
.gov = &sh7372_always_on_gov,
.suspend = sh7372_a4r_suspend,
@@ -253,14 +257,17 @@ struct sh7372_pm_domain sh7372_a4r = {
};
struct sh7372_pm_domain sh7372_a3rv = {
+ .genpd.name = "A3RV",
.bit_shift = 6,
};
struct sh7372_pm_domain sh7372_a3ri = {
+ .genpd.name = "A3RI",
.bit_shift = 8,
};
struct sh7372_pm_domain sh7372_a3sp = {
+ .genpd.name = "A3SP",
.bit_shift = 11,
.gov = &sh7372_always_on_gov,
.no_debug = true,
@@ -275,6 +282,7 @@ static void sh7372_a3sp_init(void)
}
struct sh7372_pm_domain sh7372_a3sg = {
+ .genpd.name = "A3SG",
.bit_shift = 13,
};
^ permalink raw reply
* [PATCH 17/23] SuperH: Use HAVE_MEMBLOCK_NODE_MAP
From: Tejun Heo @ 2011-11-28 19:31 UTC (permalink / raw)
To: benh, yinghai, hpa, tony.luck, ralf, schwidefsky, liqin.chen,
lethal, davem, linux-kernel, linux-arch, mingo, jonas, lennox.wu
Cc: Tejun Heo, linux-sh
In-Reply-To: <1322508685-32532-1-git-send-email-tj@kernel.org>
sh doesn't access early_node_map[] directly and enabling
HAVE_MEMBLOCK_NODE_MAP is trivial - replacing add_active_range() calls
with memblock_set_node() and selecting HAVE_MEMBLOCK_NODE_MAP is
enough.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: linux-sh@vger.kernel.org
---
arch/sh/Kconfig | 1 +
arch/sh/kernel/setup.c | 3 ++-
2 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 5629e20..47a2f1c 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -4,6 +4,7 @@ config SUPERH
select CLKDEV_LOOKUP
select HAVE_IDE if HAS_IOPORT
select HAVE_MEMBLOCK
+ select HAVE_MEMBLOCK_NODE_MAP
select HAVE_OPROFILE
select HAVE_GENERIC_DMA_COHERENT
select HAVE_ARCH_TRACEHOOK
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 1a0e946..7b57bf1 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -230,7 +230,8 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
pmb_bolt_mapping((unsigned long)__va(start), start, end - start,
PAGE_KERNEL);
- add_active_range(nid, start_pfn, end_pfn);
+ memblock_set_node(PFN_PHYS(start_pfn),
+ PFN_PHYS(end_pfn - start_pfn), nid);
}
void __init __weak plat_early_device_setup(void)
--
1.7.3.1
^ permalink raw reply related
* [PATCH] PM / Domains: Make it possible to assign names to generic PM domains
From: Rafael J. Wysocki @ 2011-11-27 20:53 UTC (permalink / raw)
To: Linux PM list; +Cc: LKML, Linux-sh list, Magnus Damm
From: Rafael J. Wysocki <rjw@sisk.pl>
Add a name member pointer to struct generic_pm_domain and use it in
diagnostic messages regarding the domain power-off and power-on
latencies. Update the ARM shmobile SH7372 code to assign names to
the PM domains used by it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
Hi,
This patch is on top of linux-pm/linux-next.
Thanks,
Rafael
---
arch/arm/mach-shmobile/include/mach/sh7372.h | 1 +
arch/arm/mach-shmobile/pm-sh7372.c | 17 +++++++++++++----
drivers/base/power/domain.c | 14 ++++++++++++--
include/linux/pm_domain.h | 1 +
4 files changed, 27 insertions(+), 6 deletions(-)
Index: linux/drivers/base/power/domain.c
=================================--- linux.orig/drivers/base/power/domain.c
+++ linux/drivers/base/power/domain.c
@@ -209,8 +209,13 @@ int __pm_genpd_poweron(struct generic_pm
goto err;
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
- if (elapsed_ns > genpd->power_on_latency_ns)
+ if (elapsed_ns > genpd->power_on_latency_ns) {
genpd->power_on_latency_ns = elapsed_ns;
+ if (genpd->name)
+ pr_warning("%s: Power-on latency exceeded, "
+ "new value %lld ns\n", genpd->name,
+ elapsed_ns);
+ }
}
genpd_set_active(genpd);
@@ -428,8 +433,13 @@ static int pm_genpd_poweroff(struct gene
}
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
- if (elapsed_ns > genpd->power_off_latency_ns)
+ if (elapsed_ns > genpd->power_off_latency_ns) {
genpd->power_off_latency_ns = elapsed_ns;
+ if (genpd->name)
+ pr_warning("%s: Power-off latency exceeded, "
+ "new value %lld ns\n", genpd->name,
+ elapsed_ns);
+ }
}
genpd->status = GPD_STATE_POWER_OFF;
Index: linux/include/linux/pm_domain.h
=================================--- linux.orig/include/linux/pm_domain.h
+++ linux/include/linux/pm_domain.h
@@ -49,6 +49,7 @@ struct generic_pm_domain {
struct mutex lock;
struct dev_power_governor *gov;
struct work_struct power_off_work;
+ char *name;
unsigned int in_progress; /* Number of devices being suspended now */
atomic_t sd_count; /* Number of subdomains with power "on" */
enum gpd_status status; /* Current state of the domain */
Index: linux/arch/arm/mach-shmobile/pm-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/pm-sh7372.c
+++ linux/arch/arm/mach-shmobile/pm-sh7372.c
@@ -101,8 +101,8 @@ static int pd_power_down(struct generic_
}
if (!sh7372_pd->no_debug)
- pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
- mask, __raw_readl(PSTR));
+ pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
+ sh7372_pd->name, mask, __raw_readl(PSTR));
return 0;
}
@@ -133,8 +133,8 @@ static int __pd_power_up(struct sh7372_p
ret = -EIO;
if (!sh7372_pd->no_debug)
- pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
- mask, __raw_readl(PSTR));
+ pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
+ sh7372_pd->name, mask, __raw_readl(PSTR));
out:
if (ret = 0 && sh7372_pd->resume && do_resume)
@@ -207,6 +207,7 @@ void sh7372_init_pm_domain(struct sh7372
struct dev_power_governor *gov = sh7372_pd->gov;
pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
+ genpd->name = sh7372_pd->name;
genpd->dev_ops.stop = sh7372_stop_dev;
genpd->dev_ops.start = sh7372_start_dev;
genpd->dev_ops.active_wakeup = pd_active_wakeup;
@@ -233,18 +234,22 @@ void sh7372_pm_add_subdomain(struct sh73
}
struct sh7372_pm_domain sh7372_a4lc = {
+ .name = "A4LC",
.bit_shift = 1,
};
struct sh7372_pm_domain sh7372_a4mp = {
+ .name = "A4MP",
.bit_shift = 2,
};
struct sh7372_pm_domain sh7372_d4 = {
+ .name = "D4",
.bit_shift = 3,
};
struct sh7372_pm_domain sh7372_a4r = {
+ .name = "A4R",
.bit_shift = 5,
.gov = &sh7372_always_on_gov,
.suspend = sh7372_a4r_suspend,
@@ -253,14 +258,17 @@ struct sh7372_pm_domain sh7372_a4r = {
};
struct sh7372_pm_domain sh7372_a3rv = {
+ .name = "A3RV",
.bit_shift = 6,
};
struct sh7372_pm_domain sh7372_a3ri = {
+ .name = "A3RI",
.bit_shift = 8,
};
struct sh7372_pm_domain sh7372_a3sp = {
+ .name = "A3SP",
.bit_shift = 11,
.gov = &sh7372_always_on_gov,
.no_debug = true,
@@ -275,6 +283,7 @@ static void sh7372_a3sp_init(void)
}
struct sh7372_pm_domain sh7372_a3sg = {
+ .name = "A3SG",
.bit_shift = 13,
};
Index: linux/arch/arm/mach-shmobile/include/mach/sh7372.h
=================================--- linux.orig/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ linux/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -480,6 +480,7 @@ struct platform_device;
struct sh7372_pm_domain {
struct generic_pm_domain genpd;
struct dev_power_governor *gov;
+ char *name;
void (*suspend)(void);
void (*resume)(void);
unsigned int bit_shift;
^ permalink raw reply
* [PATCH 06/62] sh: remove the second argument of k[un]map_atomic()
From: Cong Wang @ 2011-11-27 5:26 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, Cong Wang, Paul Mundt, Stuart Menefy, linux-sh
In-Reply-To: <1322371662-26166-1-git-send-email-amwang@redhat.com>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
arch/sh/mm/cache-sh4.c | 4 ++--
arch/sh/mm/cache.c | 12 ++++++------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index 92eb986..112fea1 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -244,7 +244,7 @@ static void sh4_flush_cache_page(void *args)
if (map_coherent)
vaddr = kmap_coherent(page, address);
else
- vaddr = kmap_atomic(page, KM_USER0);
+ vaddr = kmap_atomic(page);
address = (unsigned long)vaddr;
}
@@ -259,7 +259,7 @@ static void sh4_flush_cache_page(void *args)
if (map_coherent)
kunmap_coherent(vaddr);
else
- kunmap_atomic(vaddr, KM_USER0);
+ kunmap_atomic(vaddr);
}
}
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index 5a580ea..616966a 100644
--- a/arch/sh/mm/cache.c
+++ b/arch/sh/mm/cache.c
@@ -95,7 +95,7 @@ void copy_user_highpage(struct page *to, struct page *from,
{
void *vfrom, *vto;
- vto = kmap_atomic(to, KM_USER1);
+ vto = kmap_atomic(to);
if (boot_cpu_data.dcache.n_aliases && page_mapped(from) &&
test_bit(PG_dcache_clean, &from->flags)) {
@@ -103,16 +103,16 @@ void copy_user_highpage(struct page *to, struct page *from,
copy_page(vto, vfrom);
kunmap_coherent(vfrom);
} else {
- vfrom = kmap_atomic(from, KM_USER0);
+ vfrom = kmap_atomic(from);
copy_page(vto, vfrom);
- kunmap_atomic(vfrom, KM_USER0);
+ kunmap_atomic(vfrom);
}
if (pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK) ||
(vma->vm_flags & VM_EXEC))
__flush_purge_region(vto, PAGE_SIZE);
- kunmap_atomic(vto, KM_USER1);
+ kunmap_atomic(vto);
/* Make sure this page is cleared on other CPU's too before using it */
smp_wmb();
}
@@ -120,14 +120,14 @@ EXPORT_SYMBOL(copy_user_highpage);
void clear_user_highpage(struct page *page, unsigned long vaddr)
{
- void *kaddr = kmap_atomic(page, KM_USER0);
+ void *kaddr = kmap_atomic(page);
clear_page(kaddr);
if (pages_do_alias((unsigned long)kaddr, vaddr & PAGE_MASK))
__flush_purge_region(kaddr, PAGE_SIZE);
- kunmap_atomic(kaddr, KM_USER0);
+ kunmap_atomic(kaddr);
}
EXPORT_SYMBOL(clear_user_highpage);
--
1.7.4.4
^ permalink raw reply related
* Re: Dreamcast build broken
From: Paul Cercueil @ 2011-11-25 16:24 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <4EC81660.3010109@gmail.com>
Le 24/11/2011 08:29, Paul Mundt a écrit :
> On Tue, Nov 22, 2011 at 01:02:56PM +0100, Paul Cercueil wrote:
>> Hi,
>>
>> The commit which breaks the dreamcast build is the commit
>> 37b7a97884ba64bf7d403351ac2a9476ab4f1bba :
>> sh: machvec IO death.
>>
> It builds fine for me. You will actually have to supply the build error
> you are experiencing if you expect any further assistance, however.
Hi,
I am able to compile the Linux kernel, the problem is not the compilation.
I do get the "vmlinux" binary once the compilation completes.
However, starting from commit 37b7a97884ba64bf7d403351ac2a9476ab4f1bba
and up to the latest vanilla Linux 3.1,
the vmlinux binary won't start on my dreamcast or on the lxdream emulator.
^ permalink raw reply
* Re: sh-sci CTS problem
From: Takashi Yoshii @ 2011-11-25 5:07 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <OFB48B001D.3AA44CAE-ON80257950.0037E14A-80257950.0039B579@eu.necel.com>
Hi,
> I guess the right thing to do is add an extra field to struct
> plat_sci_port to indicate support for RTS/CTS?
Right. I guess each real pin manipulation will be handled like sci_init_pins().
On the other hand, I don't think there is much things to do here for channels
that does *not* support control lines. get_mctrl() does not provide the function
to tell "not supported" condition anyway.
I think that should be implemented in sci_set_termios().
Currently, it sets SCFCR.MCE regardless of the HW function, and does not
fix any bits in c_flags. We can negate CRTSCTS in termios->c_cflag there,
unless (s->cfg->flags & UPF_xx) or something.
Does anyone know good flags or constant definitions?
/yoshii
^ permalink raw reply
* [PATCH 2/2 v5] net/smsc911x: Add regulator support
From: Robert Marklund @ 2011-11-24 11:03 UTC (permalink / raw)
To: netdev, Steve Glendinning
Cc: Mathieu Poirier, Robert Marklund, Paul Mundt, linux-sh,
Sascha Hauer, Tony Lindgren, linux-omap, Mike Frysinger,
uclinux-dist-devel, Linus Walleij
Add some basic regulator support for the power pins, as needed
by the ST-Ericsson Snowball platform that powers up the SMSC911
chip using an external regulator.
Platforms that use regulators and the smsc911x and have no defined
regulator for the smsc911x and claim complete regulator
constraints with no dummy regulators will need to provide it, for
example using a fixed voltage regulator. It appears that this may
affect (apart from Ux500 Snowball) possibly these archs/machines
that from some grep:s appear to define both CONFIG_SMSC911X and
CONFIG_REGULATOR:
- ARM Freescale mx3 and OMAP 2 plus, Raumfeld machines
- Blackfin
- Super-H
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: linux-sh@vger.kernel.org
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Tony Lindgren <tony@atomide.com>
Cc: linux-omap@vger.kernel.org
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: uclinux-dist-devel@blackfin.uclinux.org
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Robert Marklund <robert.marklund@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v4->v5:
- Split the enable_disable method on Mikes request.
ChangeLog v3->v4:
- Remove dual prints and old comment on Mike's request.
- Split the request_free fucntion on Mike and Sascha request.
ChangeLog v2->v3:
- Use bulk regulators on Mark's request.
- Add Cc-fileds to some possibly affected platforms.
ChangeLog v1->v2:
- Don't check for NULL regulators and error out properly if the
regulators can't be found. All platforms using the smsc911x
and the regulator framework simultaneously need to provide some
kind of regulator for it.
---
drivers/net/ethernet/smsc/smsc911x.c | 111 ++++++++++++++++++++++++++++++----
1 files changed, 100 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index 8843071..06d0df6 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -44,6 +44,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/bug.h>
@@ -88,6 +89,8 @@ struct smsc911x_ops {
unsigned int *buf, unsigned int wordcount);
};
+#define SMSC911X_NUM_SUPPLIES 2
+
struct smsc911x_data {
void __iomem *ioaddr;
@@ -138,6 +141,9 @@ struct smsc911x_data {
/* register access functions */
const struct smsc911x_ops *ops;
+
+ /* regulators */
+ struct regulator_bulk_data supplies[SMSC911X_NUM_SUPPLIES];
};
/* Easy access to information */
@@ -362,6 +368,76 @@ out:
spin_unlock_irqrestore(&pdata->dev_lock, flags);
}
+/*
+ * enable resources, currently just regulators.
+ */
+static int smsc911x_enable_resources(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct smsc911x_data *pdata = netdev_priv(ndev);
+ int ret = 0;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(pdata->supplies),
+ pdata->supplies);
+ if (ret)
+ netdev_err(ndev, "failed to enable regulators %d\n",
+ ret);
+ return ret;
+}
+
+/*
+ * disable resources, currently just regulators.
+ */
+static int smsc911x_disable_resources(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct smsc911x_data *pdata = netdev_priv(ndev);
+ int ret = 0;
+
+ ret = regulator_bulk_disable(ARRAY_SIZE(pdata->supplies),
+ pdata->supplies);
+ return ret;
+}
+
+/*
+ * Request resources, currently just regulators.
+ *
+ * The SMSC911x has two power pins: vddvario and vdd33a, in designs where
+ * these are not always-on we need to request regulators to be turned on
+ * before we can try to access the device registers.
+ */
+static int smsc911x_request_resources(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct smsc911x_data *pdata = netdev_priv(ndev);
+ int ret = 0;
+
+ /* Request regulators */
+ pdata->supplies[0].supply = "vdd33a";
+ pdata->supplies[1].supply = "vddvario";
+ ret = regulator_bulk_get(&pdev->dev,
+ ARRAY_SIZE(pdata->supplies),
+ pdata->supplies);
+ if (ret)
+ netdev_err(ndev, "couldn't get regulators %d\n",
+ ret);
+ return ret;
+}
+
+/*
+ * Free resources, currently just regulators.
+ *
+ */
+static void smsc911x_free_resources(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct smsc911x_data *pdata = netdev_priv(ndev);
+
+ /* Free regulators */
+ regulator_bulk_free(ARRAY_SIZE(pdata->supplies),
+ pdata->supplies);
+}
+
/* waits for MAC not busy, with timeout. Only called by smsc911x_mac_read
* and smsc911x_mac_write, so assumes mac_lock is held */
static int smsc911x_mac_complete(struct smsc911x_data *pdata)
@@ -2092,6 +2168,9 @@ static int __devexit smsc911x_drv_remove(struct platform_device *pdev)
iounmap(pdata->ioaddr);
+ (void)smsc911x_disable_resources(pdev);
+ smsc911x_free_resources(pdev);
+
free_netdev(dev);
return 0;
@@ -2218,10 +2297,20 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
pdata->dev = dev;
pdata->msg_enable = ((1 << debug) - 1);
+ platform_set_drvdata(pdev, dev);
+
+ retval = smsc911x_request_resources(pdev);
+ if (retval)
+ goto out_return_resources;
+
+ retval = smsc911x_enable_resources(pdev);
+ if (retval)
+ goto out_disable_resources;
+
if (pdata->ioaddr = NULL) {
SMSC_WARN(pdata, probe, "Error smsc911x base address invalid");
retval = -ENOMEM;
- goto out_free_netdev_2;
+ goto out_disable_resources;
}
retval = smsc911x_probe_config_dt(&pdata->config, np);
@@ -2233,7 +2322,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
if (retval) {
SMSC_WARN(pdata, probe, "Error smsc911x config not found");
- goto out_unmap_io_3;
+ goto out_disable_resources;
}
/* assume standard, non-shifted, access to HW registers */
@@ -2244,7 +2333,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
retval = smsc911x_init(dev);
if (retval < 0)
- goto out_unmap_io_3;
+ goto out_disable_resources;
/* configure irq polarity and type before connecting isr */
if (pdata->config.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH)
@@ -2264,15 +2353,13 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
if (retval) {
SMSC_WARN(pdata, probe,
"Unable to claim requested irq: %d", dev->irq);
- goto out_unmap_io_3;
+ goto out_free_irq;
}
- platform_set_drvdata(pdev, dev);
-
retval = register_netdev(dev);
if (retval) {
SMSC_WARN(pdata, probe, "Error %i registering device", retval);
- goto out_unset_drvdata_4;
+ goto out_free_irq;
} else {
SMSC_TRACE(pdata, probe,
"Network interface: \"%s\"", dev->name);
@@ -2321,12 +2408,14 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
out_unregister_netdev_5:
unregister_netdev(dev);
-out_unset_drvdata_4:
- platform_set_drvdata(pdev, NULL);
+out_free_irq:
free_irq(dev->irq, dev);
-out_unmap_io_3:
+out_disable_resources:
+ (void)smsc911x_disable_resources(pdev);
+out_return_resources:
+ smsc911x_free_resources(pdev);
+ platform_set_drvdata(pdev, NULL);
iounmap(pdata->ioaddr);
-out_free_netdev_2:
free_netdev(dev);
out_release_io_1:
release_mem_region(res->start, resource_size(res));
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] ARM: Kota2 mach-type update fix
From: Russell King - ARM Linux @ 2011-11-24 10:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87zkflg999.wl%kuninori.morimoto.gx@renesas.com>
On Thu, Nov 24, 2011 at 01:28:06AM -0800, Kuninori Morimoto wrote:
>
> Hi Paul
>
> > > >> From: Magnus Damm <damm@opensource.se>
> > > >>
> > > >> This patch adds kota2 to the in-kernel ARM mach-type file.
> > > >>
> > > >> Basic board support is included in 3.2-rc and the mach-type
> > > >> has been registered in the ARM machine repository as
> > > >>
> > > >> 3616 Renesas SH-Mobile kota2.x Board kota2 Yusuke Goda mainlined
> > > >>
> > > >> The file arch/arm/tools/mach-types is however missing Kota2
> > > >> which makes build of sh73a0 based boards fail with:
> > > >>
> > > >> arch/arm/mach-shmobile/platsmp.c: In function 'shmobile_smp_get_core_count':
> > > >> arch/arm/mach-shmobile/platsmp.c:28:2: error: implicit declaration of function 'machine_is_kota2'
> > > >> make[1]: *** [arch/arm/mach-shmobile/platsmp.o] Error 1
> > > >>
> > > >> arch/arm/mach-shmobile/board-kota2.c:448:136: error: 'MACH_TYPE_KOTA2' undeclared here (not in a function)
> > > >> make[1]: *** [arch/arm/mach-shmobile/board-kota2.o] Error 1
> > > >> make: *** [arch/arm/mach-shmobile] Error 2
> > > >>
> > > >> Signed-off-by: Magnus Damm <damm@opensource.se>
> > > >> ---
> (snip)
> > > Russell, do you mind if we update the mach-type file to include Kota2?
> > > It's already registered via the web interface.
> > >
> > I'll add it with Russell's Acked-by, otherwise we'll simply have to wait
> > for the next batch of mach-types updates.
>
> Can I add A1 bonito mach-type too?
> I can not find it either
>
>
> 3623 Renesas R-Mobile A1 EVB bonito Kuninori Morimoto
No, because it's not in the kernel source.
^ permalink raw reply
* Re: SH2a Write-back cache issue
From: Andrea Baldini @ 2011-11-24 9:43 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <201111221415.22367.andrea.baldini@spesonline.com>
> In our setup, the problem seems related to an LCD flickering, when the
> cache is setup in read-back mode we had an heavy flickering on the LCD,
> when in write-through it seems much less present, even though not
> completely absent. We tried many different setup for cache and DRAM, but
> found no solutions for it. Of course the problem is present in 2.6.17,
> 2.6.37-38, 3.0 and 3.1 kernels. We found just one situation where the
> flickering is nearly invisible, while reserving 2Mb of frame buffer - so
> placing the fb and the other kernel/code memory far each other. What is
> your problem and setup?
>
> Federico
Hi Federico,
Currently I'm working with a framebuffer on my custom board but the problem I
described occurs in a basic setup too (without frambuffer support and other not
essential stuff).
I found this problem when I was working with the Renesas demo board rsk7203.
I tried some kernels compiled with the board defconfig and a busybox built with
a basic configuration (using a toolchain which creates flat binaries).
With this setup I found that the timer interrupts were missed when executing
the busybox applets and it was very clear especially in shell loop scripts.
With some debug work I saw that the problem was located in the function i
mentioned in the first mail, that is flush_icache_range (you can find it in
cache-sh2a.c) which caused interrupts to be missed during its execution.
The flush_icache_range is called in some points of the kernel and one of them
is in the load_flat_file() which, in my case, is heavy used (having a flat
busybox).
Hope this helps to better understand the issue.
Andrea
--
Andrea Baldini
Elettronica di Processo
SPES. S.c.p.a
Via Lamberto Corsi, 43
60044 Fabriano (AN)
tel. +39 0732 25291
fax +39 0732 2529441
<mailto:andrea.baldini@spesonline.com> andrea.baldini@spesonline.com
<http://www.spesonline.com> www.spesonline.com
^ permalink raw reply
* Re: [PATCH] ARM: Kota2 mach-type update fix
From: Kuninori Morimoto @ 2011-11-24 9:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111124082342.GD32112@linux-sh.org>
Hi Paul
> > >> From: Magnus Damm <damm@opensource.se>
> > >>
> > >> This patch adds kota2 to the in-kernel ARM mach-type file.
> > >>
> > >> Basic board support is included in 3.2-rc and the mach-type
> > >> has been registered in the ARM machine repository as
> > >>
> > >> 3616 Renesas SH-Mobile kota2.x Board kota2 Yusuke Goda mainlined
> > >>
> > >> The file arch/arm/tools/mach-types is however missing Kota2
> > >> which makes build of sh73a0 based boards fail with:
> > >>
> > >> arch/arm/mach-shmobile/platsmp.c: In function 'shmobile_smp_get_core_count':
> > >> arch/arm/mach-shmobile/platsmp.c:28:2: error: implicit declaration of function 'machine_is_kota2'
> > >> make[1]: *** [arch/arm/mach-shmobile/platsmp.o] Error 1
> > >>
> > >> arch/arm/mach-shmobile/board-kota2.c:448:136: error: 'MACH_TYPE_KOTA2' undeclared here (not in a function)
> > >> make[1]: *** [arch/arm/mach-shmobile/board-kota2.o] Error 1
> > >> make: *** [arch/arm/mach-shmobile] Error 2
> > >>
> > >> Signed-off-by: Magnus Damm <damm@opensource.se>
> > >> ---
(snip)
> > Russell, do you mind if we update the mach-type file to include Kota2?
> > It's already registered via the web interface.
> >
> I'll add it with Russell's Acked-by, otherwise we'll simply have to wait
> for the next batch of mach-types updates.
Can I add A1 bonito mach-type too?
I can not find it either
3623 Renesas R-Mobile A1 EVB bonito Kuninori Morimoto
Best regards
---
Kuninori Morimoto
^ permalink raw reply
* Re: sh-sci CTS problem
From: phil.edworthy @ 2011-11-24 9:19 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <OFB48B001D.3AA44CAE-ON80257950.0037E14A-80257950.0039B579@eu.necel.com>
Hi Paul,
> > Commit 4480a688 is a problem for some devices. For example, on the
SH7203
> > some serial ports have RTS/CTS, but others don't.
> >
> > I guess the right thing to do is add an extra field to struct
> > plat_sci_port to indicate support for RTS/CTS?
> >
> Looking at the data sheets, I think we're probably going to have to do
> something like that, as well as overhaul sci_get/set_mctrl(). There are
> certainly fewer ports that actually support RTS/CTS in hardware than
> those that don't, so the mctrl information is more often than not
> completely bogus.
>
> Could you elaborate what precisely you are encountering as a result of
> the CTS reporting on SH7203? It was initially added as a correctness
> fix to complement the existing RTS reporting, so it would be interesting
> to know what your use case is or what ill effects fell out as a result.
I am not sure if this actually causing any problems at all, this is
probably a wild goose chase. I suspect that enabling RTS/CTS on ports that
don't have these wired up won't change their behaviour.
I am trying to track down an issue with serial that has been around for a
very long time. Actually this work is on SH7264 but the same issues are on
at least SH7201 and SH7203 devices. Receiving data over serial often fails
with framing and overrun errors. I fixed a few things locally, such as the
multiplexed isr doesn't check that the interrupt source was an overrun,
and the overrun handling needs some tweaking. However these are just
addressing the symptoms, not the cause.
Phil
^ permalink raw reply
* Re: sh-sci CTS problem
From: Paul Mundt @ 2011-11-24 9:03 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <OFB48B001D.3AA44CAE-ON80257950.0037E14A-80257950.0039B579@eu.necel.com>
On Tue, Nov 22, 2011 at 10:32:41AM +0000, phil.edworthy@renesas.com wrote:
> Hi Yoshii-san, Paul,
>
> Commit 4480a688 is a problem for some devices. For example, on the SH7203
> some serial ports have RTS/CTS, but others don't.
>
> I guess the right thing to do is add an extra field to struct
> plat_sci_port to indicate support for RTS/CTS?
>
Looking at the data sheets, I think we're probably going to have to do
something like that, as well as overhaul sci_get/set_mctrl(). There are
certainly fewer ports that actually support RTS/CTS in hardware than
those that don't, so the mctrl information is more often than not
completely bogus.
Could you elaborate what precisely you are encountering as a result of
the CTS reporting on SH7203? It was initially added as a correctness
fix to complement the existing RTS reporting, so it would be interesting
to know what your use case is or what ill effects fell out as a result.
^ permalink raw reply
* Re: [PATCH] ARM: mach-shmobile: Kota2 PINT fix
From: Paul Mundt @ 2011-11-24 8:36 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <20111122061557.30983.75780.sendpatchset@w520>
On Tue, Nov 22, 2011 at 03:15:57PM +0900, Magnus Damm wrote:
> Support PINT on sh73a0 and Kota2 using INTC PINT macros.
>
> With this patch applied the Kota2 ethernet is handled
> through one of the chained sh73a0 PINT interrupt controllers.
>
> sh73a0 PINT support is included in 3.2-rc but the Kota2 board
> code does not make use of this shared code base without this
> patch. Without this patch kota2 on-board ethernet is broken.
On Tue, Nov 22, 2011 at 03:23:17PM +0900, Magnus Damm wrote:
> Keep the ZB clock enabled on sh73a0 to allow the BSC
> to access external peripherals hooked up to CS signals.
>
> This is needed to unbreak Ethernet support on sh73a0 boards
> such as AG5EVM and Kota2 together with the following patch:
>
> 794d78f drivers: sh: late disabling of clocks V2
On Tue, Nov 22, 2011 at 03:29:54PM +0900, Magnus Damm wrote:
> Fix IRQ support on the Kota2 board. The sh73a0 and the Kota2
> board make use of the ARM GIC hardware block as main interrupt
> controller. The following commit changed the default behaviour
> for non-device tree platforms and broke Kota2 irq support:
On Tue, Nov 22, 2011 at 03:31:40PM +0900, Magnus Damm wrote:
> Fix IRQ support on the AG5EVM board. The sh73a0 and the AG5EVM
> board make use of the ARM GIC hardware block as main interrupt
> controller. The following commit changed the default behaviour
> for non-device tree platforms and broke AG5EVM irq support:
On Tue, Nov 22, 2011 at 03:44:58PM +0900, Magnus Damm wrote:
> This patch updates the Kota2 board support code to
> use the recently merged TPU LED driver whenever
> possible.
>
> The sh73a0 SoC has 5 TPU hardware blocks each with
> 4 timer channels which in theory allows a total of
> 20 LEDs to be controlled by "leds-renesas-tpu"
> driver instances. The Kota2 board has 4 LEDs connected
> to GPIO pins that also come with TPU pin functions, so
> this patch ties up these 4 LEDS and leaves the remaining
> 3 LEDS for the GPIO based LED driver.
All applied, thanks.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox