From 5aca2496ac65f5163eb725a09755f9fc32b1a810 Mon Sep 17 00:00:00 2001 From: Simon Shields Date: Thu, 4 Jul 2019 18:46:47 +0200 Subject: Add generic device for mainline Linux TODO: - More code cleanups - Refactor send_command to work with MIPI GNUtoo@cyberdimension.org: [rebase, fixes and cleanups] Signed-off-by: Denis 'GNUtoo' Carikli --- Android.mk | 1 + samsung-ipc/Makefile.am | 2 + samsung-ipc/devices/aries/aries.c | 1 + samsung-ipc/devices/crespo/crespo.c | 1 + samsung-ipc/devices/galaxys2/galaxys2.c | 2 + samsung-ipc/devices/generic/generic.c | 432 ++++++++++++++++++++++++++++++++ samsung-ipc/devices/generic/generic.h | 49 ++++ samsung-ipc/devices/i9300/i9300.c | 2 + samsung-ipc/devices/maguro/maguro.c | 1 + samsung-ipc/devices/n5100/n5100.c | 2 + samsung-ipc/devices/n7100/n7100.c | 2 + samsung-ipc/devices/piranha/piranha.c | 1 + samsung-ipc/ipc_devices.c | 10 + samsung-ipc/ipc_devices.h | 1 + 14 files changed, 507 insertions(+) create mode 100644 samsung-ipc/devices/generic/generic.c create mode 100644 samsung-ipc/devices/generic/generic.h diff --git a/Android.mk b/Android.mk index c07789c..fd9f32f 100644 --- a/Android.mk +++ b/Android.mk @@ -66,6 +66,7 @@ libsamsung_ipc_local_src_files := \ samsung-ipc/devices/maguro/maguro.c \ samsung-ipc/devices/piranha/piranha.c \ samsung-ipc/devices/i9300/i9300.c \ + samsung-ipc/devices/generic/generic.c \ samsung-ipc/devices/n7100/n7100.c \ samsung-ipc/devices/n5100/n5100.c \ samsung-ipc/utils.c \ diff --git a/samsung-ipc/Makefile.am b/samsung-ipc/Makefile.am index def4a23..bf860a3 100644 --- a/samsung-ipc/Makefile.am +++ b/samsung-ipc/Makefile.am @@ -59,6 +59,8 @@ libsamsung_ipc_la_SOURCES = \ devices/piranha/piranha.h \ devices/i9300/i9300.c \ devices/i9300/i9300.h \ + devices/generic/generic.c \ + devices/generic/generic.h \ devices/n7100/n7100.c \ devices/n7100/n7100.h \ devices/n5100/n5100.c \ diff --git a/samsung-ipc/devices/aries/aries.c b/samsung-ipc/devices/aries/aries.c index a3da208..03ff4ab 100644 --- a/samsung-ipc/devices/aries/aries.c +++ b/samsung-ipc/devices/aries/aries.c @@ -808,6 +808,7 @@ struct ipc_client_handlers aries_handlers = { .read = aries_read, .write = aries_write, .poll = aries_poll, + .send_command = NULL, .transport_data = NULL, .power_on = aries_power_on, .power_off = aries_power_off, diff --git a/samsung-ipc/devices/crespo/crespo.c b/samsung-ipc/devices/crespo/crespo.c index 1bf9a97..d4bf0d5 100644 --- a/samsung-ipc/devices/crespo/crespo.c +++ b/samsung-ipc/devices/crespo/crespo.c @@ -576,6 +576,7 @@ struct ipc_client_handlers crespo_handlers = { .read = crespo_read, .write = crespo_write, .poll = crespo_poll, + .send_command = NULL, .transport_data = NULL, .power_on = crespo_power_on, .power_off = crespo_power_off, diff --git a/samsung-ipc/devices/galaxys2/galaxys2.c b/samsung-ipc/devices/galaxys2/galaxys2.c index 8b96893..40f9c80 100644 --- a/samsung-ipc/devices/galaxys2/galaxys2.c +++ b/samsung-ipc/devices/galaxys2/galaxys2.c @@ -26,6 +26,7 @@ #include #include +#include "generic-xmm626_hsic.h" #include "xmm626.h" #include "xmm626_hsic.h" #include "xmm626_sec_modem.h" @@ -383,6 +384,7 @@ struct ipc_client_handlers galaxys2_handlers = { .open = galaxys2_open, .close = galaxys2_close, .poll = galaxys2_poll, + .send_command = xmm626_hsic_command_send, .transport_data = NULL, .power_on = galaxys2_power_on, .power_off = galaxys2_power_off, diff --git a/samsung-ipc/devices/generic/generic.c b/samsung-ipc/devices/generic/generic.c new file mode 100644 index 0000000..9db9aa1 --- /dev/null +++ b/samsung-ipc/devices/generic/generic.c @@ -0,0 +1,432 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2013-2014 Paul Kocialkowski + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "generic-xmm626_hsic.h" +#include "generic-xmm626_sec_modem.h" +#include "xmm626.h" +#include "xmm626_hsic.h" +#include "xmm626_sec_modem.h" +#include "generic.h" + +int generic_boot(struct ipc_client *client) +{ + void *modem_image_data = NULL; + int modem_image_fd = -1; + int modem_boot_fd = -1; + int modem_link_fd = -1; + unsigned char *p; + int rc; + + if (client == NULL) + return -1; + + ipc_client_log(client, "Starting generic modem boot"); + + modem_image_fd = open(GENERIC_MODEM_IMAGE_DEVICE, O_RDONLY); + if (modem_image_fd < 0) { + ipc_client_log(client, "Opening modem image device failed"); + goto error; + } + ipc_client_log(client, "Opened modem image device"); + + modem_image_data = mmap(0, GENERIC_MODEM_IMAGE_SIZE, PROT_READ, MAP_SHARED, modem_image_fd, 0); + if (modem_image_data == NULL || modem_image_data == (void *) 0xffffffff) { + ipc_client_log(client, "Mapping modem image data to memory failed"); + goto error; + } + ipc_client_log(client, "Mapped modem image data to memory"); + + /* modem_link_fd = open(GENERIC_XMM626_SEC_MODEM_LINK_PM_DEVICE, O_RDWR); + if (modem_link_fd < 0) { + ipc_client_log(client, "Opening modem link device failed"); + goto error; + } + ipc_client_log(client, "Opened modem link device"); +*/ + rc = generic_xmm626_sec_modem_power(modem_boot_fd, 0); + if (rc < 0) { + ipc_client_log(client, "generic_xmm626_sec_modem_power: Turning the modem off failed with error %d", rc); + goto error; + } + rc = generic_xmm626_sec_modem_hci_power(0); + if (rc < 0) { + ipc_client_log(client, "generic_xmm626_sec_modem_hci_power: Turning the modem off failed"); + goto error; + } + ipc_client_log(client, "Turned the modem off"); + + rc = generic_xmm626_sec_modem_power(modem_boot_fd, 1); + printf("%d\n", rc); + rc |= generic_xmm626_sec_modem_hci_power(1); + printf("%d\n", rc); + + if (rc < 0) { + ipc_client_log(client, "Turning the modem on failed"); + goto error; + } + ipc_client_log(client, "Turned the modem on"); + + rc = 0; + do { + modem_boot_fd = open(GENERIC_XMM626_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (modem_boot_fd >= 0) { + break; + } + usleep(5000); + rc++; + } while (rc < 10000); + if (modem_boot_fd < 0) { + ipc_client_log(client, "Failed to open boot device"); + goto error; + } + ipc_client_log(client, "Opened modem boot device"); + + + rc = generic_xmm626_sec_modem_link_connected_wait(modem_link_fd); + if (rc < 0) { + ipc_client_log(client, "Waiting for link connected failed"); + goto error; + } + ipc_client_log(client, "Waited for link connected"); + + p = (unsigned char *) modem_image_data + GENERIC_PSI_OFFSET; + + rc = xmm626_hsic_psi_send(client, modem_boot_fd, (void *) p, GENERIC_PSI_SIZE); + if (rc < 0) { + ipc_client_log(client, "Sending XMM626 HSIC PSI failed"); + goto error; + } + ipc_client_log(client, "Sent XMM626 HSIC PSI"); + + p = (unsigned char *) modem_image_data + GENERIC_EBL_OFFSET; + + rc = xmm626_hsic_ebl_send(client, modem_boot_fd, (void *) p, GENERIC_EBL_SIZE); + if (rc < 0) { + ipc_client_log(client, "Sending XMM626 HSIC EBL failed"); + goto error; + } + ipc_client_log(client, "Sent XMM626 HSIC EBL"); + + rc = xmm626_hsic_port_config_send(client, modem_boot_fd); + if (rc < 0) { + ipc_client_log(client, "Sending XMM626 HSIC port config failed"); + goto error; + } + ipc_client_log(client, "Sent XMM626 HSIC port config"); + + p = (unsigned char *) modem_image_data + GENERIC_SEC_START_OFFSET; + + rc = xmm626_hsic_sec_start_send(client, modem_boot_fd, (void *) p, GENERIC_SEC_START_SIZE); + if (rc < 0) { + ipc_client_log(client, "Sending XMM626 HSIC SEC start failed"); + goto error; + } + ipc_client_log(client, "Sent XMM626 HSIC SEC start"); + + p = (unsigned char *) modem_image_data + GENERIC_FIRMWARE_OFFSET; + + rc = xmm626_hsic_firmware_send(client, modem_boot_fd, (void *) p, GENERIC_FIRMWARE_SIZE); + if (rc < 0) { + ipc_client_log(client, "Sending XMM626 HSIC firmware failed"); + goto error; + } + ipc_client_log(client, "Sent XMM626 HSIC firmware"); + + rc = xmm626_hsic_nv_data_send(client, modem_boot_fd); + if (rc < 0) { + ipc_client_log(client, "Sending XMM626 HSIC nv_data failed"); + goto error; + } + ipc_client_log(client, "Sent XMM626 HSIC nv_data"); + + rc = xmm626_hsic_sec_end_send(client, modem_boot_fd); + if (rc < 0) { + ipc_client_log(client, "Sending XMM626 HSIC SEC end failed"); + goto error; + } + ipc_client_log(client, "Sent XMM626 HSIC SEC end"); + + rc = xmm626_hsic_hw_reset_send(client, modem_boot_fd); + if (rc < 0) { + ipc_client_log(client, "Sending XMM626 HSIC HW reset failed"); + goto error; + } + ipc_client_log(client, "Sent XMM626 HSIC HW reset"); + + usleep(300000); + + rc = generic_xmm626_sec_modem_link_get_hostwake_wait(modem_link_fd); + if (rc < 0) { + ipc_client_log(client, "Waiting for host wake failed"); + } + + rc = generic_xmm626_sec_modem_link_control_enable(modem_link_fd, 0); + rc |= generic_xmm626_sec_modem_hci_power(0); + rc |= generic_xmm626_sec_modem_link_control_active(modem_link_fd, 0); + + if (rc < 0) { + ipc_client_log(client, "Turning the modem off failed"); + goto error; + } + + rc = generic_xmm626_sec_modem_link_get_hostwake_wait(modem_link_fd); + if (rc < 0) { + ipc_client_log(client, "Waiting for host wake failed"); + } + ipc_client_log(client, "Waited for host wake"); + + rc = generic_xmm626_sec_modem_link_control_enable(modem_link_fd, 1); + rc |= generic_xmm626_sec_modem_hci_power(1); + rc |= generic_xmm626_sec_modem_link_control_active(modem_link_fd, 1); + + if (rc < 0) { + ipc_client_log(client, "Turning the modem on failed"); + goto error; + } + + rc = generic_xmm626_sec_modem_link_connected_wait(modem_link_fd); + if (rc < 0) { + ipc_client_log(client, "Waiting for link connected failed"); + goto error; + } + ipc_client_log(client, "Waited for link connected"); + + usleep(300000); + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (modem_image_data != NULL) + munmap(modem_image_data, GENERIC_MODEM_IMAGE_SIZE); + + if (modem_image_fd >= 0) + close(modem_image_fd); + + if (modem_boot_fd >= 0) + close(modem_boot_fd); + + if (modem_link_fd >= 0) + close(modem_link_fd); + + return rc; +} + +int generic_open(void *data, int type) +{ + struct generic_transport_data *transport_data; + + if (data == NULL) + return -1; + + transport_data = (struct generic_transport_data *) data; + + transport_data->fd = generic_xmm626_sec_modem_open(type); + if (transport_data->fd < 0) + return -1; + + return 0; +} + +int generic_close(void *data) +{ + struct generic_transport_data *transport_data; + + if (data == NULL) + return -1; + + transport_data = (struct generic_transport_data *) data; + + xmm626_sec_modem_close(transport_data->fd); + transport_data->fd = -1; + + return 0; +} + +int generic_read(void *data, void *buffer, size_t length) +{ + struct generic_transport_data *transport_data; + int rc; + + if (data == NULL) + return -1; + + transport_data = (struct generic_transport_data *) data; + + rc = generic_xmm626_sec_modem_read(transport_data->fd, buffer, length); + + return rc; +} + +int generic_write(void *data, const void *buffer, size_t length) +{ + struct generic_transport_data *transport_data; + int rc; + + if (data == NULL) + return -1; + + transport_data = (struct generic_transport_data *) data; + + rc = generic_xmm626_sec_modem_write(transport_data->fd, buffer, length); + + return rc; +} + +int generic_poll(void *data, __attribute__((unused)) struct ipc_poll_fds *fds, + __attribute__((unused)) struct timeval *timeout) +{ + struct generic_transport_data *transport_data; + int rc; + struct pollfd fd; + + if (data == NULL) + return -1; + + transport_data = (struct generic_transport_data *) data; + + fd.fd = transport_data->fd; + fd.events = POLLRDNORM | POLLIN; + + rc = poll(&fd, 1, -1); + + printf("poll returns %d\n", rc); + return rc - 1; +} + +int generic_power_on(__attribute__((unused)) void *data) +{ + return 0; +} + +int generic_power_off(__attribute__((unused)) void *data) +{ + int fd; + int rc; + + fd = open(GENERIC_XMM626_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (fd < 0) + return -1; + + rc = generic_xmm626_sec_modem_power(fd, 0); + + close(fd); + + if (rc < 0) + return -1; + + return 0; +} + +int generic_gprs_activate(__attribute__((unused)) void *data, + __attribute__((unused)) unsigned int cid) +{ + return 0; +} + +int generic_gprs_deactivate(__attribute__((unused)) void *data, + __attribute__((unused)) unsigned int cid) +{ + return 0; +} + +int generic_data_create(void **transport_data, + __attribute__((unused)) void **power_data, + __attribute__((unused)) void **gprs_data) +{ + if (transport_data == NULL) + return -1; + + *transport_data = calloc(1, sizeof(struct generic_transport_data)); + + return 0; +} + +int generic_data_destroy(void *transport_data, + __attribute__((unused)) void *power_data, + __attribute__((unused)) void *gprs_data) +{ + if (transport_data == NULL) + return -1; + + free(transport_data); + + return 0; +} + +struct ipc_client_ops generic_fmt_ops = { + .boot = generic_boot, + .send = generic_xmm626_sec_modem_fmt_send, + .recv = xmm626_sec_modem_fmt_recv, +}; + +struct ipc_client_ops generic_rfs_ops = { + .boot = NULL, + .send = xmm626_sec_modem_rfs_send, + .recv = xmm626_sec_modem_rfs_recv, +}; + +struct ipc_client_handlers generic_handlers = { + .read = generic_read, + .write = generic_write, + .open = generic_open, + .close = generic_close, + .poll = generic_poll, + .send_command = generic_xmm626_hsic_command_send, + .transport_data = NULL, + .power_on = generic_power_on, + .power_off = generic_power_off, + .power_data = NULL, + .gprs_activate = generic_gprs_activate, + .gprs_deactivate = generic_gprs_deactivate, + .gprs_data = NULL, + .data_create = generic_data_create, + .data_destroy = generic_data_destroy, +}; + +struct ipc_client_gprs_specs generic_gprs_specs = { + .gprs_get_iface = xmm626_sec_modem_gprs_get_iface, + .gprs_get_capabilities = xmm626_sec_modem_gprs_get_capabilities, +}; + +struct ipc_client_nv_data_specs generic_nv_data_specs = { + .nv_data_path = XMM626_NV_DATA_PATH, + .nv_data_md5_path = XMM626_NV_DATA_MD5_PATH, + .nv_data_backup_path = XMM626_NV_DATA_BACKUP_PATH, + .nv_data_backup_md5_path = XMM626_NV_DATA_BACKUP_MD5_PATH, + .nv_data_secret = XMM626_NV_DATA_SECRET, + .nv_data_size = XMM626_NV_DATA_SIZE, + .nv_data_chunk_size = XMM626_NV_DATA_CHUNK_SIZE, +}; + +// vim:ts=4:sw=4:expandtab diff --git a/samsung-ipc/devices/generic/generic.h b/samsung-ipc/devices/generic/generic.h new file mode 100644 index 0000000..eb2e6ea --- /dev/null +++ b/samsung-ipc/devices/generic/generic.h @@ -0,0 +1,49 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2013-2014 Paul Kocialkowski + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see . + */ + +#ifndef __GENERIC_H__ +#define __GENERIC_H__ + +#define GENERIC_MODEM_IMAGE_SIZE 0x1000000 +#define GENERIC_PSI_OFFSET 0x1000 +#define GENERIC_PSI_SIZE 0xE000 +#define GENERIC_EBL_OFFSET 0xF000 +#define GENERIC_EBL_SIZE 0x19000 +#define GENERIC_SEC_START_OFFSET 0x9FF800 +#define GENERIC_SEC_START_SIZE 0x800 +#define GENERIC_FIRMWARE_OFFSET 0x28000 +#define GENERIC_FIRMWARE_SIZE 0x9D7800 +#define GENERIC_NV_DATA_OFFSET 0xA00000 +#define GENERIC_NV_DATA_SIZE 0x200000 + +#define GENERIC_MODEM_IMAGE_DEVICE "/dev/block/by-name/RADIO" + +struct generic_transport_data { + int fd; +}; + +extern struct ipc_client_ops generic_fmt_ops; +extern struct ipc_client_ops generic_rfs_ops; +extern struct ipc_client_handlers generic_handlers; +extern struct ipc_client_gprs_specs generic_gprs_specs; +extern struct ipc_client_nv_data_specs generic_nv_data_specs; + +#endif + +// vim:ts=4:sw=4:expandtab diff --git a/samsung-ipc/devices/i9300/i9300.c b/samsung-ipc/devices/i9300/i9300.c index c0d3cb1..e38e231 100644 --- a/samsung-ipc/devices/i9300/i9300.c +++ b/samsung-ipc/devices/i9300/i9300.c @@ -26,6 +26,7 @@ #include #include +#include "generic-xmm626_hsic.h" #include "xmm626.h" #include "xmm626_hsic.h" #include "xmm626_sec_modem.h" @@ -377,6 +378,7 @@ struct ipc_client_handlers i9300_handlers = { .open = i9300_open, .close = i9300_close, .poll = i9300_poll, + .send_command = xmm626_hsic_command_send, .transport_data = NULL, .power_on = i9300_power_on, .power_off = i9300_power_off, diff --git a/samsung-ipc/devices/maguro/maguro.c b/samsung-ipc/devices/maguro/maguro.c index b41eadd..4bd17cf 100644 --- a/samsung-ipc/devices/maguro/maguro.c +++ b/samsung-ipc/devices/maguro/maguro.c @@ -358,6 +358,7 @@ struct ipc_client_handlers maguro_handlers = { .open = maguro_open, .close = maguro_close, .poll = maguro_poll, + .send_command = NULL, /* xmm626_mipi_command_send */ .transport_data = NULL, .power_on = maguro_power_on, .power_off = maguro_power_off, diff --git a/samsung-ipc/devices/n5100/n5100.c b/samsung-ipc/devices/n5100/n5100.c index 78d1f1f..d40f1fc 100644 --- a/samsung-ipc/devices/n5100/n5100.c +++ b/samsung-ipc/devices/n5100/n5100.c @@ -27,6 +27,7 @@ #include #include +#include "generic-xmm626_hsic.h" #include "xmm626.h" #include "xmm626_hsic.h" #include "xmm626_sec_modem.h" @@ -378,6 +379,7 @@ struct ipc_client_handlers n5100_handlers = { .open = n5100_open, .close = n5100_close, .poll = n5100_poll, + .send_command = xmm626_hsic_command_send, .transport_data = NULL, .power_on = n5100_power_on, .power_off = n5100_power_off, diff --git a/samsung-ipc/devices/n7100/n7100.c b/samsung-ipc/devices/n7100/n7100.c index eb2005b..7ce3d38 100644 --- a/samsung-ipc/devices/n7100/n7100.c +++ b/samsung-ipc/devices/n7100/n7100.c @@ -26,6 +26,7 @@ #include #include +#include "generic-xmm626_hsic.h" #include "xmm626.h" #include "xmm626_hsic.h" #include "xmm626_sec_modem.h" @@ -377,6 +378,7 @@ struct ipc_client_handlers n7100_handlers = { .open = n7100_open, .close = n7100_close, .poll = n7100_poll, + .send_command = xmm626_hsic_command_send, .transport_data = NULL, .power_on = n7100_power_on, .power_off = n7100_power_off, diff --git a/samsung-ipc/devices/piranha/piranha.c b/samsung-ipc/devices/piranha/piranha.c index df75363..c052681 100644 --- a/samsung-ipc/devices/piranha/piranha.c +++ b/samsung-ipc/devices/piranha/piranha.c @@ -325,6 +325,7 @@ struct ipc_client_handlers piranha_handlers = { .open = piranha_open, .close = piranha_close, .poll = piranha_poll, + .send_command = NULL, /* xmm626_mipi_command_send */ .transport_data = NULL, .power_on = piranha_power_on, .power_off = piranha_power_off, diff --git a/samsung-ipc/ipc_devices.c b/samsung-ipc/ipc_devices.c index ad7d23c..b80f806 100644 --- a/samsung-ipc/ipc_devices.c +++ b/samsung-ipc/ipc_devices.c @@ -133,6 +133,16 @@ struct ipc_device_desc ipc_devices[] = { .gprs_specs = &i9300_gprs_specs, .nv_data_specs = &i9300_nv_data_specs, }, + { + .name = NULL, + .board_name = "samsung exynos (flattened device tree)", + .kernel_version = NULL, + .fmt_ops = &generic_fmt_ops, + .rfs_ops = &generic_rfs_ops, + .handlers = &generic_handlers, + .gprs_specs = &generic_gprs_specs, + .nv_data_specs = &generic_nv_data_specs, + }, { .name = "n7100", .board_name = "smdk4x12", diff --git a/samsung-ipc/ipc_devices.h b/samsung-ipc/ipc_devices.h index a7a6098..1cb1524 100644 --- a/samsung-ipc/ipc_devices.h +++ b/samsung-ipc/ipc_devices.h @@ -26,6 +26,7 @@ #include "devices/maguro/maguro.h" #include "devices/piranha/piranha.h" #include "devices/i9300/i9300.h" +#include "devices/generic/generic.h" #include "devices/n7100/n7100.h" #include "devices/n5100/n5100.h" -- cgit v1.2.3