Commit 8448cefe authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'hsi-for-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-hsi

Pull HSI updates from Sebastian Reichel:

 - proper runtime pm support for omap-ssi and ssi-protocol

 - misc fixes

* tag 'hsi-for-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-hsi: (24 commits)
  HSI: omap_ssi: drop pm_runtime_irq_safe
  HSI: omap_ssi_port: use rpm autosuspend API
  HSI: omap_ssi: call msg->complete() from process context
  HSI: omap_ssi_port: ensure clocks are kept enabled during transfer
  HSI: omap_ssi_port: replace pm_runtime_put_sync with non-sync variant
  HSI: omap_ssi_port: avoid calling runtime_pm_*_sync inside spinlock
  HSI: omap_ssi_port: avoid pm_runtime_get_sync in ssi_start_dma and ssi_start_pio
  HSI: omap_ssi_port: switch to threaded pio irq
  HSI: omap_ssi_core: remove pm_runtime_get_sync call from tasklet
  HSI: omap_ssi_core: use pm_runtime_put instead of pm_runtime_put_sync
  HSI: omap_ssi_port: prepare start_tx/stop_tx for blocking pm_runtime calls
  HSI: core: switch port event notifier from atomic to blocking
  HSI: omap_ssi_port: replace wkin_cken with atomic bitmap operations
  HSI: omap_ssi: convert cawake irq handler to thread
  HSI: ssi_protocol: fix ssip_xmit invocation
  HSI: ssi_protocol: replace spin_lock with spin_lock_bh
  HSI: ssi_protocol: avoid ssi_waketest call with held spinlock
  HSI: omap_ssi: do not reset module
  HSI: omap_ssi_port: remove useless newline
  hsi: Only descend into hsi directory when CONFIG_HSI is set
  ...
