xref: /openbsd/sys/dev/fdt/moxtet.c (revision 9fdf0c62)
1 /* $OpenBSD: moxtet.c,v 1.2 2021/10/24 17:52:26 mpi Exp $ */
2 /*
3  * Copyright (c) 2019 Patrick Wildt <patrick@blueri.se>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/kernel.h>
21 #include <sys/device.h>
22 #include <sys/malloc.h>
23 
24 #include <dev/spi/spivar.h>
25 
26 #include <dev/ofw/openfirm.h>
27 #include <dev/ofw/ofw_gpio.h>
28 #include <dev/ofw/ofw_pinctrl.h>
29 
30 #define MOX_NMODULE		10
31 
32 #define MOX_CPU_EMMC		0x00
33 #define MOX_CPU_SD		0x10
34 
35 #define MOX_MODULE_SFP		0x01
36 #define MOX_MODULE_PCI		0x02
37 #define MOX_MODULE_TOPAZ	0x03
38 #define MOX_MODULE_PERIDOT	0x04
39 #define MOX_MODULE_USB3		0x05
40 #define MOX_MODULE_PASSPCI	0x06
41 
42 struct moxtet_softc {
43 	struct device		 sc_dev;
44 	int			 sc_node;
45 
46 	spi_tag_t		 sc_spi_tag;
47 	struct spi_config	 sc_spi_conf;
48 
49 	int			 sc_nmodule;
50 };
51 
52 int	 moxtet_match(struct device *, void *, void *);
53 void	 moxtet_attach(struct device *, struct device *, void *);
54 int	 moxtet_detach(struct device *, int);
55 
56 int	 moxtet_read(struct moxtet_softc *, char *, size_t);
57 int	 moxtet_write(struct moxtet_softc *, char *, size_t);
58 
59 const struct cfattach moxtet_ca = {
60 	sizeof(struct moxtet_softc), moxtet_match, moxtet_attach, moxtet_detach
61 };
62 
63 struct cfdriver moxtet_cd = {
64 	NULL, "moxtet", DV_DULL
65 };
66 
67 int
moxtet_match(struct device * parent,void * match,void * aux)68 moxtet_match(struct device *parent, void *match, void *aux)
69 {
70 	struct spi_attach_args *sa = aux;
71 
72 	if (strcmp(sa->sa_name, "cznic,moxtet") == 0)
73 		return 1;
74 
75 	return 0;
76 }
77 
78 void
moxtet_attach(struct device * parent,struct device * self,void * aux)79 moxtet_attach(struct device *parent, struct device *self, void *aux)
80 {
81 	struct moxtet_softc *sc = (struct moxtet_softc *)self;
82 	struct spi_attach_args *sa = aux;
83 	uint8_t buf[MOX_NMODULE];
84 	int i;
85 
86 	sc->sc_spi_tag = sa->sa_tag;
87 	sc->sc_node = *(int *)sa->sa_cookie;
88 
89 	pinctrl_byname(sc->sc_node, "default");
90 
91 	sc->sc_spi_conf.sc_bpw = 8;
92 	sc->sc_spi_conf.sc_freq = OF_getpropint(sc->sc_node,
93 	    "spi-max-frequency", 0);
94 	sc->sc_spi_conf.sc_cs = OF_getpropint(sc->sc_node, "reg", 0);
95 	if (OF_getproplen(sc->sc_node, "spi-cpol") == 0)
96 		sc->sc_spi_conf.sc_flags |= SPI_CONFIG_CPOL;
97 	if (OF_getproplen(sc->sc_node, "spi-cpha") == 0)
98 		sc->sc_spi_conf.sc_flags |= SPI_CONFIG_CPHA;
99 	if (OF_getproplen(sc->sc_node, "spi-cs-high") == 0)
100 		sc->sc_spi_conf.sc_flags |= SPI_CONFIG_CS_HIGH;
101 
102 	if (moxtet_read(sc, buf, sizeof(buf))) {
103 		printf(": can't read moxtet\n");
104 		return;
105 	}
106 
107 	if (buf[0] == MOX_CPU_EMMC)
108 		printf(": eMMC");
109 	else if (buf[0] == MOX_CPU_SD)
110 		printf(": SD");
111 	else {
112 		printf(": unknown\n");
113 		return;
114 	}
115 
116 	for (i = 1; i < MOX_NMODULE; i++) {
117 		if (buf[i] == 0xff)
118 			break;
119 		sc->sc_nmodule++;
120 		switch (buf[i] & 0xf) {
121 		case MOX_MODULE_SFP:
122 			printf(", SFP");
123 			break;
124 		case MOX_MODULE_PCI:
125 			printf(", mPCIe");
126 			break;
127 		case MOX_MODULE_TOPAZ:
128 			printf(", 4x GbE");
129 			break;
130 		case MOX_MODULE_PERIDOT:
131 			printf(", 8x GbE");
132 			break;
133 		case MOX_MODULE_USB3:
134 			printf(", 4x USB 3.0");
135 			break;
136 		case MOX_MODULE_PASSPCI:
137 			printf(", mPCIe (passthrough)");
138 			break;
139 		default:
140 			printf(", unknown (0x%02x)", buf[i] & 0xf);
141 			break;
142 		}
143 	}
144 
145 	printf("\n");
146 }
147 
148 int
moxtet_detach(struct device * self,int flags)149 moxtet_detach(struct device *self, int flags)
150 {
151 	return 0;
152 }
153 
154 int
moxtet_read(struct moxtet_softc * sc,char * buf,size_t len)155 moxtet_read(struct moxtet_softc *sc, char *buf, size_t len)
156 {
157 	int error;
158 
159 	spi_acquire_bus(sc->sc_spi_tag, 0);
160 	spi_config(sc->sc_spi_tag, &sc->sc_spi_conf);
161 	error = spi_read(sc->sc_spi_tag, buf, len);
162 	spi_release_bus(sc->sc_spi_tag, 0);
163 	return error;
164 }
165 
166 int
moxtet_write(struct moxtet_softc * sc,char * buf,size_t len)167 moxtet_write(struct moxtet_softc *sc, char *buf, size_t len)
168 {
169 	int error;
170 
171 	spi_acquire_bus(sc->sc_spi_tag, 0);
172 	spi_config(sc->sc_spi_tag, &sc->sc_spi_conf);
173 	error = spi_write(sc->sc_spi_tag, buf, len);
174 	spi_release_bus(sc->sc_spi_tag, 0);
175 	return error;
176 }
177