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 | } |