mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-22 23:59:26 +07:00
usb: typec: ucsi: acpi: Move to the new API
Replacing the old "cmd" and "sync" callbacks with an implementation of struct ucsi_operations. The ACPI notification (interrupt) handler will from now on read the CCI (Command Status and Connector Change Indication) register, and call ucsi_connector_change() function and/or complete pending command completions based on it. Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20191104142435.29960-13-heikki.krogerus@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
bdc62f2bae
commit
f56de278e8
@ -19,7 +19,9 @@
|
||||
struct ucsi_acpi {
|
||||
struct device *dev;
|
||||
struct ucsi *ucsi;
|
||||
struct ucsi_ppm ppm;
|
||||
void __iomem *base;
|
||||
struct completion complete;
|
||||
unsigned long flags;
|
||||
guid_t guid;
|
||||
};
|
||||
|
||||
@ -39,27 +41,73 @@ static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ucsi_acpi_cmd(struct ucsi_ppm *ppm, struct ucsi_control *ctrl)
|
||||
static int ucsi_acpi_read(struct ucsi *ucsi, unsigned int offset,
|
||||
void *val, size_t val_len)
|
||||
{
|
||||
struct ucsi_acpi *ua = container_of(ppm, struct ucsi_acpi, ppm);
|
||||
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
|
||||
int ret;
|
||||
|
||||
ppm->data->ctrl.raw_cmd = ctrl->raw_cmd;
|
||||
ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(val, (const void __force *)(ua->base + offset), val_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ucsi_acpi_async_write(struct ucsi *ucsi, unsigned int offset,
|
||||
const void *val, size_t val_len)
|
||||
{
|
||||
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
|
||||
|
||||
memcpy((void __force *)(ua->base + offset), val, val_len);
|
||||
|
||||
return ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_WRITE);
|
||||
}
|
||||
|
||||
static int ucsi_acpi_sync(struct ucsi_ppm *ppm)
|
||||
static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset,
|
||||
const void *val, size_t val_len)
|
||||
{
|
||||
struct ucsi_acpi *ua = container_of(ppm, struct ucsi_acpi, ppm);
|
||||
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
|
||||
int ret;
|
||||
|
||||
return ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
|
||||
set_bit(COMMAND_PENDING, &ua->flags);
|
||||
|
||||
ret = ucsi_acpi_async_write(ucsi, offset, val, val_len);
|
||||
if (ret)
|
||||
goto out_clear_bit;
|
||||
|
||||
if (!wait_for_completion_timeout(&ua->complete, msecs_to_jiffies(5000)))
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
out_clear_bit:
|
||||
clear_bit(COMMAND_PENDING, &ua->flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct ucsi_operations ucsi_acpi_ops = {
|
||||
.read = ucsi_acpi_read,
|
||||
.sync_write = ucsi_acpi_sync_write,
|
||||
.async_write = ucsi_acpi_async_write
|
||||
};
|
||||
|
||||
static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct ucsi_acpi *ua = data;
|
||||
u32 cci;
|
||||
int ret;
|
||||
|
||||
ucsi_notify(ua->ucsi);
|
||||
ret = ucsi_acpi_read(ua->ucsi, UCSI_CCI, &cci, sizeof(cci));
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
if (test_bit(COMMAND_PENDING, &ua->flags) &&
|
||||
cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))
|
||||
complete(&ua->complete);
|
||||
else if (UCSI_CCI_CONNECTOR(cci))
|
||||
ucsi_connector_change(ua->ucsi, UCSI_CCI_CONNECTOR(cci));
|
||||
}
|
||||
|
||||
static int ucsi_acpi_probe(struct platform_device *pdev)
|
||||
@ -90,35 +138,39 @@ static int ucsi_acpi_probe(struct platform_device *pdev)
|
||||
* it can not be requested here, and we can not use
|
||||
* devm_ioremap_resource().
|
||||
*/
|
||||
ua->ppm.data = devm_ioremap(&pdev->dev, res->start, resource_size(res));
|
||||
if (!ua->ppm.data)
|
||||
ua->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
|
||||
if (!ua->base)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!ua->ppm.data->version)
|
||||
return -ENODEV;
|
||||
|
||||
ret = guid_parse(UCSI_DSM_UUID, &ua->guid);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ua->ppm.cmd = ucsi_acpi_cmd;
|
||||
ua->ppm.sync = ucsi_acpi_sync;
|
||||
init_completion(&ua->complete);
|
||||
ua->dev = &pdev->dev;
|
||||
|
||||
ua->ucsi = ucsi_create(&pdev->dev, &ucsi_acpi_ops);
|
||||
if (IS_ERR(ua->ucsi))
|
||||
return PTR_ERR(ua->ucsi);
|
||||
|
||||
ucsi_set_drvdata(ua->ucsi, ua);
|
||||
|
||||
status = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
ucsi_acpi_notify, ua);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dev_err(&pdev->dev, "failed to install notify handler\n");
|
||||
ucsi_destroy(ua->ucsi);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ua->ucsi = ucsi_register_ppm(&pdev->dev, &ua->ppm);
|
||||
if (IS_ERR(ua->ucsi)) {
|
||||
ret = ucsi_register(ua->ucsi);
|
||||
if (ret) {
|
||||
acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
ucsi_acpi_notify);
|
||||
return PTR_ERR(ua->ucsi);
|
||||
ucsi_destroy(ua->ucsi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, ua);
|
||||
@ -130,7 +182,8 @@ static int ucsi_acpi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ucsi_acpi *ua = platform_get_drvdata(pdev);
|
||||
|
||||
ucsi_unregister_ppm(ua->ucsi);
|
||||
ucsi_unregister(ua->ucsi);
|
||||
ucsi_destroy(ua->ucsi);
|
||||
|
||||
acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev), ACPI_DEVICE_NOTIFY,
|
||||
ucsi_acpi_notify);
|
||||
|
Loading…
Reference in New Issue
Block a user