aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/mfd/syscon/atmel-smc.h
blob: be6ebe64eebe1964573a2b963004a8055dff7abf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
 * Atmel SMC (Static Memory Controller) register offsets and bit definitions.
 *
 * Copyright (C) 2014 Atmel
 * Copyright (C) 2014 Free Electrons
 *
 * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef _LINUX_MFD_SYSCON_ATMEL_SMC_H_
#define _LINUX_MFD_SYSCON_ATMEL_SMC_H_

#include <linux/kernel.h>
#include <linux/regmap.h>

#define AT91SAM9_SMC_GENERIC		0x00
#define AT91SAM9_SMC_GENERIC_BLK_SZ	0x10

#define SAMA5_SMC_GENERIC		0x600
#define SAMA5_SMC_GENERIC_BLK_SZ	0x14

#define AT91SAM9_SMC_SETUP(o)		((o) + 0x00)
#define AT91SAM9_SMC_NWESETUP(x)	(x)
#define AT91SAM9_SMC_NCS_WRSETUP(x)	((x) << 8)
#define AT91SAM9_SMC_NRDSETUP(x)	((x) << 16)
#define AT91SAM9_SMC_NCS_NRDSETUP(x)	((x) << 24)

#define AT91SAM9_SMC_PULSE(o)		((o) + 0x04)
#define AT91SAM9_SMC_NWEPULSE(x)	(x)
#define AT91SAM9_SMC_NCS_WRPULSE(x)	((x) << 8)
#define AT91SAM9_SMC_NRDPULSE(x)	((x) << 16)
#define AT91SAM9_SMC_NCS_NRDPULSE(x)	((x) << 24)

#define AT91SAM9_SMC_CYCLE(o)		((o) + 0x08)
#define AT91SAM9_SMC_NWECYCLE(x)	(x)
#define AT91SAM9_SMC_NRDCYCLE(x)	((x) << 16)

#define AT91SAM9_SMC_MODE(o)		((o) + 0x0c)
#define SAMA5_SMC_MODE(o)		((o) + 0x10)
#define AT91_SMC_READMODE		BIT(0)
#define AT91_SMC_READMODE_NCS		(0 << 0)
#define AT91_SMC_READMODE_NRD		(1 << 0)
#define AT91_SMC_WRITEMODE		BIT(1)
#define AT91_SMC_WRITEMODE_NCS		(0 << 1)
#define AT91_SMC_WRITEMODE_NWE		(1 << 1)
#define AT91_SMC_EXNWMODE		GENMASK(5, 4)
#define AT91_SMC_EXNWMODE_DISABLE	(0 << 4)
#define AT91_SMC_EXNWMODE_FROZEN	(2 << 4)
#define AT91_SMC_EXNWMODE_READY		(3 << 4)
#define AT91_SMC_BAT			BIT(8)
#define AT91_SMC_BAT_SELECT		(0 << 8)
#define AT91_SMC_BAT_WRITE		(1 << 8)
#define AT91_SMC_DBW			GENMASK(13, 12)
#define AT91_SMC_DBW_8			(0 << 12)
#define AT91_SMC_DBW_16			(1 << 12)
#define AT91_SMC_DBW_32			(2 << 12)
#define AT91_SMC_TDF			GENMASK(19, 16)
#define AT91_SMC_TDF_(x)		((((x) - 1) << 16) & AT91_SMC_TDF)
#define AT91_SMC_TDF_MAX		16
#define AT91_SMC_TDFMODE_OPTIMIZED	BIT(20)
#define AT91_SMC_PMEN			BIT(24)
#define AT91_SMC_PS			GENMASK(29, 28)
#define AT91_SMC_PS_4			(0 << 28)
#define AT91_SMC_PS_8			(1 << 28)
#define AT91_SMC_PS_16			(2 << 28)
#define AT91_SMC_PS_32			(3 << 28)


/*
 * This function converts a setup timing expressed in nanoseconds into an
 * encoded value that can be written in the SMC_SETUP register.
 *
 * The following formula is described in atmel datasheets (section
 * "SMC Setup Register"):
 *
 * setup length = (128* SETUP[5] + SETUP[4:0])
 *
 * where setup length is the timing expressed in cycles.
 */
static inline u32 at91sam9_smc_setup_ns_to_cycles(unsigned int clk_rate,
						  u32 timing_ns)
{
	u32 clk_period = DIV_ROUND_UP(NSEC_PER_SEC, clk_rate);
	u32 coded_cycles = 0;
	u32 cycles;

	cycles = DIV_ROUND_UP(timing_ns, clk_period);
	if (cycles / 32) {
		coded_cycles |= 1 << 5;
		if (cycles < 128)
			cycles = 0;
	}

	coded_cycles |= cycles % 32;

	return coded_cycles;
}

/*
 * This function converts a pulse timing expressed in nanoseconds into an
 * encoded value that can be written in the SMC_PULSE register.
 *
 * The following formula is described in atmel datasheets (section
 * "SMC Pulse Register"):
 *
 * pulse length = (256* PULSE[6] + PULSE[5:0])
 *
 * where pulse length is the timing expressed in cycles.
 */
static inline u32 at91sam9_smc_pulse_ns_to_cycles(unsigned int clk_rate,
						  u32 timing_ns)
{
	u32 clk_period = DIV_ROUND_UP(NSEC_PER_SEC, clk_rate);
	u32 coded_cycles = 0;
	u32 cycles;

	cycles = DIV_ROUND_UP(timing_ns, clk_period);
	if (cycles / 64) {
		coded_cycles |= 1 << 6;
		if (cycles < 256)
			cycles = 0;
	}

	coded_cycles |= cycles % 64;

	return coded_cycles;
}

/*
 * This function converts a cycle timing expressed in nanoseconds into an
 * encoded value that can be written in the SMC_CYCLE register.
 *
 * The following formula is described in atmel datasheets (section
 * "SMC Cycle Register"):
 *
 * cycle length = (CYCLE[8:7]*256 + CYCLE[6:0])
 *
 * where cycle length is the timing expressed in cycles.
 */
static inline u32 at91sam9_smc_cycle_ns_to_cycles(unsigned int clk_rate,
						  u32 timing_ns)
{
	u32 clk_period = DIV_ROUND_UP(NSEC_PER_SEC, clk_rate);
	u32 coded_cycles = 0;
	u32 cycles;

	cycles = DIV_ROUND_UP(timing_ns, clk_period);
	if (cycles / 128) {
		coded_cycles = cycles / 256;
		cycles %= 256;
		if (cycles >= 128) {
			coded_cycles++;
			cycles = 0;
		}

		if (coded_cycles > 0x3) {
			coded_cycles = 0x3;
			cycles = 0x7f;
		}

		coded_cycles <<= 7;
	}

	coded_cycles |= cycles % 128;

	return coded_cycles;
}

#endif /* _LINUX_MFD_SYSCON_ATMEL_SMC_H_ */