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, ®, 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