diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-20 11:05:40 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-20 11:05:40 -0700 |
commit | 4d230d4d030e34e6eb8911fb669d1b42298eca9e (patch) | |
tree | 99e54c3857a489ccacd2cd06dafe11caa32b8bb8 /drivers/hsi/controllers/omap_ssi_port.c | |
parent | 410b42978a241dc4a269d0d75c75d260e6d016e8 (diff) | |
parent | c2f90a465df75254fb41bf6e7975464929c21e26 (diff) | |
download | op-kernel-dev-4d230d4d030e34e6eb8911fb669d1b42298eca9e.zip op-kernel-dev-4d230d4d030e34e6eb8911fb669d1b42298eca9e.tar.gz |
Merge tag 'hsi-for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-hsi
Pull HSI updates from Sebastian Reichel:
- merge omap-ssi and omap-ssi-port modules
- fix omap-ssi module reloading
- add DVFS support to omap-ssi
* tag 'hsi-for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-hsi:
HSI: omap-ssi: move omap_ssi_port_update_fclk
HSI: omap-ssi: include pinctrl header files
HSI: omap-ssi: add COMMON_CLK dependency
HSI: omap-ssi: add clk change support
HSI: omap_ssi: built omap_ssi and omap_ssi_port into one module
HSI: omap_ssi: fix removal of port platform device
HSI: omap_ssi: make sure probe stays available
HSI: omap_ssi: fix module unloading
HSI: omap_ssi_port: switch to gpiod API
Diffstat (limited to 'drivers/hsi/controllers/omap_ssi_port.c')
-rw-r--r-- | drivers/hsi/controllers/omap_ssi_port.c | 100 |
1 files changed, 48 insertions, 52 deletions
diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c index e80a66e..6b8f773 100644 --- a/drivers/hsi/controllers/omap_ssi_port.c +++ b/drivers/hsi/controllers/omap_ssi_port.c @@ -23,8 +23,10 @@ #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/pm_runtime.h> +#include <linux/delay.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> +#include <linux/pinctrl/consumer.h> #include <linux/debugfs.h> #include "omap_ssi_regs.h" @@ -43,7 +45,7 @@ static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused) static inline unsigned int ssi_wakein(struct hsi_port *port) { struct omap_ssi_port *omap_port = hsi_port_drvdata(port); - return gpio_get_value(omap_port->wake_gpio); + return gpiod_get_value(omap_port->wake_gpio); } #ifdef CONFIG_DEBUG_FS @@ -171,7 +173,7 @@ static int ssi_div_set(void *data, u64 val) DEFINE_SIMPLE_ATTRIBUTE(ssi_sst_div_fops, ssi_div_get, ssi_div_set, "%llu\n"); -static int __init ssi_debug_add_port(struct omap_ssi_port *omap_port, +static int ssi_debug_add_port(struct omap_ssi_port *omap_port, struct dentry *dir) { struct hsi_port *port = to_hsi_port(omap_port->dev); @@ -514,6 +516,11 @@ static int ssi_flush(struct hsi_client *cl) pm_runtime_get_sync(omap_port->pdev); spin_lock_bh(&omap_port->lock); + + /* stop all ssi communication */ + pinctrl_pm_select_idle_state(omap_port->pdev); + udelay(1); /* wait for racing frames */ + /* Stop all DMA transfers */ for (i = 0; i < SSI_MAX_GDD_LCH; i++) { msg = omap_ssi->gdd_trn[i].msg; @@ -550,6 +557,10 @@ static int ssi_flush(struct hsi_client *cl) ssi_flush_queue(&omap_port->rxqueue[i], NULL); } ssi_flush_queue(&omap_port->brkqueue, NULL); + + /* Resume SSI communication */ + pinctrl_pm_select_default_state(omap_port->pdev); + spin_unlock_bh(&omap_port->lock); pm_runtime_put_sync(omap_port->pdev); @@ -1007,7 +1018,7 @@ static irqreturn_t ssi_wake_isr(int irq __maybe_unused, void *ssi_port) return IRQ_HANDLED; } -static int __init ssi_port_irq(struct hsi_port *port, +static int ssi_port_irq(struct hsi_port *port, struct platform_device *pd) { struct omap_ssi_port *omap_port = hsi_port_drvdata(port); @@ -1029,19 +1040,19 @@ static int __init ssi_port_irq(struct hsi_port *port, return err; } -static int __init ssi_wake_irq(struct hsi_port *port, +static int ssi_wake_irq(struct hsi_port *port, struct platform_device *pd) { struct omap_ssi_port *omap_port = hsi_port_drvdata(port); int cawake_irq; int err; - if (omap_port->wake_gpio == -1) { + if (!omap_port->wake_gpio) { omap_port->wake_irq = -1; return 0; } - cawake_irq = gpio_to_irq(omap_port->wake_gpio); + cawake_irq = gpiod_to_irq(omap_port->wake_gpio); omap_port->wake_irq = cawake_irq; tasklet_init(&omap_port->wake_tasklet, ssi_wake_tasklet, @@ -1060,7 +1071,7 @@ static int __init ssi_wake_irq(struct hsi_port *port, return err; } -static void __init ssi_queues_init(struct omap_ssi_port *omap_port) +static void ssi_queues_init(struct omap_ssi_port *omap_port) { unsigned int ch; @@ -1071,7 +1082,7 @@ static void __init ssi_queues_init(struct omap_ssi_port *omap_port) INIT_LIST_HEAD(&omap_port->brkqueue); } -static int __init ssi_port_get_iomem(struct platform_device *pd, +static int ssi_port_get_iomem(struct platform_device *pd, const char *name, void __iomem **pbase, dma_addr_t *phy) { struct hsi_port *port = platform_get_drvdata(pd); @@ -1104,24 +1115,19 @@ static int __init ssi_port_get_iomem(struct platform_device *pd, return 0; } -static int __init ssi_port_probe(struct platform_device *pd) +static int ssi_port_probe(struct platform_device *pd) { struct device_node *np = pd->dev.of_node; struct hsi_port *port; struct omap_ssi_port *omap_port; struct hsi_controller *ssi = dev_get_drvdata(pd->dev.parent); struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi); - int cawake_gpio = 0; + struct gpio_desc *cawake_gpio = NULL; u32 port_id; int err; dev_dbg(&pd->dev, "init ssi port...\n"); - if (!try_module_get(ssi->owner)) { - dev_err(&pd->dev, "could not increment parent module refcount\n"); - return -ENODEV; - } - if (!ssi->port || !omap_ssi->port) { dev_err(&pd->dev, "ssi controller not initialized!\n"); err = -ENODEV; @@ -1147,20 +1153,10 @@ static int __init ssi_port_probe(struct platform_device *pd) goto error; } - err = of_get_named_gpio(np, "ti,ssi-cawake-gpio", 0); - if (err < 0) { - dev_err(&pd->dev, "DT data is missing cawake gpio (err=%d)\n", - err); - goto error; - } - cawake_gpio = err; - - err = devm_gpio_request_one(&port->device, cawake_gpio, GPIOF_DIR_IN, - "cawake"); - if (err) { - dev_err(&pd->dev, "could not request cawake gpio (err=%d)!\n", - err); - err = -ENXIO; + cawake_gpio = devm_gpiod_get(&pd->dev, "ti,ssi-cawake", GPIOD_IN); + if (IS_ERR(cawake_gpio)) { + err = PTR_ERR(cawake_gpio); + dev_err(&pd->dev, "couldn't get cawake gpio (err=%d)!\n", err); goto error; } @@ -1219,8 +1215,7 @@ static int __init ssi_port_probe(struct platform_device *pd) hsi_add_clients_from_dt(port, np); - dev_info(&pd->dev, "ssi port %u successfully initialized (cawake=%d)\n", - port_id, cawake_gpio); + dev_info(&pd->dev, "ssi port %u successfully initialized\n", port_id); return 0; @@ -1228,7 +1223,7 @@ error: return err; } -static int __exit ssi_port_remove(struct platform_device *pd) +static int ssi_port_remove(struct platform_device *pd) { struct hsi_port *port = platform_get_drvdata(pd); struct omap_ssi_port *omap_port = hsi_port_drvdata(port); @@ -1253,12 +1248,28 @@ static int __exit ssi_port_remove(struct platform_device *pd) omap_ssi->port[omap_port->port_id] = NULL; platform_set_drvdata(pd, NULL); - module_put(ssi->owner); pm_runtime_disable(&pd->dev); return 0; } +static int ssi_restore_divisor(struct omap_ssi_port *omap_port) +{ + writel_relaxed(omap_port->sst.divisor, + omap_port->sst_base + SSI_SST_DIVISOR_REG); + + return 0; +} + +void omap_ssi_port_update_fclk(struct hsi_controller *ssi, + struct omap_ssi_port *omap_port) +{ + /* update divisor */ + u32 div = ssi_calculate_div(ssi); + omap_port->sst.divisor = div; + ssi_restore_divisor(omap_port); +} + #ifdef CONFIG_PM static int ssi_save_port_ctx(struct omap_ssi_port *omap_port) { @@ -1311,14 +1322,6 @@ static int ssi_restore_port_mode(struct omap_ssi_port *omap_port) return 0; } -static int ssi_restore_divisor(struct omap_ssi_port *omap_port) -{ - writel_relaxed(omap_port->sst.divisor, - omap_port->sst_base + SSI_SST_DIVISOR_REG); - - return 0; -} - static int omap_ssi_port_runtime_suspend(struct device *dev) { struct hsi_port *port = dev_get_drvdata(dev); @@ -1380,19 +1383,12 @@ MODULE_DEVICE_TABLE(of, omap_ssi_port_of_match); #define omap_ssi_port_of_match NULL #endif -static struct platform_driver ssi_port_pdriver = { - .remove = __exit_p(ssi_port_remove), +struct platform_driver ssi_port_pdriver = { + .probe = ssi_port_probe, + .remove = ssi_port_remove, .driver = { .name = "omap_ssi_port", .of_match_table = omap_ssi_port_of_match, .pm = DEV_PM_OPS, }, }; - -module_platform_driver_probe(ssi_port_pdriver, ssi_port_probe); - -MODULE_ALIAS("platform:omap_ssi_port"); -MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>"); -MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>"); -MODULE_DESCRIPTION("Synchronous Serial Interface Port Driver"); -MODULE_LICENSE("GPL v2"); |