33#include <sys/endian.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
40#include <machine/resource.h>
42#include <contrib/dev/acpica/include/acpi.h>
43#include <contrib/dev/acpica/include/accommon.h>
44#include <contrib/dev/acpica/include/amlcode.h>
45#include <dev/acpica/acpivar.h>
50#define ACPI_IICBUS_LOCAL_BUFSIZE 32
58#define ResourceSource_Handle ResourceSource.StringPtr
61#define _COMPONENT ACPI_BUS
62ACPI_MODULE_NAME(
"IIC")
88 return (res->Type == ACPI_RESOURCE_TYPE_SERIAL_BUS &&
89 res->Data.CommonSerialBus.Type == ACPI_RESOURCE_SERIAL_TYPE_I2C);
144 if (buflen <=
sizeof(local_buffer))
147 msgs[1].
buf = malloc(buflen, M_DEVBUF, M_WAITOK);
151 if (
msgs[1].
buf != local_buffer)
160 uint8_t
bytes[2] = { cmd, count };
184 device_t parent = device_get_parent(
dev);
197 block_msg[0].
len = 1;
200 if (
len <=
sizeof(local_buffer))
201 block_msg[0].
buf = local_buffer;
203 block_msg[0].
buf = malloc(
len, M_DEVBUF, M_WAITOK);
211 if (block_msg[0].
buf != local_buffer)
212 free(block_msg[0].
buf, M_DEVBUF);
220 UINT32 BitWidth, UINT64 *Value,
void *HandlerContext,
void *RegionContext)
225 ACPI_CONNECTION_INFO *info;
226 ACPI_RESOURCE_I2C_SERIALBUS *sb;
233 return (AE_BAD_PARAMETER);
235 info = HandlerContext;
236 s = AcpiBufferToResource(info->Connection, info->Length, &res);
241 s = AE_BAD_PARAMETER;
245 sb = &res->Data.I2cSerialBus;
248 if (sb->AccessMode == ACPI_I2C_10BIT_MODE) {
249 s = AE_BAD_PARAMETER;
253#define AML_FIELD_ATTRIB_MASK 0x0F
254#define AML_FIELD_ATTRIO(attr, io) (((attr) << 16) | (io))
301 gsb->
data, info->AccessLength);
306 gsb->
data, info->AccessLength);
310 device_printf(
dev,
"protocol(0x%04x) is not supported.\n",
312 s = AE_BAD_PARAMETER;
330 handle = acpi_get_handle(device_get_parent(sc->
super_sc.
dev));
331 s = AcpiInstallAddressSpaceHandler(handle, ACPI_ADR_SPACE_GSBUS,
333 if (ACPI_FAILURE(s)) {
335 "Failed to install GSBUS Address Space Handler in ACPI\n");
348 handle = acpi_get_handle(device_get_parent(sc->
super_sc.
dev));
349 s = AcpiRemoveAddressSpaceHandler(handle, ACPI_ADR_SPACE_GSBUS,
351 if (ACPI_FAILURE(s)) {
353 "Failed to remove GSBUS Address Space Handler from ACPI\n");
368 status = AcpiGetHandle(ACPI_ROOT_OBJECT,
369 res->Data.I2cSerialBus.ResourceSource.StringPtr, &handle);
372 memcpy(sb, &res->Data.I2cSerialBus,
378 sb->ResourceSource_Handle = handle;
379 return (AE_CTRL_TERMINATE);
380 }
else if (res->Type == ACPI_RESOURCE_TYPE_END_TAG)
381 return (AE_NOT_FOUND);
390 return (AcpiWalkResources(handle,
"_CRS",
397 device_t
dev = context;
399 struct resource_list *rl = &super_devi->
rl;
403 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
404 if (res->Data.ExtendedIrq.InterruptCount > 0) {
405 irq = res->Data.ExtendedIrq.Interrupts[0];
407 printf(
" IRQ: %d\n", irq);
408 resource_list_add_next(rl, SYS_RES_IRQ, irq, irq, 1);
409 return (AE_CTRL_TERMINATE);
412 case ACPI_RESOURCE_TYPE_GPIO:
413 if (res->Data.Gpio.ConnectionType ==
414 ACPI_RESOURCE_GPIO_TYPE_INT) {
416 gpio_pin = res->Data.Gpio.PinTable[0];
418 printf(
" GPIO IRQ pin: %d\n", gpio_pin);
419 return (AE_CTRL_TERMINATE);
433 return (AcpiWalkResources(handle,
"_CRS",
440 device_printf(
dev,
"found ACPI child\n");
441 printf(
" SlaveAddress: 0x%04hx\n", sb->SlaveAddress);
442 printf(
" ConnectionSpeed: %uHz\n", sb->ConnectionSpeed);
443 printf(
" SlaveMode: %s\n",
444 sb->SlaveMode == ACPI_CONTROLLER_INITIATED ?
445 "ControllerInitiated" :
"DeviceInitiated");
446 printf(
" AddressingMode: %uBit\n", sb->AccessMode == 0 ? 7 : 10);
447 printf(
" ConnectionSharing: %s\n", sb->ConnectionSharing == 0 ?
448 "Exclusive" :
"Shared");
461 void *context,
void **result)
463 device_t
iicbus, child, acpi_child, acpi0;
470 super_sc = device_get_softc(
iicbus);
476 if (!ACPI_FAILURE(acpi_GetInteger(handle,
"_STA", &sta)) &&
477 !ACPI_DEVICE_PRESENT(sta))
480 if (!acpi_has_hid(handle))
489 sb.SlaveAddress == 0)
491 if (sb.ResourceSource_Handle !=
492 acpi_get_handle(device_get_parent(
iicbus)))
499 super_sc->
bus_freq = sb.ConnectionSpeed;
502 acpi_child = acpi_get_device(handle);
503 if (acpi_child != NULL) {
504 acpi0 = devclass_get_device(devclass_find(
"acpi"), 0);
505 if (device_get_parent(acpi_child) != acpi0)
508 if (device_is_attached(acpi_child))
511 if (device_delete_child(acpi0, acpi_child) != 0)
515 child = BUS_ADD_CHILD(
iicbus, 0, NULL, -1);
517 device_printf(
iicbus,
"add child failed\n");
521 iicbus_set_addr(child, sb.SlaveAddress);
522 acpi_set_handle(child, handle);
528 status = AcpiAttachData(handle, acpi_fake_objhandler, child);
529 if (ACPI_FAILURE(status))
530 printf(
"WARNING: Unable to attach object data to %s - %s\n",
531 acpi_name(handle), AcpiFormatException(status));
540 return (AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
550 if (device_get_children(
dev, &devlist, &numdevs) != 0)
553 for (i = 0; i < numdevs; i++)
554 if (all_children || device_is_attached(devlist[i]) != 0)
555 acpi_set_powerstate(devlist[i], state);
557 free(devlist, M_TEMP);
566 if (acpi_disabled(
"iicbus"))
569 controller = device_get_parent(
dev);
570 if (controller == NULL)
573 handle = acpi_get_handle(controller);
577 device_set_desc(
dev,
"Philips I2C bus (ACPI-hinted)");
578 return (BUS_PROBE_DEFAULT);
588 device_printf(
dev,
"children enumeration failed\n");
616 error = bus_generic_suspend(
dev);
629 return (bus_generic_resume(
dev));
641 acpi_set_powerstate(child, ACPI_STATE_D3);
650 device_t child, *devlist;
653 DEVICE_IDENTIFY(driver,
dev);
654 if (device_get_children(
dev, &devlist, &numdevs) != 0)
657 for (i = 0; i < numdevs; i++) {
659 if (device_get_state(child) == DS_NOTPRESENT) {
660 acpi_set_powerstate(child, ACPI_STATE_D0);
661 if (device_probe_and_attach(child) != 0)
662 acpi_set_powerstate(child, ACPI_STATE_D3);
665 free(devlist, M_TEMP);
673 if (acpi_get_device(devi->
handle) == child)
674 AcpiDetachData(devi->
handle, acpi_fake_objhandler);
683 case ACPI_IVAR_HANDLE:
684 *res = (uintptr_t)devi->
handle;
699 case ACPI_IVAR_HANDLE:
725 sbuf_printf(sb,
" handle=%s", acpi_name(devi->
handle));
745 error = acpi_pnpinfo(devi->
handle, sb);
767 DEVMETHOD(bus_get_device_path, acpi_get_acpi_device_path),
static int acpi_iicbus_detach(device_t dev)
static void acpi_iicbus_probe_nomatch(device_t bus, device_t child)
#define AML_FIELD_ATTRIB_MASK
static ACPI_STATUS acpi_iicbus_parse_resources_cb(ACPI_RESOURCE *res, void *context)
static ACPI_STATUS acpi_iicbus_space_handler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 BitWidth, UINT64 *Value, void *HandlerContext, void *RegionContext)
MODULE_DEPEND(acpi_iicbus, acpi, 1, 1, 1)
static int acpi_iicbus_attach(device_t dev)
static ACPI_STATUS acpi_iicbus_get_i2cres(ACPI_HANDLE handle, ACPI_RESOURCE_I2C_SERIALBUS *sb)
TUNABLE_INT("hw.iicbus.enable_acpi_space_handler", &install_space_handler)
MODULE_VERSION(acpi_iicbus, 1)
ACPI_RESOURCE_I2C_SERIALBUS ACPI_IICBUS_RESOURCE_I2C_SERIALBUS
static int acpi_iicbus_suspend(device_t dev)
static int acpi_iicbus_write_ivar(device_t bus, device_t child, int which, uintptr_t val)
static bool acpi_resource_is_i2c_serialbus(ACPI_RESOURCE *res)
static void acpi_iicbus_dump_res(device_t dev, ACPI_IICBUS_RESOURCE_I2C_SERIALBUS *sb)
static int acpi_iicbus_recvb(device_t dev, u_char slave, char *byte)
static int acpi_iicbus_install_address_space_handler(struct acpi_iicbus_softc *sc)
static device_t acpi_iicbus_add_child(device_t dev, u_int order, const char *name, int unit)
static int install_space_handler
static device_method_t acpi_iicbus_methods[]
static int acpi_iicbus_probe(device_t dev)
static int acpi_iicbus_child_pnpinfo(device_t bus, device_t child, struct sbuf *sb)
static ACPI_STATUS acpi_iicbus_enumerate_children(device_t dev)
static void acpi_iicbus_driver_added(device_t dev, driver_t *driver)
#define AML_FIELD_ATTRIO(attr, io)
static ACPI_STATUS acpi_iicbus_parse_resources(ACPI_HANDLE handle, device_t dev)
static ACPI_STATUS acpi_iicbus_enumerate_child(ACPI_HANDLE handle, UINT32 level, void *context, void **result)
#define ACPI_IICBUS_LOCAL_BUFSIZE
static int acpi_iicbus_read_ivar(device_t bus, device_t child, int which, uintptr_t *res)
static int acpi_iicbus_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
static ACPI_STATUS acpi_iicbus_get_i2cres_cb(ACPI_RESOURCE *res, void *context)
static int acpi_iicbus_remove_address_space_handler(struct acpi_iicbus_softc *sc)
static int acpi_iicbus_child_location(device_t bus, device_t child, struct sbuf *sb)
static int acpi_iicbus_resume(device_t dev)
static int acpi_iicbus_sendb(device_t dev, u_char slave, char byte)
struct gsb_buffer __packed
static void acpi_iicbus_set_power_children(device_t dev, int state, bool all_children)
static int acpi_iicbus_write(device_t dev, u_char slave, char cmd, void *buf, uint16_t buflen)
DEFINE_CLASS_1(iicbus, acpi_iicbus_driver, acpi_iicbus_methods, sizeof(struct acpi_iicbus_softc), iicbus_driver)
static int acpi_iicbus_read(device_t dev, u_char slave, char cmd, void *buf, uint16_t buflen)
static int acpi_iicbus_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
static void acpi_iicbus_child_deleted(device_t bus, device_t child)
int iicbus_write_ivar(device_t bus, device_t child, int which, uintptr_t value)
int iicbus_attach_common(device_t dev, u_int bus_freq)
int iicbus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
void iicbus_probe_nomatch(device_t bus, device_t child)
int iicbus_child_pnpinfo(device_t bus, device_t child, struct sbuf *sb)
int iicbus_child_location(device_t bus, device_t child, struct sbuf *sb)
device_t iicbus_add_child_common(device_t dev, u_int order, const char *name, int unit, size_t ivars_size)
int iicbus_detach(device_t dev)
driver_t acpi_iicbus_driver
int iicbus_request_bus(device_t bus, device_t dev, int how)
int iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs)
int iicbus_release_bus(device_t bus, device_t dev)
struct iicbus_ivar super_ivar
bool space_handler_installed
struct iicbus_softc super_sc
ACPI_CONNECTION_INFO space_handler_info