aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2015-03-25 09:06:16 -0400
committerMark Brown <broonie@kernel.org>2015-03-25 11:30:17 -0400
commit9df461eca18f5395ee84670cdba6755dddec1898 (patch)
treeca866b01fbfb63bdd31ccf53f50c0d05ae8765de /drivers/spi
parent025ffe88ee605acb03dba0d920908dff5ec15dd0 (diff)
spi: pxa2xx: replace ugly table by approximation
The Quark SoC data sheet describes the baud rate setting using fractional divider. The subset of possible values represented by a table suggests that the divisor has one block that could divide by 5. This explains the number of the beast in some cases in the table. Thus, in this particular case the divisor can be evaluated as 5^i * 2^j * 2 * k, where i = [0, 1] j = [0, 23] k = [1, 256] There are few cases as mentioned in the data sheet, i.e. better form of the clock signal will be in case if DDS_CLK_RATE either 2^n or 2/5. It's also possible to use any value that is less or equal to 0x33333 (1/5/16 = 1/80). All three cases are compared to each other and the one that suits better is chosen by the approximation algorithm. Anyone can play with the script [1] that represents the algorithm. [1] https://gist.github.com/06b084488b3629898121 Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-pxa2xx.c176
1 files changed, 114 insertions, 62 deletions
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 6d6473427432..60526a591742 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -20,6 +20,7 @@
20#include <linux/errno.h> 20#include <linux/errno.h>
21#include <linux/err.h> 21#include <linux/err.h>
22#include <linux/interrupt.h> 22#include <linux/interrupt.h>
23#include <linux/kernel.h>
23#include <linux/platform_device.h> 24#include <linux/platform_device.h>
24#include <linux/spi/pxa2xx_spi.h> 25#include <linux/spi/pxa2xx_spi.h>
25#include <linux/spi/spi.h> 26#include <linux/spi/spi.h>
@@ -63,54 +64,6 @@ MODULE_ALIAS("platform:pxa2xx-spi");
63#define LPSS_TX_LOTHRESH_DFLT 160 64#define LPSS_TX_LOTHRESH_DFLT 160
64#define LPSS_TX_HITHRESH_DFLT 224 65#define LPSS_TX_HITHRESH_DFLT 224
65 66
66struct quark_spi_rate {
67 u32 bitrate;
68 u32 dds_clk_rate;
69 u32 clk_div;
70};
71
72/*
73 * 'rate', 'dds', 'clk_div' lookup table, which is defined in
74 * the Quark SPI datasheet.
75 */
76static const struct quark_spi_rate quark_spi_rate_table[] = {
77/* bitrate, dds_clk_rate, clk_div */
78 {50000000, 0x800000, 0},
79 {40000000, 0x666666, 0},
80 {25000000, 0x400000, 0},
81 {20000000, 0x666666, 1},
82 {16667000, 0x800000, 2},
83 {13333000, 0x666666, 2},
84 {12500000, 0x200000, 0},
85 {10000000, 0x800000, 4},
86 {8000000, 0x666666, 4},
87 {6250000, 0x400000, 3},
88 {5000000, 0x400000, 4},
89 {4000000, 0x666666, 9},
90 {3125000, 0x80000, 0},
91 {2500000, 0x400000, 9},
92 {2000000, 0x666666, 19},
93 {1563000, 0x40000, 0},
94 {1250000, 0x200000, 9},
95 {1000000, 0x400000, 24},
96 {800000, 0x666666, 49},
97 {781250, 0x20000, 0},
98 {625000, 0x200000, 19},
99 {500000, 0x400000, 49},
100 {400000, 0x666666, 99},
101 {390625, 0x10000, 0},
102 {250000, 0x400000, 99},
103 {200000, 0x666666, 199},
104 {195313, 0x8000, 0},
105 {125000, 0x100000, 49},
106 {100000, 0x200000, 124},
107 {50000, 0x100000, 124},
108 {25000, 0x80000, 124},
109 {10016, 0x20000, 77},
110 {5040, 0x20000, 154},
111 {1002, 0x8000, 194},
112};
113
114/* Offset from drv_data->lpss_base */ 67/* Offset from drv_data->lpss_base */
115#define GENERAL_REG 0x08 68#define GENERAL_REG 0x08
116#define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24) 69#define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
@@ -697,25 +650,124 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
697} 650}
698 651
699/* 652/*
700 * The Quark SPI data sheet gives a table, and for the given 'rate', 653 * The Quark SPI has an additional 24 bit register (DDS_CLK_RATE) to multiply
701 * the 'dds' and 'clk_div' can be found in the table. 654 * input frequency by fractions of 2^24. It also has a divider by 5.
655 *
656 * There are formulas to get baud rate value for given input frequency and
657 * divider parameters, such as DDS_CLK_RATE and SCR:
658 *
659 * Fsys = 200MHz
660 *
661 * Fssp = Fsys * DDS_CLK_RATE / 2^24 (1)
662 * Baud rate = Fsclk = Fssp / (2 * (SCR + 1)) (2)
663 *
664 * DDS_CLK_RATE either 2^n or 2^n / 5.
665 * SCR is in range 0 .. 255
666 *
667 * Divisor = 5^i * 2^j * 2 * k
668 * i = [0, 1] i = 1 iff j = 0 or j > 3
669 * j = [0, 23] j = 0 iff i = 1
670 * k = [1, 256]
671 * Special case: j = 0, i = 1: Divisor = 2 / 5
672 *
673 * Accordingly to the specification the recommended values for DDS_CLK_RATE
674 * are:
675 * Case 1: 2^n, n = [0, 23]
676 * Case 2: 2^24 * 2 / 5 (0x666666)
677 * Case 3: less than or equal to 2^24 / 5 / 16 (0x33333)
678 *
679 * In all cases the lowest possible value is better.
680 *
681 * The function calculates parameters for all cases and chooses the one closest
682 * to the asked baud rate.
702 */ 683 */
703static u32 quark_x1000_set_clk_regvals(u32 rate, u32 *dds, u32 *clk_div) 684static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds)
704{ 685{
705 unsigned int i; 686 unsigned long xtal = 200000000;
706 687 unsigned long fref = xtal / 2; /* mandatory division by 2,
707 for (i = 0; i < ARRAY_SIZE(quark_spi_rate_table); i++) { 688 see (2) */
708 if (rate >= quark_spi_rate_table[i].bitrate) { 689 /* case 3 */
709 *dds = quark_spi_rate_table[i].dds_clk_rate; 690 unsigned long fref1 = fref / 2; /* case 1 */
710 *clk_div = quark_spi_rate_table[i].clk_div; 691 unsigned long fref2 = fref * 2 / 5; /* case 2 */
711 return quark_spi_rate_table[i].bitrate; 692 unsigned long scale;
693 unsigned long q, q1, q2;
694 long r, r1, r2;
695 u32 mul;
696
697 /* Case 1 */
698
699 /* Set initial value for DDS_CLK_RATE */
700 mul = (1 << 24) >> 1;
701
702 /* Calculate initial quot */
703 q1 = DIV_ROUND_CLOSEST(fref1, rate);
704
705 /* Scale q1 if it's too big */
706 if (q1 > 256) {
707 /* Scale q1 to range [1, 512] */
708 scale = fls_long(q1 - 1);
709 if (scale > 9) {
710 q1 >>= scale - 9;
711 mul >>= scale - 9;
712 } 712 }
713
714 /* Round the result if we have a remainder */
715 q1 += q1 & 1;
713 } 716 }
714 717
715 *dds = quark_spi_rate_table[i-1].dds_clk_rate; 718 /* Decrease DDS_CLK_RATE as much as we can without loss in precision */
716 *clk_div = quark_spi_rate_table[i-1].clk_div; 719 scale = __ffs(q1);
720 q1 >>= scale;
721 mul >>= scale;
722
723 /* Get the remainder */
724 r1 = abs(fref1 / (1 << (24 - fls_long(mul))) / q1 - rate);
725
726 /* Case 2 */
727
728 q2 = DIV_ROUND_CLOSEST(fref2, rate);
729 r2 = abs(fref2 / q2 - rate);
730
731 /*
732 * Choose the best between two: less remainder we have the better. We
733 * can't go case 2 if q2 is greater than 256 since SCR register can
734 * hold only values 0 .. 255.
735 */
736 if (r2 >= r1 || q2 > 256) {
737 /* case 1 is better */
738 r = r1;
739 q = q1;
740 } else {
741 /* case 2 is better */
742 r = r2;
743 q = q2;
744 mul = (1 << 24) * 2 / 5;
745 }
746
747 /* Check case 3 only If the divisor is big enough */
748 if (fref / rate >= 80) {
749 u64 fssp;
750 u32 m;
751
752 /* Calculate initial quot */
753 q1 = DIV_ROUND_CLOSEST(fref, rate);
754 m = (1 << 24) / q1;
755
756 /* Get the remainder */
757 fssp = (u64)fref * m;
758 do_div(fssp, 1 << 24);
759 r1 = abs(fssp - rate);
760
761 /* Choose this one if it suits better */
762 if (r1 < r) {
763 /* case 3 is better */
764 q = 1;
765 mul = m;
766 }
767 }
717 768
718 return quark_spi_rate_table[i-1].bitrate; 769 *dds = mul;
770 return q - 1;
719} 771}
720 772
721static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate) 773static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
@@ -738,7 +790,7 @@ static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data,
738 790
739 switch (drv_data->ssp_type) { 791 switch (drv_data->ssp_type) {
740 case QUARK_X1000_SSP: 792 case QUARK_X1000_SSP:
741 quark_x1000_set_clk_regvals(rate, &chip->dds_rate, &clk_div); 793 clk_div = quark_x1000_get_clk_div(rate, &chip->dds_rate);
742 default: 794 default:
743 clk_div = ssp_get_clk_div(drv_data, rate); 795 clk_div = ssp_get_clk_div(drv_data, rate);
744 } 796 }