summaryrefslogtreecommitdiff
path: root/include/asm-s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2007-02-05 23:18:19 +0300
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-02-05 23:18:19 +0300
commitd54853ef8cb17296ac7bce9c77430fb7c80532d0 (patch)
tree649e14d532e17231225a042a7c9a3d9207ad91ee /include/asm-s390
parentc1821c2e9711adc3cd298a16b7237c92a2cee78d (diff)
downloadlinux-d54853ef8cb17296ac7bce9c77430fb7c80532d0.tar.xz
[S390] ETR support.
This patch adds support for clock synchronization to an external time reference (ETR). The external time reference sends an oscillator signal and a synchronization signal every 2^20 microseconds to keep the TOD clocks of all connected servers in sync. For availability two ETR units can be connected to a machine. If the clock deviates for more than the sync-check tolerance all cpus get a machine check that indicates that the clock is out of sync. For the lovely details how to get the clock back in sync see the code below. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'include/asm-s390')
-rw-r--r--include/asm-s390/etr.h219
-rw-r--r--include/asm-s390/hardirq.h2
-rw-r--r--include/asm-s390/timex.h36
3 files changed, 256 insertions, 1 deletions
diff --git a/include/asm-s390/etr.h b/include/asm-s390/etr.h
new file mode 100644
index 000000000000..b498f19bb9a7
--- /dev/null
+++ b/include/asm-s390/etr.h
@@ -0,0 +1,219 @@
+/*
+ * include/asm-s390/etr.h
+ *
+ * Copyright IBM Corp. 2006
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+#ifndef __S390_ETR_H
+#define __S390_ETR_H
+
+/* ETR attachment control register */
+struct etr_eacr {
+ unsigned int e0 : 1; /* port 0 stepping control */
+ unsigned int e1 : 1; /* port 1 stepping control */
+ unsigned int _pad0 : 5; /* must be 00100 */
+ unsigned int dp : 1; /* data port control */
+ unsigned int p0 : 1; /* port 0 change recognition control */
+ unsigned int p1 : 1; /* port 1 change recognition control */
+ unsigned int _pad1 : 3; /* must be 000 */
+ unsigned int ea : 1; /* ETR alert control */
+ unsigned int es : 1; /* ETR sync check control */
+ unsigned int sl : 1; /* switch to local control */
+} __attribute__ ((packed));
+
+/* Port state returned by steai */
+enum etr_psc {
+ etr_psc_operational = 0,
+ etr_psc_semi_operational = 1,
+ etr_psc_protocol_error = 4,
+ etr_psc_no_symbols = 8,
+ etr_psc_no_signal = 12,
+ etr_psc_pps_mode = 13
+};
+
+/* Logical port state returned by stetr */
+enum etr_lpsc {
+ etr_lpsc_operational_step = 0,
+ etr_lpsc_operational_alt = 1,
+ etr_lpsc_semi_operational = 2,
+ etr_lpsc_protocol_error = 4,
+ etr_lpsc_no_symbol_sync = 8,
+ etr_lpsc_no_signal = 12,
+ etr_lpsc_pps_mode = 13
+};
+
+/* ETR status words */
+struct etr_esw {
+ struct etr_eacr eacr; /* attachment control register */
+ unsigned int y : 1; /* stepping mode */
+ unsigned int _pad0 : 5; /* must be 00000 */
+ unsigned int p : 1; /* stepping port number */
+ unsigned int q : 1; /* data port number */
+ unsigned int psc0 : 4; /* port 0 state code */
+ unsigned int psc1 : 4; /* port 1 state code */
+} __attribute__ ((packed));
+
+/* Second level data register status word */
+struct etr_slsw {
+ unsigned int vv1 : 1; /* copy of validity bit data frame 1 */
+ unsigned int vv2 : 1; /* copy of validity bit data frame 2 */
+ unsigned int vv3 : 1; /* copy of validity bit data frame 3 */
+ unsigned int vv4 : 1; /* copy of validity bit data frame 4 */
+ unsigned int _pad0 : 19; /* must by all zeroes */
+ unsigned int n : 1; /* EAF port number */
+ unsigned int v1 : 1; /* validity bit ETR data frame 1 */
+ unsigned int v2 : 1; /* validity bit ETR data frame 2 */
+ unsigned int v3 : 1; /* validity bit ETR data frame 3 */
+ unsigned int v4 : 1; /* validity bit ETR data frame 4 */
+ unsigned int _pad1 : 4; /* must be 0000 */
+} __attribute__ ((packed));
+
+/* ETR data frames */
+struct etr_edf1 {
+ unsigned int u : 1; /* untuned bit */
+ unsigned int _pad0 : 1; /* must be 0 */
+ unsigned int r : 1; /* service request bit */
+ unsigned int _pad1 : 4; /* must be 0000 */
+ unsigned int a : 1; /* time adjustment bit */
+ unsigned int net_id : 8; /* ETR network id */
+ unsigned int etr_id : 8; /* id of ETR which sends data frames */
+ unsigned int etr_pn : 8; /* port number of ETR output port */
+} __attribute__ ((packed));
+
+struct etr_edf2 {
+ unsigned int etv : 32; /* Upper 32 bits of TOD. */
+} __attribute__ ((packed));
+
+struct etr_edf3 {
+ unsigned int rc : 8; /* failure reason code */
+ unsigned int _pad0 : 3; /* must be 000 */
+ unsigned int c : 1; /* ETR coupled bit */
+ unsigned int tc : 4; /* ETR type code */
+ unsigned int blto : 8; /* biased local time offset */
+ /* (blto - 128) * 15 = minutes */
+ unsigned int buo : 8; /* biased utc offset */
+ /* (buo - 128) = leap seconds */
+} __attribute__ ((packed));
+
+struct etr_edf4 {
+ unsigned int ed : 8; /* ETS device dependent data */
+ unsigned int _pad0 : 1; /* must be 0 */
+ unsigned int buc : 5; /* biased ut1 correction */
+ /* (buc - 16) * 0.1 seconds */
+ unsigned int em : 6; /* ETS error magnitude */
+ unsigned int dc : 6; /* ETS drift code */
+ unsigned int sc : 6; /* ETS steering code */
+} __attribute__ ((packed));
+
+/*
+ * ETR attachment information block, two formats
+ * format 1 has 4 reserved words with a size of 64 bytes
+ * format 2 has 16 reserved words with a size of 96 bytes
+ */
+struct etr_aib {
+ struct etr_esw esw;
+ struct etr_slsw slsw;
+ unsigned long long tsp;
+ struct etr_edf1 edf1;
+ struct etr_edf2 edf2;
+ struct etr_edf3 edf3;
+ struct etr_edf4 edf4;
+ unsigned int reserved[16];
+} __attribute__ ((packed,aligned(8)));
+
+/* ETR interruption parameter */
+struct etr_interruption_parameter {
+ unsigned int _pad0 : 8;
+ unsigned int pc0 : 1; /* port 0 state change */
+ unsigned int pc1 : 1; /* port 1 state change */
+ unsigned int _pad1 : 3;
+ unsigned int eai : 1; /* ETR alert indication */
+ unsigned int _pad2 : 18;
+} __attribute__ ((packed));
+
+/* Query TOD offset result */
+struct etr_ptff_qto {
+ unsigned long long physical_clock;
+ unsigned long long tod_offset;
+ unsigned long long logical_tod_offset;
+ unsigned long long tod_epoch_difference;
+} __attribute__ ((packed));
+
+/* Inline assembly helper functions */
+static inline int etr_setr(struct etr_eacr *ctrl)
+{
+ int rc = -ENOSYS;
+
+ asm volatile(
+ " .insn s,0xb2160000,0(%2)\n"
+ "0: la %0,0\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "+d" (rc) : "m" (*ctrl), "a" (ctrl));
+ return rc;
+}
+
+/* Stores a format 1 aib with 64 bytes */
+static inline int etr_stetr(struct etr_aib *aib)
+{
+ int rc = -ENOSYS;
+
+ asm volatile(
+ " .insn s,0xb2170000,0(%2)\n"
+ "0: la %0,0\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "+d" (rc) : "m" (*aib), "a" (aib));
+ return rc;
+}
+
+/* Stores a format 2 aib with 96 bytes for specified port */
+static inline int etr_steai(struct etr_aib *aib, unsigned int func)
+{
+ register unsigned int reg0 asm("0") = func;
+ int rc = -ENOSYS;
+
+ asm volatile(
+ " .insn s,0xb2b30000,0(%2)\n"
+ "0: la %0,0\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "+d" (rc) : "m" (*aib), "a" (aib), "d" (reg0));
+ return rc;
+}
+
+/* Function codes for the steai instruction. */
+#define ETR_STEAI_STEPPING_PORT 0x10
+#define ETR_STEAI_ALTERNATE_PORT 0x11
+#define ETR_STEAI_PORT_0 0x12
+#define ETR_STEAI_PORT_1 0x13
+
+static inline int etr_ptff(void *ptff_block, unsigned int func)
+{
+ register unsigned int reg0 asm("0") = func;
+ register unsigned long reg1 asm("1") = (unsigned long) ptff_block;
+ int rc = -ENOSYS;
+
+ asm volatile(
+ " .word 0x0104\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (rc), "=m" (ptff_block)
+ : "d" (reg0), "d" (reg1), "m" (ptff_block) : "cc");
+ return rc;
+}
+
+/* Function codes for the ptff instruction. */
+#define ETR_PTFF_QAF 0x00 /* query available functions */
+#define ETR_PTFF_QTO 0x01 /* query tod offset */
+#define ETR_PTFF_QSI 0x02 /* query steering information */
+#define ETR_PTFF_ATO 0x40 /* adjust tod offset */
+#define ETR_PTFF_STO 0x41 /* set tod offset */
+#define ETR_PTFF_SFS 0x42 /* set fine steering rate */
+#define ETR_PTFF_SGS 0x43 /* set gross steering rate */
+
+/* Functions needed by the machine check handler */
+extern void etr_switch_to_local(void);
+extern void etr_sync_check(void);
+
+#endif /* __S390_ETR_H */
diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h
index c2f6a8782d31..31beb18cb3d1 100644
--- a/include/asm-s390/hardirq.h
+++ b/include/asm-s390/hardirq.h
@@ -32,6 +32,6 @@ typedef struct {
#define HARDIRQ_BITS 8
-extern void account_ticks(void);
+extern void account_ticks(u64 time);
#endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-s390/timex.h b/include/asm-s390/timex.h
index 9ee5d8013796..5cbd55cb40ce 100644
--- a/include/asm-s390/timex.h
+++ b/include/asm-s390/timex.h
@@ -11,6 +11,41 @@
#ifndef _ASM_S390_TIMEX_H
#define _ASM_S390_TIMEX_H
+/* Inline functions for clock register access. */
+static inline int set_clock(__u64 time)
+{
+ int cc;
+
+ asm volatile(
+ " sck 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (cc) : "m" (time), "a" (&time) : "cc");
+ return cc;
+}
+
+static inline int store_clock(__u64 *time)
+{
+ int cc;
+
+ asm volatile(
+ " stck 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (cc), "=m" (*time) : "a" (time) : "cc");
+ return cc;
+}
+
+static inline void set_clock_comparator(__u64 time)
+{
+ asm volatile("sckc 0(%1)" : : "m" (time), "a" (&time));
+}
+
+static inline void store_clock_comparator(__u64 *time)
+{
+ asm volatile("stckc 0(%1)" : "=m" (*time) : "a" (time));
+}
+
#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
typedef unsigned long long cycles_t;
@@ -32,6 +67,7 @@ static inline cycles_t get_cycles(void)
return (cycles_t) get_clock() >> 2;
}
+int get_sync_clock(unsigned long long *clock);
void init_cpu_timer(void);
#endif