diff options
Diffstat (limited to 'drivers/scsi/sata_sx4.c')
| -rw-r--r-- | drivers/scsi/sata_sx4.c | 179 |
1 files changed, 95 insertions, 84 deletions
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index efd7d7a61135..c72fcc46f0fa 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c | |||
| @@ -7,21 +7,26 @@ | |||
| 7 | * | 7 | * |
| 8 | * Copyright 2003-2004 Red Hat, Inc. | 8 | * Copyright 2003-2004 Red Hat, Inc. |
| 9 | * | 9 | * |
| 10 | * The contents of this file are subject to the Open | ||
| 11 | * Software License version 1.1 that can be found at | ||
| 12 | * http://www.opensource.org/licenses/osl-1.1.txt and is included herein | ||
| 13 | * by reference. | ||
| 14 | * | 10 | * |
| 15 | * Alternatively, the contents of this file may be used under the terms | 11 | * This program is free software; you can redistribute it and/or modify |
| 16 | * of the GNU General Public License version 2 (the "GPL") as distributed | 12 | * it under the terms of the GNU General Public License as published by |
| 17 | * in the kernel source COPYING file, in which case the provisions of | 13 | * the Free Software Foundation; either version 2, or (at your option) |
| 18 | * the GPL are applicable instead of the above. If you wish to allow | 14 | * any later version. |
| 19 | * the use of your version of this file only under the terms of the | 15 | * |
| 20 | * GPL and not to allow others to use your version of this file under | 16 | * This program is distributed in the hope that it will be useful, |
| 21 | * the OSL, indicate your decision by deleting the provisions above and | 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 22 | * replace them with the notice and other provisions required by the GPL. | 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 23 | * If you do not delete the provisions above, a recipient may use your | 19 | * GNU General Public License for more details. |
| 24 | * version of this file under either the OSL or the GPL. | 20 | * |
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; see the file COPYING. If not, write to | ||
| 23 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | * | ||
| 25 | * | ||
| 26 | * libata documentation is available via 'make {ps|pdf}docs', | ||
| 27 | * as Documentation/DocBook/libata.* | ||
| 28 | * | ||
| 29 | * Hardware documentation available under NDA. | ||
| 25 | * | 30 | * |
| 26 | */ | 31 | */ |
| 27 | 32 | ||
| @@ -94,7 +99,7 @@ enum { | |||
| 94 | PDC_DIMM1_CONTROL_OFFSET = 0x84, | 99 | PDC_DIMM1_CONTROL_OFFSET = 0x84, |
| 95 | PDC_SDRAM_CONTROL_OFFSET = 0x88, | 100 | PDC_SDRAM_CONTROL_OFFSET = 0x88, |
| 96 | PDC_I2C_WRITE = 0x00000000, | 101 | PDC_I2C_WRITE = 0x00000000, |
| 97 | PDC_I2C_READ = 0x00000040, | 102 | PDC_I2C_READ = 0x00000040, |
| 98 | PDC_I2C_START = 0x00000080, | 103 | PDC_I2C_START = 0x00000080, |
| 99 | PDC_I2C_MASK_INT = 0x00000020, | 104 | PDC_I2C_MASK_INT = 0x00000020, |
| 100 | PDC_I2C_COMPLETE = 0x00010000, | 105 | PDC_I2C_COMPLETE = 0x00010000, |
| @@ -105,16 +110,16 @@ enum { | |||
| 105 | PDC_DIMM_SPD_COLUMN_NUM = 4, | 110 | PDC_DIMM_SPD_COLUMN_NUM = 4, |
| 106 | PDC_DIMM_SPD_MODULE_ROW = 5, | 111 | PDC_DIMM_SPD_MODULE_ROW = 5, |
| 107 | PDC_DIMM_SPD_TYPE = 11, | 112 | PDC_DIMM_SPD_TYPE = 11, |
| 108 | PDC_DIMM_SPD_FRESH_RATE = 12, | 113 | PDC_DIMM_SPD_FRESH_RATE = 12, |
| 109 | PDC_DIMM_SPD_BANK_NUM = 17, | 114 | PDC_DIMM_SPD_BANK_NUM = 17, |
| 110 | PDC_DIMM_SPD_CAS_LATENCY = 18, | 115 | PDC_DIMM_SPD_CAS_LATENCY = 18, |
| 111 | PDC_DIMM_SPD_ATTRIBUTE = 21, | 116 | PDC_DIMM_SPD_ATTRIBUTE = 21, |
| 112 | PDC_DIMM_SPD_ROW_PRE_CHARGE = 27, | 117 | PDC_DIMM_SPD_ROW_PRE_CHARGE = 27, |
| 113 | PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28, | 118 | PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28, |
| 114 | PDC_DIMM_SPD_RAS_CAS_DELAY = 29, | 119 | PDC_DIMM_SPD_RAS_CAS_DELAY = 29, |
| 115 | PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30, | 120 | PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30, |
| 116 | PDC_DIMM_SPD_SYSTEM_FREQ = 126, | 121 | PDC_DIMM_SPD_SYSTEM_FREQ = 126, |
| 117 | PDC_CTL_STATUS = 0x08, | 122 | PDC_CTL_STATUS = 0x08, |
| 118 | PDC_DIMM_WINDOW_CTLR = 0x0C, | 123 | PDC_DIMM_WINDOW_CTLR = 0x0C, |
| 119 | PDC_TIME_CONTROL = 0x3C, | 124 | PDC_TIME_CONTROL = 0x3C, |
| 120 | PDC_TIME_PERIOD = 0x40, | 125 | PDC_TIME_PERIOD = 0x40, |
| @@ -157,15 +162,15 @@ static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); | |||
| 157 | static void pdc20621_host_stop(struct ata_host_set *host_set); | 162 | static void pdc20621_host_stop(struct ata_host_set *host_set); |
| 158 | static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe); | 163 | static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe); |
| 159 | static int pdc20621_detect_dimm(struct ata_probe_ent *pe); | 164 | static int pdc20621_detect_dimm(struct ata_probe_ent *pe); |
| 160 | static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, | 165 | static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, |
| 161 | u32 device, u32 subaddr, u32 *pdata); | 166 | u32 device, u32 subaddr, u32 *pdata); |
| 162 | static int pdc20621_prog_dimm0(struct ata_probe_ent *pe); | 167 | static int pdc20621_prog_dimm0(struct ata_probe_ent *pe); |
| 163 | static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe); | 168 | static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe); |
| 164 | #ifdef ATA_VERBOSE_DEBUG | 169 | #ifdef ATA_VERBOSE_DEBUG |
| 165 | static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, | 170 | static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, |
| 166 | void *psource, u32 offset, u32 size); | 171 | void *psource, u32 offset, u32 size); |
| 167 | #endif | 172 | #endif |
| 168 | static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, | 173 | static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, |
| 169 | void *psource, u32 offset, u32 size); | 174 | void *psource, u32 offset, u32 size); |
| 170 | static void pdc20621_irq_clear(struct ata_port *ap); | 175 | static void pdc20621_irq_clear(struct ata_port *ap); |
| 171 | static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); | 176 | static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); |
| @@ -825,7 +830,8 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re | |||
| 825 | ap = host_set->ports[port_no]; | 830 | ap = host_set->ports[port_no]; |
| 826 | tmp = mask & (1 << i); | 831 | tmp = mask & (1 << i); |
| 827 | VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); | 832 | VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); |
| 828 | if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { | 833 | if (tmp && ap && |
| 834 | !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { | ||
| 829 | struct ata_queued_cmd *qc; | 835 | struct ata_queued_cmd *qc; |
| 830 | 836 | ||
| 831 | qc = ata_qc_from_tag(ap, ap->active_tag); | 837 | qc = ata_qc_from_tag(ap, ap->active_tag); |
| @@ -847,10 +853,14 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re | |||
| 847 | static void pdc_eng_timeout(struct ata_port *ap) | 853 | static void pdc_eng_timeout(struct ata_port *ap) |
| 848 | { | 854 | { |
| 849 | u8 drv_stat; | 855 | u8 drv_stat; |
| 856 | struct ata_host_set *host_set = ap->host_set; | ||
| 850 | struct ata_queued_cmd *qc; | 857 | struct ata_queued_cmd *qc; |
| 858 | unsigned long flags; | ||
| 851 | 859 | ||
| 852 | DPRINTK("ENTER\n"); | 860 | DPRINTK("ENTER\n"); |
| 853 | 861 | ||
| 862 | spin_lock_irqsave(&host_set->lock, flags); | ||
| 863 | |||
| 854 | qc = ata_qc_from_tag(ap, ap->active_tag); | 864 | qc = ata_qc_from_tag(ap, ap->active_tag); |
| 855 | if (!qc) { | 865 | if (!qc) { |
| 856 | printk(KERN_ERR "ata%u: BUG: timeout without command\n", | 866 | printk(KERN_ERR "ata%u: BUG: timeout without command\n", |
| @@ -884,6 +894,7 @@ static void pdc_eng_timeout(struct ata_port *ap) | |||
| 884 | } | 894 | } |
| 885 | 895 | ||
| 886 | out: | 896 | out: |
| 897 | spin_unlock_irqrestore(&host_set->lock, flags); | ||
| 887 | DPRINTK("EXIT\n"); | 898 | DPRINTK("EXIT\n"); |
| 888 | } | 899 | } |
| 889 | 900 | ||
| @@ -922,7 +933,7 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base) | |||
| 922 | 933 | ||
| 923 | 934 | ||
| 924 | #ifdef ATA_VERBOSE_DEBUG | 935 | #ifdef ATA_VERBOSE_DEBUG |
| 925 | static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, | 936 | static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, |
| 926 | u32 offset, u32 size) | 937 | u32 offset, u32 size) |
| 927 | { | 938 | { |
| 928 | u32 window_size; | 939 | u32 window_size; |
| @@ -936,9 +947,9 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, | |||
| 936 | /* hard-code chip #0 */ | 947 | /* hard-code chip #0 */ |
| 937 | mmio += PDC_CHIP0_OFS; | 948 | mmio += PDC_CHIP0_OFS; |
| 938 | 949 | ||
| 939 | page_mask = 0x00; | 950 | page_mask = 0x00; |
| 940 | window_size = 0x2000 * 4; /* 32K byte uchar size */ | 951 | window_size = 0x2000 * 4; /* 32K byte uchar size */ |
| 941 | idx = (u16) (offset / window_size); | 952 | idx = (u16) (offset / window_size); |
| 942 | 953 | ||
| 943 | writel(0x01, mmio + PDC_GENERAL_CTLR); | 954 | writel(0x01, mmio + PDC_GENERAL_CTLR); |
| 944 | readl(mmio + PDC_GENERAL_CTLR); | 955 | readl(mmio + PDC_GENERAL_CTLR); |
| @@ -947,19 +958,19 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, | |||
| 947 | 958 | ||
| 948 | offset -= (idx * window_size); | 959 | offset -= (idx * window_size); |
| 949 | idx++; | 960 | idx++; |
| 950 | dist = ((long) (window_size - (offset + size))) >= 0 ? size : | 961 | dist = ((long) (window_size - (offset + size))) >= 0 ? size : |
| 951 | (long) (window_size - offset); | 962 | (long) (window_size - offset); |
| 952 | memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4), | 963 | memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4), |
| 953 | dist); | 964 | dist); |
| 954 | 965 | ||
| 955 | psource += dist; | 966 | psource += dist; |
| 956 | size -= dist; | 967 | size -= dist; |
| 957 | for (; (long) size >= (long) window_size ;) { | 968 | for (; (long) size >= (long) window_size ;) { |
| 958 | writel(0x01, mmio + PDC_GENERAL_CTLR); | 969 | writel(0x01, mmio + PDC_GENERAL_CTLR); |
| 959 | readl(mmio + PDC_GENERAL_CTLR); | 970 | readl(mmio + PDC_GENERAL_CTLR); |
| 960 | writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); | 971 | writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); |
| 961 | readl(mmio + PDC_DIMM_WINDOW_CTLR); | 972 | readl(mmio + PDC_DIMM_WINDOW_CTLR); |
| 962 | memcpy_fromio((char *) psource, (char *) (dimm_mmio), | 973 | memcpy_fromio((char *) psource, (char *) (dimm_mmio), |
| 963 | window_size / 4); | 974 | window_size / 4); |
| 964 | psource += window_size; | 975 | psource += window_size; |
| 965 | size -= window_size; | 976 | size -= window_size; |
| @@ -971,14 +982,14 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, | |||
| 971 | readl(mmio + PDC_GENERAL_CTLR); | 982 | readl(mmio + PDC_GENERAL_CTLR); |
| 972 | writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); | 983 | writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); |
| 973 | readl(mmio + PDC_DIMM_WINDOW_CTLR); | 984 | readl(mmio + PDC_DIMM_WINDOW_CTLR); |
| 974 | memcpy_fromio((char *) psource, (char *) (dimm_mmio), | 985 | memcpy_fromio((char *) psource, (char *) (dimm_mmio), |
| 975 | size / 4); | 986 | size / 4); |
| 976 | } | 987 | } |
| 977 | } | 988 | } |
| 978 | #endif | 989 | #endif |
| 979 | 990 | ||
| 980 | 991 | ||
| 981 | static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, | 992 | static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, |
| 982 | u32 offset, u32 size) | 993 | u32 offset, u32 size) |
| 983 | { | 994 | { |
| 984 | u32 window_size; | 995 | u32 window_size; |
| @@ -989,16 +1000,16 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, | |||
| 989 | struct pdc_host_priv *hpriv = pe->private_data; | 1000 | struct pdc_host_priv *hpriv = pe->private_data; |
| 990 | void *dimm_mmio = hpriv->dimm_mmio; | 1001 | void *dimm_mmio = hpriv->dimm_mmio; |
| 991 | 1002 | ||
| 992 | /* hard-code chip #0 */ | 1003 | /* hard-code chip #0 */ |
| 993 | mmio += PDC_CHIP0_OFS; | 1004 | mmio += PDC_CHIP0_OFS; |
| 994 | 1005 | ||
| 995 | page_mask = 0x00; | 1006 | page_mask = 0x00; |
| 996 | window_size = 0x2000 * 4; /* 32K byte uchar size */ | 1007 | window_size = 0x2000 * 4; /* 32K byte uchar size */ |
| 997 | idx = (u16) (offset / window_size); | 1008 | idx = (u16) (offset / window_size); |
| 998 | 1009 | ||
| 999 | writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); | 1010 | writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); |
| 1000 | readl(mmio + PDC_DIMM_WINDOW_CTLR); | 1011 | readl(mmio + PDC_DIMM_WINDOW_CTLR); |
| 1001 | offset -= (idx * window_size); | 1012 | offset -= (idx * window_size); |
| 1002 | idx++; | 1013 | idx++; |
| 1003 | dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size : | 1014 | dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size : |
| 1004 | (long) (window_size - offset); | 1015 | (long) (window_size - offset); |
| @@ -1006,12 +1017,12 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, | |||
| 1006 | writel(0x01, mmio + PDC_GENERAL_CTLR); | 1017 | writel(0x01, mmio + PDC_GENERAL_CTLR); |
| 1007 | readl(mmio + PDC_GENERAL_CTLR); | 1018 | readl(mmio + PDC_GENERAL_CTLR); |
| 1008 | 1019 | ||
| 1009 | psource += dist; | 1020 | psource += dist; |
| 1010 | size -= dist; | 1021 | size -= dist; |
| 1011 | for (; (long) size >= (long) window_size ;) { | 1022 | for (; (long) size >= (long) window_size ;) { |
| 1012 | writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); | 1023 | writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); |
| 1013 | readl(mmio + PDC_DIMM_WINDOW_CTLR); | 1024 | readl(mmio + PDC_DIMM_WINDOW_CTLR); |
| 1014 | memcpy_toio((char *) (dimm_mmio), (char *) psource, | 1025 | memcpy_toio((char *) (dimm_mmio), (char *) psource, |
| 1015 | window_size / 4); | 1026 | window_size / 4); |
| 1016 | writel(0x01, mmio + PDC_GENERAL_CTLR); | 1027 | writel(0x01, mmio + PDC_GENERAL_CTLR); |
| 1017 | readl(mmio + PDC_GENERAL_CTLR); | 1028 | readl(mmio + PDC_GENERAL_CTLR); |
| @@ -1019,7 +1030,7 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, | |||
| 1019 | size -= window_size; | 1030 | size -= window_size; |
| 1020 | idx ++; | 1031 | idx ++; |
| 1021 | } | 1032 | } |
| 1022 | 1033 | ||
| 1023 | if (size) { | 1034 | if (size) { |
| 1024 | writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); | 1035 | writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); |
| 1025 | readl(mmio + PDC_DIMM_WINDOW_CTLR); | 1036 | readl(mmio + PDC_DIMM_WINDOW_CTLR); |
| @@ -1030,12 +1041,12 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, | |||
| 1030 | } | 1041 | } |
| 1031 | 1042 | ||
| 1032 | 1043 | ||
| 1033 | static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device, | 1044 | static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device, |
| 1034 | u32 subaddr, u32 *pdata) | 1045 | u32 subaddr, u32 *pdata) |
| 1035 | { | 1046 | { |
| 1036 | void *mmio = pe->mmio_base; | 1047 | void *mmio = pe->mmio_base; |
| 1037 | u32 i2creg = 0; | 1048 | u32 i2creg = 0; |
| 1038 | u32 status; | 1049 | u32 status; |
| 1039 | u32 count =0; | 1050 | u32 count =0; |
| 1040 | 1051 | ||
| 1041 | /* hard-code chip #0 */ | 1052 | /* hard-code chip #0 */ |
| @@ -1049,7 +1060,7 @@ static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device, | |||
| 1049 | readl(mmio + PDC_I2C_ADDR_DATA_OFFSET); | 1060 | readl(mmio + PDC_I2C_ADDR_DATA_OFFSET); |
| 1050 | 1061 | ||
| 1051 | /* Write Control to perform read operation, mask int */ | 1062 | /* Write Control to perform read operation, mask int */ |
| 1052 | writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT, | 1063 | writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT, |
| 1053 | mmio + PDC_I2C_CONTROL_OFFSET); | 1064 | mmio + PDC_I2C_CONTROL_OFFSET); |
| 1054 | 1065 | ||
| 1055 | for (count = 0; count <= 1000; count ++) { | 1066 | for (count = 0; count <= 1000; count ++) { |
| @@ -1062,26 +1073,26 @@ static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device, | |||
| 1062 | } | 1073 | } |
| 1063 | 1074 | ||
| 1064 | *pdata = (status >> 8) & 0x000000ff; | 1075 | *pdata = (status >> 8) & 0x000000ff; |
| 1065 | return 1; | 1076 | return 1; |
| 1066 | } | 1077 | } |
| 1067 | 1078 | ||
| 1068 | 1079 | ||
| 1069 | static int pdc20621_detect_dimm(struct ata_probe_ent *pe) | 1080 | static int pdc20621_detect_dimm(struct ata_probe_ent *pe) |
| 1070 | { | 1081 | { |
| 1071 | u32 data=0 ; | 1082 | u32 data=0 ; |
| 1072 | if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, | 1083 | if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, |
| 1073 | PDC_DIMM_SPD_SYSTEM_FREQ, &data)) { | 1084 | PDC_DIMM_SPD_SYSTEM_FREQ, &data)) { |
| 1074 | if (data == 100) | 1085 | if (data == 100) |
| 1075 | return 100; | 1086 | return 100; |
| 1076 | } else | 1087 | } else |
| 1077 | return 0; | 1088 | return 0; |
| 1078 | 1089 | ||
| 1079 | if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) { | 1090 | if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) { |
| 1080 | if(data <= 0x75) | 1091 | if(data <= 0x75) |
| 1081 | return 133; | 1092 | return 133; |
| 1082 | } else | 1093 | } else |
| 1083 | return 0; | 1094 | return 0; |
| 1084 | 1095 | ||
| 1085 | return 0; | 1096 | return 0; |
| 1086 | } | 1097 | } |
| 1087 | 1098 | ||
| @@ -1091,15 +1102,15 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe) | |||
| 1091 | u32 spd0[50]; | 1102 | u32 spd0[50]; |
| 1092 | u32 data = 0; | 1103 | u32 data = 0; |
| 1093 | int size, i; | 1104 | int size, i; |
| 1094 | u8 bdimmsize; | 1105 | u8 bdimmsize; |
| 1095 | void *mmio = pe->mmio_base; | 1106 | void *mmio = pe->mmio_base; |
| 1096 | static const struct { | 1107 | static const struct { |
| 1097 | unsigned int reg; | 1108 | unsigned int reg; |
| 1098 | unsigned int ofs; | 1109 | unsigned int ofs; |
| 1099 | } pdc_i2c_read_data [] = { | 1110 | } pdc_i2c_read_data [] = { |
| 1100 | { PDC_DIMM_SPD_TYPE, 11 }, | 1111 | { PDC_DIMM_SPD_TYPE, 11 }, |
| 1101 | { PDC_DIMM_SPD_FRESH_RATE, 12 }, | 1112 | { PDC_DIMM_SPD_FRESH_RATE, 12 }, |
| 1102 | { PDC_DIMM_SPD_COLUMN_NUM, 4 }, | 1113 | { PDC_DIMM_SPD_COLUMN_NUM, 4 }, |
| 1103 | { PDC_DIMM_SPD_ATTRIBUTE, 21 }, | 1114 | { PDC_DIMM_SPD_ATTRIBUTE, 21 }, |
| 1104 | { PDC_DIMM_SPD_ROW_NUM, 3 }, | 1115 | { PDC_DIMM_SPD_ROW_NUM, 3 }, |
| 1105 | { PDC_DIMM_SPD_BANK_NUM, 17 }, | 1116 | { PDC_DIMM_SPD_BANK_NUM, 17 }, |
| @@ -1108,7 +1119,7 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe) | |||
| 1108 | { PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 }, | 1119 | { PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 }, |
| 1109 | { PDC_DIMM_SPD_RAS_CAS_DELAY, 29 }, | 1120 | { PDC_DIMM_SPD_RAS_CAS_DELAY, 29 }, |
| 1110 | { PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 }, | 1121 | { PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 }, |
| 1111 | { PDC_DIMM_SPD_CAS_LATENCY, 18 }, | 1122 | { PDC_DIMM_SPD_CAS_LATENCY, 18 }, |
| 1112 | }; | 1123 | }; |
| 1113 | 1124 | ||
| 1114 | /* hard-code chip #0 */ | 1125 | /* hard-code chip #0 */ |
| @@ -1116,17 +1127,17 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe) | |||
| 1116 | 1127 | ||
| 1117 | for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++) | 1128 | for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++) |
| 1118 | pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, | 1129 | pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, |
| 1119 | pdc_i2c_read_data[i].reg, | 1130 | pdc_i2c_read_data[i].reg, |
| 1120 | &spd0[pdc_i2c_read_data[i].ofs]); | 1131 | &spd0[pdc_i2c_read_data[i].ofs]); |
| 1121 | 1132 | ||
| 1122 | data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4); | 1133 | data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4); |
| 1123 | data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) | | 1134 | data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) | |
| 1124 | ((((spd0[27] + 9) / 10) - 1) << 8) ; | 1135 | ((((spd0[27] + 9) / 10) - 1) << 8) ; |
| 1125 | data |= (((((spd0[29] > spd0[28]) | 1136 | data |= (((((spd0[29] > spd0[28]) |
| 1126 | ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10; | 1137 | ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10; |
| 1127 | data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12; | 1138 | data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12; |
| 1128 | 1139 | ||
| 1129 | if (spd0[18] & 0x08) | 1140 | if (spd0[18] & 0x08) |
| 1130 | data |= ((0x03) << 14); | 1141 | data |= ((0x03) << 14); |
| 1131 | else if (spd0[18] & 0x04) | 1142 | else if (spd0[18] & 0x04) |
| 1132 | data |= ((0x02) << 14); | 1143 | data |= ((0x02) << 14); |
| @@ -1135,7 +1146,7 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe) | |||
| 1135 | else | 1146 | else |
| 1136 | data |= (0 << 14); | 1147 | data |= (0 << 14); |
| 1137 | 1148 | ||
| 1138 | /* | 1149 | /* |
| 1139 | Calculate the size of bDIMMSize (power of 2) and | 1150 | Calculate the size of bDIMMSize (power of 2) and |
| 1140 | merge the DIMM size by program start/end address. | 1151 | merge the DIMM size by program start/end address. |
| 1141 | */ | 1152 | */ |
| @@ -1145,9 +1156,9 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe) | |||
| 1145 | data |= (((size / 16) - 1) << 16); | 1156 | data |= (((size / 16) - 1) << 16); |
| 1146 | data |= (0 << 23); | 1157 | data |= (0 << 23); |
| 1147 | data |= 8; | 1158 | data |= 8; |
| 1148 | writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET); | 1159 | writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET); |
| 1149 | readl(mmio + PDC_DIMM0_CONTROL_OFFSET); | 1160 | readl(mmio + PDC_DIMM0_CONTROL_OFFSET); |
| 1150 | return size; | 1161 | return size; |
| 1151 | } | 1162 | } |
| 1152 | 1163 | ||
| 1153 | 1164 | ||
| @@ -1167,12 +1178,12 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe) | |||
| 1167 | Refresh Enable (bit 17) | 1178 | Refresh Enable (bit 17) |
| 1168 | */ | 1179 | */ |
| 1169 | 1180 | ||
| 1170 | data = 0x022259F1; | 1181 | data = 0x022259F1; |
| 1171 | writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); | 1182 | writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); |
| 1172 | readl(mmio + PDC_SDRAM_CONTROL_OFFSET); | 1183 | readl(mmio + PDC_SDRAM_CONTROL_OFFSET); |
| 1173 | 1184 | ||
| 1174 | /* Turn on for ECC */ | 1185 | /* Turn on for ECC */ |
| 1175 | pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, | 1186 | pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, |
| 1176 | PDC_DIMM_SPD_TYPE, &spd0); | 1187 | PDC_DIMM_SPD_TYPE, &spd0); |
| 1177 | if (spd0 == 0x02) { | 1188 | if (spd0 == 0x02) { |
| 1178 | data |= (0x01 << 16); | 1189 | data |= (0x01 << 16); |
| @@ -1186,22 +1197,22 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe) | |||
| 1186 | data |= (1<<19); | 1197 | data |= (1<<19); |
| 1187 | writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); | 1198 | writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); |
| 1188 | 1199 | ||
| 1189 | error = 1; | 1200 | error = 1; |
| 1190 | for (i = 1; i <= 10; i++) { /* polling ~5 secs */ | 1201 | for (i = 1; i <= 10; i++) { /* polling ~5 secs */ |
| 1191 | data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET); | 1202 | data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET); |
| 1192 | if (!(data & (1<<19))) { | 1203 | if (!(data & (1<<19))) { |
| 1193 | error = 0; | 1204 | error = 0; |
| 1194 | break; | 1205 | break; |
| 1195 | } | 1206 | } |
| 1196 | msleep(i*100); | 1207 | msleep(i*100); |
| 1197 | } | 1208 | } |
| 1198 | return error; | 1209 | return error; |
| 1199 | } | 1210 | } |
| 1200 | 1211 | ||
| 1201 | 1212 | ||
| 1202 | static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe) | 1213 | static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe) |
| 1203 | { | 1214 | { |
| 1204 | int speed, size, length; | 1215 | int speed, size, length; |
| 1205 | u32 addr,spd0,pci_status; | 1216 | u32 addr,spd0,pci_status; |
| 1206 | u32 tmp=0; | 1217 | u32 tmp=0; |
| 1207 | u32 time_period=0; | 1218 | u32 time_period=0; |
| @@ -1228,7 +1239,7 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe) | |||
| 1228 | /* Wait 3 seconds */ | 1239 | /* Wait 3 seconds */ |
| 1229 | msleep(3000); | 1240 | msleep(3000); |
| 1230 | 1241 | ||
| 1231 | /* | 1242 | /* |
| 1232 | When timer is enabled, counter is decreased every internal | 1243 | When timer is enabled, counter is decreased every internal |
| 1233 | clock cycle. | 1244 | clock cycle. |
| 1234 | */ | 1245 | */ |
| @@ -1236,24 +1247,24 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe) | |||
| 1236 | tcount = readl(mmio + PDC_TIME_COUNTER); | 1247 | tcount = readl(mmio + PDC_TIME_COUNTER); |
| 1237 | VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount); | 1248 | VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount); |
| 1238 | 1249 | ||
| 1239 | /* | 1250 | /* |
| 1240 | If SX4 is on PCI-X bus, after 3 seconds, the timer counter | 1251 | If SX4 is on PCI-X bus, after 3 seconds, the timer counter |
| 1241 | register should be >= (0xffffffff - 3x10^8). | 1252 | register should be >= (0xffffffff - 3x10^8). |
| 1242 | */ | 1253 | */ |
| 1243 | if(tcount >= PCI_X_TCOUNT) { | 1254 | if(tcount >= PCI_X_TCOUNT) { |
| 1244 | ticks = (time_period - tcount); | 1255 | ticks = (time_period - tcount); |
| 1245 | VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks); | 1256 | VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks); |
| 1246 | 1257 | ||
| 1247 | clock = (ticks / 300000); | 1258 | clock = (ticks / 300000); |
| 1248 | VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock); | 1259 | VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock); |
| 1249 | 1260 | ||
| 1250 | clock = (clock * 33); | 1261 | clock = (clock * 33); |
| 1251 | VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock); | 1262 | VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock); |
| 1252 | 1263 | ||
| 1253 | /* PLL F Param (bit 22:16) */ | 1264 | /* PLL F Param (bit 22:16) */ |
| 1254 | fparam = (1400000 / clock) - 2; | 1265 | fparam = (1400000 / clock) - 2; |
| 1255 | VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam); | 1266 | VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam); |
| 1256 | 1267 | ||
| 1257 | /* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */ | 1268 | /* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */ |
| 1258 | pci_status = (0x8a001824 | (fparam << 16)); | 1269 | pci_status = (0x8a001824 | (fparam << 16)); |
| 1259 | } else | 1270 | } else |
| @@ -1264,21 +1275,21 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe) | |||
| 1264 | writel(pci_status, mmio + PDC_CTL_STATUS); | 1275 | writel(pci_status, mmio + PDC_CTL_STATUS); |
| 1265 | readl(mmio + PDC_CTL_STATUS); | 1276 | readl(mmio + PDC_CTL_STATUS); |
| 1266 | 1277 | ||
| 1267 | /* | 1278 | /* |
| 1268 | Read SPD of DIMM by I2C interface, | 1279 | Read SPD of DIMM by I2C interface, |
| 1269 | and program the DIMM Module Controller. | 1280 | and program the DIMM Module Controller. |
| 1270 | */ | 1281 | */ |
| 1271 | if (!(speed = pdc20621_detect_dimm(pe))) { | 1282 | if (!(speed = pdc20621_detect_dimm(pe))) { |
| 1272 | printk(KERN_ERR "Detect Local DIMM Fail\n"); | 1283 | printk(KERN_ERR "Detect Local DIMM Fail\n"); |
| 1273 | return 1; /* DIMM error */ | 1284 | return 1; /* DIMM error */ |
| 1274 | } | 1285 | } |
| 1275 | VPRINTK("Local DIMM Speed = %d\n", speed); | 1286 | VPRINTK("Local DIMM Speed = %d\n", speed); |
| 1276 | 1287 | ||
| 1277 | /* Programming DIMM0 Module Control Register (index_CID0:80h) */ | 1288 | /* Programming DIMM0 Module Control Register (index_CID0:80h) */ |
| 1278 | size = pdc20621_prog_dimm0(pe); | 1289 | size = pdc20621_prog_dimm0(pe); |
| 1279 | VPRINTK("Local DIMM Size = %dMB\n",size); | 1290 | VPRINTK("Local DIMM Size = %dMB\n",size); |
| 1280 | 1291 | ||
| 1281 | /* Programming DIMM Module Global Control Register (index_CID0:88h) */ | 1292 | /* Programming DIMM Module Global Control Register (index_CID0:88h) */ |
| 1282 | if (pdc20621_prog_dimm_global(pe)) { | 1293 | if (pdc20621_prog_dimm_global(pe)) { |
| 1283 | printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n"); | 1294 | printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n"); |
| 1284 | return 1; | 1295 | return 1; |
| @@ -1297,30 +1308,30 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe) | |||
| 1297 | 1308 | ||
| 1298 | pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40); | 1309 | pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40); |
| 1299 | pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40); | 1310 | pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40); |
| 1300 | printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], | 1311 | printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], |
| 1301 | test_parttern2[1], &(test_parttern2[2])); | 1312 | test_parttern2[1], &(test_parttern2[2])); |
| 1302 | pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040, | 1313 | pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040, |
| 1303 | 40); | 1314 | 40); |
| 1304 | printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], | 1315 | printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], |
| 1305 | test_parttern2[1], &(test_parttern2[2])); | 1316 | test_parttern2[1], &(test_parttern2[2])); |
| 1306 | 1317 | ||
| 1307 | pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40); | 1318 | pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40); |
| 1308 | pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40); | 1319 | pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40); |
| 1309 | printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], | 1320 | printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], |
| 1310 | test_parttern2[1], &(test_parttern2[2])); | 1321 | test_parttern2[1], &(test_parttern2[2])); |
| 1311 | } | 1322 | } |
| 1312 | #endif | 1323 | #endif |
| 1313 | 1324 | ||
| 1314 | /* ECC initiliazation. */ | 1325 | /* ECC initiliazation. */ |
| 1315 | 1326 | ||
| 1316 | pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, | 1327 | pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, |
| 1317 | PDC_DIMM_SPD_TYPE, &spd0); | 1328 | PDC_DIMM_SPD_TYPE, &spd0); |
| 1318 | if (spd0 == 0x02) { | 1329 | if (spd0 == 0x02) { |
| 1319 | VPRINTK("Start ECC initialization\n"); | 1330 | VPRINTK("Start ECC initialization\n"); |
| 1320 | addr = 0; | 1331 | addr = 0; |
| 1321 | length = size * 1024 * 1024; | 1332 | length = size * 1024 * 1024; |
| 1322 | while (addr < length) { | 1333 | while (addr < length) { |
| 1323 | pdc20621_put_to_dimm(pe, (void *) &tmp, addr, | 1334 | pdc20621_put_to_dimm(pe, (void *) &tmp, addr, |
| 1324 | sizeof(u32)); | 1335 | sizeof(u32)); |
| 1325 | addr += sizeof(u32); | 1336 | addr += sizeof(u32); |
| 1326 | } | 1337 | } |
