chrome_ec.c (263981) | chrome_ec.c (266785) |
---|---|
1/*- 2 * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 15 unchanged lines hidden (view full) --- 24 * SUCH DAMAGE. 25 */ 26 27/* 28 * Samsung Chromebook Embedded Controller 29 */ 30 31#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 15 unchanged lines hidden (view full) --- 24 * SUCH DAMAGE. 25 */ 26 27/* 28 * Samsung Chromebook Embedded Controller 29 */ 30 31#include <sys/cdefs.h> |
32__FBSDID("$FreeBSD: head/sys/arm/samsung/exynos/chrome_ec.c 263981 2014-04-01 04:40:08Z br $"); | 32__FBSDID("$FreeBSD: head/sys/arm/samsung/exynos/chrome_ec.c 266785 2014-05-28 06:11:12Z br $"); |
33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/bus.h> 37#include <sys/kernel.h> 38#include <sys/module.h> 39#include <sys/malloc.h> 40#include <sys/rman.h> --- 14 unchanged lines hidden (view full) --- 55 56#include <dev/iicbus/iiconf.h> 57 58#include "iicbus_if.h" 59#include "gpio_if.h" 60 61#include <arm/samsung/exynos/chrome_ec.h> 62 | 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/bus.h> 37#include <sys/kernel.h> 38#include <sys/module.h> 39#include <sys/malloc.h> 40#include <sys/rman.h> --- 14 unchanged lines hidden (view full) --- 55 56#include <dev/iicbus/iiconf.h> 57 58#include "iicbus_if.h" 59#include "gpio_if.h" 60 61#include <arm/samsung/exynos/chrome_ec.h> 62 |
63/* TODO: export to DTS */ 64#define OUR_GPIO 177 65#define EC_GPIO 168 66 | |
67struct ec_softc { 68 device_t dev; | 63struct ec_softc { 64 device_t dev; |
65 int have_arbitrator; 66 pcell_t our_gpio; 67 pcell_t ec_gpio; |
|
69}; 70 71struct ec_softc *ec_sc; 72 73/* 74 * bus_claim, bus_release 75 * both functions used for bus arbitration 76 * in multi-master mode 77 */ 78 79static int 80bus_claim(struct ec_softc *sc) 81{ 82 device_t gpio_dev; 83 int status; 84 | 68}; 69 70struct ec_softc *ec_sc; 71 72/* 73 * bus_claim, bus_release 74 * both functions used for bus arbitration 75 * in multi-master mode 76 */ 77 78static int 79bus_claim(struct ec_softc *sc) 80{ 81 device_t gpio_dev; 82 int status; 83 |
84 if (sc->our_gpio == 0 || sc->ec_gpio == 0) { 85 device_printf(sc->dev, "i2c arbitrator is not configured\n"); 86 return (1); 87 } 88 |
|
85 gpio_dev = devclass_get_device(devclass_find("gpio"), 0); | 89 gpio_dev = devclass_get_device(devclass_find("gpio"), 0); |
86 if (gpio_dev == NULL) { | 90 if (gpio_dev == NULL) { |
87 device_printf(sc->dev, "cant find gpio_dev\n"); 88 return (1); 89 } 90 91 /* Say we want the bus */ | 91 device_printf(sc->dev, "cant find gpio_dev\n"); 92 return (1); 93 } 94 95 /* Say we want the bus */ |
92 GPIO_PIN_SET(gpio_dev, OUR_GPIO, GPIO_PIN_LOW); | 96 GPIO_PIN_SET(gpio_dev, sc->our_gpio, GPIO_PIN_LOW); |
93 | 97 |
98 /* TODO(imax): insert a delay to allow EC to react. */ 99 |
|
94 /* Check EC decision */ | 100 /* Check EC decision */ |
95 GPIO_PIN_GET(gpio_dev, EC_GPIO, &status); | 101 GPIO_PIN_GET(gpio_dev, sc->ec_gpio, &status); |
96 97 if (status == 1) { 98 /* Okay. We have bus */ 99 return (0); 100 } 101 102 /* EC is master */ 103 return (-1); 104} 105 106static int 107bus_release(struct ec_softc *sc) 108{ 109 device_t gpio_dev; 110 | 102 103 if (status == 1) { 104 /* Okay. We have bus */ 105 return (0); 106 } 107 108 /* EC is master */ 109 return (-1); 110} 111 112static int 113bus_release(struct ec_softc *sc) 114{ 115 device_t gpio_dev; 116 |
117 if (sc->our_gpio == 0 || sc->ec_gpio == 0) { 118 device_printf(sc->dev, "i2c arbitrator is not configured\n"); 119 return (1); 120 } 121 |
|
111 gpio_dev = devclass_get_device(devclass_find("gpio"), 0); | 122 gpio_dev = devclass_get_device(devclass_find("gpio"), 0); |
112 if (gpio_dev == NULL) { | 123 if (gpio_dev == NULL) { |
113 device_printf(sc->dev, "cant find gpio_dev\n"); 114 return (1); 115 } 116 | 124 device_printf(sc->dev, "cant find gpio_dev\n"); 125 return (1); 126 } 127 |
117 GPIO_PIN_SET(gpio_dev, OUR_GPIO, GPIO_PIN_HIGH); | 128 GPIO_PIN_SET(gpio_dev, sc->our_gpio, GPIO_PIN_HIGH); |
118 119 return (0); 120} 121 122static int 123ec_probe(device_t dev) 124{ 125 --- 78 unchanged lines hidden (view full) --- 204 data_in[3] = 0x10; 205 206 ec_command(EC_CMD_MKBP_STATE, data_in, 4, 207 data_out, 4); 208 209 return (0); 210} 211 | 129 130 return (0); 131} 132 133static int 134ec_probe(device_t dev) 135{ 136 --- 78 unchanged lines hidden (view full) --- 215 data_in[3] = 0x10; 216 217 ec_command(EC_CMD_MKBP_STATE, data_in, 4, 218 data_out, 4); 219 220 return (0); 221} 222 |
223static void 224configure_i2c_arbitrator(struct ec_softc *sc) 225{ 226 phandle_t arbitrator; 227 228 /* TODO(imax): look for compatible entry instead of hard-coded path */ 229 arbitrator = OF_finddevice("/i2c-arbitrator"); 230 if (arbitrator > 0 && 231 OF_hasprop(arbitrator, "freebsd,our-gpio") && 232 OF_hasprop(arbitrator, "freebsd,ec-gpio")) { 233 sc->have_arbitrator = 1; 234 OF_getencprop(arbitrator, "freebsd,our-gpio", 235 &sc->our_gpio, sizeof(sc->our_gpio)); 236 OF_getencprop(arbitrator, "freebsd,ec-gpio", 237 &sc->ec_gpio, sizeof(sc->ec_gpio)); 238 } else { 239 sc->have_arbitrator = 0; 240 sc->our_gpio = 0; 241 sc->ec_gpio = 0; 242 } 243} 244 |
|
212static int 213ec_attach(device_t dev) 214{ 215 struct ec_softc *sc; 216 217 sc = device_get_softc(dev); 218 sc->dev = dev; 219 220 ec_sc = sc; 221 | 245static int 246ec_attach(device_t dev) 247{ 248 struct ec_softc *sc; 249 250 sc = device_get_softc(dev); 251 sc->dev = dev; 252 253 ec_sc = sc; 254 |
255 configure_i2c_arbitrator(sc); 256 |
|
222 /* 223 * Claim the bus. 224 * 225 * We don't know cases when EC is master, 226 * so hold the bus forever for us. 227 * 228 */ 229 | 257 /* 258 * Claim the bus. 259 * 260 * We don't know cases when EC is master, 261 * so hold the bus forever for us. 262 * 263 */ 264 |
230 if (bus_claim(sc) != 0) { | 265 if (sc->have_arbitrator && bus_claim(sc) != 0) { |
231 return (ENXIO); 232 } 233 234 return (0); 235} 236 237static int 238ec_detach(device_t dev) 239{ 240 struct ec_softc *sc; 241 242 sc = device_get_softc(dev); 243 | 266 return (ENXIO); 267 } 268 269 return (0); 270} 271 272static int 273ec_detach(device_t dev) 274{ 275 struct ec_softc *sc; 276 277 sc = device_get_softc(dev); 278 |
244 bus_release(sc); | 279 if (sc->have_arbitrator) { 280 bus_release(sc); 281 } |
245 246 return (0); 247} 248 249static device_method_t ec_methods[] = { 250 DEVMETHOD(device_probe, ec_probe), 251 DEVMETHOD(device_attach, ec_attach), 252 DEVMETHOD(device_detach, ec_detach), --- 14 unchanged lines hidden --- | 282 283 return (0); 284} 285 286static device_method_t ec_methods[] = { 287 DEVMETHOD(device_probe, ec_probe), 288 DEVMETHOD(device_attach, ec_attach), 289 DEVMETHOD(device_detach, ec_detach), --- 14 unchanged lines hidden --- |