From: Guenter Roeck <linux@roeck-us.net>
To: Heikki Krogerus <heikki.krogerus@linux.intel.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Ajay Gupta <ajayg@nvidia.com>, linux-usb@vger.kernel.org
Subject: Re: [PATCH v4 13/18] usb: typec: ucsi: ccg: Move to the new API
Date: Mon, 4 Nov 2019 06:36:44 -0800 [thread overview]
Message-ID: <1a404105-8872-7377-465c-cf792f2fad58@roeck-us.net> (raw)
In-Reply-To: <20191104142435.29960-14-heikki.krogerus@linux.intel.com>
On 11/4/19 6:24 AM, Heikki Krogerus wrote:
> Replacing the old "cmd" and "sync" callbacks with an
> implementation of struct ucsi_operations. The 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>
> Tested-by: Ajay Gupta <ajayg@nvidia.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
> ---
> drivers/usb/typec/ucsi/ucsi_ccg.c | 166 +++++++++++++++---------------
> 1 file changed, 81 insertions(+), 85 deletions(-)
>
> diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
> index d772fce51905..3370b3fc37b1 100644
> --- a/drivers/usb/typec/ucsi/ucsi_ccg.c
> +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
> @@ -176,8 +176,8 @@ struct ccg_resp {
> struct ucsi_ccg {
> struct device *dev;
> struct ucsi *ucsi;
> - struct ucsi_ppm ppm;
> struct i2c_client *client;
> +
> struct ccg_dev_info info;
> /* version info for boot, primary and secondary */
> struct version_info version[FW2 + 1];
> @@ -196,6 +196,8 @@ struct ucsi_ccg {
> /* fw build with vendor information */
> u16 fw_build;
> struct work_struct pm_work;
> +
> + struct completion complete;
> };
>
> static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
> @@ -243,7 +245,7 @@ static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
> return 0;
> }
>
> -static int ccg_write(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
> +static int ccg_write(struct ucsi_ccg *uc, u16 rab, const u8 *data, u32 len)
> {
> struct i2c_client *client = uc->client;
> unsigned char *buf;
> @@ -317,88 +319,85 @@ static int ucsi_ccg_init(struct ucsi_ccg *uc)
> return -ETIMEDOUT;
> }
>
> -static int ucsi_ccg_send_data(struct ucsi_ccg *uc)
> +static int ucsi_ccg_read(struct ucsi *ucsi, unsigned int offset,
> + void *val, size_t val_len)
> {
> - u8 *ppm = (u8 *)uc->ppm.data;
> - int status;
> - u16 rab;
> + u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(offset);
>
> - rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, message_out));
> - status = ccg_write(uc, rab, ppm +
> - offsetof(struct ucsi_data, message_out),
> - sizeof(uc->ppm.data->message_out));
> - if (status < 0)
> - return status;
> -
> - rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, ctrl));
> - return ccg_write(uc, rab, ppm + offsetof(struct ucsi_data, ctrl),
> - sizeof(uc->ppm.data->ctrl));
> + return ccg_read(ucsi_get_drvdata(ucsi), reg, val, val_len);
> }
>
> -static int ucsi_ccg_recv_data(struct ucsi_ccg *uc)
> +static int ucsi_ccg_async_write(struct ucsi *ucsi, unsigned int offset,
> + const void *val, size_t val_len)
> {
> - u8 *ppm = (u8 *)uc->ppm.data;
> - int status;
> - u16 rab;
> + u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(offset);
>
> - rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, cci));
> - status = ccg_read(uc, rab, ppm + offsetof(struct ucsi_data, cci),
> - sizeof(uc->ppm.data->cci));
> - if (status < 0)
> - return status;
> -
> - rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, message_in));
> - return ccg_read(uc, rab, ppm + offsetof(struct ucsi_data, message_in),
> - sizeof(uc->ppm.data->message_in));
> + return ccg_write(ucsi_get_drvdata(ucsi), reg, val, val_len);
> }
>
> -static int ucsi_ccg_ack_interrupt(struct ucsi_ccg *uc)
> +static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset,
> + const void *val, size_t val_len)
> {
> - int status;
> - unsigned char data;
> + struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi);
> + int ret;
>
> - status = ccg_read(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
> - if (status < 0)
> - return status;
> + mutex_lock(&uc->lock);
> + pm_runtime_get_sync(uc->dev);
> + set_bit(DEV_CMD_PENDING, &uc->flags);
>
> - return ccg_write(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
> -}
> + ret = ucsi_ccg_async_write(ucsi, offset, val, val_len);
> + if (ret)
> + goto err_clear_bit;
>
> -static int ucsi_ccg_sync(struct ucsi_ppm *ppm)
> -{
> - struct ucsi_ccg *uc = container_of(ppm, struct ucsi_ccg, ppm);
> - int status;
> + if (!wait_for_completion_timeout(&uc->complete, msecs_to_jiffies(5000)))
> + ret = -ETIMEDOUT;
>
> - status = ucsi_ccg_recv_data(uc);
> - if (status < 0)
> - return status;
> +err_clear_bit:
> + clear_bit(DEV_CMD_PENDING, &uc->flags);
> + pm_runtime_put_sync(uc->dev);
> + mutex_unlock(&uc->lock);
>
> - /* ack interrupt to allow next command to run */
> - return ucsi_ccg_ack_interrupt(uc);
> + return ret;
> }
>
> -static int ucsi_ccg_cmd(struct ucsi_ppm *ppm, struct ucsi_control *ctrl)
> -{
> - struct ucsi_ccg *uc = container_of(ppm, struct ucsi_ccg, ppm);
> -
> - ppm->data->ctrl.raw_cmd = ctrl->raw_cmd;
> - return ucsi_ccg_send_data(uc);
> -}
> +static const struct ucsi_operations ucsi_ccg_ops = {
> + .read = ucsi_ccg_read,
> + .sync_write = ucsi_ccg_sync_write,
> + .async_write = ucsi_ccg_async_write
> +};
>
> static irqreturn_t ccg_irq_handler(int irq, void *data)
> {
> + u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(UCSI_CCI);
> struct ucsi_ccg *uc = data;
> + u8 intr_reg;
> + u32 cci;
> + int ret;
> +
> + ret = ccg_read(uc, CCGX_RAB_INTR_REG, &intr_reg, sizeof(intr_reg));
> + if (ret)
> + return ret;
> +
> + ret = ccg_read(uc, reg, (void *)&cci, sizeof(cci));
> + if (ret)
> + goto err_clear_irq;
> +
> + if (UCSI_CCI_CONNECTOR(cci))
> + ucsi_connector_change(uc->ucsi, UCSI_CCI_CONNECTOR(cci));
> +
> + if (test_bit(DEV_CMD_PENDING, &uc->flags) &&
> + cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))
> + complete(&uc->complete);
>
> - ucsi_notify(uc->ucsi);
> +err_clear_irq:
> + ccg_write(uc, CCGX_RAB_INTR_REG, &intr_reg, sizeof(intr_reg));
>
> return IRQ_HANDLED;
> }
>
> static void ccg_pm_workaround_work(struct work_struct *pm_work)
> {
> - struct ucsi_ccg *uc = container_of(pm_work, struct ucsi_ccg, pm_work);
> -
> - ucsi_notify(uc->ucsi);
> + ccg_irq_handler(0, container_of(pm_work, struct ucsi_ccg, pm_work));
> }
>
> static int get_fw_info(struct ucsi_ccg *uc)
> @@ -1027,10 +1026,10 @@ static int ccg_restart(struct ucsi_ccg *uc)
> return status;
> }
>
> - uc->ucsi = ucsi_register_ppm(dev, &uc->ppm);
> - if (IS_ERR(uc->ucsi)) {
> - dev_err(uc->dev, "ucsi_register_ppm failed\n");
> - return PTR_ERR(uc->ucsi);
> + status = ucsi_register(uc->ucsi);
> + if (status) {
> + dev_err(uc->dev, "failed to register the interface\n");
> + return status;
> }
>
> return 0;
> @@ -1047,7 +1046,7 @@ static void ccg_update_firmware(struct work_struct *work)
> return;
>
> if (flash_mode != FLASH_NOT_NEEDED) {
> - ucsi_unregister_ppm(uc->ucsi);
> + ucsi_unregister(uc->ucsi);
> free_irq(uc->irq, uc);
>
> ccg_fw_update(uc, flash_mode);
> @@ -1091,21 +1090,15 @@ static int ucsi_ccg_probe(struct i2c_client *client,
> struct device *dev = &client->dev;
> struct ucsi_ccg *uc;
> int status;
> - u16 rab;
>
> uc = devm_kzalloc(dev, sizeof(*uc), GFP_KERNEL);
> if (!uc)
> return -ENOMEM;
>
> - uc->ppm.data = devm_kzalloc(dev, sizeof(struct ucsi_data), GFP_KERNEL);
> - if (!uc->ppm.data)
> - return -ENOMEM;
> -
> - uc->ppm.cmd = ucsi_ccg_cmd;
> - uc->ppm.sync = ucsi_ccg_sync;
> uc->dev = dev;
> uc->client = client;
> mutex_init(&uc->lock);
> + init_completion(&uc->complete);
> INIT_WORK(&uc->work, ccg_update_firmware);
> INIT_WORK(&uc->pm_work, ccg_pm_workaround_work);
>
> @@ -1133,30 +1126,25 @@ static int ucsi_ccg_probe(struct i2c_client *client,
> if (uc->info.mode & CCG_DEVINFO_PDPORTS_MASK)
> uc->port_num++;
>
> + uc->ucsi = ucsi_create(dev, &ucsi_ccg_ops);
> + if (IS_ERR(uc->ucsi))
> + return PTR_ERR(uc->ucsi);
> +
> + ucsi_set_drvdata(uc->ucsi, uc);
> +
> status = request_threaded_irq(client->irq, NULL, ccg_irq_handler,
> IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
> dev_name(dev), uc);
> if (status < 0) {
> dev_err(uc->dev, "request_threaded_irq failed - %d\n", status);
> - return status;
> + goto out_ucsi_destroy;
> }
>
> uc->irq = client->irq;
>
> - uc->ucsi = ucsi_register_ppm(dev, &uc->ppm);
> - if (IS_ERR(uc->ucsi)) {
> - dev_err(uc->dev, "ucsi_register_ppm failed\n");
> - return PTR_ERR(uc->ucsi);
> - }
> -
> - rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, version));
> - status = ccg_read(uc, rab, (u8 *)(uc->ppm.data) +
> - offsetof(struct ucsi_data, version),
> - sizeof(uc->ppm.data->version));
> - if (status < 0) {
> - ucsi_unregister_ppm(uc->ucsi);
> - return status;
> - }
> + status = ucsi_register(uc->ucsi);
> + if (status)
> + goto out_free_irq;
>
> i2c_set_clientdata(client, uc);
>
> @@ -1167,6 +1155,13 @@ static int ucsi_ccg_probe(struct i2c_client *client,
> pm_runtime_idle(uc->dev);
>
> return 0;
> +
> +out_free_irq:
> + free_irq(uc->irq, uc);
> +out_ucsi_destroy:
> + ucsi_destroy(uc->ucsi);
> +
> + return status;
> }
>
> static int ucsi_ccg_remove(struct i2c_client *client)
> @@ -1175,8 +1170,9 @@ static int ucsi_ccg_remove(struct i2c_client *client)
>
> cancel_work_sync(&uc->pm_work);
> cancel_work_sync(&uc->work);
> - ucsi_unregister_ppm(uc->ucsi);
> pm_runtime_disable(uc->dev);
> + ucsi_unregister(uc->ucsi);
> + ucsi_destroy(uc->ucsi);
> free_irq(uc->irq, uc);
>
> return 0;
>
next prev parent reply other threads:[~2019-11-04 14:36 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-11-04 14:24 [PATCH v4 00/18] usb: typec: API improvements Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 01/18] usb: typec: Copy everything from struct typec_capability during registration Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 02/18] usb: typec: Introduce typec_get_drvdata() Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 03/18] usb: typec: Separate the operations vector Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 04/18] usb: typec: tcpm: Start using struct typec_operations Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 05/18] usb: typec: tps6598x: " Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 06/18] usb: typec: ucsi: " Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 07/18] usb: typec: hd3ss3220: " Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 08/18] usb: typec: Remove the callback members from struct typec_capability Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 09/18] usb: typec: Remove unused " Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 10/18] usb: typec: hd3ss3220: Give the connector fwnode to the port device Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 11/18] usb: typec: ucsi: Simplified registration and I/O API Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 12/18] usb: typec: ucsi: acpi: Move to the new API Heikki Krogerus
2019-11-04 14:35 ` Guenter Roeck
2019-11-04 18:54 ` Guenter Roeck
2019-11-05 8:46 ` Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 13/18] usb: typec: ucsi: ccg: " Heikki Krogerus
2019-11-04 14:36 ` Guenter Roeck [this message]
2019-11-04 14:24 ` [PATCH v4 14/18] usb: typec: ucsi: Remove the old API Heikki Krogerus
2019-11-04 14:38 ` Guenter Roeck
2019-11-04 14:24 ` [PATCH v4 15/18] usb: typec: ucsi: Remove struct ucsi_control Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 16/18] usb: typec: ucsi: Remove all bit-fields Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 17/18] usb: typec: ucsi: New error codes Heikki Krogerus
2019-11-04 14:41 ` Guenter Roeck
2019-11-04 14:24 ` [PATCH v4 18/18] usb: typec: ucsi: Optimise ucsi_unregister() Heikki Krogerus
2019-11-04 14:42 ` Guenter Roeck
2019-11-04 15:05 ` [PATCH v4 00/18] usb: typec: API improvements Greg Kroah-Hartman
2019-11-04 18:53 ` Guenter Roeck
2019-11-04 20:53 ` Greg Kroah-Hartman
2019-11-04 20:54 ` Greg Kroah-Hartman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1a404105-8872-7377-465c-cf792f2fad58@roeck-us.net \
--to=linux@roeck-us.net \
--cc=ajayg@nvidia.com \
--cc=gregkh@linuxfoundation.org \
--cc=heikki.krogerus@linux.intel.com \
--cc=linux-usb@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).