Ping on this patchset > -----Original Message----- > From: Reizer, Eyal > Sent: Wednesday, December 23, 2015 1:38 PM > To: 'devicetree@xxxxxxxxxxxxxxx'; 'linux-omap@xxxxxxxxxxxxxxx'; 'linux-arm- > kernel@xxxxxxxxxxxxxxxxxxx' > Cc: 'robh+dt@xxxxxxxxxx'; 'pawel.moll@xxxxxxx'; 'mark.rutland@xxxxxxx'; > 'ijc+devicetree@xxxxxxxxxxxxxx'; 'galak@xxxxxxxxxxxxxx'; > 'tony@xxxxxxxxxxx'; 'linux@xxxxxxxxxxxxxxxx' > Subject: [PATCH 1/3] ti-st: use device handles and add device tree binding > > - Add support for getting the platform data which includes the uart > used and gpio pin used for enable from device tree. > > - Fix the implementation for using device handle for the uart and > gpiod for the enable pin, instead of device name (as string) used > for the uart and pio number which are both bad practice. > > Signed-off-by: Eyal Reizer <eyalr@xxxxxx> > --- > Documentation/devicetree/bindings/misc/ti-st.txt | 42 ++++++ > arch/arm/mach-omap2/pdata-quirks.c | 16 ++- > drivers/misc/ti-st/st_kim.c | 159 ++++++++++++++++------ > drivers/misc/ti-st/st_ll.c | 16 ++- > include/linux/ti_wilink_st.h | 13 +- > 5 files changed, 190 insertions(+), 56 deletions(-) create mode 100644 > Documentation/devicetree/bindings/misc/ti-st.txt > > diff --git a/Documentation/devicetree/bindings/misc/ti-st.txt > b/Documentation/devicetree/bindings/misc/ti-st.txt > new file mode 100644 > index 0000000..4490da6 > --- /dev/null > +++ b/Documentation/devicetree/bindings/misc/ti-st.txt > @@ -0,0 +1,42 @@ > +TI Wilink 6/7/8 (wl12xx/wl18xx) Shared transport driver > + > +TI’s Wireless Connectivity chips support Bluetooth (BT), WiFi, and GPS > +technology cores in a single die. > + > +Such a multi-core combo chip will be interfaced to the application > +processor using a single physical port (like UART). > + > +Shared Transport (ST) software enables BT and GPS protocols or software > +components to interact with their respective cores over single physical port. > +ST uses logical channels, over physical transport, to communicate with > +individual cores. > + > +Logical channels 1, 2, 3, and 4 are used for BT packets, channel 8 for > +FM, channel 9 for GPS and channels 30, 31, 32, and 33 are used for Chip > +Power Management (PM). > + > +This node provides properties for passing parameters to the ti shared > +transport driver. > + > +Required properties: > + - compatible: should be the following: > + * "kim" - ti-st parameters > + > +Optional properties: > + - nshutdown-gpios : specifies attributes for gpio ping used for enabling > + the bluetooth,gps and FM sub systems > + - serial-device : the phandle for the phisical uart used for interacting > + with the wilink device > + - flow_cntrl : Indicates if uart flow control is used > + - flow_cntrl : uart baud rate in BPS > + > +Example: > + > +kim { > + compatible = "kim"; > + nshutdown-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; > + serial-device = <&uart1>; > + flow_cntrl = <1>; > + flow_cntrl = <3000000>; > +}; > + > diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach- > omap2/pdata-quirks.c > index 5814477..b516fdc 100644 > --- a/arch/arm/mach-omap2/pdata-quirks.c > +++ b/arch/arm/mach-omap2/pdata-quirks.c > @@ -10,6 +10,7 @@ > #include <linux/clk.h> > #include <linux/davinci_emac.h> > #include <linux/gpio.h> > +#include <linux/gpio/machine.h> > #include <linux/init.h> > #include <linux/kernel.h> > #include <linux/of_platform.h> > @@ -135,11 +136,18 @@ static void __init > omap3_sbc_t3530_legacy_init(void) > omap3_sbc_t3x_usb_hub_init(167, "sb-t35 usb hub"); } > > +struct gpiod_lookup_table bt_gpios_table = { > + .dev_id = "kim", > + .table = { > + GPIO_LOOKUP("gpio4", 9, "nshutdown", GPIO_ACTIVE_HIGH), > + { }, > + }, > +}; > + > static struct ti_st_plat_data wilink_pdata = { > - .nshutdown_gpio = 137, > - .dev_name = "/dev/ttyO1", > + .dev_addr = 0x48022000, /* uart1 */ > .flow_cntrl = 1, > - .baud_rate = 300000, > + .baud_rate = 3000000, > }; > > static struct platform_device wl18xx_device = { @@ -157,12 +165,14 @@ > static struct platform_device btwilink_device = { > > static void __init omap3_igep0020_rev_f_legacy_init(void) > { > + gpiod_add_lookup_table(&bt_gpios_table); > platform_device_register(&wl18xx_device); > platform_device_register(&btwilink_device); > } > > static void __init omap3_igep0030_rev_g_legacy_init(void) > { > + gpiod_add_lookup_table(&bt_gpios_table); > platform_device_register(&wl18xx_device); > platform_device_register(&btwilink_device); > } > diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index > 71b6455..61d4f054 100644 > --- a/drivers/misc/ti-st/st_kim.c > +++ b/drivers/misc/ti-st/st_kim.c > @@ -36,6 +36,8 @@ > #include <linux/skbuff.h> > #include <linux/ti_wilink_st.h> > #include <linux/module.h> > +#include <linux/of.h> > +#include <linux/of_device.h> > > #define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */ > static struct platform_device *st_kim_devices[MAX_ST_DEVICES]; @@ -43,6 > +45,9 @@ static struct platform_device *st_kim_devices[MAX_ST_DEVICES]; > /*********************************************************** > ***********/ > /* internal functions */ > > +struct ti_st_plat_data *dt_pdata; > +static struct ti_st_plat_data *get_platform_data(struct device *dev); > + > /** > * st_get_plat_device - > * function which returns the reference to the platform device > @@ -464,7 +469,12 @@ long st_kim_start(void *kim_data) > struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; > > pr_info(" %s", __func__); > - pdata = kim_gdata->kim_pdev->dev.platform_data; > + if (kim_gdata->kim_pdev->dev.of_node) { > + pr_debug("use device tree data"); > + pdata = dt_pdata; > + } else { > + pdata = kim_gdata->kim_pdev->dev.platform_data; > + } > > do { > /* platform specific enabling code here */ @@ -472,9 +482,9 > @@ long st_kim_start(void *kim_data) > pdata->chip_enable(kim_gdata); > > /* Configure BT nShutdown to HIGH state */ > - gpio_set_value_cansleep(kim_gdata->nshutdown, > GPIO_LOW); > + gpiod_set_value_cansleep(kim_gdata->nshutdown, > GPIO_LOW); > mdelay(5); /* FIXME: a proper toggle */ > - gpio_set_value_cansleep(kim_gdata->nshutdown, > GPIO_HIGH); > + gpiod_set_value_cansleep(kim_gdata->nshutdown, > GPIO_HIGH); > mdelay(100); > /* re-initialize the completion */ > reinit_completion(&kim_gdata->ldisc_installed); > @@ -524,11 +534,15 @@ long st_kim_stop(void *kim_data) { > long err = 0; > struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; > - struct ti_st_plat_data *pdata = > - kim_gdata->kim_pdev->dev.platform_data; > + struct ti_st_plat_data *pdata; > struct tty_struct *tty = kim_gdata->core_data->tty; > > reinit_completion(&kim_gdata->ldisc_installed); > + if (kim_gdata->kim_pdev->dev.of_node) { > + pr_debug("use device tree data"); > + pdata = dt_pdata; > + } else > + pdata = kim_gdata->kim_pdev->dev.platform_data; > > if (tty) { /* can be called before ldisc is installed */ > /* Flush any pending characters in the driver and discipline. > */ @@ -550,11 +564,11 @@ long st_kim_stop(void *kim_data) > } > > /* By default configure BT nShutdown to LOW state */ > - gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW); > + gpiod_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW); > mdelay(1); > - gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_HIGH); > + gpiod_set_value_cansleep(kim_gdata->nshutdown, GPIO_HIGH); > mdelay(1); > - gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW); > + gpiod_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW); > > /* platform specific disable */ > if (pdata->chip_disable) > @@ -590,32 +604,43 @@ static ssize_t show_install(struct device *dev, } > > #ifdef DEBUG > -static ssize_t store_dev_name(struct device *dev, > - struct device_attribute *attr, const char *buf, size_t count) > +static ssize_t store_dev_addr(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t count) > { > + int rc; > + > struct kim_data_s *kim_data = dev_get_drvdata(dev); > - pr_debug("storing dev name >%s<", buf); > - strncpy(kim_data->dev_name, buf, count); > - pr_debug("stored dev name >%s<", kim_data->dev_name); > + pr_debug("storing dev address >%s<", buf); > + rc = kstrtou32(buf, 0, &kim_data->dev_addr); > + if (rc) > + return rc; > + > + pr_debug("stored dev address >%x<", kim_data->dev_addr); > return count; > } > > static ssize_t store_baud_rate(struct device *dev, > struct device_attribute *attr, const char *buf, size_t count) { > + int rc; > + > struct kim_data_s *kim_data = dev_get_drvdata(dev); > pr_debug("storing baud rate >%s<", buf); > - sscanf(buf, "%ld", &kim_data->baud_rate); > - pr_debug("stored baud rate >%ld<", kim_data->baud_rate); > + rc = kstrtou32(buf, 0, &kim_data->baud_rate); > + if (rc) > + return rc; > + > + pr_debug("stored baud rate >%x<", kim_data->baud_rate); > return count; > } > #endif /* if DEBUG */ > > -static ssize_t show_dev_name(struct device *dev, > - struct device_attribute *attr, char *buf) > +static ssize_t show_dev_addr(struct device *dev, > + struct device_attribute *attr, char *buf) > { > struct kim_data_s *kim_data = dev_get_drvdata(dev); > - return sprintf(buf, "%s\n", kim_data->dev_name); > + return sprintf(buf, "%x\n", kim_data->dev_addr); > } > > static ssize_t show_baud_rate(struct device *dev, @@ -636,11 +661,11 @@ > static ssize_t show_flow_cntrl(struct device *dev, static struct kobj_attribute > ldisc_install = __ATTR(install, 0444, (void *)show_install, NULL); > > -static struct kobj_attribute uart_dev_name = > +static struct kobj_attribute uart_dev_addr = > #ifdef DEBUG /* TODO: move this to debug-fs if possible */ > -__ATTR(dev_name, 0644, (void *)show_dev_name, (void > *)store_dev_name); > +__ATTR(dev_addr, 0644, (void *)show_dev_addr, (void *)store_dev_addr); > #else > -__ATTR(dev_name, 0444, (void *)show_dev_name, NULL); > +__ATTR(dev_addr, 0444, (void *)show_dev_addr, NULL); > #endif > > static struct kobj_attribute uart_baud_rate = @@ -655,7 +680,7 @@ > __ATTR(flow_cntrl, 0444, (void *)show_flow_cntrl, NULL); > > static struct attribute *uim_attrs[] = { > &ldisc_install.attr, > - &uart_dev_name.attr, > + &uart_dev_addr.attr, > &uart_baud_rate.attr, > &uart_flow_cntrl.attr, > NULL, > @@ -721,13 +746,54 @@ static const struct file_operations > list_debugfs_fops = { > * board-*.c file > */ > > +static const struct of_device_id kim_of_match[] = { { > + .compatible = "kim", > + }, > + {} > +}; > +MODULE_DEVICE_TABLE(of, kim_of_match); > + > +static struct ti_st_plat_data *get_platform_data(struct device *dev) { > + struct device_node *np = dev->of_node; > + struct device_node *serial_node; > + > + dt_pdata = kzalloc(sizeof(*dt_pdata), GFP_KERNEL); > + if (!dt_pdata) > + return NULL; > + > + serial_node = of_parse_phandle(np, "serial-device", 0); > + if (serial_node) { > + pr_info("using serial device %s\n", serial_node->full_name); > + of_property_read_u32(serial_node, "reg", &dt_pdata- > >dev_addr); > + } else { > + dev_err(dev, "Serial device missing"); > + } > + > + of_property_read_u32(np, "flow_cntrl", &dt_pdata->flow_cntrl); > + of_property_read_u32(np, "baud_rate", &dt_pdata->baud_rate); > + > + return dt_pdata; > +} > + > static struct dentry *kim_debugfs_dir; > static int kim_probe(struct platform_device *pdev) { > struct kim_data_s *kim_gdata; > - struct ti_st_plat_data *pdata = pdev->dev.platform_data; > + struct ti_st_plat_data *pdata; > int err; > > + if (pdev->dev.of_node) > + pdata = get_platform_data(&pdev->dev); > + else > + pdata = pdev->dev.platform_data; > + > + if (!pdata) { > + dev_err(&pdev->dev, "Platform Data is missing\n"); > + return -ENXIO; > + } > + > if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) { > /* multiple devices could exist */ > st_kim_devices[pdev->id] = pdev; > @@ -735,7 +801,6 @@ static int kim_probe(struct platform_device *pdev) > /* platform's sure about existence of 1 device */ > st_kim_devices[0] = pdev; > } > - > kim_gdata = kzalloc(sizeof(struct kim_data_s), GFP_ATOMIC); > if (!kim_gdata) { > pr_err("no mem to allocate"); > @@ -753,19 +818,14 @@ static int kim_probe(struct platform_device > *pdev) > kim_gdata->core_data->kim_data = kim_gdata; > > /* Claim the chip enable nShutdown gpio from the system */ > - kim_gdata->nshutdown = pdata->nshutdown_gpio; > - err = gpio_request(kim_gdata->nshutdown, "kim"); > - if (unlikely(err)) { > - pr_err(" gpio %d request failed ", kim_gdata->nshutdown); > - return err; > + kim_gdata->nshutdown = devm_gpiod_get(&pdev->dev, > "nshutdown", > + GPIOD_OUT_HIGH); > + if (IS_ERR(kim_gdata->nshutdown)) { > + err = PTR_ERR(kim_gdata->nshutdown); > + dev_err(&pdev->dev, "unable to claim gpio > \"nshutdown\"\n"); > + goto err_core_init; > } > > - /* Configure nShutdown GPIO as output=0 */ > - err = gpio_direction_output(kim_gdata->nshutdown, 0); > - if (unlikely(err)) { > - pr_err(" unable to configure gpio %d", kim_gdata- > >nshutdown); > - return err; > - } > /* get reference of pdev for request_firmware > */ > kim_gdata->kim_pdev = pdev; > @@ -779,7 +839,7 @@ static int kim_probe(struct platform_device *pdev) > } > > /* copying platform data */ > - strncpy(kim_gdata->dev_name, pdata->dev_name, > UART_DEV_NAME_LEN); > + kim_gdata->dev_addr = pdata->dev_addr; > kim_gdata->flow_cntrl = pdata->flow_cntrl; > kim_gdata->baud_rate = pdata->baud_rate; > pr_info("sysfs entries created\n"); > @@ -808,16 +868,17 @@ err_core_init: > static int kim_remove(struct platform_device *pdev) { > /* free the GPIOs requested */ > - struct ti_st_plat_data *pdata = pdev->dev.platform_data; > + struct ti_st_plat_data *pdata; > struct kim_data_s *kim_gdata; > > - kim_gdata = platform_get_drvdata(pdev); > + if (pdev->dev.of_node) { > + pr_debug("use device tree data"); > + pdata = dt_pdata; > + } else { > + pdata = pdev->dev.platform_data; > + } > > - /* Free the Bluetooth/FM/GPIO > - * nShutdown gpio from the system > - */ > - gpio_free(pdata->nshutdown_gpio); > - pr_info("nshutdown GPIO Freed"); > + kim_gdata = platform_get_drvdata(pdev); > > debugfs_remove_recursive(kim_debugfs_dir); > sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); @@ -828,12 > +889,21 @@ static int kim_remove(struct platform_device *pdev) > > kfree(kim_gdata); > kim_gdata = NULL; > + kfree(dt_pdata); > + dt_pdata = NULL; > return 0; > } > > static int kim_suspend(struct platform_device *pdev, pm_message_t state) { > - struct ti_st_plat_data *pdata = pdev->dev.platform_data; > + struct ti_st_plat_data *pdata; > + > + if (pdev->dev.of_node) { > + pr_debug("use device tree data"); > + pdata = dt_pdata; > + } else { > + pdata = pdev->dev.platform_data; > + } > > if (pdata->suspend) > return pdata->suspend(pdev, state); > @@ -860,6 +930,7 @@ static struct platform_driver kim_platform_driver = { > .resume = kim_resume, > .driver = { > .name = "kim", > + .of_match_table = of_match_ptr(kim_of_match), > }, > }; > > diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c index > 93b4d67..d68b427 100644 > --- a/drivers/misc/ti-st/st_ll.c > +++ b/drivers/misc/ti-st/st_ll.c > @@ -53,7 +53,13 @@ static void ll_device_want_to_sleep(struct st_data_s > *st_data) > > /* communicate to platform about chip asleep */ > kim_data = st_data->kim_data; > - pdata = kim_data->kim_pdev->dev.platform_data; > + if (kim_data->kim_pdev->dev.of_node) { > + pr_debug("use device tree data"); > + pdata = dt_pdata; > + } else { > + pdata = kim_data->kim_pdev->dev.platform_data; > + } > + > if (pdata->chip_asleep) > pdata->chip_asleep(NULL); > } > @@ -86,7 +92,13 @@ static void ll_device_want_to_wakeup(struct st_data_s > *st_data) > > /* communicate to platform about chip wakeup */ > kim_data = st_data->kim_data; > - pdata = kim_data->kim_pdev->dev.platform_data; > + if (kim_data->kim_pdev->dev.of_node) { > + pr_debug("use device tree data"); > + pdata = dt_pdata; > + } else { > + pdata = kim_data->kim_pdev->dev.platform_data; > + } > + > if (pdata->chip_awake) > pdata->chip_awake(NULL); > } > diff --git a/include/linux/ti_wilink_st.h b/include/linux/ti_wilink_st.h index > 0a0d568..e01e530 100644 > --- a/include/linux/ti_wilink_st.h > +++ b/include/linux/ti_wilink_st.h > @@ -86,6 +86,7 @@ struct st_proto_s { > extern long st_register(struct st_proto_s *); extern long st_unregister(struct > st_proto_s *); > > +extern struct ti_st_plat_data *dt_pdata; > > /* > * header information used by st_core.c @@ -206,7 +207,7 @@ void > gps_chrdrv_stub_init(void); > /* time in msec to wait for > * line discipline to be installed > */ > -#define LDISC_TIME 1000 > +#define LDISC_TIME 1500 > #define CMD_RESP_TIME 800 > #define CMD_WR_TIME 5000 > #define MAKEWORD(a, b) ((unsigned short)(((unsigned char)(a)) \ @@ - > 231,7 +232,6 @@ struct chip_version { > unsigned short maj_ver; > }; > > -#define UART_DEV_NAME_LEN 32 > /** > * struct kim_data_s - the KIM internal data, embedded as the > * platform's drv data. One for each ST device in the system. > @@ -262,14 +262,14 @@ struct kim_data_s { > struct completion kim_rcvd, ldisc_installed; > char resp_buffer[30]; > const struct firmware *fw_entry; > - unsigned nshutdown; > + struct gpio_desc *nshutdown; > unsigned long rx_state; > unsigned long rx_count; > struct sk_buff *rx_skb; > struct st_data_s *core_data; > struct chip_version version; > unsigned char ldisc_install; > - unsigned char dev_name[UART_DEV_NAME_LEN + 1]; > + unsigned dev_addr; > unsigned flow_cntrl; > unsigned baud_rate; > }; > @@ -418,7 +418,7 @@ struct gps_event_hdr { > * struct ti_st_plat_data - platform data shared between ST driver and > * platform specific board file which adds the ST device. > * @nshutdown_gpio: Host's GPIO line to which chip's BT_EN is connected. > - * @dev_name: The UART/TTY name to which chip is interfaced. (eg: > /dev/ttyS1) > + * @dev_addr: Memory address of UART peripheral to which chip is > + interfaced > * @flow_cntrl: Should always be 1, since UART's CTS/RTS is used for PM > * purposes. > * @baud_rate: The baud rate supported by the Host UART controller, this > will @@ -437,8 +437,7 @@ struct gps_event_hdr { > * > */ > struct ti_st_plat_data { > - u32 nshutdown_gpio; > - unsigned char dev_name[UART_DEV_NAME_LEN]; /* uart name */ > + u32 dev_addr; /* uart address */ > u32 flow_cntrl; /* flow control flag */ > u32 baud_rate; > int (*suspend)(struct platform_device *, pm_message_t); > -- > 1.7.9.5 ��.n��������+%������w��{.n����z�{��ܨ}���Ơz�j:+v�����w����ޙ��&�)ߡ�a����z�ޗ���ݢj��w�f