parents 818e607b 9c99e5e5
......@@ -484,7 +484,7 @@ X!Ilib/fonts/fonts.c
</para>
!Iinclude/linux/hsi/hsi.h
!Edrivers/hsi/hsi.c
!Edrivers/hsi/hsi_core.c
</chapter>
<chapter id="pwm">
......
......@@ -78,7 +78,7 @@ obj-$(CONFIG_TARGET_CORE) += target/
obj-$(CONFIG_MTD) += mtd/
obj-$(CONFIG_SPI) += spi/
obj-$(CONFIG_SPMI) += spmi/
obj-y += hsi/
obj-$(CONFIG_HSI) += hsi/
obj-y += net/
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_FUSION) += message/
......
#
# Makefile for HSI
#
obj-$(CONFIG_HSI_BOARDINFO) += hsi_boardinfo.o
obj-$(CONFIG_HSI) += hsi.o
hsi-objs := hsi_core.o
hsi-$(CONFIG_HSI_BOARDINFO) += hsi_boardinfo.o
obj-y += controllers/
obj-y += clients/
......@@ -444,8 +444,8 @@ static void cs_hsi_read_on_control_complete(struct hsi_msg *msg)
hi->control_state &= ~SSI_CHANNEL_STATE_READING;
if (msg->status == HSI_STATUS_ERROR) {
dev_err(&hi->cl->device, "Control RX error detected\n");
cs_hsi_control_read_error(hi, msg);
spin_unlock(&hi->lock);
cs_hsi_control_read_error(hi, msg);
goto out;
}
dev_dbg(&hi->cl->device, "Read on control: %08X\n", cmd);
......@@ -1275,7 +1275,7 @@ static int cs_char_mmap(struct file *file, struct vm_area_struct *vma)
if (vma->vm_end < vma->vm_start)
return -EINVAL;
if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) != 1)
if (vma_pages(vma) != 1)
return -EINVAL;
vma->vm_flags |= VM_IO | VM_DONTDUMP | VM_DONTEXPAND;
......
......@@ -88,6 +88,8 @@ void ssi_waketest(struct hsi_client *cl, unsigned int enable);
#define SSIP_READY_CMD SSIP_CMD(SSIP_READY, 0)
#define SSIP_SWBREAK_CMD SSIP_CMD(SSIP_SW_BREAK, 0)
#define SSIP_WAKETEST_FLAG 0
/* Main state machine states */
enum {
INIT,
......@@ -116,7 +118,7 @@ enum {
* @main_state: Main state machine
* @send_state: TX state machine
* @recv_state: RX state machine
* @waketest: Flag to follow wake line test
* @flags: Flags, currently only used to follow wake line test
* @rxid: RX data id
* @txid: TX data id
* @txqueue_len: TX queue length
......@@ -137,7 +139,7 @@ struct ssi_protocol {
unsigned int main_state;
unsigned int send_state;
unsigned int recv_state;
unsigned int waketest:1;
unsigned long flags;
u8 rxid;
u8 txid;
unsigned int txqueue_len;
......@@ -148,6 +150,7 @@ struct ssi_protocol {
struct net_device *netdev;
struct list_head txqueue;
struct list_head cmdqueue;
struct work_struct work;
struct hsi_client *cl;
struct list_head link;
atomic_t tx_usecnt;
......@@ -405,15 +408,17 @@ static void ssip_reset(struct hsi_client *cl)
spin_lock_bh(&ssi->lock);
if (ssi->send_state != SEND_IDLE)
hsi_stop_tx(cl);
if (ssi->waketest)
ssi_waketest(cl, 0);
spin_unlock_bh(&ssi->lock);
if (test_and_clear_bit(SSIP_WAKETEST_FLAG, &ssi->flags))
ssi_waketest(cl, 0); /* FIXME: To be removed */
spin_lock_bh(&ssi->lock);
del_timer(&ssi->rx_wd);
del_timer(&ssi->tx_wd);
del_timer(&ssi->keep_alive);
ssi->main_state = 0;
ssi->send_state = 0;
ssi->recv_state = 0;
ssi->waketest = 0;
ssi->flags = 0;
ssi->rxid = 0;
ssi->txid = 0;
list_for_each_safe(head, tmp, &ssi->txqueue) {
......@@ -437,7 +442,8 @@ static void ssip_dump_state(struct hsi_client *cl)
dev_err(&cl->device, "Send state: %d\n", ssi->send_state);
dev_err(&cl->device, "CMT %s\n", (ssi->main_state == ACTIVE) ?
"Online" : "Offline");
dev_err(&cl->device, "Wake test %d\n", ssi->waketest);
dev_err(&cl->device, "Wake test %d\n",
test_bit(SSIP_WAKETEST_FLAG, &ssi->flags));
dev_err(&cl->device, "Data RX id: %d\n", ssi->rxid);
dev_err(&cl->device, "Data TX id: %d\n", ssi->txid);
......@@ -515,17 +521,17 @@ static void ssip_start_rx(struct hsi_client *cl)
dev_dbg(&cl->device, "RX start M(%d) R(%d)\n", ssi->main_state,
ssi->recv_state);
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
/*
* We can have two UP events in a row due to a short low
* high transition. Therefore we need to ignore the sencond UP event.
*/
if ((ssi->main_state != ACTIVE) || (ssi->recv_state == RECV_READY)) {
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
return;
}
ssip_set_rxstate(ssi, RECV_READY);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
msg = ssip_claim_cmd(ssi);
ssip_set_cmd(msg, SSIP_READY_CMD);
......@@ -539,10 +545,10 @@ static void ssip_stop_rx(struct hsi_client *cl)
struct ssi_protocol *ssi = hsi_client_drvdata(cl);
dev_dbg(&cl->device, "RX stop M(%d)\n", ssi->main_state);
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (likely(ssi->main_state == ACTIVE))
ssip_set_rxstate(ssi, RECV_IDLE);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
}
static void ssip_free_strans(struct hsi_msg *msg)
......@@ -559,9 +565,9 @@ static void ssip_strans_complete(struct hsi_msg *msg)
data = msg->context;
ssip_release_cmd(msg);
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
ssip_set_txstate(ssi, SENDING);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
hsi_async_write(cl, data);
}
......@@ -666,15 +672,17 @@ static void ssip_rx_bootinforeq(struct hsi_client *cl, u32 cmd)
/* Fall through */
case INIT:
case HANDSHAKE:
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
ssi->main_state = HANDSHAKE;
if (!ssi->waketest) {
ssi->waketest = 1;
spin_unlock_bh(&ssi->lock);
if (!test_and_set_bit(SSIP_WAKETEST_FLAG, &ssi->flags))
ssi_waketest(cl, 1); /* FIXME: To be removed */
}
spin_lock_bh(&ssi->lock);
/* Start boot handshake watchdog */
mod_timer(&ssi->tx_wd, jiffies + msecs_to_jiffies(SSIP_WDTOUT));
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
dev_dbg(&cl->device, "Send BOOTINFO_RESP\n");
if (SSIP_DATA_VERSION(cmd) != SSIP_LOCAL_VERID)
dev_warn(&cl->device, "boot info req verid mismatch\n");
......@@ -696,14 +704,14 @@ static void ssip_rx_bootinforesp(struct hsi_client *cl, u32 cmd)
if (SSIP_DATA_VERSION(cmd) != SSIP_LOCAL_VERID)
dev_warn(&cl->device, "boot info resp verid mismatch\n");
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (ssi->main_state != ACTIVE)
/* Use tx_wd as a boot watchdog in non ACTIVE state */
mod_timer(&ssi->tx_wd, jiffies + msecs_to_jiffies(SSIP_WDTOUT));
else
dev_dbg(&cl->device, "boot info resp ignored M(%d)\n",
ssi->main_state);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
}
static void ssip_rx_waketest(struct hsi_client *cl, u32 cmd)
......@@ -711,20 +719,22 @@ static void ssip_rx_waketest(struct hsi_client *cl, u32 cmd)
struct ssi_protocol *ssi = hsi_client_drvdata(cl);
unsigned int wkres = SSIP_PAYLOAD(cmd);
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (ssi->main_state != HANDSHAKE) {
dev_dbg(&cl->device, "wake lines test ignored M(%d)\n",
ssi->main_state);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
return;
}
if (ssi->waketest) {
ssi->waketest = 0;
spin_unlock_bh(&ssi->lock);
if (test_and_clear_bit(SSIP_WAKETEST_FLAG, &ssi->flags))
ssi_waketest(cl, 0); /* FIXME: To be removed */
}
spin_lock_bh(&ssi->lock);
ssi->main_state = ACTIVE;
del_timer(&ssi->tx_wd); /* Stop boot handshake timer */
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
dev_notice(&cl->device, "WAKELINES TEST %s\n",
wkres & SSIP_WAKETEST_FAILED ? "FAILED" : "OK");
......@@ -741,20 +751,20 @@ static void ssip_rx_ready(struct hsi_client *cl)
{
struct ssi_protocol *ssi = hsi_client_drvdata(cl);
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (unlikely(ssi->main_state != ACTIVE)) {
dev_dbg(&cl->device, "READY on wrong state: S(%d) M(%d)\n",
ssi->send_state, ssi->main_state);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
return;
}
if (ssi->send_state != WAIT4READY) {
dev_dbg(&cl->device, "Ignore spurious READY command\n");
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
return;
}
ssip_set_txstate(ssi, SEND_READY);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
ssip_xmit(cl);
}
......@@ -766,22 +776,22 @@ static void ssip_rx_strans(struct hsi_client *cl, u32 cmd)
int len = SSIP_PDU_LENGTH(cmd);
dev_dbg(&cl->device, "RX strans: %d frames\n", len);
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (unlikely(ssi->main_state != ACTIVE)) {
dev_err(&cl->device, "START TRANS wrong state: S(%d) M(%d)\n",
ssi->send_state, ssi->main_state);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
return;
}
ssip_set_rxstate(ssi, RECEIVING);
if (unlikely(SSIP_MSG_ID(cmd) != ssi->rxid)) {
dev_err(&cl->device, "START TRANS id %d expected %d\n",
SSIP_MSG_ID(cmd), ssi->rxid);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
goto out1;
}
ssi->rxid++;
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
skb = netdev_alloc_skb(ssi->netdev, len * 4);
if (unlikely(!skb)) {
dev_err(&cl->device, "No memory for rx skb\n");
......@@ -849,7 +859,7 @@ static void ssip_swbreak_complete(struct hsi_msg *msg)
struct ssi_protocol *ssi = hsi_client_drvdata(cl);
ssip_release_cmd(msg);
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (list_empty(&ssi->txqueue)) {
if (atomic_read(&ssi->tx_usecnt)) {
ssip_set_txstate(ssi, SEND_READY);
......@@ -857,9 +867,9 @@ static void ssip_swbreak_complete(struct hsi_msg *msg)
ssip_set_txstate(ssi, SEND_IDLE);
hsi_stop_tx(cl);
}
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
} else {
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
ssip_xmit(cl);
}
netif_wake_queue(ssi->netdev);
......@@ -876,17 +886,17 @@ static void ssip_tx_data_complete(struct hsi_msg *msg)
ssip_error(cl);
goto out;
}
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (list_empty(&ssi->txqueue)) {
ssip_set_txstate(ssi, SENDING_SWBREAK);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
cmsg = ssip_claim_cmd(ssi);
ssip_set_cmd(cmsg, SSIP_SWBREAK_CMD);
cmsg->complete = ssip_swbreak_complete;
dev_dbg(&cl->device, "Send SWBREAK\n");
hsi_async_write(cl, cmsg);
} else {
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
ssip_xmit(cl);
}
out:
......@@ -926,11 +936,11 @@ static int ssip_pn_open(struct net_device *dev)
}
dev_dbg(&cl->device, "Configuring SSI port\n");
hsi_setup(cl);
spin_lock_bh(&ssi->lock);
if (!ssi->waketest) {
ssi->waketest = 1;
if (!test_and_set_bit(SSIP_WAKETEST_FLAG, &ssi->flags))
ssi_waketest(cl, 1); /* FIXME: To be removed */
}
spin_lock_bh(&ssi->lock);
ssi->main_state = HANDSHAKE;
spin_unlock_bh(&ssi->lock);
......@@ -959,6 +969,15 @@ static int ssip_pn_set_mtu(struct net_device *dev, int new_mtu)
return 0;
}
static void ssip_xmit_work(struct work_struct *work)
{
struct ssi_protocol *ssi =
container_of(work, struct ssi_protocol, work);
struct hsi_client *cl = ssi->cl;
ssip_xmit(cl);
}
static int ssip_pn_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct hsi_client *cl = to_hsi_client(dev->dev.parent);
......@@ -1011,7 +1030,7 @@ static int ssip_pn_xmit(struct sk_buff *skb, struct net_device *dev)
dev_dbg(&cl->device, "Start TX on SEND READY qlen %d\n",
ssi->txqueue_len);
spin_unlock_bh(&ssi->lock);
ssip_xmit(cl);
schedule_work(&ssi->work);
} else {
spin_unlock_bh(&ssi->lock);
}
......@@ -1088,6 +1107,7 @@ static int ssi_protocol_probe(struct device *dev)
atomic_set(&ssi->tx_usecnt, 0);
hsi_client_set_drvdata(cl, ssi);
ssi->cl = cl;
INIT_WORK(&ssi->work, ssip_xmit_work);
ssi->channel_id_cmd = hsi_get_channel_id_by_name(cl, "mcsaab-control");
if (ssi->channel_id_cmd < 0) {
......
......@@ -35,6 +35,8 @@
#define SSI_MAX_GDD_LCH 8
#define SSI_BYTES_TO_FRAMES(x) ((((x) - 1) >> 2) + 1)
#define SSI_WAKE_EN 0
/**
* struct omap_ssm_ctx - OMAP synchronous serial module (TX/RX) context
* @mode: Bit transmission mode
......@@ -71,13 +73,14 @@ struct omap_ssm_ctx {
* @txqueue: TX message queues
* @rxqueue: RX message queues
* @brkqueue: Queue of incoming HWBREAK requests (FRAME mode)
* @errqueue: Queue for failed messages
* @errqueue_work: Delayed Work for failed messages
* @irq: IRQ number
* @wake_irq: IRQ number for incoming wake line (-1 if none)
* @wake_gpio: GPIO number for incoming wake line (-1 if none)
* @pio_tasklet: Bottom half for PIO transfers and events
* @wake_tasklet: Bottom half for incoming wake events
* @wkin_cken: Keep track of clock references due to the incoming wake line
* @flags: flags to keep track of states
* @wk_refcount: Reference count for output wake line
* @work: worker for starting TX
* @sys_mpu_enable: Context for the interrupt enable register for irq 0
* @sst: Context for the synchronous serial transmitter
* @ssr: Context for the synchronous serial receiver
......@@ -95,14 +98,15 @@ struct omap_ssi_port {
struct list_head txqueue[SSI_MAX_CHANNELS];
struct list_head rxqueue[SSI_MAX_CHANNELS];
struct list_head brkqueue;
struct list_head errqueue;
struct delayed_work errqueue_work;
unsigned int irq;
int wake_irq;
struct gpio_desc *wake_gpio;
struct tasklet_struct pio_tasklet;
struct tasklet_struct wake_tasklet;
bool wktest:1; /* FIXME: HACK to be removed */
bool wkin_cken:1; /* Workaround */
unsigned long flags;
unsigned int wk_refcount;
struct work_struct work;
/* OMAP SSI port context */
u32 sys_mpu_enable; /* We use only one irq */
struct omap_ssm_ctx sst;
......@@ -138,7 +142,6 @@ struct gdd_trn {
* @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
* @gdd_gcr: SSI GDD saved context
* @get_loss: Pointer to omap_pm_get_dev_context_loss_count, if any
* @port: Array of pointers of the ports of the controller
......@@ -158,7 +161,6 @@ struct omap_ssi_controller {
u32 loss_count;
u32 max_speed;
/* OMAP SSI Controller context */
u32 sysconfig;
u32 gdd_gcr;
int (*get_loss)(struct device *dev);
struct omap_ssi_port **port;
......
......@@ -58,7 +58,7 @@ static int ssi_debug_show(struct seq_file *m, void *p __maybe_unused)
seq_printf(m, "REVISION\t: 0x%08x\n", readl(sys + SSI_REVISION_REG));
seq_printf(m, "SYSCONFIG\t: 0x%08x\n", readl(sys + SSI_SYSCONFIG_REG));
seq_printf(m, "SYSSTATUS\t: 0x%08x\n", readl(sys + SSI_SYSSTATUS_REG));
pm_runtime_put_sync(ssi->device.parent);
pm_runtime_put(ssi->device.parent);
return 0;
}
......@@ -112,7 +112,7 @@ static int ssi_debug_gdd_show(struct seq_file *m, void *p __maybe_unused)
readw(gdd + SSI_GDD_CLNK_CTRL_REG(lch)));
}
pm_runtime_put_sync(ssi->device.parent);
pm_runtime_put(ssi->device.parent);
return 0;
}
......@@ -193,7 +193,7 @@ void ssi_waketest(struct hsi_client *cl, unsigned int enable)
} else {
writel_relaxed(SSI_WAKE(0),
omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num));
pm_runtime_put_sync(ssi->device.parent);
pm_runtime_put(ssi->device.parent);
}
}
EXPORT_SYMBOL_GPL(ssi_waketest);
......@@ -217,7 +217,7 @@ static void ssi_gdd_complete(struct hsi_controller *ssi, unsigned int lch)
if (msg->ttype == HSI_MSG_READ) {
dir = DMA_FROM_DEVICE;
val = SSI_DATAAVAILABLE(msg->channel);
pm_runtime_put_sync(ssi->device.parent);
pm_runtime_put(omap_port->pdev);
} else {
dir = DMA_TO_DEVICE;
val = SSI_DATAACCEPT(msg->channel);
......@@ -235,7 +235,9 @@ static void ssi_gdd_complete(struct hsi_controller *ssi, unsigned int lch)
spin_lock(&omap_port->lock);
list_del(&msg->link); /* Dequeue msg */
spin_unlock(&omap_port->lock);
msg->complete(msg);
list_add_tail(&msg->link, &omap_port->errqueue);
schedule_delayed_work(&omap_port->errqueue_work, 0);
return;
}
spin_lock(&omap_port->lock);
......@@ -255,7 +257,13 @@ static void ssi_gdd_tasklet(unsigned long dev)
unsigned int lch;
u32 status_reg;
pm_runtime_get_sync(ssi->device.parent);
pm_runtime_get(ssi->device.parent);
if (!pm_runtime_active(ssi->device.parent)) {
dev_warn(ssi->device.parent, "ssi_gdd_tasklet called without runtime PM!\n");
pm_runtime_put(ssi->device.parent);
return;
}
status_reg = readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG);
for (lch = 0; lch < SSI_MAX_GDD_LCH; lch++) {
......@@ -265,7 +273,7 @@ static void ssi_gdd_tasklet(unsigned long dev)
writel_relaxed(status_reg, sys + SSI_GDD_MPU_IRQ_STATUS_REG);
status_reg = readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG);
pm_runtime_put_sync(ssi->device.parent);
pm_runtime_put(ssi->device.parent);
if (status_reg)
tasklet_hi_schedule(&omap_ssi->gdd_tasklet);
......@@ -312,7 +320,7 @@ static int ssi_clk_event(struct notifier_block *nb, unsigned long event,
continue;
/* Workaround for SWBREAK + CAwake down race in CMT */
tasklet_disable(&omap_port->wake_tasklet);
disable_irq(omap_port->wake_irq);
/* stop all ssi communication */
pinctrl_pm_select_idle_state(omap_port->pdev);
......@@ -338,7 +346,7 @@ static int ssi_clk_event(struct notifier_block *nb, unsigned long event,
/* resume ssi communication */
pinctrl_pm_select_default_state(omap_port->pdev);
tasklet_enable(&omap_port->wake_tasklet);
enable_irq(omap_port->wake_irq);
}
break;
......@@ -452,8 +460,6 @@ static int ssi_add_controller(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;
u32 val;
int err;
err = pm_runtime_get_sync(ssi->device.parent);
......@@ -461,27 +467,12 @@ static int ssi_hw_init(struct hsi_controller *ssi)
dev_err(&ssi->device, "runtime PM failed %d\n", err);
return err;
}
/* Reseting SSI controller */
writel_relaxed(SSI_SOFTRESET, omap_ssi->sys + SSI_SYSCONFIG_REG);
val = readl(omap_ssi->sys + SSI_SYSSTATUS_REG);
for (i = 0; ((i < 20) && !(val & SSI_RESETDONE)); i++) {
msleep(20);
val = readl(omap_ssi->sys + SSI_SYSSTATUS_REG);
}
if (!(val & SSI_RESETDONE)) {
dev_err(&ssi->device, "SSI HW reset failed\n");
pm_runtime_put_sync(ssi->device.parent);
return -EIO;
}
/* Reseting GDD */
writel_relaxed(SSI_SWRESET, omap_ssi->gdd + SSI_GDD_GRST_REG);
/* Get FCK rate in KHz */
omap_ssi->fck_rate = DIV_ROUND_CLOSEST(ssi_get_clk_rate(ssi), 1000);
dev_dbg(&ssi->device, "SSI fck rate %lu KHz\n", omap_ssi->fck_rate);
/* Set default PM settings */
val = SSI_AUTOIDLE | SSI_SIDLEMODE_SMART | SSI_MIDLEMODE_SMART;
writel_relaxed(val, omap_ssi->sys + SSI_SYSCONFIG_REG);
omap_ssi->sysconfig = val;
writel_relaxed(SSI_CLK_AUTOGATING_ON, omap_ssi->sys + SSI_GDD_GCR_REG);
omap_ssi->gdd_gcr = SSI_CLK_AUTOGATING_ON;
pm_runtime_put_sync(ssi->device.parent);
......@@ -552,7 +543,6 @@ static int ssi_probe(struct platform_device *pd)
if (err < 0)
goto out1;
pm_runtime_irq_safe(&pd->dev);
pm_runtime_enable(&pd->dev);
err = ssi_hw_init(ssi);
......
This diff is collapsed.
......@@ -90,19 +90,19 @@ struct hsi_client *hsi_new_client(struct hsi_port *port,
cl->tx_cfg = info->tx_cfg;
if (cl->tx_cfg.channels) {
size = cl->tx_cfg.num_channels * sizeof(*cl->tx_cfg.channels);
cl->tx_cfg.channels = kzalloc(size , GFP_KERNEL);
cl->tx_cfg.channels = kmemdup(info->tx_cfg.channels, size,
GFP_KERNEL);
if (!cl->tx_cfg.channels)
goto err_tx;
memcpy(cl->tx_cfg.channels, info->tx_cfg.channels, size);
}
cl->rx_cfg = info->rx_cfg;
if (cl->rx_cfg.channels) {
size = cl->rx_cfg.num_channels * sizeof(*cl->rx_cfg.channels);
cl->rx_cfg.channels = kzalloc(size , GFP_KERNEL);
cl->rx_cfg.channels = kmemdup(info->rx_cfg.channels, size,
GFP_KERNEL);
if (!cl->rx_cfg.channels)
goto err_rx;
memcpy(cl->rx_cfg.channels, info->rx_cfg.channels, size);
}
cl->device.bus = &hsi_bus_type;
......@@ -507,7 +507,7 @@ struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags)
port[i]->stop_tx = hsi_dummy_cl;
port[i]->release = hsi_dummy_cl;
mutex_init(&port[i]->lock);
ATOMIC_INIT_NOTIFIER_HEAD(&port[i]->n_head);
BLOCKING_INIT_NOTIFIER_HEAD(&port[i]->n_head);
dev_set_name(&port[i]->device, "port%d", i);
hsi->port[i]->device.release = hsi_port_release;
device_initialize(&hsi->port[i]->device);
......@@ -689,7 +689,7 @@ int hsi_register_port_event(struct hsi_client *cl,
cl->ehandler = handler;
cl->nb.notifier_call = hsi_event_notifier_call;
return atomic_notifier_chain_register(&port->n_head, &cl->nb);
return blocking_notifier_chain_register(&port->n_head, &cl->nb);
}
EXPORT_SYMBOL_GPL(hsi_register_port_event);
......@@ -709,7 +709,7 @@ int hsi_unregister_port_event(struct hsi_client *cl)
WARN_ON(!hsi_port_claimed(cl));
err = atomic_notifier_chain_unregister(&port->n_head, &cl->nb);
err = blocking_notifier_chain_unregister(&port->n_head, &cl->nb);
if (!err)
cl->ehandler = NULL;
......@@ -734,7 +734,7 @@ EXPORT_SYMBOL_GPL(hsi_unregister_port_event);
*/
int hsi_event(struct hsi_port *port, unsigned long event)
{
return atomic_notifier_call_chain(&port->n_head, event, NULL);
return blocking_notifier_call_chain(&port->n_head, event, NULL);
}
EXPORT_SYMBOL_GPL(hsi_event);
......
......@@ -246,7 +246,7 @@ struct hsi_port {
int (*stop_tx)(struct hsi_client *cl);
int (*release)(struct hsi_client *cl);
/* private */
struct atomic_notifier_head n_head;
struct blocking_notifier_head n_head;
};
#define to_hsi_port(dev) container_of(dev, struct hsi_port, device)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment