rs5c316_mainbus.c revision 1.1 1 /* $NetBSD: rs5c316_mainbus.c,v 1.1 2010/04/06 15:54:29 nonaka Exp $ */
2
3 /*-
4 * Copyright (c) 2009 NONAKA Kimihiro <nonaka (at) netbsd.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: rs5c316_mainbus.c,v 1.1 2010/04/06 15:54:29 nonaka Exp $");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/device.h>
35 #include <sys/kernel.h>
36
37 #include <dev/clock_subr.h>
38 #include <dev/ic/rs5c313var.h>
39
40 #include <machine/autoconf.h>
41
42 #include <sh3/devreg.h>
43 #include <sh3/pfcreg.h>
44
45 #include <evbsh3/ap_ms104_sh4/ap_ms104_sh4reg.h>
46 #include <evbsh3/ap_ms104_sh4/ap_ms104_sh4var.h>
47
48 /* chip access methods */
49 static void rtc_begin(struct rs5c313_softc *);
50 static void rtc_ce(struct rs5c313_softc *, int);
51 static void rtc_dir(struct rs5c313_softc *, int);
52 static void rtc_clk(struct rs5c313_softc *, int);
53 static int rtc_read(struct rs5c313_softc *);
54 static void rtc_write(struct rs5c313_softc *, int);
55
56 static struct rs5c313_ops rs5c316_mainbus_ops = {
57 .rs5c313_op_begin = rtc_begin,
58 .rs5c313_op_ce = rtc_ce,
59 .rs5c313_op_clk = rtc_clk,
60 .rs5c313_op_dir = rtc_dir,
61 .rs5c313_op_read = rtc_read,
62 .rs5c313_op_write = rtc_write,
63 };
64
65 /* autoconf glue */
66 static int rs5c316_mainbus_match(device_t, cfdata_t, void *);
67 static void rs5c316_mainbus_attach(device_t, device_t, void *);
68
69 CFATTACH_DECL_NEW(rs5c313_mainbus, sizeof(struct rs5c313_softc),
70 rs5c316_mainbus_match, rs5c316_mainbus_attach, NULL, NULL);
71
72 #define ndelay(x) delay(((x) + 999) / 1000)
73
74 static int
75 rs5c316_mainbus_match(device_t parent, cfdata_t cf, void *aux)
76 {
77 struct mainbus_attach_args *maa = (struct mainbus_attach_args *)aux;
78
79 if (strcmp(maa->ma_name, "rs5c313rtc") != 0)
80 return 0;
81 return 1;
82 }
83
84
85 static void
86 rs5c316_mainbus_attach(device_t parent, device_t self, void *aux)
87 {
88 struct rs5c313_softc *sc = device_private(self);
89 uint32_t reg;
90
91 sc->sc_dev = self;
92 sc->sc_model = MODEL_5C316;
93 sc->sc_ops = &rs5c316_mainbus_ops;
94
95 /* setup gpio pin */
96 reg = _reg_read_4(SH4_PCTRA);
97 reg &= ~(3 << (GPIO_PIN_RTC_CE * 2));
98 reg |= (1 << (GPIO_PIN_RTC_CE * 2)); /* output */
99 reg &= ~(3 << (GPIO_PIN_RTC_SCLK * 2));
100 reg |= (1 << (GPIO_PIN_RTC_SCLK * 2)); /* output */
101 reg &= ~(3 << (GPIO_PIN_RTC_SIO * 2));
102 reg |= (1 << (GPIO_PIN_RTC_SIO * 2)); /* output */
103 _reg_write_4(SH4_PCTRA, reg);
104
105 rs5c313_attach(sc);
106 }
107
108 static void
109 rtc_begin(struct rs5c313_softc *sc)
110 {
111
112 /* nothing to do */
113 }
114
115 static void
116 rtc_ce(struct rs5c313_softc *sc, int onoff)
117 {
118 uint16_t
119
120 reg = _reg_read_2(SH4_PDTRA);
121 if (onoff) {
122 reg |= (1 << GPIO_PIN_RTC_CE);
123 } else {
124 reg &= ~(1 << GPIO_PIN_RTC_CE);
125 }
126 _reg_write_2(SH4_PDTRA, reg);
127 ndelay(600);
128 }
129
130 static void
131 rtc_clk(struct rs5c313_softc *sc, int onoff)
132 {
133 uint16_t reg;
134
135 reg = _reg_read_2(SH4_PDTRA);
136 if (onoff) {
137 reg |= (1 << GPIO_PIN_RTC_SCLK);
138 } else {
139 reg &= ~(1 << GPIO_PIN_RTC_SCLK);
140 }
141 _reg_write_2(SH4_PDTRA, reg);
142 }
143
144 static void
145 rtc_dir(struct rs5c313_softc *sc, int output)
146 {
147 uint32_t reg;
148
149 reg = _reg_read_4(SH4_PCTRA);
150 reg &= ~(3 << (GPIO_PIN_RTC_SIO * 2)); /* input */
151 if (output) {
152 reg |= (1 << (GPIO_PIN_RTC_SIO * 2)); /* output */
153 }
154 _reg_write_4(SH4_PCTRA, reg);
155 }
156
157 static int
158 rtc_read(struct rs5c313_softc *sc)
159 {
160 int bit;
161
162 ndelay(300);
163
164 bit = (_reg_read_2(SH4_PDTRA) & (1 << GPIO_PIN_RTC_SIO)) ? 1 : 0;
165
166 rtc_clk(sc, 0);
167 ndelay(300);
168 rtc_clk(sc, 1);
169
170 return bit;
171 }
172
173 static void
174 rtc_write(struct rs5c313_softc *sc, int bit)
175 {
176 uint16_t reg;
177
178 reg = _reg_read_2(SH4_PDTRA);
179 if (bit)
180 reg |= (1 << GPIO_PIN_RTC_SIO);
181 else
182 reg &= ~(1 << GPIO_PIN_RTC_SIO);
183 _reg_write_2(SH4_PDTRA, reg);
184
185 ndelay(300);
186
187 rtc_clk(sc, 0);
188 ndelay(300);
189 rtc_clk(sc, 1);
190 }
191