/* the caller passed in the clock source spec that was read from *thedevicetree,gettheoptionalclockdivideraswell
*/
np = ofdev->dev.of_node;
clockdiv = 1;
of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
clock_source ? clock_source : "<NULL>", clockdiv);
/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to *getset,andthe'ips'clockistheinputtotheMSCAN *component * *forclock-sourcevaluesof'ref'or'sys'theCANCTL1[CLKSRC] *bitneedstogetcleared,anoptionalclock-dividermayhave *beenspecified(thedefaultvalueis1),theappropriate *MSCANrelatedMCLKistheinputtotheMSCANcomponent * *intheabsenceofaclock-sourcespec,firstanoptimalclock *getsdeterminedbasedonthe'sys'clock,ifthatfailsthe *'ref'clockisused
*/
clk_from = CLK_FROM_AUTO; if (clock_source) { /* interpret the device tree's spec for the clock source */ if (!strcmp(clock_source, "ip"))
clk_from = CLK_FROM_IPS; elseif (!strcmp(clock_source, "sys"))
clk_from = CLK_FROM_SYS; elseif (!strcmp(clock_source, "ref"))
clk_from = CLK_FROM_REF; else goto err_invalid;
dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
} if (clk_from == CLK_FROM_AUTO) { /* no spec so far, try the 'sys' clock; round to the *nextMHzandseeifwecangetamultipleof16MHz
*/
dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
clk_in = devm_clk_get(&ofdev->dev, "sys"); if (IS_ERR(clk_in)) goto err_notavail;
freq_calc = clk_get_rate(clk_in);
freq_calc += 499999;
freq_calc /= 1000000;
freq_calc *= 1000000; if ((freq_calc % 16000000) == 0) {
clk_from = CLK_FROM_SYS;
clockdiv = freq_calc / 16000000;
dev_dbg(&ofdev->dev, "clk fit, sys[%lu] div[%d] freq[%lu]\n",
freq_calc, clockdiv, freq_calc / clockdiv);
}
} if (clk_from == CLK_FROM_AUTO) { /* no spec so far, use the 'ref' clock */
dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
clk_in = devm_clk_get(&ofdev->dev, "ref"); if (IS_ERR(clk_in)) goto err_notavail;
clk_from = CLK_FROM_REF;
freq_calc = clk_get_rate(clk_in);
dev_dbg(&ofdev->dev, "clk fit, ref[%lu] (no div) freq[%lu]\n",
freq_calc, freq_calc);
}
/* select IPS or MCLK as the MSCAN input (returned to the caller), *setuptheMCLKmuxsourceandrateifapplicable,applythe *optionallyspecifiedorderivedabovedivider,anddetermine *theactualresultingclockratetoreturntothecaller
*/ switch (clk_from) { case CLK_FROM_IPS:
clk_can = devm_clk_get(&ofdev->dev, "ips"); if (IS_ERR(clk_can)) goto err_notavail;
priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
priv->clk_can = clk_can;
freq_calc = clk_get_rate(clk_can);
*mscan_clksrc = MSCAN_CLKSRC_IPS;
dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
*mscan_clksrc, freq_calc); break; case CLK_FROM_SYS: case CLK_FROM_REF:
clk_can = devm_clk_get(&ofdev->dev, "mclk"); if (IS_ERR(clk_can)) goto err_notavail;
priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
priv->clk_can = clk_can; if (clk_from == CLK_FROM_SYS)
clk_in = devm_clk_get(&ofdev->dev, "sys"); if (clk_from == CLK_FROM_REF)
clk_in = devm_clk_get(&ofdev->dev, "ref"); if (IS_ERR(clk_in)) goto err_notavail;
clk_set_parent(clk_can, clk_in);
freq_calc = clk_get_rate(clk_in);
freq_calc /= clockdiv;
clk_set_rate(clk_can, freq_calc);
freq_calc = clk_get_rate(clk_can);
*mscan_clksrc = MSCAN_CLKSRC_BUS;
dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
*mscan_clksrc, freq_calc); break; default: goto err_invalid;
}
/* the above clk_can item is used for the bitrate, access to *theperipheral'sregistersetneedstheclk_ipgitem
*/
clk_ipg = devm_clk_get(&ofdev->dev, "ipg"); if (IS_ERR(clk_ipg)) goto err_notavail_ipg; if (clk_prepare_enable(clk_ipg)) goto err_notavail_ipg;
priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
priv->clk_ipg = clk_ipg;
/* return the determined clock source rate */ return freq_calc;
err_invalid:
dev_err(&ofdev->dev, "invalid clock source specification\n"); /* clock source rate could not get determined */ return0;
err_notavail:
dev_err(&ofdev->dev, "cannot acquire or setup bitrate clock source\n"); /* clock source rate could not get determined */ return0;
err_notavail_ipg:
dev_err(&ofdev->dev, "cannot acquire or setup register clock\n"); /* clock source rate could not get determined */ return0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.