1*9fdf0c62Smpi /* $OpenBSD: moxtet.c,v 1.2 2021/10/24 17:52:26 mpi Exp $ */
2646ec6a7Spatrick /*
3646ec6a7Spatrick * Copyright (c) 2019 Patrick Wildt <patrick@blueri.se>
4646ec6a7Spatrick *
5646ec6a7Spatrick * Permission to use, copy, modify, and distribute this software for any
6646ec6a7Spatrick * purpose with or without fee is hereby granted, provided that the above
7646ec6a7Spatrick * copyright notice and this permission notice appear in all copies.
8646ec6a7Spatrick *
9646ec6a7Spatrick * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10646ec6a7Spatrick * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11646ec6a7Spatrick * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12646ec6a7Spatrick * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13646ec6a7Spatrick * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14646ec6a7Spatrick * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15646ec6a7Spatrick * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16646ec6a7Spatrick */
17646ec6a7Spatrick
18646ec6a7Spatrick #include <sys/param.h>
19646ec6a7Spatrick #include <sys/systm.h>
20646ec6a7Spatrick #include <sys/kernel.h>
21646ec6a7Spatrick #include <sys/device.h>
22646ec6a7Spatrick #include <sys/malloc.h>
23646ec6a7Spatrick
24646ec6a7Spatrick #include <dev/spi/spivar.h>
25646ec6a7Spatrick
26646ec6a7Spatrick #include <dev/ofw/openfirm.h>
27646ec6a7Spatrick #include <dev/ofw/ofw_gpio.h>
28646ec6a7Spatrick #include <dev/ofw/ofw_pinctrl.h>
29646ec6a7Spatrick
30646ec6a7Spatrick #define MOX_NMODULE 10
31646ec6a7Spatrick
32646ec6a7Spatrick #define MOX_CPU_EMMC 0x00
33646ec6a7Spatrick #define MOX_CPU_SD 0x10
34646ec6a7Spatrick
35646ec6a7Spatrick #define MOX_MODULE_SFP 0x01
36646ec6a7Spatrick #define MOX_MODULE_PCI 0x02
37646ec6a7Spatrick #define MOX_MODULE_TOPAZ 0x03
38646ec6a7Spatrick #define MOX_MODULE_PERIDOT 0x04
39646ec6a7Spatrick #define MOX_MODULE_USB3 0x05
40646ec6a7Spatrick #define MOX_MODULE_PASSPCI 0x06
41646ec6a7Spatrick
42646ec6a7Spatrick struct moxtet_softc {
43646ec6a7Spatrick struct device sc_dev;
44646ec6a7Spatrick int sc_node;
45646ec6a7Spatrick
46646ec6a7Spatrick spi_tag_t sc_spi_tag;
47646ec6a7Spatrick struct spi_config sc_spi_conf;
48646ec6a7Spatrick
49646ec6a7Spatrick int sc_nmodule;
50646ec6a7Spatrick };
51646ec6a7Spatrick
52646ec6a7Spatrick int moxtet_match(struct device *, void *, void *);
53646ec6a7Spatrick void moxtet_attach(struct device *, struct device *, void *);
54646ec6a7Spatrick int moxtet_detach(struct device *, int);
55646ec6a7Spatrick
56646ec6a7Spatrick int moxtet_read(struct moxtet_softc *, char *, size_t);
57646ec6a7Spatrick int moxtet_write(struct moxtet_softc *, char *, size_t);
58646ec6a7Spatrick
59*9fdf0c62Smpi const struct cfattach moxtet_ca = {
60646ec6a7Spatrick sizeof(struct moxtet_softc), moxtet_match, moxtet_attach, moxtet_detach
61646ec6a7Spatrick };
62646ec6a7Spatrick
63646ec6a7Spatrick struct cfdriver moxtet_cd = {
64646ec6a7Spatrick NULL, "moxtet", DV_DULL
65646ec6a7Spatrick };
66646ec6a7Spatrick
67646ec6a7Spatrick int
moxtet_match(struct device * parent,void * match,void * aux)68646ec6a7Spatrick moxtet_match(struct device *parent, void *match, void *aux)
69646ec6a7Spatrick {
70646ec6a7Spatrick struct spi_attach_args *sa = aux;
71646ec6a7Spatrick
72646ec6a7Spatrick if (strcmp(sa->sa_name, "cznic,moxtet") == 0)
73646ec6a7Spatrick return 1;
74646ec6a7Spatrick
75646ec6a7Spatrick return 0;
76646ec6a7Spatrick }
77646ec6a7Spatrick
78646ec6a7Spatrick void
moxtet_attach(struct device * parent,struct device * self,void * aux)79646ec6a7Spatrick moxtet_attach(struct device *parent, struct device *self, void *aux)
80646ec6a7Spatrick {
81646ec6a7Spatrick struct moxtet_softc *sc = (struct moxtet_softc *)self;
82646ec6a7Spatrick struct spi_attach_args *sa = aux;
83646ec6a7Spatrick uint8_t buf[MOX_NMODULE];
84646ec6a7Spatrick int i;
85646ec6a7Spatrick
86646ec6a7Spatrick sc->sc_spi_tag = sa->sa_tag;
87646ec6a7Spatrick sc->sc_node = *(int *)sa->sa_cookie;
88646ec6a7Spatrick
89646ec6a7Spatrick pinctrl_byname(sc->sc_node, "default");
90646ec6a7Spatrick
91646ec6a7Spatrick sc->sc_spi_conf.sc_bpw = 8;
92646ec6a7Spatrick sc->sc_spi_conf.sc_freq = OF_getpropint(sc->sc_node,
93646ec6a7Spatrick "spi-max-frequency", 0);
94646ec6a7Spatrick sc->sc_spi_conf.sc_cs = OF_getpropint(sc->sc_node, "reg", 0);
95646ec6a7Spatrick if (OF_getproplen(sc->sc_node, "spi-cpol") == 0)
96646ec6a7Spatrick sc->sc_spi_conf.sc_flags |= SPI_CONFIG_CPOL;
97646ec6a7Spatrick if (OF_getproplen(sc->sc_node, "spi-cpha") == 0)
98646ec6a7Spatrick sc->sc_spi_conf.sc_flags |= SPI_CONFIG_CPHA;
99646ec6a7Spatrick if (OF_getproplen(sc->sc_node, "spi-cs-high") == 0)
100646ec6a7Spatrick sc->sc_spi_conf.sc_flags |= SPI_CONFIG_CS_HIGH;
101646ec6a7Spatrick
102646ec6a7Spatrick if (moxtet_read(sc, buf, sizeof(buf))) {
103646ec6a7Spatrick printf(": can't read moxtet\n");
104646ec6a7Spatrick return;
105646ec6a7Spatrick }
106646ec6a7Spatrick
107646ec6a7Spatrick if (buf[0] == MOX_CPU_EMMC)
108646ec6a7Spatrick printf(": eMMC");
109646ec6a7Spatrick else if (buf[0] == MOX_CPU_SD)
110646ec6a7Spatrick printf(": SD");
111646ec6a7Spatrick else {
112646ec6a7Spatrick printf(": unknown\n");
113646ec6a7Spatrick return;
114646ec6a7Spatrick }
115646ec6a7Spatrick
116646ec6a7Spatrick for (i = 1; i < MOX_NMODULE; i++) {
117646ec6a7Spatrick if (buf[i] == 0xff)
118646ec6a7Spatrick break;
119646ec6a7Spatrick sc->sc_nmodule++;
120646ec6a7Spatrick switch (buf[i] & 0xf) {
121646ec6a7Spatrick case MOX_MODULE_SFP:
122646ec6a7Spatrick printf(", SFP");
123646ec6a7Spatrick break;
124646ec6a7Spatrick case MOX_MODULE_PCI:
125646ec6a7Spatrick printf(", mPCIe");
126646ec6a7Spatrick break;
127646ec6a7Spatrick case MOX_MODULE_TOPAZ:
128646ec6a7Spatrick printf(", 4x GbE");
129646ec6a7Spatrick break;
130646ec6a7Spatrick case MOX_MODULE_PERIDOT:
131646ec6a7Spatrick printf(", 8x GbE");
132646ec6a7Spatrick break;
133646ec6a7Spatrick case MOX_MODULE_USB3:
134646ec6a7Spatrick printf(", 4x USB 3.0");
135646ec6a7Spatrick break;
136646ec6a7Spatrick case MOX_MODULE_PASSPCI:
137646ec6a7Spatrick printf(", mPCIe (passthrough)");
138646ec6a7Spatrick break;
139646ec6a7Spatrick default:
140646ec6a7Spatrick printf(", unknown (0x%02x)", buf[i] & 0xf);
141646ec6a7Spatrick break;
142646ec6a7Spatrick }
143646ec6a7Spatrick }
144646ec6a7Spatrick
145646ec6a7Spatrick printf("\n");
146646ec6a7Spatrick }
147646ec6a7Spatrick
148646ec6a7Spatrick int
moxtet_detach(struct device * self,int flags)149646ec6a7Spatrick moxtet_detach(struct device *self, int flags)
150646ec6a7Spatrick {
151646ec6a7Spatrick return 0;
152646ec6a7Spatrick }
153646ec6a7Spatrick
154646ec6a7Spatrick int
moxtet_read(struct moxtet_softc * sc,char * buf,size_t len)155646ec6a7Spatrick moxtet_read(struct moxtet_softc *sc, char *buf, size_t len)
156646ec6a7Spatrick {
157646ec6a7Spatrick int error;
158646ec6a7Spatrick
159646ec6a7Spatrick spi_acquire_bus(sc->sc_spi_tag, 0);
160646ec6a7Spatrick spi_config(sc->sc_spi_tag, &sc->sc_spi_conf);
161646ec6a7Spatrick error = spi_read(sc->sc_spi_tag, buf, len);
162646ec6a7Spatrick spi_release_bus(sc->sc_spi_tag, 0);
163646ec6a7Spatrick return error;
164646ec6a7Spatrick }
165646ec6a7Spatrick
166646ec6a7Spatrick int
moxtet_write(struct moxtet_softc * sc,char * buf,size_t len)167646ec6a7Spatrick moxtet_write(struct moxtet_softc *sc, char *buf, size_t len)
168646ec6a7Spatrick {
169646ec6a7Spatrick int error;
170646ec6a7Spatrick
171646ec6a7Spatrick spi_acquire_bus(sc->sc_spi_tag, 0);
172646ec6a7Spatrick spi_config(sc->sc_spi_tag, &sc->sc_spi_conf);
173646ec6a7Spatrick error = spi_write(sc->sc_spi_tag, buf, len);
174646ec6a7Spatrick spi_release_bus(sc->sc_spi_tag, 0);
175646ec6a7Spatrick return error;
176646ec6a7Spatrick }
177