├── .gitignore ├── Documentation ├── es1_ap_desc.c ├── firmware │ ├── authenticate.c │ ├── firmware-management │ └── firmware.c ├── sysfs-bus-greybus └── sysfs │ ├── greybus1 │ ├── 1-2 │ │ ├── 1-2.2 │ │ │ ├── 1-2.2.1 │ │ │ │ ├── bundle_class │ │ │ │ ├── bundle_id │ │ │ │ └── state │ │ │ ├── 1-2.2.2 │ │ │ │ ├── bundle_class │ │ │ │ ├── bundle_id │ │ │ │ └── state │ │ │ ├── 1-2.2.ctrl │ │ │ │ ├── product_string │ │ │ │ └── vendor_string │ │ │ ├── ddbl1_manufacturer_id │ │ │ ├── ddbl1_product_id │ │ │ ├── interface_id │ │ │ ├── product_id │ │ │ ├── serial_number │ │ │ └── vendor_id │ │ ├── eject │ │ ├── module_id │ │ └── num_interfaces │ ├── 1-5 │ │ ├── 1-5.5 │ │ │ ├── 1-5.5.2 │ │ │ │ ├── bundle_class │ │ │ │ ├── bundle_id │ │ │ │ ├── gbphy1 │ │ │ │ │ ├── gpio │ │ │ │ │ │ └── gpiochip490 │ │ │ │ │ │ │ └── .gitignore │ │ │ │ │ └── i2c-4 │ │ │ │ │ │ └── .gitignore │ │ │ │ └── state │ │ │ ├── 1-5.5.ctrl │ │ │ │ ├── product_string │ │ │ │ └── vendor_string │ │ │ ├── ddbl1_manufacturer_id │ │ │ ├── ddbl1_product_id │ │ │ ├── interface_id │ │ │ ├── product_id │ │ │ ├── serial_number │ │ │ └── vendor_id │ │ ├── 1-5.6 │ │ │ └── interface_id │ │ ├── eject │ │ ├── module_id │ │ └── num_interfaces │ ├── 1-svc │ │ ├── ap_intf_id │ │ ├── endo_id │ │ └── intf_eject │ └── bus_id │ └── greybus2 │ ├── 2-3 │ ├── 2-3.3 │ │ ├── 2-3.3.1 │ │ │ ├── bundle_class │ │ │ ├── bundle_id │ │ │ └── state │ │ ├── 2-3.3.ctrl │ │ │ ├── product_string │ │ │ └── vendor_string │ │ ├── ddbl1_manufacturer_id │ │ ├── ddbl1_product_id │ │ ├── interface_id │ │ ├── product_id │ │ ├── serial_number │ │ └── vendor_id │ ├── eject │ ├── module_id │ └── num_interfaces │ ├── 2-svc │ ├── ap_intf_id │ ├── endo_id │ └── intf_eject │ └── bus_id ├── LICENSE ├── Makefile ├── README ├── arche-apb-ctrl.c ├── arche-platform.c ├── arche_platform.h ├── arpc.h ├── audio_apbridgea.c ├── audio_apbridgea.h ├── audio_codec.c ├── audio_codec.h ├── audio_gb.c ├── audio_manager.c ├── audio_manager.h ├── audio_manager_module.c ├── audio_manager_private.h ├── audio_manager_sysfs.c ├── audio_module.c ├── audio_topology.c ├── authentication.c ├── bootrom.c ├── bundle.c ├── bundle.h ├── camera.c ├── connection.c ├── connection.h ├── control.c ├── control.h ├── core.c ├── debugfs.c ├── devices ├── es2.c ├── firmware.h ├── fw-core.c ├── fw-download.c ├── fw-management.c ├── gb-camera.h ├── gbphy.c ├── gbphy.h ├── gpio.c ├── greybus.h ├── greybus_authentication.h ├── greybus_firmware.h ├── greybus_id.h ├── greybus_manifest.h ├── greybus_protocols.h ├── greybus_trace.h ├── hd.c ├── hd.h ├── hid.c ├── i2c.c ├── interface.c ├── interface.h ├── kernel_ver.h ├── light.c ├── log.c ├── loopback.c ├── manifest.c ├── manifest.h ├── module.c ├── module.h ├── operation.c ├── operation.h ├── power_supply.c ├── pwm.c ├── raw.c ├── scripts ├── checkpatch.pl └── spelling.txt ├── sdio.c ├── spi.c ├── spilib.c ├── spilib.h ├── svc.c ├── svc.h ├── svc_watchdog.c ├── timesync.c ├── timesync.h ├── timesync_platform.c ├── tools ├── Android.mk ├── Makefile ├── README.loopback ├── lbtest └── loopback_test.c ├── uart.c ├── usb.c └── vibrator.c /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.cmd 3 | *.ko 4 | *.mod.c 5 | modules.order 6 | Module.symvers 7 | *.o 8 | *.o.* 9 | *.swp 10 | .tmp_versions 11 | tags 12 | cscope.* 13 | ncscope.* 14 | *.patch 15 | tools/loopback_test 16 | -------------------------------------------------------------------------------- /Documentation/es1_ap_desc.c: -------------------------------------------------------------------------------- 1 | /* ES1 AP Bridge Chip USB descriptor definitions */ 2 | 3 | static const u8 es1_dev_descriptor[] = { 4 | 0x12, /* __u8 bLength */ 5 | 0x01, /* __u8 bDescriptorType; Device */ 6 | 0x00, 0x02 /* __le16 bcdUSB v2.0 */ 7 | 0x00, /* __u8 bDeviceClass */ 8 | 0x00, /* __u8 bDeviceClass */ 9 | 0x00, /* __u8 bDeviceSubClass; */ 10 | 0x00, /* __u8 bDeviceProtocol; */ 11 | 0x40, /* __u8 bMaxPacketSize0; 2^64 = 512 Bytes */ 12 | 13 | 0xff, 0xff, /* __le16 idVendor; 0xffff made up for now */ 14 | 0x01, 0x00, /* __le16 idProduct; 0x0001 made up for now */ 15 | 0x01, 0x00, /* __le16 bcdDevice; ES1 */ 16 | 17 | 0x03, /* __u8 iManufacturer; */ 18 | 0x02, /* __u8 iProduct; */ 19 | 0x01, /* __u8 iSerialNumber; */ 20 | 0x01 /* __u8 bNumConfigurations; */ 21 | }; 22 | 23 | static const u8 es1_config_descriptor[] = { 24 | /* one configuration */ 25 | 0x09, /* __u8 bLength; */ 26 | 0x02, /* __u8 bDescriptorType; Configuration */ 27 | 0x19, 0x00, /* __le16 wTotalLength; */ 28 | 0x01, /* __u8 bNumInterfaces; (1) */ 29 | 0x01, /* __u8 bConfigurationValue; */ 30 | 0x00, /* __u8 iConfiguration; */ 31 | 0xc0, /* __u8 bmAttributes; 32 | Bit 7: must be set, 33 | 6: Self-powered, 34 | 5: Remote wakeup, 35 | 4..0: resvd */ 36 | 0x00, /* __u8 MaxPower; */ 37 | 38 | /* one interface */ 39 | 0x09, /* __u8 if_bLength; */ 40 | 0x04, /* __u8 if_bDescriptorType; Interface */ 41 | 0x00, /* __u8 if_bInterfaceNumber; */ 42 | 0x00, /* __u8 if_bAlternateSetting; */ 43 | 0x03, /* __u8 if_bNumEndpoints; */ 44 | 0xff, /* __u8 if_bInterfaceClass; Vendor-specific */ 45 | 0xff, /* __u8 if_bInterfaceSubClass; Vendor-specific */ 46 | 0xff, /* __u8 if_bInterfaceProtocol; Vendor-specific */ 47 | 0x00, /* __u8 if_iInterface; */ 48 | 49 | /* three endpoints */ 50 | 0x07, /* __u8 ep_bLength; */ 51 | 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 52 | 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ 53 | 0x03, /* __u8 ep_bmAttributes; Interrupt */ 54 | 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ 55 | 0x40, /* __u8 ep_bInterval; 64ms */ 56 | 57 | 0x07, /* __u8 ep_bLength; */ 58 | 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 59 | 0x82, /* __u8 ep_bEndpointAddress; IN Endpoint 2 */ 60 | 0x02, /* __u8 ep_bmAttributes; Bulk */ 61 | 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ 62 | 0x40 /* __u8 ep_bInterval; */ 63 | 64 | 0x07, /* __u8 ep_bLength; */ 65 | 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 66 | 0x02, /* __u8 ep_bEndpointAddress; Out Endpoint 2 */ 67 | 0x02, /* __u8 ep_bmAttributes; Bulk */ 68 | 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ 69 | 0x40 /* __u8 ep_bInterval; */ 70 | }; 71 | -------------------------------------------------------------------------------- /Documentation/firmware/authenticate.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Sample code to test CAP protocol 3 | * 4 | * This file is provided under a dual BSD/GPLv2 license. When using or 5 | * redistributing this file, you may do so under either license. 6 | * 7 | * GPL LICENSE SUMMARY 8 | * 9 | * Copyright(c) 2016 Google Inc. All rights reserved. 10 | * Copyright(c) 2016 Linaro Ltd. All rights reserved. 11 | * 12 | * This program is free software; you can redistribute it and/or modify 13 | * it under the terms of version 2 of the GNU General Public License as 14 | * published by the Free Software Foundation. 15 | * 16 | * This program is distributed in the hope that it will be useful, but 17 | * WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | * General Public License version 2 for more details. 20 | * 21 | * BSD LICENSE 22 | * 23 | * Copyright(c) 2016 Google Inc. All rights reserved. 24 | * Copyright(c) 2016 Linaro Ltd. All rights reserved. 25 | * 26 | * Redistribution and use in source and binary forms, with or without 27 | * modification, are permitted provided that the following conditions 28 | * are met: 29 | * 30 | * * Redistributions of source code must retain the above copyright 31 | * notice, this list of conditions and the following disclaimer. 32 | * * Redistributions in binary form must reproduce the above copyright 33 | * notice, this list of conditions and the following disclaimer in 34 | * the documentation and/or other materials provided with the 35 | * distribution. 36 | * * Neither the name of Google Inc. or Linaro Ltd. nor the names of 37 | * its contributors may be used to endorse or promote products 38 | * derived from this software without specific prior written 39 | * permission. 40 | * 41 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 42 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 43 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 44 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR 45 | * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 46 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 47 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 48 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 49 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 50 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 51 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 | */ 53 | 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | 61 | #include "../../greybus_authentication.h" 62 | 63 | struct cap_ioc_get_endpoint_uid uid; 64 | struct cap_ioc_get_ims_certificate cert = { 65 | .certificate_class = 0, 66 | .certificate_id = 0, 67 | }; 68 | 69 | struct cap_ioc_authenticate authenticate = { 70 | .auth_type = 0, 71 | .challenge = {0}, 72 | }; 73 | 74 | int main(int argc, char *argv[]) 75 | { 76 | unsigned int timeout = 10000; 77 | char *capdev; 78 | int fd, ret; 79 | 80 | /* Make sure arguments are correct */ 81 | if (argc != 2) { 82 | printf("\nUsage: ./firmware \n"); 83 | return 0; 84 | } 85 | 86 | capdev = argv[1]; 87 | 88 | printf("Opening %s authentication device\n", capdev); 89 | 90 | fd = open(capdev, O_RDWR); 91 | if (fd < 0) { 92 | printf("Failed to open: %s\n", capdev); 93 | return -1; 94 | } 95 | 96 | /* Get UID */ 97 | printf("Get UID\n"); 98 | 99 | ret = ioctl(fd, CAP_IOC_GET_ENDPOINT_UID, &uid); 100 | if (ret < 0) { 101 | printf("Failed to get UID: %s (%d)\n", capdev, ret); 102 | ret = -1; 103 | goto close_fd; 104 | } 105 | 106 | printf("UID received: 0x%llx\n", *(long long unsigned int *)(uid.uid)); 107 | 108 | /* Get certificate */ 109 | printf("Get IMS certificate\n"); 110 | 111 | ret = ioctl(fd, CAP_IOC_GET_IMS_CERTIFICATE, &cert); 112 | if (ret < 0) { 113 | printf("Failed to get IMS certificate: %s (%d)\n", capdev, ret); 114 | ret = -1; 115 | goto close_fd; 116 | } 117 | 118 | printf("IMS Certificate size: %d\n", cert.cert_size); 119 | 120 | /* Authenticate */ 121 | printf("Authenticate module\n"); 122 | 123 | memcpy(authenticate.uid, uid.uid, 8); 124 | 125 | ret = ioctl(fd, CAP_IOC_AUTHENTICATE, &authenticate); 126 | if (ret < 0) { 127 | printf("Failed to authenticate module: %s (%d)\n", capdev, ret); 128 | ret = -1; 129 | goto close_fd; 130 | } 131 | 132 | printf("Authenticated, result (%02x), sig-size (%02x)\n", 133 | authenticate.result_code, authenticate.signature_size); 134 | 135 | close_fd: 136 | close(fd); 137 | 138 | return ret; 139 | } 140 | -------------------------------------------------------------------------------- /Documentation/firmware/firmware.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Sample code to test firmware-management protocol 3 | * 4 | * This file is provided under a dual BSD/GPLv2 license. When using or 5 | * redistributing this file, you may do so under either license. 6 | * 7 | * GPL LICENSE SUMMARY 8 | * 9 | * Copyright(c) 2016 Google Inc. All rights reserved. 10 | * Copyright(c) 2016 Linaro Ltd. All rights reserved. 11 | * 12 | * This program is free software; you can redistribute it and/or modify 13 | * it under the terms of version 2 of the GNU General Public License as 14 | * published by the Free Software Foundation. 15 | * 16 | * This program is distributed in the hope that it will be useful, but 17 | * WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | * General Public License version 2 for more details. 20 | * 21 | * BSD LICENSE 22 | * 23 | * Copyright(c) 2016 Google Inc. All rights reserved. 24 | * Copyright(c) 2016 Linaro Ltd. All rights reserved. 25 | * 26 | * Redistribution and use in source and binary forms, with or without 27 | * modification, are permitted provided that the following conditions 28 | * are met: 29 | * 30 | * * Redistributions of source code must retain the above copyright 31 | * notice, this list of conditions and the following disclaimer. 32 | * * Redistributions in binary form must reproduce the above copyright 33 | * notice, this list of conditions and the following disclaimer in 34 | * the documentation and/or other materials provided with the 35 | * distribution. 36 | * * Neither the name of Google Inc. or Linaro Ltd. nor the names of 37 | * its contributors may be used to endorse or promote products 38 | * derived from this software without specific prior written 39 | * permission. 40 | * 41 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 42 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 43 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 44 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR 45 | * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 46 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 47 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 48 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 49 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 50 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 51 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 | */ 53 | 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | 61 | #include "../../greybus_firmware.h" 62 | 63 | #define FW_DEV_DEFAULT "/dev/gb-fw-mgmt-0" 64 | #define FW_TAG_INT_DEFAULT "s3f" 65 | #define FW_TAG_BCND_DEFAULT "bf_01" 66 | #define FW_UPDATE_TYPE_DEFAULT 0 67 | #define FW_TIMEOUT_DEFAULT 10000; 68 | 69 | static const char *firmware_tag; 70 | static const char *fwdev = FW_DEV_DEFAULT; 71 | static int fw_update_type = FW_UPDATE_TYPE_DEFAULT; 72 | static int fw_timeout = FW_TIMEOUT_DEFAULT; 73 | 74 | static struct fw_mgmt_ioc_get_intf_version intf_fw_info; 75 | static struct fw_mgmt_ioc_get_backend_version backend_fw_info; 76 | static struct fw_mgmt_ioc_intf_load_and_validate intf_load; 77 | static struct fw_mgmt_ioc_backend_fw_update backend_update; 78 | 79 | static void usage(void) 80 | { 81 | printf("\nUsage: ./firmware (default: \"s3f\"/\"bf_01\") \n"); 82 | } 83 | 84 | static int update_intf_firmware(int fd) 85 | { 86 | int ret; 87 | 88 | /* Get Interface Firmware Version */ 89 | printf("Get Interface Firmware Version\n"); 90 | 91 | ret = ioctl(fd, FW_MGMT_IOC_GET_INTF_FW, &intf_fw_info); 92 | if (ret < 0) { 93 | printf("Failed to get interface firmware version: %s (%d)\n", 94 | fwdev, ret); 95 | return -1; 96 | } 97 | 98 | printf("Interface Firmware tag (%s), major (%d), minor (%d)\n", 99 | intf_fw_info.firmware_tag, intf_fw_info.major, 100 | intf_fw_info.minor); 101 | 102 | /* Try Interface Firmware load over Unipro */ 103 | printf("Loading Interface Firmware\n"); 104 | 105 | intf_load.load_method = GB_FW_U_LOAD_METHOD_UNIPRO; 106 | intf_load.status = 0; 107 | intf_load.major = 0; 108 | intf_load.minor = 0; 109 | 110 | strncpy((char *)&intf_load.firmware_tag, firmware_tag, 111 | GB_FIRMWARE_U_TAG_MAX_SIZE); 112 | 113 | ret = ioctl(fd, FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE, &intf_load); 114 | if (ret < 0) { 115 | printf("Failed to load interface firmware: %s (%d)\n", fwdev, 116 | ret); 117 | return -1; 118 | } 119 | 120 | if (intf_load.status != GB_FW_U_LOAD_STATUS_VALIDATED && 121 | intf_load.status != GB_FW_U_LOAD_STATUS_UNVALIDATED) { 122 | printf("Load status says loading failed: %d\n", 123 | intf_load.status); 124 | return -1; 125 | } 126 | 127 | printf("Interface Firmware (%s) Load done: major: %d, minor: %d, status: %d\n", 128 | firmware_tag, intf_load.major, intf_load.minor, 129 | intf_load.status); 130 | 131 | /* Initiate Mode-switch to the newly loaded firmware */ 132 | printf("Initiate Mode switch\n"); 133 | 134 | ret = ioctl(fd, FW_MGMT_IOC_MODE_SWITCH); 135 | if (ret < 0) 136 | printf("Failed to initiate mode-switch (%d)\n", ret); 137 | 138 | return ret; 139 | } 140 | 141 | static int update_backend_firmware(int fd) 142 | { 143 | int ret; 144 | 145 | /* Get Backend Firmware Version */ 146 | printf("Getting Backend Firmware Version\n"); 147 | 148 | strncpy((char *)&backend_fw_info.firmware_tag, firmware_tag, 149 | GB_FIRMWARE_U_TAG_MAX_SIZE); 150 | 151 | retry_fw_version: 152 | ret = ioctl(fd, FW_MGMT_IOC_GET_BACKEND_FW, &backend_fw_info); 153 | if (ret < 0) { 154 | printf("Failed to get backend firmware version: %s (%d)\n", 155 | fwdev, ret); 156 | return -1; 157 | } 158 | 159 | printf("Backend Firmware tag (%s), major (%d), minor (%d), status (%d)\n", 160 | backend_fw_info.firmware_tag, backend_fw_info.major, 161 | backend_fw_info.minor, backend_fw_info.status); 162 | 163 | if (backend_fw_info.status == GB_FW_U_BACKEND_VERSION_STATUS_RETRY) 164 | goto retry_fw_version; 165 | 166 | if ((backend_fw_info.status != GB_FW_U_BACKEND_VERSION_STATUS_SUCCESS) 167 | && (backend_fw_info.status != GB_FW_U_BACKEND_VERSION_STATUS_NOT_AVAILABLE)) { 168 | printf("Failed to get backend firmware version: %s (%d)\n", 169 | fwdev, backend_fw_info.status); 170 | return -1; 171 | } 172 | 173 | /* Try Backend Firmware Update over Unipro */ 174 | printf("Updating Backend Firmware\n"); 175 | 176 | strncpy((char *)&backend_update.firmware_tag, firmware_tag, 177 | GB_FIRMWARE_U_TAG_MAX_SIZE); 178 | 179 | retry_fw_update: 180 | backend_update.status = 0; 181 | 182 | ret = ioctl(fd, FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE, &backend_update); 183 | if (ret < 0) { 184 | printf("Failed to load backend firmware: %s (%d)\n", fwdev, ret); 185 | return -1; 186 | } 187 | 188 | if (backend_update.status == GB_FW_U_BACKEND_FW_STATUS_RETRY) { 189 | printf("Retrying firmware update: %d\n", backend_update.status); 190 | goto retry_fw_update; 191 | } 192 | 193 | if (backend_update.status != GB_FW_U_BACKEND_FW_STATUS_SUCCESS) { 194 | printf("Load status says loading failed: %d\n", 195 | backend_update.status); 196 | } else { 197 | printf("Backend Firmware (%s) Load done: status: %d\n", 198 | firmware_tag, backend_update.status); 199 | } 200 | 201 | return 0; 202 | } 203 | 204 | int main(int argc, char *argv[]) 205 | { 206 | int fd, ret; 207 | 208 | if (argc > 1 && 209 | (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) { 210 | usage(); 211 | return -1; 212 | } 213 | 214 | if (argc > 1) 215 | fwdev = argv[1]; 216 | 217 | if (argc > 2) 218 | sscanf(argv[2], "%u", &fw_update_type); 219 | 220 | if (argc > 3) { 221 | firmware_tag = argv[3]; 222 | } else if (!fw_update_type) { 223 | firmware_tag = FW_TAG_INT_DEFAULT; 224 | } else { 225 | firmware_tag = FW_TAG_BCND_DEFAULT; 226 | } 227 | 228 | if (argc > 4) 229 | sscanf(argv[4], "%u", &fw_timeout); 230 | 231 | printf("Trying Firmware update: fwdev: %s, type: %s, tag: %s, timeout: %d\n", 232 | fwdev, fw_update_type == 0 ? "interface" : "backend", 233 | firmware_tag, fw_timeout); 234 | 235 | printf("Opening %s firmware management device\n", fwdev); 236 | 237 | fd = open(fwdev, O_RDWR); 238 | if (fd < 0) { 239 | printf("Failed to open: %s\n", fwdev); 240 | return -1; 241 | } 242 | 243 | /* Set Timeout */ 244 | printf("Setting timeout to %u ms\n", fw_timeout); 245 | 246 | ret = ioctl(fd, FW_MGMT_IOC_SET_TIMEOUT_MS, &fw_timeout); 247 | if (ret < 0) { 248 | printf("Failed to set timeout: %s (%d)\n", fwdev, ret); 249 | ret = -1; 250 | goto close_fd; 251 | } 252 | 253 | if (!fw_update_type) 254 | ret = update_intf_firmware(fd); 255 | else 256 | ret = update_backend_firmware(fd); 257 | 258 | close_fd: 259 | close(fd); 260 | 261 | return ret; 262 | } 263 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_class -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_id: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/state: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/state -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_class -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_id: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/state: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/state -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.ctrl/product_string: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.ctrl/product_string -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.ctrl/vendor_string: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.ctrl/vendor_string -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/ddbl1_manufacturer_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-2/1-2.2/ddbl1_manufacturer_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/ddbl1_product_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-2/1-2.2/ddbl1_product_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/interface_id: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/product_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-2/1-2.2/product_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/serial_number: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-2/1-2.2/serial_number -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/1-2.2/vendor_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-2/1-2.2/vendor_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/eject: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-2/eject -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/module_id: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-2/num_interfaces: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_class -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_id: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/gpio/gpiochip490/.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/i2c-4/.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/state: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/state -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.ctrl/product_string: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.ctrl/product_string -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.ctrl/vendor_string: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.ctrl/vendor_string -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/ddbl1_manufacturer_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-5/1-5.5/ddbl1_manufacturer_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/ddbl1_product_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-5/1-5.5/ddbl1_product_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/interface_id: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/product_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-5/1-5.5/product_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/serial_number: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-5/1-5.5/serial_number -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.5/vendor_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-5/1-5.5/vendor_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/1-5.6/interface_id: -------------------------------------------------------------------------------- 1 | 6 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/eject: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-5/eject -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/module_id: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-5/num_interfaces: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-svc/ap_intf_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-svc/ap_intf_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-svc/endo_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-svc/endo_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/1-svc/intf_eject: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus1/1-svc/intf_eject -------------------------------------------------------------------------------- /Documentation/sysfs/greybus1/bus_id: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_class -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_id: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/state: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/state -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.ctrl/product_string: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.ctrl/product_string -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.ctrl/vendor_string: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.ctrl/vendor_string -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/2-3.3/ddbl1_manufacturer_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-3/2-3.3/ddbl1_manufacturer_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/2-3.3/ddbl1_product_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-3/2-3.3/ddbl1_product_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/2-3.3/interface_id: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/2-3.3/product_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-3/2-3.3/product_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/2-3.3/serial_number: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-3/2-3.3/serial_number -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/2-3.3/vendor_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-3/2-3.3/vendor_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/eject: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-3/eject -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/module_id: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-3/num_interfaces: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-svc/ap_intf_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-svc/ap_intf_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-svc/endo_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-svc/endo_id -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/2-svc/intf_eject: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregkh/greybus/4c5fd38b744ea955d61d6636c107fd7c6dc0e17f/Documentation/sysfs/greybus2/2-svc/intf_eject -------------------------------------------------------------------------------- /Documentation/sysfs/greybus2/bus_id: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | greybus-y := core.o \ 2 | debugfs.o \ 3 | hd.o \ 4 | manifest.o \ 5 | module.o \ 6 | interface.o \ 7 | bundle.o \ 8 | connection.o \ 9 | control.o \ 10 | svc.o \ 11 | svc_watchdog.o \ 12 | operation.o \ 13 | timesync.o \ 14 | timesync_platform.o 15 | 16 | gb-gbphy-y := gbphy.o 17 | 18 | # Prefix all modules with gb- 19 | gb-vibrator-y := vibrator.o 20 | gb-power-supply-y := power_supply.o 21 | gb-log-y := log.o 22 | gb-loopback-y := loopback.o 23 | gb-light-y := light.o 24 | gb-raw-y := raw.o 25 | gb-hid-y := hid.o 26 | gb-es2-y := es2.o 27 | gb-arche-y := arche-platform.o arche-apb-ctrl.o 28 | gb-audio-module-y := audio_module.o audio_topology.o 29 | gb-audio-codec-y := audio_codec.o 30 | gb-audio-gb-y := audio_gb.o 31 | gb-audio-apbridgea-y := audio_apbridgea.o 32 | gb-audio-manager-y += audio_manager.o 33 | gb-audio-manager-y += audio_manager_module.o 34 | gb-bootrom-y := bootrom.o 35 | gb-camera-y := camera.o 36 | gb-firmware-y := fw-core.o fw-download.o fw-management.o authentication.o 37 | gb-spilib-y := spilib.o 38 | gb-sdio-y := sdio.o 39 | gb-uart-y := uart.o 40 | gb-pwm-y := pwm.o 41 | gb-gpio-y := gpio.o 42 | gb-i2c-y := i2c.o 43 | gb-usb-y := usb.o 44 | gb-spi-y := spi.o 45 | 46 | obj-m += greybus.o 47 | obj-m += gb-gbphy.o 48 | obj-m += gb-vibrator.o 49 | obj-m += gb-power-supply.o 50 | obj-m += gb-log.o 51 | obj-m += gb-loopback.o 52 | obj-m += gb-light.o 53 | obj-m += gb-hid.o 54 | obj-m += gb-raw.o 55 | obj-m += gb-es2.o 56 | ifeq ($(CONFIG_USB_HSIC_USB3613),y) 57 | obj-m += gb-arche.o 58 | endif 59 | ifeq ($(CONFIG_ARCH_MSM8994),y) 60 | obj-m += gb-audio-codec.o 61 | obj-m += gb-audio-module.o 62 | obj-m += gb-camera.o 63 | endif 64 | obj-m += gb-audio-gb.o 65 | obj-m += gb-audio-apbridgea.o 66 | obj-m += gb-audio-manager.o 67 | obj-m += gb-bootrom.o 68 | obj-m += gb-firmware.o 69 | obj-m += gb-spilib.o 70 | obj-m += gb-sdio.o 71 | obj-m += gb-uart.o 72 | obj-m += gb-pwm.o 73 | obj-m += gb-gpio.o 74 | obj-m += gb-i2c.o 75 | obj-m += gb-usb.o 76 | obj-m += gb-spi.o 77 | 78 | KERNELVER ?= $(shell uname -r) 79 | KERNELDIR ?= /lib/modules/$(KERNELVER)/build 80 | INSTALL_MOD_PATH ?= /.. 81 | PWD := $(shell pwd) 82 | 83 | # kernel config option that shall be enable 84 | CONFIG_OPTIONS_ENABLE := POWER_SUPPLY PWM SYSFS SPI USB SND_SOC MMC LEDS_CLASS INPUT 85 | 86 | # kernel config option that shall be disable 87 | CONFIG_OPTIONS_DISABLE := 88 | 89 | # this only run in kbuild part of the makefile 90 | ifneq ($(KERNELRELEASE),) 91 | # This function returns the argument version if current kernel version is minor 92 | # than the passed version, return 1 if equal or the current kernel version if it 93 | # is greater than argument version. 94 | kvers_cmp=$(shell [ "$(KERNELVERSION)" = "$(1)" ] && echo 1 || printf "$(1)\n$(KERNELVERSION)" | sort -V | tail -1) 95 | 96 | ifneq ($(call kvers_cmp,"3.19.0"),3.19.0) 97 | CONFIG_OPTIONS_ENABLE += LEDS_CLASS_FLASH 98 | endif 99 | 100 | ifneq ($(call kvers_cmp,"4.2.0"),4.2.0) 101 | CONFIG_OPTIONS_ENABLE += V4L2_FLASH_LED_CLASS 102 | endif 103 | 104 | $(foreach opt,$(CONFIG_OPTIONS_ENABLE),$(if $(CONFIG_$(opt)),, \ 105 | $(error CONFIG_$(opt) is disabled in the kernel configuration and must be enable \ 106 | to continue compilation))) 107 | $(foreach opt,$(CONFIG_OPTIONS_DISABLE),$(if $(filter m y, $(CONFIG_$(opt))), \ 108 | $(error CONFIG_$(opt) is enabled in the kernel configuration and must be disable \ 109 | to continue compilation),)) 110 | endif 111 | 112 | # add -Wall to try to catch everything we can. 113 | ccflags-y := -Wall 114 | 115 | # needed for trace events 116 | ccflags-y += -I$(src) 117 | 118 | GB_AUDIO_MANAGER_SYSFS ?= true 119 | ifeq ($(GB_AUDIO_MANAGER_SYSFS),true) 120 | gb-audio-manager-y += audio_manager_sysfs.o 121 | ccflags-y += -DGB_AUDIO_MANAGER_SYSFS 122 | endif 123 | 124 | all: module 125 | 126 | tools:: 127 | $(MAKE) -C tools KERNELDIR=$(realpath $(KERNELDIR)) 128 | 129 | module: 130 | $(MAKE) -C $(KERNELDIR) M=$(PWD) 131 | 132 | check: 133 | $(MAKE) -C $(KERNELDIR) M=$(PWD) C=2 CF="-D__CHECK_ENDIAN__" 134 | 135 | clean: 136 | rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c 137 | rm -f Module.markers Module.symvers modules.order 138 | rm -rf .tmp_versions Modules.symvers 139 | $(MAKE) -C tools clean 140 | 141 | coccicheck: 142 | $(MAKE) -C $(KERNELDIR) M=$(PWD) coccicheck 143 | 144 | install: module 145 | mkdir -p $(INSTALL_MOD_PATH)/lib/modules/$(KERNELVER)/kernel/drivers/greybus/ 146 | cp -f *.ko $(INSTALL_MOD_PATH)/lib/modules/$(KERNELVER)/kernel/drivers/greybus/ 147 | depmod -b $(INSTALL_MOD_PATH) -a $(KERNELVER) 148 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Greybus kernel code 2 | 3 | To build against the running kernel (odds are you don't want this): 4 | make 5 | 6 | To build against a specific kernel source tree (odds are you want this): 7 | KERNELDIR=/home/some/random/place make 8 | 9 | Any questions / concerns about this code base, please email: 10 | Greg Kroah-Hartman 11 | -------------------------------------------------------------------------------- /arche_platform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Arche Platform driver to enable Unipro link. 3 | * 4 | * Copyright 2015-2016 Google Inc. 5 | * Copyright 2015-2016 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __ARCHE_PLATFORM_H 11 | #define __ARCHE_PLATFORM_H 12 | 13 | #include "timesync.h" 14 | 15 | enum arche_platform_state { 16 | ARCHE_PLATFORM_STATE_OFF, 17 | ARCHE_PLATFORM_STATE_ACTIVE, 18 | ARCHE_PLATFORM_STATE_STANDBY, 19 | ARCHE_PLATFORM_STATE_FW_FLASHING, 20 | ARCHE_PLATFORM_STATE_TIME_SYNC, 21 | }; 22 | 23 | int arche_platform_change_state(enum arche_platform_state state, 24 | struct gb_timesync_svc *pdata); 25 | 26 | extern int (*arche_platform_change_state_cb)(enum arche_platform_state state, 27 | struct gb_timesync_svc *pdata); 28 | int __init arche_apb_init(void); 29 | void __exit arche_apb_exit(void); 30 | 31 | /* Operational states for the APB device */ 32 | int apb_ctrl_coldboot(struct device *dev); 33 | int apb_ctrl_fw_flashing(struct device *dev); 34 | int apb_ctrl_standby_boot(struct device *dev); 35 | void apb_ctrl_poweroff(struct device *dev); 36 | void apb_bootret_assert(struct device *dev); 37 | void apb_bootret_deassert(struct device *dev); 38 | 39 | #endif /* __ARCHE_PLATFORM_H */ 40 | -------------------------------------------------------------------------------- /arpc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is provided under a dual BSD/GPLv2 license. When using or 3 | * redistributing this file, you may do so under either license. 4 | * 5 | * GPL LICENSE SUMMARY 6 | * 7 | * Copyright(c) 2016 Google Inc. All rights reserved. 8 | * Copyright(c) 2016 Linaro Ltd. All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of version 2 of the GNU General Public License as 12 | * published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, but 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * General Public License version 2 for more details. 18 | * 19 | * BSD LICENSE 20 | * 21 | * Copyright(c) 2016 Google Inc. All rights reserved. 22 | * Copyright(c) 2016 Linaro Ltd. All rights reserved. 23 | * 24 | * Redistribution and use in source and binary forms, with or without 25 | * modification, are permitted provided that the following conditions 26 | * are met: 27 | * 28 | * * Redistributions of source code must retain the above copyright 29 | * notice, this list of conditions and the following disclaimer. 30 | * * Redistributions in binary form must reproduce the above copyright 31 | * notice, this list of conditions and the following disclaimer in 32 | * the documentation and/or other materials provided with the 33 | * distribution. 34 | * * Neither the name of Google Inc. or Linaro Ltd. nor the names of 35 | * its contributors may be used to endorse or promote products 36 | * derived from this software without specific prior written 37 | * permission. 38 | * 39 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 40 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 41 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 42 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR 43 | * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 44 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 45 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 46 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 47 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 48 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 49 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 | */ 51 | 52 | #ifndef __ARPC_H 53 | #define __ARPC_H 54 | 55 | /* APBridgeA RPC (ARPC) */ 56 | 57 | enum arpc_result { 58 | ARPC_SUCCESS = 0x00, 59 | ARPC_NO_MEMORY = 0x01, 60 | ARPC_INVALID = 0x02, 61 | ARPC_TIMEOUT = 0x03, 62 | ARPC_UNKNOWN_ERROR = 0xff, 63 | }; 64 | 65 | struct arpc_request_message { 66 | __le16 id; /* RPC unique id */ 67 | __le16 size; /* Size in bytes of header + payload */ 68 | __u8 type; /* RPC type */ 69 | __u8 data[0]; /* ARPC data */ 70 | } __packed; 71 | 72 | struct arpc_response_message { 73 | __le16 id; /* RPC unique id */ 74 | __u8 result; /* Result of RPC */ 75 | } __packed; 76 | 77 | 78 | /* ARPC requests */ 79 | #define ARPC_TYPE_CPORT_CONNECTED 0x01 80 | #define ARPC_TYPE_CPORT_QUIESCE 0x02 81 | #define ARPC_TYPE_CPORT_CLEAR 0x03 82 | #define ARPC_TYPE_CPORT_FLUSH 0x04 83 | #define ARPC_TYPE_CPORT_SHUTDOWN 0x05 84 | 85 | struct arpc_cport_connected_req { 86 | __le16 cport_id; 87 | } __packed; 88 | 89 | struct arpc_cport_quiesce_req { 90 | __le16 cport_id; 91 | __le16 peer_space; 92 | __le16 timeout; 93 | } __packed; 94 | 95 | struct arpc_cport_clear_req { 96 | __le16 cport_id; 97 | } __packed; 98 | 99 | struct arpc_cport_flush_req { 100 | __le16 cport_id; 101 | } __packed; 102 | 103 | struct arpc_cport_shutdown_req { 104 | __le16 cport_id; 105 | __le16 timeout; 106 | __u8 phase; 107 | } __packed; 108 | 109 | #endif /* __ARPC_H */ 110 | -------------------------------------------------------------------------------- /audio_apbridgea.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Audio Device Class Protocol helpers 3 | * 4 | * Copyright 2015-2016 Google Inc. 5 | * 6 | * Released under the GPLv2 only. 7 | */ 8 | 9 | #include "greybus.h" 10 | #include "greybus_protocols.h" 11 | #include "audio_apbridgea.h" 12 | #include "audio_codec.h" 13 | 14 | int gb_audio_apbridgea_set_config(struct gb_connection *connection, 15 | __u16 i2s_port, __u32 format, __u32 rate, 16 | __u32 mclk_freq) 17 | { 18 | struct audio_apbridgea_set_config_request req; 19 | 20 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_CONFIG; 21 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 22 | req.format = cpu_to_le32(format); 23 | req.rate = cpu_to_le32(rate); 24 | req.mclk_freq = cpu_to_le32(mclk_freq); 25 | 26 | return gb_hd_output(connection->hd, &req, sizeof(req), 27 | GB_APB_REQUEST_AUDIO_CONTROL, true); 28 | } 29 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_config); 30 | 31 | int gb_audio_apbridgea_register_cport(struct gb_connection *connection, 32 | __u16 i2s_port, __u16 cportid, 33 | __u8 direction) 34 | { 35 | struct audio_apbridgea_register_cport_request req; 36 | int ret; 37 | 38 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_REGISTER_CPORT; 39 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 40 | req.cport = cpu_to_le16(cportid); 41 | req.direction = direction; 42 | 43 | ret = gb_pm_runtime_get_sync(connection->bundle); 44 | if (ret) 45 | return ret; 46 | 47 | return gb_hd_output(connection->hd, &req, sizeof(req), 48 | GB_APB_REQUEST_AUDIO_CONTROL, true); 49 | } 50 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_register_cport); 51 | 52 | int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection, 53 | __u16 i2s_port, __u16 cportid, 54 | __u8 direction) 55 | { 56 | struct audio_apbridgea_unregister_cport_request req; 57 | int ret; 58 | 59 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT; 60 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 61 | req.cport = cpu_to_le16(cportid); 62 | req.direction = direction; 63 | 64 | ret = gb_hd_output(connection->hd, &req, sizeof(req), 65 | GB_APB_REQUEST_AUDIO_CONTROL, true); 66 | 67 | gb_pm_runtime_put_autosuspend(connection->bundle); 68 | 69 | return ret; 70 | } 71 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_unregister_cport); 72 | 73 | int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection, 74 | __u16 i2s_port, __u16 size) 75 | { 76 | struct audio_apbridgea_set_tx_data_size_request req; 77 | 78 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_TX_DATA_SIZE; 79 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 80 | req.size = cpu_to_le16(size); 81 | 82 | return gb_hd_output(connection->hd, &req, sizeof(req), 83 | GB_APB_REQUEST_AUDIO_CONTROL, true); 84 | } 85 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_tx_data_size); 86 | 87 | int gb_audio_apbridgea_prepare_tx(struct gb_connection *connection, 88 | __u16 i2s_port) 89 | { 90 | struct audio_apbridgea_prepare_tx_request req; 91 | 92 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_PREPARE_TX; 93 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 94 | 95 | return gb_hd_output(connection->hd, &req, sizeof(req), 96 | GB_APB_REQUEST_AUDIO_CONTROL, true); 97 | } 98 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_tx); 99 | 100 | int gb_audio_apbridgea_start_tx(struct gb_connection *connection, 101 | __u16 i2s_port, __u64 timestamp) 102 | { 103 | struct audio_apbridgea_start_tx_request req; 104 | 105 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_START_TX; 106 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 107 | req.timestamp = cpu_to_le64(timestamp); 108 | 109 | return gb_hd_output(connection->hd, &req, sizeof(req), 110 | GB_APB_REQUEST_AUDIO_CONTROL, true); 111 | } 112 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_start_tx); 113 | 114 | int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, __u16 i2s_port) 115 | { 116 | struct audio_apbridgea_stop_tx_request req; 117 | 118 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_STOP_TX; 119 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 120 | 121 | return gb_hd_output(connection->hd, &req, sizeof(req), 122 | GB_APB_REQUEST_AUDIO_CONTROL, true); 123 | } 124 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_tx); 125 | 126 | int gb_audio_apbridgea_shutdown_tx(struct gb_connection *connection, 127 | __u16 i2s_port) 128 | { 129 | struct audio_apbridgea_shutdown_tx_request req; 130 | 131 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_SHUTDOWN_TX; 132 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 133 | 134 | return gb_hd_output(connection->hd, &req, sizeof(req), 135 | GB_APB_REQUEST_AUDIO_CONTROL, true); 136 | } 137 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_tx); 138 | 139 | int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection, 140 | __u16 i2s_port, __u16 size) 141 | { 142 | struct audio_apbridgea_set_rx_data_size_request req; 143 | 144 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE; 145 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 146 | req.size = cpu_to_le16(size); 147 | 148 | return gb_hd_output(connection->hd, &req, sizeof(req), 149 | GB_APB_REQUEST_AUDIO_CONTROL, true); 150 | } 151 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_rx_data_size); 152 | 153 | int gb_audio_apbridgea_prepare_rx(struct gb_connection *connection, 154 | __u16 i2s_port) 155 | { 156 | struct audio_apbridgea_prepare_rx_request req; 157 | 158 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_PREPARE_RX; 159 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 160 | 161 | return gb_hd_output(connection->hd, &req, sizeof(req), 162 | GB_APB_REQUEST_AUDIO_CONTROL, true); 163 | } 164 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_rx); 165 | 166 | int gb_audio_apbridgea_start_rx(struct gb_connection *connection, 167 | __u16 i2s_port) 168 | { 169 | struct audio_apbridgea_start_rx_request req; 170 | 171 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_START_RX; 172 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 173 | 174 | return gb_hd_output(connection->hd, &req, sizeof(req), 175 | GB_APB_REQUEST_AUDIO_CONTROL, true); 176 | } 177 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_start_rx); 178 | 179 | int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, __u16 i2s_port) 180 | { 181 | struct audio_apbridgea_stop_rx_request req; 182 | 183 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_STOP_RX; 184 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 185 | 186 | return gb_hd_output(connection->hd, &req, sizeof(req), 187 | GB_APB_REQUEST_AUDIO_CONTROL, true); 188 | } 189 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_rx); 190 | 191 | int gb_audio_apbridgea_shutdown_rx(struct gb_connection *connection, 192 | __u16 i2s_port) 193 | { 194 | struct audio_apbridgea_shutdown_rx_request req; 195 | 196 | req.hdr.type = AUDIO_APBRIDGEA_TYPE_SHUTDOWN_RX; 197 | req.hdr.i2s_port = cpu_to_le16(i2s_port); 198 | 199 | return gb_hd_output(connection->hd, &req, sizeof(req), 200 | GB_APB_REQUEST_AUDIO_CONTROL, true); 201 | } 202 | EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_rx); 203 | 204 | MODULE_LICENSE("GPL v2"); 205 | MODULE_ALIAS("greybus:audio-apbridgea"); 206 | MODULE_DESCRIPTION("Greybus Special APBridgeA Audio Protocol library"); 207 | MODULE_AUTHOR("Mark Greer "); 208 | -------------------------------------------------------------------------------- /audio_apbridgea.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-2016 Google Inc. 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 are met: 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * 3. Neither the name of the copyright holder nor the names of its 13 | * contributors may be used to endorse or promote products derived from this 14 | * software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | /* 29 | * This is a special protocol for configuring communication over the 30 | * I2S bus between the DSP on the MSM8994 and APBridgeA. Therefore, 31 | * we can predefine several low-level attributes of the communication 32 | * because we know that they are supported. In particular, the following 33 | * assumptions are made: 34 | * - there are two channels (i.e., stereo) 35 | * - the low-level protocol is I2S as defined by Philips/NXP 36 | * - the DSP on the MSM8994 is the clock master for MCLK, BCLK, and WCLK 37 | * - WCLK changes on the falling edge of BCLK 38 | * - WCLK low for left channel; high for right channel 39 | * - TX data is sent on the falling edge of BCLK 40 | * - RX data is received/latched on the rising edge of BCLK 41 | */ 42 | 43 | #ifndef __AUDIO_APBRIDGEA_H 44 | #define __AUDIO_APBRIDGEA_H 45 | 46 | #define AUDIO_APBRIDGEA_TYPE_SET_CONFIG 0x01 47 | #define AUDIO_APBRIDGEA_TYPE_REGISTER_CPORT 0x02 48 | #define AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT 0x03 49 | #define AUDIO_APBRIDGEA_TYPE_SET_TX_DATA_SIZE 0x04 50 | /* 0x05 unused */ 51 | #define AUDIO_APBRIDGEA_TYPE_PREPARE_TX 0x06 52 | #define AUDIO_APBRIDGEA_TYPE_START_TX 0x07 53 | #define AUDIO_APBRIDGEA_TYPE_STOP_TX 0x08 54 | #define AUDIO_APBRIDGEA_TYPE_SHUTDOWN_TX 0x09 55 | #define AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE 0x0a 56 | /* 0x0b unused */ 57 | #define AUDIO_APBRIDGEA_TYPE_PREPARE_RX 0x0c 58 | #define AUDIO_APBRIDGEA_TYPE_START_RX 0x0d 59 | #define AUDIO_APBRIDGEA_TYPE_STOP_RX 0x0e 60 | #define AUDIO_APBRIDGEA_TYPE_SHUTDOWN_RX 0x0f 61 | 62 | #define AUDIO_APBRIDGEA_PCM_FMT_8 BIT(0) 63 | #define AUDIO_APBRIDGEA_PCM_FMT_16 BIT(1) 64 | #define AUDIO_APBRIDGEA_PCM_FMT_24 BIT(2) 65 | #define AUDIO_APBRIDGEA_PCM_FMT_32 BIT(3) 66 | #define AUDIO_APBRIDGEA_PCM_FMT_64 BIT(4) 67 | 68 | #define AUDIO_APBRIDGEA_PCM_RATE_5512 BIT(0) 69 | #define AUDIO_APBRIDGEA_PCM_RATE_8000 BIT(1) 70 | #define AUDIO_APBRIDGEA_PCM_RATE_11025 BIT(2) 71 | #define AUDIO_APBRIDGEA_PCM_RATE_16000 BIT(3) 72 | #define AUDIO_APBRIDGEA_PCM_RATE_22050 BIT(4) 73 | #define AUDIO_APBRIDGEA_PCM_RATE_32000 BIT(5) 74 | #define AUDIO_APBRIDGEA_PCM_RATE_44100 BIT(6) 75 | #define AUDIO_APBRIDGEA_PCM_RATE_48000 BIT(7) 76 | #define AUDIO_APBRIDGEA_PCM_RATE_64000 BIT(8) 77 | #define AUDIO_APBRIDGEA_PCM_RATE_88200 BIT(9) 78 | #define AUDIO_APBRIDGEA_PCM_RATE_96000 BIT(10) 79 | #define AUDIO_APBRIDGEA_PCM_RATE_176400 BIT(11) 80 | #define AUDIO_APBRIDGEA_PCM_RATE_192000 BIT(12) 81 | 82 | #define AUDIO_APBRIDGEA_DIRECTION_TX BIT(0) 83 | #define AUDIO_APBRIDGEA_DIRECTION_RX BIT(1) 84 | 85 | /* The I2S port is passed in the 'index' parameter of the USB request */ 86 | /* The CPort is passed in the 'value' parameter of the USB request */ 87 | 88 | struct audio_apbridgea_hdr { 89 | __u8 type; 90 | __le16 i2s_port; 91 | __u8 data[0]; 92 | } __packed; 93 | 94 | struct audio_apbridgea_set_config_request { 95 | struct audio_apbridgea_hdr hdr; 96 | __le32 format; /* AUDIO_APBRIDGEA_PCM_FMT_* */ 97 | __le32 rate; /* AUDIO_APBRIDGEA_PCM_RATE_* */ 98 | __le32 mclk_freq; /* XXX Remove? */ 99 | } __packed; 100 | 101 | struct audio_apbridgea_register_cport_request { 102 | struct audio_apbridgea_hdr hdr; 103 | __le16 cport; 104 | __u8 direction; 105 | } __packed; 106 | 107 | struct audio_apbridgea_unregister_cport_request { 108 | struct audio_apbridgea_hdr hdr; 109 | __le16 cport; 110 | __u8 direction; 111 | } __packed; 112 | 113 | struct audio_apbridgea_set_tx_data_size_request { 114 | struct audio_apbridgea_hdr hdr; 115 | __le16 size; 116 | } __packed; 117 | 118 | struct audio_apbridgea_prepare_tx_request { 119 | struct audio_apbridgea_hdr hdr; 120 | } __packed; 121 | 122 | struct audio_apbridgea_start_tx_request { 123 | struct audio_apbridgea_hdr hdr; 124 | __le64 timestamp; 125 | } __packed; 126 | 127 | struct audio_apbridgea_stop_tx_request { 128 | struct audio_apbridgea_hdr hdr; 129 | } __packed; 130 | 131 | struct audio_apbridgea_shutdown_tx_request { 132 | struct audio_apbridgea_hdr hdr; 133 | } __packed; 134 | 135 | struct audio_apbridgea_set_rx_data_size_request { 136 | struct audio_apbridgea_hdr hdr; 137 | __le16 size; 138 | } __packed; 139 | 140 | struct audio_apbridgea_prepare_rx_request { 141 | struct audio_apbridgea_hdr hdr; 142 | } __packed; 143 | 144 | struct audio_apbridgea_start_rx_request { 145 | struct audio_apbridgea_hdr hdr; 146 | } __packed; 147 | 148 | struct audio_apbridgea_stop_rx_request { 149 | struct audio_apbridgea_hdr hdr; 150 | } __packed; 151 | 152 | struct audio_apbridgea_shutdown_rx_request { 153 | struct audio_apbridgea_hdr hdr; 154 | } __packed; 155 | 156 | #endif /*__AUDIO_APBRIDGEA_H */ 157 | -------------------------------------------------------------------------------- /audio_codec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus audio driver 3 | * Copyright 2015 Google Inc. 4 | * Copyright 2015 Linaro Ltd. 5 | * 6 | * Released under the GPLv2 only. 7 | */ 8 | 9 | #ifndef __LINUX_GBAUDIO_CODEC_H 10 | #define __LINUX_GBAUDIO_CODEC_H 11 | 12 | #include 13 | #include 14 | 15 | #include "greybus.h" 16 | #include "greybus_protocols.h" 17 | 18 | #define NAME_SIZE 32 19 | #define MAX_DAIS 2 /* APB1, APB2 */ 20 | 21 | enum { 22 | APB1_PCM = 0, 23 | APB2_PCM, 24 | NUM_CODEC_DAIS, 25 | }; 26 | 27 | enum gbcodec_reg_index { 28 | GBCODEC_CTL_REG, 29 | GBCODEC_MUTE_REG, 30 | GBCODEC_PB_LVOL_REG, 31 | GBCODEC_PB_RVOL_REG, 32 | GBCODEC_CAP_LVOL_REG, 33 | GBCODEC_CAP_RVOL_REG, 34 | GBCODEC_APB1_MUX_REG, 35 | GBCODEC_APB2_MUX_REG, 36 | GBCODEC_REG_COUNT 37 | }; 38 | 39 | /* device_type should be same as defined in audio.h (Android media layer) */ 40 | enum { 41 | GBAUDIO_DEVICE_NONE = 0x0, 42 | /* reserved bits */ 43 | GBAUDIO_DEVICE_BIT_IN = 0x80000000, 44 | GBAUDIO_DEVICE_BIT_DEFAULT = 0x40000000, 45 | /* output devices */ 46 | GBAUDIO_DEVICE_OUT_SPEAKER = 0x2, 47 | GBAUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4, 48 | GBAUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8, 49 | /* input devices */ 50 | GBAUDIO_DEVICE_IN_BUILTIN_MIC = GBAUDIO_DEVICE_BIT_IN | 0x4, 51 | GBAUDIO_DEVICE_IN_WIRED_HEADSET = GBAUDIO_DEVICE_BIT_IN | 0x10, 52 | }; 53 | 54 | /* bit 0-SPK, 1-HP, 2-DAC, 55 | * 4-MIC, 5-HSMIC, 6-MIC2 56 | */ 57 | #define GBCODEC_CTL_REG_DEFAULT 0x00 58 | 59 | /* bit 0,1 - APB1-PB-L/R 60 | * bit 2,3 - APB2-PB-L/R 61 | * bit 4,5 - APB1-Cap-L/R 62 | * bit 6,7 - APB2-Cap-L/R 63 | */ 64 | #define GBCODEC_MUTE_REG_DEFAULT 0x00 65 | 66 | /* 0-127 steps */ 67 | #define GBCODEC_PB_VOL_REG_DEFAULT 0x00 68 | #define GBCODEC_CAP_VOL_REG_DEFAULT 0x00 69 | 70 | /* bit 0,1,2 - PB stereo, left, right 71 | * bit 8,9,10 - Cap stereo, left, right 72 | */ 73 | #define GBCODEC_APB1_MUX_REG_DEFAULT 0x00 74 | #define GBCODEC_APB2_MUX_REG_DEFAULT 0x00 75 | 76 | #define GBCODEC_JACK_MASK 0x0000FFFF 77 | #define GBCODEC_JACK_BUTTON_MASK 0xFFFF0000 78 | 79 | static const u8 gbcodec_reg_defaults[GBCODEC_REG_COUNT] = { 80 | GBCODEC_CTL_REG_DEFAULT, 81 | GBCODEC_MUTE_REG_DEFAULT, 82 | GBCODEC_PB_VOL_REG_DEFAULT, 83 | GBCODEC_PB_VOL_REG_DEFAULT, 84 | GBCODEC_CAP_VOL_REG_DEFAULT, 85 | GBCODEC_CAP_VOL_REG_DEFAULT, 86 | GBCODEC_APB1_MUX_REG_DEFAULT, 87 | GBCODEC_APB2_MUX_REG_DEFAULT, 88 | }; 89 | 90 | enum gbaudio_codec_state { 91 | GBAUDIO_CODEC_SHUTDOWN = 0, 92 | GBAUDIO_CODEC_STARTUP, 93 | GBAUDIO_CODEC_HWPARAMS, 94 | GBAUDIO_CODEC_PREPARE, 95 | GBAUDIO_CODEC_START, 96 | GBAUDIO_CODEC_STOP, 97 | }; 98 | 99 | struct gbaudio_stream_params { 100 | int state; 101 | uint8_t sig_bits, channels; 102 | uint32_t format, rate; 103 | }; 104 | 105 | struct gbaudio_codec_dai { 106 | int id; 107 | /* runtime params for playback/capture streams */ 108 | struct gbaudio_stream_params params[2]; 109 | struct list_head list; 110 | }; 111 | 112 | struct gbaudio_codec_info { 113 | struct device *dev; 114 | struct snd_soc_codec *codec; 115 | struct list_head module_list; 116 | /* to maintain runtime stream params for each DAI */ 117 | struct list_head dai_list; 118 | struct mutex lock; 119 | u8 reg[GBCODEC_REG_COUNT]; 120 | }; 121 | 122 | struct gbaudio_widget { 123 | __u8 id; 124 | const char *name; 125 | struct list_head list; 126 | }; 127 | 128 | struct gbaudio_control { 129 | __u8 id; 130 | char *name; 131 | char *wname; 132 | const char * const *texts; 133 | int items; 134 | struct list_head list; 135 | }; 136 | 137 | struct gbaudio_data_connection { 138 | int id; 139 | __le16 data_cport; 140 | struct gb_connection *connection; 141 | struct list_head list; 142 | /* maintain runtime state for playback/capture stream */ 143 | int state[2]; 144 | }; 145 | 146 | /* stream direction */ 147 | #define GB_PLAYBACK BIT(0) 148 | #define GB_CAPTURE BIT(1) 149 | 150 | enum gbaudio_module_state { 151 | GBAUDIO_MODULE_OFF = 0, 152 | GBAUDIO_MODULE_ON, 153 | }; 154 | 155 | struct gbaudio_module_info { 156 | /* module info */ 157 | struct device *dev; 158 | int dev_id; /* check if it should be bundle_id/hd_cport_id */ 159 | int vid; 160 | int pid; 161 | int slot; 162 | int type; 163 | int set_uevent; 164 | char vstr[NAME_SIZE]; 165 | char pstr[NAME_SIZE]; 166 | struct list_head list; 167 | /* need to share this info to above user space */ 168 | int manager_id; 169 | char name[NAME_SIZE]; 170 | unsigned int ip_devices; 171 | unsigned int op_devices; 172 | 173 | /* jack related */ 174 | char jack_name[NAME_SIZE]; 175 | char button_name[NAME_SIZE]; 176 | int jack_type; 177 | int jack_mask; 178 | int button_mask; 179 | int button_status; 180 | struct snd_soc_jack headset_jack; 181 | struct snd_soc_jack button_jack; 182 | 183 | /* connection info */ 184 | struct gb_connection *mgmt_connection; 185 | size_t num_data_connections; 186 | struct list_head data_list; 187 | 188 | /* topology related */ 189 | int num_dais; 190 | int num_controls; 191 | int num_dapm_widgets; 192 | int num_dapm_routes; 193 | unsigned long dai_offset; 194 | unsigned long widget_offset; 195 | unsigned long control_offset; 196 | unsigned long route_offset; 197 | struct snd_kcontrol_new *controls; 198 | struct snd_soc_dapm_widget *dapm_widgets; 199 | struct snd_soc_dapm_route *dapm_routes; 200 | struct snd_soc_dai_driver *dais; 201 | 202 | struct list_head widget_list; 203 | struct list_head ctl_list; 204 | struct list_head widget_ctl_list; 205 | 206 | struct gb_audio_topology *topology; 207 | }; 208 | 209 | int gbaudio_tplg_parse_data(struct gbaudio_module_info *module, 210 | struct gb_audio_topology *tplg_data); 211 | void gbaudio_tplg_release(struct gbaudio_module_info *module); 212 | 213 | int gbaudio_module_update(struct gbaudio_codec_info *codec, 214 | struct snd_soc_dapm_widget *w, 215 | struct gbaudio_module_info *module, 216 | int enable); 217 | int gbaudio_register_module(struct gbaudio_module_info *module); 218 | void gbaudio_unregister_module(struct gbaudio_module_info *module); 219 | 220 | /* protocol related */ 221 | extern int gb_audio_gb_get_topology(struct gb_connection *connection, 222 | struct gb_audio_topology **topology); 223 | extern int gb_audio_gb_get_control(struct gb_connection *connection, 224 | uint8_t control_id, uint8_t index, 225 | struct gb_audio_ctl_elem_value *value); 226 | extern int gb_audio_gb_set_control(struct gb_connection *connection, 227 | uint8_t control_id, uint8_t index, 228 | struct gb_audio_ctl_elem_value *value); 229 | extern int gb_audio_gb_enable_widget(struct gb_connection *connection, 230 | uint8_t widget_id); 231 | extern int gb_audio_gb_disable_widget(struct gb_connection *connection, 232 | uint8_t widget_id); 233 | extern int gb_audio_gb_get_pcm(struct gb_connection *connection, 234 | uint16_t data_cport, uint32_t *format, 235 | uint32_t *rate, uint8_t *channels, 236 | uint8_t *sig_bits); 237 | extern int gb_audio_gb_set_pcm(struct gb_connection *connection, 238 | uint16_t data_cport, uint32_t format, 239 | uint32_t rate, uint8_t channels, 240 | uint8_t sig_bits); 241 | extern int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, 242 | uint16_t data_cport, uint16_t size); 243 | extern int gb_audio_gb_activate_tx(struct gb_connection *connection, 244 | uint16_t data_cport); 245 | extern int gb_audio_gb_deactivate_tx(struct gb_connection *connection, 246 | uint16_t data_cport); 247 | extern int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, 248 | uint16_t data_cport, uint16_t size); 249 | extern int gb_audio_gb_activate_rx(struct gb_connection *connection, 250 | uint16_t data_cport); 251 | extern int gb_audio_gb_deactivate_rx(struct gb_connection *connection, 252 | uint16_t data_cport); 253 | extern int gb_audio_apbridgea_set_config(struct gb_connection *connection, 254 | __u16 i2s_port, __u32 format, 255 | __u32 rate, __u32 mclk_freq); 256 | extern int gb_audio_apbridgea_register_cport(struct gb_connection *connection, 257 | __u16 i2s_port, __u16 cportid, 258 | __u8 direction); 259 | extern int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection, 260 | __u16 i2s_port, __u16 cportid, 261 | __u8 direction); 262 | extern int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection, 263 | __u16 i2s_port, __u16 size); 264 | extern int gb_audio_apbridgea_prepare_tx(struct gb_connection *connection, 265 | __u16 i2s_port); 266 | extern int gb_audio_apbridgea_start_tx(struct gb_connection *connection, 267 | __u16 i2s_port, __u64 timestamp); 268 | extern int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, 269 | __u16 i2s_port); 270 | extern int gb_audio_apbridgea_shutdown_tx(struct gb_connection *connection, 271 | __u16 i2s_port); 272 | extern int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection, 273 | __u16 i2s_port, __u16 size); 274 | extern int gb_audio_apbridgea_prepare_rx(struct gb_connection *connection, 275 | __u16 i2s_port); 276 | extern int gb_audio_apbridgea_start_rx(struct gb_connection *connection, 277 | __u16 i2s_port); 278 | extern int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, 279 | __u16 i2s_port); 280 | extern int gb_audio_apbridgea_shutdown_rx(struct gb_connection *connection, 281 | __u16 i2s_port); 282 | 283 | #endif /* __LINUX_GBAUDIO_CODEC_H */ 284 | -------------------------------------------------------------------------------- /audio_gb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Audio Device Class Protocol helpers 3 | * 4 | * Copyright 2015-2016 Google Inc. 5 | * 6 | * Released under the GPLv2 only. 7 | */ 8 | 9 | #include "greybus.h" 10 | #include "greybus_protocols.h" 11 | #include "operation.h" 12 | #include "audio_codec.h" 13 | 14 | /* TODO: Split into separate calls */ 15 | int gb_audio_gb_get_topology(struct gb_connection *connection, 16 | struct gb_audio_topology **topology) 17 | { 18 | struct gb_audio_get_topology_size_response size_resp; 19 | struct gb_audio_topology *topo; 20 | uint16_t size; 21 | int ret; 22 | 23 | ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE, 24 | NULL, 0, &size_resp, sizeof(size_resp)); 25 | if (ret) 26 | return ret; 27 | 28 | size = le16_to_cpu(size_resp.size); 29 | if (size < sizeof(*topo)) 30 | return -ENODATA; 31 | 32 | topo = kzalloc(size, GFP_KERNEL); 33 | if (!topo) 34 | return -ENOMEM; 35 | 36 | ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY, NULL, 0, 37 | topo, size); 38 | if (ret) { 39 | kfree(topo); 40 | return ret; 41 | } 42 | 43 | *topology = topo; 44 | 45 | return 0; 46 | } 47 | EXPORT_SYMBOL_GPL(gb_audio_gb_get_topology); 48 | 49 | int gb_audio_gb_get_control(struct gb_connection *connection, 50 | uint8_t control_id, uint8_t index, 51 | struct gb_audio_ctl_elem_value *value) 52 | { 53 | struct gb_audio_get_control_request req; 54 | struct gb_audio_get_control_response resp; 55 | int ret; 56 | 57 | req.control_id = control_id; 58 | req.index = index; 59 | 60 | ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_CONTROL, 61 | &req, sizeof(req), &resp, sizeof(resp)); 62 | if (ret) 63 | return ret; 64 | 65 | memcpy(value, &resp.value, sizeof(*value)); 66 | 67 | return 0; 68 | } 69 | EXPORT_SYMBOL_GPL(gb_audio_gb_get_control); 70 | 71 | int gb_audio_gb_set_control(struct gb_connection *connection, 72 | uint8_t control_id, uint8_t index, 73 | struct gb_audio_ctl_elem_value *value) 74 | { 75 | struct gb_audio_set_control_request req; 76 | 77 | req.control_id = control_id; 78 | req.index = index; 79 | memcpy(&req.value, value, sizeof(req.value)); 80 | 81 | return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_CONTROL, 82 | &req, sizeof(req), NULL, 0); 83 | } 84 | EXPORT_SYMBOL_GPL(gb_audio_gb_set_control); 85 | 86 | int gb_audio_gb_enable_widget(struct gb_connection *connection, 87 | uint8_t widget_id) 88 | { 89 | struct gb_audio_enable_widget_request req; 90 | 91 | req.widget_id = widget_id; 92 | 93 | return gb_operation_sync(connection, GB_AUDIO_TYPE_ENABLE_WIDGET, 94 | &req, sizeof(req), NULL, 0); 95 | } 96 | EXPORT_SYMBOL_GPL(gb_audio_gb_enable_widget); 97 | 98 | int gb_audio_gb_disable_widget(struct gb_connection *connection, 99 | uint8_t widget_id) 100 | { 101 | struct gb_audio_disable_widget_request req; 102 | 103 | req.widget_id = widget_id; 104 | 105 | return gb_operation_sync(connection, GB_AUDIO_TYPE_DISABLE_WIDGET, 106 | &req, sizeof(req), NULL, 0); 107 | } 108 | EXPORT_SYMBOL_GPL(gb_audio_gb_disable_widget); 109 | 110 | int gb_audio_gb_get_pcm(struct gb_connection *connection, uint16_t data_cport, 111 | uint32_t *format, uint32_t *rate, uint8_t *channels, 112 | uint8_t *sig_bits) 113 | { 114 | struct gb_audio_get_pcm_request req; 115 | struct gb_audio_get_pcm_response resp; 116 | int ret; 117 | 118 | req.data_cport = cpu_to_le16(data_cport); 119 | 120 | ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_PCM, 121 | &req, sizeof(req), &resp, sizeof(resp)); 122 | if (ret) 123 | return ret; 124 | 125 | *format = le32_to_cpu(resp.format); 126 | *rate = le32_to_cpu(resp.rate); 127 | *channels = resp.channels; 128 | *sig_bits = resp.sig_bits; 129 | 130 | return 0; 131 | } 132 | EXPORT_SYMBOL_GPL(gb_audio_gb_get_pcm); 133 | 134 | int gb_audio_gb_set_pcm(struct gb_connection *connection, uint16_t data_cport, 135 | uint32_t format, uint32_t rate, uint8_t channels, 136 | uint8_t sig_bits) 137 | { 138 | struct gb_audio_set_pcm_request req; 139 | 140 | req.data_cport = cpu_to_le16(data_cport); 141 | req.format = cpu_to_le32(format); 142 | req.rate = cpu_to_le32(rate); 143 | req.channels = channels; 144 | req.sig_bits = sig_bits; 145 | 146 | return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_PCM, 147 | &req, sizeof(req), NULL, 0); 148 | } 149 | EXPORT_SYMBOL_GPL(gb_audio_gb_set_pcm); 150 | 151 | int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, 152 | uint16_t data_cport, uint16_t size) 153 | { 154 | struct gb_audio_set_tx_data_size_request req; 155 | 156 | req.data_cport = cpu_to_le16(data_cport); 157 | req.size = cpu_to_le16(size); 158 | 159 | return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_TX_DATA_SIZE, 160 | &req, sizeof(req), NULL, 0); 161 | } 162 | EXPORT_SYMBOL_GPL(gb_audio_gb_set_tx_data_size); 163 | 164 | int gb_audio_gb_activate_tx(struct gb_connection *connection, 165 | uint16_t data_cport) 166 | { 167 | struct gb_audio_activate_tx_request req; 168 | 169 | req.data_cport = cpu_to_le16(data_cport); 170 | 171 | return gb_operation_sync(connection, GB_AUDIO_TYPE_ACTIVATE_TX, 172 | &req, sizeof(req), NULL, 0); 173 | } 174 | EXPORT_SYMBOL_GPL(gb_audio_gb_activate_tx); 175 | 176 | int gb_audio_gb_deactivate_tx(struct gb_connection *connection, 177 | uint16_t data_cport) 178 | { 179 | struct gb_audio_deactivate_tx_request req; 180 | 181 | req.data_cport = cpu_to_le16(data_cport); 182 | 183 | return gb_operation_sync(connection, GB_AUDIO_TYPE_DEACTIVATE_TX, 184 | &req, sizeof(req), NULL, 0); 185 | } 186 | EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_tx); 187 | 188 | int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, 189 | uint16_t data_cport, uint16_t size) 190 | { 191 | struct gb_audio_set_rx_data_size_request req; 192 | 193 | req.data_cport = cpu_to_le16(data_cport); 194 | req.size = cpu_to_le16(size); 195 | 196 | return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_RX_DATA_SIZE, 197 | &req, sizeof(req), NULL, 0); 198 | } 199 | EXPORT_SYMBOL_GPL(gb_audio_gb_set_rx_data_size); 200 | 201 | int gb_audio_gb_activate_rx(struct gb_connection *connection, 202 | uint16_t data_cport) 203 | { 204 | struct gb_audio_activate_rx_request req; 205 | 206 | req.data_cport = cpu_to_le16(data_cport); 207 | 208 | return gb_operation_sync(connection, GB_AUDIO_TYPE_ACTIVATE_RX, 209 | &req, sizeof(req), NULL, 0); 210 | } 211 | EXPORT_SYMBOL_GPL(gb_audio_gb_activate_rx); 212 | 213 | int gb_audio_gb_deactivate_rx(struct gb_connection *connection, 214 | uint16_t data_cport) 215 | { 216 | struct gb_audio_deactivate_rx_request req; 217 | 218 | req.data_cport = cpu_to_le16(data_cport); 219 | 220 | return gb_operation_sync(connection, GB_AUDIO_TYPE_DEACTIVATE_RX, 221 | &req, sizeof(req), NULL, 0); 222 | } 223 | EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_rx); 224 | 225 | MODULE_LICENSE("GPL v2"); 226 | MODULE_ALIAS("greybus:audio-gb"); 227 | MODULE_DESCRIPTION("Greybus Audio Device Class Protocol library"); 228 | MODULE_AUTHOR("Mark Greer "); 229 | -------------------------------------------------------------------------------- /audio_manager.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus operations 3 | * 4 | * Copyright 2015-2016 Google Inc. 5 | * 6 | * Released under the GPLv2 only. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "audio_manager.h" 17 | #include "audio_manager_private.h" 18 | 19 | static struct kset *manager_kset; 20 | 21 | static LIST_HEAD(modules_list); 22 | static DECLARE_RWSEM(modules_rwsem); 23 | static DEFINE_IDA(module_id); 24 | 25 | /* helpers */ 26 | static struct gb_audio_manager_module *gb_audio_manager_get_locked(int id) 27 | { 28 | struct gb_audio_manager_module *module; 29 | 30 | if (id < 0) 31 | return NULL; 32 | 33 | list_for_each_entry(module, &modules_list, list) { 34 | if (module->id == id) 35 | return module; 36 | } 37 | 38 | return NULL; 39 | } 40 | 41 | /* public API */ 42 | int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc) 43 | { 44 | struct gb_audio_manager_module *module; 45 | int id; 46 | int err; 47 | 48 | id = ida_simple_get(&module_id, 0, 0, GFP_KERNEL); 49 | err = gb_audio_manager_module_create(&module, manager_kset, 50 | id, desc); 51 | if (err) { 52 | ida_simple_remove(&module_id, id); 53 | return err; 54 | } 55 | 56 | /* Add it to the list */ 57 | down_write(&modules_rwsem); 58 | list_add_tail(&module->list, &modules_list); 59 | up_write(&modules_rwsem); 60 | 61 | return module->id; 62 | } 63 | EXPORT_SYMBOL_GPL(gb_audio_manager_add); 64 | 65 | int gb_audio_manager_remove(int id) 66 | { 67 | struct gb_audio_manager_module *module; 68 | 69 | down_write(&modules_rwsem); 70 | 71 | module = gb_audio_manager_get_locked(id); 72 | if (!module) { 73 | up_write(&modules_rwsem); 74 | return -EINVAL; 75 | } 76 | list_del(&module->list); 77 | kobject_put(&module->kobj); 78 | up_write(&modules_rwsem); 79 | ida_simple_remove(&module_id, id); 80 | return 0; 81 | } 82 | EXPORT_SYMBOL_GPL(gb_audio_manager_remove); 83 | 84 | void gb_audio_manager_remove_all(void) 85 | { 86 | struct gb_audio_manager_module *module, *next; 87 | int is_empty = 1; 88 | 89 | down_write(&modules_rwsem); 90 | 91 | list_for_each_entry_safe(module, next, &modules_list, list) { 92 | list_del(&module->list); 93 | kobject_put(&module->kobj); 94 | ida_simple_remove(&module_id, module->id); 95 | } 96 | 97 | is_empty = list_empty(&modules_list); 98 | 99 | up_write(&modules_rwsem); 100 | 101 | if (!is_empty) 102 | pr_warn("Not all nodes were deleted\n"); 103 | } 104 | EXPORT_SYMBOL_GPL(gb_audio_manager_remove_all); 105 | 106 | struct gb_audio_manager_module *gb_audio_manager_get_module(int id) 107 | { 108 | struct gb_audio_manager_module *module; 109 | 110 | down_read(&modules_rwsem); 111 | module = gb_audio_manager_get_locked(id); 112 | kobject_get(&module->kobj); 113 | up_read(&modules_rwsem); 114 | return module; 115 | } 116 | EXPORT_SYMBOL_GPL(gb_audio_manager_get_module); 117 | 118 | void gb_audio_manager_put_module(struct gb_audio_manager_module *module) 119 | { 120 | kobject_put(&module->kobj); 121 | } 122 | EXPORT_SYMBOL_GPL(gb_audio_manager_put_module); 123 | 124 | int gb_audio_manager_dump_module(int id) 125 | { 126 | struct gb_audio_manager_module *module; 127 | 128 | down_read(&modules_rwsem); 129 | module = gb_audio_manager_get_locked(id); 130 | up_read(&modules_rwsem); 131 | 132 | if (!module) 133 | return -EINVAL; 134 | 135 | gb_audio_manager_module_dump(module); 136 | return 0; 137 | } 138 | EXPORT_SYMBOL_GPL(gb_audio_manager_dump_module); 139 | 140 | void gb_audio_manager_dump_all(void) 141 | { 142 | struct gb_audio_manager_module *module; 143 | int count = 0; 144 | 145 | down_read(&modules_rwsem); 146 | list_for_each_entry(module, &modules_list, list) { 147 | gb_audio_manager_module_dump(module); 148 | count++; 149 | } 150 | up_read(&modules_rwsem); 151 | 152 | pr_info("Number of connected modules: %d\n", count); 153 | } 154 | EXPORT_SYMBOL_GPL(gb_audio_manager_dump_all); 155 | 156 | /* 157 | * module init/deinit 158 | */ 159 | static int __init manager_init(void) 160 | { 161 | manager_kset = kset_create_and_add(GB_AUDIO_MANAGER_NAME, NULL, 162 | kernel_kobj); 163 | if (!manager_kset) 164 | return -ENOMEM; 165 | 166 | #ifdef GB_AUDIO_MANAGER_SYSFS 167 | gb_audio_manager_sysfs_init(&manager_kset->kobj); 168 | #endif 169 | 170 | return 0; 171 | } 172 | 173 | static void __exit manager_exit(void) 174 | { 175 | gb_audio_manager_remove_all(); 176 | kset_unregister(manager_kset); 177 | ida_destroy(&module_id); 178 | } 179 | 180 | module_init(manager_init); 181 | module_exit(manager_exit); 182 | 183 | MODULE_LICENSE("GPL"); 184 | MODULE_AUTHOR("Svetlin Ankov "); 185 | -------------------------------------------------------------------------------- /audio_manager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus operations 3 | * 4 | * Copyright 2015-2016 Google Inc. 5 | * 6 | * Released under the GPLv2 only. 7 | */ 8 | 9 | #ifndef _GB_AUDIO_MANAGER_H_ 10 | #define _GB_AUDIO_MANAGER_H_ 11 | 12 | #include 13 | #include 14 | 15 | #define GB_AUDIO_MANAGER_NAME "gb_audio_manager" 16 | #define GB_AUDIO_MANAGER_MODULE_NAME_LEN 64 17 | #define GB_AUDIO_MANAGER_MODULE_NAME_LEN_SSCANF "63" 18 | 19 | struct gb_audio_manager_module_descriptor { 20 | char name[GB_AUDIO_MANAGER_MODULE_NAME_LEN]; 21 | int slot; 22 | int vid; 23 | int pid; 24 | int cport; 25 | unsigned int ip_devices; 26 | unsigned int op_devices; 27 | }; 28 | 29 | struct gb_audio_manager_module { 30 | struct kobject kobj; 31 | struct list_head list; 32 | int id; 33 | struct gb_audio_manager_module_descriptor desc; 34 | }; 35 | 36 | /* 37 | * Creates a new gb_audio_manager_module_descriptor, using the specified 38 | * descriptor. 39 | * 40 | * Returns a negative result on error, or the id of the newly created module. 41 | * 42 | */ 43 | int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc); 44 | 45 | /* 46 | * Removes a connected gb_audio_manager_module_descriptor for the specified ID. 47 | * 48 | * Returns zero on success, or a negative value on error. 49 | */ 50 | int gb_audio_manager_remove(int id); 51 | 52 | /* 53 | * Removes all connected gb_audio_modules 54 | * 55 | * Returns zero on success, or a negative value on error. 56 | */ 57 | void gb_audio_manager_remove_all(void); 58 | 59 | /* 60 | * Retrieves a gb_audio_manager_module_descriptor for the specified id. 61 | * Returns the gb_audio_manager_module_descriptor structure, 62 | * or NULL if there is no module with the specified ID. 63 | */ 64 | struct gb_audio_manager_module *gb_audio_manager_get_module(int id); 65 | 66 | /* 67 | * Decreases the refcount of the module, obtained by the get function. 68 | * Modules are removed via gb_audio_manager_remove 69 | */ 70 | void gb_audio_manager_put_module(struct gb_audio_manager_module *module); 71 | 72 | /* 73 | * Dumps the module for the specified id 74 | * Return 0 on success 75 | */ 76 | int gb_audio_manager_dump_module(int id); 77 | 78 | /* 79 | * Dumps all connected modules 80 | */ 81 | void gb_audio_manager_dump_all(void); 82 | 83 | #endif /* _GB_AUDIO_MANAGER_H_ */ 84 | -------------------------------------------------------------------------------- /audio_manager_module.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus operations 3 | * 4 | * Copyright 2015-2016 Google Inc. 5 | * 6 | * Released under the GPLv2 only. 7 | */ 8 | 9 | #include 10 | 11 | #include "audio_manager.h" 12 | #include "audio_manager_private.h" 13 | 14 | #define to_gb_audio_module_attr(x) \ 15 | container_of(x, struct gb_audio_manager_module_attribute, attr) 16 | #define to_gb_audio_module(x) \ 17 | container_of(x, struct gb_audio_manager_module, kobj) 18 | 19 | struct gb_audio_manager_module_attribute { 20 | struct attribute attr; 21 | ssize_t (*show)(struct gb_audio_manager_module *module, 22 | struct gb_audio_manager_module_attribute *attr, 23 | char *buf); 24 | ssize_t (*store)(struct gb_audio_manager_module *module, 25 | struct gb_audio_manager_module_attribute *attr, 26 | const char *buf, size_t count); 27 | }; 28 | 29 | static ssize_t gb_audio_module_attr_show( 30 | struct kobject *kobj, struct attribute *attr, char *buf) 31 | { 32 | struct gb_audio_manager_module_attribute *attribute; 33 | struct gb_audio_manager_module *module; 34 | 35 | attribute = to_gb_audio_module_attr(attr); 36 | module = to_gb_audio_module(kobj); 37 | 38 | if (!attribute->show) 39 | return -EIO; 40 | 41 | return attribute->show(module, attribute, buf); 42 | } 43 | 44 | static ssize_t gb_audio_module_attr_store(struct kobject *kobj, 45 | struct attribute *attr, 46 | const char *buf, size_t len) 47 | { 48 | struct gb_audio_manager_module_attribute *attribute; 49 | struct gb_audio_manager_module *module; 50 | 51 | attribute = to_gb_audio_module_attr(attr); 52 | module = to_gb_audio_module(kobj); 53 | 54 | if (!attribute->store) 55 | return -EIO; 56 | 57 | return attribute->store(module, attribute, buf, len); 58 | } 59 | 60 | static const struct sysfs_ops gb_audio_module_sysfs_ops = { 61 | .show = gb_audio_module_attr_show, 62 | .store = gb_audio_module_attr_store, 63 | }; 64 | 65 | static void gb_audio_module_release(struct kobject *kobj) 66 | { 67 | struct gb_audio_manager_module *module = to_gb_audio_module(kobj); 68 | 69 | pr_info("Destroying audio module #%d\n", module->id); 70 | /* TODO -> delete from list */ 71 | kfree(module); 72 | } 73 | 74 | static ssize_t gb_audio_module_name_show( 75 | struct gb_audio_manager_module *module, 76 | struct gb_audio_manager_module_attribute *attr, char *buf) 77 | { 78 | return sprintf(buf, "%s", module->desc.name); 79 | } 80 | 81 | static struct gb_audio_manager_module_attribute gb_audio_module_name_attribute = 82 | __ATTR(name, 0664, gb_audio_module_name_show, NULL); 83 | 84 | static ssize_t gb_audio_module_slot_show( 85 | struct gb_audio_manager_module *module, 86 | struct gb_audio_manager_module_attribute *attr, char *buf) 87 | { 88 | return sprintf(buf, "%d", module->desc.slot); 89 | } 90 | 91 | static struct gb_audio_manager_module_attribute gb_audio_module_slot_attribute = 92 | __ATTR(slot, 0664, gb_audio_module_slot_show, NULL); 93 | 94 | static ssize_t gb_audio_module_vid_show( 95 | struct gb_audio_manager_module *module, 96 | struct gb_audio_manager_module_attribute *attr, char *buf) 97 | { 98 | return sprintf(buf, "%d", module->desc.vid); 99 | } 100 | 101 | static struct gb_audio_manager_module_attribute gb_audio_module_vid_attribute = 102 | __ATTR(vid, 0664, gb_audio_module_vid_show, NULL); 103 | 104 | static ssize_t gb_audio_module_pid_show( 105 | struct gb_audio_manager_module *module, 106 | struct gb_audio_manager_module_attribute *attr, char *buf) 107 | { 108 | return sprintf(buf, "%d", module->desc.pid); 109 | } 110 | 111 | static struct gb_audio_manager_module_attribute gb_audio_module_pid_attribute = 112 | __ATTR(pid, 0664, gb_audio_module_pid_show, NULL); 113 | 114 | static ssize_t gb_audio_module_cport_show( 115 | struct gb_audio_manager_module *module, 116 | struct gb_audio_manager_module_attribute *attr, char *buf) 117 | { 118 | return sprintf(buf, "%d", module->desc.cport); 119 | } 120 | 121 | static struct gb_audio_manager_module_attribute 122 | gb_audio_module_cport_attribute = 123 | __ATTR(cport, 0664, gb_audio_module_cport_show, NULL); 124 | 125 | static ssize_t gb_audio_module_ip_devices_show( 126 | struct gb_audio_manager_module *module, 127 | struct gb_audio_manager_module_attribute *attr, char *buf) 128 | { 129 | return sprintf(buf, "0x%X", module->desc.ip_devices); 130 | } 131 | 132 | static struct gb_audio_manager_module_attribute 133 | gb_audio_module_ip_devices_attribute = 134 | __ATTR(ip_devices, 0664, gb_audio_module_ip_devices_show, NULL); 135 | 136 | static ssize_t gb_audio_module_op_devices_show( 137 | struct gb_audio_manager_module *module, 138 | struct gb_audio_manager_module_attribute *attr, char *buf) 139 | { 140 | return sprintf(buf, "0x%X", module->desc.op_devices); 141 | } 142 | 143 | static struct gb_audio_manager_module_attribute 144 | gb_audio_module_op_devices_attribute = 145 | __ATTR(op_devices, 0664, gb_audio_module_op_devices_show, NULL); 146 | 147 | static struct attribute *gb_audio_module_default_attrs[] = { 148 | &gb_audio_module_name_attribute.attr, 149 | &gb_audio_module_slot_attribute.attr, 150 | &gb_audio_module_vid_attribute.attr, 151 | &gb_audio_module_pid_attribute.attr, 152 | &gb_audio_module_cport_attribute.attr, 153 | &gb_audio_module_ip_devices_attribute.attr, 154 | &gb_audio_module_op_devices_attribute.attr, 155 | NULL, /* need to NULL terminate the list of attributes */ 156 | }; 157 | 158 | static struct kobj_type gb_audio_module_type = { 159 | .sysfs_ops = &gb_audio_module_sysfs_ops, 160 | .release = gb_audio_module_release, 161 | .default_attrs = gb_audio_module_default_attrs, 162 | }; 163 | 164 | static void send_add_uevent(struct gb_audio_manager_module *module) 165 | { 166 | char name_string[128]; 167 | char slot_string[64]; 168 | char vid_string[64]; 169 | char pid_string[64]; 170 | char cport_string[64]; 171 | char ip_devices_string[64]; 172 | char op_devices_string[64]; 173 | 174 | char *envp[] = { 175 | name_string, 176 | slot_string, 177 | vid_string, 178 | pid_string, 179 | cport_string, 180 | ip_devices_string, 181 | op_devices_string, 182 | NULL 183 | }; 184 | 185 | snprintf(name_string, 128, "NAME=%s", module->desc.name); 186 | snprintf(slot_string, 64, "SLOT=%d", module->desc.slot); 187 | snprintf(vid_string, 64, "VID=%d", module->desc.vid); 188 | snprintf(pid_string, 64, "PID=%d", module->desc.pid); 189 | snprintf(cport_string, 64, "CPORT=%d", module->desc.cport); 190 | snprintf(ip_devices_string, 64, "I/P DEVICES=0x%X", 191 | module->desc.ip_devices); 192 | snprintf(op_devices_string, 64, "O/P DEVICES=0x%X", 193 | module->desc.op_devices); 194 | 195 | kobject_uevent_env(&module->kobj, KOBJ_ADD, envp); 196 | } 197 | 198 | int gb_audio_manager_module_create( 199 | struct gb_audio_manager_module **module, 200 | struct kset *manager_kset, 201 | int id, struct gb_audio_manager_module_descriptor *desc) 202 | { 203 | int err; 204 | struct gb_audio_manager_module *m; 205 | 206 | m = kzalloc(sizeof(*m), GFP_ATOMIC); 207 | if (!m) 208 | return -ENOMEM; 209 | 210 | /* Initialize the node */ 211 | INIT_LIST_HEAD(&m->list); 212 | 213 | /* Set the module id */ 214 | m->id = id; 215 | 216 | /* Copy the provided descriptor */ 217 | memcpy(&m->desc, desc, sizeof(*desc)); 218 | 219 | /* set the kset */ 220 | m->kobj.kset = manager_kset; 221 | 222 | /* 223 | * Initialize and add the kobject to the kernel. All the default files 224 | * will be created here. As we have already specified a kset for this 225 | * kobject, we don't have to set a parent for the kobject, the kobject 226 | * will be placed beneath that kset automatically. 227 | */ 228 | err = kobject_init_and_add(&m->kobj, &gb_audio_module_type, NULL, "%d", 229 | id); 230 | if (err) { 231 | pr_err("failed initializing kobject for audio module #%d\n", 232 | id); 233 | kobject_put(&m->kobj); 234 | return err; 235 | } 236 | 237 | /* 238 | * Notify the object was created 239 | */ 240 | send_add_uevent(m); 241 | 242 | *module = m; 243 | pr_info("Created audio module #%d\n", id); 244 | return 0; 245 | } 246 | 247 | void gb_audio_manager_module_dump(struct gb_audio_manager_module *module) 248 | { 249 | pr_info("audio module #%d name=%s slot=%d vid=%d pid=%d cport=%d i/p devices=0x%X o/p devices=0x%X\n", 250 | module->id, 251 | module->desc.name, 252 | module->desc.slot, 253 | module->desc.vid, 254 | module->desc.pid, 255 | module->desc.cport, 256 | module->desc.ip_devices, 257 | module->desc.op_devices); 258 | } 259 | -------------------------------------------------------------------------------- /audio_manager_private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus operations 3 | * 4 | * Copyright 2015-2016 Google Inc. 5 | * 6 | * Released under the GPLv2 only. 7 | */ 8 | 9 | #ifndef _GB_AUDIO_MANAGER_PRIVATE_H_ 10 | #define _GB_AUDIO_MANAGER_PRIVATE_H_ 11 | 12 | #include 13 | 14 | #include "audio_manager.h" 15 | 16 | int gb_audio_manager_module_create( 17 | struct gb_audio_manager_module **module, 18 | struct kset *manager_kset, 19 | int id, struct gb_audio_manager_module_descriptor *desc); 20 | 21 | /* module destroyed via kobject_put */ 22 | 23 | void gb_audio_manager_module_dump(struct gb_audio_manager_module *module); 24 | 25 | /* sysfs control */ 26 | void gb_audio_manager_sysfs_init(struct kobject *kobj); 27 | 28 | #endif /* _GB_AUDIO_MANAGER_PRIVATE_H_ */ 29 | -------------------------------------------------------------------------------- /audio_manager_sysfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus operations 3 | * 4 | * Copyright 2015-2016 Google Inc. 5 | * 6 | * Released under the GPLv2 only. 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "audio_manager.h" 13 | #include "audio_manager_private.h" 14 | 15 | static ssize_t manager_sysfs_add_store( 16 | struct kobject *kobj, struct kobj_attribute *attr, 17 | const char *buf, size_t count) 18 | { 19 | struct gb_audio_manager_module_descriptor desc = { {0} }; 20 | 21 | int num = sscanf(buf, 22 | "name=%" GB_AUDIO_MANAGER_MODULE_NAME_LEN_SSCANF "s " 23 | "slot=%d vid=%d pid=%d cport=%d i/p devices=0x%X" 24 | "o/p devices=0x%X", 25 | desc.name, &desc.slot, &desc.vid, &desc.pid, 26 | &desc.cport, &desc.ip_devices, &desc.op_devices); 27 | 28 | if (num != 7) 29 | return -EINVAL; 30 | 31 | num = gb_audio_manager_add(&desc); 32 | if (num < 0) 33 | return -EINVAL; 34 | 35 | return count; 36 | } 37 | 38 | static struct kobj_attribute manager_add_attribute = 39 | __ATTR(add, 0664, NULL, manager_sysfs_add_store); 40 | 41 | static ssize_t manager_sysfs_remove_store( 42 | struct kobject *kobj, struct kobj_attribute *attr, 43 | const char *buf, size_t count) 44 | { 45 | int id; 46 | 47 | int num = sscanf(buf, "%d", &id); 48 | 49 | if (num != 1) 50 | return -EINVAL; 51 | 52 | num = gb_audio_manager_remove(id); 53 | if (num) 54 | return num; 55 | 56 | return count; 57 | } 58 | 59 | static struct kobj_attribute manager_remove_attribute = 60 | __ATTR(remove, 0664, NULL, manager_sysfs_remove_store); 61 | 62 | static ssize_t manager_sysfs_dump_store( 63 | struct kobject *kobj, struct kobj_attribute *attr, 64 | const char *buf, size_t count) 65 | { 66 | int id; 67 | 68 | int num = sscanf(buf, "%d", &id); 69 | 70 | if (num == 1) { 71 | num = gb_audio_manager_dump_module(id); 72 | if (num) 73 | return num; 74 | } else if (!strncmp("all", buf, 3)) 75 | gb_audio_manager_dump_all(); 76 | else 77 | return -EINVAL; 78 | 79 | return count; 80 | } 81 | 82 | static struct kobj_attribute manager_dump_attribute = 83 | __ATTR(dump, 0664, NULL, manager_sysfs_dump_store); 84 | 85 | static void manager_sysfs_init_attribute( 86 | struct kobject *kobj, struct kobj_attribute *kattr) 87 | { 88 | int err; 89 | 90 | err = sysfs_create_file(kobj, &kattr->attr); 91 | if (err) { 92 | pr_warn("creating the sysfs entry for %s failed: %d\n", 93 | kattr->attr.name, err); 94 | } 95 | } 96 | 97 | void gb_audio_manager_sysfs_init(struct kobject *kobj) 98 | { 99 | manager_sysfs_init_attribute(kobj, &manager_add_attribute); 100 | manager_sysfs_init_attribute(kobj, &manager_remove_attribute); 101 | manager_sysfs_init_attribute(kobj, &manager_dump_attribute); 102 | } 103 | -------------------------------------------------------------------------------- /bundle.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus bundles 3 | * 4 | * Copyright 2014-2015 Google Inc. 5 | * Copyright 2014-2015 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #include "greybus.h" 11 | #include "greybus_trace.h" 12 | 13 | static ssize_t bundle_class_show(struct device *dev, 14 | struct device_attribute *attr, char *buf) 15 | { 16 | struct gb_bundle *bundle = to_gb_bundle(dev); 17 | 18 | return sprintf(buf, "0x%02x\n", bundle->class); 19 | } 20 | static DEVICE_ATTR_RO(bundle_class); 21 | 22 | static ssize_t bundle_id_show(struct device *dev, 23 | struct device_attribute *attr, char *buf) 24 | { 25 | struct gb_bundle *bundle = to_gb_bundle(dev); 26 | 27 | return sprintf(buf, "%u\n", bundle->id); 28 | } 29 | static DEVICE_ATTR_RO(bundle_id); 30 | 31 | static ssize_t state_show(struct device *dev, struct device_attribute *attr, 32 | char *buf) 33 | { 34 | struct gb_bundle *bundle = to_gb_bundle(dev); 35 | 36 | if (bundle->state == NULL) 37 | return sprintf(buf, "\n"); 38 | 39 | return sprintf(buf, "%s\n", bundle->state); 40 | } 41 | 42 | static ssize_t state_store(struct device *dev, struct device_attribute *attr, 43 | const char *buf, size_t size) 44 | { 45 | struct gb_bundle *bundle = to_gb_bundle(dev); 46 | 47 | kfree(bundle->state); 48 | bundle->state = kstrdup(buf, GFP_KERNEL); 49 | if (!bundle->state) 50 | return -ENOMEM; 51 | 52 | /* Tell userspace that the file contents changed */ 53 | sysfs_notify(&bundle->dev.kobj, NULL, "state"); 54 | 55 | return size; 56 | } 57 | static DEVICE_ATTR_RW(state); 58 | 59 | static struct attribute *bundle_attrs[] = { 60 | &dev_attr_bundle_class.attr, 61 | &dev_attr_bundle_id.attr, 62 | &dev_attr_state.attr, 63 | NULL, 64 | }; 65 | 66 | ATTRIBUTE_GROUPS(bundle); 67 | 68 | static struct gb_bundle *gb_bundle_find(struct gb_interface *intf, 69 | u8 bundle_id) 70 | { 71 | struct gb_bundle *bundle; 72 | 73 | list_for_each_entry(bundle, &intf->bundles, links) { 74 | if (bundle->id == bundle_id) 75 | return bundle; 76 | } 77 | 78 | return NULL; 79 | } 80 | 81 | static void gb_bundle_release(struct device *dev) 82 | { 83 | struct gb_bundle *bundle = to_gb_bundle(dev); 84 | 85 | trace_gb_bundle_release(bundle); 86 | 87 | kfree(bundle->state); 88 | kfree(bundle->cport_desc); 89 | kfree(bundle); 90 | } 91 | 92 | #ifdef CONFIG_PM_RUNTIME 93 | 94 | static void gb_bundle_disable_all_connections(struct gb_bundle *bundle) 95 | { 96 | struct gb_connection *connection; 97 | 98 | list_for_each_entry(connection, &bundle->connections, bundle_links) 99 | gb_connection_disable(connection); 100 | } 101 | 102 | static void gb_bundle_enable_all_connections(struct gb_bundle *bundle) 103 | { 104 | struct gb_connection *connection; 105 | 106 | list_for_each_entry(connection, &bundle->connections, bundle_links) 107 | gb_connection_enable(connection); 108 | } 109 | 110 | static int gb_bundle_suspend(struct device *dev) 111 | { 112 | struct gb_bundle *bundle = to_gb_bundle(dev); 113 | const struct dev_pm_ops *pm = dev->driver->pm; 114 | int ret; 115 | 116 | if (pm && pm->runtime_suspend) { 117 | ret = pm->runtime_suspend(&bundle->dev); 118 | if (ret) 119 | return ret; 120 | } else { 121 | gb_bundle_disable_all_connections(bundle); 122 | } 123 | 124 | ret = gb_control_bundle_suspend(bundle->intf->control, bundle->id); 125 | if (ret) { 126 | if (pm && pm->runtime_resume) 127 | ret = pm->runtime_resume(dev); 128 | else 129 | gb_bundle_enable_all_connections(bundle); 130 | 131 | return ret; 132 | } 133 | 134 | return 0; 135 | } 136 | 137 | static int gb_bundle_resume(struct device *dev) 138 | { 139 | struct gb_bundle *bundle = to_gb_bundle(dev); 140 | const struct dev_pm_ops *pm = dev->driver->pm; 141 | int ret; 142 | 143 | ret = gb_control_bundle_resume(bundle->intf->control, bundle->id); 144 | if (ret) 145 | return ret; 146 | 147 | if (pm && pm->runtime_resume) { 148 | ret = pm->runtime_resume(dev); 149 | if (ret) 150 | return ret; 151 | } else { 152 | gb_bundle_enable_all_connections(bundle); 153 | } 154 | 155 | return 0; 156 | } 157 | 158 | static int gb_bundle_idle(struct device *dev) 159 | { 160 | pm_runtime_mark_last_busy(dev); 161 | pm_request_autosuspend(dev); 162 | 163 | return 0; 164 | } 165 | #endif 166 | 167 | static const struct dev_pm_ops gb_bundle_pm_ops = { 168 | SET_RUNTIME_PM_OPS(gb_bundle_suspend, gb_bundle_resume, gb_bundle_idle) 169 | }; 170 | 171 | struct device_type greybus_bundle_type = { 172 | .name = "greybus_bundle", 173 | .release = gb_bundle_release, 174 | .pm = &gb_bundle_pm_ops, 175 | }; 176 | 177 | /* 178 | * Create a gb_bundle structure to represent a discovered 179 | * bundle. Returns a pointer to the new bundle or a null 180 | * pointer if a failure occurs due to memory exhaustion. 181 | */ 182 | struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, 183 | u8 class) 184 | { 185 | struct gb_bundle *bundle; 186 | 187 | if (bundle_id == BUNDLE_ID_NONE) { 188 | dev_err(&intf->dev, "can't use bundle id %u\n", bundle_id); 189 | return NULL; 190 | } 191 | 192 | /* 193 | * Reject any attempt to reuse a bundle id. We initialize 194 | * these serially, so there's no need to worry about keeping 195 | * the interface bundle list locked here. 196 | */ 197 | if (gb_bundle_find(intf, bundle_id)) { 198 | dev_err(&intf->dev, "duplicate bundle id %u\n", bundle_id); 199 | return NULL; 200 | } 201 | 202 | bundle = kzalloc(sizeof(*bundle), GFP_KERNEL); 203 | if (!bundle) 204 | return NULL; 205 | 206 | bundle->intf = intf; 207 | bundle->id = bundle_id; 208 | bundle->class = class; 209 | INIT_LIST_HEAD(&bundle->connections); 210 | 211 | bundle->dev.parent = &intf->dev; 212 | bundle->dev.bus = &greybus_bus_type; 213 | bundle->dev.type = &greybus_bundle_type; 214 | bundle->dev.groups = bundle_groups; 215 | bundle->dev.dma_mask = intf->dev.dma_mask; 216 | device_initialize(&bundle->dev); 217 | dev_set_name(&bundle->dev, "%s.%d", dev_name(&intf->dev), bundle_id); 218 | 219 | list_add(&bundle->links, &intf->bundles); 220 | 221 | trace_gb_bundle_create(bundle); 222 | 223 | return bundle; 224 | } 225 | 226 | int gb_bundle_add(struct gb_bundle *bundle) 227 | { 228 | int ret; 229 | 230 | ret = device_add(&bundle->dev); 231 | if (ret) { 232 | dev_err(&bundle->dev, "failed to register bundle: %d\n", ret); 233 | return ret; 234 | } 235 | 236 | trace_gb_bundle_add(bundle); 237 | 238 | return 0; 239 | } 240 | 241 | /* 242 | * Tear down a previously set up bundle. 243 | */ 244 | void gb_bundle_destroy(struct gb_bundle *bundle) 245 | { 246 | trace_gb_bundle_destroy(bundle); 247 | 248 | if (device_is_registered(&bundle->dev)) 249 | device_del(&bundle->dev); 250 | 251 | list_del(&bundle->links); 252 | 253 | put_device(&bundle->dev); 254 | } 255 | -------------------------------------------------------------------------------- /bundle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus bundles 3 | * 4 | * Copyright 2014 Google Inc. 5 | * Copyright 2014 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __BUNDLE_H 11 | #define __BUNDLE_H 12 | 13 | #include 14 | 15 | #define BUNDLE_ID_NONE U8_MAX 16 | 17 | /* Greybus "public" definitions" */ 18 | struct gb_bundle { 19 | struct device dev; 20 | struct gb_interface *intf; 21 | 22 | u8 id; 23 | u8 class; 24 | u8 class_major; 25 | u8 class_minor; 26 | 27 | size_t num_cports; 28 | struct greybus_descriptor_cport *cport_desc; 29 | 30 | struct list_head connections; 31 | u8 *state; 32 | 33 | struct list_head links; /* interface->bundles */ 34 | }; 35 | #define to_gb_bundle(d) container_of(d, struct gb_bundle, dev) 36 | 37 | /* Greybus "private" definitions" */ 38 | struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, 39 | u8 class); 40 | int gb_bundle_add(struct gb_bundle *bundle); 41 | void gb_bundle_destroy(struct gb_bundle *bundle); 42 | 43 | /* Bundle Runtime PM wrappers */ 44 | #ifdef CONFIG_PM_RUNTIME 45 | static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) 46 | { 47 | int retval; 48 | 49 | retval = pm_runtime_get_sync(&bundle->dev); 50 | if (retval < 0) { 51 | dev_err(&bundle->dev, 52 | "pm_runtime_get_sync failed: %d\n", retval); 53 | pm_runtime_put_noidle(&bundle->dev); 54 | return retval; 55 | } 56 | 57 | return 0; 58 | } 59 | 60 | static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) 61 | { 62 | int retval; 63 | 64 | pm_runtime_mark_last_busy(&bundle->dev); 65 | retval = pm_runtime_put_autosuspend(&bundle->dev); 66 | 67 | return retval; 68 | } 69 | 70 | static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) 71 | { 72 | pm_runtime_get_noresume(&bundle->dev); 73 | } 74 | 75 | static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) 76 | { 77 | pm_runtime_put_noidle(&bundle->dev); 78 | } 79 | 80 | #else 81 | static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) 82 | { return 0; } 83 | static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) 84 | { return 0; } 85 | 86 | static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) {} 87 | static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) {} 88 | #endif 89 | 90 | #endif /* __BUNDLE_H */ 91 | -------------------------------------------------------------------------------- /connection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus connections 3 | * 4 | * Copyright 2014 Google Inc. 5 | * Copyright 2014 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __CONNECTION_H 11 | #define __CONNECTION_H 12 | 13 | #include 14 | #include 15 | 16 | #define GB_CONNECTION_FLAG_CSD BIT(0) 17 | #define GB_CONNECTION_FLAG_NO_FLOWCTRL BIT(1) 18 | #define GB_CONNECTION_FLAG_OFFLOADED BIT(2) 19 | #define GB_CONNECTION_FLAG_CDSI1 BIT(3) 20 | #define GB_CONNECTION_FLAG_CONTROL BIT(4) 21 | #define GB_CONNECTION_FLAG_HIGH_PRIO BIT(5) 22 | 23 | #define GB_CONNECTION_FLAG_CORE_MASK GB_CONNECTION_FLAG_CONTROL 24 | 25 | enum gb_connection_state { 26 | GB_CONNECTION_STATE_DISABLED = 0, 27 | GB_CONNECTION_STATE_ENABLED_TX = 1, 28 | GB_CONNECTION_STATE_ENABLED = 2, 29 | GB_CONNECTION_STATE_DISCONNECTING = 3, 30 | }; 31 | 32 | struct gb_operation; 33 | 34 | typedef int (*gb_request_handler_t)(struct gb_operation *); 35 | 36 | struct gb_connection { 37 | struct gb_host_device *hd; 38 | struct gb_interface *intf; 39 | struct gb_bundle *bundle; 40 | struct kref kref; 41 | u16 hd_cport_id; 42 | u16 intf_cport_id; 43 | 44 | struct list_head hd_links; 45 | struct list_head bundle_links; 46 | 47 | gb_request_handler_t handler; 48 | unsigned long flags; 49 | 50 | struct mutex mutex; 51 | spinlock_t lock; 52 | enum gb_connection_state state; 53 | struct list_head operations; 54 | 55 | char name[16]; 56 | struct workqueue_struct *wq; 57 | 58 | atomic_t op_cycle; 59 | 60 | void *private; 61 | 62 | bool mode_switch; 63 | }; 64 | 65 | struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, 66 | u16 hd_cport_id, gb_request_handler_t handler); 67 | struct gb_connection *gb_connection_create_control(struct gb_interface *intf); 68 | struct gb_connection *gb_connection_create(struct gb_bundle *bundle, 69 | u16 cport_id, gb_request_handler_t handler); 70 | struct gb_connection *gb_connection_create_flags(struct gb_bundle *bundle, 71 | u16 cport_id, gb_request_handler_t handler, 72 | unsigned long flags); 73 | struct gb_connection *gb_connection_create_offloaded(struct gb_bundle *bundle, 74 | u16 cport_id, unsigned long flags); 75 | void gb_connection_destroy(struct gb_connection *connection); 76 | 77 | static inline bool gb_connection_is_static(struct gb_connection *connection) 78 | { 79 | return !connection->intf; 80 | } 81 | 82 | int gb_connection_enable(struct gb_connection *connection); 83 | int gb_connection_enable_tx(struct gb_connection *connection); 84 | void gb_connection_disable_rx(struct gb_connection *connection); 85 | void gb_connection_disable(struct gb_connection *connection); 86 | void gb_connection_disable_forced(struct gb_connection *connection); 87 | 88 | void gb_connection_mode_switch_prepare(struct gb_connection *connection); 89 | void gb_connection_mode_switch_complete(struct gb_connection *connection); 90 | 91 | void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, 92 | u8 *data, size_t length); 93 | 94 | void gb_connection_latency_tag_enable(struct gb_connection *connection); 95 | void gb_connection_latency_tag_disable(struct gb_connection *connection); 96 | 97 | static inline bool gb_connection_e2efc_enabled(struct gb_connection *connection) 98 | { 99 | return !(connection->flags & GB_CONNECTION_FLAG_CSD); 100 | } 101 | 102 | static inline bool 103 | gb_connection_flow_control_disabled(struct gb_connection *connection) 104 | { 105 | return connection->flags & GB_CONNECTION_FLAG_NO_FLOWCTRL; 106 | } 107 | 108 | static inline bool gb_connection_is_offloaded(struct gb_connection *connection) 109 | { 110 | return connection->flags & GB_CONNECTION_FLAG_OFFLOADED; 111 | } 112 | 113 | static inline bool gb_connection_is_control(struct gb_connection *connection) 114 | { 115 | return connection->flags & GB_CONNECTION_FLAG_CONTROL; 116 | } 117 | 118 | static inline void *gb_connection_get_data(struct gb_connection *connection) 119 | { 120 | return connection->private; 121 | } 122 | 123 | static inline void gb_connection_set_data(struct gb_connection *connection, 124 | void *data) 125 | { 126 | connection->private = data; 127 | } 128 | 129 | #endif /* __CONNECTION_H */ 130 | -------------------------------------------------------------------------------- /control.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus CPort control protocol 3 | * 4 | * Copyright 2015 Google Inc. 5 | * Copyright 2015 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __CONTROL_H 11 | #define __CONTROL_H 12 | 13 | struct gb_control { 14 | struct device dev; 15 | struct gb_interface *intf; 16 | 17 | struct gb_connection *connection; 18 | 19 | u8 protocol_major; 20 | u8 protocol_minor; 21 | 22 | bool has_bundle_activate; 23 | bool has_bundle_version; 24 | 25 | char *vendor_string; 26 | char *product_string; 27 | }; 28 | #define to_gb_control(d) container_of(d, struct gb_control, dev) 29 | 30 | struct gb_control *gb_control_create(struct gb_interface *intf); 31 | int gb_control_enable(struct gb_control *control); 32 | void gb_control_disable(struct gb_control *control); 33 | int gb_control_suspend(struct gb_control *control); 34 | int gb_control_resume(struct gb_control *control); 35 | int gb_control_add(struct gb_control *control); 36 | void gb_control_del(struct gb_control *control); 37 | struct gb_control *gb_control_get(struct gb_control *control); 38 | void gb_control_put(struct gb_control *control); 39 | 40 | int gb_control_get_bundle_versions(struct gb_control *control); 41 | int gb_control_connected_operation(struct gb_control *control, u16 cport_id); 42 | int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); 43 | int gb_control_disconnecting_operation(struct gb_control *control, 44 | u16 cport_id); 45 | int gb_control_mode_switch_operation(struct gb_control *control); 46 | void gb_control_mode_switch_prepare(struct gb_control *control); 47 | void gb_control_mode_switch_complete(struct gb_control *control); 48 | int gb_control_get_manifest_size_operation(struct gb_interface *intf); 49 | int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, 50 | size_t size); 51 | int gb_control_timesync_enable(struct gb_control *control, u8 count, 52 | u64 frame_time, u32 strobe_delay, u32 refclk); 53 | int gb_control_timesync_disable(struct gb_control *control); 54 | int gb_control_timesync_get_last_event(struct gb_control *control, 55 | u64 *frame_time); 56 | int gb_control_timesync_authoritative(struct gb_control *control, 57 | u64 *frame_time); 58 | int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id); 59 | int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id); 60 | int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id); 61 | int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id); 62 | int gb_control_interface_suspend_prepare(struct gb_control *control); 63 | int gb_control_interface_deactivate_prepare(struct gb_control *control); 64 | int gb_control_interface_hibernate_abort(struct gb_control *control); 65 | #endif /* __CONTROL_H */ 66 | -------------------------------------------------------------------------------- /debugfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus debugfs code 3 | * 4 | * Copyright 2014 Google Inc. 5 | * Copyright 2014 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #include 11 | 12 | #include "greybus.h" 13 | 14 | static struct dentry *gb_debug_root; 15 | 16 | void __init gb_debugfs_init(void) 17 | { 18 | gb_debug_root = debugfs_create_dir("greybus", NULL); 19 | } 20 | 21 | void gb_debugfs_cleanup(void) 22 | { 23 | debugfs_remove_recursive(gb_debug_root); 24 | gb_debug_root = NULL; 25 | } 26 | 27 | struct dentry *gb_debugfs_get(void) 28 | { 29 | return gb_debug_root; 30 | } 31 | EXPORT_SYMBOL_GPL(gb_debugfs_get); 32 | -------------------------------------------------------------------------------- /devices: -------------------------------------------------------------------------------- 1 | T: Bus=01 Lev=03 Prnt=07 Port=02 Cnt=03 Dev#= 12 Spd=12 MxCh= 0 2 | D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 3 | P: Vendor=ffff ProdID=0001 Rev= 1.00 4 | S: Manufacturer=Greybus 5 | S: Product=SVC Bridge 6 | S: SerialNumber=12239 7 | C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA 8 | I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=es1_ap_driver 9 | E: Ad=81(I) Atr=03(Int.) MxPS= 64 Ivl=64ms 10 | E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms 11 | E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms 12 | -------------------------------------------------------------------------------- /firmware.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Firmware Management Header 3 | * 4 | * Copyright 2016 Google Inc. 5 | * Copyright 2016 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __FIRMWARE_H 11 | #define __FIRMWARE_H 12 | 13 | #include "greybus.h" 14 | 15 | #define FW_NAME_PREFIX "gmp_" 16 | 17 | /* 18 | * Length of the string in format: "FW_NAME_PREFIX""%08x_%08x_%08x_%08x_%s.tftf" 19 | * (3 + 1 + 4 * (8 + 1) + 10 + 1 + 4 + 1) 20 | */ 21 | #define FW_NAME_SIZE 56 22 | 23 | /* Firmware Management Protocol specific functions */ 24 | int fw_mgmt_init(void); 25 | void fw_mgmt_exit(void); 26 | struct gb_connection *to_fw_mgmt_connection(struct device *dev); 27 | int gb_fw_mgmt_request_handler(struct gb_operation *op); 28 | int gb_fw_mgmt_connection_init(struct gb_connection *connection); 29 | void gb_fw_mgmt_connection_exit(struct gb_connection *connection); 30 | 31 | /* Firmware Download Protocol specific functions */ 32 | int gb_fw_download_request_handler(struct gb_operation *op); 33 | int gb_fw_download_connection_init(struct gb_connection *connection); 34 | void gb_fw_download_connection_exit(struct gb_connection *connection); 35 | 36 | /* CAP Protocol specific functions */ 37 | int cap_init(void); 38 | void cap_exit(void); 39 | int gb_cap_connection_init(struct gb_connection *connection); 40 | void gb_cap_connection_exit(struct gb_connection *connection); 41 | 42 | #endif /* __FIRMWARE_H */ 43 | -------------------------------------------------------------------------------- /gb-camera.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Camera protocol driver. 3 | * 4 | * Copyright 2015 Google Inc. 5 | * 6 | * Released under the GPLv2 only. 7 | */ 8 | #ifndef __GB_CAMERA_H 9 | #define __GB_CAMERA_H 10 | 11 | #include 12 | 13 | /* Input flags need to be set from the caller */ 14 | #define GB_CAMERA_IN_FLAG_TEST (1 << 0) 15 | /* Output flags returned */ 16 | #define GB_CAMERA_OUT_FLAG_ADJUSTED (1 << 0) 17 | 18 | /** 19 | * struct gb_camera_stream - Represents greybus camera stream. 20 | * @width: Stream width in pixels. 21 | * @height: Stream height in pixels. 22 | * @pixel_code: Media bus pixel code. 23 | * @vc: MIPI CSI virtual channel. 24 | * @dt: MIPI CSI data types. Most formats use a single data type, in which case 25 | * the second element will be ignored. 26 | * @max_size: Maximum size of a frame in bytes. The camera module guarantees 27 | * that all data between the Frame Start and Frame End packet for 28 | * the associated virtual channel and data type(s) will not exceed 29 | * this size. 30 | */ 31 | struct gb_camera_stream { 32 | unsigned int width; 33 | unsigned int height; 34 | enum v4l2_mbus_pixelcode pixel_code; 35 | unsigned int vc; 36 | unsigned int dt[2]; 37 | unsigned int max_size; 38 | }; 39 | 40 | /** 41 | * struct gb_camera_csi_params - CSI configuration parameters 42 | * @num_lanes: number of CSI data lanes 43 | * @clk_freq: CSI clock frequency in Hz 44 | */ 45 | struct gb_camera_csi_params { 46 | unsigned int num_lanes; 47 | unsigned int clk_freq; 48 | }; 49 | 50 | /** 51 | * struct gb_camera_ops - Greybus camera operations, used by the Greybus camera 52 | * driver to expose operations to the host camera driver. 53 | * @capabilities: Retrieve camera capabilities and store them in the buffer 54 | * 'buf' capabilities. The buffer maximum size is specified by 55 | * the caller in the 'size' parameter, and the effective 56 | * capabilities size is returned from the function. If the buffer 57 | * size is too small to hold the capabilities an error is 58 | * returned and the buffer is left untouched. 59 | * 60 | * @configure_streams: Negotiate configuration and prepare the module for video 61 | * capture. The caller specifies the number of streams it 62 | * requests in the 'nstreams' argument and the associated 63 | * streams configurations in the 'streams' argument. The 64 | * GB_CAMERA_IN_FLAG_TEST 'flag' can be set to test a 65 | * configuration without applying it, otherwise the 66 | * configuration is applied by the module. The module can 67 | * decide to modify the requested configuration, including 68 | * using a different number of streams. In that case the 69 | * modified configuration won't be applied, the 70 | * GB_CAMERA_OUT_FLAG_ADJUSTED 'flag' will be set upon 71 | * return, and the modified configuration and number of 72 | * streams stored in 'streams' and 'array'. The module 73 | * returns its CSI-2 bus parameters in the 'csi_params' 74 | * structure in all cases. 75 | * 76 | * @capture: Submit a capture request. The supplied 'request_id' must be unique 77 | * and higher than the IDs of all the previously submitted requests. 78 | * The 'streams' argument specifies which streams are affected by the 79 | * request in the form of a bitmask, with bits corresponding to the 80 | * configured streams indexes. If the request contains settings, the 81 | * 'settings' argument points to the settings buffer and its size is 82 | * specified by the 'settings_size' argument. Otherwise the 'settings' 83 | * argument should be set to NULL and 'settings_size' to 0. 84 | * 85 | * @flush: Flush the capture requests queue. Return the ID of the last request 86 | * that will processed by the device before it stops transmitting video 87 | * frames. All queued capture requests with IDs higher than the returned 88 | * ID will be dropped without being processed. 89 | */ 90 | struct gb_camera_ops { 91 | ssize_t (*capabilities)(void *priv, char *buf, size_t len); 92 | int (*configure_streams)(void *priv, unsigned int *nstreams, 93 | unsigned int *flags, struct gb_camera_stream *streams, 94 | struct gb_camera_csi_params *csi_params); 95 | int (*capture)(void *priv, u32 request_id, 96 | unsigned int streams, unsigned int num_frames, 97 | size_t settings_size, const void *settings); 98 | int (*flush)(void *priv, u32 *request_id); 99 | }; 100 | 101 | /** 102 | * struct gb_camera_module - Represents greybus camera module. 103 | * @priv: Module private data, passed to all camera operations. 104 | * @ops: Greybus camera operation callbacks. 105 | * @interface_id: Interface id of the module. 106 | * @refcount: Reference counting object. 107 | * @release: Module release function. 108 | * @list: List entry in the camera modules list. 109 | */ 110 | struct gb_camera_module { 111 | void *priv; 112 | const struct gb_camera_ops *ops; 113 | 114 | unsigned int interface_id; 115 | struct kref refcount; 116 | void (*release)(struct kref *kref); 117 | struct list_head list; /* Global list */ 118 | }; 119 | 120 | #define gb_camera_call(f, op, args...) \ 121 | (!(f) ? -ENODEV : (((f)->ops->op) ? \ 122 | (f)->ops->op((f)->priv, ##args) : -ENOIOCTLCMD)) 123 | 124 | int gb_camera_register(struct gb_camera_module *module); 125 | int gb_camera_unregister(struct gb_camera_module *module); 126 | 127 | #endif /* __GB_CAMERA_H */ 128 | -------------------------------------------------------------------------------- /gbphy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Bridged-Phy Bus driver 3 | * 4 | * Copyright 2016 Google Inc. 5 | * 6 | * Released under the GPLv2 only. 7 | */ 8 | 9 | #ifndef __GBPHY_H 10 | #define __GBPHY_H 11 | 12 | struct gbphy_device { 13 | u32 id; 14 | struct greybus_descriptor_cport *cport_desc; 15 | struct gb_bundle *bundle; 16 | struct list_head list; 17 | struct device dev; 18 | }; 19 | #define to_gbphy_dev(d) container_of(d, struct gbphy_device, dev) 20 | 21 | static inline void *gb_gbphy_get_data(struct gbphy_device *gdev) 22 | { 23 | return dev_get_drvdata(&gdev->dev); 24 | } 25 | 26 | static inline void gb_gbphy_set_data(struct gbphy_device *gdev, void *data) 27 | { 28 | dev_set_drvdata(&gdev->dev, data); 29 | } 30 | 31 | struct gbphy_device_id { 32 | __u8 protocol_id; 33 | }; 34 | 35 | #define GBPHY_PROTOCOL(p) \ 36 | .protocol_id = (p), 37 | 38 | struct gbphy_driver { 39 | const char *name; 40 | int (*probe)(struct gbphy_device *, 41 | const struct gbphy_device_id *id); 42 | void (*remove)(struct gbphy_device *); 43 | const struct gbphy_device_id *id_table; 44 | 45 | struct device_driver driver; 46 | }; 47 | #define to_gbphy_driver(d) container_of(d, struct gbphy_driver, driver) 48 | 49 | int gb_gbphy_register_driver(struct gbphy_driver *driver, 50 | struct module *owner, const char *mod_name); 51 | void gb_gbphy_deregister_driver(struct gbphy_driver *driver); 52 | 53 | #define gb_gbphy_register(driver) \ 54 | gb_gbphy_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) 55 | #define gb_gbphy_deregister(driver) \ 56 | gb_gbphy_deregister_driver(driver) 57 | 58 | /** 59 | * module_gbphy_driver() - Helper macro for registering a gbphy driver 60 | * @__gbphy_driver: gbphy_driver structure 61 | * 62 | * Helper macro for gbphy drivers to set up proper module init / exit 63 | * functions. Replaces module_init() and module_exit() and keeps people from 64 | * printing pointless things to the kernel log when their driver is loaded. 65 | */ 66 | #define module_gbphy_driver(__gbphy_driver) \ 67 | module_driver(__gbphy_driver, gb_gbphy_register, gb_gbphy_deregister) 68 | 69 | #ifdef CONFIG_PM_RUNTIME 70 | static inline int gbphy_runtime_get_sync(struct gbphy_device *gbphy_dev) 71 | { 72 | struct device *dev = &gbphy_dev->dev; 73 | int ret; 74 | 75 | ret = pm_runtime_get_sync(dev); 76 | if (ret < 0) { 77 | dev_err(dev, "pm_runtime_get_sync failed: %d\n", ret); 78 | pm_runtime_put_noidle(dev); 79 | return ret; 80 | } 81 | 82 | return 0; 83 | } 84 | 85 | static inline void gbphy_runtime_put_autosuspend(struct gbphy_device *gbphy_dev) 86 | { 87 | struct device *dev = &gbphy_dev->dev; 88 | 89 | pm_runtime_mark_last_busy(dev); 90 | pm_runtime_put_autosuspend(dev); 91 | } 92 | 93 | static inline void gbphy_runtime_get_noresume(struct gbphy_device *gbphy_dev) 94 | { 95 | pm_runtime_get_noresume(&gbphy_dev->dev); 96 | } 97 | 98 | static inline void gbphy_runtime_put_noidle(struct gbphy_device *gbphy_dev) 99 | { 100 | pm_runtime_put_noidle(&gbphy_dev->dev); 101 | } 102 | #else 103 | static inline int gbphy_runtime_get_sync(struct gbphy_device *gbphy_dev) { return 0; } 104 | static inline void gbphy_runtime_put_autosuspend(struct gbphy_device *gbphy_dev) {} 105 | static inline void gbphy_runtime_get_noresume(struct gbphy_device *gbphy_dev) {} 106 | static inline void gbphy_runtime_put_noidle(struct gbphy_device *gbphy_dev) {} 107 | #endif 108 | 109 | #endif /* __GBPHY_H */ 110 | 111 | -------------------------------------------------------------------------------- /greybus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus driver and device API 3 | * 4 | * Copyright 2014-2015 Google Inc. 5 | * Copyright 2014-2015 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __LINUX_GREYBUS_H 11 | #define __LINUX_GREYBUS_H 12 | 13 | #ifdef __KERNEL__ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "kernel_ver.h" 25 | #include "greybus_id.h" 26 | #include "greybus_manifest.h" 27 | #include "greybus_protocols.h" 28 | #include "manifest.h" 29 | #include "hd.h" 30 | #include "svc.h" 31 | #include "control.h" 32 | #include "module.h" 33 | #include "interface.h" 34 | #include "bundle.h" 35 | #include "connection.h" 36 | #include "operation.h" 37 | #include "timesync.h" 38 | 39 | /* Matches up with the Greybus Protocol specification document */ 40 | #define GREYBUS_VERSION_MAJOR 0x00 41 | #define GREYBUS_VERSION_MINOR 0x01 42 | 43 | #define GREYBUS_ID_MATCH_DEVICE \ 44 | (GREYBUS_ID_MATCH_VENDOR | GREYBUS_ID_MATCH_PRODUCT) 45 | 46 | #define GREYBUS_DEVICE(v, p) \ 47 | .match_flags = GREYBUS_ID_MATCH_DEVICE, \ 48 | .vendor = (v), \ 49 | .product = (p), 50 | 51 | #define GREYBUS_DEVICE_CLASS(c) \ 52 | .match_flags = GREYBUS_ID_MATCH_CLASS, \ 53 | .class = (c), 54 | 55 | /* Maximum number of CPorts */ 56 | #define CPORT_ID_MAX 4095 /* UniPro max id is 4095 */ 57 | #define CPORT_ID_BAD U16_MAX 58 | 59 | struct greybus_driver { 60 | const char *name; 61 | 62 | int (*probe)(struct gb_bundle *bundle, 63 | const struct greybus_bundle_id *id); 64 | void (*disconnect)(struct gb_bundle *bundle); 65 | 66 | const struct greybus_bundle_id *id_table; 67 | 68 | struct device_driver driver; 69 | }; 70 | #define to_greybus_driver(d) container_of(d, struct greybus_driver, driver) 71 | 72 | static inline void greybus_set_drvdata(struct gb_bundle *bundle, void *data) 73 | { 74 | dev_set_drvdata(&bundle->dev, data); 75 | } 76 | 77 | static inline void *greybus_get_drvdata(struct gb_bundle *bundle) 78 | { 79 | return dev_get_drvdata(&bundle->dev); 80 | } 81 | 82 | /* Don't call these directly, use the module_greybus_driver() macro instead */ 83 | int greybus_register_driver(struct greybus_driver *driver, 84 | struct module *module, const char *mod_name); 85 | void greybus_deregister_driver(struct greybus_driver *driver); 86 | 87 | /* define to get proper THIS_MODULE and KBUILD_MODNAME values */ 88 | #define greybus_register(driver) \ 89 | greybus_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) 90 | #define greybus_deregister(driver) \ 91 | greybus_deregister_driver(driver) 92 | 93 | /** 94 | * module_greybus_driver() - Helper macro for registering a Greybus driver 95 | * @__greybus_driver: greybus_driver structure 96 | * 97 | * Helper macro for Greybus drivers to set up proper module init / exit 98 | * functions. Replaces module_init() and module_exit() and keeps people from 99 | * printing pointless things to the kernel log when their driver is loaded. 100 | */ 101 | #define module_greybus_driver(__greybus_driver) \ 102 | module_driver(__greybus_driver, greybus_register, greybus_deregister) 103 | 104 | int greybus_disabled(void); 105 | 106 | void gb_debugfs_init(void); 107 | void gb_debugfs_cleanup(void); 108 | struct dentry *gb_debugfs_get(void); 109 | 110 | extern struct bus_type greybus_bus_type; 111 | 112 | extern struct device_type greybus_hd_type; 113 | extern struct device_type greybus_module_type; 114 | extern struct device_type greybus_interface_type; 115 | extern struct device_type greybus_control_type; 116 | extern struct device_type greybus_bundle_type; 117 | extern struct device_type greybus_svc_type; 118 | 119 | static inline int is_gb_host_device(const struct device *dev) 120 | { 121 | return dev->type == &greybus_hd_type; 122 | } 123 | 124 | static inline int is_gb_module(const struct device *dev) 125 | { 126 | return dev->type == &greybus_module_type; 127 | } 128 | 129 | static inline int is_gb_interface(const struct device *dev) 130 | { 131 | return dev->type == &greybus_interface_type; 132 | } 133 | 134 | static inline int is_gb_control(const struct device *dev) 135 | { 136 | return dev->type == &greybus_control_type; 137 | } 138 | 139 | static inline int is_gb_bundle(const struct device *dev) 140 | { 141 | return dev->type == &greybus_bundle_type; 142 | } 143 | 144 | static inline int is_gb_svc(const struct device *dev) 145 | { 146 | return dev->type == &greybus_svc_type; 147 | } 148 | 149 | static inline bool cport_id_valid(struct gb_host_device *hd, u16 cport_id) 150 | { 151 | return cport_id != CPORT_ID_BAD && cport_id < hd->num_cports; 152 | } 153 | 154 | #endif /* __KERNEL__ */ 155 | #endif /* __LINUX_GREYBUS_H */ 156 | -------------------------------------------------------------------------------- /greybus_authentication.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Component Authentication User Header 3 | * 4 | * This file is provided under a dual BSD/GPLv2 license. When using or 5 | * redistributing this file, you may do so under either license. 6 | * 7 | * GPL LICENSE SUMMARY 8 | * 9 | * Copyright(c) 2016 Google Inc. All rights reserved. 10 | * Copyright(c) 2016 Linaro Ltd. All rights reserved. 11 | * 12 | * This program is free software; you can redistribute it and/or modify 13 | * it under the terms of version 2 of the GNU General Public License as 14 | * published by the Free Software Foundation. 15 | * 16 | * This program is distributed in the hope that it will be useful, but 17 | * WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | * General Public License version 2 for more details. 20 | * 21 | * BSD LICENSE 22 | * 23 | * Copyright(c) 2016 Google Inc. All rights reserved. 24 | * Copyright(c) 2016 Linaro Ltd. All rights reserved. 25 | * 26 | * Redistribution and use in source and binary forms, with or without 27 | * modification, are permitted provided that the following conditions 28 | * are met: 29 | * 30 | * * Redistributions of source code must retain the above copyright 31 | * notice, this list of conditions and the following disclaimer. 32 | * * Redistributions in binary form must reproduce the above copyright 33 | * notice, this list of conditions and the following disclaimer in 34 | * the documentation and/or other materials provided with the 35 | * distribution. 36 | * * Neither the name of Google Inc. or Linaro Ltd. nor the names of 37 | * its contributors may be used to endorse or promote products 38 | * derived from this software without specific prior written 39 | * permission. 40 | * 41 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 42 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 43 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 44 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR 45 | * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 46 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 47 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 48 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 49 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 50 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 51 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 | */ 53 | 54 | #ifndef __GREYBUS_AUTHENTICATION_USER_H 55 | #define __GREYBUS_AUTHENTICATION_USER_H 56 | 57 | #include 58 | #include 59 | 60 | #define CAP_CERTIFICATE_MAX_SIZE 1600 61 | #define CAP_SIGNATURE_MAX_SIZE 320 62 | 63 | /* Certificate class types */ 64 | #define CAP_CERT_IMS_EAPC 0x00000001 65 | #define CAP_CERT_IMS_EASC 0x00000002 66 | #define CAP_CERT_IMS_EARC 0x00000003 67 | #define CAP_CERT_IMS_IAPC 0x00000004 68 | #define CAP_CERT_IMS_IASC 0x00000005 69 | #define CAP_CERT_IMS_IARC 0x00000006 70 | 71 | /* IMS Certificate response result codes */ 72 | #define CAP_IMS_RESULT_CERT_FOUND 0x00 73 | #define CAP_IMS_RESULT_CERT_CLASS_INVAL 0x01 74 | #define CAP_IMS_RESULT_CERT_CORRUPT 0x02 75 | #define CAP_IMS_RESULT_CERT_NOT_FOUND 0x03 76 | 77 | /* Authentication types */ 78 | #define CAP_AUTH_IMS_PRI 0x00000001 79 | #define CAP_AUTH_IMS_SEC 0x00000002 80 | #define CAP_AUTH_IMS_RSA 0x00000003 81 | 82 | /* Authenticate response result codes */ 83 | #define CAP_AUTH_RESULT_CR_SUCCESS 0x00 84 | #define CAP_AUTH_RESULT_CR_BAD_TYPE 0x01 85 | #define CAP_AUTH_RESULT_CR_WRONG_EP 0x02 86 | #define CAP_AUTH_RESULT_CR_NO_KEY 0x03 87 | #define CAP_AUTH_RESULT_CR_SIG_FAIL 0x04 88 | 89 | 90 | /* IOCTL support */ 91 | struct cap_ioc_get_endpoint_uid { 92 | __u8 uid[8]; 93 | } __attribute__ ((__packed__)); 94 | 95 | struct cap_ioc_get_ims_certificate { 96 | __u32 certificate_class; 97 | __u32 certificate_id; 98 | 99 | __u8 result_code; 100 | __u32 cert_size; 101 | __u8 certificate[CAP_CERTIFICATE_MAX_SIZE]; 102 | } __attribute__ ((__packed__)); 103 | 104 | struct cap_ioc_authenticate { 105 | __u32 auth_type; 106 | __u8 uid[8]; 107 | __u8 challenge[32]; 108 | 109 | __u8 result_code; 110 | __u8 response[64]; 111 | __u32 signature_size; 112 | __u8 signature[CAP_SIGNATURE_MAX_SIZE]; 113 | } __attribute__ ((__packed__)); 114 | 115 | #define CAP_IOCTL_BASE 'C' 116 | #define CAP_IOC_GET_ENDPOINT_UID _IOR(CAP_IOCTL_BASE, 0, struct cap_ioc_get_endpoint_uid) 117 | #define CAP_IOC_GET_IMS_CERTIFICATE _IOWR(CAP_IOCTL_BASE, 1, struct cap_ioc_get_ims_certificate) 118 | #define CAP_IOC_AUTHENTICATE _IOWR(CAP_IOCTL_BASE, 2, struct cap_ioc_authenticate) 119 | 120 | #endif /* __GREYBUS_AUTHENTICATION_USER_H */ 121 | -------------------------------------------------------------------------------- /greybus_firmware.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Firmware Management User Header 3 | * 4 | * This file is provided under a dual BSD/GPLv2 license. When using or 5 | * redistributing this file, you may do so under either license. 6 | * 7 | * GPL LICENSE SUMMARY 8 | * 9 | * Copyright(c) 2016 Google Inc. All rights reserved. 10 | * Copyright(c) 2016 Linaro Ltd. All rights reserved. 11 | * 12 | * This program is free software; you can redistribute it and/or modify 13 | * it under the terms of version 2 of the GNU General Public License as 14 | * published by the Free Software Foundation. 15 | * 16 | * This program is distributed in the hope that it will be useful, but 17 | * WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | * General Public License version 2 for more details. 20 | * 21 | * BSD LICENSE 22 | * 23 | * Copyright(c) 2016 Google Inc. All rights reserved. 24 | * Copyright(c) 2016 Linaro Ltd. All rights reserved. 25 | * 26 | * Redistribution and use in source and binary forms, with or without 27 | * modification, are permitted provided that the following conditions 28 | * are met: 29 | * 30 | * * Redistributions of source code must retain the above copyright 31 | * notice, this list of conditions and the following disclaimer. 32 | * * Redistributions in binary form must reproduce the above copyright 33 | * notice, this list of conditions and the following disclaimer in 34 | * the documentation and/or other materials provided with the 35 | * distribution. 36 | * * Neither the name of Google Inc. or Linaro Ltd. nor the names of 37 | * its contributors may be used to endorse or promote products 38 | * derived from this software without specific prior written 39 | * permission. 40 | * 41 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 42 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 43 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 44 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR 45 | * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 46 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 47 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 48 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 49 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 50 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 51 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 | */ 53 | 54 | #ifndef __GREYBUS_FIRMWARE_USER_H 55 | #define __GREYBUS_FIRMWARE_USER_H 56 | 57 | #include 58 | #include 59 | 60 | #define GB_FIRMWARE_U_TAG_MAX_SIZE 10 61 | 62 | #define GB_FW_U_LOAD_METHOD_UNIPRO 0x01 63 | #define GB_FW_U_LOAD_METHOD_INTERNAL 0x02 64 | 65 | #define GB_FW_U_LOAD_STATUS_FAILED 0x00 66 | #define GB_FW_U_LOAD_STATUS_UNVALIDATED 0x01 67 | #define GB_FW_U_LOAD_STATUS_VALIDATED 0x02 68 | #define GB_FW_U_LOAD_STATUS_VALIDATION_FAILED 0x03 69 | 70 | #define GB_FW_U_BACKEND_FW_STATUS_SUCCESS 0x01 71 | #define GB_FW_U_BACKEND_FW_STATUS_FAIL_FIND 0x02 72 | #define GB_FW_U_BACKEND_FW_STATUS_FAIL_FETCH 0x03 73 | #define GB_FW_U_BACKEND_FW_STATUS_FAIL_WRITE 0x04 74 | #define GB_FW_U_BACKEND_FW_STATUS_INT 0x05 75 | #define GB_FW_U_BACKEND_FW_STATUS_RETRY 0x06 76 | #define GB_FW_U_BACKEND_FW_STATUS_NOT_SUPPORTED 0x07 77 | 78 | #define GB_FW_U_BACKEND_VERSION_STATUS_SUCCESS 0x01 79 | #define GB_FW_U_BACKEND_VERSION_STATUS_NOT_AVAILABLE 0x02 80 | #define GB_FW_U_BACKEND_VERSION_STATUS_NOT_SUPPORTED 0x03 81 | #define GB_FW_U_BACKEND_VERSION_STATUS_RETRY 0x04 82 | #define GB_FW_U_BACKEND_VERSION_STATUS_FAIL_INT 0x05 83 | 84 | /* IOCTL support */ 85 | struct fw_mgmt_ioc_get_intf_version { 86 | __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; 87 | __u16 major; 88 | __u16 minor; 89 | } __attribute__ ((__packed__)); 90 | 91 | struct fw_mgmt_ioc_get_backend_version { 92 | __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; 93 | __u16 major; 94 | __u16 minor; 95 | __u8 status; 96 | } __attribute__ ((__packed__)); 97 | 98 | struct fw_mgmt_ioc_intf_load_and_validate { 99 | __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; 100 | __u8 load_method; 101 | __u8 status; 102 | __u16 major; 103 | __u16 minor; 104 | } __attribute__ ((__packed__)); 105 | 106 | struct fw_mgmt_ioc_backend_fw_update { 107 | __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; 108 | __u8 status; 109 | } __attribute__ ((__packed__)); 110 | 111 | #define FW_MGMT_IOCTL_BASE 'F' 112 | #define FW_MGMT_IOC_GET_INTF_FW _IOR(FW_MGMT_IOCTL_BASE, 0, struct fw_mgmt_ioc_get_intf_version) 113 | #define FW_MGMT_IOC_GET_BACKEND_FW _IOWR(FW_MGMT_IOCTL_BASE, 1, struct fw_mgmt_ioc_get_backend_version) 114 | #define FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE _IOWR(FW_MGMT_IOCTL_BASE, 2, struct fw_mgmt_ioc_intf_load_and_validate) 115 | #define FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE _IOWR(FW_MGMT_IOCTL_BASE, 3, struct fw_mgmt_ioc_backend_fw_update) 116 | #define FW_MGMT_IOC_SET_TIMEOUT_MS _IOW(FW_MGMT_IOCTL_BASE, 4, unsigned int) 117 | #define FW_MGMT_IOC_MODE_SWITCH _IO(FW_MGMT_IOCTL_BASE, 5) 118 | 119 | #endif /* __GREYBUS_FIRMWARE_USER_H */ 120 | 121 | -------------------------------------------------------------------------------- /greybus_id.h: -------------------------------------------------------------------------------- 1 | /* FIXME 2 | * move this to include/linux/mod_devicetable.h when merging 3 | */ 4 | 5 | #ifndef __LINUX_GREYBUS_ID_H 6 | #define __LINUX_GREYBUS_ID_H 7 | 8 | #include 9 | #include 10 | 11 | 12 | struct greybus_bundle_id { 13 | __u16 match_flags; 14 | __u32 vendor; 15 | __u32 product; 16 | __u8 class; 17 | 18 | kernel_ulong_t driver_info __aligned(sizeof(kernel_ulong_t)); 19 | }; 20 | 21 | /* Used to match the greybus_bundle_id */ 22 | #define GREYBUS_ID_MATCH_VENDOR BIT(0) 23 | #define GREYBUS_ID_MATCH_PRODUCT BIT(1) 24 | #define GREYBUS_ID_MATCH_CLASS BIT(2) 25 | 26 | #endif /* __LINUX_GREYBUS_ID_H */ 27 | -------------------------------------------------------------------------------- /greybus_manifest.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus manifest definition 3 | * 4 | * See "Greybus Application Protocol" document (version 0.1) for 5 | * details on these values and structures. 6 | * 7 | * Copyright 2014-2015 Google Inc. 8 | * Copyright 2014-2015 Linaro Ltd. 9 | * 10 | * Released under the GPLv2 and BSD licenses. 11 | */ 12 | 13 | #ifndef __GREYBUS_MANIFEST_H 14 | #define __GREYBUS_MANIFEST_H 15 | 16 | enum greybus_descriptor_type { 17 | GREYBUS_TYPE_INVALID = 0x00, 18 | GREYBUS_TYPE_INTERFACE = 0x01, 19 | GREYBUS_TYPE_STRING = 0x02, 20 | GREYBUS_TYPE_BUNDLE = 0x03, 21 | GREYBUS_TYPE_CPORT = 0x04, 22 | }; 23 | 24 | enum greybus_protocol { 25 | GREYBUS_PROTOCOL_CONTROL = 0x00, 26 | /* 0x01 is unused */ 27 | GREYBUS_PROTOCOL_GPIO = 0x02, 28 | GREYBUS_PROTOCOL_I2C = 0x03, 29 | GREYBUS_PROTOCOL_UART = 0x04, 30 | GREYBUS_PROTOCOL_HID = 0x05, 31 | GREYBUS_PROTOCOL_USB = 0x06, 32 | GREYBUS_PROTOCOL_SDIO = 0x07, 33 | GREYBUS_PROTOCOL_POWER_SUPPLY = 0x08, 34 | GREYBUS_PROTOCOL_PWM = 0x09, 35 | /* 0x0a is unused */ 36 | GREYBUS_PROTOCOL_SPI = 0x0b, 37 | GREYBUS_PROTOCOL_DISPLAY = 0x0c, 38 | GREYBUS_PROTOCOL_CAMERA_MGMT = 0x0d, 39 | GREYBUS_PROTOCOL_SENSOR = 0x0e, 40 | GREYBUS_PROTOCOL_LIGHTS = 0x0f, 41 | GREYBUS_PROTOCOL_VIBRATOR = 0x10, 42 | GREYBUS_PROTOCOL_LOOPBACK = 0x11, 43 | GREYBUS_PROTOCOL_AUDIO_MGMT = 0x12, 44 | GREYBUS_PROTOCOL_AUDIO_DATA = 0x13, 45 | GREYBUS_PROTOCOL_SVC = 0x14, 46 | GREYBUS_PROTOCOL_BOOTROM = 0x15, 47 | GREYBUS_PROTOCOL_CAMERA_DATA = 0x16, 48 | GREYBUS_PROTOCOL_FW_DOWNLOAD = 0x17, 49 | GREYBUS_PROTOCOL_FW_MANAGEMENT = 0x18, 50 | GREYBUS_PROTOCOL_AUTHENTICATION = 0x19, 51 | GREYBUS_PROTOCOL_LOG = 0x1a, 52 | /* ... */ 53 | GREYBUS_PROTOCOL_RAW = 0xfe, 54 | GREYBUS_PROTOCOL_VENDOR = 0xff, 55 | }; 56 | 57 | enum greybus_class_type { 58 | GREYBUS_CLASS_CONTROL = 0x00, 59 | /* 0x01 is unused */ 60 | /* 0x02 is unused */ 61 | /* 0x03 is unused */ 62 | /* 0x04 is unused */ 63 | GREYBUS_CLASS_HID = 0x05, 64 | /* 0x06 is unused */ 65 | /* 0x07 is unused */ 66 | GREYBUS_CLASS_POWER_SUPPLY = 0x08, 67 | /* 0x09 is unused */ 68 | GREYBUS_CLASS_BRIDGED_PHY = 0x0a, 69 | /* 0x0b is unused */ 70 | GREYBUS_CLASS_DISPLAY = 0x0c, 71 | GREYBUS_CLASS_CAMERA = 0x0d, 72 | GREYBUS_CLASS_SENSOR = 0x0e, 73 | GREYBUS_CLASS_LIGHTS = 0x0f, 74 | GREYBUS_CLASS_VIBRATOR = 0x10, 75 | GREYBUS_CLASS_LOOPBACK = 0x11, 76 | GREYBUS_CLASS_AUDIO = 0x12, 77 | /* 0x13 is unused */ 78 | /* 0x14 is unused */ 79 | GREYBUS_CLASS_BOOTROM = 0x15, 80 | GREYBUS_CLASS_FW_MANAGEMENT = 0x16, 81 | GREYBUS_CLASS_LOG = 0x17, 82 | /* ... */ 83 | GREYBUS_CLASS_RAW = 0xfe, 84 | GREYBUS_CLASS_VENDOR = 0xff, 85 | }; 86 | 87 | enum { 88 | GREYBUS_INTERFACE_FEATURE_TIMESYNC = BIT(0), 89 | }; 90 | 91 | /* 92 | * The string in a string descriptor is not NUL-terminated. The 93 | * size of the descriptor will be rounded up to a multiple of 4 94 | * bytes, by padding the string with 0x00 bytes if necessary. 95 | */ 96 | struct greybus_descriptor_string { 97 | __u8 length; 98 | __u8 id; 99 | __u8 string[0]; 100 | } __packed; 101 | 102 | /* 103 | * An interface descriptor describes information about an interface as a whole, 104 | * *not* the functions within it. 105 | */ 106 | struct greybus_descriptor_interface { 107 | __u8 vendor_stringid; 108 | __u8 product_stringid; 109 | __u8 features; 110 | __u8 pad; 111 | } __packed; 112 | 113 | /* 114 | * An bundle descriptor defines an identification number and a class for 115 | * each bundle. 116 | * 117 | * @id: Uniquely identifies a bundle within a interface, its sole purpose is to 118 | * allow CPort descriptors to specify which bundle they are associated with. 119 | * The first bundle will have id 0, second will have 1 and so on. 120 | * 121 | * The largest CPort id associated with an bundle (defined by a 122 | * CPort descriptor in the manifest) is used to determine how to 123 | * encode the device id and module number in UniPro packets 124 | * that use the bundle. 125 | * 126 | * @class: It is used by kernel to know the functionality provided by the 127 | * bundle and will be matched against drivers functinality while probing greybus 128 | * driver. It should contain one of the values defined in 129 | * 'enum greybus_class_type'. 130 | * 131 | */ 132 | struct greybus_descriptor_bundle { 133 | __u8 id; /* interface-relative id (0..) */ 134 | __u8 class; 135 | __u8 pad[2]; 136 | } __packed; 137 | 138 | /* 139 | * A CPort descriptor indicates the id of the bundle within the 140 | * module it's associated with, along with the CPort id used to 141 | * address the CPort. The protocol id defines the format of messages 142 | * exchanged using the CPort. 143 | */ 144 | struct greybus_descriptor_cport { 145 | __le16 id; 146 | __u8 bundle; 147 | __u8 protocol_id; /* enum greybus_protocol */ 148 | } __packed; 149 | 150 | struct greybus_descriptor_header { 151 | __le16 size; 152 | __u8 type; /* enum greybus_descriptor_type */ 153 | __u8 pad; 154 | } __packed; 155 | 156 | struct greybus_descriptor { 157 | struct greybus_descriptor_header header; 158 | union { 159 | struct greybus_descriptor_string string; 160 | struct greybus_descriptor_interface interface; 161 | struct greybus_descriptor_bundle bundle; 162 | struct greybus_descriptor_cport cport; 163 | }; 164 | } __packed; 165 | 166 | struct greybus_manifest_header { 167 | __le16 size; 168 | __u8 version_major; 169 | __u8 version_minor; 170 | } __packed; 171 | 172 | struct greybus_manifest { 173 | struct greybus_manifest_header header; 174 | struct greybus_descriptor descriptors[0]; 175 | } __packed; 176 | 177 | #endif /* __GREYBUS_MANIFEST_H */ 178 | -------------------------------------------------------------------------------- /hd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Host Device 3 | * 4 | * Copyright 2014-2015 Google Inc. 5 | * Copyright 2014-2015 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include "greybus.h" 14 | #include "greybus_trace.h" 15 | 16 | EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_create); 17 | EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_release); 18 | EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_add); 19 | EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_del); 20 | EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_in); 21 | EXPORT_TRACEPOINT_SYMBOL_GPL(gb_message_submit); 22 | 23 | static struct ida gb_hd_bus_id_map; 24 | 25 | int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, 26 | bool async) 27 | { 28 | if (!hd || !hd->driver || !hd->driver->output) 29 | return -EINVAL; 30 | return hd->driver->output(hd, req, size, cmd, async); 31 | } 32 | EXPORT_SYMBOL_GPL(gb_hd_output); 33 | 34 | static ssize_t bus_id_show(struct device *dev, 35 | struct device_attribute *attr, char *buf) 36 | { 37 | struct gb_host_device *hd = to_gb_host_device(dev); 38 | 39 | return sprintf(buf, "%d\n", hd->bus_id); 40 | } 41 | static DEVICE_ATTR_RO(bus_id); 42 | 43 | static struct attribute *bus_attrs[] = { 44 | &dev_attr_bus_id.attr, 45 | NULL 46 | }; 47 | ATTRIBUTE_GROUPS(bus); 48 | 49 | int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id) 50 | { 51 | struct ida *id_map = &hd->cport_id_map; 52 | int ret; 53 | 54 | ret = ida_simple_get(id_map, cport_id, cport_id + 1, GFP_KERNEL); 55 | if (ret < 0) { 56 | dev_err(&hd->dev, "failed to reserve cport %u\n", cport_id); 57 | return ret; 58 | } 59 | 60 | return 0; 61 | } 62 | EXPORT_SYMBOL_GPL(gb_hd_cport_reserve); 63 | 64 | void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id) 65 | { 66 | struct ida *id_map = &hd->cport_id_map; 67 | 68 | ida_simple_remove(id_map, cport_id); 69 | } 70 | EXPORT_SYMBOL_GPL(gb_hd_cport_release_reserved); 71 | 72 | /* Locking: Caller guarantees serialisation */ 73 | int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, 74 | unsigned long flags) 75 | { 76 | struct ida *id_map = &hd->cport_id_map; 77 | int ida_start, ida_end; 78 | 79 | if (hd->driver->cport_allocate) 80 | return hd->driver->cport_allocate(hd, cport_id, flags); 81 | 82 | if (cport_id < 0) { 83 | ida_start = 0; 84 | ida_end = hd->num_cports; 85 | } else if (cport_id < hd->num_cports) { 86 | ida_start = cport_id; 87 | ida_end = cport_id + 1; 88 | } else { 89 | dev_err(&hd->dev, "cport %d not available\n", cport_id); 90 | return -EINVAL; 91 | } 92 | 93 | return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); 94 | } 95 | 96 | /* Locking: Caller guarantees serialisation */ 97 | void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id) 98 | { 99 | if (hd->driver->cport_release) { 100 | hd->driver->cport_release(hd, cport_id); 101 | return; 102 | } 103 | 104 | ida_simple_remove(&hd->cport_id_map, cport_id); 105 | } 106 | 107 | static void gb_hd_release(struct device *dev) 108 | { 109 | struct gb_host_device *hd = to_gb_host_device(dev); 110 | 111 | trace_gb_hd_release(hd); 112 | 113 | if (hd->svc) 114 | gb_svc_put(hd->svc); 115 | ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id); 116 | ida_destroy(&hd->cport_id_map); 117 | kfree(hd); 118 | } 119 | 120 | struct device_type greybus_hd_type = { 121 | .name = "greybus_host_device", 122 | .release = gb_hd_release, 123 | }; 124 | 125 | struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, 126 | struct device *parent, 127 | size_t buffer_size_max, 128 | size_t num_cports) 129 | { 130 | struct gb_host_device *hd; 131 | int ret; 132 | 133 | /* 134 | * Validate that the driver implements all of the callbacks 135 | * so that we don't have to every time we make them. 136 | */ 137 | if ((!driver->message_send) || (!driver->message_cancel)) { 138 | dev_err(parent, "mandatory hd-callbacks missing\n"); 139 | return ERR_PTR(-EINVAL); 140 | } 141 | 142 | if (buffer_size_max < GB_OPERATION_MESSAGE_SIZE_MIN) { 143 | dev_err(parent, "greybus host-device buffers too small\n"); 144 | return ERR_PTR(-EINVAL); 145 | } 146 | 147 | if (num_cports == 0 || num_cports > CPORT_ID_MAX + 1) { 148 | dev_err(parent, "Invalid number of CPorts: %zu\n", num_cports); 149 | return ERR_PTR(-EINVAL); 150 | } 151 | 152 | /* 153 | * Make sure to never allocate messages larger than what the Greybus 154 | * protocol supports. 155 | */ 156 | if (buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) { 157 | dev_warn(parent, "limiting buffer size to %u\n", 158 | GB_OPERATION_MESSAGE_SIZE_MAX); 159 | buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX; 160 | } 161 | 162 | hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL); 163 | if (!hd) 164 | return ERR_PTR(-ENOMEM); 165 | 166 | ret = ida_simple_get(&gb_hd_bus_id_map, 1, 0, GFP_KERNEL); 167 | if (ret < 0) { 168 | kfree(hd); 169 | return ERR_PTR(ret); 170 | } 171 | hd->bus_id = ret; 172 | 173 | hd->driver = driver; 174 | INIT_LIST_HEAD(&hd->modules); 175 | INIT_LIST_HEAD(&hd->connections); 176 | ida_init(&hd->cport_id_map); 177 | hd->buffer_size_max = buffer_size_max; 178 | hd->num_cports = num_cports; 179 | 180 | hd->dev.parent = parent; 181 | hd->dev.bus = &greybus_bus_type; 182 | hd->dev.type = &greybus_hd_type; 183 | hd->dev.groups = bus_groups; 184 | hd->dev.dma_mask = hd->dev.parent->dma_mask; 185 | device_initialize(&hd->dev); 186 | dev_set_name(&hd->dev, "greybus%d", hd->bus_id); 187 | 188 | trace_gb_hd_create(hd); 189 | 190 | hd->svc = gb_svc_create(hd); 191 | if (!hd->svc) { 192 | dev_err(&hd->dev, "failed to create svc\n"); 193 | put_device(&hd->dev); 194 | return ERR_PTR(-ENOMEM); 195 | } 196 | 197 | return hd; 198 | } 199 | EXPORT_SYMBOL_GPL(gb_hd_create); 200 | 201 | int gb_hd_add(struct gb_host_device *hd) 202 | { 203 | int ret; 204 | 205 | ret = device_add(&hd->dev); 206 | if (ret) 207 | return ret; 208 | 209 | ret = gb_svc_add(hd->svc); 210 | if (ret) { 211 | device_del(&hd->dev); 212 | return ret; 213 | } 214 | 215 | trace_gb_hd_add(hd); 216 | 217 | return 0; 218 | } 219 | EXPORT_SYMBOL_GPL(gb_hd_add); 220 | 221 | void gb_hd_del(struct gb_host_device *hd) 222 | { 223 | trace_gb_hd_del(hd); 224 | 225 | /* 226 | * Tear down the svc and flush any on-going hotplug processing before 227 | * removing the remaining interfaces. 228 | */ 229 | gb_svc_del(hd->svc); 230 | 231 | device_del(&hd->dev); 232 | } 233 | EXPORT_SYMBOL_GPL(gb_hd_del); 234 | 235 | void gb_hd_shutdown(struct gb_host_device *hd) 236 | { 237 | gb_svc_del(hd->svc); 238 | } 239 | EXPORT_SYMBOL_GPL(gb_hd_shutdown); 240 | 241 | void gb_hd_put(struct gb_host_device *hd) 242 | { 243 | put_device(&hd->dev); 244 | } 245 | EXPORT_SYMBOL_GPL(gb_hd_put); 246 | 247 | int __init gb_hd_init(void) 248 | { 249 | ida_init(&gb_hd_bus_id_map); 250 | 251 | return 0; 252 | } 253 | 254 | void gb_hd_exit(void) 255 | { 256 | ida_destroy(&gb_hd_bus_id_map); 257 | } 258 | -------------------------------------------------------------------------------- /hd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Host Device 3 | * 4 | * Copyright 2014-2015 Google Inc. 5 | * Copyright 2014-2015 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __HD_H 11 | #define __HD_H 12 | 13 | struct gb_host_device; 14 | struct gb_message; 15 | 16 | struct gb_hd_driver { 17 | size_t hd_priv_size; 18 | 19 | int (*cport_allocate)(struct gb_host_device *hd, int cport_id, 20 | unsigned long flags); 21 | void (*cport_release)(struct gb_host_device *hd, u16 cport_id); 22 | int (*cport_enable)(struct gb_host_device *hd, u16 cport_id, 23 | unsigned long flags); 24 | int (*cport_disable)(struct gb_host_device *hd, u16 cport_id); 25 | int (*cport_connected)(struct gb_host_device *hd, u16 cport_id); 26 | int (*cport_flush)(struct gb_host_device *hd, u16 cport_id); 27 | int (*cport_shutdown)(struct gb_host_device *hd, u16 cport_id, 28 | u8 phase, unsigned int timeout); 29 | int (*cport_quiesce)(struct gb_host_device *hd, u16 cport_id, 30 | size_t peer_space, unsigned int timeout); 31 | int (*cport_clear)(struct gb_host_device *hd, u16 cport_id); 32 | 33 | int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id, 34 | struct gb_message *message, gfp_t gfp_mask); 35 | void (*message_cancel)(struct gb_message *message); 36 | int (*latency_tag_enable)(struct gb_host_device *hd, u16 cport_id); 37 | int (*latency_tag_disable)(struct gb_host_device *hd, u16 cport_id); 38 | int (*output)(struct gb_host_device *hd, void *req, u16 size, u8 cmd, 39 | bool async); 40 | int (*timesync_enable)(struct gb_host_device *hd, u8 count, 41 | u64 frame_time, u32 strobe_delay, u32 refclk); 42 | int (*timesync_disable)(struct gb_host_device *hd); 43 | int (*timesync_authoritative)(struct gb_host_device *hd, 44 | u64 *frame_time); 45 | int (*timesync_get_last_event)(struct gb_host_device *hd, 46 | u64 *frame_time); 47 | }; 48 | 49 | struct gb_host_device { 50 | struct device dev; 51 | int bus_id; 52 | const struct gb_hd_driver *driver; 53 | 54 | struct list_head modules; 55 | struct list_head connections; 56 | struct ida cport_id_map; 57 | 58 | /* Number of CPorts supported by the UniPro IP */ 59 | size_t num_cports; 60 | 61 | /* Host device buffer constraints */ 62 | size_t buffer_size_max; 63 | 64 | struct gb_svc *svc; 65 | /* Private data for the host driver */ 66 | unsigned long hd_priv[0] __aligned(sizeof(s64)); 67 | }; 68 | #define to_gb_host_device(d) container_of(d, struct gb_host_device, dev) 69 | 70 | int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id); 71 | void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id); 72 | int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, 73 | unsigned long flags); 74 | void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id); 75 | 76 | struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, 77 | struct device *parent, 78 | size_t buffer_size_max, 79 | size_t num_cports); 80 | int gb_hd_add(struct gb_host_device *hd); 81 | void gb_hd_del(struct gb_host_device *hd); 82 | void gb_hd_shutdown(struct gb_host_device *hd); 83 | void gb_hd_put(struct gb_host_device *hd); 84 | int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, 85 | bool in_irq); 86 | 87 | int gb_hd_init(void); 88 | void gb_hd_exit(void); 89 | 90 | #endif /* __HD_H */ 91 | -------------------------------------------------------------------------------- /interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Interface Block code 3 | * 4 | * Copyright 2014 Google Inc. 5 | * Copyright 2014 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __INTERFACE_H 11 | #define __INTERFACE_H 12 | 13 | enum gb_interface_type { 14 | GB_INTERFACE_TYPE_INVALID = 0, 15 | GB_INTERFACE_TYPE_UNKNOWN, 16 | GB_INTERFACE_TYPE_DUMMY, 17 | GB_INTERFACE_TYPE_UNIPRO, 18 | GB_INTERFACE_TYPE_GREYBUS, 19 | }; 20 | 21 | #define GB_INTERFACE_QUIRK_NO_CPORT_FEATURES BIT(0) 22 | #define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(1) 23 | #define GB_INTERFACE_QUIRK_NO_GMP_IDS BIT(2) 24 | #define GB_INTERFACE_QUIRK_FORCED_DISABLE BIT(3) 25 | #define GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH BIT(4) 26 | #define GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE BIT(5) 27 | #define GB_INTERFACE_QUIRK_NO_PM BIT(6) 28 | 29 | struct gb_interface { 30 | struct device dev; 31 | struct gb_control *control; 32 | 33 | struct list_head bundles; 34 | struct list_head module_node; 35 | struct list_head manifest_descs; 36 | u8 interface_id; /* Physical location within the Endo */ 37 | u8 device_id; 38 | u8 features; /* Feature flags set in the manifest */ 39 | 40 | enum gb_interface_type type; 41 | 42 | u32 ddbl1_manufacturer_id; 43 | u32 ddbl1_product_id; 44 | u32 vendor_id; 45 | u32 product_id; 46 | u64 serial_number; 47 | 48 | struct gb_host_device *hd; 49 | struct gb_module *module; 50 | 51 | unsigned long quirks; 52 | 53 | struct mutex mutex; 54 | 55 | bool disconnected; 56 | 57 | bool ejected; 58 | bool removed; 59 | bool active; 60 | bool enabled; 61 | bool mode_switch; 62 | bool dme_read; 63 | 64 | struct work_struct mode_switch_work; 65 | struct completion mode_switch_completion; 66 | }; 67 | #define to_gb_interface(d) container_of(d, struct gb_interface, dev) 68 | 69 | struct gb_interface *gb_interface_create(struct gb_module *module, 70 | u8 interface_id); 71 | int gb_interface_activate(struct gb_interface *intf); 72 | void gb_interface_deactivate(struct gb_interface *intf); 73 | int gb_interface_enable(struct gb_interface *intf); 74 | void gb_interface_disable(struct gb_interface *intf); 75 | int gb_interface_timesync_enable(struct gb_interface *intf, u8 count, 76 | u64 frame_time, u32 strobe_delay, u32 refclk); 77 | int gb_interface_timesync_authoritative(struct gb_interface *intf, 78 | u64 *frame_time); 79 | int gb_interface_timesync_disable(struct gb_interface *intf); 80 | int gb_interface_add(struct gb_interface *intf); 81 | void gb_interface_del(struct gb_interface *intf); 82 | void gb_interface_put(struct gb_interface *intf); 83 | void gb_interface_mailbox_event(struct gb_interface *intf, u16 result, 84 | u32 mailbox); 85 | 86 | int gb_interface_request_mode_switch(struct gb_interface *intf); 87 | 88 | #endif /* __INTERFACE_H */ 89 | -------------------------------------------------------------------------------- /log.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus driver for the log protocol 3 | * 4 | * Copyright 2016 Google Inc. 5 | * 6 | * Released under the GPLv2 only. 7 | */ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "greybus.h" 15 | 16 | struct gb_log { 17 | struct gb_connection *connection; 18 | }; 19 | 20 | static int gb_log_request_handler(struct gb_operation *op) 21 | { 22 | struct gb_connection *connection = op->connection; 23 | struct device *dev = &connection->bundle->dev; 24 | struct gb_log_send_log_request *receive; 25 | u16 len; 26 | 27 | if (op->type != GB_LOG_TYPE_SEND_LOG) { 28 | dev_err(dev, "unknown request type 0x%02x\n", op->type); 29 | return -EINVAL; 30 | } 31 | 32 | /* Verify size of payload */ 33 | if (op->request->payload_size < sizeof(*receive)) { 34 | dev_err(dev, "log request too small (%zu < %zu)\n", 35 | op->request->payload_size, sizeof(*receive)); 36 | return -EINVAL; 37 | } 38 | receive = op->request->payload; 39 | len = le16_to_cpu(receive->len); 40 | if (len != (int)(op->request->payload_size - sizeof(*receive))) { 41 | dev_err(dev, "log request wrong size %d vs %d\n", len, 42 | (int)(op->request->payload_size - sizeof(*receive))); 43 | return -EINVAL; 44 | } 45 | if (len == 0) { 46 | dev_err(dev, "log request of 0 bytes?\n"); 47 | return -EINVAL; 48 | } 49 | 50 | if (len > GB_LOG_MAX_LEN) { 51 | dev_err(dev, "log request too big: %d\n", len); 52 | return -EINVAL; 53 | } 54 | 55 | /* Ensure the buffer is 0 terminated */ 56 | receive->msg[len - 1] = '\0'; 57 | 58 | /* Print with dev_dbg() so that it can be easily turned off using 59 | * dynamic debugging (and prevent any DoS) */ 60 | dev_dbg(dev, "%s", receive->msg); 61 | 62 | return 0; 63 | } 64 | 65 | static int gb_log_probe(struct gb_bundle *bundle, 66 | const struct greybus_bundle_id *id) 67 | { 68 | struct greybus_descriptor_cport *cport_desc; 69 | struct gb_connection *connection; 70 | struct gb_log *log; 71 | int retval; 72 | 73 | if (bundle->num_cports != 1) 74 | return -ENODEV; 75 | 76 | cport_desc = &bundle->cport_desc[0]; 77 | if (cport_desc->protocol_id != GREYBUS_PROTOCOL_LOG) 78 | return -ENODEV; 79 | 80 | log = kzalloc(sizeof(*log), GFP_KERNEL); 81 | if (!log) 82 | return -ENOMEM; 83 | 84 | connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), 85 | gb_log_request_handler); 86 | if (IS_ERR(connection)) { 87 | retval = PTR_ERR(connection); 88 | goto error_free; 89 | } 90 | 91 | log->connection = connection; 92 | greybus_set_drvdata(bundle, log); 93 | 94 | retval = gb_connection_enable(connection); 95 | if (retval) 96 | goto error_connection_destroy; 97 | 98 | return 0; 99 | 100 | error_connection_destroy: 101 | gb_connection_destroy(connection); 102 | error_free: 103 | kfree(log); 104 | return retval; 105 | } 106 | 107 | static void gb_log_disconnect(struct gb_bundle *bundle) 108 | { 109 | struct gb_log *log = greybus_get_drvdata(bundle); 110 | struct gb_connection *connection = log->connection; 111 | 112 | gb_connection_disable(connection); 113 | gb_connection_destroy(connection); 114 | 115 | kfree(log); 116 | } 117 | 118 | static const struct greybus_bundle_id gb_log_id_table[] = { 119 | { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOG) }, 120 | { } 121 | }; 122 | MODULE_DEVICE_TABLE(greybus, gb_log_id_table); 123 | 124 | static struct greybus_driver gb_log_driver = { 125 | .name = "log", 126 | .probe = gb_log_probe, 127 | .disconnect = gb_log_disconnect, 128 | .id_table = gb_log_id_table, 129 | }; 130 | module_greybus_driver(gb_log_driver); 131 | 132 | MODULE_LICENSE("GPL v2"); 133 | -------------------------------------------------------------------------------- /manifest.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus manifest parsing 3 | * 4 | * Copyright 2014 Google Inc. 5 | * Copyright 2014 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __MANIFEST_H 11 | #define __MANIFEST_H 12 | 13 | struct gb_interface; 14 | bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size); 15 | 16 | #endif /* __MANIFEST_H */ 17 | -------------------------------------------------------------------------------- /module.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Module code 3 | * 4 | * Copyright 2016 Google Inc. 5 | * Copyright 2016 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #include "greybus.h" 11 | #include "greybus_trace.h" 12 | 13 | 14 | static ssize_t eject_store(struct device *dev, 15 | struct device_attribute *attr, 16 | const char *buf, size_t len) 17 | { 18 | struct gb_module *module = to_gb_module(dev); 19 | struct gb_interface *intf; 20 | size_t i; 21 | long val; 22 | int ret; 23 | 24 | ret = kstrtol(buf, 0, &val); 25 | if (ret) 26 | return ret; 27 | 28 | if (!val) 29 | return len; 30 | 31 | for (i = 0; i < module->num_interfaces; ++i) { 32 | intf = module->interfaces[i]; 33 | 34 | mutex_lock(&intf->mutex); 35 | /* Set flag to prevent concurrent activation. */ 36 | intf->ejected = true; 37 | gb_interface_disable(intf); 38 | gb_interface_deactivate(intf); 39 | mutex_unlock(&intf->mutex); 40 | } 41 | 42 | /* Tell the SVC to eject the primary interface. */ 43 | ret = gb_svc_intf_eject(module->hd->svc, module->module_id); 44 | if (ret) 45 | return ret; 46 | 47 | return len; 48 | } 49 | static DEVICE_ATTR_WO(eject); 50 | 51 | static ssize_t module_id_show(struct device *dev, 52 | struct device_attribute *attr, char *buf) 53 | { 54 | struct gb_module *module = to_gb_module(dev); 55 | 56 | return sprintf(buf, "%u\n", module->module_id); 57 | } 58 | static DEVICE_ATTR_RO(module_id); 59 | 60 | static ssize_t num_interfaces_show(struct device *dev, 61 | struct device_attribute *attr, char *buf) 62 | { 63 | struct gb_module *module = to_gb_module(dev); 64 | 65 | return sprintf(buf, "%zu\n", module->num_interfaces); 66 | } 67 | static DEVICE_ATTR_RO(num_interfaces); 68 | 69 | static struct attribute *module_attrs[] = { 70 | &dev_attr_eject.attr, 71 | &dev_attr_module_id.attr, 72 | &dev_attr_num_interfaces.attr, 73 | NULL, 74 | }; 75 | ATTRIBUTE_GROUPS(module); 76 | 77 | static void gb_module_release(struct device *dev) 78 | { 79 | struct gb_module *module = to_gb_module(dev); 80 | 81 | trace_gb_module_release(module); 82 | 83 | kfree(module); 84 | } 85 | 86 | struct device_type greybus_module_type = { 87 | .name = "greybus_module", 88 | .release = gb_module_release, 89 | }; 90 | 91 | struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, 92 | size_t num_interfaces) 93 | { 94 | struct gb_interface *intf; 95 | struct gb_module *module; 96 | int i; 97 | 98 | module = kzalloc(sizeof(*module) + num_interfaces * sizeof(intf), 99 | GFP_KERNEL); 100 | if (!module) 101 | return NULL; 102 | 103 | module->hd = hd; 104 | module->module_id = module_id; 105 | module->num_interfaces = num_interfaces; 106 | 107 | module->dev.parent = &hd->dev; 108 | module->dev.bus = &greybus_bus_type; 109 | module->dev.type = &greybus_module_type; 110 | module->dev.groups = module_groups; 111 | module->dev.dma_mask = hd->dev.dma_mask; 112 | device_initialize(&module->dev); 113 | dev_set_name(&module->dev, "%d-%u", hd->bus_id, module_id); 114 | 115 | trace_gb_module_create(module); 116 | 117 | for (i = 0; i < num_interfaces; ++i) { 118 | intf = gb_interface_create(module, module_id + i); 119 | if (!intf) { 120 | dev_err(&module->dev, "failed to create interface %u\n", 121 | module_id + i); 122 | goto err_put_interfaces; 123 | } 124 | module->interfaces[i] = intf; 125 | } 126 | 127 | return module; 128 | 129 | err_put_interfaces: 130 | for (--i; i > 0; --i) 131 | gb_interface_put(module->interfaces[i]); 132 | 133 | put_device(&module->dev); 134 | 135 | return NULL; 136 | } 137 | 138 | /* 139 | * Register and enable an interface after first attempting to activate it. 140 | */ 141 | static void gb_module_register_interface(struct gb_interface *intf) 142 | { 143 | struct gb_module *module = intf->module; 144 | u8 intf_id = intf->interface_id; 145 | int ret; 146 | 147 | mutex_lock(&intf->mutex); 148 | 149 | ret = gb_interface_activate(intf); 150 | if (ret) { 151 | if (intf->type != GB_INTERFACE_TYPE_DUMMY) { 152 | dev_err(&module->dev, 153 | "failed to activate interface %u: %d\n", 154 | intf_id, ret); 155 | } 156 | 157 | gb_interface_add(intf); 158 | goto err_unlock; 159 | } 160 | 161 | ret = gb_interface_add(intf); 162 | if (ret) 163 | goto err_interface_deactivate; 164 | 165 | ret = gb_interface_enable(intf); 166 | if (ret) { 167 | dev_err(&module->dev, "failed to enable interface %u: %d\n", 168 | intf_id, ret); 169 | goto err_interface_deactivate; 170 | } 171 | 172 | mutex_unlock(&intf->mutex); 173 | 174 | return; 175 | 176 | err_interface_deactivate: 177 | gb_interface_deactivate(intf); 178 | err_unlock: 179 | mutex_unlock(&intf->mutex); 180 | } 181 | 182 | static void gb_module_deregister_interface(struct gb_interface *intf) 183 | { 184 | /* Mark as disconnected to prevent I/O during disable. */ 185 | if (intf->module->disconnected) 186 | intf->disconnected = true; 187 | 188 | mutex_lock(&intf->mutex); 189 | intf->removed = true; 190 | gb_interface_disable(intf); 191 | gb_interface_deactivate(intf); 192 | mutex_unlock(&intf->mutex); 193 | 194 | gb_interface_del(intf); 195 | } 196 | 197 | /* Register a module and its interfaces. */ 198 | int gb_module_add(struct gb_module *module) 199 | { 200 | size_t i; 201 | int ret; 202 | 203 | ret = device_add(&module->dev); 204 | if (ret) { 205 | dev_err(&module->dev, "failed to register module: %d\n", ret); 206 | return ret; 207 | } 208 | 209 | trace_gb_module_add(module); 210 | 211 | for (i = 0; i < module->num_interfaces; ++i) 212 | gb_module_register_interface(module->interfaces[i]); 213 | 214 | return 0; 215 | } 216 | 217 | /* Deregister a module and its interfaces. */ 218 | void gb_module_del(struct gb_module *module) 219 | { 220 | size_t i; 221 | 222 | for (i = 0; i < module->num_interfaces; ++i) 223 | gb_module_deregister_interface(module->interfaces[i]); 224 | 225 | trace_gb_module_del(module); 226 | 227 | device_del(&module->dev); 228 | } 229 | 230 | void gb_module_put(struct gb_module *module) 231 | { 232 | size_t i; 233 | 234 | for (i = 0; i < module->num_interfaces; ++i) 235 | gb_interface_put(module->interfaces[i]); 236 | 237 | put_device(&module->dev); 238 | } 239 | -------------------------------------------------------------------------------- /module.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Module code 3 | * 4 | * Copyright 2016 Google Inc. 5 | * Copyright 2016 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __MODULE_H 11 | #define __MODULE_H 12 | 13 | struct gb_module { 14 | struct device dev; 15 | struct gb_host_device *hd; 16 | 17 | struct list_head hd_node; 18 | 19 | u8 module_id; 20 | size_t num_interfaces; 21 | 22 | bool disconnected; 23 | 24 | struct gb_interface *interfaces[0]; 25 | }; 26 | #define to_gb_module(d) container_of(d, struct gb_module, dev) 27 | 28 | struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, 29 | size_t num_interfaces); 30 | int gb_module_add(struct gb_module *module); 31 | void gb_module_del(struct gb_module *module); 32 | void gb_module_put(struct gb_module *module); 33 | 34 | #endif /* __MODULE_H */ 35 | -------------------------------------------------------------------------------- /operation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus operations 3 | * 4 | * Copyright 2014 Google Inc. 5 | * Copyright 2014 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __OPERATION_H 11 | #define __OPERATION_H 12 | 13 | #include 14 | 15 | struct gb_operation; 16 | 17 | /* The default amount of time a request is given to complete */ 18 | #define GB_OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ 19 | 20 | /* 21 | * The top bit of the type in an operation message header indicates 22 | * whether the message is a request (bit clear) or response (bit set) 23 | */ 24 | #define GB_MESSAGE_TYPE_RESPONSE ((u8)0x80) 25 | 26 | enum gb_operation_result { 27 | GB_OP_SUCCESS = 0x00, 28 | GB_OP_INTERRUPTED = 0x01, 29 | GB_OP_TIMEOUT = 0x02, 30 | GB_OP_NO_MEMORY = 0x03, 31 | GB_OP_PROTOCOL_BAD = 0x04, 32 | GB_OP_OVERFLOW = 0x05, 33 | GB_OP_INVALID = 0x06, 34 | GB_OP_RETRY = 0x07, 35 | GB_OP_NONEXISTENT = 0x08, 36 | GB_OP_UNKNOWN_ERROR = 0xfe, 37 | GB_OP_MALFUNCTION = 0xff, 38 | }; 39 | 40 | #define GB_OPERATION_MESSAGE_SIZE_MIN sizeof(struct gb_operation_msg_hdr) 41 | #define GB_OPERATION_MESSAGE_SIZE_MAX U16_MAX 42 | 43 | /* 44 | * Protocol code should only examine the payload and payload_size fields, and 45 | * host-controller drivers may use the hcpriv field. All other fields are 46 | * intended to be private to the operations core code. 47 | */ 48 | struct gb_message { 49 | struct gb_operation *operation; 50 | struct gb_operation_msg_hdr *header; 51 | 52 | void *payload; 53 | size_t payload_size; 54 | 55 | void *buffer; 56 | 57 | void *hcpriv; 58 | }; 59 | 60 | #define GB_OPERATION_FLAG_INCOMING BIT(0) 61 | #define GB_OPERATION_FLAG_UNIDIRECTIONAL BIT(1) 62 | #define GB_OPERATION_FLAG_SHORT_RESPONSE BIT(2) 63 | #define GB_OPERATION_FLAG_CORE BIT(3) 64 | 65 | #define GB_OPERATION_FLAG_USER_MASK (GB_OPERATION_FLAG_SHORT_RESPONSE | \ 66 | GB_OPERATION_FLAG_UNIDIRECTIONAL) 67 | 68 | /* 69 | * A Greybus operation is a remote procedure call performed over a 70 | * connection between two UniPro interfaces. 71 | * 72 | * Every operation consists of a request message sent to the other 73 | * end of the connection coupled with a reply message returned to 74 | * the sender. Every operation has a type, whose interpretation is 75 | * dependent on the protocol associated with the connection. 76 | * 77 | * Only four things in an operation structure are intended to be 78 | * directly usable by protocol handlers: the operation's connection 79 | * pointer; the operation type; the request message payload (and 80 | * size); and the response message payload (and size). Note that a 81 | * message with a 0-byte payload has a null message payload pointer. 82 | * 83 | * In addition, every operation has a result, which is an errno 84 | * value. Protocol handlers access the operation result using 85 | * gb_operation_result(). 86 | */ 87 | typedef void (*gb_operation_callback)(struct gb_operation *); 88 | struct gb_operation { 89 | struct gb_connection *connection; 90 | struct gb_message *request; 91 | struct gb_message *response; 92 | 93 | unsigned long flags; 94 | u8 type; 95 | u16 id; 96 | int errno; /* Operation result */ 97 | 98 | struct work_struct work; 99 | gb_operation_callback callback; 100 | struct completion completion; 101 | 102 | struct kref kref; 103 | atomic_t waiters; 104 | 105 | int active; 106 | struct list_head links; /* connection->operations */ 107 | }; 108 | 109 | static inline bool 110 | gb_operation_is_incoming(struct gb_operation *operation) 111 | { 112 | return operation->flags & GB_OPERATION_FLAG_INCOMING; 113 | } 114 | 115 | static inline bool 116 | gb_operation_is_unidirectional(struct gb_operation *operation) 117 | { 118 | return operation->flags & GB_OPERATION_FLAG_UNIDIRECTIONAL; 119 | } 120 | 121 | static inline bool 122 | gb_operation_short_response_allowed(struct gb_operation *operation) 123 | { 124 | return operation->flags & GB_OPERATION_FLAG_SHORT_RESPONSE; 125 | } 126 | 127 | static inline bool gb_operation_is_core(struct gb_operation *operation) 128 | { 129 | return operation->flags & GB_OPERATION_FLAG_CORE; 130 | } 131 | 132 | void gb_connection_recv(struct gb_connection *connection, 133 | void *data, size_t size); 134 | 135 | int gb_operation_result(struct gb_operation *operation); 136 | 137 | size_t gb_operation_get_payload_size_max(struct gb_connection *connection); 138 | struct gb_operation * 139 | gb_operation_create_flags(struct gb_connection *connection, 140 | u8 type, size_t request_size, 141 | size_t response_size, unsigned long flags, 142 | gfp_t gfp); 143 | 144 | static inline struct gb_operation * 145 | gb_operation_create(struct gb_connection *connection, 146 | u8 type, size_t request_size, 147 | size_t response_size, gfp_t gfp) 148 | { 149 | return gb_operation_create_flags(connection, type, request_size, 150 | response_size, 0, gfp); 151 | } 152 | 153 | struct gb_operation * 154 | gb_operation_create_core(struct gb_connection *connection, 155 | u8 type, size_t request_size, 156 | size_t response_size, unsigned long flags, 157 | gfp_t gfp); 158 | 159 | void gb_operation_get(struct gb_operation *operation); 160 | void gb_operation_put(struct gb_operation *operation); 161 | 162 | bool gb_operation_response_alloc(struct gb_operation *operation, 163 | size_t response_size, gfp_t gfp); 164 | 165 | int gb_operation_request_send(struct gb_operation *operation, 166 | gb_operation_callback callback, 167 | gfp_t gfp); 168 | int gb_operation_request_send_sync_timeout(struct gb_operation *operation, 169 | unsigned int timeout); 170 | static inline int 171 | gb_operation_request_send_sync(struct gb_operation *operation) 172 | { 173 | return gb_operation_request_send_sync_timeout(operation, 174 | GB_OPERATION_TIMEOUT_DEFAULT); 175 | } 176 | 177 | void gb_operation_cancel(struct gb_operation *operation, int errno); 178 | void gb_operation_cancel_incoming(struct gb_operation *operation, int errno); 179 | 180 | void greybus_message_sent(struct gb_host_device *hd, 181 | struct gb_message *message, int status); 182 | 183 | int gb_operation_sync_timeout(struct gb_connection *connection, int type, 184 | void *request, int request_size, 185 | void *response, int response_size, 186 | unsigned int timeout); 187 | int gb_operation_unidirectional_timeout(struct gb_connection *connection, 188 | int type, void *request, int request_size, 189 | unsigned int timeout); 190 | 191 | static inline int gb_operation_sync(struct gb_connection *connection, int type, 192 | void *request, int request_size, 193 | void *response, int response_size) 194 | { 195 | return gb_operation_sync_timeout(connection, type, 196 | request, request_size, response, response_size, 197 | GB_OPERATION_TIMEOUT_DEFAULT); 198 | } 199 | 200 | static inline int gb_operation_unidirectional(struct gb_connection *connection, 201 | int type, void *request, int request_size) 202 | { 203 | return gb_operation_unidirectional_timeout(connection, type, 204 | request, request_size, GB_OPERATION_TIMEOUT_DEFAULT); 205 | } 206 | 207 | int gb_operation_init(void); 208 | void gb_operation_exit(void); 209 | 210 | #endif /* !__OPERATION_H */ 211 | -------------------------------------------------------------------------------- /pwm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PWM Greybus driver. 3 | * 4 | * Copyright 2014 Google Inc. 5 | * Copyright 2014 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "greybus.h" 16 | #include "gbphy.h" 17 | 18 | struct gb_pwm_chip { 19 | struct gb_connection *connection; 20 | u8 pwm_max; /* max pwm number */ 21 | 22 | struct pwm_chip chip; 23 | struct pwm_chip *pwm; 24 | }; 25 | #define pwm_chip_to_gb_pwm_chip(chip) \ 26 | container_of(chip, struct gb_pwm_chip, chip) 27 | 28 | 29 | static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) 30 | { 31 | struct gb_pwm_count_response response; 32 | int ret; 33 | 34 | ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PWM_COUNT, 35 | NULL, 0, &response, sizeof(response)); 36 | if (ret) 37 | return ret; 38 | pwmc->pwm_max = response.count; 39 | return 0; 40 | } 41 | 42 | static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, 43 | u8 which) 44 | { 45 | struct gb_pwm_activate_request request; 46 | struct gbphy_device *gbphy_dev; 47 | int ret; 48 | 49 | if (which > pwmc->pwm_max) 50 | return -EINVAL; 51 | 52 | request.which = which; 53 | 54 | gbphy_dev = to_gbphy_dev(pwmc->chip.dev); 55 | ret = gbphy_runtime_get_sync(gbphy_dev); 56 | if (ret) 57 | return ret; 58 | 59 | ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ACTIVATE, 60 | &request, sizeof(request), NULL, 0); 61 | 62 | gbphy_runtime_put_autosuspend(gbphy_dev); 63 | 64 | return ret; 65 | } 66 | 67 | static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, 68 | u8 which) 69 | { 70 | struct gb_pwm_deactivate_request request; 71 | struct gbphy_device *gbphy_dev; 72 | int ret; 73 | 74 | if (which > pwmc->pwm_max) 75 | return -EINVAL; 76 | 77 | request.which = which; 78 | 79 | gbphy_dev = to_gbphy_dev(pwmc->chip.dev); 80 | ret = gbphy_runtime_get_sync(gbphy_dev); 81 | if (ret) 82 | return ret; 83 | 84 | ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DEACTIVATE, 85 | &request, sizeof(request), NULL, 0); 86 | 87 | gbphy_runtime_put_autosuspend(gbphy_dev); 88 | 89 | return ret; 90 | } 91 | 92 | static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, 93 | u8 which, u32 duty, u32 period) 94 | { 95 | struct gb_pwm_config_request request; 96 | struct gbphy_device *gbphy_dev; 97 | int ret; 98 | 99 | if (which > pwmc->pwm_max) 100 | return -EINVAL; 101 | 102 | request.which = which; 103 | request.duty = cpu_to_le32(duty); 104 | request.period = cpu_to_le32(period); 105 | 106 | gbphy_dev = to_gbphy_dev(pwmc->chip.dev); 107 | ret = gbphy_runtime_get_sync(gbphy_dev); 108 | if (ret) 109 | return ret; 110 | 111 | ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_CONFIG, 112 | &request, sizeof(request), NULL, 0); 113 | 114 | gbphy_runtime_put_autosuspend(gbphy_dev); 115 | 116 | return ret; 117 | } 118 | 119 | static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, 120 | u8 which, u8 polarity) 121 | { 122 | struct gb_pwm_polarity_request request; 123 | struct gbphy_device *gbphy_dev; 124 | int ret; 125 | 126 | if (which > pwmc->pwm_max) 127 | return -EINVAL; 128 | 129 | request.which = which; 130 | request.polarity = polarity; 131 | 132 | gbphy_dev = to_gbphy_dev(pwmc->chip.dev); 133 | ret = gbphy_runtime_get_sync(gbphy_dev); 134 | if (ret) 135 | return ret; 136 | 137 | ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_POLARITY, 138 | &request, sizeof(request), NULL, 0); 139 | 140 | gbphy_runtime_put_autosuspend(gbphy_dev); 141 | 142 | return ret; 143 | } 144 | 145 | static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, 146 | u8 which) 147 | { 148 | struct gb_pwm_enable_request request; 149 | struct gbphy_device *gbphy_dev; 150 | int ret; 151 | 152 | if (which > pwmc->pwm_max) 153 | return -EINVAL; 154 | 155 | request.which = which; 156 | 157 | gbphy_dev = to_gbphy_dev(pwmc->chip.dev); 158 | ret = gbphy_runtime_get_sync(gbphy_dev); 159 | if (ret) 160 | return ret; 161 | 162 | ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ENABLE, 163 | &request, sizeof(request), NULL, 0); 164 | if (ret) 165 | gbphy_runtime_put_autosuspend(gbphy_dev); 166 | 167 | return ret; 168 | } 169 | 170 | static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, 171 | u8 which) 172 | { 173 | struct gb_pwm_disable_request request; 174 | struct gbphy_device *gbphy_dev; 175 | int ret; 176 | 177 | if (which > pwmc->pwm_max) 178 | return -EINVAL; 179 | 180 | request.which = which; 181 | 182 | ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DISABLE, 183 | &request, sizeof(request), NULL, 0); 184 | 185 | gbphy_dev = to_gbphy_dev(pwmc->chip.dev); 186 | gbphy_runtime_put_autosuspend(gbphy_dev); 187 | 188 | return ret; 189 | } 190 | 191 | static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) 192 | { 193 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); 194 | 195 | return gb_pwm_activate_operation(pwmc, pwm->hwpwm); 196 | }; 197 | 198 | static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) 199 | { 200 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); 201 | 202 | if (pwm_is_enabled(pwm)) 203 | dev_warn(chip->dev, "freeing PWM device without disabling\n"); 204 | 205 | gb_pwm_deactivate_operation(pwmc, pwm->hwpwm); 206 | } 207 | 208 | static int gb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 209 | int duty_ns, int period_ns) 210 | { 211 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); 212 | 213 | return gb_pwm_config_operation(pwmc, pwm->hwpwm, duty_ns, period_ns); 214 | }; 215 | 216 | static int gb_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, 217 | enum pwm_polarity polarity) 218 | { 219 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); 220 | 221 | return gb_pwm_set_polarity_operation(pwmc, pwm->hwpwm, polarity); 222 | }; 223 | 224 | static int gb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 225 | { 226 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); 227 | 228 | return gb_pwm_enable_operation(pwmc, pwm->hwpwm); 229 | }; 230 | 231 | static void gb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 232 | { 233 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); 234 | 235 | gb_pwm_disable_operation(pwmc, pwm->hwpwm); 236 | }; 237 | 238 | static const struct pwm_ops gb_pwm_ops = { 239 | .request = gb_pwm_request, 240 | .free = gb_pwm_free, 241 | .config = gb_pwm_config, 242 | .set_polarity = gb_pwm_set_polarity, 243 | .enable = gb_pwm_enable, 244 | .disable = gb_pwm_disable, 245 | .owner = THIS_MODULE, 246 | }; 247 | 248 | static int gb_pwm_probe(struct gbphy_device *gbphy_dev, 249 | const struct gbphy_device_id *id) 250 | { 251 | struct gb_connection *connection; 252 | struct gb_pwm_chip *pwmc; 253 | struct pwm_chip *pwm; 254 | int ret; 255 | 256 | pwmc = kzalloc(sizeof(*pwmc), GFP_KERNEL); 257 | if (!pwmc) 258 | return -ENOMEM; 259 | 260 | connection = gb_connection_create(gbphy_dev->bundle, 261 | le16_to_cpu(gbphy_dev->cport_desc->id), 262 | NULL); 263 | if (IS_ERR(connection)) { 264 | ret = PTR_ERR(connection); 265 | goto exit_pwmc_free; 266 | } 267 | 268 | pwmc->connection = connection; 269 | gb_connection_set_data(connection, pwmc); 270 | gb_gbphy_set_data(gbphy_dev, pwmc); 271 | 272 | ret = gb_connection_enable(connection); 273 | if (ret) 274 | goto exit_connection_destroy; 275 | 276 | /* Query number of pwms present */ 277 | ret = gb_pwm_count_operation(pwmc); 278 | if (ret) 279 | goto exit_connection_disable; 280 | 281 | pwm = &pwmc->chip; 282 | 283 | pwm->dev = &gbphy_dev->dev; 284 | pwm->ops = &gb_pwm_ops; 285 | pwm->base = -1; /* Allocate base dynamically */ 286 | pwm->npwm = pwmc->pwm_max + 1; 287 | pwm->can_sleep = true; /* FIXME */ 288 | 289 | ret = pwmchip_add(pwm); 290 | if (ret) { 291 | dev_err(&gbphy_dev->dev, 292 | "failed to register PWM: %d\n", ret); 293 | goto exit_connection_disable; 294 | } 295 | 296 | gbphy_runtime_put_autosuspend(gbphy_dev); 297 | return 0; 298 | 299 | exit_connection_disable: 300 | gb_connection_disable(connection); 301 | exit_connection_destroy: 302 | gb_connection_destroy(connection); 303 | exit_pwmc_free: 304 | kfree(pwmc); 305 | return ret; 306 | } 307 | 308 | static void gb_pwm_remove(struct gbphy_device *gbphy_dev) 309 | { 310 | struct gb_pwm_chip *pwmc = gb_gbphy_get_data(gbphy_dev); 311 | struct gb_connection *connection = pwmc->connection; 312 | int ret; 313 | 314 | ret = gbphy_runtime_get_sync(gbphy_dev); 315 | if (ret) 316 | gbphy_runtime_get_noresume(gbphy_dev); 317 | 318 | pwmchip_remove(&pwmc->chip); 319 | gb_connection_disable(connection); 320 | gb_connection_destroy(connection); 321 | kfree(pwmc); 322 | } 323 | 324 | static const struct gbphy_device_id gb_pwm_id_table[] = { 325 | { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_PWM) }, 326 | { }, 327 | }; 328 | MODULE_DEVICE_TABLE(gbphy, gb_pwm_id_table); 329 | 330 | static struct gbphy_driver pwm_driver = { 331 | .name = "pwm", 332 | .probe = gb_pwm_probe, 333 | .remove = gb_pwm_remove, 334 | .id_table = gb_pwm_id_table, 335 | }; 336 | 337 | module_gbphy_driver(pwm_driver); 338 | MODULE_LICENSE("GPL v2"); 339 | -------------------------------------------------------------------------------- /spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPI bridge PHY driver. 3 | * 4 | * Copyright 2014-2016 Google Inc. 5 | * Copyright 2014-2016 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #include 11 | 12 | #include "greybus.h" 13 | #include "gbphy.h" 14 | #include "spilib.h" 15 | 16 | #ifndef SPI_CORE_SUPPORT_PM 17 | static int gbphy_spi_prepare_transfer_hardware(struct device *dev) 18 | { 19 | return gbphy_runtime_get_sync(to_gbphy_dev(dev)); 20 | } 21 | 22 | static void gbphy_spi_unprepare_transfer_hardware(struct device *dev) 23 | { 24 | gbphy_runtime_put_autosuspend(to_gbphy_dev(dev)); 25 | } 26 | 27 | static struct spilib_ops __spilib_ops = { 28 | .prepare_transfer_hardware = gbphy_spi_prepare_transfer_hardware, 29 | .unprepare_transfer_hardware = gbphy_spi_unprepare_transfer_hardware, 30 | }; 31 | 32 | static struct spilib_ops *spilib_ops = &__spilib_ops; 33 | #else 34 | static struct spilib_ops *spilib_ops = NULL; 35 | #endif 36 | 37 | static int gb_spi_probe(struct gbphy_device *gbphy_dev, 38 | const struct gbphy_device_id *id) 39 | { 40 | struct gb_connection *connection; 41 | int ret; 42 | 43 | connection = gb_connection_create(gbphy_dev->bundle, 44 | le16_to_cpu(gbphy_dev->cport_desc->id), 45 | NULL); 46 | if (IS_ERR(connection)) 47 | return PTR_ERR(connection); 48 | 49 | ret = gb_connection_enable(connection); 50 | if (ret) 51 | goto exit_connection_destroy; 52 | 53 | ret = gb_spilib_master_init(connection, &gbphy_dev->dev, spilib_ops); 54 | if (ret) 55 | goto exit_connection_disable; 56 | 57 | gb_gbphy_set_data(gbphy_dev, connection); 58 | 59 | gbphy_runtime_put_autosuspend(gbphy_dev); 60 | return 0; 61 | 62 | exit_connection_disable: 63 | gb_connection_disable(connection); 64 | exit_connection_destroy: 65 | gb_connection_destroy(connection); 66 | 67 | return ret; 68 | } 69 | 70 | static void gb_spi_remove(struct gbphy_device *gbphy_dev) 71 | { 72 | struct gb_connection *connection = gb_gbphy_get_data(gbphy_dev); 73 | int ret; 74 | 75 | ret = gbphy_runtime_get_sync(gbphy_dev); 76 | if (ret) 77 | gbphy_runtime_get_noresume(gbphy_dev); 78 | 79 | gb_spilib_master_exit(connection); 80 | gb_connection_disable(connection); 81 | gb_connection_destroy(connection); 82 | } 83 | 84 | static const struct gbphy_device_id gb_spi_id_table[] = { 85 | { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_SPI) }, 86 | { }, 87 | }; 88 | MODULE_DEVICE_TABLE(gbphy, gb_spi_id_table); 89 | 90 | static struct gbphy_driver spi_driver = { 91 | .name = "spi", 92 | .probe = gb_spi_probe, 93 | .remove = gb_spi_remove, 94 | .id_table = gb_spi_id_table, 95 | }; 96 | 97 | module_gbphy_driver(spi_driver); 98 | MODULE_LICENSE("GPL v2"); 99 | -------------------------------------------------------------------------------- /spilib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus SPI library header 3 | * 4 | * copyright 2016 google inc. 5 | * copyright 2016 linaro ltd. 6 | * 7 | * released under the gplv2 only. 8 | */ 9 | 10 | #ifndef __SPILIB_H 11 | #define __SPILIB_H 12 | 13 | struct device; 14 | struct gb_connection; 15 | 16 | struct spilib_ops { 17 | int (*prepare_transfer_hardware)(struct device *dev); 18 | void (*unprepare_transfer_hardware)(struct device *dev); 19 | }; 20 | 21 | int gb_spilib_master_init(struct gb_connection *connection, struct device *dev, struct spilib_ops *ops); 22 | void gb_spilib_master_exit(struct gb_connection *connection); 23 | 24 | #endif /* __SPILIB_H */ 25 | -------------------------------------------------------------------------------- /svc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus SVC code 3 | * 4 | * Copyright 2015 Google Inc. 5 | * Copyright 2015 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __SVC_H 11 | #define __SVC_H 12 | 13 | #define GB_SVC_CPORT_FLAG_E2EFC BIT(0) 14 | #define GB_SVC_CPORT_FLAG_CSD_N BIT(1) 15 | #define GB_SVC_CPORT_FLAG_CSV_N BIT(2) 16 | 17 | enum gb_svc_state { 18 | GB_SVC_STATE_RESET, 19 | GB_SVC_STATE_PROTOCOL_VERSION, 20 | GB_SVC_STATE_SVC_HELLO, 21 | }; 22 | 23 | enum gb_svc_watchdog_bite { 24 | GB_SVC_WATCHDOG_BITE_RESET_UNIPRO = 0, 25 | GB_SVC_WATCHDOG_BITE_PANIC_KERNEL, 26 | }; 27 | 28 | struct gb_svc_watchdog; 29 | 30 | struct svc_debugfs_pwrmon_rail { 31 | u8 id; 32 | struct gb_svc *svc; 33 | }; 34 | 35 | struct gb_svc { 36 | struct device dev; 37 | 38 | struct gb_host_device *hd; 39 | struct gb_connection *connection; 40 | enum gb_svc_state state; 41 | struct ida device_id_map; 42 | struct workqueue_struct *wq; 43 | 44 | u16 endo_id; 45 | u8 ap_intf_id; 46 | 47 | u8 protocol_major; 48 | u8 protocol_minor; 49 | 50 | struct gb_svc_watchdog *watchdog; 51 | enum gb_svc_watchdog_bite action; 52 | 53 | struct dentry *debugfs_dentry; 54 | struct svc_debugfs_pwrmon_rail *pwrmon_rails; 55 | }; 56 | #define to_gb_svc(d) container_of(d, struct gb_svc, dev) 57 | 58 | struct gb_svc *gb_svc_create(struct gb_host_device *hd); 59 | int gb_svc_add(struct gb_svc *svc); 60 | void gb_svc_del(struct gb_svc *svc); 61 | void gb_svc_put(struct gb_svc *svc); 62 | 63 | int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, 64 | u8 measurement_type, u32 *value); 65 | int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id); 66 | int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, 67 | u8 intf2_id, u8 dev2_id); 68 | void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id); 69 | int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, 70 | u8 intf2_id, u16 cport2_id, u8 cport_flags); 71 | void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, 72 | u8 intf2_id, u16 cport2_id); 73 | int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id); 74 | int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable); 75 | int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable); 76 | int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable); 77 | int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type); 78 | int gb_svc_intf_resume(struct gb_svc *svc, u8 intf_id); 79 | 80 | int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, 81 | u32 *value); 82 | int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, 83 | u32 value); 84 | int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, 85 | u8 tx_mode, u8 tx_gear, u8 tx_nlanes, 86 | u8 tx_amplitude, u8 tx_hs_equalizer, 87 | u8 rx_mode, u8 rx_gear, u8 rx_nlanes, 88 | u8 flags, u32 quirks, 89 | struct gb_svc_l2_timer_cfg *local, 90 | struct gb_svc_l2_timer_cfg *remote); 91 | int gb_svc_intf_set_power_mode_hibernate(struct gb_svc *svc, u8 intf_id); 92 | int gb_svc_ping(struct gb_svc *svc); 93 | int gb_svc_watchdog_create(struct gb_svc *svc); 94 | void gb_svc_watchdog_destroy(struct gb_svc *svc); 95 | bool gb_svc_watchdog_enabled(struct gb_svc *svc); 96 | int gb_svc_watchdog_enable(struct gb_svc *svc); 97 | int gb_svc_watchdog_disable(struct gb_svc *svc); 98 | int gb_svc_timesync_enable(struct gb_svc *svc, u8 count, u64 frame_time, 99 | u32 strobe_delay, u32 refclk); 100 | int gb_svc_timesync_disable(struct gb_svc *svc); 101 | int gb_svc_timesync_authoritative(struct gb_svc *svc, u64 *frame_time); 102 | int gb_svc_timesync_ping(struct gb_svc *svc, u64 *frame_time); 103 | int gb_svc_timesync_wake_pins_acquire(struct gb_svc *svc, u32 strobe_mask); 104 | int gb_svc_timesync_wake_pins_release(struct gb_svc *svc); 105 | 106 | int gb_svc_protocol_init(void); 107 | void gb_svc_protocol_exit(void); 108 | 109 | #endif /* __SVC_H */ 110 | -------------------------------------------------------------------------------- /svc_watchdog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SVC Greybus "watchdog" driver. 3 | * 4 | * Copyright 2016 Google Inc. 5 | * 6 | * Released under the GPLv2 only. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "greybus.h" 13 | 14 | #define SVC_WATCHDOG_PERIOD (2*HZ) 15 | 16 | struct gb_svc_watchdog { 17 | struct delayed_work work; 18 | struct gb_svc *svc; 19 | bool enabled; 20 | struct notifier_block pm_notifier; 21 | }; 22 | 23 | static struct delayed_work reset_work; 24 | 25 | static int svc_watchdog_pm_notifier(struct notifier_block *notifier, 26 | unsigned long pm_event, void *unused) 27 | { 28 | struct gb_svc_watchdog *watchdog = 29 | container_of(notifier, struct gb_svc_watchdog, pm_notifier); 30 | 31 | switch (pm_event) { 32 | case PM_SUSPEND_PREPARE: 33 | gb_svc_watchdog_disable(watchdog->svc); 34 | break; 35 | case PM_POST_SUSPEND: 36 | gb_svc_watchdog_enable(watchdog->svc); 37 | break; 38 | default: 39 | break; 40 | } 41 | 42 | return NOTIFY_DONE; 43 | } 44 | 45 | static void greybus_reset(struct work_struct *work) 46 | { 47 | static char start_path[256] = "/system/bin/start"; 48 | static char *envp[] = { 49 | "HOME=/", 50 | "PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin", 51 | NULL, 52 | }; 53 | static char *argv[] = { 54 | start_path, 55 | "unipro_reset", 56 | NULL, 57 | }; 58 | 59 | printk(KERN_ERR "svc_watchdog: calling \"%s %s\" to reset greybus network!\n", 60 | argv[0], argv[1]); 61 | call_usermodehelper(start_path, argv, envp, UMH_WAIT_EXEC); 62 | } 63 | 64 | static void do_work(struct work_struct *work) 65 | { 66 | struct gb_svc_watchdog *watchdog; 67 | struct gb_svc *svc; 68 | int retval; 69 | 70 | watchdog = container_of(work, struct gb_svc_watchdog, work.work); 71 | svc = watchdog->svc; 72 | 73 | dev_dbg(&svc->dev, "%s: ping.\n", __func__); 74 | retval = gb_svc_ping(svc); 75 | if (retval) { 76 | /* 77 | * Something went really wrong, let's warn userspace and then 78 | * pull the plug and reset the whole greybus network. 79 | * We need to do this outside of this workqueue as we will be 80 | * tearing down the svc device itself. So queue up 81 | * yet-another-callback to do that. 82 | */ 83 | dev_err(&svc->dev, 84 | "SVC ping has returned %d, something is wrong!!!\n", 85 | retval); 86 | 87 | if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) { 88 | panic("SVC is not responding\n"); 89 | } else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO) { 90 | dev_err(&svc->dev, "Resetting the greybus network, watch out!!!\n"); 91 | 92 | INIT_DELAYED_WORK(&reset_work, greybus_reset); 93 | schedule_delayed_work(&reset_work, HZ / 2); 94 | 95 | /* 96 | * Disable ourselves, we don't want to trip again unless 97 | * userspace wants us to. 98 | */ 99 | watchdog->enabled = false; 100 | } 101 | } 102 | 103 | /* resubmit our work to happen again, if we are still "alive" */ 104 | if (watchdog->enabled) 105 | schedule_delayed_work(&watchdog->work, SVC_WATCHDOG_PERIOD); 106 | } 107 | 108 | int gb_svc_watchdog_create(struct gb_svc *svc) 109 | { 110 | struct gb_svc_watchdog *watchdog; 111 | int retval; 112 | 113 | if (svc->watchdog) 114 | return 0; 115 | 116 | watchdog = kmalloc(sizeof(*watchdog), GFP_KERNEL); 117 | if (!watchdog) 118 | return -ENOMEM; 119 | 120 | watchdog->enabled = false; 121 | watchdog->svc = svc; 122 | INIT_DELAYED_WORK(&watchdog->work, do_work); 123 | svc->watchdog = watchdog; 124 | 125 | watchdog->pm_notifier.notifier_call = svc_watchdog_pm_notifier; 126 | retval = register_pm_notifier(&watchdog->pm_notifier); 127 | if (retval) { 128 | dev_err(&svc->dev, "error registering pm notifier(%d)\n", 129 | retval); 130 | goto svc_watchdog_create_err; 131 | } 132 | 133 | retval = gb_svc_watchdog_enable(svc); 134 | if (retval) { 135 | dev_err(&svc->dev, "error enabling watchdog (%d)\n", retval); 136 | unregister_pm_notifier(&watchdog->pm_notifier); 137 | goto svc_watchdog_create_err; 138 | } 139 | return retval; 140 | 141 | svc_watchdog_create_err: 142 | svc->watchdog = NULL; 143 | kfree(watchdog); 144 | 145 | return retval; 146 | } 147 | 148 | void gb_svc_watchdog_destroy(struct gb_svc *svc) 149 | { 150 | struct gb_svc_watchdog *watchdog = svc->watchdog; 151 | 152 | if (!watchdog) 153 | return; 154 | 155 | unregister_pm_notifier(&watchdog->pm_notifier); 156 | gb_svc_watchdog_disable(svc); 157 | svc->watchdog = NULL; 158 | kfree(watchdog); 159 | } 160 | 161 | bool gb_svc_watchdog_enabled(struct gb_svc *svc) 162 | { 163 | if (!svc || !svc->watchdog) 164 | return false; 165 | return svc->watchdog->enabled; 166 | } 167 | 168 | int gb_svc_watchdog_enable(struct gb_svc *svc) 169 | { 170 | struct gb_svc_watchdog *watchdog; 171 | 172 | if (!svc->watchdog) 173 | return -ENODEV; 174 | 175 | watchdog = svc->watchdog; 176 | if (watchdog->enabled) 177 | return 0; 178 | 179 | watchdog->enabled = true; 180 | schedule_delayed_work(&watchdog->work, SVC_WATCHDOG_PERIOD); 181 | return 0; 182 | } 183 | 184 | int gb_svc_watchdog_disable(struct gb_svc *svc) 185 | { 186 | struct gb_svc_watchdog *watchdog; 187 | 188 | if (!svc->watchdog) 189 | return -ENODEV; 190 | 191 | watchdog = svc->watchdog; 192 | if (!watchdog->enabled) 193 | return 0; 194 | 195 | watchdog->enabled = false; 196 | cancel_delayed_work_sync(&watchdog->work); 197 | return 0; 198 | } 199 | -------------------------------------------------------------------------------- /timesync.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TimeSync API driver. 3 | * 4 | * Copyright 2016 Google Inc. 5 | * Copyright 2016 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #ifndef __TIMESYNC_H 11 | #define __TIMESYNC_H 12 | 13 | struct gb_svc; 14 | struct gb_interface; 15 | struct gb_timesync_svc; 16 | 17 | /* Platform */ 18 | u64 gb_timesync_platform_get_counter(void); 19 | u32 gb_timesync_platform_get_clock_rate(void); 20 | int gb_timesync_platform_lock_bus(struct gb_timesync_svc *pdata); 21 | void gb_timesync_platform_unlock_bus(void); 22 | 23 | int gb_timesync_platform_init(void); 24 | void gb_timesync_platform_exit(void); 25 | 26 | /* Core API */ 27 | int gb_timesync_interface_add(struct gb_interface *interface); 28 | void gb_timesync_interface_remove(struct gb_interface *interface); 29 | int gb_timesync_svc_add(struct gb_svc *svc); 30 | void gb_timesync_svc_remove(struct gb_svc *svc); 31 | 32 | u64 gb_timesync_get_frame_time_by_interface(struct gb_interface *interface); 33 | u64 gb_timesync_get_frame_time_by_svc(struct gb_svc *svc); 34 | int gb_timesync_to_timespec_by_svc(struct gb_svc *svc, u64 frame_time, 35 | struct timespec *ts); 36 | int gb_timesync_to_timespec_by_interface(struct gb_interface *interface, 37 | u64 frame_time, struct timespec *ts); 38 | 39 | int gb_timesync_schedule_synchronous(struct gb_interface *intf); 40 | void gb_timesync_schedule_asynchronous(struct gb_interface *intf); 41 | void gb_timesync_irq(struct gb_timesync_svc *timesync_svc); 42 | int gb_timesync_init(void); 43 | void gb_timesync_exit(void); 44 | 45 | #endif /* __TIMESYNC_H */ 46 | -------------------------------------------------------------------------------- /timesync_platform.c: -------------------------------------------------------------------------------- 1 | /* 2 | * TimeSync API driver. 3 | * 4 | * Copyright 2016 Google Inc. 5 | * Copyright 2016 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | * 9 | * This code reads directly from an ARMv7 memory-mapped timer that lives in 10 | * MMIO space. Since this counter lives inside of MMIO space its shared between 11 | * cores and that means we don't have to worry about issues like TSC on x86 12 | * where each time-stamp-counter (TSC) is local to a particular core. 13 | * 14 | * Register-level access code is based on 15 | * drivers/clocksource/arm_arch_timer.c 16 | */ 17 | #include 18 | #include 19 | 20 | #include "greybus.h" 21 | #include "arche_platform.h" 22 | 23 | static u32 gb_timesync_clock_frequency; 24 | int (*arche_platform_change_state_cb)(enum arche_platform_state state, 25 | struct gb_timesync_svc *pdata); 26 | EXPORT_SYMBOL_GPL(arche_platform_change_state_cb); 27 | 28 | u64 gb_timesync_platform_get_counter(void) 29 | { 30 | return (u64)get_cycles(); 31 | } 32 | 33 | u32 gb_timesync_platform_get_clock_rate(void) 34 | { 35 | if (unlikely(!gb_timesync_clock_frequency)) 36 | return cpufreq_get(0); 37 | 38 | return gb_timesync_clock_frequency; 39 | } 40 | 41 | int gb_timesync_platform_lock_bus(struct gb_timesync_svc *pdata) 42 | { 43 | return arche_platform_change_state_cb(ARCHE_PLATFORM_STATE_TIME_SYNC, 44 | pdata); 45 | } 46 | 47 | void gb_timesync_platform_unlock_bus(void) 48 | { 49 | arche_platform_change_state_cb(ARCHE_PLATFORM_STATE_ACTIVE, NULL); 50 | } 51 | 52 | static const struct of_device_id arch_timer_of_match[] = { 53 | { .compatible = "google,greybus-frame-time-counter", }, 54 | {}, 55 | }; 56 | 57 | int __init gb_timesync_platform_init(void) 58 | { 59 | struct device_node *np; 60 | 61 | np = of_find_matching_node(NULL, arch_timer_of_match); 62 | if (!np) { 63 | /* Tolerate not finding to allow BBB etc to continue */ 64 | pr_warn("Unable to find a compatible ARMv7 timer\n"); 65 | return 0; 66 | } 67 | 68 | if (of_property_read_u32(np, "clock-frequency", 69 | &gb_timesync_clock_frequency)) { 70 | pr_err("Unable to find timer clock-frequency\n"); 71 | return -ENODEV; 72 | } 73 | 74 | return 0; 75 | } 76 | 77 | void gb_timesync_platform_exit(void) {} 78 | -------------------------------------------------------------------------------- /tools/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_SRC_FILES:= loopback_test.c 6 | LOCAL_MODULE_TAGS := optional 7 | LOCAL_MODULE := gb_loopback_test 8 | 9 | include $(BUILD_EXECUTABLE) 10 | 11 | -------------------------------------------------------------------------------- /tools/Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(strip $(V)), 1) 2 | Q = 3 | else 4 | Q = @ 5 | endif 6 | 7 | CFLAGS += -std=gnu99 -Wall -Wextra -g \ 8 | -D_GNU_SOURCE \ 9 | -Wno-unused-parameter \ 10 | -Wmaybe-uninitialized \ 11 | -Wredundant-decls \ 12 | -Wcast-align \ 13 | -Wsign-compare \ 14 | -Wno-missing-field-initializers 15 | 16 | CC := $(CROSS_COMPILE)gcc 17 | 18 | TOOLS = loopback_test 19 | 20 | all: $(TOOLS) 21 | 22 | %.o: %.c ../greybus_protocols.h 23 | @echo ' TARGET_CC $@' 24 | $(Q)$(CC) $(CFLAGS) -c $< -o $@ 25 | 26 | loopback_%: loopback_%.o 27 | @echo ' TARGET_LD $@' 28 | $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ 29 | 30 | clean:: 31 | rm -f *.o $(TOOLS) 32 | -------------------------------------------------------------------------------- /tools/lbtest: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2015 Google, Inc. 4 | # Copyright (c) 2015 Linaro, Ltd. 5 | # All rights reserved. 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 1. Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # 2. Redistributions in binary form must reproduce the above copyright notice, 12 | # this list of conditions and the following disclaimer in the documentation 13 | # and/or other materials provided with the distribution. 14 | # 3. Neither the name of the copyright holder nor the names of its 15 | # contributors may be used to endorse or promote products derived from this 16 | # software without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 20 | # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 22 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | from __future__ import print_function 31 | import csv 32 | import datetime 33 | import sys 34 | import time 35 | 36 | dict = {'ping': '2', 'transfer': '3', 'sink': '4'} 37 | verbose = 1 38 | 39 | def abort(): 40 | sys.exit(1) 41 | 42 | def usage(): 43 | print('Usage: looptest TEST SIZE ITERATIONS PATH\n\n' 44 | ' Run TEST for a number of ITERATIONS with operation data SIZE bytes\n' 45 | ' TEST may be \'ping\' \'transfer\' or \'sink\'\n' 46 | ' SIZE indicates the size of transfer <= greybus max payload bytes\n' 47 | ' ITERATIONS indicates the number of times to execute TEST at SIZE bytes\n' 48 | ' Note if ITERATIONS is set to zero then this utility will\n' 49 | ' initiate an infinite (non terminating) test and exit\n' 50 | ' without logging any metrics data\n' 51 | ' PATH indicates the sysfs path for the loopback greybus entries e.g.\n' 52 | ' /sys/bus/greybus/devices/endo0:1:1:1:1/\n' 53 | 'Examples:\n' 54 | ' looptest transfer 128 10000\n' 55 | ' looptest ping 0 128\n' 56 | ' looptest sink 2030 32768\n' 57 | .format(sys.argv[0]), file=sys.stderr) 58 | 59 | abort() 60 | 61 | def read_sysfs_int(path): 62 | try: 63 | f = open(path, "r"); 64 | val = f.read(); 65 | f.close() 66 | return int(val) 67 | except IOError as e: 68 | print("I/O error({0}): {1}".format(e.errno, e.strerror)) 69 | print("Invalid path %s" % path) 70 | 71 | def write_sysfs_val(path, val): 72 | try: 73 | f = open(path, "r+") 74 | f.write(val) 75 | f.close() 76 | except IOError as e: 77 | print("I/O error({0}): {1}".format(e.errno, e.strerror)) 78 | print("Invalid path %s" % path) 79 | 80 | def log_csv(test_name, size, iteration_max, sys_pfx): 81 | # file name will test_name_size_iteration_max.csv 82 | # every time the same test with the same parameters is run we will then 83 | # append to the same CSV with datestamp - representing each test dataset 84 | fname = test_name + '_' + size + '_' + str(iteration_max) + '.csv' 85 | 86 | try: 87 | # gather data set 88 | date = str(datetime.datetime.now()) 89 | error = read_sysfs_int(sys_pfx + 'error') 90 | request_min = read_sysfs_int(sys_pfx + 'requests_per_second_min') 91 | request_max = read_sysfs_int(sys_pfx + 'requests_per_second_max') 92 | request_avg = read_sysfs_int(sys_pfx + 'requests_per_second_avg') 93 | latency_min = read_sysfs_int(sys_pfx + 'latency_min') 94 | latency_max = read_sysfs_int(sys_pfx + 'latency_max') 95 | latency_avg = read_sysfs_int(sys_pfx + 'latency_avg') 96 | throughput_min = read_sysfs_int(sys_pfx + 'throughput_min') 97 | throughput_max = read_sysfs_int(sys_pfx + 'throughput_max') 98 | throughput_avg = read_sysfs_int(sys_pfx + 'throughput_avg') 99 | 100 | # derive jitter 101 | request_jitter = request_max - request_min 102 | latency_jitter = latency_max - latency_min 103 | throughput_jitter = throughput_max - throughput_min 104 | 105 | # append data set to file 106 | with open(fname, 'a') as csvf: 107 | row = csv.writer(csvf, delimiter=",", quotechar="'", 108 | quoting=csv.QUOTE_MINIMAL) 109 | row.writerow([date, test_name, size, iteration_max, error, 110 | request_min, request_max, request_avg, request_jitter, 111 | latency_min, latency_max, latency_avg, latency_jitter, 112 | throughput_min, throughput_max, throughput_avg, throughput_jitter]) 113 | except IOError as e: 114 | print("I/O error({0}): {1}".format(e.errno, e.strerror)) 115 | 116 | def loopback_run(test_name, size, iteration_max, sys_pfx): 117 | test_id = dict[test_name] 118 | try: 119 | # Terminate any currently running test 120 | write_sysfs_val(sys_pfx + 'type', '0') 121 | # Set parameter for no wait between messages 122 | write_sysfs_val(sys_pfx + 'ms_wait', '0') 123 | # Set operation size 124 | write_sysfs_val(sys_pfx + 'size', size) 125 | # Set iterations 126 | write_sysfs_val(sys_pfx + 'iteration_max', str(iteration_max)) 127 | # Initiate by setting loopback operation type 128 | write_sysfs_val(sys_pfx + 'type', test_id) 129 | time.sleep(1) 130 | 131 | if iteration_max == 0: 132 | print ("Infinite test initiated CSV won't be logged\n") 133 | return 134 | 135 | previous = 0 136 | err = 0 137 | while True: 138 | # get current count bail out if it hasn't changed 139 | iteration_count = read_sysfs_int(sys_pfx + 'iteration_count') 140 | if previous == iteration_count: 141 | err = 1 142 | break 143 | elif iteration_count == iteration_max: 144 | break 145 | previous = iteration_count 146 | if verbose: 147 | print('%02d%% complete %d of %d ' % 148 | (100 * iteration_count / iteration_max, 149 | iteration_count, iteration_max)) 150 | time.sleep(1) 151 | if err: 152 | print ('\nError executing test\n') 153 | else: 154 | log_csv(test_name, size, iteration_max, sys_pfx) 155 | except ValueError as ve: 156 | print("Error: %s " % format(e.strerror), file=sys.stderr) 157 | abort() 158 | 159 | def main(): 160 | if len(sys.argv) < 5: 161 | usage() 162 | 163 | if sys.argv[1] in dict.keys(): 164 | loopback_run(sys.argv[1], sys.argv[2], int(sys.argv[3]), sys.argv[4]) 165 | else: 166 | usage() 167 | if __name__ == '__main__': 168 | main() 169 | -------------------------------------------------------------------------------- /usb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * USB host driver for the Greybus "generic" USB module. 3 | * 4 | * Copyright 2014 Google Inc. 5 | * Copyright 2014 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | * 9 | */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "greybus.h" 17 | #include "gbphy.h" 18 | 19 | /* Greybus USB request types */ 20 | #define GB_USB_TYPE_HCD_START 0x02 21 | #define GB_USB_TYPE_HCD_STOP 0x03 22 | #define GB_USB_TYPE_HUB_CONTROL 0x04 23 | 24 | struct gb_usb_hub_control_request { 25 | __le16 typeReq; 26 | __le16 wValue; 27 | __le16 wIndex; 28 | __le16 wLength; 29 | }; 30 | 31 | struct gb_usb_hub_control_response { 32 | u8 buf[0]; 33 | }; 34 | 35 | struct gb_usb_device { 36 | struct gb_connection *connection; 37 | struct gbphy_device *gbphy_dev; 38 | }; 39 | 40 | static inline struct gb_usb_device *to_gb_usb_device(struct usb_hcd *hcd) 41 | { 42 | return (struct gb_usb_device *)hcd->hcd_priv; 43 | } 44 | 45 | static inline struct usb_hcd *gb_usb_device_to_hcd(struct gb_usb_device *dev) 46 | { 47 | return container_of((void *)dev, struct usb_hcd, hcd_priv); 48 | } 49 | 50 | static void hcd_stop(struct usb_hcd *hcd) 51 | { 52 | struct gb_usb_device *dev = to_gb_usb_device(hcd); 53 | int ret; 54 | 55 | ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_STOP, 56 | NULL, 0, NULL, 0); 57 | if (ret) 58 | dev_err(&dev->gbphy_dev->dev, "HCD stop failed '%d'\n", ret); 59 | } 60 | 61 | static int hcd_start(struct usb_hcd *hcd) 62 | { 63 | struct usb_bus *bus = hcd_to_bus(hcd); 64 | struct gb_usb_device *dev = to_gb_usb_device(hcd); 65 | int ret; 66 | 67 | ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_START, 68 | NULL, 0, NULL, 0); 69 | if (ret) { 70 | dev_err(&dev->gbphy_dev->dev, "HCD start failed '%d'\n", ret); 71 | return ret; 72 | } 73 | 74 | hcd->state = HC_STATE_RUNNING; 75 | if (bus->root_hub) 76 | usb_hcd_resume_root_hub(hcd); 77 | return 0; 78 | } 79 | 80 | static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) 81 | { 82 | return -ENXIO; 83 | } 84 | 85 | static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) 86 | { 87 | return -ENXIO; 88 | } 89 | 90 | static int get_frame_number(struct usb_hcd *hcd) 91 | { 92 | return 0; 93 | } 94 | 95 | static int hub_status_data(struct usb_hcd *hcd, char *buf) 96 | { 97 | return 0; 98 | } 99 | 100 | static int hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, 101 | char *buf, u16 wLength) 102 | { 103 | struct gb_usb_device *dev = to_gb_usb_device(hcd); 104 | struct gb_operation *operation; 105 | struct gb_usb_hub_control_request *request; 106 | struct gb_usb_hub_control_response *response; 107 | size_t response_size; 108 | int ret; 109 | 110 | /* FIXME: handle unspecified lengths */ 111 | response_size = sizeof(*response) + wLength; 112 | 113 | operation = gb_operation_create(dev->connection, 114 | GB_USB_TYPE_HUB_CONTROL, 115 | sizeof(*request), 116 | response_size, 117 | GFP_KERNEL); 118 | if (!operation) 119 | return -ENOMEM; 120 | 121 | request = operation->request->payload; 122 | request->typeReq = cpu_to_le16(typeReq); 123 | request->wValue = cpu_to_le16(wValue); 124 | request->wIndex = cpu_to_le16(wIndex); 125 | request->wLength = cpu_to_le16(wLength); 126 | 127 | ret = gb_operation_request_send_sync(operation); 128 | if (ret) 129 | goto out; 130 | 131 | if (wLength) { 132 | /* Greybus core has verified response size */ 133 | response = operation->response->payload; 134 | memcpy(buf, response->buf, wLength); 135 | } 136 | out: 137 | gb_operation_put(operation); 138 | 139 | return ret; 140 | } 141 | 142 | static struct hc_driver usb_gb_hc_driver = { 143 | .description = "greybus-hcd", 144 | .product_desc = "Greybus USB Host Controller", 145 | .hcd_priv_size = sizeof(struct gb_usb_device), 146 | 147 | .flags = HCD_USB2, 148 | 149 | .start = hcd_start, 150 | .stop = hcd_stop, 151 | 152 | .urb_enqueue = urb_enqueue, 153 | .urb_dequeue = urb_dequeue, 154 | 155 | .get_frame_number = get_frame_number, 156 | .hub_status_data = hub_status_data, 157 | .hub_control = hub_control, 158 | }; 159 | 160 | static int gb_usb_probe(struct gbphy_device *gbphy_dev, 161 | const struct gbphy_device_id *id) 162 | { 163 | struct gb_connection *connection; 164 | struct device *dev = &gbphy_dev->dev; 165 | struct gb_usb_device *gb_usb_dev; 166 | struct usb_hcd *hcd; 167 | int retval; 168 | 169 | hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev)); 170 | if (!hcd) 171 | return -ENOMEM; 172 | 173 | connection = gb_connection_create(gbphy_dev->bundle, 174 | le16_to_cpu(gbphy_dev->cport_desc->id), 175 | NULL); 176 | if (IS_ERR(connection)) { 177 | retval = PTR_ERR(connection); 178 | goto exit_usb_put; 179 | } 180 | 181 | gb_usb_dev = to_gb_usb_device(hcd); 182 | gb_usb_dev->connection = connection; 183 | gb_connection_set_data(connection, gb_usb_dev); 184 | gb_usb_dev->gbphy_dev = gbphy_dev; 185 | gb_gbphy_set_data(gbphy_dev, gb_usb_dev); 186 | 187 | hcd->has_tt = 1; 188 | 189 | retval = gb_connection_enable(connection); 190 | if (retval) 191 | goto exit_connection_destroy; 192 | 193 | /* 194 | * FIXME: The USB bridged-PHY protocol driver depends on changes to 195 | * USB core which are not yet upstream. 196 | * 197 | * Disable for now. 198 | */ 199 | if (1) { 200 | dev_warn(dev, "USB protocol disabled\n"); 201 | retval = -EPROTONOSUPPORT; 202 | goto exit_connection_disable; 203 | } 204 | 205 | retval = usb_add_hcd(hcd, 0, 0); 206 | if (retval) 207 | goto exit_connection_disable; 208 | 209 | return 0; 210 | 211 | exit_connection_disable: 212 | gb_connection_disable(connection); 213 | exit_connection_destroy: 214 | gb_connection_destroy(connection); 215 | exit_usb_put: 216 | usb_put_hcd(hcd); 217 | 218 | return retval; 219 | } 220 | 221 | static void gb_usb_remove(struct gbphy_device *gbphy_dev) 222 | { 223 | struct gb_usb_device *gb_usb_dev = gb_gbphy_get_data(gbphy_dev); 224 | struct gb_connection *connection = gb_usb_dev->connection; 225 | struct usb_hcd *hcd = gb_usb_device_to_hcd(gb_usb_dev); 226 | 227 | usb_remove_hcd(hcd); 228 | gb_connection_disable(connection); 229 | gb_connection_destroy(connection); 230 | usb_put_hcd(hcd); 231 | } 232 | 233 | static const struct gbphy_device_id gb_usb_id_table[] = { 234 | { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_USB) }, 235 | { }, 236 | }; 237 | MODULE_DEVICE_TABLE(gbphy, gb_usb_id_table); 238 | 239 | static struct gbphy_driver usb_driver = { 240 | .name = "usb", 241 | .probe = gb_usb_probe, 242 | .remove = gb_usb_remove, 243 | .id_table = gb_usb_id_table, 244 | }; 245 | 246 | module_gbphy_driver(usb_driver); 247 | MODULE_LICENSE("GPL v2"); 248 | -------------------------------------------------------------------------------- /vibrator.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Greybus Vibrator protocol driver. 3 | * 4 | * Copyright 2014 Google Inc. 5 | * Copyright 2014 Linaro Ltd. 6 | * 7 | * Released under the GPLv2 only. 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "greybus.h" 19 | 20 | struct gb_vibrator_device { 21 | struct gb_connection *connection; 22 | struct device *dev; 23 | int minor; /* vibrator minor number */ 24 | struct delayed_work delayed_work; 25 | }; 26 | 27 | /* Greybus Vibrator operation types */ 28 | #define GB_VIBRATOR_TYPE_ON 0x02 29 | #define GB_VIBRATOR_TYPE_OFF 0x03 30 | 31 | static int turn_off(struct gb_vibrator_device *vib) 32 | { 33 | struct gb_bundle *bundle = vib->connection->bundle; 34 | int ret; 35 | 36 | ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, 37 | NULL, 0, NULL, 0); 38 | 39 | gb_pm_runtime_put_autosuspend(bundle); 40 | 41 | return ret; 42 | } 43 | 44 | static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) 45 | { 46 | struct gb_bundle *bundle = vib->connection->bundle; 47 | int ret; 48 | 49 | ret = gb_pm_runtime_get_sync(bundle); 50 | if (ret) 51 | return ret; 52 | 53 | /* Vibrator was switched ON earlier */ 54 | if (cancel_delayed_work_sync(&vib->delayed_work)) 55 | turn_off(vib); 56 | 57 | ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, 58 | NULL, 0, NULL, 0); 59 | if (ret) { 60 | gb_pm_runtime_put_autosuspend(bundle); 61 | return ret; 62 | } 63 | 64 | schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms)); 65 | 66 | return 0; 67 | } 68 | 69 | static void gb_vibrator_worker(struct work_struct *work) 70 | { 71 | struct delayed_work *delayed_work = to_delayed_work(work); 72 | struct gb_vibrator_device *vib = 73 | container_of(delayed_work, struct gb_vibrator_device, delayed_work); 74 | 75 | turn_off(vib); 76 | } 77 | 78 | static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, 79 | const char *buf, size_t count) 80 | { 81 | struct gb_vibrator_device *vib = dev_get_drvdata(dev); 82 | unsigned long val; 83 | int retval; 84 | 85 | retval = kstrtoul(buf, 10, &val); 86 | if (retval < 0) { 87 | dev_err(dev, "could not parse timeout value %d\n", retval); 88 | return retval; 89 | } 90 | 91 | if (val) 92 | retval = turn_on(vib, (u16)val); 93 | else 94 | retval = turn_off(vib); 95 | if (retval) 96 | return retval; 97 | 98 | return count; 99 | } 100 | static DEVICE_ATTR_WO(timeout); 101 | 102 | static struct attribute *vibrator_attrs[] = { 103 | &dev_attr_timeout.attr, 104 | NULL, 105 | }; 106 | ATTRIBUTE_GROUPS(vibrator); 107 | 108 | static struct class vibrator_class = { 109 | .name = "vibrator", 110 | .owner = THIS_MODULE, 111 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) 112 | .dev_groups = vibrator_groups, 113 | #endif 114 | }; 115 | 116 | static DEFINE_IDA(minors); 117 | 118 | static int gb_vibrator_probe(struct gb_bundle *bundle, 119 | const struct greybus_bundle_id *id) 120 | { 121 | struct greybus_descriptor_cport *cport_desc; 122 | struct gb_connection *connection; 123 | struct gb_vibrator_device *vib; 124 | struct device *dev; 125 | int retval; 126 | 127 | if (bundle->num_cports != 1) 128 | return -ENODEV; 129 | 130 | cport_desc = &bundle->cport_desc[0]; 131 | if (cport_desc->protocol_id != GREYBUS_PROTOCOL_VIBRATOR) 132 | return -ENODEV; 133 | 134 | vib = kzalloc(sizeof(*vib), GFP_KERNEL); 135 | if (!vib) 136 | return -ENOMEM; 137 | 138 | connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), 139 | NULL); 140 | if (IS_ERR(connection)) { 141 | retval = PTR_ERR(connection); 142 | goto err_free_vib; 143 | } 144 | gb_connection_set_data(connection, vib); 145 | 146 | vib->connection = connection; 147 | 148 | greybus_set_drvdata(bundle, vib); 149 | 150 | retval = gb_connection_enable(connection); 151 | if (retval) 152 | goto err_connection_destroy; 153 | 154 | /* 155 | * For now we create a device in sysfs for the vibrator, but odds are 156 | * there is a "real" device somewhere in the kernel for this, but I 157 | * can't find it at the moment... 158 | */ 159 | vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL); 160 | if (vib->minor < 0) { 161 | retval = vib->minor; 162 | goto err_connection_disable; 163 | } 164 | dev = device_create(&vibrator_class, &bundle->dev, 165 | MKDEV(0, 0), vib, "vibrator%d", vib->minor); 166 | if (IS_ERR(dev)) { 167 | retval = -EINVAL; 168 | goto err_ida_remove; 169 | } 170 | vib->dev = dev; 171 | 172 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) 173 | /* 174 | * Newer kernels handle this in a race-free manner, by the dev_groups 175 | * field in the struct class up above. But for older kernels, we need 176 | * to "open code this :( 177 | */ 178 | retval = sysfs_create_group(&dev->kobj, vibrator_groups[0]); 179 | if (retval) { 180 | device_unregister(dev); 181 | goto err_ida_remove; 182 | } 183 | #endif 184 | 185 | INIT_DELAYED_WORK(&vib->delayed_work, gb_vibrator_worker); 186 | 187 | gb_pm_runtime_put_autosuspend(bundle); 188 | 189 | return 0; 190 | 191 | err_ida_remove: 192 | ida_simple_remove(&minors, vib->minor); 193 | err_connection_disable: 194 | gb_connection_disable(connection); 195 | err_connection_destroy: 196 | gb_connection_destroy(connection); 197 | err_free_vib: 198 | kfree(vib); 199 | 200 | return retval; 201 | } 202 | 203 | static void gb_vibrator_disconnect(struct gb_bundle *bundle) 204 | { 205 | struct gb_vibrator_device *vib = greybus_get_drvdata(bundle); 206 | int ret; 207 | 208 | ret = gb_pm_runtime_get_sync(bundle); 209 | if (ret) 210 | gb_pm_runtime_get_noresume(bundle); 211 | 212 | if (cancel_delayed_work_sync(&vib->delayed_work)) 213 | turn_off(vib); 214 | 215 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) 216 | sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); 217 | #endif 218 | device_unregister(vib->dev); 219 | ida_simple_remove(&minors, vib->minor); 220 | gb_connection_disable(vib->connection); 221 | gb_connection_destroy(vib->connection); 222 | kfree(vib); 223 | } 224 | 225 | static const struct greybus_bundle_id gb_vibrator_id_table[] = { 226 | { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) }, 227 | { } 228 | }; 229 | MODULE_DEVICE_TABLE(greybus, gb_vibrator_id_table); 230 | 231 | static struct greybus_driver gb_vibrator_driver = { 232 | .name = "vibrator", 233 | .probe = gb_vibrator_probe, 234 | .disconnect = gb_vibrator_disconnect, 235 | .id_table = gb_vibrator_id_table, 236 | }; 237 | 238 | static __init int gb_vibrator_init(void) 239 | { 240 | int retval; 241 | 242 | retval = class_register(&vibrator_class); 243 | if (retval) 244 | return retval; 245 | 246 | retval = greybus_register(&gb_vibrator_driver); 247 | if (retval) 248 | goto err_class_unregister; 249 | 250 | return 0; 251 | 252 | err_class_unregister: 253 | class_unregister(&vibrator_class); 254 | 255 | return retval; 256 | } 257 | module_init(gb_vibrator_init); 258 | 259 | static __exit void gb_vibrator_exit(void) 260 | { 261 | greybus_deregister(&gb_vibrator_driver); 262 | class_unregister(&vibrator_class); 263 | ida_destroy(&minors); 264 | } 265 | module_exit(gb_vibrator_exit); 266 | 267 | MODULE_LICENSE("GPL v2"); 268 | --------------------------------------------------------------------------------