forked from Minki/linux
HSI changes for the v4.7 series
* merge omap-ssi and omap-ssi-port modules * fix omap-ssi module reloading * add DVFS support to omap-ssi -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCgAGBQJXPpJpAAoJENju1/PIO/qaRWQP/ia/qFECRFiObARtny5zUtMS NX/QIXz96XozP0BhP58yS/qXP2N+RUZzXuft8NnlIgM7xcOScUu07WL3nPZ7sQO/ QI7NL3NJtuh2UWKFa6mjEZiHkprM/qvcGPu2cY4SLGGczNbKBESBdnl0wUUHftqg vSoRtr8mK1zVPFCpoKOFcZkVq2mhzU6re5CxXwwRCsM55qwtaaQkBk2qzn9ZkQvm AVB39zh8QitpIZbJtM45ZHkoVzq12MuqYXvLXO7wUUxrS2A9aZn//J+D7UEc5e4l QArC+N71wLCioYqGQXvKDUWsPybjtIT0CLljaXVyRn+3ZHoCrWrbNRVz7bU28HQo gXM0BhDuexdZsWE6aWvlmSBr1jFi1Hwp7POyYHLwTKpqUmJTbEd+F/HP9UxkVMpo d9j0wiIziTeRYvQ/o0maFkkARQkirJGv+zL1nZr5Q7q4WqdXNd7MDwN6qsi2QAD5 EkJpsetllH8e5JZqT4drFMtAOypgstSpzuU5EuyL5EO6ES7apzGQhNGW+cWlVtCb 8J0HYpa3T39ekNPIWbuHcGatKJYdPZVlLnDAZiQRjdhGAahS1i52MwjIlB68AWoc hYGAccDdwgarjp+ce5QFu6cGiX2jOt7zgO1PhQAXY8Yzt9q7PJPaR8mxdxUNiCvv KZ2DzE1GRlBD1TP+NMQc =4zdt -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
4d230d4d03
@ -5,15 +5,11 @@ comment "HSI controllers"
|
||||
|
||||
config OMAP_SSI
|
||||
tristate "OMAP SSI hardware driver"
|
||||
depends on HSI && OF && (ARCH_OMAP3 || (ARM && COMPILE_TEST))
|
||||
depends on HSI && OF && ARM && COMMON_CLK
|
||||
depends on ARCH_OMAP3 || COMPILE_TEST
|
||||
---help---
|
||||
SSI is a legacy version of HSI. It is usually used to connect
|
||||
an application engine with a cellular modem.
|
||||
If you say Y here, you will enable the OMAP SSI hardware driver.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config OMAP_SSI_PORT
|
||||
tristate
|
||||
default m if OMAP_SSI=m
|
||||
default y if OMAP_SSI=y
|
||||
|
@ -2,5 +2,5 @@
|
||||
# Makefile for HSI controllers drivers
|
||||
#
|
||||
|
||||
obj-$(CONFIG_OMAP_SSI) += omap_ssi.o
|
||||
obj-$(CONFIG_OMAP_SSI_PORT) += omap_ssi_port.o
|
||||
omap_ssi-objs += omap_ssi_core.o omap_ssi_port.o
|
||||
obj-$(CONFIG_OMAP_SSI) += omap_ssi.o
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/hsi/hsi.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
@ -97,7 +97,7 @@ struct omap_ssi_port {
|
||||
struct list_head brkqueue;
|
||||
unsigned int irq;
|
||||
int wake_irq;
|
||||
int wake_gpio;
|
||||
struct gpio_desc *wake_gpio;
|
||||
struct tasklet_struct pio_tasklet;
|
||||
struct tasklet_struct wake_tasklet;
|
||||
bool wktest:1; /* FIXME: HACK to be removed */
|
||||
@ -134,6 +134,8 @@ struct gdd_trn {
|
||||
* @gdd_tasklet: bottom half for DMA transfers
|
||||
* @gdd_trn: Array of GDD transaction data for ongoing GDD transfers
|
||||
* @lock: lock to serialize access to GDD
|
||||
* @fck_nb: DVFS notfifier block
|
||||
* @fck_rate: clock rate
|
||||
* @loss_count: To follow if we need to restore context or not
|
||||
* @max_speed: Maximum TX speed (Kb/s) set by the clients.
|
||||
* @sysconfig: SSI controller saved context
|
||||
@ -151,6 +153,7 @@ struct omap_ssi_controller {
|
||||
struct tasklet_struct gdd_tasklet;
|
||||
struct gdd_trn gdd_trn[SSI_MAX_GDD_LCH];
|
||||
spinlock_t lock;
|
||||
struct notifier_block fck_nb;
|
||||
unsigned long fck_rate;
|
||||
u32 loss_count;
|
||||
u32 max_speed;
|
||||
@ -164,4 +167,9 @@ struct omap_ssi_controller {
|
||||
#endif
|
||||
};
|
||||
|
||||
void omap_ssi_port_update_fclk(struct hsi_controller *ssi,
|
||||
struct omap_ssi_port *omap_port);
|
||||
|
||||
extern struct platform_driver ssi_port_pdriver;
|
||||
|
||||
#endif /* __LINUX_HSI_OMAP_SSI_H__ */
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -36,6 +35,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/hsi/hsi.h>
|
||||
@ -141,7 +141,7 @@ static const struct file_operations ssi_gdd_regs_fops = {
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int __init ssi_debug_add_ctrl(struct hsi_controller *ssi)
|
||||
static int ssi_debug_add_ctrl(struct hsi_controller *ssi)
|
||||
{
|
||||
struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
|
||||
struct dentry *dir;
|
||||
@ -291,7 +291,65 @@ static unsigned long ssi_get_clk_rate(struct hsi_controller *ssi)
|
||||
return rate;
|
||||
}
|
||||
|
||||
static int __init ssi_get_iomem(struct platform_device *pd,
|
||||
static int ssi_clk_event(struct notifier_block *nb, unsigned long event,
|
||||
void *data)
|
||||
{
|
||||
struct omap_ssi_controller *omap_ssi = container_of(nb,
|
||||
struct omap_ssi_controller, fck_nb);
|
||||
struct hsi_controller *ssi = to_hsi_controller(omap_ssi->dev);
|
||||
struct clk_notifier_data *clk_data = data;
|
||||
struct omap_ssi_port *omap_port;
|
||||
int i;
|
||||
|
||||
switch (event) {
|
||||
case PRE_RATE_CHANGE:
|
||||
dev_dbg(&ssi->device, "pre rate change\n");
|
||||
|
||||
for (i = 0; i < ssi->num_ports; i++) {
|
||||
omap_port = omap_ssi->port[i];
|
||||
|
||||
if (!omap_port)
|
||||
continue;
|
||||
|
||||
/* Workaround for SWBREAK + CAwake down race in CMT */
|
||||
tasklet_disable(&omap_port->wake_tasklet);
|
||||
|
||||
/* stop all ssi communication */
|
||||
pinctrl_pm_select_idle_state(omap_port->pdev);
|
||||
udelay(1); /* wait for racing frames */
|
||||
}
|
||||
|
||||
break;
|
||||
case ABORT_RATE_CHANGE:
|
||||
dev_dbg(&ssi->device, "abort rate change\n");
|
||||
/* Fall through */
|
||||
case POST_RATE_CHANGE:
|
||||
dev_dbg(&ssi->device, "post rate change (%lu -> %lu)\n",
|
||||
clk_data->old_rate, clk_data->new_rate);
|
||||
omap_ssi->fck_rate = DIV_ROUND_CLOSEST(clk_data->new_rate, 1000); /* KHz */
|
||||
|
||||
for (i = 0; i < ssi->num_ports; i++) {
|
||||
omap_port = omap_ssi->port[i];
|
||||
|
||||
if (!omap_port)
|
||||
continue;
|
||||
|
||||
omap_ssi_port_update_fclk(ssi, omap_port);
|
||||
|
||||
/* resume ssi communication */
|
||||
pinctrl_pm_select_default_state(omap_port->pdev);
|
||||
tasklet_enable(&omap_port->wake_tasklet);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int ssi_get_iomem(struct platform_device *pd,
|
||||
const char *name, void __iomem **pbase, dma_addr_t *phy)
|
||||
{
|
||||
struct resource *mem;
|
||||
@ -311,7 +369,7 @@ static int __init ssi_get_iomem(struct platform_device *pd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init ssi_add_controller(struct hsi_controller *ssi,
|
||||
static int ssi_add_controller(struct hsi_controller *ssi,
|
||||
struct platform_device *pd)
|
||||
{
|
||||
struct omap_ssi_controller *omap_ssi;
|
||||
@ -370,6 +428,10 @@ static int __init ssi_add_controller(struct hsi_controller *ssi,
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
omap_ssi->fck_nb.notifier_call = ssi_clk_event;
|
||||
omap_ssi->fck_nb.priority = INT_MAX;
|
||||
clk_notifier_register(omap_ssi->fck, &omap_ssi->fck_nb);
|
||||
|
||||
/* TODO: find register, which can be used to detect context loss */
|
||||
omap_ssi->get_loss = NULL;
|
||||
|
||||
@ -387,7 +449,7 @@ out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __init ssi_hw_init(struct hsi_controller *ssi)
|
||||
static int ssi_hw_init(struct hsi_controller *ssi)
|
||||
{
|
||||
struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
|
||||
unsigned int i;
|
||||
@ -433,6 +495,7 @@ static void ssi_remove_controller(struct hsi_controller *ssi)
|
||||
int id = ssi->id;
|
||||
tasklet_kill(&omap_ssi->gdd_tasklet);
|
||||
hsi_unregister_controller(ssi);
|
||||
clk_notifier_unregister(omap_ssi->fck, &omap_ssi->fck_nb);
|
||||
ida_simple_remove(&platform_omap_ssi_ida, id);
|
||||
}
|
||||
|
||||
@ -452,12 +515,16 @@ static int ssi_remove_ports(struct device *dev, void *c)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
if (!dev->of_node)
|
||||
return 0;
|
||||
|
||||
of_node_clear_flag(dev->of_node, OF_POPULATED);
|
||||
of_device_unregister(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init ssi_probe(struct platform_device *pd)
|
||||
static int ssi_probe(struct platform_device *pd)
|
||||
{
|
||||
struct platform_device *childpdev;
|
||||
struct device_node *np = pd->dev.of_node;
|
||||
@ -523,10 +590,13 @@ out1:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __exit ssi_remove(struct platform_device *pd)
|
||||
static int ssi_remove(struct platform_device *pd)
|
||||
{
|
||||
struct hsi_controller *ssi = platform_get_drvdata(pd);
|
||||
|
||||
/* cleanup of of_platform_populate() call */
|
||||
device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
ssi_debug_remove_ctrl(ssi);
|
||||
#endif
|
||||
@ -535,9 +605,6 @@ static int __exit ssi_remove(struct platform_device *pd)
|
||||
|
||||
pm_runtime_disable(&pd->dev);
|
||||
|
||||
/* cleanup of of_platform_populate() call */
|
||||
device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -593,7 +660,8 @@ MODULE_DEVICE_TABLE(of, omap_ssi_of_match);
|
||||
#endif
|
||||
|
||||
static struct platform_driver ssi_pdriver = {
|
||||
.remove = __exit_p(ssi_remove),
|
||||
.probe = ssi_probe,
|
||||
.remove = ssi_remove,
|
||||
.driver = {
|
||||
.name = "omap_ssi",
|
||||
.pm = DEV_PM_OPS,
|
||||
@ -601,7 +669,22 @@ static struct platform_driver ssi_pdriver = {
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver_probe(ssi_pdriver, ssi_probe);
|
||||
static int __init ssi_init(void) {
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&ssi_pdriver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return platform_driver_register(&ssi_port_pdriver);
|
||||
}
|
||||
module_init(ssi_init);
|
||||
|
||||
static void __exit ssi_exit(void) {
|
||||
platform_driver_unregister(&ssi_port_pdriver);
|
||||
platform_driver_unregister(&ssi_pdriver);
|
||||
}
|
||||
module_exit(ssi_exit);
|
||||
|
||||
MODULE_ALIAS("platform:omap_ssi");
|
||||
MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user