xref: /openbsd/sys/dev/fdt/sfp.c (revision e5dd7070)
1 /* $OpenBSD: sfp.c,v 1.1 2019/09/07 13:32:36 patrick 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 
23 #include <net/if.h>
24 
25 #include <machine/bus.h>
26 #include <machine/fdt.h>
27 
28 #include <dev/i2c/i2cvar.h>
29 #include <dev/ofw/openfirm.h>
30 #include <dev/ofw/ofw_gpio.h>
31 #include <dev/ofw/ofw_misc.h>
32 
33 struct sfp_softc {
34 	struct device		 sc_dev;
35 	i2c_tag_t		 sc_tag;
36 	int			 sc_node;
37 
38 	struct sfp_device	 sc_sd;
39 };
40 
41 int	 sfp_match(struct device *, void *, void *);
42 void	 sfp_attach(struct device *, struct device *, void *);
43 int	 sfp_detach(struct device *, int);
44 
45 int	 sfp_i2c_get_sffpage(void *, struct if_sffpage *);
46 
47 struct cfattach sfp_ca = {
48 	sizeof(struct sfp_softc), sfp_match, sfp_attach, sfp_detach,
49 };
50 
51 struct cfdriver sfp_cd = {
52 	NULL, "sfp", DV_DULL
53 };
54 
55 int
56 sfp_match(struct device *parent, void *match, void *aux)
57 {
58 	struct fdt_attach_args *faa = aux;
59 
60 	return (OF_is_compatible(faa->fa_node, "sff,sfp") ||
61 	    OF_is_compatible(faa->fa_node, "sff,sfp+"));
62 }
63 
64 void
65 sfp_attach(struct device *parent, struct device *self, void *aux)
66 {
67 	struct sfp_softc *sc = (struct sfp_softc *)self;
68 	struct fdt_attach_args *faa = aux;
69 
70 	sc->sc_node = faa->fa_node;
71 	sc->sc_tag = i2c_byphandle(OF_getpropint(sc->sc_node,
72 	    "i2c-bus", 0));
73 
74 	if (sc->sc_tag == NULL) {
75 		printf(": can't get i2c bus\n");
76 		return;
77 	}
78 
79 	printf("\n");
80 
81 	sc->sc_sd.sd_node = faa->fa_node;
82 	sc->sc_sd.sd_cookie = sc;
83 	sc->sc_sd.sd_get_sffpage = sfp_i2c_get_sffpage;
84 	sfp_register(&sc->sc_sd);
85 }
86 
87 int
88 sfp_detach(struct device *self, int flags)
89 {
90 	return 0;
91 }
92 
93 int
94 sfp_i2c_get_sffpage(void *cookie, struct if_sffpage *sff)
95 {
96 	struct sfp_softc *sc = cookie;
97 	uint8_t reg = sff->sff_page;
98 
99 	iic_acquire_bus(sc->sc_tag, 0);
100 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
101 	    sff->sff_addr >> 1, &reg, sizeof(reg),
102 	    sff->sff_data, sizeof(sff->sff_data), 0)) {
103 		printf("%s: cannot read register 0x%x\n",
104 		    sc->sc_dev.dv_xname, reg);
105 	}
106 	iic_release_bus(sc->sc_tag, 0);
107 
108 	return 0;
109 }
110