/** * DOC: The IPA embedded microcontroller * * The IPA incorporates a microcontroller that is able to do some additional * handling/offloading of network activity. The current code makes * essentially no use of the microcontroller, but it still requires some * initialization. It needs to be notified in the event the AP crashes. * * The microcontroller can generate two interrupts to the AP. One interrupt * is used to indicate that a response to a request from the AP is available. * The other is used to notify the AP of the occurrence of an event. In * addition, the AP can interrupt the microcontroller by writing a register. * * A 128 byte block of structured memory within the IPA SRAM is used together * with these interrupts to implement the communication interface between the * AP and the IPA microcontroller. Each side writes data to the shared area * before interrupting its peer, which will read the written data in response * to the interrupt. Some information found in the shared area is currently * unused. All remaining space in the shared area is reserved, and must not * be read or written by the AP.
*/ /* Supports hardware interface version 0x2000 */
/* Delay to allow a the microcontroller to save state when crashing */ #define IPA_SEND_DELAY 100 /* microseconds */
/** * struct ipa_uc_mem_area - AP/microcontroller shared memory area * @command: command code (AP->microcontroller) * @reserved0: reserved bytes; avoid reading or writing * @command_param: low 32 bits of command parameter (AP->microcontroller) * @command_param_hi: high 32 bits of command parameter (AP->microcontroller) * * @response: response code (microcontroller->AP) * @reserved1: reserved bytes; avoid reading or writing * @response_param: response parameter (microcontroller->AP) * * @event: event code (microcontroller->AP) * @reserved2: reserved bytes; avoid reading or writing * @event_param: event parameter (microcontroller->AP) * * @first_error_address: address of first error-source on SNOC * @hw_state: state of hardware (including error type information) * @warning_counter: counter of non-fatal hardware errors * @reserved3: reserved bytes; avoid reading or writing * @interface_version: hardware-reported interface version * @reserved4: reserved bytes; avoid reading or writing * * A shared memory area at the base of IPA resident memory is used for * communication with the microcontroller. The region is 128 bytes in * size, but only the first 40 bytes (structured this way) are used.
*/ struct ipa_uc_mem_area {
u8 command; /* enum ipa_uc_command */
u8 reserved0[3];
__le32 command_param;
__le32 command_param_hi;
u8 response; /* enum ipa_uc_response */
u8 reserved1[3];
__le32 response_param;
u8 event; /* enum ipa_uc_event */
u8 reserved2[3];
/* An INIT_COMPLETED response message is sent to the AP by the * microcontroller when it is operational. Other than this, the AP * should only receive responses from the microcontroller when it has * sent it a request message. * * We can drop the power reference taken in ipa_uc_power() once we * know the microcontroller has finished its initialization.
*/ switch (shared->response) { case IPA_UC_RESPONSE_INIT_COMPLETED: if (ipa->uc_powered) {
ipa->uc_loaded = true;
ipa_power_retention(ipa, true);
pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);
ipa->uc_powered = false;
} else {
dev_warn(dev, "unexpected init_completed response\n");
} break; default:
dev_warn(dev, "unsupported microcontroller response %u\n",
shared->response); break;
}
}
/* Take a proxy power reference for the microcontroller */ void ipa_uc_power(struct ipa *ipa)
{ struct device *dev = ipa->dev; staticbool already; int ret;
if (already) return;
already = true; /* Only do this on first boot */
/* This power reference dropped in ipa_uc_response_hdlr() above */
ret = pm_runtime_get_sync(dev); if (ret < 0) {
pm_runtime_put_noidle(dev);
dev_err(dev, "error %d getting proxy power\n", ret);
} else {
ipa->uc_powered = true;
}
}
/* Send a command to the microcontroller */ staticvoid send_uc_command(struct ipa *ipa, u32 command, u32 command_param)
{ struct ipa_uc_mem_area *shared = ipa_uc_shared(ipa); conststruct reg *reg;
u32 val;
/* Fill in the command data */
shared->command = command;
shared->command_param = cpu_to_le32(command_param);
shared->command_param_hi = 0;
shared->response = 0;
shared->response_param = 0;
/* Use an interrupt to tell the microcontroller the command is ready */
reg = ipa_reg(ipa, IPA_IRQ_UC);
val = reg_bit(reg, UC_INTR);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.