in controllers/omap_ssi_core.c [268:324]
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 */
disable_irq(omap_port->wake_irq);
/* 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");
fallthrough;
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);
enable_irq(omap_port->wake_irq);
}
break;
default:
break;
}
return NOTIFY_DONE;
}