aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-pl022.c102
1 files changed, 51 insertions, 51 deletions
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 248674c8a8c2..4e1a1e3b2a8c 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -1790,67 +1790,67 @@ static int pl022_transfer(struct spi_device *spi, struct spi_message *msg)
1790 return 0; 1790 return 0;
1791} 1791}
1792 1792
1793static int calculate_effective_freq(struct pl022 *pl022, 1793static inline u32 spi_rate(u32 rate, u16 cpsdvsr, u16 scr)
1794 int freq, 1794{
1795 struct ssp_clock_params *clk_freq) 1795 return rate / (cpsdvsr * (1 + scr));
1796}
1797
1798static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
1799 ssp_clock_params * clk_freq)
1796{ 1800{
1797 /* Lets calculate the frequency parameters */ 1801 /* Lets calculate the frequency parameters */
1798 u16 cpsdvsr = 2; 1802 u16 cpsdvsr = CPSDVR_MIN, scr = SCR_MIN;
1799 u16 scr = 0; 1803 u32 rate, max_tclk, min_tclk, best_freq = 0, best_cpsdvsr = 0,
1800 bool freq_found = false; 1804 best_scr = 0, tmp, found = 0;
1801 u32 rate;
1802 u32 max_tclk;
1803 u32 min_tclk;
1804 1805
1805 rate = clk_get_rate(pl022->clk); 1806 rate = clk_get_rate(pl022->clk);
1806 /* cpsdvscr = 2 & scr 0 */ 1807 /* cpsdvscr = 2 & scr 0 */
1807 max_tclk = (rate / (CPSDVR_MIN * (1 + SCR_MIN))); 1808 max_tclk = spi_rate(rate, CPSDVR_MIN, SCR_MIN);
1808 /* cpsdvsr = 254 & scr = 255 */ 1809 /* cpsdvsr = 254 & scr = 255 */
1809 min_tclk = (rate / (CPSDVR_MAX * (1 + SCR_MAX))); 1810 min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX);
1810 1811
1811 if ((freq <= max_tclk) && (freq >= min_tclk)) { 1812 if (!((freq <= max_tclk) && (freq >= min_tclk))) {
1812 while (cpsdvsr <= CPSDVR_MAX && !freq_found) {
1813 while (scr <= SCR_MAX && !freq_found) {
1814 if ((rate /
1815 (cpsdvsr * (1 + scr))) > freq)
1816 scr += 1;
1817 else {
1818 /*
1819 * This bool is made true when
1820 * effective frequency >=
1821 * target frequency is found
1822 */
1823 freq_found = true;
1824 if ((rate /
1825 (cpsdvsr * (1 + scr))) != freq) {
1826 if (scr == SCR_MIN) {
1827 cpsdvsr -= 2;
1828 scr = SCR_MAX;
1829 } else
1830 scr -= 1;
1831 }
1832 }
1833 }
1834 if (!freq_found) {
1835 cpsdvsr += 2;
1836 scr = SCR_MIN;
1837 }
1838 }
1839 if (cpsdvsr != 0) {
1840 dev_dbg(&pl022->adev->dev,
1841 "SSP Effective Frequency is %u\n",
1842 (rate / (cpsdvsr * (1 + scr))));
1843 clk_freq->cpsdvsr = (u8) (cpsdvsr & 0xFF);
1844 clk_freq->scr = (u8) (scr & 0xFF);
1845 dev_dbg(&pl022->adev->dev,
1846 "SSP cpsdvsr = %d, scr = %d\n",
1847 clk_freq->cpsdvsr, clk_freq->scr);
1848 }
1849 } else {
1850 dev_err(&pl022->adev->dev, 1813 dev_err(&pl022->adev->dev,
1851 "controller data is incorrect: out of range frequency"); 1814 "controller data is incorrect: out of range frequency");
1852 return -EINVAL; 1815 return -EINVAL;
1853 } 1816 }
1817
1818 /*
1819 * best_freq will give closest possible available rate (<= requested
1820 * freq) for all values of scr & cpsdvsr.
1821 */
1822 while ((cpsdvsr <= CPSDVR_MAX) && !found) {
1823 while (scr <= SCR_MAX) {
1824 tmp = spi_rate(rate, cpsdvsr, scr);
1825
1826 if (tmp > freq)
1827 scr++;
1828 /*
1829 * If found exact value, update and break.
1830 * If found more closer value, update and continue.
1831 */
1832 else if ((tmp == freq) || (tmp > best_freq)) {
1833 best_freq = tmp;
1834 best_cpsdvsr = cpsdvsr;
1835 best_scr = scr;
1836
1837 if (tmp == freq)
1838 break;
1839 }
1840 scr++;
1841 }
1842 cpsdvsr += 2;
1843 scr = SCR_MIN;
1844 }
1845
1846 clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
1847 clk_freq->scr = (u8) (best_scr & 0xFF);
1848 dev_dbg(&pl022->adev->dev,
1849 "SSP Target Frequency is: %u, Effective Frequency is %u\n",
1850 freq, best_freq);
1851 dev_dbg(&pl022->adev->dev, "SSP cpsdvsr = %d, scr = %d\n",
1852 clk_freq->cpsdvsr, clk_freq->scr);
1853
1854 return 0; 1854 return 0;
1855} 1855}
1856 1856