diff options
| -rw-r--r-- | drivers/spi/spi-pxa2xx.c | 176 |
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 | ||
| 66 | struct 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 | */ | ||
| 76 | static 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 | */ |
| 703 | static u32 quark_x1000_set_clk_regvals(u32 rate, u32 *dds, u32 *clk_div) | 684 | static 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 | ||
| 721 | static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate) | 773 | static 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 | } |
