Message ID | 1417241944-17799-1-git-send-email-muth@cypress.com |
---|---|
State | Not Applicable |
Headers | show |
> Adds support for USB-I2C/GPIO interfaces of Cypress Semiconductor > CYUSBS234 USB-Serial Bridge controller. I would like a USB Ack for this. > Details about the device can be found at: > http://www.cypress.com/?rID=84126 > > Signed-off-by: Muthu Mani <muth@cypress.com> > Signed-off-by: Rajaram Regupathy <rera@cypress.com> > --- > Changes since v3: > * Added devm_* allocation function > * Added vendor commands to read configuration info > > Changes since v2: > * Used auto mfd id to support multiple devices > * Cleaned up the code > > Changes since v1: > * Identified different serial interface and loaded correct cell driver > * Formed a mfd id to support multiple devices > * Removed unused platform device > > drivers/mfd/Kconfig | 12 +++ > drivers/mfd/Makefile | 1 + > drivers/mfd/cyusbs23x.c | 167 ++++++++++++++++++++++++++++++++++++++++++ > include/linux/mfd/cyusbs23x.h | 56 ++++++++++++++ > 4 files changed, 236 insertions(+) > create mode 100644 drivers/mfd/cyusbs23x.c > create mode 100644 include/linux/mfd/cyusbs23x.h > > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig > index 1456ea7..504d125 100644 > --- a/drivers/mfd/Kconfig > +++ b/drivers/mfd/Kconfig > @@ -116,6 +116,18 @@ config MFD_ASIC3 > This driver supports the ASIC3 multifunction chip found on many > PDAs (mainly iPAQ and HTC based ones) > > +config MFD_CYUSBS23X > + tristate "Cypress CYUSBS23x USB Serial Bridge controller" > + select MFD_CORE > + depends on USB > + default n Not sure there's a requirement for this. It's not going to magically turn itself on if not requested. > + help > + Say yes here if you want support for Cypress Semiconductor > + CYUSBS23x USB-Serial Bridge controller. > + > + This driver can also be built as a module. If so, the module will be > + called cyusbs23x. > + > config PMIC_DA903X > bool "Dialog Semiconductor DA9030/DA9034 PMIC Support" > depends on I2C=y > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile > index 8bd54b1..81c0f87 100644 > --- a/drivers/mfd/Makefile > +++ b/drivers/mfd/Makefile > @@ -151,6 +151,7 @@ si476x-core-y := si476x-cmd.o si476x-prop.o si476x-i2c.o > obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o > > obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o > +obj-$(CONFIG_MFD_CYUSBS23X) += cyusbs23x.o > obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o > obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o ssbi.o > obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o > diff --git a/drivers/mfd/cyusbs23x.c b/drivers/mfd/cyusbs23x.c > new file mode 100644 > index 0000000..bdde42f > --- /dev/null > +++ b/drivers/mfd/cyusbs23x.c > @@ -0,0 +1,167 @@ > +/* > + * Cypress USB-Serial Bridge Controller USB adapter driver > + * > + * Copyright (c) 2014 Cypress Semiconductor Corporation. > + * > + * Author: > + * Muthu Mani <muth@cypress.com> > + * > + * Additional contributors include: > + * Rajaram Regupathy <rera@cypress.com> > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License version 2 as published by > + * the Free Software Foundation. > + */ > + > +/* > + * This is core MFD driver for Cypress Semiconductor CYUSBS234 USB-Serial > + * Bridge controller. CYUSBS234 offers a single channel serial interface > + * (I2C/SPI/UART). It can be configured to enable either of I2C, SPI, UART > + * interfaces. The GPIOs are also available to access. > + * Details about the device can be found at: > + * http://www.cypress.com/?rID=84126 > + * > + * Separate cell drivers are available for I2C and GPIO. SPI and UART are not > + * supported yet. All GPIOs are exposed for get operation. However, only > + * unused GPIOs can be set. By all means put this in the commit log, but I'm not sure it lives here. Besides, we can make those assumptions by the lack of entries in the mfd_cell struct array. > + */ > + > +#include <linux/kernel.h> > +#include <linux/errno.h> > +#include <linux/module.h> > +#include <linux/slab.h> > +#include <linux/types.h> > +#include <linux/mutex.h> > +#include <linux/mfd/core.h> > +#include <linux/mfd/cyusbs23x.h> > + > +#include <linux/usb.h> Does is this separate? Please remove the '\n'. > +/* Serial interfaces (I2C, SPI, UART) differ in interface subclass */ > +enum cy_scb_modes { > + CY_USBS_SCB_DISABLED = 0, > + CY_USBS_SCB_UART = 1, > + CY_USBS_SCB_SPI = 2, > + CY_USBS_SCB_I2C = 3 Why have you numbered these individually? > +}; > + > +static const struct usb_device_id cyusbs23x_usb_table[] = { > + { USB_DEVICE(0x04b4, 0x0004) }, /* Cypress Semiconductor CYUSBS234 */ > + { } > +}; > + > +MODULE_DEVICE_TABLE(usb, cyusbs23x_usb_table); > + > +static const struct mfd_cell cyusbs23x_i2c_gpio_devs[] = { > + { > + .name = "cyusbs23x-i2c", > + }, > + { > + .name = "cyusbs23x-gpio", > + }, > +}; Please make these one line entries: { .name = "cyusbs23x-i2c", }, { .name = "cyusbs23x-gpio", }, > +static int update_ep_details(struct usb_interface *interface, > + struct cyusbs23x *cyusbs) > +{ > + struct usb_host_interface *iface_desc; > + struct usb_endpoint_descriptor *ep; > + int i; > + > + iface_desc = interface->cur_altsetting; > + > + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { > + > + ep = &iface_desc->endpoint[i].desc; > + > + if (!cyusbs->bulk_in_ep_num && usb_endpoint_is_bulk_in(ep)) > + cyusbs->bulk_in_ep_num = ep->bEndpointAddress; > + if (!cyusbs->bulk_out_ep_num && usb_endpoint_is_bulk_out(ep)) > + cyusbs->bulk_out_ep_num = ep->bEndpointAddress; > + if (!cyusbs->intr_in_ep_num && usb_endpoint_is_int_in(ep)) > + cyusbs->intr_in_ep_num = ep->bEndpointAddress; > + } > + > + dev_dbg(&interface->dev, "%s intr_in=%d, bulk_in=%d, bulk_out=%d\n", > + __func__, cyusbs->intr_in_ep_num , > + cyusbs->bulk_in_ep_num, cyusbs->bulk_out_ep_num); > + > + if (!cyusbs->bulk_in_ep_num || !cyusbs->bulk_out_ep_num || > + !cyusbs->intr_in_ep_num) { > + dev_err(&interface->dev, "%s invalid endpoints\n", __func__); > + return -ENODEV; > + } > + > + return 0; > +} > + > +static int cyusbs23x_probe(struct usb_interface *interface, > + const struct usb_device_id *id) > +{ > + struct cyusbs23x *cyusbs; > + const struct mfd_cell *cyusbs23x_devs; > + int ret, ndevs = 0; No need to pre-allocate this. It can't be used before it's initialised elsewhere. > + cyusbs = devm_kzalloc(&interface->dev, sizeof(*cyusbs), GFP_KERNEL); > + if (!cyusbs) > + return -ENOMEM; > + > + ret = update_ep_details(interface, cyusbs); > + if (ret) > + return -ENODEV; > + > + /* Serial interfaces (I2C, SPI, UART) differ in interface subclass */ > + switch (interface->cur_altsetting->desc.bInterfaceSubClass) { > + case CY_USBS_SCB_I2C: > + dev_info(&interface->dev, "using I2C interface\n"); > + cyusbs23x_devs = cyusbs23x_i2c_gpio_devs; > + ndevs = ARRAY_SIZE(cyusbs23x_i2c_gpio_devs); Not sure I get this. Why do you have local variables for these instead of using them directly? > + break; > + default: > + dev_err(&interface->dev, "unsupported subclass\n"); > + return -ENODEV; > + } > + > + cyusbs->usb_dev = usb_get_dev(interface_to_usbdev(interface)); > + cyusbs->usb_intf = interface; > + cyusbs->intf_num = interface->cur_altsetting->desc.bInterfaceNumber; If you're saving interface, you probably don't need to save this separately. > + usb_set_intfdata(interface, cyusbs); > + > + ret = mfd_add_devices(&interface->dev, PLATFORM_DEVID_AUTO, > + cyusbs23x_devs, ndevs, NULL, 0, NULL); > + if (ret) { > + dev_err(&interface->dev, "Failed to register devices\n"); > + goto error; > + } > + > + dev_info(&interface->dev, "registered MFD device\n"); Remove this line. > + return 0; > + > +error: > + usb_put_dev(cyusbs->usb_dev); Isn't there a devm_* version of usb_set_intfdata()? > + return ret; > +} > + > +static void cyusbs23x_disconnect(struct usb_interface *interface) > +{ > + struct cyusbs23x *cyusbs = usb_get_intfdata(interface); > + > + mfd_remove_devices(&interface->dev); > + usb_put_dev(cyusbs->usb_dev); > +} > + > +static struct usb_driver cyusbs23x_usb_driver = { > + .name = "cyusbs23x", > + .probe = cyusbs23x_probe, > + .disconnect = cyusbs23x_disconnect, > + .id_table = cyusbs23x_usb_table, > +}; > + > +module_usb_driver(cyusbs23x_usb_driver); > + > +MODULE_AUTHOR("Rajaram Regupathy <rera@cypress.com>"); > +MODULE_AUTHOR("Muthu Mani <muth@cypress.com>"); > +MODULE_DESCRIPTION("Cypress CYUSBS23x MFD core driver"); > +MODULE_LICENSE("GPL v2"); > diff --git a/include/linux/mfd/cyusbs23x.h b/include/linux/mfd/cyusbs23x.h > new file mode 100644 > index 0000000..534fcf7 > --- /dev/null > +++ b/include/linux/mfd/cyusbs23x.h > @@ -0,0 +1,56 @@ > +/* > + * Cypress USB-Serial Bridge Controller definitions > + * > + * Copyright (c) 2014 Cypress Semiconductor Corporation. > + * > + * Author: > + * Muthu Mani <muth@cypress.com> > + * > + * Additional contributors include: > + * Rajaram Regupathy <rera@cypress.com> > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License version 2 as published by > + * the Free Software Foundation. > + */ > + > +#ifndef __MFD_CYUSBS23X_H__ > +#define __MFD_CYUSBS23X_H__ > + > +#include <linux/types.h> > +#include <linux/usb.h> > + > +/* Structure to hold all device specific stuff */ > +struct cyusbs23x { > + struct usb_device *usb_dev; > + struct usb_interface *usb_intf; > + > + u8 intf_num; > + u8 bulk_in_ep_num; > + u8 bulk_out_ep_num; > + u8 intr_in_ep_num; > +}; > + > +enum cy_usbs_vendor_cmds { > + CY_DEV_CMD_READ_CONFIG = 0xB5, > + CY_I2C_GET_CONFIG_CMD = 0xC4, > + CY_I2C_SET_CONFIG_CMD = 0xC5, > + CY_I2C_WRITE_CMD = 0xC6, > + CY_I2C_READ_CMD = 0xC7, > + CY_I2C_GET_STATUS_CMD = 0xC8, > + CY_I2C_RESET_CMD = 0xC9, > + CY_GPIO_GET_CONFIG_CMD = 0xD8, > + CY_GPIO_SET_CONFIG_CMD = 0xD9, > + CY_GPIO_GET_VALUE_CMD = 0xDA, > + CY_GPIO_SET_VALUE_CMD = 0xDB, > + CY_DEV_ENABLE_CONFIG_READ_CMD = 0xE2 > +}; > + > +/* SCB index shift */ > +#define CY_SCB_INDEX_SHIFT 15 > + > +#define CY_USBS_CTRL_XFER_TIMEOUT 2000 > +#define CY_USBS_BULK_XFER_TIMEOUT 5000 > +#define CY_USBS_INTR_XFER_TIMEOUT 5000 > + > +#endif /* __MFD_CYUSBS23X_H__ */
Thanks for your inputs. > > +/* Serial interfaces (I2C, SPI, UART) differ in interface subclass */ > > +enum cy_scb_modes { > > + CY_USBS_SCB_DISABLED = 0, > > + CY_USBS_SCB_UART = 1, > > + CY_USBS_SCB_SPI = 2, > > + CY_USBS_SCB_I2C = 3 > > Why have you numbered these individually? I have changed them as #define's now. These values are not arbitrary. > > + /* Serial interfaces (I2C, SPI, UART) differ in interface subclass */ > > + switch (interface->cur_altsetting->desc.bInterfaceSubClass) { > > + case CY_USBS_SCB_I2C: > > + dev_info(&interface->dev, "using I2C interface\n"); > > + cyusbs23x_devs = cyusbs23x_i2c_gpio_devs; > > + ndevs = ARRAY_SIZE(cyusbs23x_i2c_gpio_devs); > > Not sure I get this. Why do you have local variables for these instead of using > them directly? We are planning to support other protocols in future. To facilitate that, local variables are used. > > + return 0; > > + > > +error: > > + usb_put_dev(cyusbs->usb_dev); > > Isn't there a devm_* version of usb_set_intfdata()? No. Thanks, Muthu This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message.
On Sat, Nov 29, 2014 at 11:49:04AM +0530, Muthu Mani wrote: > Adds support for USB-I2C/GPIO interfaces of Cypress Semiconductor > CYUSBS234 USB-Serial Bridge controller. > > Details about the device can be found at: > http://www.cypress.com/?rID=84126 > > Signed-off-by: Muthu Mani <muth@cypress.com> > Signed-off-by: Rajaram Regupathy <rera@cypress.com> > --- This patch as well as the other two patches in the series is white-space damaged. Please always make sure to run your patches through checkpatch.pl before submission (and/or fix your mailer). Also use git-send-email when submitting your series so that the individual patches get threaded properly. And always increase (or add a "resend" prefix) when resending. I got two v4 series in my inbox. No idea what's the difference, if any. Thanks, Johan -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> On Sat, Nov 29, 2014 at 11:49:04AM +0530, Muthu Mani wrote: > > Adds support for USB-I2C/GPIO interfaces of Cypress Semiconductor > > CYUSBS234 USB-Serial Bridge controller. > > > > Details about the device can be found at: > > http://www.cypress.com/?rID=84126 > > > > Signed-off-by: Muthu Mani <muth@cypress.com> > > Signed-off-by: Rajaram Regupathy <rera@cypress.com> > > --- > > This patch as well as the other two patches in the series is white-space > damaged. Please always make sure to run your patches through > checkpatch.pl before submission (and/or fix your mailer). > > Also use git-send-email when submitting your series so that the individual > patches get threaded properly. Sorry about the inconvenience. I ran checkpatch.pl for all the patches before I submitted them using git-send-email. checkpatch doesn't show any error. I used the following command to submit patch. Please let me know if anything wrong. $ git format-patch -s -n -v4 master..Driver_v4 $ git send-email --smtp-encryption=tls --smtp-server=<mail-server> --smtp-user=muth@cypress.com --smtp-server-port=<port#> --to="Samuel Ortiz <sameo@linux.intel.com>" --to="Lee Jones <lee.jones@linaro.org>" --to="Wolfram Sang <wsa@the-dreams.de>" --to="Linus Walleij <linus.walleij@linaro.org>" --to="Alexandre Courbot <gnurou@gmail.com>" --to="gregkh@linuxfoundation.org" --to="Johan Hovold <johan@kernel.org>" --cc="linux-usb@vger.kernel.org" --cc="linux-kernel@vger.kernel.org" --cc="linux-i2c@vger.kernel.org" --cc="linux-gpio@vger.kernel.org" v4-0001-mfd-add-support-for-Cypress-CYUSBS234-USB-Serial-.patch > > And always increase (or add a "resend" prefix) when resending. I got two > v4 series in my inbox. No idea what's the difference, if any. In the second v4 patch, I added Greg KH and usb group. There is no code changes. I will take care when I resend again. Thanks, Muthu > > Thanks, > Johan This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message. -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Dec 08, 2014 at 04:00:13PM +0000, Muthu Mani wrote: > > On Sat, Nov 29, 2014 at 11:49:04AM +0530, Muthu Mani wrote: > > > Adds support for USB-I2C/GPIO interfaces of Cypress Semiconductor > > > CYUSBS234 USB-Serial Bridge controller. > > > > > > Details about the device can be found at: > > > http://www.cypress.com/?rID=84126 > > > > > > Signed-off-by: Muthu Mani <muth@cypress.com> > > > Signed-off-by: Rajaram Regupathy <rera@cypress.com> > > > --- > > > > This patch as well as the other two patches in the series is white-space > > damaged. Please always make sure to run your patches through > > checkpatch.pl before submission (and/or fix your mailer). > > > > Also use git-send-email when submitting your series so that the individual > > patches get threaded properly. > > Sorry about the inconvenience. > I ran checkpatch.pl for all the patches before I submitted them using > git-send-email. > checkpatch doesn't show any error. Then the problem could be your mail server. All (leading) tabs have been converted to spaces. > I used the following command to submit patch. Please let me know if anything wrong. > $ git format-patch -s -n -v4 master..Driver_v4 > $ git send-email --smtp-encryption=tls --smtp-server=<mail-server> --smtp-user=muth@cypress.com --smtp-server-port=<port#> --to="Samuel Ortiz <sameo@linux.intel.com>" --to="Lee Jones <lee.jones@linaro.org>" --to="Wolfram Sang <wsa@the-dreams.de>" --to="Linus Walleij <linus.walleij@linaro.org>" --to="Alexandre Courbot <gnurou@gmail.com>" --to="gregkh@linuxfoundation.org" --to="Johan Hovold <johan@kernel.org>" --cc="linux-usb@vger.kernel.org" --cc="linux-kernel@vger.kernel.org" --cc="linux-i2c@vger.kernel.org" --cc="linux-gpio@vger.kernel.org" v4-0001-mfd-add-support-for-Cypress-CYUSBS234-USB-Serial-.patch Have a look at git-send-email's --thread switch. Depending on your settings you may only need to specify all three patches to git-send-email at once to have them threaded properly. > > And always increase (or add a "resend" prefix) when resending. I got two > > v4 series in my inbox. No idea what's the difference, if any. > > In the second v4 patch, I added Greg KH and usb group. There is no code changes. > I will take care when I resend again. > > Thanks, > Muthu > > > > > Thanks, > > Johan > > This message and any attachments may contain Cypress (or its > subsidiaries) confidential information. If it has been received in > error, please advise the sender and immediately delete this message. Make sure not to include such disclaimers when posting to public mailing lists. Thanks, Johan -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1456ea7..504d125 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -116,6 +116,18 @@ config MFD_ASIC3 This driver supports the ASIC3 multifunction chip found on many PDAs (mainly iPAQ and HTC based ones) +config MFD_CYUSBS23X + tristate "Cypress CYUSBS23x USB Serial Bridge controller" + select MFD_CORE + depends on USB + default n + help + Say yes here if you want support for Cypress Semiconductor + CYUSBS23x USB-Serial Bridge controller. + + This driver can also be built as a module. If so, the module will be + called cyusbs23x. + config PMIC_DA903X bool "Dialog Semiconductor DA9030/DA9034 PMIC Support" depends on I2C=y diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8bd54b1..81c0f87 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -151,6 +151,7 @@ si476x-core-y := si476x-cmd.o si476x-prop.o si476x-i2c.o obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o +obj-$(CONFIG_MFD_CYUSBS23X) += cyusbs23x.o obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o ssbi.o obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o diff --git a/drivers/mfd/cyusbs23x.c b/drivers/mfd/cyusbs23x.c new file mode 100644 index 0000000..bdde42f --- /dev/null +++ b/drivers/mfd/cyusbs23x.c @@ -0,0 +1,167 @@ +/* + * Cypress USB-Serial Bridge Controller USB adapter driver + * + * Copyright (c) 2014 Cypress Semiconductor Corporation. + * + * Author: + * Muthu Mani <muth@cypress.com> + * + * Additional contributors include: + * Rajaram Regupathy <rera@cypress.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +/* + * This is core MFD driver for Cypress Semiconductor CYUSBS234 USB-Serial + * Bridge controller. CYUSBS234 offers a single channel serial interface + * (I2C/SPI/UART). It can be configured to enable either of I2C, SPI, UART + * interfaces. The GPIOs are also available to access. + * Details about the device can be found at: + * http://www.cypress.com/?rID=84126 + * + * Separate cell drivers are available for I2C and GPIO. SPI and UART are not + * supported yet. All GPIOs are exposed for get operation. However, only + * unused GPIOs can be set. + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/types.h> +#include <linux/mutex.h> +#include <linux/mfd/core.h> +#include <linux/mfd/cyusbs23x.h> + +#include <linux/usb.h> + +/* Serial interfaces (I2C, SPI, UART) differ in interface subclass */ +enum cy_scb_modes { + CY_USBS_SCB_DISABLED = 0, + CY_USBS_SCB_UART = 1, + CY_USBS_SCB_SPI = 2, + CY_USBS_SCB_I2C = 3 +}; + +static const struct usb_device_id cyusbs23x_usb_table[] = { + { USB_DEVICE(0x04b4, 0x0004) }, /* Cypress Semiconductor CYUSBS234 */ + { } +}; + +MODULE_DEVICE_TABLE(usb, cyusbs23x_usb_table); + +static const struct mfd_cell cyusbs23x_i2c_gpio_devs[] = { + { + .name = "cyusbs23x-i2c", + }, + { + .name = "cyusbs23x-gpio", + }, +}; + +static int update_ep_details(struct usb_interface *interface, + struct cyusbs23x *cyusbs) +{ + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *ep; + int i; + + iface_desc = interface->cur_altsetting; + + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + + ep = &iface_desc->endpoint[i].desc; + + if (!cyusbs->bulk_in_ep_num && usb_endpoint_is_bulk_in(ep)) + cyusbs->bulk_in_ep_num = ep->bEndpointAddress; + if (!cyusbs->bulk_out_ep_num && usb_endpoint_is_bulk_out(ep)) + cyusbs->bulk_out_ep_num = ep->bEndpointAddress; + if (!cyusbs->intr_in_ep_num && usb_endpoint_is_int_in(ep)) + cyusbs->intr_in_ep_num = ep->bEndpointAddress; + } + + dev_dbg(&interface->dev, "%s intr_in=%d, bulk_in=%d, bulk_out=%d\n", + __func__, cyusbs->intr_in_ep_num , + cyusbs->bulk_in_ep_num, cyusbs->bulk_out_ep_num); + + if (!cyusbs->bulk_in_ep_num || !cyusbs->bulk_out_ep_num || + !cyusbs->intr_in_ep_num) { + dev_err(&interface->dev, "%s invalid endpoints\n", __func__); + return -ENODEV; + } + + return 0; +} + +static int cyusbs23x_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct cyusbs23x *cyusbs; + const struct mfd_cell *cyusbs23x_devs; + int ret, ndevs = 0; + + cyusbs = devm_kzalloc(&interface->dev, sizeof(*cyusbs), GFP_KERNEL); + if (!cyusbs) + return -ENOMEM; + + ret = update_ep_details(interface, cyusbs); + if (ret) + return -ENODEV; + + /* Serial interfaces (I2C, SPI, UART) differ in interface subclass */ + switch (interface->cur_altsetting->desc.bInterfaceSubClass) { + case CY_USBS_SCB_I2C: + dev_info(&interface->dev, "using I2C interface\n"); + cyusbs23x_devs = cyusbs23x_i2c_gpio_devs; + ndevs = ARRAY_SIZE(cyusbs23x_i2c_gpio_devs); + break; + default: + dev_err(&interface->dev, "unsupported subclass\n"); + return -ENODEV; + } + + cyusbs->usb_dev = usb_get_dev(interface_to_usbdev(interface)); + cyusbs->usb_intf = interface; + cyusbs->intf_num = interface->cur_altsetting->desc.bInterfaceNumber; + usb_set_intfdata(interface, cyusbs); + + ret = mfd_add_devices(&interface->dev, PLATFORM_DEVID_AUTO, + cyusbs23x_devs, ndevs, NULL, 0, NULL); + if (ret) { + dev_err(&interface->dev, "Failed to register devices\n"); + goto error; + } + + dev_info(&interface->dev, "registered MFD device\n"); + return 0; + +error: + usb_put_dev(cyusbs->usb_dev); + + return ret; +} + +static void cyusbs23x_disconnect(struct usb_interface *interface) +{ + struct cyusbs23x *cyusbs = usb_get_intfdata(interface); + + mfd_remove_devices(&interface->dev); + usb_put_dev(cyusbs->usb_dev); +} + +static struct usb_driver cyusbs23x_usb_driver = { + .name = "cyusbs23x", + .probe = cyusbs23x_probe, + .disconnect = cyusbs23x_disconnect, + .id_table = cyusbs23x_usb_table, +}; + +module_usb_driver(cyusbs23x_usb_driver); + +MODULE_AUTHOR("Rajaram Regupathy <rera@cypress.com>"); +MODULE_AUTHOR("Muthu Mani <muth@cypress.com>"); +MODULE_DESCRIPTION("Cypress CYUSBS23x MFD core driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/cyusbs23x.h b/include/linux/mfd/cyusbs23x.h new file mode 100644 index 0000000..534fcf7 --- /dev/null +++ b/include/linux/mfd/cyusbs23x.h @@ -0,0 +1,56 @@ +/* + * Cypress USB-Serial Bridge Controller definitions + * + * Copyright (c) 2014 Cypress Semiconductor Corporation. + * + * Author: + * Muthu Mani <muth@cypress.com> + * + * Additional contributors include: + * Rajaram Regupathy <rera@cypress.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef __MFD_CYUSBS23X_H__ +#define __MFD_CYUSBS23X_H__ + +#include <linux/types.h> +#include <linux/usb.h> + +/* Structure to hold all device specific stuff */ +struct cyusbs23x { + struct usb_device *usb_dev; + struct usb_interface *usb_intf; + + u8 intf_num; + u8 bulk_in_ep_num; + u8 bulk_out_ep_num; + u8 intr_in_ep_num; +}; + +enum cy_usbs_vendor_cmds { + CY_DEV_CMD_READ_CONFIG = 0xB5, + CY_I2C_GET_CONFIG_CMD = 0xC4, + CY_I2C_SET_CONFIG_CMD = 0xC5, + CY_I2C_WRITE_CMD = 0xC6, + CY_I2C_READ_CMD = 0xC7, + CY_I2C_GET_STATUS_CMD = 0xC8, + CY_I2C_RESET_CMD = 0xC9, + CY_GPIO_GET_CONFIG_CMD = 0xD8, + CY_GPIO_SET_CONFIG_CMD = 0xD9, + CY_GPIO_GET_VALUE_CMD = 0xDA, + CY_GPIO_SET_VALUE_CMD = 0xDB, + CY_DEV_ENABLE_CONFIG_READ_CMD = 0xE2 +}; + +/* SCB index shift */ +#define CY_SCB_INDEX_SHIFT 15 + +#define CY_USBS_CTRL_XFER_TIMEOUT 2000 +#define CY_USBS_BULK_XFER_TIMEOUT 5000 +#define CY_USBS_INTR_XFER_TIMEOUT 5000 + +#endif /* __MFD_CYUSBS23X_H__ */